better error handling for better idetools support
This commit is contained in:
parent
feaf6509bd
commit
b595fc8347
13 changed files with 378 additions and 268 deletions
|
|
@ -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 = ""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,11 @@ proc considerAcc*(n: PNode): PIdent =
|
||||||
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
|
||||||
oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice,
|
oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice,
|
||||||
|
|
@ -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)
|
||||||
|
result = errorSym(n.sons[1])
|
||||||
elif checkUndeclared in flags:
|
elif checkUndeclared in flags:
|
||||||
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])
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
# error correction:
|
||||||
|
result = newEmptyStrNode(n)
|
||||||
else:
|
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:
|
||||||
|
LocalError(n.info, errStringLiteralExpected)
|
||||||
|
# error correction:
|
||||||
|
result = newEmptyStrNode(n)
|
||||||
else:
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
result = fitNode(c, getSysType(tyBool), nn)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
GlobalError(n.info, errConstExprExpected)
|
LocalError(n.info, errConstExprExpected)
|
||||||
return
|
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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
LocalError(n.info, errXisNoMacroOrTemplate, s.name.s)
|
||||||
|
result = emptyNode
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errInvalidExpressionX,
|
LocalError(n.info, errInvalidExpressionX,
|
||||||
renderTree(a, {renderNoComments}))
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -163,17 +163,19 @@ 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})
|
||||||
|
|
@ -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:
|
||||||
|
LocalError(n.info, errWrongNumberOfVariables)
|
||||||
|
elif length-2 != sonsLen(iter):
|
||||||
|
LocalError(n.info, errWrongNumberOfVariables)
|
||||||
else:
|
else:
|
||||||
if length-2 != sonsLen(iter):
|
|
||||||
GlobalError(n.info, errWrongNumberOfVariables)
|
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
elif lengthOrd(base) > MaxSetElements:
|
||||||
|
LocalError(n.info, errSetTooBig)
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errXExpectsOneTypeParam, "set")
|
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,16 +138,17 @@ 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)
|
||||||
|
|
@ -146,9 +157,12 @@ 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:
|
||||||
|
LocalError(n.sons[0].info, errRangeExpected)
|
||||||
|
result = errorType(c)
|
||||||
else:
|
else:
|
||||||
GlobalError(n.info, errXExpectsOneTypeParam, "range")
|
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
|
||||||
|
|
@ -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,9 +449,12 @@ 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)
|
||||||
|
else:
|
||||||
|
typ = semTypeNode(c, n.sons[length-2], nil)
|
||||||
for i in countup(0, sonsLen(n)-3):
|
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
|
||||||
|
|
@ -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,8 +822,10 @@ 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)
|
||||||
|
|
@ -800,7 +841,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -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
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue