diff --git a/src/parser.bux b/src/parser.bux index 8a79311..2e540b3 100644 --- a/src/parser.bux +++ b/src/parser.bux @@ -2168,6 +2168,7 @@ module Parser { parserParseTypeParams(p, d); discard parserExpect(p, tkLBrace, "expected '{'"); + var lastWasComma: bool = false; while !parserCheck(p, tkRBrace) && parserPeek(p, 0) != tkEndOfFile { if fieldCount >= 256 { parserEmitDiag(p, line, col, "too many struct fields (max 255)"); @@ -2176,14 +2177,16 @@ module Parser { if parserCheck(p, tkNewLine) { discard parserAdvance(p); continue; } if parserCheck(p, tkSemicolon) { discard parserAdvance(p); continue; } // Commas are also valid field separators (incl. trailing comma before '}') - if parserCheck(p, tkComma) { discard parserAdvance(p); continue; } + if parserCheck(p, tkComma) { + if fieldCount == 0 || lastWasComma { + parserEmitDiag(p, parserCurToken(p).line, parserCurToken(p).column, "expected field name"); + } + lastWasComma = true; + discard parserAdvance(p); + continue; + } let beforePos: int = p.pos; let fName: LexToken = parserExpectIdentOrKeyword(p, "expected field name"); - if fieldCount >= 250 && fieldCount <= 256 { - PrintLine(String_Concat("RAW fieldCount=", bux_int_to_str(fieldCount as int64))); - PrintLine(String_Concat("RAW fName=", fName.text)); - PrintLine(String_Concat("RAW pos=", bux_int_to_str(p.pos as int64))); - } discard parserExpect(p, tkColon, "expected ':' in struct field"); let fType: *TypeExpr = parserParseType(p); parserMatch(p, tkSemicolon); @@ -2196,6 +2199,7 @@ module Parser { d.fields[fieldCount].name = fName.text; d.fields[fieldCount].refFieldType = fType; fieldCount = fieldCount + 1; + lastWasComma = false; } d.fieldCount = fieldCount; discard parserExpect(p, tkRBrace, "expected '}'"); diff --git a/src/sema.bux b/src/sema.bux index a0cdfff..cb45548 100644 --- a/src/sema.bux +++ b/src/sema.bux @@ -360,6 +360,34 @@ module Sema { i = i + 1; } + // Report named args that match no parameter + var checkArg: *ExprList = expr.callArgs; + while checkArg != null as *ExprList { + if !String_Eq(checkArg.argName, "") { + var foundName: bool = false; + var j: int = 0; + while j < decl.paramCount { + var pj: *Param = null as *Param; + if j == 0 { pj = &decl.param0; } + else if j == 1 { pj = &decl.param1; } + else if j == 2 { pj = &decl.param2; } + else if j == 3 { pj = &decl.param3; } + else if j == 4 { pj = &decl.param4; } + else if j == 5 { pj = &decl.param5; } + else if j == 6 { pj = &decl.param6; } + else if j == 7 { pj = &decl.param7; } + else if j == 8 { pj = &decl.param8; } + if String_Eq(checkArg.argName, pj.name) { foundName = true; } + j = j + 1; + } + if !foundName { + Sema_EmitError(sema, expr.line, expr.column, + String_Concat("unknown argument name '", String_Concat(checkArg.argName, "'"))); + } + } + checkArg = checkArg.next; + } + expr.callArgs = newFirst; expr.callArgCount = newCount; } @@ -1227,6 +1255,10 @@ module Sema { // Struct init: TypeName { field: value, ... } if kind == ekStructInit { + let te: *TypeExpr = bux_alloc(sizeof(TypeExpr)) as *TypeExpr; + te.kind = tekNamed; + te.typeName = expr.structName; + expr.refType = te; return tyNamed; }