better error handling for better idetools support

This commit is contained in:
Araq
2012-07-29 23:08:28 +02:00
parent feaf6509bd
commit b595fc8347
13 changed files with 378 additions and 268 deletions

View File

@@ -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 = ""

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -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)
if isCallExpr(n):
var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
if expandedSym == nil:
LocalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
return errorSym(n[0])
var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
if expandedSym == nil:
GlobalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
if expandedSym.kind notin {skMacro, skTemplate}:
LocalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
return errorSym(n[0])
if expandedSym.kind notin {skMacro, skTemplate}:
GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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")

View File

@@ -29,6 +29,7 @@ Bugs
compiles
- bug: blocks can "export" an identifier but the CCG generates {} for them ...
version 0.9.XX
==============