better error handling for better idetools support

This commit is contained in:
Araq 2012-07-29 23:08:28 +02:00
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 = proc evalSlurp*(e: PNode, module: PSym): PNode =
expectString(e) expectString(e)
result = newNodeIT(nkStrLit, e.info, getSysType(tyString))
try: try:
var filename = e.strVal.FindFile var filename = e.strVal.FindFile
var content = readFile(filename) result.strVal = readFile(filename)
result = newStrNode(nkStrLit, content)
result.typ = getSysType(tyString)
result.info = e.info
# we produce a fake include statement for every slurped filename, so that # we produce a fake include statement for every slurped filename, so that
# the module dependencies are accurate: # the module dependencies are accurate:
appendToModule(module, newNode(nkIncludeStmt, e.info, @[ appendToModule(module, newNode(nkIncludeStmt, e.info, @[
newStrNode(nkStrLit, filename)])) newStrNode(nkStrLit, filename)]))
except EIO: except EIO:
GlobalError(e.info, errCannotOpenFile, e.strVal) result.strVal = ""
LocalError(e.info, errCannotOpenFile, e.strVal)
proc readOutput(p: PProcess): string = proc readOutput(p: PProcess): string =
result = "" result = ""

View file

@ -76,21 +76,23 @@ proc rawImportSymbol(c: PContext, s: PSym) =
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
let ident = lookups.considerAcc(n) let ident = lookups.considerAcc(n)
let s = StrTableGet(fromMod.tab, ident) let s = StrTableGet(fromMod.tab, ident)
if s == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s) if s == nil:
if s.kind == skStub: loadStub(s) LocalError(n.info, errUndeclaredIdentifier, ident.s)
if s.Kind notin ExportableSymKinds: else:
InternalError(n.info, "importSymbol: 2") if s.kind == skStub: loadStub(s)
# for an enumeration we have to add all identifiers if s.Kind notin ExportableSymKinds:
case s.Kind InternalError(n.info, "importSymbol: 2")
of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter: # for an enumeration we have to add all identifiers
# for a overloadable syms add all overloaded routines case s.Kind
var it: TIdentIter of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
var e = InitIdentIter(it, fromMod.tab, s.name) # for a overloadable syms add all overloaded routines
while e != nil: var it: TIdentIter
if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3") var e = InitIdentIter(it, fromMod.tab, s.name)
rawImportSymbol(c, e) while e != nil:
e = NextIdentIter(it, fromMod.tab) if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3")
else: rawImportSymbol(c, s) rawImportSymbol(c, e)
e = NextIdentIter(it, fromMod.tab)
else: rawImportSymbol(c, s)
proc importAllSymbols(c: PContext, fromMod: PSym) = proc importAllSymbols(c: PContext, fromMod: PSym) =
var i: TTabIter var i: TTabIter

View file

@ -36,6 +36,11 @@ proc considerAcc*(n: PNode): PIdent =
result = getIdent(id) result = getIdent(id)
else: else:
GlobalError(n.info, errIdentifierExpected, renderTree(n)) 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 type
TOverloadIterMode* = enum TOverloadIterMode* = enum
@ -122,13 +127,17 @@ proc lookUp*(c: PContext, n: PNode): PSym =
case n.kind case n.kind
of nkIdent: of nkIdent:
result = SymtabGet(c.Tab, n.ident) 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: of nkSym:
result = n.sym result = n.sym
of nkAccQuoted: of nkAccQuoted:
var ident = considerAcc(n) var ident = considerAcc(n)
result = SymtabGet(c.Tab, ident) 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") else: InternalError(n.info, "lookUp")
if Contains(c.AmbiguousSymbols, result.id): if Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, result.name.s) LocalError(n.info, errUseQualifier, result.name.s)
@ -144,7 +153,8 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
var ident = considerAcc(n) var ident = considerAcc(n)
result = SymtabGet(c.Tab, ident) result = SymtabGet(c.Tab, ident)
if result == nil and checkUndeclared in flags: 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 elif checkAmbiguity in flags and result != nil and
Contains(c.AmbiguousSymbols, result.id): Contains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, ident.s) LocalError(n.info, errUseQualifier, ident.s)
@ -167,10 +177,12 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
else: else:
result = StrTableGet(m.tab, ident) result = StrTableGet(m.tab, ident)
if result == nil and checkUndeclared in flags: if result == nil and checkUndeclared in flags:
GlobalError(n.sons[1].info, errUndeclaredIdentifier, ident.s) LocalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
elif checkUndeclared in flags: result = errorSym(n.sons[1])
GlobalError(n.sons[1].info, errIdentifierExpected, elif checkUndeclared in flags:
renderTree(n.sons[1])) LocalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1]))
result = errorSym(n.sons[1])
else: else:
result = nil result = nil
if result != nil and result.kind == skStub: loadStub(result) if result != nil and result.kind == skStub: loadStub(result)
@ -205,8 +217,9 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else: else:
result = InitIdentIter(o.it, o.m.tab, ident) result = InitIdentIter(o.it, o.m.tab, ident)
else: else:
GlobalError(n.sons[1].info, errIdentifierExpected, LocalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1])) renderTree(n.sons[1]))
result = errorSym(n.sons[1])
of nkSymChoice: of nkSymChoice:
o.mode = oimSymChoice o.mode = oimSymChoice
result = n.sons[0].sym 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 assert(false) # we want a stack trace here
if msg >= fatalMin and msg <= fatalMax: if msg >= fatalMin and msg <= fatalMax:
if gVerbosity >= 3: assert(false) if gVerbosity >= 3: assert(false)
quit(1) if gCmd != cmdIdeTools: quit(1)
if msg >= errMin and msg <= errMax: if msg >= errMin and msg <= errMax:
if gVerbosity >= 3: assert(false) if gVerbosity >= 3: assert(false)
inc(gErrorCounter) inc(gErrorCounter)

View file

@ -109,14 +109,23 @@ proc processImportObjC(s: PSym, extname: string) =
incl(s.flags, sfNamedParamCall) incl(s.flags, sfNamedParamCall)
excl(s.flags, sfForward) 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 = proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr: if n.kind != nkExprColonExpr:
GlobalError(n.info, errStringLiteralExpected) LocalError(n.info, errStringLiteralExpected)
else: # error correction:
result = newEmptyStrNode(n)
else:
n.sons[1] = c.semConstExpr(c, n.sons[1]) n.sons[1] = c.semConstExpr(c, n.sons[1])
case n.sons[1].kind case n.sons[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1] 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 = proc expectStrLit(c: PContext, n: PNode): string =
result = getStrLitNode(c, n).strVal result = getStrLitNode(c, n).strVal
@ -190,13 +199,17 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
Append(c.libs, result) Append(c.libs, result)
proc expectDynlibNode(c: PContext, n: PNode): PNode = proc expectDynlibNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr: GlobalError(n.info, errStringLiteralExpected) if n.kind != nkExprColonExpr:
else: LocalError(n.info, errStringLiteralExpected)
# error correction:
result = newEmptyStrNode(n)
else:
result = c.semExpr(c, n.sons[1]) result = c.semExpr(c, n.sons[1])
if result.kind == nkSym and result.sym.kind == skConst: if result.kind == nkSym and result.sym.kind == skConst:
result = result.sym.ast # look it up result = result.sym.ast # look it up
if result.typ == nil or result.typ.kind != tyString: 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) = proc processDynLib(c: PContext, n: PNode, sym: PSym) =
if (sym == nil) or (sym.kind == skModule): if (sym == nil) or (sym.kind == skModule):
@ -359,7 +372,9 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
of nkStrLit, nkRStrLit, nkTripleStrLit: of nkStrLit, nkRStrLit, nkTripleStrLit:
result = copyNode(n) result = copyNode(n)
var str = n.sons[1].strVal 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: # now parse the string literal and substitute symbols:
var a = 0 var a = 0
while true: while true:
@ -405,15 +420,20 @@ proc PragmaLine(c: PContext, n: PNode) =
if n.kind == nkExprColonExpr: if n.kind == nkExprColonExpr:
n.sons[1] = c.semConstExpr(c, n.sons[1]) n.sons[1] = c.semConstExpr(c, n.sons[1])
let a = n.sons[1] let a = n.sons[1]
if a.kind != nkPar: GlobalError(n.info, errXExpected, "tuple") if a.kind == nkPar:
var x = a.sons[0] var x = a.sons[0]
var y = a.sons[1] var y = a.sons[1]
if x.kind == nkExprColonExpr: x = x.sons[1] if x.kind == nkExprColonExpr: x = x.sons[1]
if y.kind == nkExprColonExpr: y = y.sons[1] if y.kind == nkExprColonExpr: y = y.sons[1]
if x.kind != nkStrLit: GlobalError(n.info, errStringLiteralExpected) if x.kind != nkStrLit:
if y.kind != nkIntLit: GlobalError(n.info, errIntLiteralExpected) LocalError(n.info, errStringLiteralExpected)
n.info.fileIndex = msgs.fileInfoIdx(x.strVal) elif y.kind != nkIntLit:
n.info.line = int16(y.intVal) 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: else:
# sensible default: # sensible default:
n.info = getInfoContext(-1) 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 instGenericContainer(c: PContext, n: PNode, header: PType): PType
proc typeMismatch(n: PNode, formal, actual: PType) = proc typeMismatch(n: PNode, formal, actual: PType) =
GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) & LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
typeToString(actual) & ") " & typeToString(actual) & ") " &
`%`(msgKindToString(errButExpectedX), [typeToString(formal)])) `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
@ -45,6 +45,9 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
result = IndexTypesMatch(c, formal, arg.typ, arg) result = IndexTypesMatch(c, formal, arg.typ, arg)
if result == nil: if result == nil:
typeMismatch(arg, formal, arg.typ) typeMismatch(arg, formal, arg.typ)
# error correction:
result = copyNode(arg)
result.typ = formal
proc isTopLevel(c: PContext): bool {.inline.} = proc isTopLevel(c: PContext): bool {.inline.} =
result = c.tab.tos <= 2 result = c.tab.tos <= 2
@ -62,7 +65,7 @@ proc semStmtScope(c: PContext, n: PNode): PNode
proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} = proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
if not typeAllowed(typ, skConst): 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 proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
@ -80,13 +83,15 @@ proc evalTypedExpr(c: PContext, e: PNode): PNode =
if result == nil: if result == nil:
result = evalConstExpr(c.module, e) result = evalConstExpr(c.module, e)
if result == nil or result.kind == nkEmpty: 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 = proc semConstExpr(c: PContext, n: PNode): PNode =
var e = semExprWithType(c, n) var e = semExprWithType(c, n)
if e == nil: if e == nil:
GlobalError(n.info, errConstExprExpected) LocalError(n.info, errConstExprExpected)
return nil return n
result = evalTypedExpr(c, e) result = evalTypedExpr(c, e)
include seminst, semcall include seminst, semcall
@ -129,12 +134,15 @@ proc forceBool(c: PContext, n: PNode): PNode =
if result == nil: result = n if result == nil: result = n
proc semConstBoolExpr(c: PContext, n: PNode): PNode = proc semConstBoolExpr(c: PContext, n: PNode): PNode =
result = fitNode(c, getSysType(tyBool), semExprWithType(c, n)) let nn = semExprWithType(c, n)
if result == nil: result = fitNode(c, getSysType(tyBool), nn)
GlobalError(n.info, errConstExprExpected) if result == nil:
return LocalError(n.info, errConstExprExpected)
return nn
result = getConstExpr(c.module, result) 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 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 = proc newTypeS(kind: TTypeKind, c: PContext): PType =
result = newType(kind, getCurrOwner()) 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) = proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
dest.kind = kind dest.kind = kind
dest.owner = getCurrOwner() 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 != nil:
if result.typ.kind == tyVar: result = newDeref(result) if result.typ.kind == tyVar: result = newDeref(result)
else: else:
GlobalError(n.info, errExprXHasNoType, LocalError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments})) renderTree(result, {renderNoComments}))
result.typ = errorType(c)
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags) 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: # do not produce another redundant error message:
raiseRecoverableError("") raiseRecoverableError("")
if result.typ == nil: if result.typ == nil:
GlobalError(n.info, errExprXHasNoType, LocalError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments})) renderTree(result, {renderNoComments}))
result.typ = errorType(c)
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
result = symChoice(c, n, s) 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 c.p.owner.typ.callConv = ccClosure
if illegalCapture(s) or c.p.next.owner != s.owner: if illegalCapture(s) or c.p.next.owner != s.owner:
# Currently captures are restricted to a single level of nesting: # 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) result = newSymNode(s, n.info)
of skGenericParam: of skGenericParam:
if s.ast == nil: InternalError(n.info, "no default for") 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) = proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
var diff = inheritanceDiff(castDest, src) var diff = inheritanceDiff(castDest, src)
if diff == high(int): if diff == high(int):
GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [ LocalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [
src.typeToString, castDest.typeToString]) src.typeToString, castDest.typeToString])
const const
@ -147,7 +149,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
d = base(d) d = base(d)
s = base(s) s = base(s)
if d == nil: if d == nil:
GlobalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [ LocalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
src.typeToString, castDest.typeToString]) src.typeToString, castDest.typeToString])
elif d.Kind == tyObject and s.Kind == tyObject: elif d.Kind == tyObject and s.Kind == tyObject:
checkConversionBetweenObjects(info, d, s) checkConversionBetweenObjects(info, d, s)
@ -159,7 +161,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
case cmpTypes(d, s) case cmpTypes(d, s)
of isNone, isGeneric: of isNone, isGeneric:
if not compareTypes(castDest, src, dcEqIgnoreDistinct): if not compareTypes(castDest, src, dcEqIgnoreDistinct):
GlobalError(info, errGenerated, `%`( LocalError(info, errGenerated, `%`(
MsgKindToString(errIllegalConvFromXtoY), MsgKindToString(errIllegalConvFromXtoY),
[typeToString(src), typeToString(castDest)])) [typeToString(src), typeToString(castDest)]))
else: else:
@ -184,7 +186,9 @@ proc isCastable(dst, src: PType): bool =
(skipTypes(src, abstractInst).kind in IntegralTypes) (skipTypes(src, abstractInst).kind in IntegralTypes)
proc semConv(c: PContext, n: PNode, s: PSym): PNode = 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 = newNodeI(nkConv, n.info)
result.typ = semTypeNode(c, n.sons[0], nil) result.typ = semTypeNode(c, n.sons[0], nil)
addSon(result, copyTree(n.sons[0])) 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, copyTree(n.sons[0]))
addSon(result, semExprWithType(c, n.sons[1])) addSon(result, semExprWithType(c, n.sons[1]))
if not isCastable(result.typ, result.sons[1].Typ): if not isCastable(result.typ, result.sons[1].Typ):
GlobalError(result.info, errExprCannotBeCastedToX, LocalError(result.info, errExprCannotBeCastedToX,
typeToString(result.Typ)) typeToString(result.Typ))
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
const const
opToStr: array[mLow..mHigh, string] = ["low", "high"] opToStr: array[mLow..mHigh, string] = ["low", "high"]
if sonsLen(n) != 2: if sonsLen(n) != 2:
GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m]) LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
else: else:
n.sons[1] = semExprWithType(c, n.sons[1]) n.sons[1] = semExprWithType(c, n.sons[1])
restoreOldStyleType(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 n.typ = n.sons[1].typ.sons[0] # indextype
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32:
n.typ = n.sons[1].typ n.typ = n.sons[1].typ
else: GlobalError(n.info, errInvalidArgForX, opToStr[m]) else: LocalError(n.info, errInvalidArgForX, opToStr[m])
result = n result = n
proc semSizeof(c: PContext, n: PNode): PNode = proc semSizeof(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2: if sonsLen(n) != 2:
GlobalError(n.info, errXExpectsTypeOrValue, "sizeof") LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
else: else:
n.sons[1] = semExprWithType(c, n.sons[1]) n.sons[1] = semExprWithType(c, n.sons[1])
restoreOldStyleType(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) let y = skipTypes(n.sons[2].typ, abstractPtrs)
if x.kind == tyTypeDesc or y.kind != tyTypeDesc: 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: elif b.kind != tyObject or a.kind != tyObject:
GlobalError(n.info, errXExpectsObjectTypes, "of") LocalError(n.info, errXExpectsObjectTypes, "of")
let diff = inheritanceDiff(a, b) else:
# | returns: 0 iff `a` == `b` let diff = inheritanceDiff(a, b)
# | returns: -x iff `a` is the x'th direct superclass of `b` # | returns: 0 iff `a` == `b`
# | returns: +x iff `a` is the x'th direct subclass of `b` # | returns: -x iff `a` is the x'th direct superclass of `b`
# | returns: `maxint` iff `a` and `b` are not compatible at all # | returns: +x iff `a` is the x'th direct subclass of `b`
if diff <= 0: # | returns: `maxint` iff `a` and `b` are not compatible at all
# optimize to true: if diff <= 0:
Message(n.info, hintConditionAlwaysTrue, renderTree(n)) # optimize to true:
result = newIntNode(nkIntLit, 1) Message(n.info, hintConditionAlwaysTrue, renderTree(n))
result.info = n.info result = newIntNode(nkIntLit, 1)
result.typ = getSysType(tyBool) result.info = n.info
return result result.typ = getSysType(tyBool)
elif diff == high(int): return result
GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a)) elif diff == high(int):
n.typ = getSysType(tyBool) LocalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
else: else:
GlobalError(n.info, errXExpectsTwoArguments, "of") LocalError(n.info, errXExpectsTwoArguments, "of")
n.typ = getSysType(tyBool)
result = n result = n
proc semIs(c: PContext, n: PNode): PNode = 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}: if n[2].kind notin {nkStrLit..nkTripleStrLit}:
let b = semTypeNode(c, n[2], nil) let b = semTypeNode(c, n[2], nil)
n.sons[2] = newNodeIT(nkType, n[2].info, b) n.sons[2] = newNodeIT(nkType, n[2].info, b)
result = n
else: else:
GlobalError(n.info, errXExpectsTwoArguments, "is") LocalError(n.info, errXExpectsTwoArguments, "is")
result = n
proc semOpAux(c: PContext, n: PNode) = proc semOpAux(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
@ -590,7 +595,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
of skMacro, skTemplate: nil of skMacro, skTemplate: nil
else: else:
if (callee.kind == skIterator) and (callee.id == c.p.owner.id): 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 sfNoSideEffect notin callee.flags:
if {sfImportc, sfSideEffect} * callee.flags != {}: if {sfImportc, sfSideEffect} * callee.flags != {}:
incl(c.p.owner.flags, sfSideEffect) incl(c.p.owner.flags, sfSideEffect)
@ -625,7 +630,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if m.state != csMatch: if m.state != csMatch:
if c.inCompilesContext > 0: if c.inCompilesContext > 0:
# speed up error generation: # speed up error generation:
GlobalError(n.Info, errTypeMismatch, "") LocalError(n.Info, errTypeMismatch, "")
return emptyNode
else: else:
var msg = msgKindToString(errTypeMismatch) var msg = msgKindToString(errTypeMismatch)
for i in countup(1, sonsLen(n) - 1): 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, typeToString(n.sons[i].typ))
add(msg, ")\n" & msgKindToString(errButExpected) & "\n" & add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
typeToString(n.sons[0].typ)) typeToString(n.sons[0].typ))
GlobalError(n.Info, errGenerated, msg) LocalError(n.Info, errGenerated, msg)
return emptyNode
result = nil result = nil
else: else:
result = m.call result = m.call
@ -649,8 +656,9 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
nOrig.sons[0] = prc nOrig.sons[0] = prc
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil: if result == nil:
GlobalError(n.info, errExprXCannotBeCalled, LocalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))
return emptyNode
fixAbstractType(c, result) fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result) analyseIfAddressTakenInCall(c, result)
if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone: 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) result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil: if result == nil:
result = overloadedCallOpr(c, n) 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 let callee = result.sons[0].sym
case callee.kind case callee.kind
of skMacro: result = semMacroExpr(c, nOrig, callee) 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! # we MUST not check 'n' for semantics again here!
result = newNodeI(nkCall, n.info) result = newNodeI(nkCall, n.info)
var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo") var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo")
if e == nil: GlobalError(n.info, errSystemNeeds, "echo") if e != nil:
addSon(result, newSymNode(e)) addSon(result, newSymNode(e))
else:
LocalError(n.info, errSystemNeeds, "echo")
addSon(result, emptyNode)
var arg = buildStringify(c, n) var arg = buildStringify(c, n)
# problem is: implicit '$' is not checked for semantics yet. So we give up # problem is: implicit '$' is not checked for semantics yet. So we give up
# and check 'arg' for semantics again: # 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, newIdentNode(i, n.info))
addSon(result, copyTree(n[0])) addSon(result, copyTree(n[0]))
else: else:
GlobalError(n.Info, errUndeclaredFieldX, i.s) LocalError(n.Info, errUndeclaredFieldX, i.s)
result = emptyNode
proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode = proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
result = newNodeI(nkCall, n.info) result = newNodeI(nkCall, n.info)
@ -946,9 +960,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
{tyInt..tyInt64}: {tyInt..tyInt64}:
var idx = getOrdValue(n.sons[1]) var idx = getOrdValue(n.sons[1])
if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)] if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
else: GlobalError(n.info, errInvalidIndexValueForTuple) else: LocalError(n.info, errInvalidIndexValueForTuple)
else: else:
GlobalError(n.info, errIndexTypesDoNotMatch) LocalError(n.info, errIndexTypesDoNotMatch)
result = n result = n
else: nil else: nil
@ -972,7 +986,7 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
fixAbstractType(c, result) fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result) analyseIfAddressTakenInCall(c, result)
else: else:
globalError(n.Info, errUndeclaredFieldX, id.s) LocalError(n.Info, errUndeclaredFieldX, id.s)
proc takeImplicitAddr(c: PContext, n: PNode): PNode = proc takeImplicitAddr(c: PContext, n: PNode): PNode =
case n.kind case n.kind
@ -984,9 +998,9 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode =
var valid = isAssignable(c, n) var valid = isAssignable(c, n)
if valid != arLValue: if valid != arLValue:
if valid == arLocalLValue: if valid == arLocalLValue:
GlobalError(n.info, errXStackEscape, renderTree(n, {renderNoComments})) LocalError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
else: else:
GlobalError(n.info, errExprHasNoAddress) LocalError(n.info, errExprHasNoAddress)
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ)) result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
result.add(n) result.add(n)
@ -1062,13 +1076,13 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
else: else:
result = StrTableGet(m.tab, ident) result = StrTableGet(m.tab, ident)
else: else:
GlobalError(n.sons[1].info, errIdentifierExpected, "") LocalError(n.sons[1].info, errIdentifierExpected, "")
of nkAccQuoted: of nkAccQuoted:
result = lookupForDefined(c, considerAcc(n), onlyCurrentScope) result = lookupForDefined(c, considerAcc(n), onlyCurrentScope)
of nkSym: of nkSym:
result = n.sym result = n.sym
else: else:
GlobalError(n.info, errIdentifierExpected, renderTree(n)) LocalError(n.info, errIdentifierExpected, renderTree(n))
result = nil result = nil
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = 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 = proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
## The argument to the proc should be nkCall(...) or similar ## The argument to the proc should be nkCall(...) or similar
## Returns the macro/template symbol ## Returns the macro/template symbol
if not isCallExpr(n): if isCallExpr(n):
GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree) 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.kind notin {skMacro, skTemplate}:
if expandedSym == nil: LocalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
GlobalError(n.info, errUndeclaredIdentifier, n[0].renderTree) return errorSym(n[0])
if expandedSym.kind notin {skMacro, skTemplate}: result = expandedSym
GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s) else:
LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
result = expandedSym result = errorSym(n)
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym, proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
flags: TExprFlags): PNode = flags: TExprFlags): PNode =
@ -1240,7 +1257,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
if typ == nil: if typ == nil:
typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal}) typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
if not isOrdinalType(typ): if not isOrdinalType(typ):
GlobalError(n.info, errOrdinalTypeExpected) LocalError(n.info, errOrdinalTypeExpected)
return return
if lengthOrd(typ) > MaxSetElements: if lengthOrd(typ) > MaxSetElements:
typ = makeRangeType(c, 0, MaxSetElements - 1, n.info) typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
@ -1288,11 +1305,11 @@ proc checkPar(n: PNode): TParKind =
if result == paTupleFields: if result == paTupleFields:
if (n.sons[i].kind != nkExprColonExpr) or if (n.sons[i].kind != nkExprColonExpr) or
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}): not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
GlobalError(n.sons[i].info, errNamedExprExpected) LocalError(n.sons[i].info, errNamedExprExpected)
return paNone return paNone
else: else:
if n.sons[i].kind == nkExprColonExpr: if n.sons[i].kind == nkExprColonExpr:
GlobalError(n.sons[i].info, errNamedExprNotAllowed) LocalError(n.sons[i].info, errNamedExprNotAllowed)
return paNone return paNone
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode = 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]) addSon(result, n.sons[0].sons[i])
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i]) for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
result = semTemplateExpr(c, result, s, semCheck) result = semTemplateExpr(c, result, s, semCheck)
else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s) else:
else: LocalError(n.info, errXisNoMacroOrTemplate, s.name.s)
GlobalError(n.info, errInvalidExpressionX, result = emptyNode
renderTree(a, {renderNoComments})) else:
LocalError(n.info, errInvalidExpressionX,
renderTree(a, {renderNoComments}))
result = emptyNode
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n result = n
@ -1505,7 +1525,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
checkSonsLen(n, 1) checkSonsLen(n, 1)
n.sons[0] = semExprWithType(c, n.sons[0]) n.sons[0] = semExprWithType(c, n.sons[0])
if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}: 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) n.typ = makePtrType(c, n.sons[0].typ)
of nkHiddenAddr, nkHiddenDeref: of nkHiddenAddr, nkHiddenDeref:
checkSonsLen(n, 1) checkSonsLen(n, 1)
@ -1525,10 +1545,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkTableConstr: of nkTableConstr:
result = semTableConstr(c, n) result = semTableConstr(c, n)
of nkSymChoice: 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: of nkStaticExpr:
result = semStaticExpr(c, n) result = semStaticExpr(c, n)
else: else:
GlobalError(n.info, errInvalidExpressionX, LocalError(n.info, errInvalidExpressionX,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))
incl(result.flags, nfSem) incl(result.flags, nfSem)

View file

@ -18,7 +18,7 @@ proc expectIntLit(c: PContext, n: PNode): int =
let x = c.semConstExpr(c, n) let x = c.semConstExpr(c, n)
case x.kind case x.kind
of nkIntLit..nkInt64Lit: result = int(x.intVal) of nkIntLit..nkInt64Lit: result = int(x.intVal)
else: GlobalError(n.info, errIntLiteralExpected) else: LocalError(n.info, errIntLiteralExpected)
proc semInstantiationInfo(c: PContext, n: PNode): PNode = proc semInstantiationInfo(c: PContext, n: PNode): PNode =
result = newNodeIT(nkPar, n.info, n.typ) result = newNodeIT(nkPar, n.info, n.typ)

View file

@ -163,18 +163,20 @@ proc SemReturn(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1)
if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}: if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}:
globalError(n.info, errXNotAllowedHere, "\'return\'") LocalError(n.info, errXNotAllowedHere, "\'return\'")
if n.sons[0].kind != nkEmpty: elif n.sons[0].kind != nkEmpty:
# transform ``return expr`` to ``result = expr; return`` # transform ``return expr`` to ``result = expr; return``
if c.p.resultSym == nil: globalError(n.info, errNoReturnTypeDeclared) if c.p.resultSym != nil:
var a = newNodeI(nkAsgn, n.sons[0].info) var a = newNodeI(nkAsgn, n.sons[0].info)
addSon(a, newSymNode(c.p.resultSym)) addSon(a, newSymNode(c.p.resultSym))
addSon(a, n.sons[0]) addSon(a, n.sons[0])
n.sons[0] = semAsgn(c, a) n.sons[0] = semAsgn(c, a)
# optimize away ``result = result``: # optimize away ``result = result``:
if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult:
n.sons[0] = ast.emptyNode n.sons[0] = ast.emptyNode
else:
LocalError(n.info, errNoReturnTypeDeclared)
proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) = proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
var t = skipTypes(restype, {tyGenericInst}) var t = skipTypes(restype, {tyGenericInst})
case t.kind case t.kind
@ -198,8 +200,8 @@ proc SemYield(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1)
if c.p.owner == nil or c.p.owner.kind != skIterator: if c.p.owner == nil or c.p.owner.kind != skIterator:
GlobalError(n.info, errYieldNotAllowedHere) LocalError(n.info, errYieldNotAllowedHere)
if n.sons[0].kind != nkEmpty: elif n.sons[0].kind != nkEmpty:
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility: n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
var restype = c.p.owner.typ.sons[0] var restype = c.p.owner.typ.sons[0]
if restype != nil: if restype != nil:
@ -254,22 +256,24 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
else: typ = skipIntLit(def.typ) else: typ = skipIntLit(def.typ)
else: else:
def = ast.emptyNode 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: # this can only happen for errornous var statements:
if typ == nil: continue if typ == nil: continue
if not typeAllowed(typ, symkind): if not typeAllowed(typ, symkind):
GlobalError(a.info, errXisNoType, typeToString(typ)) LocalError(a.info, errXisNoType, typeToString(typ))
var tup = skipTypes(typ, {tyGenericInst}) var tup = skipTypes(typ, {tyGenericInst})
if a.kind == nkVarTuple: if a.kind == nkVarTuple:
if tup.kind != tyTuple: GlobalError(a.info, errXExpected, "tuple") if tup.kind != tyTuple:
if length-2 != sonsLen(tup): localError(a.info, errXExpected, "tuple")
GlobalError(a.info, errWrongNumberOfVariables) elif length-2 != sonsLen(tup):
b = newNodeI(nkVarTuple, a.info) localError(a.info, errWrongNumberOfVariables)
newSons(b, length) else:
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator b = newNodeI(nkVarTuple, a.info)
b.sons[length-1] = def newSons(b, length)
addSon(result, b) 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 elif tup.kind == tyTuple and def.kind == nkPar and
a.kind == nkIdentDefs and a.len > 3: a.kind == nkIdentDefs and a.len > 3:
Message(a.info, warnEachIdentIsTuple) Message(a.info, warnEachIdentIsTuple)
@ -308,33 +312,19 @@ proc semConst(c: PContext, n: PNode): PNode =
var typ: PType = nil var typ: PType = nil
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
when true: var def = semConstExpr(c, a.sons[2])
var def = semConstExpr(c, a.sons[2]) if def == nil:
if def == nil: GlobalError(a.sons[2].info, errConstExprExpected) LocalError(a.sons[2].info, errConstExprExpected)
# check type compatibility between def.typ and typ: continue
if typ != nil: # check type compatibility between def.typ and typ:
def = fitRemoveHiddenConv(c, typ, def) if typ != nil:
else: def = fitRemoveHiddenConv(c, typ, def)
typ = def.typ
if not typeAllowed(typ, skConst):
GlobalError(a.info, errXisNoType, typeToString(typ))
else: else:
var e = semExprWithType(c, a.sons[2]) typ = def.typ
if e == nil: GlobalError(a.sons[2].info, errConstExprExpected) if typ == nil: continue
var def = getConstExpr(c.module, e) if not typeAllowed(typ, skConst):
if def == nil: LocalError(a.info, errXisNoType, typeToString(typ))
v.flags.incl(sfFakeConst) continue
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))
v.typ = typ v.typ = typ
v.ast = def # no need to copy v.ast = def # no need to copy
addInterfaceDecl(c, v) addInterfaceDecl(c, v)
@ -382,7 +372,10 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
# a 'while true: stmt; break' loop ... # a 'while true: stmt; break' loop ...
result = newNodeI(nkWhileStmt, n.info) result = newNodeI(nkWhileStmt, n.info)
var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true") 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)) result.add(newSymNode(trueSymbol, n.info))
var stmts = newNodeI(nkStmtList, 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 length = sonsLen(n)
var call = n.sons[length-2] var call = n.sons[length-2]
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs): 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) var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!") 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 # length == 3 means that there is one for loop variable
# and thus no tuple unpacking: # and thus no tuple unpacking:
if iter.kind != tyTuple or length == 3: if iter.kind != tyTuple or length == 3:
if length != 3: GlobalError(n.info, errWrongNumberOfVariables) if length == 3:
var v = newSymS(skForVar, n.sons[0], c) var v = newSymS(skForVar, n.sons[0], c)
if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal)
# BUGFIX: don't use `iter` here as that would strip away # BUGFIX: don't use `iter` here as that would strip away
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
# for an example: # for an example:
v.typ = n.sons[length-2].typ v.typ = n.sons[length-2].typ
n.sons[0] = newSymNode(v) n.sons[0] = newSymNode(v)
addDecl(c, v) addDecl(c, v)
else: else:
if length-2 != sonsLen(iter): LocalError(n.info, errWrongNumberOfVariables)
GlobalError(n.info, errWrongNumberOfVariables) elif length-2 != sonsLen(iter):
LocalError(n.info, errWrongNumberOfVariables)
else:
for i in countup(0, length - 3): for i in countup(0, length - 3):
var v = newSymS(skForVar, n.sons[i], c) var v = newSymS(skForVar, n.sons[i], c)
if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) 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: call.sons[0].sym.kind != skIterator:
if length == 3: if length == 3:
n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2]) n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
result = semForVars(c, n)
elif length == 4: elif length == 4:
n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2]) n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
result = semForVars(c, n)
else: 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: elif call.sons[0].sym.magic != mNone:
if call.sons[0].sym.magic == mOmpParFor: if call.sons[0].sym.magic == mOmpParFor:
result = semForVars(c, n) result = semForVars(c, n)
@ -504,7 +499,7 @@ proc semTry(c: PContext, n: PNode): PNode =
var typ = semTypeNode(c, a.sons[j], nil) var typ = semTypeNode(c, a.sons[j], nil)
if typ.kind == tyRef: typ = typ.sons[0] if typ.kind == tyRef: typ = typ.sons[0]
if typ.kind != tyObject: 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] = newNodeI(nkType, a.sons[j].info)
a.sons[j].typ = typ a.sons[j].typ = typ
if ContainsOrIncl(check, typ.id): if ContainsOrIncl(check, typ.id):
@ -549,7 +544,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
if (a.sons[0].kind != nkSym): IllFormedAst(a) if (a.sons[0].kind != nkSym): IllFormedAst(a)
var s = a.sons[0].sym var s = a.sons[0].sym
if s.magic == mNone and a.sons[2].kind == nkEmpty: 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 s.magic != mNone: processMagicType(c, s)
if a.sons[1].kind != nkEmpty: if a.sons[1].kind != nkEmpty:
# We have a generic type declaration here. In generic types, # 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 f = checkModuleName(n.sons[i])
var fileIndex = f.fileInfoIdx var fileIndex = f.fileInfoIdx
if ContainsOrIncl(c.includedFiles, fileIndex): if ContainsOrIncl(c.includedFiles, fileIndex):
GlobalError(n.info, errRecursiveDependencyX, f.extractFilename) LocalError(n.info, errRecursiveDependencyX, f.extractFilename)
addSon(result, semStmt(c, gIncludeFile(f))) else:
Excl(c.includedFiles, fileIndex) addSon(result, semStmt(c, gIncludeFile(f)))
Excl(c.includedFiles, fileIndex)
proc setLine(n: PNode, info: TLineInfo) = proc setLine(n: PNode, info: TLineInfo) =
for i in 0 .. <safeLen(n): setLine(n.sons[i], info) 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 var strVal: PNode = nil
case skipTypes(v.typ, abstractInst).kind case skipTypes(v.typ, abstractInst).kind
of tyTuple: of tyTuple:
if sonsLen(v) != 2: GlobalError(v.info, errWrongNumberOfVariables) if sonsLen(v) == 2:
strVal = v.sons[1] # second tuple part is the string value strVal = v.sons[1] # second tuple part is the string value
if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}: if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCstring}:
GlobalError(strVal.info, errStringLiteralExpected) x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal else:
LocalError(strVal.info, errStringLiteralExpected)
else:
LocalError(v.info, errWrongNumberOfVariables)
of tyString, tyCstring: of tyString, tyCstring:
strVal = v strVal = v
x = counter x = counter
@ -59,7 +62,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if i != 1: if i != 1:
if x != counter: incl(result.flags, tfEnumHasHoles) if x != counter: incl(result.flags, tfEnumHasHoles)
if x < counter: 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 e.ast = strVal # might be nil
counter = x counter = x
of nkSym: of nkSym:
@ -84,10 +88,13 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
if base.kind == tyGenericInst: base = lastSon(base) if base.kind == tyGenericInst: base = lastSon(base)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected) if not isOrdinalType(base):
if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig) LocalError(n.info, errOrdinalTypeExpected)
else: elif lengthOrd(base) > MaxSetElements:
GlobalError(n.info, errXExpectsOneTypeParam, "set") LocalError(n.info, errSetTooBig)
else:
LocalError(n.info, errXExpectsOneTypeParam, "set")
addSonSkipIntLit(result, errorType(c))
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType = 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) var base = semTypeNode(c, n.sons[1], nil)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: 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 = proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, prev: PType): PType =
if sonsLen(n) == 1: if sonsLen(n) == 1:
@ -110,7 +118,9 @@ proc semVarType(c: PContext, n: PNode, prev: PType): PType =
if sonsLen(n) == 1: if sonsLen(n) == 1:
result = newOrPrevType(tyVar, prev, c) result = newOrPrevType(tyVar, prev, c)
var base = semTypeNode(c, n.sons[0], nil) 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) addSonSkipIntLit(result, base)
else: else:
result = newConstraint(c, tyVar) result = newConstraint(c, tyVar)
@ -128,28 +138,32 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyRange, prev, c) result = newOrPrevType(tyRange, prev, c)
result.n = newNodeI(nkRange, n.info) result.n = newNodeI(nkRange, n.info)
if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): 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 a = semConstExpr(c, n[1])
var b = semConstExpr(c, n[2]) var b = semConstExpr(c, n[2])
if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch) if not sameType(a.typ, b.typ):
if a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,tyFloat..tyFloat128, LocalError(n.info, errPureTypeMismatch)
tyUInt8..tyUInt32}: elif a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,
GlobalError(n.info, errOrdinalTypeExpected) tyFloat..tyFloat128,tyUInt8..tyUInt32}:
if enumHasHoles(a.typ): LocalError(n.info, errOrdinalTypeExpected)
GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) elif enumHasHoles(a.typ):
if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty) 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, a)
addSon(result.n, b) addSon(result.n, b)
addSonSkipIntLit(result, b.typ) addSonSkipIntLit(result, b.typ)
proc semRange(c: PContext, n: PNode, prev: PType): PType = proc semRange(c: PContext, n: PNode, prev: PType): PType =
result = nil result = nil
if sonsLen(n) == 2: if sonsLen(n) == 2:
if isRange(n[1]): result = semRangeAux(c, n[1], prev) if isRange(n[1]): result = semRangeAux(c, n[1], prev)
else: GlobalError(n.sons[0].info, errRangeExpected) else:
else: LocalError(n.sons[0].info, errRangeExpected)
GlobalError(n.info, errXExpectsOneTypeParam, "range") result = errorType(c)
else:
LocalError(n.info, errXExpectsOneTypeParam, "range")
result = errorType(c)
proc semArray(c: PContext, n: PNode, prev: PType): PType = proc semArray(c: PContext, n: PNode, prev: PType): PType =
var indx, base: PType var indx, base: PType
result = newOrPrevType(tyArray, prev, c) 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 == tyGenericInst: indx = lastSon(indx)
if indx.kind != tyGenericParam: if indx.kind != tyGenericParam:
if not isOrdinalType(indx): if not isOrdinalType(indx):
GlobalError(n.sons[1].info, errOrdinalTypeExpected) LocalError(n.sons[1].info, errOrdinalTypeExpected)
if enumHasHoles(indx): elif enumHasHoles(indx):
GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s) LocalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
base = semTypeNode(c, n.sons[2], nil) base = semTypeNode(c, n.sons[2], nil)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: else:
GlobalError(n.info, errArrayExpectsTwoTypeParams) LocalError(n.info, errArrayExpectsTwoTypeParams)
result = errorType(c)
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyOrdinal, prev, c) 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) var base = semTypeNode(c, n.sons[1], nil)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): if not isOrdinalType(base):
GlobalError(n.sons[1].info, errOrdinalTypeExpected) LocalError(n.sons[1].info, errOrdinalTypeExpected)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: else:
GlobalError(n.info, errXExpectsOneTypeParam, "ordinal") LocalError(n.info, errXExpectsOneTypeParam, "ordinal")
result = errorType(c)
proc semTypeIdent(c: PContext, n: PNode): PSym = proc semTypeIdent(c: PContext, n: PNode): PSym =
if n.kind == nkSym: if n.kind == nkSym:
@ -205,14 +221,17 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
while amb != nil and amb.kind != skType: while amb != nil and amb.kind != skType:
amb = nextOverloadIter(ov, c, n) amb = nextOverloadIter(ov, c, n)
if amb != nil: result = amb if amb != nil: result = amb
else: GlobalError(n.info, errTypeExpected) else:
LocalError(n.info, errTypeExpected)
return errorSym(n)
if result.typ.kind != tyGenericParam: if result.typ.kind != tyGenericParam:
# XXX get rid of this hack! # XXX get rid of this hack!
reset(n[]) reset(n[])
n.kind = nkSym n.kind = nkSym
n.sym = result n.sym = result
else: else:
GlobalError(n.info, errIdentifierExpected) LocalError(n.info, errIdentifierExpected)
result = errorSym(n)
proc semTuple(c: PContext, n: PNode, prev: PType): PType = proc semTuple(c: PContext, n: PNode, prev: PType): PType =
if n.sonsLen == 0: return newConstraint(c, tyTuple) 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) var length = sonsLen(a)
if a.sons[length - 2].kind != nkEmpty: if a.sons[length - 2].kind != nkEmpty:
typ = semTypeNode(c, a.sons[length - 2], nil) 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: 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): for j in countup(0, length - 3):
var field = newSymS(skField, a.sons[j], c) var field = newSymS(skField, a.sons[j], c)
field.typ = typ field.typ = typ
field.position = counter field.position = counter
inc(counter) inc(counter)
if ContainsOrIncl(check, field.name.id): if ContainsOrIncl(check, field.name.id):
GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s) LocalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
addSon(result.n, newSymNode(field)) else:
addSonSkipIntLit(result, typ) addSon(result.n, newSymNode(field))
addSonSkipIntLit(result, typ)
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
allowed: TSymFlags): PSym = 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 = newNodeI(nkRange, a.info)
result.add(at) result.add(at)
result.add(bt) result.add(bt)
if emptyRange(ac, bc): GlobalError(b.info, errRangeIsEmpty) if emptyRange(ac, bc): LocalError(b.info, errRangeIsEmpty)
covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1 else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
proc SemCaseBranchRange(c: PContext, t, b: PNode, proc SemCaseBranchRange(c: PContext, t, b: PNode,
covered: var biggestInt): 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) incl(a.sons[0].sym.flags, sfDiscriminant)
var covered: biggestInt = 0 var covered: biggestInt = 0
var typ = skipTypes(a.sons[0].Typ, abstractVar) var typ = skipTypes(a.sons[0].Typ, abstractVar)
if not isOrdinalType(typ): GlobalError(n.info, errSelectorMustBeOrdinal) if not isOrdinalType(typ):
if firstOrd(typ) < 0: LocalError(n.info, errSelectorMustBeOrdinal)
GlobalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s) elif firstOrd(typ) < 0:
if lengthOrd(typ) > 0x00007FFF: LocalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
GlobalError(n.info, errLenXinvalid, a.sons[0].sym.name.s) elif lengthOrd(typ) > 0x00007FFF:
LocalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
var chckCovered = true var chckCovered = true
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
var b = copyTree(n.sons[i]) 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 else: a = ast.emptyNode
if n.sons[length-1].kind != nkEmpty: if n.sons[length-1].kind != nkEmpty:
localError(n.sons[length-1].info, errInitHereNotAllowed) localError(n.sons[length-1].info, errInitHereNotAllowed)
var typ: PType
if n.sons[length-2].kind == nkEmpty: if n.sons[length-2].kind == nkEmpty:
GlobalError(n.info, errTypeExpected) LocalError(n.info, errTypeExpected)
var typ = semTypeNode(c, n.sons[length-2], nil) typ = errorType(c)
for i in countup(0, sonsLen(n)-3): 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}) var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
f.typ = typ f.typ = typ
f.position = pos f.position = pos
@ -568,7 +594,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
let s = SymtabGet(c.tab, paramTypId) let s = SymtabGet(c.tab, paramTypId)
# tests/run/tinterf triggers this: # tests/run/tinterf triggers this:
if s != nil: result = s.typ if s != nil: result = s.typ
else: GlobalError(info, errCannotInstantiateX, paramName) else:
LocalError(info, errCannotInstantiateX, paramName)
result = errorType(c)
else: else:
block addImplicitGeneric: block addImplicitGeneric:
# is this a bindOnce type class already present in the param list? # 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) result = newOrPrevType(tyGenericInvokation, prev, c)
var isConcrete = true var isConcrete = true
if s.typ == nil: 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: elif s.typ.kind != tyGenericBody:
isConcrete = false isConcrete = false
elif s.typ.containerID == 0: elif s.typ.containerID == 0:
InternalError(n.info, "semtypes.semGeneric") InternalError(n.info, "semtypes.semGeneric")
elif sonsLen(n) != sonsLen(s.typ): elif sonsLen(n) != sonsLen(s.typ):
GlobalError(n.info, errWrongNumberOfArguments) LocalError(n.info, errWrongNumberOfArguments)
return errorType(c)
addSonSkipIntLit(result, s.typ) addSonSkipIntLit(result, s.typ)
# iterate over arguments: # iterate over arguments:
for i in countup(1, sonsLen(n)-1): 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) if elem.isNil: rawAddSon(result, elem)
else: addSonSkipIntLit(result, elem) else: addSonSkipIntLit(result, elem)
if isConcrete: if isConcrete:
if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s) if s.ast == nil:
result = instGenericContainer(c, n, result) LocalError(n.info, errCannotInstantiateX, s.name.s)
result = errorType(c)
else:
result = instGenericContainer(c, n, result)
proc semTypeFromMacro(c: PContext, n: PNode): PType = proc semTypeFromMacro(c: PContext, n: PNode): PType =
# Expands a macro or template until a type is returned # 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) var sym = expectMacroOrTemplateCall(c, n)
markUsed(n, sym) markUsed(n, sym)
case sym.kind case sym.kind
@ -730,7 +763,8 @@ proc semTypeFromMacro(c: PContext, n: PNode): PType =
of skTemplate: of skTemplate:
result = semTypeNode(c, semTemplateExpr(c, n, sym), nil) result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
else: 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 = proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = nil result = nil
@ -743,16 +777,21 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semExprWithType(c, n.sons[0], {efInTypeof}).typ result = semExprWithType(c, n.sons[0], {efInTypeof}).typ
of nkPar: of nkPar:
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) 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: of nkCallKinds:
let op = n.sons[0].ident let op = n.sons[0].ident
if op.id in {ord(wAnd), ord(wOr)} or op.s == "|": if op.id in {ord(wAnd), ord(wOr)} or op.s == "|":
var var
t1 = semTypeNode(c, n.sons[1], nil) t1 = semTypeNode(c, n.sons[1], nil)
t2 = semTypeNode(c, n.sons[2], nil) t2 = semTypeNode(c, n.sons[2], nil)
if t1 == nil:
if t1 == nil: GlobalError(n.sons[1].info, errTypeExpected) LocalError(n.sons[1].info, errTypeExpected)
elif t2 == nil: GlobalError(n.sons[2].info, errTypeExpected) result = errorType(c)
elif t2 == nil:
LocalError(n.sons[2].info, errTypeExpected)
result = errorType(c)
else: else:
result = newTypeS(tyTypeClass, c) result = newTypeS(tyTypeClass, c)
result.addSonSkipIntLit(t1) result.addSonSkipIntLit(t1)
@ -783,14 +822,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else: result = semGeneric(c, n, s, prev) else: result = semGeneric(c, n, s, prev)
of nkIdent, nkDotExpr, nkAccQuoted: of nkIdent, nkDotExpr, nkAccQuoted:
var s = semTypeIdent(c, n) var s = semTypeIdent(c, n)
if s.typ == nil: GlobalError(n.info, errTypeExpected) if s.typ == nil:
if prev == nil: LocalError(n.info, errTypeExpected)
result = errorType(c)
elif prev == nil:
result = s.typ result = s.typ
else: else:
assignType(prev, s.typ) assignType(prev, s.typ)
prev.id = s.typ.id prev.id = s.typ.id
result = prev result = prev
of nkSym: of nkSym:
if n.sym.kind == skType and n.sym.typ != nil: if n.sym.kind == skType and n.sym.typ != nil:
var t = n.sym.typ var t = n.sym.typ
if prev == nil: if prev == nil:
@ -799,8 +840,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
assignType(prev, t) assignType(prev, t)
result = prev result = prev
markUsed(n, n.sym) markUsed(n, n.sym)
else: else:
GlobalError(n.info, errTypeExpected) LocalError(n.info, errTypeExpected)
result = errorType(c)
of nkObjectTy: result = semObjectNode(c, n, prev) of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev) of nkTupleTy: result = semTuple(c, n, prev)
of nkRefTy: result = semAnyRef(c, n, tyRef, 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 nkType: result = n.typ
of nkStmtListType: result = semStmtListType(c, n, prev) of nkStmtListType: result = semStmtListType(c, n, prev)
of nkBlockType: result = semBlockType(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) = proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
m.typ.kind = kind m.typ.kind = kind
@ -874,7 +918,7 @@ proc processMagicType(c: PContext, m: PSym) =
of mSeq: setMagicType(m, tySequence, 0) of mSeq: setMagicType(m, tySequence, 0)
of mOrdinal: setMagicType(m, tyOrdinal, 0) of mOrdinal: setMagicType(m, tyOrdinal, 0)
of mPNimrodNode: nil of mPNimrodNode: nil
else: GlobalError(m.info, errTypeExpected) else: LocalError(m.info, errTypeExpected)
proc semGenericConstraints(c: PContext, n: PNode, result: PType) = proc semGenericConstraints(c: PContext, n: PNode, result: PType) =
var x = semTypeNode(c, n, nil) 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 = proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
result = PType(idTableGet(cl.typeMap, t)) result = PType(idTableGet(cl.typeMap, t))
if result == nil: 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: elif result.kind == tyGenericParam:
InternalError(cl.info, "substitution with generic parameter") InternalError(cl.info, "substitution with generic parameter")

View file

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