diff options
-rwxr-xr-x | compiler/evals.nim | 9 | ||||
-rwxr-xr-x | compiler/importer.nim | 32 | ||||
-rwxr-xr-x | compiler/lookups.nim | 31 | ||||
-rwxr-xr-x | compiler/msgs.nim | 2 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 52 | ||||
-rwxr-xr-x | compiler/sem.nim | 28 | ||||
-rwxr-xr-x | compiler/semdata.nim | 4 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 164 | ||||
-rw-r--r-- | compiler/semmagic.nim | 2 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 138 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 180 | ||||
-rwxr-xr-x | compiler/semtypinst.nim | 3 | ||||
-rwxr-xr-x | todo.txt | 1 |
13 files changed, 378 insertions, 268 deletions
diff --git a/compiler/evals.nim b/compiler/evals.nim index 1f79466ef..570e64dd3 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -918,18 +918,17 @@ proc expectString(n: PNode) = proc evalSlurp*(e: PNode, module: PSym): PNode = expectString(e) + result = newNodeIT(nkStrLit, e.info, getSysType(tyString)) try: var filename = e.strVal.FindFile - var content = readFile(filename) - result = newStrNode(nkStrLit, content) - result.typ = getSysType(tyString) - result.info = e.info + result.strVal = readFile(filename) # we produce a fake include statement for every slurped filename, so that # the module dependencies are accurate: appendToModule(module, newNode(nkIncludeStmt, e.info, @[ newStrNode(nkStrLit, filename)])) except EIO: - GlobalError(e.info, errCannotOpenFile, e.strVal) + result.strVal = "" + LocalError(e.info, errCannotOpenFile, e.strVal) proc readOutput(p: PProcess): string = result = "" diff --git a/compiler/importer.nim b/compiler/importer.nim index 86511f228..19f0574b8 100755 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -76,21 +76,23 @@ proc rawImportSymbol(c: PContext, s: PSym) = proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = let ident = lookups.considerAcc(n) let s = StrTableGet(fromMod.tab, ident) - if s == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s) - if s.kind == skStub: loadStub(s) - if s.Kind notin ExportableSymKinds: - InternalError(n.info, "importSymbol: 2") - # for an enumeration we have to add all identifiers - case s.Kind - of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter: - # for a overloadable syms add all overloaded routines - var it: TIdentIter - var e = InitIdentIter(it, fromMod.tab, s.name) - while e != nil: - if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3") - rawImportSymbol(c, e) - e = NextIdentIter(it, fromMod.tab) - else: rawImportSymbol(c, s) + if s == nil: + LocalError(n.info, errUndeclaredIdentifier, ident.s) + else: + if s.kind == skStub: loadStub(s) + if s.Kind notin ExportableSymKinds: + InternalError(n.info, "importSymbol: 2") + # for an enumeration we have to add all identifiers + case s.Kind + of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter: + # for a overloadable syms add all overloaded routines + var it: TIdentIter + var e = InitIdentIter(it, fromMod.tab, s.name) + while e != nil: + if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3") + rawImportSymbol(c, e) + e = NextIdentIter(it, fromMod.tab) + else: rawImportSymbol(c, s) proc importAllSymbols(c: PContext, fromMod: PSym) = var i: TTabIter diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 0ad1c7f01..c67520997 100755 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -36,6 +36,11 @@ proc considerAcc*(n: PNode): PIdent = result = getIdent(id) else: GlobalError(n.info, errIdentifierExpected, renderTree(n)) + +proc errorSym*(n: PNode): PSym = + ## creates an error symbol to avoid cascading errors (for IDE support) + result = newSym(skUnknown, considerAcc(n), getCurrOwner()) + result.info = n.info type TOverloadIterMode* = enum @@ -122,13 +127,17 @@ proc lookUp*(c: PContext, n: PNode): PSym = case n.kind of nkIdent: result = SymtabGet(c.Tab, n.ident) - if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s) + if result == nil: + LocalError(n.info, errUndeclaredIdentifier, n.ident.s) + result = errorSym(n) of nkSym: result = n.sym of nkAccQuoted: var ident = considerAcc(n) result = SymtabGet(c.Tab, ident) - if result == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s) + if result == nil: + LocalError(n.info, errUndeclaredIdentifier, ident.s) + result = errorSym(n) else: InternalError(n.info, "lookUp") if Contains(c.AmbiguousSymbols, result.id): LocalError(n.info, errUseQualifier, result.name.s) @@ -144,7 +153,8 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = var ident = considerAcc(n) result = SymtabGet(c.Tab, ident) if result == nil and checkUndeclared in flags: - GlobalError(n.info, errUndeclaredIdentifier, ident.s) + LocalError(n.info, errUndeclaredIdentifier, ident.s) + result = errorSym(n) elif checkAmbiguity in flags and result != nil and Contains(c.AmbiguousSymbols, result.id): LocalError(n.info, errUseQualifier, ident.s) @@ -167,10 +177,12 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = else: result = StrTableGet(m.tab, ident) if result == nil and checkUndeclared in flags: - GlobalError(n.sons[1].info, errUndeclaredIdentifier, ident.s) - elif checkUndeclared in flags: - GlobalError(n.sons[1].info, errIdentifierExpected, - renderTree(n.sons[1])) + LocalError(n.sons[1].info, errUndeclaredIdentifier, ident.s) + result = errorSym(n.sons[1]) + elif checkUndeclared in flags: + LocalError(n.sons[1].info, errIdentifierExpected, + renderTree(n.sons[1])) + result = errorSym(n.sons[1]) else: result = nil if result != nil and result.kind == skStub: loadStub(result) @@ -205,8 +217,9 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = else: result = InitIdentIter(o.it, o.m.tab, ident) else: - GlobalError(n.sons[1].info, errIdentifierExpected, - renderTree(n.sons[1])) + LocalError(n.sons[1].info, errIdentifierExpected, + renderTree(n.sons[1])) + result = errorSym(n.sons[1]) of nkSymChoice: o.mode = oimSymChoice result = n.sons[0].sym diff --git a/compiler/msgs.nim b/compiler/msgs.nim index edcb66274..527c96dca 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -576,7 +576,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) = assert(false) # we want a stack trace here if msg >= fatalMin and msg <= fatalMax: if gVerbosity >= 3: assert(false) - quit(1) + if gCmd != cmdIdeTools: quit(1) if msg >= errMin and msg <= errMax: if gVerbosity >= 3: assert(false) inc(gErrorCounter) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 7df477327..28f77d1b9 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -109,14 +109,23 @@ proc processImportObjC(s: PSym, extname: string) = incl(s.flags, sfNamedParamCall) excl(s.flags, sfForward) +proc newEmptyStrNode(n: PNode): PNode {.noinline.} = + result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) + result.strVal = "" + proc getStrLitNode(c: PContext, n: PNode): PNode = if n.kind != nkExprColonExpr: - GlobalError(n.info, errStringLiteralExpected) - else: + LocalError(n.info, errStringLiteralExpected) + # error correction: + result = newEmptyStrNode(n) + else: n.sons[1] = c.semConstExpr(c, n.sons[1]) case n.sons[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1] - else: GlobalError(n.info, errStringLiteralExpected) + else: + LocalError(n.info, errStringLiteralExpected) + # error correction: + result = newEmptyStrNode(n) proc expectStrLit(c: PContext, n: PNode): string = result = getStrLitNode(c, n).strVal @@ -190,13 +199,17 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = Append(c.libs, result) proc expectDynlibNode(c: PContext, n: PNode): PNode = - if n.kind != nkExprColonExpr: GlobalError(n.info, errStringLiteralExpected) - else: + if n.kind != nkExprColonExpr: + LocalError(n.info, errStringLiteralExpected) + # error correction: + result = newEmptyStrNode(n) + else: result = c.semExpr(c, n.sons[1]) if result.kind == nkSym and result.sym.kind == skConst: result = result.sym.ast # look it up if result.typ == nil or result.typ.kind != tyString: - GlobalError(n.info, errStringLiteralExpected) + LocalError(n.info, errStringLiteralExpected) + result = newEmptyStrNode(n) proc processDynLib(c: PContext, n: PNode, sym: PSym) = if (sym == nil) or (sym.kind == skModule): @@ -359,7 +372,9 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = of nkStrLit, nkRStrLit, nkTripleStrLit: result = copyNode(n) var str = n.sons[1].strVal - if str == "": GlobalError(n.info, errEmptyAsm) + if str == "": + LocalError(n.info, errEmptyAsm) + return # now parse the string literal and substitute symbols: var a = 0 while true: @@ -405,15 +420,20 @@ proc PragmaLine(c: PContext, n: PNode) = if n.kind == nkExprColonExpr: n.sons[1] = c.semConstExpr(c, n.sons[1]) let a = n.sons[1] - if a.kind != nkPar: GlobalError(n.info, errXExpected, "tuple") - var x = a.sons[0] - var y = a.sons[1] - if x.kind == nkExprColonExpr: x = x.sons[1] - if y.kind == nkExprColonExpr: y = y.sons[1] - if x.kind != nkStrLit: GlobalError(n.info, errStringLiteralExpected) - if y.kind != nkIntLit: GlobalError(n.info, errIntLiteralExpected) - n.info.fileIndex = msgs.fileInfoIdx(x.strVal) - n.info.line = int16(y.intVal) + if a.kind == nkPar: + var x = a.sons[0] + var y = a.sons[1] + if x.kind == nkExprColonExpr: x = x.sons[1] + if y.kind == nkExprColonExpr: y = y.sons[1] + if x.kind != nkStrLit: + LocalError(n.info, errStringLiteralExpected) + elif y.kind != nkIntLit: + LocalError(n.info, errIntLiteralExpected) + else: + n.info.fileIndex = msgs.fileInfoIdx(x.strVal) + n.info.line = int16(y.intVal) + else: + LocalError(n.info, errXExpected, "tuple") else: # sensible default: n.info = getInfoContext(-1) diff --git a/compiler/sem.nim b/compiler/sem.nim index 904adf955..c1ea6d1af 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -37,7 +37,7 @@ proc addResultNode(c: PContext, n: PNode) proc instGenericContainer(c: PContext, n: PNode, header: PType): PType proc typeMismatch(n: PNode, formal, actual: PType) = - GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) & + LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) & typeToString(actual) & ") " & `%`(msgKindToString(errButExpectedX), [typeToString(formal)])) @@ -45,6 +45,9 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode = result = IndexTypesMatch(c, formal, arg.typ, arg) if result == nil: typeMismatch(arg, formal, arg.typ) + # error correction: + result = copyNode(arg) + result.typ = formal proc isTopLevel(c: PContext): bool {.inline.} = result = c.tab.tos <= 2 @@ -62,7 +65,7 @@ proc semStmtScope(c: PContext, n: PNode): PNode proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} = if not typeAllowed(typ, skConst): - GlobalError(typ.n.info, errXisNoType, typeToString(typ)) + LocalError(typ.n.info, errXisNoType, typeToString(typ)) proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym @@ -80,13 +83,15 @@ proc evalTypedExpr(c: PContext, e: PNode): PNode = if result == nil: result = evalConstExpr(c.module, e) if result == nil or result.kind == nkEmpty: - GlobalError(e.info, errConstExprExpected) + LocalError(e.info, errConstExprExpected) + # error correction: + result = e proc semConstExpr(c: PContext, n: PNode): PNode = var e = semExprWithType(c, n) if e == nil: - GlobalError(n.info, errConstExprExpected) - return nil + LocalError(n.info, errConstExprExpected) + return n result = evalTypedExpr(c, e) include seminst, semcall @@ -129,12 +134,15 @@ proc forceBool(c: PContext, n: PNode): PNode = if result == nil: result = n proc semConstBoolExpr(c: PContext, n: PNode): PNode = - result = fitNode(c, getSysType(tyBool), semExprWithType(c, n)) - if result == nil: - GlobalError(n.info, errConstExprExpected) - return + let nn = semExprWithType(c, n) + result = fitNode(c, getSysType(tyBool), nn) + if result == nil: + LocalError(n.info, errConstExprExpected) + return nn result = getConstExpr(c.module, result) - if result == nil: GlobalError(n.info, errConstExprExpected) + if result == nil: + LocalError(n.info, errConstExprExpected) + result = nn include semtypes, semexprs, semgnrc, semstmts diff --git a/compiler/semdata.nim b/compiler/semdata.nim index fb5b8075a..26552c294 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -224,6 +224,10 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType = proc newTypeS(kind: TTypeKind, c: PContext): PType = result = newType(kind, getCurrOwner()) +proc errorType*(c: PContext): PType = + ## creates a type representing an error state + result = newTypeS(tyEmpty, c) + proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) = dest.kind = kind dest.owner = getCurrOwner() diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d1606eef6..6a9af12ab 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -42,8 +42,9 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if result.typ != nil: if result.typ.kind == tyVar: result = newDeref(result) else: - GlobalError(n.info, errExprXHasNoType, - renderTree(result, {renderNoComments})) + LocalError(n.info, errExprXHasNoType, + renderTree(result, {renderNoComments})) + result.typ = errorType(c) proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = semExpr(c, n, flags) @@ -51,8 +52,9 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = # do not produce another redundant error message: raiseRecoverableError("") if result.typ == nil: - GlobalError(n.info, errExprXHasNoType, - renderTree(result, {renderNoComments})) + LocalError(n.info, errExprXHasNoType, + renderTree(result, {renderNoComments})) + result.typ = errorType(c) proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = result = symChoice(c, n, s) @@ -113,7 +115,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = c.p.owner.typ.callConv = ccClosure if illegalCapture(s) or c.p.next.owner != s.owner: # Currently captures are restricted to a single level of nesting: - GlobalError(n.info, errIllegalCaptureX, s.name.s) + LocalError(n.info, errIllegalCaptureX, s.name.s) result = newSymNode(s, n.info) of skGenericParam: if s.ast == nil: InternalError(n.info, "no default for") @@ -129,7 +131,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) = var diff = inheritanceDiff(castDest, src) if diff == high(int): - GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [ + LocalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [ src.typeToString, castDest.typeToString]) const @@ -147,7 +149,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) = d = base(d) s = base(s) if d == nil: - GlobalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [ + LocalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [ src.typeToString, castDest.typeToString]) elif d.Kind == tyObject and s.Kind == tyObject: checkConversionBetweenObjects(info, d, s) @@ -159,7 +161,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) = case cmpTypes(d, s) of isNone, isGeneric: if not compareTypes(castDest, src, dcEqIgnoreDistinct): - GlobalError(info, errGenerated, `%`( + LocalError(info, errGenerated, `%`( MsgKindToString(errIllegalConvFromXtoY), [typeToString(src), typeToString(castDest)])) else: @@ -184,7 +186,9 @@ proc isCastable(dst, src: PType): bool = (skipTypes(src, abstractInst).kind in IntegralTypes) proc semConv(c: PContext, n: PNode, s: PSym): PNode = - if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg) + if sonsLen(n) != 2: + LocalError(n.info, errConvNeedsOneArg) + return n result = newNodeI(nkConv, n.info) result.typ = semTypeNode(c, n.sons[0], nil) addSon(result, copyTree(n.sons[0])) @@ -210,14 +214,14 @@ proc semCast(c: PContext, n: PNode): PNode = addSon(result, copyTree(n.sons[0])) addSon(result, semExprWithType(c, n.sons[1])) if not isCastable(result.typ, result.sons[1].Typ): - GlobalError(result.info, errExprCannotBeCastedToX, - typeToString(result.Typ)) + LocalError(result.info, errExprCannotBeCastedToX, + typeToString(result.Typ)) proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = const opToStr: array[mLow..mHigh, string] = ["low", "high"] if sonsLen(n) != 2: - GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m]) + LocalError(n.info, errXExpectsTypeOrValue, opToStr[m]) else: n.sons[1] = semExprWithType(c, n.sons[1]) restoreOldStyleType(n.sons[1]) @@ -229,12 +233,12 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = n.typ = n.sons[1].typ.sons[0] # indextype of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: n.typ = n.sons[1].typ - else: GlobalError(n.info, errInvalidArgForX, opToStr[m]) + else: LocalError(n.info, errInvalidArgForX, opToStr[m]) result = n proc semSizeof(c: PContext, n: PNode): PNode = if sonsLen(n) != 2: - GlobalError(n.info, errXExpectsTypeOrValue, "sizeof") + LocalError(n.info, errXExpectsTypeOrValue, "sizeof") else: n.sons[1] = semExprWithType(c, n.sons[1]) restoreOldStyleType(n.sons[1]) @@ -253,26 +257,27 @@ proc semOf(c: PContext, n: PNode): PNode = let y = skipTypes(n.sons[2].typ, abstractPtrs) if x.kind == tyTypeDesc or y.kind != tyTypeDesc: - GlobalError(n.info, errXExpectsObjectTypes, "of") + LocalError(n.info, errXExpectsObjectTypes, "of") elif b.kind != tyObject or a.kind != tyObject: - GlobalError(n.info, errXExpectsObjectTypes, "of") - let diff = inheritanceDiff(a, b) - # | returns: 0 iff `a` == `b` - # | returns: -x iff `a` is the x'th direct superclass of `b` - # | returns: +x iff `a` is the x'th direct subclass of `b` - # | returns: `maxint` iff `a` and `b` are not compatible at all - if diff <= 0: - # optimize to true: - Message(n.info, hintConditionAlwaysTrue, renderTree(n)) - result = newIntNode(nkIntLit, 1) - result.info = n.info - result.typ = getSysType(tyBool) - return result - elif diff == high(int): - GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a)) - n.typ = getSysType(tyBool) - else: - GlobalError(n.info, errXExpectsTwoArguments, "of") + LocalError(n.info, errXExpectsObjectTypes, "of") + else: + let diff = inheritanceDiff(a, b) + # | returns: 0 iff `a` == `b` + # | returns: -x iff `a` is the x'th direct superclass of `b` + # | returns: +x iff `a` is the x'th direct subclass of `b` + # | returns: `maxint` iff `a` and `b` are not compatible at all + if diff <= 0: + # optimize to true: + Message(n.info, hintConditionAlwaysTrue, renderTree(n)) + result = newIntNode(nkIntLit, 1) + result.info = n.info + result.typ = getSysType(tyBool) + return result + elif diff == high(int): + LocalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a)) + else: + LocalError(n.info, errXExpectsTwoArguments, "of") + n.typ = getSysType(tyBool) result = n proc semIs(c: PContext, n: PNode): PNode = @@ -283,9 +288,9 @@ proc semIs(c: PContext, n: PNode): PNode = if n[2].kind notin {nkStrLit..nkTripleStrLit}: let b = semTypeNode(c, n[2], nil) n.sons[2] = newNodeIT(nkType, n[2].info, b) - result = n else: - GlobalError(n.info, errXExpectsTwoArguments, "is") + LocalError(n.info, errXExpectsTwoArguments, "is") + result = n proc semOpAux(c: PContext, n: PNode) = for i in countup(1, sonsLen(n) - 1): @@ -590,7 +595,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, of skMacro, skTemplate: nil else: if (callee.kind == skIterator) and (callee.id == c.p.owner.id): - GlobalError(n.info, errRecursiveDependencyX, callee.name.s) + LocalError(n.info, errRecursiveDependencyX, callee.name.s) if sfNoSideEffect notin callee.flags: if {sfImportc, sfSideEffect} * callee.flags != {}: incl(c.p.owner.flags, sfSideEffect) @@ -625,7 +630,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = if m.state != csMatch: if c.inCompilesContext > 0: # speed up error generation: - GlobalError(n.Info, errTypeMismatch, "") + LocalError(n.Info, errTypeMismatch, "") + return emptyNode else: var msg = msgKindToString(errTypeMismatch) for i in countup(1, sonsLen(n) - 1): @@ -633,7 +639,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = add(msg, typeToString(n.sons[i].typ)) add(msg, ")\n" & msgKindToString(errButExpected) & "\n" & typeToString(n.sons[0].typ)) - GlobalError(n.Info, errGenerated, msg) + LocalError(n.Info, errGenerated, msg) + return emptyNode result = nil else: result = m.call @@ -649,8 +656,9 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = nOrig.sons[0] = prc result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) if result == nil: - GlobalError(n.info, errExprXCannotBeCalled, - renderTree(n, {renderNoComments})) + LocalError(n.info, errExprXCannotBeCalled, + renderTree(n, {renderNoComments})) + return emptyNode fixAbstractType(c, result) analyseIfAddressTakenInCall(c, result) if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone: @@ -664,7 +672,9 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) if result == nil: result = overloadedCallOpr(c, n) - if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n)) + if result == nil: + LocalError(n.Info, errGenerated, getNotFoundError(c, n)) + return emptyNode let callee = result.sons[0].sym case callee.kind of skMacro: result = semMacroExpr(c, nOrig, callee) @@ -696,8 +706,11 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode = # we MUST not check 'n' for semantics again here! result = newNodeI(nkCall, n.info) var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo") - if e == nil: GlobalError(n.info, errSystemNeeds, "echo") - addSon(result, newSymNode(e)) + if e != nil: + addSon(result, newSymNode(e)) + else: + LocalError(n.info, errSystemNeeds, "echo") + addSon(result, emptyNode) var arg = buildStringify(c, n) # problem is: implicit '$' is not checked for semantics yet. So we give up # and check 'arg' for semantics again: @@ -890,7 +903,8 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = addSon(result, newIdentNode(i, n.info)) addSon(result, copyTree(n[0])) else: - GlobalError(n.Info, errUndeclaredFieldX, i.s) + LocalError(n.Info, errUndeclaredFieldX, i.s) + result = emptyNode proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode = result = newNodeI(nkCall, n.info) @@ -946,9 +960,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = {tyInt..tyInt64}: var idx = getOrdValue(n.sons[1]) if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)] - else: GlobalError(n.info, errInvalidIndexValueForTuple) + else: LocalError(n.info, errInvalidIndexValueForTuple) else: - GlobalError(n.info, errIndexTypesDoNotMatch) + LocalError(n.info, errIndexTypesDoNotMatch) result = n else: nil @@ -972,7 +986,7 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode = fixAbstractType(c, result) analyseIfAddressTakenInCall(c, result) else: - globalError(n.Info, errUndeclaredFieldX, id.s) + LocalError(n.Info, errUndeclaredFieldX, id.s) proc takeImplicitAddr(c: PContext, n: PNode): PNode = case n.kind @@ -984,9 +998,9 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode = var valid = isAssignable(c, n) if valid != arLValue: if valid == arLocalLValue: - GlobalError(n.info, errXStackEscape, renderTree(n, {renderNoComments})) + LocalError(n.info, errXStackEscape, renderTree(n, {renderNoComments})) else: - GlobalError(n.info, errExprHasNoAddress) + LocalError(n.info, errExprHasNoAddress) result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ)) result.add(n) @@ -1062,13 +1076,13 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym = else: result = StrTableGet(m.tab, ident) else: - GlobalError(n.sons[1].info, errIdentifierExpected, "") + LocalError(n.sons[1].info, errIdentifierExpected, "") of nkAccQuoted: result = lookupForDefined(c, considerAcc(n), onlyCurrentScope) of nkSym: result = n.sym else: - GlobalError(n.info, errIdentifierExpected, renderTree(n)) + LocalError(n.info, errIdentifierExpected, renderTree(n)) result = nil proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = @@ -1091,17 +1105,20 @@ proc setMs(n: PNode, s: PSym): PNode = proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym = ## The argument to the proc should be nkCall(...) or similar ## Returns the macro/template symbol - if not isCallExpr(n): - GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree) - - var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared}) - if expandedSym == nil: - GlobalError(n.info, errUndeclaredIdentifier, n[0].renderTree) + if isCallExpr(n): + var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared}) + if expandedSym == nil: + LocalError(n.info, errUndeclaredIdentifier, n[0].renderTree) + return errorSym(n[0]) - if expandedSym.kind notin {skMacro, skTemplate}: - GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s) + if expandedSym.kind notin {skMacro, skTemplate}: + LocalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s) + return errorSym(n[0]) - result = expandedSym + result = expandedSym + else: + LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree) + result = errorSym(n) proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym, flags: TExprFlags): PNode = @@ -1240,7 +1257,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode = if typ == nil: typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal}) if not isOrdinalType(typ): - GlobalError(n.info, errOrdinalTypeExpected) + LocalError(n.info, errOrdinalTypeExpected) return if lengthOrd(typ) > MaxSetElements: typ = makeRangeType(c, 0, MaxSetElements - 1, n.info) @@ -1288,11 +1305,11 @@ proc checkPar(n: PNode): TParKind = if result == paTupleFields: if (n.sons[i].kind != nkExprColonExpr) or not (n.sons[i].sons[0].kind in {nkSym, nkIdent}): - GlobalError(n.sons[i].info, errNamedExprExpected) + LocalError(n.sons[i].info, errNamedExprExpected) return paNone else: if n.sons[i].kind == nkExprColonExpr: - GlobalError(n.sons[i].info, errNamedExprNotAllowed) + LocalError(n.sons[i].info, errNamedExprNotAllowed) return paNone proc semTupleFieldsConstr(c: PContext, n: PNode): PNode = @@ -1369,10 +1386,13 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode = addSon(result, n.sons[0].sons[i]) for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i]) result = semTemplateExpr(c, result, s, semCheck) - else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s) - else: - GlobalError(n.info, errInvalidExpressionX, - renderTree(a, {renderNoComments})) + else: + LocalError(n.info, errXisNoMacroOrTemplate, s.name.s) + result = emptyNode + else: + LocalError(n.info, errInvalidExpressionX, + renderTree(a, {renderNoComments})) + result = emptyNode proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = n @@ -1505,7 +1525,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = checkSonsLen(n, 1) n.sons[0] = semExprWithType(c, n.sons[0]) if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}: - GlobalError(n.info, errExprHasNoAddress) + LocalError(n.info, errExprHasNoAddress) n.typ = makePtrType(c, n.sons[0].typ) of nkHiddenAddr, nkHiddenDeref: checkSonsLen(n, 1) @@ -1525,10 +1545,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkTableConstr: result = semTableConstr(c, n) of nkSymChoice: - GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments})) + LocalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments})) + # error correction: Pick first element: + result = n.sons[0] of nkStaticExpr: result = semStaticExpr(c, n) else: - GlobalError(n.info, errInvalidExpressionX, - renderTree(n, {renderNoComments})) + LocalError(n.info, errInvalidExpressionX, + renderTree(n, {renderNoComments})) incl(result.flags, nfSem) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 646034218..c6a5aaa73 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -18,7 +18,7 @@ proc expectIntLit(c: PContext, n: PNode): int = let x = c.semConstExpr(c, n) case x.kind of nkIntLit..nkInt64Lit: result = int(x.intVal) - else: GlobalError(n.info, errIntLiteralExpected) + else: LocalError(n.info, errIntLiteralExpected) proc semInstantiationInfo(c: PContext, n: PNode): PNode = result = newNodeIT(nkPar, n.info, n.typ) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 7b1c6d76a..a5d2098c3 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -163,18 +163,20 @@ proc SemReturn(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}: - globalError(n.info, errXNotAllowedHere, "\'return\'") - if n.sons[0].kind != nkEmpty: + LocalError(n.info, errXNotAllowedHere, "\'return\'") + elif n.sons[0].kind != nkEmpty: # transform ``return expr`` to ``result = expr; return`` - if c.p.resultSym == nil: globalError(n.info, errNoReturnTypeDeclared) - var a = newNodeI(nkAsgn, n.sons[0].info) - addSon(a, newSymNode(c.p.resultSym)) - addSon(a, n.sons[0]) - n.sons[0] = semAsgn(c, a) - # optimize away ``result = result``: - if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: - n.sons[0] = ast.emptyNode - + if c.p.resultSym != nil: + var a = newNodeI(nkAsgn, n.sons[0].info) + addSon(a, newSymNode(c.p.resultSym)) + addSon(a, n.sons[0]) + n.sons[0] = semAsgn(c, a) + # optimize away ``result = result``: + if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: + n.sons[0] = ast.emptyNode + else: + LocalError(n.info, errNoReturnTypeDeclared) + proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) = var t = skipTypes(restype, {tyGenericInst}) case t.kind @@ -198,8 +200,8 @@ proc SemYield(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) if c.p.owner == nil or c.p.owner.kind != skIterator: - GlobalError(n.info, errYieldNotAllowedHere) - if n.sons[0].kind != nkEmpty: + LocalError(n.info, errYieldNotAllowedHere) + elif n.sons[0].kind != nkEmpty: n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility: var restype = c.p.owner.typ.sons[0] if restype != nil: @@ -254,22 +256,24 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = else: typ = skipIntLit(def.typ) else: def = ast.emptyNode - if symkind == skLet: GlobalError(a.info, errLetNeedsInit) + if symkind == skLet: LocalError(a.info, errLetNeedsInit) # this can only happen for errornous var statements: if typ == nil: continue if not typeAllowed(typ, symkind): - GlobalError(a.info, errXisNoType, typeToString(typ)) + LocalError(a.info, errXisNoType, typeToString(typ)) var tup = skipTypes(typ, {tyGenericInst}) if a.kind == nkVarTuple: - if tup.kind != tyTuple: GlobalError(a.info, errXExpected, "tuple") - if length-2 != sonsLen(tup): - GlobalError(a.info, errWrongNumberOfVariables) - b = newNodeI(nkVarTuple, a.info) - newSons(b, length) - b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator - b.sons[length-1] = def - addSon(result, b) + if tup.kind != tyTuple: + localError(a.info, errXExpected, "tuple") + elif length-2 != sonsLen(tup): + localError(a.info, errWrongNumberOfVariables) + else: + b = newNodeI(nkVarTuple, a.info) + newSons(b, length) + b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator + b.sons[length-1] = def + addSon(result, b) elif tup.kind == tyTuple and def.kind == nkPar and a.kind == nkIdentDefs and a.len > 3: Message(a.info, warnEachIdentIsTuple) @@ -308,33 +312,19 @@ proc semConst(c: PContext, n: PNode): PNode = var typ: PType = nil if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) - when true: - var def = semConstExpr(c, a.sons[2]) - if def == nil: GlobalError(a.sons[2].info, errConstExprExpected) - # check type compatibility between def.typ and typ: - if typ != nil: - def = fitRemoveHiddenConv(c, typ, def) - else: - typ = def.typ - if not typeAllowed(typ, skConst): - GlobalError(a.info, errXisNoType, typeToString(typ)) + var def = semConstExpr(c, a.sons[2]) + if def == nil: + LocalError(a.sons[2].info, errConstExprExpected) + continue + # check type compatibility between def.typ and typ: + if typ != nil: + def = fitRemoveHiddenConv(c, typ, def) else: - var e = semExprWithType(c, a.sons[2]) - if e == nil: GlobalError(a.sons[2].info, errConstExprExpected) - var def = getConstExpr(c.module, e) - if def == nil: - v.flags.incl(sfFakeConst) - def = evalConstExpr(c.module, e) - if def == nil or def.kind == nkEmpty: def = e - # check type compatibility between def.typ and typ: - if typ != nil: - def = fitRemoveHiddenConv(c, typ, def) - else: - typ = def.typ - if not typeAllowed(typ, skConst): - v.flags.incl(sfFakeConst) - if not typeAllowed(typ, skVar): - GlobalError(a.info, errXisNoType, typeToString(typ)) + typ = def.typ + if typ == nil: continue + if not typeAllowed(typ, skConst): + LocalError(a.info, errXisNoType, typeToString(typ)) + continue v.typ = typ v.ast = def # no need to copy addInterfaceDecl(c, v) @@ -382,7 +372,10 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = # a 'while true: stmt; break' loop ... result = newNodeI(nkWhileStmt, n.info) var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true") - if trueSymbol == nil: GlobalError(n.info, errSystemNeeds, "true") + if trueSymbol == nil: + LocalError(n.info, errSystemNeeds, "true") + trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner()) + trueSymbol.typ = getSysType(tyBool) result.add(newSymNode(trueSymbol, n.info)) var stmts = newNodeI(nkStmtList, n.info) @@ -391,7 +384,8 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = var length = sonsLen(n) var call = n.sons[length-2] if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs): - GlobalError(n.info, errWrongNumberOfVariables) + LocalError(n.info, errWrongNumberOfVariables) + return result var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar) if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!") @@ -422,18 +416,20 @@ proc semForVars(c: PContext, n: PNode): PNode = # length == 3 means that there is one for loop variable # and thus no tuple unpacking: if iter.kind != tyTuple or length == 3: - if length != 3: GlobalError(n.info, errWrongNumberOfVariables) - var v = newSymS(skForVar, n.sons[0], c) - if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) - # BUGFIX: don't use `iter` here as that would strip away - # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` - # for an example: - v.typ = n.sons[length-2].typ - n.sons[0] = newSymNode(v) - addDecl(c, v) - else: - if length-2 != sonsLen(iter): - GlobalError(n.info, errWrongNumberOfVariables) + if length == 3: + var v = newSymS(skForVar, n.sons[0], c) + if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) + # BUGFIX: don't use `iter` here as that would strip away + # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` + # for an example: + v.typ = n.sons[length-2].typ + n.sons[0] = newSymNode(v) + addDecl(c, v) + else: + LocalError(n.info, errWrongNumberOfVariables) + elif length-2 != sonsLen(iter): + LocalError(n.info, errWrongNumberOfVariables) + else: for i in countup(0, length - 3): var v = newSymS(skForVar, n.sons[i], c) if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) @@ -461,12 +457,11 @@ proc semFor(c: PContext, n: PNode): PNode = call.sons[0].sym.kind != skIterator: if length == 3: n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2]) - result = semForVars(c, n) elif length == 4: n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2]) - result = semForVars(c, n) else: - GlobalError(n.sons[length - 2].info, errIteratorExpected) + LocalError(n.sons[length-2].info, errIteratorExpected) + result = semForVars(c, n) elif call.sons[0].sym.magic != mNone: if call.sons[0].sym.magic == mOmpParFor: result = semForVars(c, n) @@ -504,7 +499,7 @@ proc semTry(c: PContext, n: PNode): PNode = var typ = semTypeNode(c, a.sons[j], nil) if typ.kind == tyRef: typ = typ.sons[0] if typ.kind != tyObject: - GlobalError(a.sons[j].info, errExprCannotBeRaised) + LocalError(a.sons[j].info, errExprCannotBeRaised) a.sons[j] = newNodeI(nkType, a.sons[j].info) a.sons[j].typ = typ if ContainsOrIncl(check, typ.id): @@ -549,7 +544,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = if (a.sons[0].kind != nkSym): IllFormedAst(a) var s = a.sons[0].sym if s.magic == mNone and a.sons[2].kind == nkEmpty: - GlobalError(a.info, errImplOfXexpected, s.name.s) + LocalError(a.info, errImplOfXexpected, s.name.s) if s.magic != mNone: processMagicType(c, s) if a.sons[1].kind != nkEmpty: # We have a generic type declaration here. In generic types, @@ -901,9 +896,10 @@ proc evalInclude(c: PContext, n: PNode): PNode = var f = checkModuleName(n.sons[i]) var fileIndex = f.fileInfoIdx if ContainsOrIncl(c.includedFiles, fileIndex): - GlobalError(n.info, errRecursiveDependencyX, f.extractFilename) - addSon(result, semStmt(c, gIncludeFile(f))) - Excl(c.includedFiles, fileIndex) + LocalError(n.info, errRecursiveDependencyX, f.extractFilename) + else: + addSon(result, semStmt(c, gIncludeFile(f))) + Excl(c.includedFiles, fileIndex) proc setLine(n: PNode, info: TLineInfo) = for i in 0 .. <safeLen(n): setLine(n.sons[i], info) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 39c5acad1..e77bb9f86 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -46,11 +46,14 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = var strVal: PNode = nil case skipTypes(v.typ, abstractInst).kind of tyTuple: - if sonsLen(v) != 2: GlobalError(v.info, errWrongNumberOfVariables) - strVal = v.sons[1] # second tuple part is the string value - if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}: - GlobalError(strVal.info, errStringLiteralExpected) - x = getOrdValue(v.sons[0]) # first tuple part is the ordinal + if sonsLen(v) == 2: + strVal = v.sons[1] # second tuple part is the string value + if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCstring}: + x = getOrdValue(v.sons[0]) # first tuple part is the ordinal + else: + LocalError(strVal.info, errStringLiteralExpected) + else: + LocalError(v.info, errWrongNumberOfVariables) of tyString, tyCstring: strVal = v x = counter @@ -59,7 +62,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType = if i != 1: if x != counter: incl(result.flags, tfEnumHasHoles) if x < counter: - GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s) + LocalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s) + x = counter e.ast = strVal # might be nil counter = x of nkSym: @@ -84,10 +88,13 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType = addSonSkipIntLit(result, base) if base.kind == tyGenericInst: base = lastSon(base) if base.kind != tyGenericParam: - if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected) - if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig) - else: - GlobalError(n.info, errXExpectsOneTypeParam, "set") + if not isOrdinalType(base): + LocalError(n.info, errOrdinalTypeExpected) + elif lengthOrd(base) > MaxSetElements: + LocalError(n.info, errSetTooBig) + else: + LocalError(n.info, errXExpectsOneTypeParam, "set") + addSonSkipIntLit(result, errorType(c)) proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, prev: PType): PType = @@ -96,7 +103,8 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, var base = semTypeNode(c, n.sons[1], nil) addSonSkipIntLit(result, base) else: - GlobalError(n.info, errXExpectsOneTypeParam, kindStr) + LocalError(n.info, errXExpectsOneTypeParam, kindStr) + addSonSkipIntLit(result, errorType(c)) proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, prev: PType): PType = if sonsLen(n) == 1: @@ -110,7 +118,9 @@ proc semVarType(c: PContext, n: PNode, prev: PType): PType = if sonsLen(n) == 1: result = newOrPrevType(tyVar, prev, c) var base = semTypeNode(c, n.sons[0], nil) - if base.kind == tyVar: GlobalError(n.info, errVarVarTypeNotAllowed) + if base.kind == tyVar: + LocalError(n.info, errVarVarTypeNotAllowed) + base = base.sons[0] addSonSkipIntLit(result, base) else: result = newConstraint(c, tyVar) @@ -128,28 +138,32 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyRange, prev, c) result.n = newNodeI(nkRange, n.info) if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): - GlobalError(n.Info, errRangeIsEmpty) + LocalError(n.Info, errRangeIsEmpty) var a = semConstExpr(c, n[1]) var b = semConstExpr(c, n[2]) - if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch) - if a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,tyFloat..tyFloat128, - tyUInt8..tyUInt32}: - GlobalError(n.info, errOrdinalTypeExpected) - if enumHasHoles(a.typ): - GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) - if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty) + if not sameType(a.typ, b.typ): + LocalError(n.info, errPureTypeMismatch) + elif a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar, + tyFloat..tyFloat128,tyUInt8..tyUInt32}: + LocalError(n.info, errOrdinalTypeExpected) + elif enumHasHoles(a.typ): + LocalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) + elif not leValue(a, b): LocalError(n.Info, errRangeIsEmpty) addSon(result.n, a) addSon(result.n, b) addSonSkipIntLit(result, b.typ) -proc semRange(c: PContext, n: PNode, prev: PType): PType = +proc semRange(c: PContext, n: PNode, prev: PType): PType = result = nil - if sonsLen(n) == 2: + if sonsLen(n) == 2: if isRange(n[1]): result = semRangeAux(c, n[1], prev) - else: GlobalError(n.sons[0].info, errRangeExpected) - else: - GlobalError(n.info, errXExpectsOneTypeParam, "range") - + else: + LocalError(n.sons[0].info, errRangeExpected) + result = errorType(c) + else: + LocalError(n.info, errXExpectsOneTypeParam, "range") + result = errorType(c) + proc semArray(c: PContext, n: PNode, prev: PType): PType = var indx, base: PType result = newOrPrevType(tyArray, prev, c) @@ -161,13 +175,14 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = if indx.kind == tyGenericInst: indx = lastSon(indx) if indx.kind != tyGenericParam: if not isOrdinalType(indx): - GlobalError(n.sons[1].info, errOrdinalTypeExpected) - if enumHasHoles(indx): - GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s) + LocalError(n.sons[1].info, errOrdinalTypeExpected) + elif enumHasHoles(indx): + LocalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s) base = semTypeNode(c, n.sons[2], nil) addSonSkipIntLit(result, base) else: - GlobalError(n.info, errArrayExpectsTwoTypeParams) + LocalError(n.info, errArrayExpectsTwoTypeParams) + result = errorType(c) proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyOrdinal, prev, c) @@ -175,10 +190,11 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = var base = semTypeNode(c, n.sons[1], nil) if base.kind != tyGenericParam: if not isOrdinalType(base): - GlobalError(n.sons[1].info, errOrdinalTypeExpected) + LocalError(n.sons[1].info, errOrdinalTypeExpected) addSonSkipIntLit(result, base) - else: - GlobalError(n.info, errXExpectsOneTypeParam, "ordinal") + else: + LocalError(n.info, errXExpectsOneTypeParam, "ordinal") + result = errorType(c) proc semTypeIdent(c: PContext, n: PNode): PSym = if n.kind == nkSym: @@ -205,14 +221,17 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = while amb != nil and amb.kind != skType: amb = nextOverloadIter(ov, c, n) if amb != nil: result = amb - else: GlobalError(n.info, errTypeExpected) + else: + LocalError(n.info, errTypeExpected) + return errorSym(n) if result.typ.kind != tyGenericParam: # XXX get rid of this hack! reset(n[]) n.kind = nkSym n.sym = result else: - GlobalError(n.info, errIdentifierExpected) + LocalError(n.info, errIdentifierExpected) + result = errorSym(n) proc semTuple(c: PContext, n: PNode, prev: PType): PType = if n.sonsLen == 0: return newConstraint(c, tyTuple) @@ -228,18 +247,21 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = var length = sonsLen(a) if a.sons[length - 2].kind != nkEmpty: typ = semTypeNode(c, a.sons[length - 2], nil) - else: GlobalError(a.info, errTypeExpected) + else: + LocalError(a.info, errTypeExpected) + typ = errorType(c) if a.sons[length - 1].kind != nkEmpty: - GlobalError(a.sons[length - 1].info, errInitHereNotAllowed) + LocalError(a.sons[length - 1].info, errInitHereNotAllowed) for j in countup(0, length - 3): var field = newSymS(skField, a.sons[j], c) field.typ = typ field.position = counter inc(counter) if ContainsOrIncl(check, field.name.id): - GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s) - addSon(result.n, newSymNode(field)) - addSonSkipIntLit(result, typ) + LocalError(a.sons[j].info, errAttemptToRedefine, field.name.s) + else: + addSon(result.n, newSymNode(field)) + addSonSkipIntLit(result, typ) proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = @@ -290,8 +312,8 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode result = newNodeI(nkRange, a.info) result.add(at) result.add(bt) - if emptyRange(ac, bc): GlobalError(b.info, errRangeIsEmpty) - covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1 + if emptyRange(ac, bc): LocalError(b.info, errRangeIsEmpty) + else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1 proc SemCaseBranchRange(c: PContext, t, b: PNode, covered: var biggestInt): PNode = @@ -349,11 +371,12 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int, incl(a.sons[0].sym.flags, sfDiscriminant) var covered: biggestInt = 0 var typ = skipTypes(a.sons[0].Typ, abstractVar) - if not isOrdinalType(typ): GlobalError(n.info, errSelectorMustBeOrdinal) - if firstOrd(typ) < 0: - GlobalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s) - if lengthOrd(typ) > 0x00007FFF: - GlobalError(n.info, errLenXinvalid, a.sons[0].sym.name.s) + if not isOrdinalType(typ): + LocalError(n.info, errSelectorMustBeOrdinal) + elif firstOrd(typ) < 0: + LocalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s) + elif lengthOrd(typ) > 0x00007FFF: + LocalError(n.info, errLenXinvalid, a.sons[0].sym.name.s) var chckCovered = true for i in countup(1, sonsLen(n) - 1): var b = copyTree(n.sons[i]) @@ -426,10 +449,13 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int, else: a = ast.emptyNode if n.sons[length-1].kind != nkEmpty: localError(n.sons[length-1].info, errInitHereNotAllowed) + var typ: PType if n.sons[length-2].kind == nkEmpty: - GlobalError(n.info, errTypeExpected) - var typ = semTypeNode(c, n.sons[length-2], nil) - for i in countup(0, sonsLen(n)-3): + LocalError(n.info, errTypeExpected) + typ = errorType(c) + else: + typ = semTypeNode(c, n.sons[length-2], nil) + for i in countup(0, sonsLen(n)-3): var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported}) f.typ = typ f.position = pos @@ -568,7 +594,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, let s = SymtabGet(c.tab, paramTypId) # tests/run/tinterf triggers this: if s != nil: result = s.typ - else: GlobalError(info, errCannotInstantiateX, paramName) + else: + LocalError(info, errCannotInstantiateX, paramName) + result = errorType(c) else: block addImplicitGeneric: # is this a bindOnce type class already present in the param list? @@ -700,13 +728,15 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = result = newOrPrevType(tyGenericInvokation, prev, c) var isConcrete = true if s.typ == nil: - GlobalError(n.info, errCannotInstantiateX, s.name.s) + LocalError(n.info, errCannotInstantiateX, s.name.s) + return errorType(c) elif s.typ.kind != tyGenericBody: isConcrete = false elif s.typ.containerID == 0: InternalError(n.info, "semtypes.semGeneric") elif sonsLen(n) != sonsLen(s.typ): - GlobalError(n.info, errWrongNumberOfArguments) + LocalError(n.info, errWrongNumberOfArguments) + return errorType(c) addSonSkipIntLit(result, s.typ) # iterate over arguments: for i in countup(1, sonsLen(n)-1): @@ -716,12 +746,15 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = if elem.isNil: rawAddSon(result, elem) else: addSonSkipIntLit(result, elem) if isConcrete: - if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s) - result = instGenericContainer(c, n, result) + if s.ast == nil: + LocalError(n.info, errCannotInstantiateX, s.name.s) + result = errorType(c) + else: + result = instGenericContainer(c, n, result) proc semTypeFromMacro(c: PContext, n: PNode): PType = # Expands a macro or template until a type is returned - # results in GlobalError if the macro expands to something different + # results in an error type if the macro expands to something different var sym = expectMacroOrTemplateCall(c, n) markUsed(n, sym) case sym.kind @@ -730,7 +763,8 @@ proc semTypeFromMacro(c: PContext, n: PNode): PType = of skTemplate: result = semTypeNode(c, semTemplateExpr(c, n, sym), nil) else: - GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree) + LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree) + result = errorType(c) proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil @@ -743,16 +777,21 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semExprWithType(c, n.sons[0], {efInTypeof}).typ of nkPar: if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) - else: GlobalError(n.info, errTypeExpected) + else: + LocalError(n.info, errTypeExpected) + result = errorType(c) of nkCallKinds: let op = n.sons[0].ident if op.id in {ord(wAnd), ord(wOr)} or op.s == "|": var t1 = semTypeNode(c, n.sons[1], nil) t2 = semTypeNode(c, n.sons[2], nil) - - if t1 == nil: GlobalError(n.sons[1].info, errTypeExpected) - elif t2 == nil: GlobalError(n.sons[2].info, errTypeExpected) + if t1 == nil: + LocalError(n.sons[1].info, errTypeExpected) + result = errorType(c) + elif t2 == nil: + LocalError(n.sons[2].info, errTypeExpected) + result = errorType(c) else: result = newTypeS(tyTypeClass, c) result.addSonSkipIntLit(t1) @@ -783,14 +822,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = else: result = semGeneric(c, n, s, prev) of nkIdent, nkDotExpr, nkAccQuoted: var s = semTypeIdent(c, n) - if s.typ == nil: GlobalError(n.info, errTypeExpected) - if prev == nil: + if s.typ == nil: + LocalError(n.info, errTypeExpected) + result = errorType(c) + elif prev == nil: result = s.typ else: assignType(prev, s.typ) prev.id = s.typ.id result = prev - of nkSym: + of nkSym: if n.sym.kind == skType and n.sym.typ != nil: var t = n.sym.typ if prev == nil: @@ -799,8 +840,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = assignType(prev, t) result = prev markUsed(n, n.sym) - else: - GlobalError(n.info, errTypeExpected) + else: + LocalError(n.info, errTypeExpected) + result = errorType(c) of nkObjectTy: result = semObjectNode(c, n, prev) of nkTupleTy: result = semTuple(c, n, prev) of nkRefTy: result = semAnyRef(c, n, tyRef, prev) @@ -826,7 +868,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of nkType: result = n.typ of nkStmtListType: result = semStmtListType(c, n, prev) of nkBlockType: result = semBlockType(c, n, prev) - else: GlobalError(n.info, errTypeExpected) + else: + LocalError(n.info, errTypeExpected) + result = errorType(c) proc setMagicType(m: PSym, kind: TTypeKind, size: int) = m.typ.kind = kind @@ -874,7 +918,7 @@ proc processMagicType(c: PContext, m: PSym) = of mSeq: setMagicType(m, tySequence, 0) of mOrdinal: setMagicType(m, tyOrdinal, 0) of mPNimrodNode: nil - else: GlobalError(m.info, errTypeExpected) + else: LocalError(m.info, errTypeExpected) proc semGenericConstraints(c: PContext, n: PNode, result: PType) = var x = semTypeNode(c, n, nil) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 8cd7c3d1a..d75594dff 100755 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -119,7 +119,8 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = result = PType(idTableGet(cl.typeMap, t)) if result == nil: - GlobalError(t.sym.info, errCannotInstantiateX, typeToString(t)) + LocalError(t.sym.info, errCannotInstantiateX, typeToString(t)) + result = errorType(cl.c) elif result.kind == tyGenericParam: InternalError(cl.info, "substitution with generic parameter") diff --git a/todo.txt b/todo.txt index 2668945fa..0a7bcee89 100755 --- a/todo.txt +++ b/todo.txt @@ -29,6 +29,7 @@ Bugs compiles - bug: blocks can "export" an identifier but the CCG generates {} for them ... + version 0.9.XX ============== |