non-nil AST; continue after errors for IDE support

This commit is contained in:
Araq
2011-02-12 19:24:20 +01:00
parent 27dc54cbda
commit 5b28d08203
84 changed files with 678 additions and 722 deletions

0
.gitignore vendored Normal file → Executable file
View File

View File

@@ -43,10 +43,8 @@ To specify the AST for the different Nimrod constructs, the notation
``nodekind(son1, son2, ...)`` or ``nodekind(value)`` or
``nodekind(field=value)`` is used.
Some child may be missing. Then it is ``nil``. A nil child is equivalent to
a node of kind ``nnkEmpty``. This is more or less a (useful) artifact from
the implementation. (In the compiler's implementation ``nil`` is of course
not the same as ``nnkEmpty``!)
Some child may be missing. A missing child is a node of kind ``nnkEmpty``;
a child can never be nil.
Leaf nodes/Atoms
@@ -364,7 +362,7 @@ When statement
--------------
Like the ``if`` statement, but the root has the kind ``nnkWhenStmt``.
Assignment
----------

0
doc/lib.txt Normal file → Executable file
View File

0
examples/httpserver2.nim Normal file → Executable file
View File

0
icons/koch.rc Normal file → Executable file
View File

0
icons/koch.res Normal file → Executable file
View File

0
icons/nimrod.rc Normal file → Executable file
View File

0
icons/nimrod.res Normal file → Executable file
View File

0
koch.nim Normal file → Executable file
View File

0
lib/core/marshal.nim Normal file → Executable file
View File

0
lib/core/threads.nim Normal file → Executable file
View File

0
lib/impure/ssl.nim Normal file → Executable file
View File

0
lib/pure/base64.nim Normal file → Executable file
View File

0
lib/pure/cookies.nim Normal file → Executable file
View File

View File

@@ -185,11 +185,12 @@ when not defined(ECMAScript):
proc random(max: int): int = return int(rand()) mod max
proc trunc*(x: float): float {.importc: "trunc", nodecl.}
proc floor*(x: float): float {.importc: "floor", nodecl.}
else:
proc mathrandom(): float {.importc: "Math.random", nodecl.}
proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.}
proc random*(max: int): int = return mathfloor(mathrandom() * max)
proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
proc random*(max: int): int = return floor(mathrandom() * max)
proc randomize*() = nil
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
@@ -208,7 +209,7 @@ else:
elif x < 0.0:
result = -frexp(-x, exponent)
else:
var ex = mathfloor(log2(x))
var ex = floor(log2(x))
exponent = round(ex)
result = x / pow(2.0, ex)
@@ -227,7 +228,6 @@ else:
var y = exp(2.0*x)
return (y-1.0)/(y+1.0)
type
TRunningStat* = object ## an accumulator for statistical data
n*: int ## number of pushed data

0
lib/pure/scgi.nim Normal file → Executable file
View File

0
lib/pure/smtp.nim Normal file → Executable file
View File

0
lib/wrappers/claro.nim Normal file → Executable file
View File

0
lib/wrappers/openssl.nim Normal file → Executable file
View File

0
lib/wrappers/pcre.nim Normal file → Executable file
View File

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -44,9 +44,8 @@ proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObje
# ----------------------- str table -----------------------------------------
proc StrTableContains*(t: TStrTable, n: PSym): bool
proc StrTableAdd*(t: var TStrTable, n: PSym)
proc StrTableGet*(t: TStrTable, name: PIdent): PSym
proc StrTableIncl*(t: var TStrTable, n: PSym): bool
# returns true if n is already in the string table
proc StrTableGet*(t: TStrTable, name: PIdent): PSym
# the iterator scheme:
type
TTabIter*{.final.} = object # consider all fields here private
@@ -574,8 +573,10 @@ proc StrTableAdd(t: var TStrTable, n: PSym) =
StrTableRawInsert(t.data, n)
inc(t.counter)
proc StrTableIncl(t: var TStrTable, n: PSym): bool =
proc StrTableIncl*(t: var TStrTable, n: PSym): bool =
# returns true if n is already in the string table:
# It is essential that `n` is written nevertheless!
# This way the newest redefinition is picked by the semantic analyses!
var
h: THash
it: PSym
@@ -584,6 +585,7 @@ proc StrTableIncl(t: var TStrTable, n: PSym): bool =
it = t.data[h]
if it == nil: break
if it.name.id == n.name.id:
t.data[h] = n # overwrite it with newer definition!
return true # found it
h = nextTry(h, high(t.data))
if mustRehash(len(t.data), t.counter):
@@ -661,10 +663,9 @@ proc SymTabAdd(tab: var TSymTab, e: PSym) =
StrTableAdd(tab.stack[tab.tos - 1], e)
proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult =
if StrTableGet(tab.stack[at], e.name) != nil:
if StrTableIncl(tab.stack[at], e):
result = Failure
else:
StrTableAdd(tab.stack[at], e)
result = Success
proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult =

View File

@@ -130,11 +130,11 @@ proc getLineInfo*(L: TLexer): TLineInfo =
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
msgs.liMessage(getLineInfo(L), msg, arg)
msgs.GenericMessage(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
msgs.liMessage(info, msg, arg)
msgs.GenericMessage(info, msg, arg)
proc TokKindToStr*(k: TTokKind): string =
case k

View File

@@ -1439,7 +1439,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mEcho: genEcho(p, e)
of mArrToSeq: genArrToSeq(p, e, d)
of mNLen..mNError:
liMessage(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s)
localError(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s)
else: internalError(e.info, "genMagicExpr: " & $op)
proc genConstExpr(p: BProc, n: PNode): PRope
@@ -1605,7 +1605,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
var sym = e.sym
case sym.Kind
of skMethod:
if sym.ast.sons[codePos] == nil:
if sym.ast.sons[codePos].kind == nkEmpty:
# we cannot produce code for the dispatcher yet:
fillProcLoc(sym)
genProcPrototype(p.module, sym)

View File

@@ -56,22 +56,19 @@ proc genVarTuple(p: BProc, n: PNode) =
genObjectInit(p, v.typ, v.loc, true)
proc genVarStmt(p: BProc, n: PNode) =
var
v: PSym
a: PNode
for i in countup(0, sonsLen(n) - 1):
a = n.sons[i]
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if a.kind == nkIdentDefs:
assert(a.sons[0].kind == nkSym)
v = a.sons[0].sym
var v = a.sons[0].sym
if sfGlobal in v.flags:
assignGlobalVar(p, v)
else:
assignLocalVar(p, v)
initVariable(p, v) # XXX: this is not required if a.sons[2] != nil,
# unless it is a GC'ed pointer
if a.sons[2] != nil:
if a.sons[2].kind != nkEmpty:
genLineDir(p, a)
expr(p, a.sons[2], v.loc)
genObjectInit(p, v.typ, v.loc, true) # correct position
@@ -79,13 +76,11 @@ proc genVarStmt(p: BProc, n: PNode) =
genVarTuple(p, a)
proc genConstStmt(p: BProc, t: PNode) =
var c: PSym
for i in countup(0, sonsLen(t) - 1):
if t.sons[i].kind == nkCommentStmt: continue
if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt")
c = t.sons[i].sons[0].sym # This can happen for forward consts:
if (c.ast != nil) and (c.typ.kind in ConstantDataTypes) and
not (lfNoDecl in c.loc.flags):
var c = t.sons[i].sons[0].sym
if c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags):
# generate the data:
fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
if sfImportc in c.flags:
@@ -134,7 +129,7 @@ proc genIfStmt(p: BProc, n: PNode) =
proc popSafePoints(p: BProc, howMany: int) =
var L = p.nestedTryStmts.len
# danger of endless recursion! we workaround this here, by a temp stack
# danger of endless recursion! we workaround this here by a temp stack
var stack: seq[PNode]
newSeq(stack, howMany)
for i in countup(1, howMany):
@@ -154,7 +149,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
p.beforeRetNeeded = true
popSafePoints(p, min(1, p.nestedTryStmts.len))
genLineDir(p, t)
if (t.sons[0] != nil): genStmts(p, t.sons[0])
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
proc genWhileStmt(p: BProc, t: PNode) =
@@ -185,7 +180,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
proc genBlock(p: BProc, t: PNode, d: var TLoc) =
inc(p.labels)
var idx = len(p.blocks)
if t.sons[0] != nil:
if t.sons[0].kind != nkEmpty:
# named block?
assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym
@@ -202,7 +197,7 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
proc genBreakStmt(p: BProc, t: PNode) =
var idx = len(p.blocks) - 1
if t.sons[0] != nil:
if t.sons[0].kind != nkEmpty:
# named break?
assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym
@@ -220,7 +215,7 @@ proc getRaiseFrmt(p: BProc): string =
result = "#raiseException((#E_Base*)$1, $2);$n"
proc genRaiseStmt(p: BProc, t: PNode) =
if t.sons[0] != nil:
if t.sons[0].kind != nkEmpty:
var a: TLoc
InitLocExpr(p, t.sons[0], a)
var e = rdLoc(a)
@@ -668,8 +663,6 @@ proc genStmts(p: BProc, t: PNode) =
var
a: TLoc
prc: PSym
#assert(t <> nil);
if inCheckpoint(t.info): MessageOut(renderTree(t))
case t.kind
of nkEmpty:
nil
@@ -707,7 +700,7 @@ proc genStmts(p: BProc, t: PNode) =
nil
of nkPragma: genPragma(p, t)
of nkProcDef, nkMethodDef, nkConverterDef:
if (t.sons[genericParamsPos] == nil):
if (t.sons[genericParamsPos].kind == nkEmpty):
prc = t.sons[namePos].sym
if (optDeadCodeElim notin gGlobalOptions and
sfDeadCodeElim notin getModule(prc).flags) or
@@ -715,7 +708,7 @@ proc genStmts(p: BProc, t: PNode) =
(sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
(prc.kind == skMethod):
# we have not only the header:
if (t.sons[codePos] != nil) or (lfDynamicLib in prc.loc.flags):
if (t.sons[codePos].kind != nkEmpty) or (lfDynamicLib in prc.loc.flags):
genProc(p.module, prc)
else: internalError(t.info, "genStmts(" & $t.kind & ')')

View File

@@ -890,12 +890,12 @@ proc myOpen(module: PSym, filename: string): PPassContext =
proc myOpenCached(module: PSym, filename: string,
rd: PRodReader): PPassContext =
if gNimDat == nil:
registerTypeInfoModule()
#MessageOut('cgen.myOpenCached has been called ' + filename);
registerTypeInfoModule()
#MessageOut('cgen.myOpenCached has been called ' + filename)
var cfile = changeFileExt(completeCFilePath(filename), cExt)
var cfilenoext = changeFileExt(cfile, "")
addFileToLink(cfilenoext)
registerModuleToMain(module)
registerModuleToMain(module)
# XXX: this cannot be right here, initalization has to be appended during
# the ``myClose`` call
result = nil
@@ -911,7 +911,7 @@ proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool =
proc myProcess(b: PPassContext, n: PNode): PNode =
result = n
if b == nil: return
if b == nil or passes.skipCodegen(n): return
var m = BModule(b)
m.initProc.options = gOptions
genStmts(m.initProc, n)
@@ -951,7 +951,7 @@ proc writeModule(m: BModule) =
proc myClose(b: PPassContext, n: PNode): PNode =
result = n
if b == nil: return
if b == nil or passes.skipCodegen(n): return
var m = BModule(b)
if n != nil:
m.initProc.options = gOptions

View File

@@ -1,22 +1,17 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This module implements code generation for multi methods.
## This module implements code generation for multi methods.
import
options, ast, astalgo, msgs, idents, rnimsyn, types, magicsys
proc methodDef*(s: PSym)
proc methodCall*(n: PNode): PNode
proc generateMethodDispatchers*(): PNode
# implementation
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
var
dest, source: PType
@@ -40,7 +35,7 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
else:
result = n
proc methodCall(n: PNode): PNode =
proc methodCall*(n: PNode): PNode =
var disp: PSym
result = n
disp = lastSon(result.sons[0].sym.ast).sym
@@ -76,7 +71,7 @@ proc sameMethodBucket(a, b: PSym): bool =
return
result = true
proc methodDef(s: PSym) =
proc methodDef*(s: PSym) =
var
L, q: int
disp: PSym
@@ -86,12 +81,12 @@ proc methodDef(s: PSym) =
add(gMethods[i], s) # store a symbol to the dispatcher:
addSon(s.ast, lastSon(gMethods[i][0].ast))
return
add(gMethods, @ [s]) # create a new dispatcher:
add(gMethods, @[s]) # create a new dispatcher:
disp = copySym(s)
disp.typ = copyType(disp.typ, disp.typ.owner, false)
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
disp.ast = copyTree(s.ast)
disp.ast.sons[codePos] = nil
disp.ast.sons[codePos] = ast.emptyNode
if s.typ.sons[0] != nil:
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
addSon(s.ast, newSymNode(disp))
@@ -188,7 +183,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
addSon(disp, a)
result.ast.sons[codePos] = disp
proc generateMethodDispatchers(): PNode =
proc generateMethodDispatchers*(): PNode =
var relevantCols: TIntSet
result = newNode(nkStmtList)
for bucket in countup(0, len(gMethods) - 1):

View File

@@ -152,7 +152,7 @@ proc writeCommandLineUsage() =
helpWritten = true
proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) =
liMessage(info, errInvalidCmdLineOption, switch)
LocalError(info, errInvalidCmdLineOption, switch)
proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
info: TLineInfo) =
@@ -174,20 +174,20 @@ proc ProcessOnOffSwitch(op: TOptions, arg: string, pass: TCmdlinePass,
case whichKeyword(arg)
of wOn: gOptions = gOptions + op
of wOff: gOptions = gOptions - op
else: liMessage(info, errOnOrOffExpectedButXFound, arg)
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass,
info: TLineInfo) =
case whichKeyword(arg)
of wOn: gGlobalOptions = gGlobalOptions + op
of wOff: gGlobalOptions = gGlobalOptions - op
else: liMessage(info, errOnOrOffExpectedButXFound, arg)
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
if arg == "": liMessage(info, errCmdLineArgExpected, switch)
if arg == "": LocalError(info, errCmdLineArgExpected, switch)
proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
if arg != "": liMessage(info, errCmdLineNoArgExpected, switch)
if arg != "": LocalError(info, errCmdLineNoArgExpected, switch)
proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
info: TLineInfo) =
@@ -212,7 +212,7 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
case whichKeyword(copy(arg, i))
of wOn: incl(gNotes, n)
of wOff: excl(gNotes, n)
else: liMessage(info, errOnOrOffExpectedButXFound, arg)
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
proc processCompile(filename: string) =
var found = findFile(filename)
@@ -228,13 +228,13 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
of wBoehm: result = contains(gGlobalOptions, optBoehmGC)
of wRefc: result = contains(gGlobalOptions, optRefcGC)
of wNone: result = gGlobalOptions * {optBoehmGC, optRefcGC} == {}
else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
of wOpt:
case whichKeyword(arg)
of wSpeed: result = contains(gOptions, optOptimizeSpeed)
of wSize: result = contains(gOptions, optOptimizeSize)
of wNone: result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {}
else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
else: InvalidCmdLineOption(passCmd1, switch, info)
proc testCompileOption*(switch: string, info: TLineInfo): bool =
@@ -285,7 +285,7 @@ proc addPathRec(dir: string, info: TLineInfo) =
if k == pcDir and p[pos] != '.':
addPathRec(p, info)
if not contains(options.searchPaths, p):
liMessage(info, hintPath, p)
Message(info, hintPath, p)
lists.PrependStr(options.searchPaths, p)
proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
@@ -346,7 +346,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
excl(gGlobalOptions, optRefcGC)
excl(gGlobalOptions, optBoehmGC)
defineSymbol("nogc")
else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
of wWarnings, wW: ProcessOnOffSwitch({optWarns}, arg, pass, info)
of wWarning: ProcessSpecificNote(arg, wWarning, pass, info)
of wHint: ProcessSpecificNote(arg, wHint, pass, info)
@@ -388,7 +388,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
of wNone:
excl(gOptions, optOptimizeSpeed)
excl(gOptions, optOptimizeSize)
else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
of wApp:
expectArg(switch, arg, pass, info)
case whichKeyword(arg)
@@ -401,7 +401,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
incl(gGlobalOptions, optGenDynLib)
excl(gGlobalOptions, optGenGuiApp)
defineSymbol("library")
else: liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)
else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
of wListDef:
expectNoArg(switch, arg, pass, info)
if pass in {passCmd2, passPP}: condsyms.listSymbols()
@@ -427,8 +427,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
expectArg(switch, arg, pass, info)
if (pass == passCmd1):
theOS = platform.NameToOS(arg)
if theOS == osNone: liMessage(info, errUnknownOS, arg)
if theOS != platform.hostOS:
if theOS == osNone: LocalError(info, errUnknownOS, arg)
elif theOS != platform.hostOS:
setTarget(theOS, targetCPU)
incl(gGlobalOptions, optCompileOnly)
condsyms.InitDefines()
@@ -436,8 +436,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
expectArg(switch, arg, pass, info)
if (pass == passCmd1):
cpu = platform.NameToCPU(arg)
if cpu == cpuNone: liMessage(info, errUnknownCPU, arg)
if cpu != platform.hostCPU:
if cpu == cpuNone: LocalError(info, errUnknownCPU, arg)
elif cpu != platform.hostCPU:
setTarget(targetOS, cpu)
incl(gGlobalOptions, optCompileOnly)
condsyms.InitDefines()

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -547,7 +547,7 @@ proc genRaiseStmt(p: var TProc, n: PNode, r: var TCompRes) =
a: TCompRes
typ: PType
genLineDir(p, n, r)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
gen(p, n.sons[0], a)
if a.com != nil: appf(r.com, "$1;$n", [a.com])
typ = skipTypes(n.sons[0].typ, abstractPtrs)
@@ -610,7 +610,7 @@ proc genBlock(p: var TProc, n: PNode, r: var TCompRes) =
sym: PSym
inc(p.unique)
idx = len(p.blocks)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
# named block?
if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock")
sym = n.sons[0].sym
@@ -633,7 +633,7 @@ proc genBreakStmt(p: var TProc, n: PNode, r: var TCompRes) =
sym: PSym
genLineDir(p, n, r)
idx = len(p.blocks) - 1
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
# named break?
assert(n.sons[0].kind == nkSym)
sym = n.sons[0].sym
@@ -991,7 +991,7 @@ proc genVarInit(p: var TProc, v: PSym, n: PNode, r: var TCompRes) =
var
a: TCompRes
s: PRope
if n == nil:
if n.kind == nkEmpty:
appf(r.com, "var $1 = $2;$n",
[mangleName(v), createVar(p, v.typ, isIndirect(v))])
else:
@@ -1135,7 +1135,7 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
of mExcl: binaryStmt(p, n, r, "", "delete $1[$2]")
of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
of mNLen..mNError:
liMessage(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
localError(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
of mEcho: genEcho(p, n, r)
else:
@@ -1231,7 +1231,7 @@ proc genReturnStmt(p: var TProc, n: PNode, r: var TCompRes) =
var a: TCompRes
if p.procDef == nil: InternalError(n.info, "genReturnStmt")
p.BeforeRetNeeded = true
if (n.sons[0] != nil):
if (n.sons[0].kind != nkEmpty):
genStmt(p, n.sons[0], a)
if a.com != nil: appf(r.com, "$1;$n", mergeStmt(a))
else:
@@ -1297,7 +1297,7 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
r.com = nil
r.res = nil
case n.kind
of nkNilLit: nil
of nkNilLit, nkEmpty: nil
of nkStmtList:
for i in countup(0, sonsLen(n) - 1):
genStmt(p, n.sons[i], a)
@@ -1324,9 +1324,9 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma:
nil
of nkProcDef, nkMethodDef, nkConverterDef:
if (n.sons[genericParamsPos] == nil):
if (n.sons[genericParamsPos].kind == nkEmpty):
var prc = n.sons[namePos].sym
if (n.sons[codePos] != nil) and not (lfNoDecl in prc.loc.flags):
if (n.sons[codePos].kind != nkEmpty) and not (lfNoDecl in prc.loc.flags):
genProc(p, n, r)
else:
discard mangleName(prc)
@@ -1391,6 +1391,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
of nkCStringToString: convCStrToStr(p, n, r)
of nkPassAsOpenArray: gen(p, n.sons[0], r)
of nkStmtListExpr: genStmtListExpr(p, n, r)
of nkEmpty: nil
else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
var globals: PGlobals
@@ -1416,6 +1417,7 @@ proc genModule(p: var TProc, n: PNode, r: var TCompRes) =
makeCString(toFilename(p.module.module.info)), r.com])
proc myProcess(b: PPassContext, n: PNode): PNode =
if passes.skipCodegen(n): return n
var
p: TProc
r: TCompRes
@@ -1428,6 +1430,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
app(p.globals.code, mergeStmt(r))
proc myClose(b: PPassContext, n: PNode): PNode =
if passes.skipCodegen(n): return n
result = myProcess(b, n)
var m = BModule(b)
if sfMainModule in m.module.flags:

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -84,7 +84,7 @@ proc stackTraceAux(x: PStackFrame) =
proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") =
messageOut("stack trace: (most recent call last)")
stackTraceAux(c.tos)
liMessage(n.info, msg, arg)
Fatal(n.info, msg, arg)
proc isSpecial(n: PNode): bool =
result = (n.kind == nkExceptBranch)
@@ -414,7 +414,7 @@ proc evalEcho(c: PEvalContext, n: PNode): PNode =
proc evalExit(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {})
if isSpecial(result): return
liMessage(n.info, hintQuitCalled)
Message(n.info, hintQuitCalled)
quit(int(getOrdValue(result)))
proc evalOr(c: PEvalContext, n: PNode): PNode =
@@ -915,12 +915,12 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of mNHint:
result = evalAux(c, n.sons[1], {})
if isSpecial(result): return
liMessage(n.info, hintUser, getStrValue(result))
Message(n.info, hintUser, getStrValue(result))
result = emptyNode
of mNWarning:
result = evalAux(c, n.sons[1], {})
if isSpecial(result): return
liMessage(n.info, warnUser, getStrValue(result))
Message(n.info, warnUser, getStrValue(result))
result = emptyNode
of mNError:
result = evalAux(c, n.sons[1], {})

0
rod/extccomp.nim Normal file → Executable file
View File

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -9,7 +9,7 @@
# This module implements Nimrod's simple filters and helpers for filters.
import
import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, rnimsyn
proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
@@ -21,7 +21,7 @@ proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool
# implementation
proc invalidPragma(n: PNode) =
liMessage(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
LocalError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
proc getArg(n: PNode, name: string, pos: int): PNode =
result = nil

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -22,7 +22,7 @@ proc getModuleFile*(n: PNode): string
proc findModule(info: TLineInfo, modulename: string): string =
# returns path to module
result = options.FindFile(AddFileExt(modulename, nimExt))
if result == "": liMessage(info, errCannotOpenFile, modulename)
if result == "": Fatal(info, errCannotOpenFile, modulename)
proc getModuleFile(n: PNode): string =
case n.kind
@@ -73,7 +73,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
proc importSymbol(c: PContext, ident: PNode, fromMod: PSym) =
if (ident.kind != nkIdent): InternalError(ident.info, "importSymbol")
var s = StrTableGet(fromMod.tab, ident.ident)
if s == nil: liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s)
if s == nil: GlobalError(ident.info, errUndeclaredIdentifier, ident.ident.s)
if s.kind == skStub: loadStub(s)
if not (s.Kind in ExportableSymKinds):
InternalError(ident.info, "importSymbol: 2")
@@ -106,7 +106,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
var f = getModuleFile(n.sons[i])
var m = gImportModule(f)
if sfDeprecated in m.flags:
liMessage(n.sons[i].info, warnDeprecated, m.name.s)
Message(n.sons[i].info, warnDeprecated, m.name.s)
# ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m) # add symbol to symbol table of module
importAllSymbols(c, m)

View File

@@ -35,24 +35,24 @@ proc CloseScope*(tab: var TSymTab) =
s = InitTabIter(it, tab.stack[tab.tos - 1])
while s != nil:
if sfForward in s.flags:
liMessage(s.info, errImplOfXexpected, getSymRepr(s))
LocalError(s.info, errImplOfXexpected, getSymRepr(s))
elif ({sfUsed, sfInInterface} * s.flags == {}) and
(optHints in s.options): # BUGFIX: check options in s!
if not (s.kind in {skForVar, skParam, skMethod, skUnknown}):
liMessage(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
s = NextIter(it, tab.stack[tab.tos - 1])
astalgo.rawCloseScope(tab)
proc AddSym*(t: var TStrTable, n: PSym) =
if StrTableIncl(t, n): liMessage(n.info, errAttemptToRedefine, n.name.s)
if StrTableIncl(t, n): LocalError(n.info, errAttemptToRedefine, n.name.s)
proc addDecl*(c: PContext, sym: PSym) =
if SymTabAddUnique(c.tab, sym) == Failure:
liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
proc addDeclAt*(c: PContext, sym: PSym, at: Natural) =
if SymTabAddUniqueAt(c.tab, sym, at) == Failure:
liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
if (sfInInterface in sym.flags):
@@ -66,12 +66,13 @@ proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
AddInterfaceDeclAux(c, sym)
proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural) =
if not (fn.kind in OverloadableSyms):
if fn.kind notin OverloadableSyms:
InternalError(fn.info, "addOverloadableSymAt")
var check = StrTableGet(c.tab.stack[at], fn.name)
if (check != nil) and not (check.Kind in OverloadableSyms):
liMessage(fn.info, errAttemptToRedefine, fn.Name.s)
SymTabAddAt(c.tab, fn, at)
if check != nil and check.Kind notin OverloadableSyms:
LocalError(fn.info, errAttemptToRedefine, fn.Name.s)
else:
SymTabAddAt(c.tab, fn, at)
proc addInterfaceDecl*(c: PContext, sym: PSym) =
# it adds the symbol to the interface if appropriate
@@ -89,17 +90,13 @@ proc lookUp*(c: PContext, n: PNode): PSym =
of nkAccQuoted:
result = lookup(c, n.sons[0])
of nkSym:
#
# result := SymtabGet(c.Tab, n.sym.name);
# if result = nil then
# liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s);
result = n.sym
of nkIdent:
result = SymtabGet(c.Tab, n.ident)
if result == nil: liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
else: InternalError(n.info, "lookUp")
if IntSetContains(c.AmbiguousSymbols, result.id):
liMessage(n.info, errUseQualifier, result.name.s)
LocalError(n.info, errUseQualifier, result.name.s)
if result.kind == skStub: loadStub(result)
type
@@ -111,20 +108,15 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
of nkIdent:
result = SymtabGet(c.Tab, n.ident)
if result == nil and checkUndeclared in flags:
liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
elif checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols,
result.id):
liMessage(n.info, errUseQualifier, n.ident.s)
GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
elif checkAmbiguity in flags and result != nil and
IntSetContains(c.AmbiguousSymbols, result.id):
LocalError(n.info, errUseQualifier, n.ident.s)
of nkSym:
#
# result = SymtabGet(c.Tab, n.sym.name)
# if result == nil:
# liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
# else
result = n.sym
if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols,
result.id):
liMessage(n.info, errUseQualifier, n.sym.name.s)
LocalError(n.info, errUseQualifier, n.sym.name.s)
of nkDotExpr:
result = nil
var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
@@ -141,9 +133,10 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
else:
result = StrTableGet(m.tab, ident)
if result == nil and checkUndeclared in flags:
liMessage(n.sons[1].info, errUndeclaredIdentifier, ident.s)
GlobalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
elif checkUndeclared in flags:
liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
GlobalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1]))
of nkAccQuoted:
result = QualifiedLookup(c, n.sons[0], flags)
else:
@@ -151,7 +144,6 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
if (result != nil) and (result.kind == skStub): loadStub(result)
proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
var ident: PIdent
result = nil
case n.kind
of nkIdent:
@@ -163,18 +155,12 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident)
of nkSym:
result = n.sym
o.mode = oimDone
# o.stackPtr = c.tab.tos
# o.mode = oimNoQualifier
# while result == nil:
# dec(o.stackPtr)
# if o.stackPtr < 0: break
# result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name)
o.mode = oimDone
of nkDotExpr:
o.mode = oimOtherModule
o.m = qualifiedLookUp(c, n.sons[0])
if (o.m != nil) and (o.m.kind == skModule):
ident = nil
var ident: PIdent = nil
if (n.sons[1].kind == nkIdent):
ident = n.sons[1].ident
elif (n.sons[1].kind == nkAccQuoted) and
@@ -188,7 +174,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else:
result = InitIdentIter(o.it, o.m.tab, ident)
else:
liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
GlobalError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1]))
of nkAccQuoted:
result = InitOverloadIter(o, c, n.sons[0])
of nkSymChoice:

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -73,7 +73,7 @@ proc importModule(filename: string): PSym =
# compile the module
result = compileModule(filename, false, false)
elif sfSystemModule in result.flags:
liMessage(result.info, errAttemptToRedefine, result.Name.s)
LocalError(result.info, errAttemptToRedefine, result.Name.s)
proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym =
var rd: PRodReader = nil
@@ -177,7 +177,7 @@ proc CommandScan(filename: string) =
proc WantFile(filename: string) =
if filename == "":
liMessage(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
proc MainCommand(cmd, filename: string) =
appendStr(searchPaths, options.libpath)

View File

@@ -343,7 +343,6 @@ const
"RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported",
"CommentXIgnored", "XisPassedToProcVar", "User"]
const
HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
@@ -371,19 +370,20 @@ type
# only 8 bytes.
line*, col*: int16
fileIndex*: int32
ERecoverableError* = object of EInvalidValue
proc UnknownLineInfo*(): TLineInfo
var
var
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)}
gErrorCounter*: int = 0 # counts the number of errors
gHintCounter*: int = 0
gWarnCounter*: int = 0
gErrorMax*: int = 1 # stop after gErrorMax errors
const # this format is understood by many text editors: it is the same that
# Borland and Freepascal use
# this format is understood by many text editors: it is the same that
# Borland and Freepascal use
const
PosErrorFormat* = "$1($2, $3) Error: $4"
PosWarningFormat* = "$1($2, $3) Warning: $4"
PosHintFormat* = "$1($2, $3) Hint: $4"
@@ -391,47 +391,22 @@ const # this format is understood by many text editors: it is the same that
RawWarningFormat* = "Warning: $1"
RawHintFormat* = "Hint: $1"
proc MessageOut*(s: string)
proc rawMessage*(msg: TMsgKind, arg: string)
proc rawMessage*(msg: TMsgKind, args: openarray[string])
proc liMessage*(info: TLineInfo, msg: TMsgKind, arg: string = "")
proc InternalError*(info: TLineInfo, errMsg: string)
proc InternalError*(errMsg: string)
proc newLineInfo*(filename: string, line, col: int): TLineInfo
proc ToFilename*(info: TLineInfo): string
proc toColumn*(info: TLineInfo): int
proc ToLinenumber*(info: TLineInfo): int
proc MsgKindToString*(kind: TMsgKind): string
# checkpoints are used for debugging:
proc checkpoint*(info: TLineInfo, filename: string, line: int): bool
proc addCheckpoint*(info: TLineInfo)
proc addCheckpoint*(filename: string, line: int)
proc inCheckpoint*(current: TLineInfo): bool
# prints the line information if in checkpoint
proc pushInfoContext*(info: TLineInfo)
proc popInfoContext*()
proc includeFilename*(f: string): int
# implementation
proc UnknownLineInfo(): TLineInfo =
result.line = int16(- 1)
result.col = int16(- 1)
result.fileIndex = - 1
proc UnknownLineInfo*(): TLineInfo =
result.line = int16(-1)
result.col = int16(-1)
result.fileIndex = -1
var
filenames: seq[string] = @ []
msgContext: seq[TLineInfo] = @ []
proc pushInfoContext(info: TLineInfo) =
var length: int
length = len(msgContext)
setlen(msgContext, length + 1)
msgContext[length] = info
proc popInfoContext() =
proc pushInfoContext*(info: TLineInfo) =
msgContext.add(info)
proc popInfoContext*() =
setlen(msgContext, len(msgContext) - 1)
proc includeFilename(f: string): int =
proc includeFilename*(f: string): int =
for i in countdown(high(filenames), low(filenames)):
if filenames[i] == f:
return i
@@ -439,53 +414,51 @@ proc includeFilename(f: string): int =
setlen(filenames, result + 1)
filenames[result] = f
proc checkpoint(info: TLineInfo, filename: string, line: int): bool =
proc newLineInfo*(filename: string, line, col: int): TLineInfo =
result.fileIndex = includeFilename(filename)
result.line = int16(line)
result.col = int16(col)
proc ToFilename*(info: TLineInfo): string =
if info.fileIndex == - 1: result = "???"
else: result = filenames[info.fileIndex]
proc ToLinenumber*(info: TLineInfo): int =
result = info.line
proc toColumn*(info: TLineInfo): int =
result = info.col
proc checkpoint*(info: TLineInfo, filename: string, line: int): bool =
result = (int(info.line) == line) and
(ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
filename)
var checkPoints: seq[TLineInfo] = @[]
proc addCheckpoint(info: TLineInfo) =
var length: int
length = len(checkPoints)
setlen(checkPoints, length + 1)
checkPoints[length] = info
proc addCheckpoint*(info: TLineInfo) =
checkPoints.add(info)
proc addCheckpoint(filename: string, line: int) =
proc addCheckpoint*(filename: string, line: int) =
addCheckpoint(newLineInfo(filename, line, - 1))
proc newLineInfo(filename: string, line, col: int): TLineInfo =
result.fileIndex = includeFilename(filename)
result.line = int16(line)
result.col = int16(col)
proc ToFilename(info: TLineInfo): string =
if info.fileIndex == - 1: result = "???"
else: result = filenames[info.fileIndex]
proc ToLinenumber(info: TLineInfo): int =
result = info.line
proc toColumn(info: TLineInfo): int =
result = info.col
proc MessageOut(s: string) =
proc MessageOut*(s: string) =
# change only this proc to put it elsewhere
Writeln(stdout, s)
proc coordToStr(coord: int): string =
if coord == - 1: result = "???"
else: result = $(coord)
if coord == -1: result = "???"
else: result = $coord
proc MsgKindToString(kind: TMsgKind): string =
proc MsgKindToString*(kind: TMsgKind): string =
# later versions may provide translated error messages
result = msgKindToStr[kind]
proc getMessageStr(msg: TMsgKind, arg: string): string =
result = `%`(msgKindToString(msg), [arg])
proc inCheckpoint(current: TLineInfo): bool =
proc inCheckpoint*(current: TLineInfo): bool =
## prints the line information if in checkpoint
result = false
if not (optCheckpoints in gOptions):
return # ignore all checkpoints
@@ -496,7 +469,10 @@ proc inCheckpoint(current: TLineInfo): bool =
coordToStr(current.line), coordToStr(current.col)]))
return true
proc handleError(msg: TMsgKind) =
type
TErrorHandling = enum doNothing, doAbort, doRaise
proc handleError(msg: TMsgKind, eh: TErrorHandling) =
if msg == errInternal:
assert(false) # we want a stack trace here
if (msg >= fatalMin) and (msg <= fatalMax):
@@ -504,9 +480,12 @@ proc handleError(msg: TMsgKind) =
quit(1)
if (msg >= errMin) and (msg <= errMax):
inc(gErrorCounter)
if gErrorCounter >= gErrorMax:
options.gExitcode = 1'i8
if gErrorCounter >= gErrorMax or eh == doAbort:
if gVerbosity >= 3: assert(false)
quit(1) # one error stops the compiler
elif eh == doRaise:
raise newException(ERecoverableError, "")
proc sameLineInfo(a, b: TLineInfo): bool =
result = (a.line == b.line) and (a.fileIndex == b.fileIndex)
@@ -523,7 +502,7 @@ proc writeContext(lastinfo: TLineInfo) =
getMessageStr(errInstantiationFrom, "")]))
info = msgContext[i]
proc rawMessage(msg: TMsgKind, args: openarray[string]) =
proc rawMessage*(msg: TMsgKind, args: openarray[string]) =
var frmt: string
case msg
of errMin..errMax:
@@ -542,12 +521,13 @@ proc rawMessage(msg: TMsgKind, args: openarray[string]) =
else:
assert(false) # cannot happen
MessageOut(`%`(frmt, `%`(msgKindToString(msg), args)))
handleError(msg)
handleError(msg, doAbort)
proc rawMessage(msg: TMsgKind, arg: string) =
proc rawMessage*(msg: TMsgKind, arg: string) =
rawMessage(msg, [arg])
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string = "") =
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
eh: TErrorHandling) =
var frmt: string
case msg
of errMin..errMax:
@@ -567,12 +547,29 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string = "") =
assert(false) # cannot happen
MessageOut(`%`(frmt, [toFilename(info), coordToStr(info.line),
coordToStr(info.col), getMessageStr(msg, arg)]))
handleError(msg)
handleError(msg, doAbort)
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doAbort)
proc InternalError(info: TLineInfo, errMsg: string) =
proc GlobalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doRaise)
proc LocalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doNothing)
proc Message*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doNothing)
proc GenericMessage*(info: TLineInfo, msg: TMsgKind, arg = "") =
## does the right thing for old code that is written with "abort on first
## error" in mind.
liMessage(info, msg, arg, doAbort)
proc InternalError*(info: TLineInfo, errMsg: string) =
writeContext(info)
liMessage(info, errInternal, errMsg)
liMessage(info, errInternal, errMsg, doAbort)
proc InternalError(errMsg: string) =
proc InternalError*(errMsg: string) =
writeContext(UnknownLineInfo())
rawMessage(errInternal, errMsg)

0
rod/nimrod.ini Normal file → Executable file
View File

0
rod/nimrod.nim Normal file → Executable file
View File

View File

@@ -109,11 +109,11 @@ proc getLineInfo*(L: TLexer): TLineInfo =
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
msgs.liMessage(getLineInfo(L), msg, arg)
msgs.GenericMessage(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
msgs.liMessage(info, msg, arg)
msgs.GenericMessage(info, msg, arg)
proc TokKindToStr*(k: TTokKind): string =
case k

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -12,10 +12,6 @@
import
strutils, ast, astalgo, passes, msgs, options
proc verbosePass*(): TPass
proc cleanupPass*(): TPass
# implementation
proc verboseOpen(s: PSym, filename: string): PPassContext =
#MessageOut('compiling ' + s.name.s);
result = nil # we don't need a context
@@ -24,9 +20,9 @@ proc verboseOpen(s: PSym, filename: string): PPassContext =
proc verboseProcess(context: PPassContext, n: PNode): PNode =
result = n
if context != nil: InternalError("logpass: context is not nil")
if gVerbosity == 3: liMessage(n.info, hintProcessing, $(ast.gid))
if gVerbosity == 3: Message(n.info, hintProcessing, $ast.gid)
proc verbosePass(): TPass =
proc verbosePass*(): TPass =
initPass(result)
result.open = verboseOpen
result.process = verboseProcess
@@ -43,11 +39,11 @@ proc cleanUp(c: PPassContext, n: PNode): PNode =
if (n.sons[namePos].kind == nkSym):
s = n.sons[namePos].sym
if not (sfDeadCodeElim in getModule(s).flags) and not astNeeded(s):
s.ast.sons[codePos] = nil # free the memory
s.ast.sons[codePos] = ast.emptyNode # free the memory
else:
nil
proc cleanupPass(): TPass =
proc cleanupPass*(): TPass =
initPass(result)
result.process = cleanUp
result.close = cleanUp

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -25,9 +25,9 @@ type
close: proc (p: PPassContext, n: PNode): PNode,
process: proc (p: PPassContext, topLevelStmt: PNode): PNode]
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
# nodes. These are passed to the other close procedures.
# This mechanism is needed for the instantiation of generics.
# This mechanism used to be used for the instantiation of generics.
proc registerPass*(p: TPass)
proc initPass*(p: var TPass)
@@ -37,11 +37,6 @@ proc initPass*(p: var TPass)
# whole program optimizations. For now, we avoid it to save a lot of memory.
proc processModule*(module: PSym, filename: string, stream: PLLStream,
rd: PRodReader)
proc astNeeded*(s: PSym): bool
# The ``rodwrite`` module uses this to determine if the body of a proc
# needs to be stored. The passes manager frees s.sons[codePos] when
# appropriate to free the procedure body's memory. This is important
# to keep memory usage down.
# the semantic checker needs these:
var
@@ -50,10 +45,21 @@ var
# implementation
proc astNeeded(s: PSym): bool =
proc skipCodegen*(n: PNode): bool {.inline.} =
# can be used by codegen passes to determine whether they should do
# something with `n`. Currently, this ignores `n` and uses the global
# error count instead.
result = msgs.gErrorCounter > 0
proc astNeeded*(s: PSym): bool =
# The ``rodwrite`` module uses this to determine if the body of a proc
# needs to be stored. The passes manager frees s.sons[codePos] when
# appropriate to free the procedure body's memory. This is important
# to keep memory usage down.
if (s.kind in {skMethod, skProc}) and
({sfCompilerProc, sfCompileTime} * s.flags == {}) and
(s.typ.callConv != ccInline) and (s.ast.sons[genericParamsPos] == nil):
(s.typ.callConv != ccInline) and
(s.ast.sons[genericParamsPos].kind == nkEmpty):
result = false
else:
result = true

View File

@@ -117,7 +117,7 @@ proc indAndComment(p: var TParser, n: PNode) =
var info = parLineInfo(p)
getTok(p)
if p.tok.tokType == tkComment: skipComment(p, n)
else: liMessage(info, errInvalidIndentation)
else: LocalError(info, errInvalidIndentation)
else:
skipComment(p, n)

View File

@@ -52,7 +52,7 @@ proc pragmaAsm*(c: PContext, n: PNode): char
# implementation
proc invalidPragma(n: PNode) =
liMessage(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
LocalError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
proc pragmaAsm(c: PContext, n: PNode): char =
result = '\0'
@@ -82,27 +82,24 @@ proc MakeExternExport(s: PSym, extname: string) =
proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr:
liMessage(n.info, errStringLiteralExpected)
GlobalError(n.info, errStringLiteralExpected)
else:
n.sons[1] = c.semConstExpr(c, n.sons[1])
case n.sons[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
else: liMessage(n.info, errStringLiteralExpected)
else: GlobalError(n.info, errStringLiteralExpected)
proc expectStrLit(c: PContext, n: PNode): string =
result = getStrLitNode(c, n).strVal
proc expectIntLit(c: PContext, n: PNode): int =
if n.kind != nkExprColonExpr:
liMessage(n.info, errIntLiteralExpected)
result = 0
LocalError(n.info, errIntLiteralExpected)
else:
n.sons[1] = c.semConstExpr(c, n.sons[1])
case n.sons[1].kind
of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal)
else:
liMessage(n.info, errIntLiteralExpected)
result = 0
else: LocalError(n.info, errIntLiteralExpected)
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
@@ -112,7 +109,9 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
var v: string
#if not (sfSystemModule in c.module.flags) then
# liMessage(n.info, errMagicOnlyInSystem);
if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
if n.kind != nkExprColonExpr:
LocalError(n.info, errStringLiteralExpected)
return
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
else: v = expectStrLit(c, n)
incl(s.flags, sfImportc)
@@ -123,7 +122,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
if copy($m, 1) == v:
s.magic = m
return
liMessage(n.info, warnUnknownMagic, v)
Message(n.info, warnUnknownMagic, v)
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
# this assumes that the order of special words and calling conventions is
@@ -135,9 +134,9 @@ proc IsTurnedOn(c: PContext, n: PNode): bool =
case whichKeyword(n.sons[1].ident)
of wOn: result = true
of wOff: result = false
else: liMessage(n.info, errOnOrOffExpected)
else: LocalError(n.info, errOnOrOffExpected)
else:
liMessage(n.info, errOnOrOffExpected)
LocalError(n.info, errOnOrOffExpected)
proc onOff(c: PContext, n: PNode, op: TOptions) =
if IsTurnedOn(c, n): gOptions = gOptions + op
@@ -153,9 +152,9 @@ proc processCallConv(c: PContext, n: PNode) =
case sw
of firstCallConv..lastCallConv:
POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
else: liMessage(n.info, errCallConvExpected)
else: LocalError(n.info, errCallConvExpected)
else:
liMessage(n.info, errCallConvExpected)
LocalError(n.info, errCallConvExpected)
proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
var it = PLib(c.libs.head)
@@ -168,13 +167,13 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
Append(c.libs, result)
proc expectDynlibNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
if n.kind != nkExprColonExpr: GlobalError(n.info, errStringLiteralExpected)
else:
result = c.semExpr(c, n.sons[1])
if result.kind == nkSym and result.sym.kind == skConst:
result = result.sym.ast # look it up
if result.typ == nil or result.typ.kind != tyString:
liMessage(n.info, errStringLiteralExpected)
GlobalError(n.info, errStringLiteralExpected)
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
if (sym == nil) or (sym.kind == skModule):
@@ -208,7 +207,7 @@ proc processNote(c: PContext, n: PNode) =
case whichKeyword(n.sons[1].ident)
of wOn: incl(gNotes, nk)
of wOff: excl(gNotes, nk)
else: liMessage(n.info, errOnOrOffExpected)
else: LocalError(n.info, errOnOrOffExpected)
else:
invalidPragma(n)
@@ -254,8 +253,8 @@ proc processOption(c: PContext, n: PNode) =
of wNone:
excl(gOptions, optOptimizeSpeed)
excl(gOptions, optOptimizeSize)
else: liMessage(n.info, errNoneSpeedOrSizeExpected)
else: liMessage(n.info, errOptionExpected)
else: LocalError(n.info, errNoneSpeedOrSizeExpected)
else: LocalError(n.info, errOptionExpected)
proc processPush(c: PContext, n: PNode, start: int) =
var x = newOptionEntry()
@@ -271,7 +270,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
proc processPop(c: PContext, n: PNode) =
if c.optionStack.counter <= 1:
liMessage(n.info, errAtPopWithoutPush)
LocalError(n.info, errAtPopWithoutPush)
else:
gOptions = POptionEntry(c.optionStack.tail).options
#liMessage(n.info, warnUser, ropeToStr(optionsToStr(gOptions)));
@@ -281,14 +280,14 @@ proc processPop(c: PContext, n: PNode) =
proc processDefine(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
DefineSymbol(n.sons[1].ident.s)
liMessage(n.info, warnDeprecated, "define")
Message(n.info, warnDeprecated, "define")
else:
invalidPragma(n)
proc processUndef(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
UndefSymbol(n.sons[1].ident.s)
liMessage(n.info, warnDeprecated, "undef")
Message(n.info, warnDeprecated, "undef")
else:
invalidPragma(n)
@@ -329,7 +328,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
of nkStrLit, nkRStrLit, nkTripleStrLit:
result = copyNode(n)
var str = n.sons[1].strVal
if str == "": liMessage(n.info, errEmptyAsm)
if str == "": GlobalError(n.info, errEmptyAsm)
# now parse the string literal and substitute symbols:
var a = 0
while true:
@@ -392,14 +391,16 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wExtern: setExternName(sym, expectStrLit(c, it))
of wAlign:
if sym.typ == nil: invalidPragma(it)
sym.typ.align = expectIntLit(c, it)
if not IsPowerOfTwo(sym.typ.align) and (sym.typ.align != 0):
liMessage(it.info, errPowerOfTwoExpected)
var align = expectIntLit(c, it)
if not IsPowerOfTwo(align) and align != 0:
LocalError(it.info, errPowerOfTwoExpected)
else:
sym.typ.align = align
of wSize:
if sym.typ == nil: invalidPragma(it)
var size = expectIntLit(c, it)
if not IsPowerOfTwo(size) or size <= 0 or size > 8:
liMessage(it.info, errPowerOfTwoExpected)
LocalError(it.info, errPowerOfTwoExpected)
else:
sym.typ.size = size
of wNodecl:
@@ -477,12 +478,10 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wTypeCheck:
noVal(it)
incl(sym.flags, sfTypeCheck)
of wHint: liMessage(it.info, hintUser, expectStrLit(c, it))
of wWarning: liMessage(it.info, warnUser, expectStrLit(c, it))
of wError: liMessage(it.info, errUser, expectStrLit(c, it))
of wFatal:
liMessage(it.info, errUser, expectStrLit(c, it))
quit(1)
of wHint: Message(it.info, hintUser, expectStrLit(c, it))
of wWarning: Message(it.info, warnUser, expectStrLit(c, it))
of wError: LocalError(it.info, errUser, expectStrLit(c, it))
of wFatal: Fatal(it.info, errUser, expectStrLit(c, it))
of wDefine: processDefine(c, it)
of wUndef: processUndef(c, it)
of wCompile: processCompile(c, it)
@@ -515,7 +514,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
else: processNote(c, it)
if (sym != nil) and (sym.kind != skModule):
if (lfExportLib in sym.loc.flags) and not (sfExportc in sym.flags):
liMessage(n.info, errDynlibRequiresExportc)
LocalError(n.info, errDynlibRequiresExportc)
var lib = POptionEntry(c.optionstack.tail).dynlib
if ({lfDynamicLib, lfHeader} * sym.loc.flags == {}) and
(sfImportc in sym.flags) and (lib != nil):

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -50,7 +50,7 @@ proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym =
of paramsEqual:
return
of paramsIncompatible:
liMessage(fn.info, errNotOverloadable, fn.name.s)
LocalError(fn.info, errNotOverloadable, fn.name.s)
return
of paramsNotEqual:
nil

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -94,7 +94,7 @@ proc parseLine(p: var TTmplParser) =
dec(p.indent, 2)
else:
p.info.col = int16(j)
liMessage(p.info, errXNotAllowedHere, "end")
LocalError(p.info, errXNotAllowedHere, "end")
LLStreamWrite(p.outp, repeatChar(p.indent))
LLStreamWrite(p.outp, "#end")
of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
@@ -163,7 +163,8 @@ proc parseLine(p: var TTmplParser) =
while true:
case p.x[j]
of '\0':
liMessage(p.info, errXExpected, "}")
LocalError(p.info, errXExpected, "}")
break
of '{':
inc(j)
inc(curly)
@@ -196,7 +197,7 @@ proc parseLine(p: var TTmplParser) =
inc(j)
else:
p.info.col = int16(j)
liMessage(p.info, errInvalidExpression, "$")
LocalError(p.info, errInvalidExpression, "$")
else:
LLStreamWrite(p.outp, p.x[j])
inc(j)

0
rod/rodutils.nim Normal file → Executable file
View File

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -288,10 +288,10 @@ proc tokInfo(p: TRstParser, tok: TToken): TLineInfo =
result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col)
proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) =
liMessage(tokInfo(p, p.tok[p.idx]), msgKind, arg)
GenericMessage(tokInfo(p, p.tok[p.idx]), msgKind, arg)
proc rstMessage(p: TRstParser, msgKind: TMsgKind) =
liMessage(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol)
GenericMessage(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol)
proc currInd(p: TRstParser): int =
result = p.indentStack[high(p.indentStack)]

View File

@@ -223,11 +223,11 @@ proc getLineInfo(L: TLexer): TLineInfo =
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") =
msgs.liMessage(getLineInfo(L), msg, arg)
msgs.Message(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
msgs.liMessage(info, msg, arg)
msgs.Message(info, msg, arg)
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
var pos = L.bufpos # use registers for pos, buf

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -25,7 +25,7 @@ proc considerAcc(n: PNode): PIdent =
of nkIdent: result = x.ident
of nkSym: result = x.sym.name
else:
liMessage(n.info, errIdentifierExpected, renderTree(n))
GlobalError(n.info, errIdentifierExpected, renderTree(n))
result = nil
proc isTopLevel(c: PContext): bool =
@@ -37,7 +37,7 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
proc markUsed(n: PNode, s: PSym) =
incl(s.flags, sfUsed)
if sfDeprecated in s.flags: liMessage(n.info, warnDeprecated, s.name.s)
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym
# identifier with visability
@@ -65,22 +65,22 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
proc semConstExpr(c: PContext, n: PNode): PNode =
result = semExprWithType(c, n)
if result == nil:
liMessage(n.info, errConstExprExpected)
GlobalError(n.info, errConstExprExpected)
return
result = getConstExpr(c.module, result)
if result == nil: liMessage(n.info, errConstExprExpected)
if result == nil: GlobalError(n.info, errConstExprExpected)
proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
var e = semExprWithType(c, n)
if e == nil:
liMessage(n.info, errConstExprExpected)
GlobalError(n.info, errConstExprExpected)
return nil
result = getConstExpr(c.module, e)
if result == nil:
#writeln(output, renderTree(n));
result = evalConstExpr(c.module, e)
if (result == nil) or (result.kind == nkEmpty):
liMessage(n.info, errConstExprExpected)
GlobalError(n.info, errConstExprExpected)
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
result = n
@@ -91,7 +91,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
result = semExpr(c, result) # semExprWithType(c, result)
of tyStmt: result = semStmt(c, result)
of tyTypeDesc: result.typ = semTypeNode(c, result, nil)
else: liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
else: GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
include "semtempl.nim"
@@ -99,7 +99,7 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
semCheck: bool = true): PNode =
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
liMessage(n.info, errTemplateInstantiationTooNested)
GlobalError(n.info, errTemplateInstantiationTooNested)
markUsed(n, sym)
var p = newEvalContext(c.module, "", false)
var s = newStackFrame()
@@ -111,23 +111,23 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
discard eval(p, sym.ast.sons[codePos])
result = s.params[0]
popStackFrame(p)
if cyclicTree(result): liMessage(n.info, errCyclicTree)
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
if semCheck: result = semAfterMacroCall(c, result, sym)
dec(evalTemplateCounter)
include "seminst.nim", "sigmatch.nim"
include seminst, sigmatch
proc CheckBool(t: PNode) =
if (t.Typ == nil) or
(skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool):
liMessage(t.Info, errExprMustBeBool)
LocalError(t.Info, errExprMustBeBool)
proc typeMismatch(n: PNode, formal, actual: PType) =
liMessage(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
typeToString(actual) & ") " &
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
include "semtypes.nim", "semexprs.nim", "semgnrc.nim", "semstmts.nim"
include semtypes, semexprs, semgnrc, semstmts
proc addCodeForGenerics(c: PContext, n: PNode) =
for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1):
@@ -166,19 +166,28 @@ proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext
c.fromCache = true
result = c
proc myProcess(context: PPassContext, n: PNode): PNode =
result = nil
var c = PContext(context)
result = semStmt(c, n)
proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
result = semStmt(c, n)
# BUGFIX: process newly generated generics here, not at the end!
if sonsLen(c.generics) > 0:
var a = newNodeI(nkStmtList, n.info)
addCodeForGenerics(c, a)
if sonsLen(a) > 0:
# a generic has been added to `a`:
addSonIfNotNil(a, result)
if result.kind != nkEmpty: addSon(a, result)
result = a
proc myProcess(context: PPassContext, n: PNode): PNode =
var c = PContext(context)
# no need for an expensive 'try' if we stop after the first error anyway:
if msgs.gErrorMax <= 1:
result = SemStmtAndGenerateGenerics(c, n)
else:
try:
result = SemStmtAndGenerateGenerics(c, n)
except ERecoverableError:
result = ast.emptyNode
proc myClose(context: PPassContext, n: PNode): PNode =
var c = PContext(context)
closeScope(c.tab) # close module's scope

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -69,10 +69,6 @@ proc makeVarType*(c: PContext, baseType: PType): PType
proc newTypeS*(kind: TTypeKind, c: PContext): PType
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext)
proc makeRangeType*(c: PContext, first, last: biggestInt, info: TLineInfo): PType
proc illFormedAst*(n: PNode)
proc getSon*(n: PNode, indx: int): PNode
proc checkSonsLen*(n: PNode, length: int)
proc checkMinSonsLen*(n: PNode, length: int)
# owner handling:
proc getCurrOwner*(): PSym
@@ -122,7 +118,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
append(result.optionStack, newOptionEntry())
result.module = module
result.generics = newNode(nkStmtList)
result.converters = @ []
result.converters = @[]
result.filename = nimfile
IntSetInit(result.includedFiles)
initStrTable(result.userPragmas)
@@ -140,7 +136,7 @@ proc newLib(kind: TLibKind): PLib =
proc addToLib(lib: PLib, sym: PSym) =
#ObjectSetIncl(lib.syms, sym);
if sym.annex != nil: liMessage(sym.info, errInvalidPragma)
if sym.annex != nil: LocalError(sym.info, errInvalidPragma)
sym.annex = lib
proc makePtrType(c: PContext, baseType: PType): PType =
@@ -170,20 +166,13 @@ proc makeRangeType(c: PContext, first, last: biggestInt,
result.n = n
addSon(result, getSysType(tyInt)) # basetype of range
proc illFormedAst(n: PNode) =
liMessage(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
proc illFormedAst*(n: PNode) =
GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
proc getSon(n: PNode, indx: int): PNode =
if (n != nil) and (indx < sonsLen(n)):
result = n.sons[indx]
else:
illFormedAst(n)
result = nil
proc checkSonsLen(n: PNode, length: int) =
if (n == nil) or (sonsLen(n) != length): illFormedAst(n)
proc checkSonsLen*(n: PNode, length: int) =
if sonsLen(n) != length: illFormedAst(n)
proc checkMinSonsLen(n: PNode, length: int) =
if (n == nil) or (sonsLen(n) < length): illFormedAst(n)
proc checkMinSonsLen*(n: PNode, length: int) =
if sonsLen(n) < length: illFormedAst(n)
initIdTable(gInstTypes)

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -23,22 +23,24 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags)
if result == nil: InternalError("semExprWithType")
if (result.typ == nil):
liMessage(n.info, errExprXHasNoType, renderTree(result, {renderNoComments}))
if result.typ.kind == tyVar:
var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
addSon(d, result)
result = d
if result.kind == nkEmpty: InternalError("semExprWithType")
if result.typ != nil:
if result.typ.kind == tyVar:
var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
addSon(d, result)
result = d
else:
GlobalError(n.info, errExprXHasNoType,
renderTree(result, {renderNoComments}))
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
if s.kind == skType and efAllowType notin flags:
liMessage(n.info, errATypeHasNoValue)
GlobalError(n.info, errATypeHasNoValue)
case s.kind
of skProc, skMethod, skIterator, skConverter:
if not (sfProcVar in s.flags) and (s.typ.callConv == ccDefault) and
(getModule(s).id != c.module.id):
liMessage(n.info, errXCannotBePassedToProcVar, s.name.s)
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
result = symChoice(c, n, s)
of skConst:
#
@@ -79,7 +81,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
var diff = inheritanceDiff(castDest, src)
if diff == high(int):
liMessage(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
GlobalError(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
typeToString(src), typeToString(castDest)]))
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
@@ -88,7 +90,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
if sameType(castDest, src):
# don't annoy conversions that may be needed on another processor:
if not (castDest.kind in {tyInt..tyFloat128, tyNil}):
liMessage(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
return
var d = skipTypes(castDest, abstractVar)
var s = skipTypes(src, abstractVar)
@@ -96,9 +98,9 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
d = base(d)
s = base(s)
if d == nil:
liMessage(info, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
GlobalError(info, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
typeToString(src), typeToString(castDest)]))
if (d.Kind == tyObject) and (s.Kind == tyObject):
elif d.Kind == tyObject and s.Kind == tyObject:
checkConversionBetweenObjects(info, d, s)
elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
(skipTypes(src, abstractVarRange).Kind in IntegralTypes):
@@ -109,7 +111,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
of isNone, isGeneric:
if not equalOrDistinctOf(castDest, src) and
not equalOrDistinctOf(src, castDest):
liMessage(info, errGenerated, `%`(
GlobalError(info, errGenerated, `%`(
MsgKindToString(errIllegalConvFromXtoY),
[typeToString(src), typeToString(castDest)]))
else:
@@ -134,7 +136,7 @@ proc isCastable(dst, src: PType): bool =
(skipTypes(src, abstractInst).kind in {tyInt..tyFloat128})
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
if sonsLen(n) != 2: liMessage(n.info, errConvNeedsOneArg)
if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg)
result = newNodeI(nkConv, n.info)
result.typ = semTypeNode(c, n.sons[0], nil)
addSon(result, copyTree(n.sons[0]))
@@ -147,10 +149,10 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
if sameType(result.typ, op.sons[i].typ):
markUsed(n, op.sons[i].sym)
return op.sons[i]
liMessage(n.info, errUseQualifier, op.sons[0].sym.name.s)
localError(n.info, errUseQualifier, op.sons[0].sym.name.s)
proc semCast(c: PContext, n: PNode): PNode =
if optSafeCode in gGlobalOptions: liMessage(n.info, errCastNotInSafeMode)
if optSafeCode in gGlobalOptions: localError(n.info, errCastNotInSafeMode)
incl(c.p.owner.flags, sfSideEffect)
checkSonsLen(n, 2)
result = newNodeI(nkCast, n.info)
@@ -158,13 +160,13 @@ proc semCast(c: PContext, n: PNode): PNode =
addSon(result, copyTree(n.sons[0]))
addSon(result, semExprWithType(c, n.sons[1]))
if not isCastable(result.typ, result.sons[1].Typ):
liMessage(result.info, errExprCannotBeCastedToX, typeToString(result.Typ))
GlobalError(result.info, errExprCannotBeCastedToX, typeToString(result.Typ))
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
const
opToStr: array[mLow..mHigh, string] = ["low", "high"]
if sonsLen(n) != 2:
liMessage(n.info, errXExpectsTypeOrValue, opToStr[m])
GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
else:
n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
@@ -175,11 +177,11 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
n.typ = n.sons[1].typ.sons[0] # indextype
of tyInt..tyInt64, tyChar, tyBool, tyEnum:
n.typ = n.sons[1].typ
else: liMessage(n.info, errInvalidArgForX, opToStr[m])
else: GlobalError(n.info, errInvalidArgForX, opToStr[m])
result = n
proc semSizeof(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2: liMessage(n.info, errXExpectsTypeOrValue, "sizeof")
if sonsLen(n) != 2: GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
else: n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
n.typ = getSysType(tyInt)
result = n
@@ -190,20 +192,22 @@ proc semIs(c: PContext, n: PNode): PNode =
n.sons[2] = semExprWithType(c, n.sons[2], {efAllowType})
var a = n.sons[1].typ
var b = n.sons[2].typ
if (b.kind != tyObject) or (a.kind != tyObject):
liMessage(n.info, errIsExpectsObjectTypes)
while (b != nil) and (b.id != a.id): b = b.sons[0]
if b == nil: liMessage(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
# a and b can be nil in case of an error:
if a != nil and b != nil:
if (b.kind != tyObject) or (a.kind != tyObject):
GlobalError(n.info, errIsExpectsObjectTypes)
while (b != nil) and (b.id != a.id): b = b.sons[0]
if b == nil:
GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
n.typ = getSysType(tyBool)
else:
liMessage(n.info, errIsExpectsTwoArguments)
GlobalError(n.info, errIsExpectsTwoArguments)
result = n
proc semOpAux(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
var a = n.sons[i]
if a.kind == nkExprEqExpr:
checkSonsLen(a, 2)
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
var info = a.sons[0].info
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
a.sons[1] = semExprWithType(c, a.sons[1])
@@ -223,9 +227,6 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
result = semExpr(c, result)
proc changeType(n: PNode, newType: PType) =
var
f: PSym
a, m: PNode
case n.kind
of nkCurly, nkBracket:
for i in countup(0, sonsLen(n) - 1): changeType(n.sons[i], elemType(newType))
@@ -235,22 +236,21 @@ proc changeType(n: PNode, newType: PType) =
if newType.n == nil: InternalError(n.info, "changeType: no tuple fields")
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
for i in countup(0, sonsLen(n) - 1):
m = n.sons[i].sons[0]
var m = n.sons[i].sons[0]
if m.kind != nkSym:
internalError(m.info, "changeType(): invalid tuple constr")
f = getSymFromList(newType.n, m.sym.name)
var f = getSymFromList(newType.n, m.sym.name)
if f == nil: internalError(m.info, "changeType(): invalid identifier")
changeType(n.sons[i].sons[1], f.typ)
else:
for i in countup(0, sonsLen(n) - 1):
m = n.sons[i]
a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
var m = n.sons[i]
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
addSon(a, newSymNode(newType.n.sons[i].sym))
addSon(a, m)
changeType(m, newType.sons[i])
n.sons[i] = a
else:
nil
else: nil
n.typ = newType
proc semArrayConstr(c: PContext, n: PNode): PNode =
@@ -263,7 +263,7 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
var x = n.sons[0]
var lastIndex: biggestInt = 0
var indexType = getSysType(tyInt)
if x.kind == nkExprColonExpr:
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
var idx = semConstExpr(c, x.sons[0])
lastIndex = getOrdValue(idx)
indexType = idx.typ
@@ -273,11 +273,11 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
for i in countup(1, sonsLen(n) - 1):
x = n.sons[i]
if x.kind == nkExprColonExpr:
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
var idx = semConstExpr(c, x.sons[0])
idx = fitNode(c, indexType, idx)
if lastIndex+1 != getOrdValue(idx):
liMessage(x.info, errInvalidOrderInArrayConstructor)
localError(x.info, errInvalidOrderInArrayConstructor)
x = x.sons[1]
n.sons[i] = semExprWithType(c, x)
@@ -334,7 +334,6 @@ proc isAssignable(n: PNode): TAssignableResult =
of nkSym:
if (n.sym.kind in {skVar, skTemp}): result = arLValue
of nkDotExpr:
checkMinSonsLen(n, 1)
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
result = arLValue
else:
@@ -342,7 +341,6 @@ proc isAssignable(n: PNode): TAssignableResult =
if (result == arLValue) and (sfDiscriminant in n.sons[1].sym.flags):
result = arDiscriminant
of nkBracketExpr:
checkMinSonsLen(n, 1)
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
result = arLValue
else:
@@ -368,7 +366,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
addSon(result, n)
if isAssignable(n) != arLValue:
liMessage(n.info, errVarForOutParamNeeded)
localError(n.info, errVarForOutParamNeeded)
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
result = n
@@ -403,7 +401,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
if i < sonsLen(t) and skipTypes(t.sons[i], abstractInst).kind == tyVar:
if isAssignable(n.sons[i]) != arLValue:
liMessage(n.sons[i].info, errVarForOutParamNeeded)
LocalError(n.sons[i].info, errVarForOutParamNeeded)
return
for i in countup(1, sonsLen(n) - 1):
if (i < sonsLen(t)) and
@@ -421,7 +419,7 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
InternalError("semDirectCallAnalyseEffects")
var callee = result.sons[0].sym
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
liMessage(n.info, errRecursiveDependencyX, callee.name.s)
GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
if not (sfNoSideEffect in callee.flags):
if (sfForward in callee.flags) or
({sfImportc, sfSideEffect} * callee.flags != {}):
@@ -456,7 +454,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
add(msg, typeToString(n.sons[i].typ))
add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
typeToString(n.sons[0].typ))
liMessage(n.Info, errGenerated, msg)
GlobalError(n.Info, errGenerated, msg)
result = nil
else:
result = m.call
@@ -471,8 +469,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
n.sons[0] = prc
result = semDirectCallAnalyseEffects(c, n, flags)
if result == nil:
liMessage(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
GlobalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
@@ -482,7 +480,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = semDirectCallAnalyseEffects(c, n, flags)
if result == nil:
result = overloadedCallOpr(c, n)
if result == nil: liMessage(n.Info, errGenerated, getNotFoundError(c, n))
if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
@@ -517,12 +515,12 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
else:
result = StrTableGet(m.tab, ident)
else:
liMessage(n.sons[1].info, errIdentifierExpected, "")
GlobalError(n.sons[1].info, errIdentifierExpected, "")
of nkAccQuoted:
checkSonsLen(n, 1)
result = lookupForDefined(c, n.sons[0], onlyCurrentScope)
else:
liMessage(n.info, errIdentifierExpected, renderTree(n))
GlobalError(n.info, errIdentifierExpected, renderTree(n))
result = nil
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
@@ -588,7 +586,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
else:
if check == nil:
check = newNodeI(nkCheckedFieldExpr, n.info)
addSon(check, nil) # make space for access node
addSon(check, ast.emptyNode) # make space for access node
s = newNodeI(nkCurly, n.info)
for j in countup(0, sonsLen(it) - 2): addSon(s, copyTree(it.sons[j]))
inExpr = newNodeI(nkCall, n.info)
@@ -602,7 +600,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
if result != nil:
if check == nil:
check = newNodeI(nkCheckedFieldExpr, n.info)
addSon(check, nil) # make space for access node
addSon(check, ast.emptyNode) # make space for access node
inExpr = newNodeI(nkCall, n.info)
addSon(inExpr, newIdentNode(getIdent("in"), n.info))
addSon(inExpr, copyTree(r.sons[0]))
@@ -653,10 +651,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result.typ = ty
markUsed(n, f)
else:
liMessage(n.sons[1].info, errEnumHasNoValueX, i.s)
GlobalError(n.sons[1].info, errEnumHasNoValueX, i.s)
return
elif not (efAllowType in flags) and isTypeExpr(n.sons[0]):
liMessage(n.sons[0].info, errATypeHasNoValue)
GlobalError(n.sons[0].info, errATypeHasNoValue)
return
ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
var check: PNode = nil
@@ -705,27 +703,27 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
addSon(result, newIdentNode(i, n.info))
addSon(result, copyTree(n[0]))
else:
liMessage(n.Info, errUndeclaredFieldX, i.s)
GlobalError(n.Info, errUndeclaredFieldX, i.s)
proc whichSliceOpr(n: PNode): string =
if (n.sons[0] == nil):
if (n.sons[1] == nil): result = "[..]"
if n.sons[0].kind == nkEmpty:
if n.sons[1].kind == nkEmpty: result = "[..]"
else: result = "[..$]"
elif (n.sons[1] == nil):
elif n.sons[1].kind == nkEmpty:
result = "[$..]"
else:
result = "[$..$]"
proc addSliceOpr(result: var string, n: PNode) =
if n[0] == nil:
if n[1] == nil: result.add("..")
if n[0].kind == nkEmpty:
if n[1].kind == nkEmpty: result.add("..")
else: result.add("..$")
elif n[1] == nil: result.add("$..")
elif n[1].kind == nkEmpty: result.add("$..")
else: result.add("$..$")
proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
result = newNodeI(nkCall, n.info)
add(result, nil) # fill with the correct node later
add(result, ast.emptyNode) # fill with the correct node later
add(result, n[0])
var opr = "["
for i in 1..n.len-1:
@@ -734,8 +732,8 @@ proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
# we have a slice argument
checkSonsLen(n[i], 2)
addSliceOpr(opr, n[i])
addSonIfNotNil(result, n[i][0])
addSonIfNotNil(result, n[i][1])
addSon(result, n[i][0])
addSon(result, n[i][1])
else:
add(result, n[i])
if inAsgn: add(opr, "]=")
@@ -757,7 +755,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
if arg != nil: n.sons[1] = arg
else: liMessage(n.info, errIndexTypesDoNotMatch)
else: GlobalError(n.info, errIndexTypesDoNotMatch)
result = n
result.typ = elemType(arr)
of tyTuple:
@@ -769,9 +767,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
{tyInt..tyInt64}:
var idx = getOrdValue(n.sons[1])
if (idx >= 0) and (idx < sonsLen(arr)): n.typ = arr.sons[int(idx)]
else: liMessage(n.info, errInvalidIndexValueForTuple)
else: GlobalError(n.info, errInvalidIndexValueForTuple)
else:
liMessage(n.info, errIndexTypesDoNotMatch)
GlobalError(n.info, errIndexTypesDoNotMatch)
result = n
else: nil
@@ -779,21 +777,7 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = semSubscript(c, n, flags)
if result == nil:
# overloaded [] operator:
when false:
result = newNodeI(nkCall, n.info)
if n.sons[1].kind == nkRange:
checkSonsLen(n.sons[1], 2)
addSon(result, newIdentNode(getIdent(whichSliceOpr(n.sons[1])), n.info))
addSon(result, n.sons[0])
addSonIfNotNil(result, n.sons[1].sons[0])
addSonIfNotNil(result, n.sons[1].sons[1])
else:
addSon(result, newIdentNode(getIdent("[]"), n.info))
addSon(result, n.sons[0])
addSon(result, n.sons[1])
result = semExpr(c, result)
else:
result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
proc semIfExpr(c: PContext, n: PNode): PNode =
result = n
@@ -839,7 +823,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
if typ == nil:
typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
if not isOrdinalType(typ):
liMessage(n.info, errOrdinalTypeExpected)
GlobalError(n.info, errOrdinalTypeExpected)
return
if lengthOrd(typ) > MaxSetElements:
typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
@@ -871,11 +855,11 @@ proc checkPar(n: PNode): TParKind =
if result == paTupleFields:
if (n.sons[i].kind != nkExprColonExpr) or
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
liMessage(n.sons[i].info, errNamedExprExpected)
GlobalError(n.sons[i].info, errNamedExprExpected)
return paNone
else:
if n.sons[i].kind == nkExprColonExpr:
liMessage(n.sons[i].info, errNamedExprNotAllowed)
GlobalError(n.sons[i].info, errNamedExprNotAllowed)
return paNone
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
@@ -892,7 +876,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
else: id = n.sons[i].sons[0].sym.name
if IntSetContainsOrIncl(ids, id.id):
liMessage(n.sons[i].info, errFieldInitTwice, id.s)
localError(n.sons[i].info, errFieldInitTwice, id.s)
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
var f = newSymS(skField, n.sons[i].sons[0], c)
f.typ = n.sons[i].sons[1].typ
@@ -925,7 +909,7 @@ proc semBlockExpr(c: PContext, n: PNode): PNode =
Inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2)
openScope(c.tab) # BUGFIX: label is in the scope of block!
if n.sons[0] != nil: addDecl(c, newSymS(skLabel, n.sons[0], c))
if n.sons[0].kind != nkEmpty: addDecl(c, newSymS(skLabel, n.sons[0], c))
n.sons[1] = semStmtListExpr(c, n.sons[1])
n.typ = n.sons[1].typ
closeScope(c.tab)
@@ -935,7 +919,7 @@ proc isCallExpr(n: PNode): bool =
result = n.kind in {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit}
proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode =
proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
checkMinSonsLen(n, 2)
var a: PNode
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
@@ -957,23 +941,18 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode =
addSon(result, n.sons[0].sons[i])
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
result = semTemplateExpr(c, result, s, semCheck)
else: liMessage(n.info, errXisNoMacroOrTemplate, s.name.s)
else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
else:
liMessage(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n
if n == nil: return
if nfSem in n.flags: return
case n.kind # atoms:
of nkIdent:
var s = lookUp(c, n)
result = semSym(c, n, s, flags)
of nkSym:
#s := n.sym;
# include(s.flags, sfUsed);
# if (s.kind = skType) and not (efAllowType in flags) then
# liMessage(n.info, errATypeHasNoValue);
# because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again!
result = semSym(c, n, n.sym, flags)
@@ -982,7 +961,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkNilLit:
result.typ = getSysType(tyNil)
of nkType:
if not (efAllowType in flags): liMessage(n.info, errATypeHasNoValue)
if not (efAllowType in flags): GlobalError(n.info, errATypeHasNoValue)
n.typ = semTypeNode(c, n, nil)
of nkIntLit:
if result.typ == nil: result.typ = getSysType(tyInt)
@@ -1020,7 +999,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of skMacro: result = semMacroExpr(c, n, s)
of skTemplate: result = semTemplateExpr(c, n, s)
of skType:
if n.kind != nkCall: liMessage(n.info, errXisNotCallable, s.name.s)
if n.kind != nkCall: GlobalError(n.info, errXisNotCallable, s.name.s)
# XXX does this check make any sense?
result = semConv(c, n, s)
of skProc, skMethod, skConverter, skIterator:
@@ -1062,14 +1041,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
case t.kind
of tyRef, tyPtr: n.typ = t.sons[0]
else: liMessage(n.sons[0].info, errCircumNeedsPointer)
else: GlobalError(n.sons[0].info, errCircumNeedsPointer)
result = n
of nkAddr:
result = n
checkSonsLen(n, 1)
n.sons[0] = semExprWithType(c, n.sons[0])
if isAssignable(n.sons[0]) != arLValue:
liMessage(n.info, errExprHasNoAddress)
GlobalError(n.info, errExprHasNoAddress)
n.typ = makePtrType(c, n.sons[0].typ)
of nkHiddenAddr, nkHiddenDeref:
checkSonsLen(n, 1)
@@ -1091,8 +1070,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkCheckedFieldExpr:
checkMinSonsLen(n, 2)
of nkSymChoice:
liMessage(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
else:
#InternalError(n.info, nodeKindToStr[n.kind]);
liMessage(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
GlobalError(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
incl(result.flags, nfSem)

View File

@@ -334,8 +334,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
of mSizeOf:
var a = n.sons[1]
if computeSize(a.typ) < 0:
liMessage(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof")
if a.typ.kind in {tyArray, tyObject, tyTuple}:
LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined,
"sizeof")
result = nil
elif a.typ.kind in {tyArray, tyObject, tyTuple}:
result = nil
# XXX: size computation for complex types is still wrong
else:
@@ -345,7 +347,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
of mHigh:
if not (skipTypes(n.sons[1].typ, abstractVar).kind in
{tyOpenArray, tySequence, tyString}):
result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)), n)
result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)),
n)
of mLengthOpenArray:
var a = n.sons[1]
if a.kind == nkPassAsOpenArray: a = a.sons[0]
@@ -357,9 +360,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
else:
result = magicCall(m, n)
except EOverflow:
liMessage(n.info, errOverOrUnderflow)
LocalError(n.info, errOverOrUnderflow)
except EDivByZero:
liMessage(n.info, errConstantDivisionByZero)
LocalError(n.info, errConstantDivisionByZero)
of nkAddr:
var a = getConstExpr(m, n.sons[0])
if a != nil:
@@ -408,7 +411,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
result = a # a <= x and x <= b
result.typ = n.typ
else:
liMessage(n.info, errGenerated, `%`(
LocalError(n.info, errGenerated, `%`(
msgKindToString(errIllegalConvFromXtoY),
[typeToString(n.sons[0].typ), typeToString(n.typ)]))
of nkStringToCString, nkCStringToString:

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -55,7 +55,7 @@ proc getIdentNode(n: PNode): PNode =
of nkIdent: result = n
else:
illFormedAst(n)
result = nil
result = n
# of nkAccQuoted:
# s = lookUp(c, n)
@@ -67,21 +67,20 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
L: int
a: PNode
result = n
if n == nil: return
case n.kind
of nkIdent:
var s = SymtabGet(c.Tab, n.ident)
if s == nil:
# no error if symbol cannot be bound, unless in ``bind`` context:
if withinBind in flags:
liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
localError(n.info, errUndeclaredIdentifier, n.ident.s)
else:
if withinBind in flags: result = symChoice(c, n, s)
else: result = semGenericStmtSymbol(c, n, s)
of nkDotExpr:
var s = QualifiedLookUp(c, n, {})
if s != nil: result = semGenericStmtSymbol(c, n, s)
of nkSym..nkNilLit:
of nkEmpty, nkSym..nkNilLit:
nil
of nkBind:
result = semGenericStmt(c, n.sons[0], {withinBind})
@@ -138,7 +137,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
of nkBlockStmt, nkBlockExpr, nkBlockType:
checkSonsLen(n, 2)
openScope(c.tab)
if n.sons[0] != nil: addDecl(c, newSymS(skUnknown, n.sons[0], c))
if n.sons[0].kind != nkEmpty: addDecl(c, newSymS(skUnknown, n.sons[0], c))
n.sons[1] = semGenericStmt(c, n.sons[1])
closeScope(c.tab)
of nkTryStmt:
@@ -193,7 +192,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): IllFormedAst(a)
checkSonsLen(a, 3)
if a.sons[1] != nil:
if a.sons[1].kind != nkEmpty:
openScope(c.tab)
a.sons[1] = semGenericStmt(c, a.sons[1])
a.sons[2] = semGenericStmt(c, a.sons[2], {withinTypeDesc})
@@ -202,7 +201,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
a.sons[2] = semGenericStmt(c, a.sons[2], {withinTypeDesc})
of nkEnumTy:
checkMinSonsLen(n, 1)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
for i in countup(1, sonsLen(n) - 1):
case n.sons[i].kind
@@ -214,7 +213,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
nil
of nkFormalParams:
checkMinSonsLen(n, 1)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
for i in countup(1, sonsLen(n) - 1):
a = n.sons[i]
@@ -231,8 +230,8 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
addDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c))
openScope(c.tab)
n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos])
if n.sons[paramsPos] != nil:
if n.sons[paramsPos].sons[0] != nil:
if n.sons[paramsPos].kind != nkEmpty:
if n.sons[paramsPos].sons[0].kind != nkEmpty:
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos])
n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos])

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -48,7 +48,9 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
var s = newSym(skType, q.name, getCurrOwner())
var t = PType(IdTableGet(pt, q.typ))
if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
if t == nil:
LocalError(a.info, errCannotInstantiateX, s.name.s)
break
if (t.kind == tyGenericParam):
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
s.typ = t
@@ -94,13 +96,14 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
result.ast = n
pushOwner(result)
openScope(c.tab)
if (n.sons[genericParamsPos] == nil):
if (n.sons[genericParamsPos].kind == nkEmpty):
InternalError(n.info, "generateInstance")
n.sons[namePos] = newSymNode(result)
pushInfoContext(info)
instantiateGenericParamList(c, n.sons[genericParamsPos], pt)
n.sons[genericParamsPos] = nil # semantic checking for the parameters:
if n.sons[paramsPos] != nil:
n.sons[genericParamsPos] = ast.emptyNode
# semantic checking for the parameters:
if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[ParamsPos], nil, result)
addParams(c, result.typ.n)
else:
@@ -112,7 +115,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
# add it here, so that recursive generic procs are possible:
GenericCacheAdd(c, fn, result)
addDecl(c, result)
if n.sons[codePos] != nil:
if n.sons[codePos].kind != nkEmpty:
c.p = newProcCon(result)
if result.kind in {skProc, skMethod, skConverter}:
addResult(c, result.typ.sons[0], n.info)
@@ -129,11 +132,11 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
proc checkConstructedType(info: TLineInfo, t: PType) =
if (tfAcyclic in t.flags) and (skipTypes(t, abstractInst).kind != tyObject):
liMessage(info, errInvalidPragmaX, "acyclic")
if computeSize(t) < 0:
liMessage(info, errIllegalRecursionInTypeX, typeToString(t))
if (t.kind == tyVar) and (t.sons[0].kind == tyVar):
liMessage(info, errVarVarTypeNotAllowed)
LocalError(info, errInvalidPragmaX, "acyclic")
elif computeSize(t) < 0:
LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
elif (t.kind == tyVar) and (t.sons[0].kind == tyVar):
LocalError(info, errVarVarTypeNotAllowed)
type
TReplTypeVars{.final.} = object
@@ -162,8 +165,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
if s == nil:
return nil
if s == nil: return nil
result = PSym(idTableGet(cl.symMap, s))
if result == nil:
result = copySym(s, false)
@@ -176,7 +178,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
result = PType(idTableGet(cl.typeMap, t))
if result == nil:
liMessage(t.sym.info, errCannotInstantiateX, typeToString(t))
GlobalError(t.sym.info, errCannotInstantiateX, typeToString(t))
elif result.kind == tyGenericParam:
InternalError(cl.info, "substitution with generic parameter")
@@ -210,7 +212,8 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
idTablePut(gInstTypes, header, result)
newbody = ReplaceTypeVarsT(cl, lastSon(body))
newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
addSon(result, newbody) #writeln(output, ropeToStr(Typetoyaml(newbody)));
addSon(result, newbody)
#writeln(output, ropeToStr(Typetoyaml(newbody)));
checkConstructedType(cl.info, newbody)
of tyGenericBody:
InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
@@ -222,7 +225,7 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
result.n = ReplaceTypeVarsN(cl, result.n)
if result.Kind in GenericTypes:
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
LocalError(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
#writeln(output, ropeToStr(Typetoyaml(result)))
#checkConstructedType(cl.info, result)

View File

@@ -12,13 +12,12 @@
proc semExprNoType(c: PContext, n: PNode): PNode =
result = semExpr(c, n)
if result.typ != nil and result.typ.kind != tyStmt:
liMessage(n.info, errDiscardValue)
localError(n.info, errDiscardValue)
proc semWhen(c: PContext, n: PNode): PNode =
result = nil
for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i]
if it == nil: illFormedAst(n)
case it.kind
of nkElifBranch:
checkSonsLen(it, 2)
@@ -43,7 +42,6 @@ proc semIf(c: PContext, n: PNode): PNode =
result = n
for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i]
if it == nil: illFormedAst(n)
case it.kind
of nkElifBranch:
checkSonsLen(it, 2)
@@ -61,12 +59,12 @@ proc semDiscard(c: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 1)
n.sons[0] = semExprWithType(c, n.sons[0])
if n.sons[0].typ == nil: liMessage(n.info, errInvalidDiscard)
if n.sons[0].typ == nil: localError(n.info, errInvalidDiscard)
proc semBreakOrContinue(c: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 1)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
var s: PSym
case n.sons[0].kind
of nkIdent: s = lookUp(c, n.sons[0])
@@ -78,19 +76,20 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
incl(s.flags, sfUsed)
n.sons[0] = x
else:
liMessage(n.info, errInvalidControlFlowX, s.name.s)
localError(n.info, errInvalidControlFlowX, s.name.s)
elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0):
liMessage(n.info, errInvalidControlFlowX, renderTree(n, {renderNoComments}))
localError(n.info, errInvalidControlFlowX,
renderTree(n, {renderNoComments}))
proc semBlock(c: PContext, n: PNode): PNode =
result = n
Inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2)
openScope(c.tab) # BUGFIX: label is in the scope of block!
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
var labl = newSymS(skLabel, n.sons[0], c)
addDecl(c, labl)
n.sons[0] = newSymNode(labl) # BUGFIX
n.sons[0] = newSymNode(labl)
n.sons[1] = semStmt(c, n.sons[1])
closeScope(c.tab)
Dec(c.p.nestedBlockCounter)
@@ -132,7 +131,9 @@ proc semCase(c: PContext, n: PNode): PNode =
chckCovered = true
of tyFloat..tyFloat128, tyString:
nil
else: liMessage(n.info, errSelectorMustBeOfCertainTypes)
else:
LocalError(n.info, errSelectorMustBeOfCertainTypes)
return
for i in countup(1, sonsLen(n) - 1):
var x = n.sons[i]
case x.kind
@@ -153,7 +154,7 @@ proc semCase(c: PContext, n: PNode): PNode =
x.sons[0] = semStmtScope(c, x.sons[0])
else: illFormedAst(x)
if chckCovered and (covered != toCover(n.sons[0].typ)):
liMessage(n.info, errNotAllCasesCovered)
localError(n.info, errNotAllCasesCovered)
closeScope(c.tab)
proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
@@ -170,7 +171,7 @@ proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
else:
liMessage(n.Info, errUndeclaredFieldX, id.s)
globalError(n.Info, errUndeclaredFieldX, id.s)
proc semAsgn(c: PContext, n: PNode): PNode =
checkSonsLen(n, 2)
@@ -197,7 +198,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
var le = a.typ
if skipTypes(le, {tyGenericInst}).kind != tyVar and IsAssignable(a) == arNone:
# Direct assignment to a discriminant is allowed!
liMessage(a.info, errXCannotBeAssignedTo, renderTree(a, {renderNoComments}))
localError(a.info, errXCannotBeAssignedTo,
renderTree(a, {renderNoComments}))
else:
n.sons[1] = fitNode(c, le, n.sons[1])
fixAbstractType(c, n)
@@ -210,83 +212,84 @@ proc SemReturn(c: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 1)
if not (c.p.owner.kind in {skConverter, skMethod, skProc, skMacro}):
liMessage(n.info, errXNotAllowedHere, "\'return\'")
if (n.sons[0] != nil):
globalError(n.info, errXNotAllowedHere, "\'return\'")
if n.sons[0].kind != nkEmpty:
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
restype = c.p.owner.typ.sons[0]
if (restype != nil):
if restype != nil:
a = newNodeI(nkAsgn, n.sons[0].info)
n.sons[0] = fitNode(c, restype, n.sons[0])
# optimize away ``return result``, because it would be transformed
# to ``result = result; return``:
if (n.sons[0].kind == nkSym) and (sfResult in n.sons[0].sym.flags):
n.sons[0] = nil
n.sons[0] = ast.emptyNode
else:
if (c.p.resultSym == nil): InternalError(n.info, "semReturn")
addSon(a, semExprWithType(c, newSymNode(c.p.resultSym)))
addSon(a, n.sons[0])
n.sons[0] = a
else:
liMessage(n.info, errCannotReturnExpr)
localError(n.info, errCannotReturnExpr)
proc SemYield(c: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 1)
if (c.p.owner == nil) or (c.p.owner.kind != skIterator):
liMessage(n.info, errYieldNotAllowedHere)
if (n.sons[0] != nil):
GlobalError(n.info, errYieldNotAllowedHere)
if n.sons[0].kind != nkEmpty:
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
var restype = c.p.owner.typ.sons[0]
if (restype != nil):
if restype != nil:
n.sons[0] = fitNode(c, restype, n.sons[0])
if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
else:
liMessage(n.info, errCannotReturnExpr)
localError(n.info, errCannotReturnExpr)
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
result = fitNode(c, typ, n)
if (result.kind in {nkHiddenStdConv, nkHiddenSubConv}):
if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
changeType(result.sons[1], typ)
result = result.sons[1]
elif not sameType(result.typ, typ):
changeType(result, typ)
proc semVar(c: PContext, n: PNode): PNode =
var
length: int
a, b, def: PNode
typ, tup: PType
v: PSym
var b: PNode
result = copyNode(n)
for i in countup(0, sonsLen(n) - 1):
a = n.sons[i]
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
checkMinSonsLen(a, 3)
length = sonsLen(a)
if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil)
else: typ = nil
if a.sons[length - 1] != nil:
def = semExprWithType(c, a.sons[length - 1])
var length = sonsLen(a)
var typ: PType
if a.sons[length-2].kind != nkEmpty:
typ = semTypeNode(c, a.sons[length-2], nil)
else:
typ = nil
var def: PNode
if a.sons[length-1].kind != nkEmpty:
def = semExprWithType(c, a.sons[length-1])
# BUGFIX: ``fitNode`` is needed here!
# check type compability between def.typ and typ:
if (typ != nil): def = fitNode(c, typ, def)
if typ != nil: def = fitNode(c, typ, def)
else: typ = def.typ
else:
def = nil
def = ast.emptyNode
if not typeAllowed(typ, skVar):
liMessage(a.info, errXisNoType, typeToString(typ))
tup = skipTypes(typ, {tyGenericInst})
GlobalError(a.info, errXisNoType, typeToString(typ))
var tup = skipTypes(typ, {tyGenericInst})
if a.kind == nkVarTuple:
if tup.kind != tyTuple: liMessage(a.info, errXExpected, "tuple")
if tup.kind != tyTuple: GlobalError(a.info, errXExpected, "tuple")
if length - 2 != sonsLen(tup):
liMessage(a.info, errWrongNumberOfVariables)
GlobalError(a.info, errWrongNumberOfVariables)
b = newNodeI(nkVarTuple, a.info)
newSons(b, length)
b.sons[length - 2] = nil # no type desc
b.sons[length - 2] = ast.emptyNode # no type desc
b.sons[length - 1] = def
addSon(result, b)
for j in countup(0, length - 3):
var v: PSym
if (c.p.owner.kind == skModule):
v = semIdentWithPragma(c, skVar, a.sons[j], {sfStar, sfMinus})
incl(v.flags, sfGlobal)
@@ -298,7 +301,7 @@ proc semVar(c: PContext, n: PNode): PNode =
v.typ = typ
b = newNodeI(nkIdentDefs, a.info)
addSon(b, newSymNode(v))
addSon(b, nil) # no type description
addSon(b, ast.emptyNode) # no type description
addSon(b, copyTree(def))
addSon(result, b)
else:
@@ -306,57 +309,53 @@ proc semVar(c: PContext, n: PNode): PNode =
b.sons[j] = newSymNode(v)
proc semConst(c: PContext, n: PNode): PNode =
var
a, def, b: PNode
v: PSym
typ: PType
result = copyNode(n)
for i in countup(0, sonsLen(n) - 1):
a = n.sons[i]
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): IllFormedAst(a)
checkSonsLen(a, 3)
var v: PSym
if (c.p.owner.kind == skModule):
v = semIdentWithPragma(c, skConst, a.sons[0], {sfStar, sfMinus})
incl(v.flags, sfGlobal)
else:
v = semIdentWithPragma(c, skConst, a.sons[0], {})
if a.sons[1] != nil: typ = semTypeNode(c, a.sons[1], nil)
else: typ = nil
def = semAndEvalConstExpr(c, a.sons[2])
var typ: PType = nil
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
var def = semAndEvalConstExpr(c, a.sons[2])
# check type compability between def.typ and typ:
if (typ != nil):
def = fitRemoveHiddenConv(c, typ, def)
else:
typ = def.typ
if not typeAllowed(typ, skConst):
liMessage(a.info, errXisNoType, typeToString(typ))
GlobalError(a.info, errXisNoType, typeToString(typ))
v.typ = typ
v.ast = def # no need to copy
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
addInterfaceDecl(c, v)
b = newNodeI(nkConstDef, a.info)
var b = newNodeI(nkConstDef, a.info)
addSon(b, newSymNode(v))
addSon(b, nil) # no type description
addSon(b, ast.emptyNode) # no type description
addSon(b, copyTree(def))
addSon(result, b)
proc semFor(c: PContext, n: PNode): PNode =
var
length: int
v, countup: PSym
iter: PType
countupNode, call: PNode
result = n
checkMinSonsLen(n, 3)
length = sonsLen(n)
var length = sonsLen(n)
openScope(c.tab)
if n.sons[length - 2].kind == nkRange:
checkSonsLen(n.sons[length - 2], 2)
# convert ``in 3..5`` to ``in countup(3, 5)``
countupNode = newNodeI(nkCall, n.sons[length - 2].info)
countUp = StrTableGet(magicsys.systemModule.Tab, getIdent("countup"))
if (countUp == nil): liMessage(countupNode.info, errSystemNeeds, "countup")
if countUp == nil: GlobalError(countupNode.info, errSystemNeeds, "countup")
newSons(countupNode, 3)
countupnode.sons[0] = newSymNode(countup)
countupNode.sons[1] = n.sons[length - 2].sons[0]
@@ -366,16 +365,16 @@ proc semFor(c: PContext, n: PNode): PNode =
call = n.sons[length - 2]
if (call.kind != nkCall) or (call.sons[0].kind != nkSym) or
(call.sons[0].sym.kind != skIterator):
liMessage(n.sons[length - 2].info, errIteratorExpected)
GlobalError(n.sons[length - 2].info, errIteratorExpected)
iter = skipTypes(n.sons[length - 2].typ, {tyGenericInst})
if iter.kind != tyTuple:
if length != 3: liMessage(n.info, errWrongNumberOfVariables)
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
v = newSymS(skForVar, n.sons[0], c)
v.typ = iter
n.sons[0] = newSymNode(v)
addDecl(c, v)
else:
if length - 2 != sonsLen(iter): liMessage(n.info, errWrongNumberOfVariables)
if length-2 != sonsLen(iter): GlobalError(n.info, errWrongNumberOfVariables)
for i in countup(0, length - 3):
v = newSymS(skForVar, n.sons[i], c)
v.typ = iter.sons[i]
@@ -389,11 +388,11 @@ proc semFor(c: PContext, n: PNode): PNode =
proc semRaise(c: PContext, n: PNode): PNode =
result = n
checkSonsLen(n, 1)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
n.sons[0] = semExprWithType(c, n.sons[0])
var typ = n.sons[0].typ
if (typ.kind != tyRef) or (typ.sons[0].kind != tyObject):
liMessage(n.info, errExprCannotBeRaised)
localError(n.info, errExprCannotBeRaised)
proc semTry(c: PContext, n: PNode): PNode =
var check: TIntSet
@@ -409,12 +408,12 @@ proc semTry(c: PContext, n: PNode): PNode =
for j in countup(0, length - 2):
var typ = semTypeNode(c, a.sons[j], nil)
if typ.kind == tyRef: typ = typ.sons[0]
if (typ.kind != tyObject):
liMessage(a.sons[j].info, errExprCannotBeRaised)
if typ.kind != tyObject:
GlobalError(a.sons[j].info, errExprCannotBeRaised)
a.sons[j] = newNodeI(nkType, a.sons[j].info)
a.sons[j].typ = typ
if IntSetContainsOrIncl(check, typ.id):
liMessage(a.sons[j].info, errExceptionAlreadyHandled)
localError(a.sons[j].info, errExceptionAlreadyHandled)
elif a.kind != nkFinally:
illFormedAst(n)
# last child of an nkExcept/nkFinally branch is a statement:
@@ -423,16 +422,16 @@ proc semTry(c: PContext, n: PNode): PNode =
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
result = copyNode(n)
if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
for i in countup(0, sonsLen(n) - 1):
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if a.kind != nkIdentDefs: illFormedAst(n)
var L = sonsLen(a)
var def = a.sons[L - 1]
var def = a.sons[L-1]
var typ: PType
if a.sons[L - 2] != nil: typ = semTypeNode(c, a.sons[L - 2], nil)
elif def != nil: typ = newTypeS(tyExpr, c)
if a.sons[L-2].kind != nkEmpty: typ = semTypeNode(c, a.sons[L-2], nil)
elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
else: typ = nil
for j in countup(0, L - 3):
for j in countup(0, L-3):
var s: PSym
if (typ == nil) or (typ.kind == tyTypeDesc):
s = newSymS(skType, a.sons[j], c)
@@ -441,7 +440,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
# not a type param, but an expression
s = newSymS(skGenericParam, a.sons[j], c)
s.typ = typ
s.ast = def
if def.kind != nkEmpty: s.ast = def
s.typ.sym = s
if father != nil: addSon(father, s.typ)
s.position = i
@@ -451,7 +450,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
proc addGenericParamListToScope(c: PContext, n: PNode) =
if n.kind != nkGenericParams:
InternalError(n.info, "addGenericParamListToScope")
for i in countup(0, sonsLen(n) - 1):
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if a.kind != nkSym: internalError(a.info, "addGenericParamListToScope")
addDecl(c, a.sym)
@@ -466,7 +465,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): IllFormedAst(a)
if a.kind != nkTypeDef: IllFormedAst(a)
checkSonsLen(a, 3)
if (c.p.owner.kind == skModule):
s = semIdentWithPragma(c, skType, a.sons[0], {sfStar, sfMinus})
@@ -488,10 +487,10 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
checkSonsLen(a, 3)
if (a.sons[0].kind != nkSym): IllFormedAst(a)
s = a.sons[0].sym
if (s.magic == mNone) and (a.sons[2] == nil):
liMessage(a.info, errImplOfXexpected, s.name.s)
if (s.magic == mNone) and (a.sons[2].kind == nkEmpty):
GlobalError(a.info, errImplOfXexpected, s.name.s)
if s.magic != mNone: processMagicType(c, s)
if a.sons[1] != nil:
if a.sons[1].kind != nkEmpty:
# We have a generic type declaration here. In generic types,
# symbol lookup needs to be done here.
openScope(c.tab)
@@ -508,7 +507,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
s.typ.sons[sonsLen(s.typ) - 1] = body #debug(s.typ);
popOwner()
closeScope(c.tab)
elif a.sons[2] != nil:
elif a.sons[2].kind != nkEmpty:
# process the type's body:
pushOwner(s)
t = semTypeNode(c, a.sons[2], s.typ)
@@ -523,9 +522,8 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
if (a.sons[0].kind != nkSym): IllFormedAst(a)
s = a.sons[0].sym
# compute the type's size and check for illegal recursions:
if a.sons[1] == nil:
if (a.sons[2] != nil) and
(a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}):
if a.sons[1].kind == nkEmpty:
if (a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}):
# type aliases are hard:
#MessageOut('for type ' + typeToString(s.typ));
t = semTypeNode(c, a.sons[2], nil)
@@ -538,21 +536,23 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
s.typ = semProcTypeNode(c, n, genericParams, nil)
proc addParams(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
for i in countup(1, sonsLen(n)-1):
if (n.sons[i].kind != nkSym): InternalError(n.info, "addParams")
addDecl(c, n.sons[i].sym)
proc semBorrow(c: PContext, n: PNode, s: PSym) =
# search for the correct alias:
var b = SearchForBorrowProc(c, s, c.tab.tos - 2)
if b == nil:
liMessage(n.info, errNoSymbolToBorrowFromFound) # store the alias:
n.sons[codePos] = newSymNode(b)
if b != nil:
# store the alias:
n.sons[codePos] = newSymNode(b)
else:
LocalError(n.info, errNoSymbolToBorrowFromFound)
proc sideEffectsCheck(c: PContext, s: PSym) =
if {sfNoSideEffect, sfSideEffect} * s.flags ==
{sfNoSideEffect, sfSideEffect}:
liMessage(s.info, errXhasSideEffects, s.name.s)
LocalError(s.info, errXhasSideEffects, s.name.s)
proc addResult(c: PContext, t: PType, info: TLineInfo) =
if t != nil:
@@ -577,26 +577,27 @@ proc semLambda(c: PContext, n: PNode): PNode =
n.sons[namePos] = newSymNode(s)
pushOwner(s)
openScope(c.tab)
if (n.sons[genericParamsPos] != nil):
if (n.sons[genericParamsPos].kind != nkEmpty):
illFormedAst(n) # process parameters:
if n.sons[paramsPos] != nil:
if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[ParamsPos], nil, s)
addParams(c, s.typ.n)
else:
s.typ = newTypeS(tyProc, c)
addSon(s.typ, nil)
s.typ.callConv = ccClosure
if n.sons[pragmasPos] != nil: pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
s.options = gOptions
if n.sons[codePos] != nil:
if n.sons[codePos].kind != nkEmpty:
if sfImportc in s.flags:
liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
c.p = newProcCon(s)
addResult(c, s.typ.sons[0], n.info)
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
addResultNode(c, n)
else:
liMessage(n.info, errImplOfXexpected, s.name.s)
LocalError(n.info, errImplOfXexpected, s.name.s)
closeScope(c.tab) # close scope for parameters
popOwner()
c.p = oldP # restore
@@ -620,16 +621,16 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
s.ast = n
pushOwner(s)
openScope(c.tab)
if n.sons[genericParamsPos] != nil:
if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
gp = n.sons[genericParamsPos]
else:
gp = newNodeI(nkGenericParams, n.info)
# process parameters:
if n.sons[paramsPos] != nil:
if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[ParamsPos], gp, s)
if sonsLen(gp) > 0:
if n.sons[genericParamsPos] == nil:
if n.sons[genericParamsPos].kind == nkEmpty:
# we have a list of implicit type parameters:
n.sons[genericParamsPos] = gp
# check for semantics again:
@@ -651,16 +652,17 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
else:
addInterfaceDeclAt(c, s, c.tab.tos - 2)
if n.sons[pragmasPos] != nil: pragma(c, s, n.sons[pragmasPos], validPragmas)
if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], validPragmas)
else:
if n.sons[pragmasPos] != nil:
liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
if n.sons[pragmasPos].kind != nkEmpty:
LocalError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
if sfForward notin proto.flags:
liMessage(n.info, errAttemptToRedefineX, proto.name.s)
LocalError(n.info, errAttemptToRedefineX, proto.name.s)
excl(proto.flags, sfForward)
closeScope(c.tab) # close scope with wrong parameter symbols
openScope(c.tab) # open scope for old (correct) parameter symbols
if proto.ast.sons[genericParamsPos] != nil:
if proto.ast.sons[genericParamsPos].kind != nkEmpty:
addGenericParamListToScope(c, proto.ast.sons[genericParamsPos])
addParams(c, proto.typ.n)
proto.info = s.info # more accurate line information
@@ -674,27 +676,27 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
popOwner()
pushOwner(s)
s.options = gOptions
if n.sons[codePos] != nil:
# for DLL generation, it is annoying to check for sfImportc!
if n.sons[codePos].kind != nkEmpty:
# for DLL generation it is annoying to check for sfImportc!
if sfBorrow in s.flags:
liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
if (n.sons[genericParamsPos] == nil):
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
if n.sons[genericParamsPos].kind == nkEmpty:
c.p = newProcCon(s)
if (s.typ.sons[0] != nil) and (kind != skIterator):
addResult(c, s.typ.sons[0], n.info)
if sfImportc notin s.flags:
# no semantic checking for importc:
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n)
else:
if (s.typ.sons[0] != nil) and (kind != skIterator):
if s.typ.sons[0] != nil and kind != skIterator:
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
n.sons[codePos] = semGenericStmtScope(c, n.sons[codePos])
if sfImportc in s.flags:
# so we just ignore the body after semantic checking for importc:
n.sons[codePos] = nil
n.sons[codePos] = ast.emptyNode
else:
if proto != nil: liMessage(n.info, errImplOfXexpected, proto.name.s)
if proto != nil: LocalError(n.info, errImplOfXexpected, proto.name.s)
if {sfImportc, sfBorrow} * s.flags == {}: incl(s.flags, sfForward)
elif sfBorrow in s.flags: semBorrow(c, n, s)
sideEffectsCheck(c, s)
@@ -706,14 +708,16 @@ proc semIterator(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skIterator, iteratorPragmas)
var s = result.sons[namePos].sym
var t = s.typ
if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "iterator")
if n.sons[codePos] == nil: liMessage(n.info, errImplOfXexpected, s.name.s)
if t.sons[0] == nil:
LocalError(n.info, errXNeedsReturnType, "iterator")
if n.sons[codePos].kind == nkEmpty:
LocalError(n.info, errImplOfXexpected, s.name.s)
proc semProc(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skProc, procPragmas)
proc semMethod(c: PContext, n: PNode): PNode =
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "method")
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "method")
result = semProcAux(c, n, skMethod, methodPragmas)
var s = result.sons[namePos].sym
@@ -728,30 +732,31 @@ proc semMethod(c: PContext, n: PNode): PNode =
# XXX this not really correct way to do it: Perhaps it should be done after
# generic instantiation. Well it's good enough for now:
if not hasObjParam:
liMessage(n.info, errXNeedsParamObjectType, "method")
LocalError(n.info, errXNeedsParamObjectType, "method")
proc semConverterDef(c: PContext, n: PNode): PNode =
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "converter")
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter")
checkSonsLen(n, codePos + 1)
if n.sons[genericParamsPos] != nil:
liMessage(n.info, errNoGenericParamsAllowedForX, "converter")
if n.sons[genericParamsPos].kind != nkEmpty:
LocalError(n.info, errNoGenericParamsAllowedForX, "converter")
result = semProcAux(c, n, skConverter, converterPragmas)
var s = result.sons[namePos].sym
var t = s.typ
if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "converter")
if sonsLen(t) != 2: liMessage(n.info, errXRequiresOneArgument, "converter")
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "converter")
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "converter")
addConverter(c, s)
proc semMacroDef(c: PContext, n: PNode): PNode =
checkSonsLen(n, codePos + 1)
if n.sons[genericParamsPos] != nil:
liMessage(n.info, errNoGenericParamsAllowedForX, "macro")
if n.sons[genericParamsPos].kind != nkEmpty:
LocalError(n.info, errNoGenericParamsAllowedForX, "macro")
result = semProcAux(c, n, skMacro, macroPragmas)
var s = result.sons[namePos].sym
var t = s.typ
if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "macro")
if sonsLen(t) != 2: liMessage(n.info, errXRequiresOneArgument, "macro")
if n.sons[codePos] == nil: liMessage(n.info, errImplOfXexpected, s.name.s)
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "macro")
if n.sons[codePos].kind == nkEmpty:
LocalError(n.info, errImplOfXexpected, s.name.s)
proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info)
@@ -760,7 +765,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
var f = getModuleFile(n.sons[i])
var fileIndex = includeFilename(f)
if IntSetContainsOrIncl(c.includedFiles, fileIndex):
liMessage(n.info, errRecursiveDependencyX, f)
GlobalError(n.info, errRecursiveDependencyX, f)
addSon(result, semStmt(c, gIncludeFile(f)))
IntSetExcl(c.includedFiles, fileIndex)
@@ -771,7 +776,6 @@ proc SemStmt(c: PContext, n: PNode): PNode =
const # must be last statements in a block:
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
result = n
if n == nil: return
if nfSem in n.flags: return
case n.kind
of nkAsgn: result = semAsgn(c, n)
@@ -783,12 +787,11 @@ proc SemStmt(c: PContext, n: PNode): PNode =
var length = sonsLen(n)
for i in countup(0, length - 1):
n.sons[i] = semStmt(c, n.sons[i])
if (n.sons[i].kind in LastBlockStmts):
if n.sons[i].kind in LastBlockStmts:
for j in countup(i + 1, length - 1):
case n.sons[j].kind
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty:
nil
else: liMessage(n.sons[j].info, errStmtInvalidAfterReturn)
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil
else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
of nkRaiseStmt: result = semRaise(c, n)
of nkVarSection: result = semVar(c, n)
of nkConstSection: result = semConst(c, n)
@@ -812,15 +815,15 @@ proc SemStmt(c: PContext, n: PNode): PNode =
of nkMacroDef: result = semMacroDef(c, n)
of nkTemplateDef: result = semTemplateDef(c, n)
of nkImportStmt:
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "import")
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
result = evalImport(c, n)
of nkFromStmt:
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "from")
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
result = evalFrom(c, n)
of nkIncludeStmt:
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "include")
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
result = evalInclude(c, n)
else: liMessage(n.info, errStmtExpected)
else: LocalError(n.info, errStmtExpected)
if result == nil: InternalError(n.info, "SemStmt: result = nil")
incl(result.flags, nfSem)

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -9,8 +9,6 @@
proc isExpr(n: PNode): bool =
# returns true if ``n`` looks like an expression
if n == nil:
return false
case n.kind
of nkIdent..nkNilLit:
result = true
@@ -23,8 +21,6 @@ proc isExpr(n: PNode): bool =
proc isTypeDesc(n: PNode): bool =
# returns true if ``n`` looks like a type desc
if n == nil:
return false
case n.kind
of nkIdent, nkSym, nkType:
result = true
@@ -38,12 +34,9 @@ proc isTypeDesc(n: PNode): bool =
else: result = false
proc evalTemplateAux(c: PContext, templ, actual: PNode, sym: PSym): PNode =
var p: PSym
if templ == nil:
return nil
case templ.kind
of nkSym:
p = templ.sym
var p = templ.sym
if (p.kind == skParam) and (p.owner.id == sym.id):
result = copyTree(actual.sons[p.position])
else:
@@ -63,32 +56,38 @@ proc evalTemplateArgs(c: PContext, n: PNode, s: PSym): PNode =
var
f, a: int
arg: PNode
f = sonsLen(s.typ) # if the template has zero arguments, it can be called without ``()``
# `n` is then a nkSym or something similar
f = sonsLen(s.typ)
# if the template has zero arguments, it can be called without ``()``
# `n` is then a nkSym or something similar
case n.kind
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
a = sonsLen(n)
else: a = 0
if a > f: liMessage(n.info, errWrongNumberOfArguments)
if a > f: LocalError(n.info, errWrongNumberOfArguments)
result = copyNode(n)
for i in countup(1, f - 1):
if i < a: arg = n.sons[i]
else: arg = copyTree(s.typ.n.sons[i].sym.ast)
if arg == nil: liMessage(n.info, errWrongNumberOfArguments)
if not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}):
if arg == nil or arg.kind == nkEmpty:
LocalError(n.info, errWrongNumberOfArguments)
elif not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}):
# concrete type means semantic checking for argument:
# XXX This is horrible! Better make semantic checking use some kind
# of fixpoint iteration ...
arg = fitNode(c, s.typ.sons[i], semExprWithType(c, arg))
addSon(result, arg)
proc evalTemplate(c: PContext, n: PNode, sym: PSym): PNode =
var args: PNode
inc(evalTemplateCounter)
if evalTemplateCounter > 100:
liMessage(n.info, errTemplateInstantiationTooNested)
# replace each param by the corresponding node:
args = evalTemplateArgs(c, n, sym)
result = evalTemplateAux(c, sym.ast.sons[codePos], args, sym)
dec(evalTemplateCounter)
if evalTemplateCounter <= 100:
# replace each param by the corresponding node:
args = evalTemplateArgs(c, n, sym)
result = evalTemplateAux(c, sym.ast.sons[codePos], args, sym)
dec(evalTemplateCounter)
else:
GlobalError(n.info, errTemplateInstantiationTooNested)
result = n
proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
var
@@ -116,8 +115,6 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
toBind: var TIntSet): PNode =
var s: PSym
if n == nil:
return nil
case n.kind
of nkIdent:
if not withinBind and not IntSetContains(toBind, n.ident.id):
@@ -130,7 +127,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
else:
IntSetIncl(toBind, n.ident.id)
result = symChoice(c, n, lookup(c, n))
of nkSym..nkNilLit: # atom
of nkEmpty, nkSym..nkNilLit: # atom
result = n
of nkBind:
result = resolveTemplateParams(c, n.sons[0], true, toBind)
@@ -155,7 +152,8 @@ proc transformToExpr(n: PNode): PNode =
if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
else: n.kind = nkStmtListExpr
of nkBlockStmt:
n.kind = nkBlockExpr #nkIfStmt: n.kind := nkIfExpr; // this is not correct!
n.kind = nkBlockExpr
#nkIfStmt: n.kind := nkIfExpr; // this is not correct!
else:
nil
@@ -173,11 +171,12 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
pushOwner(s)
openScope(c.tab)
n.sons[namePos] = newSymNode(s) # check that no pragmas exist:
if n.sons[pragmasPos] != nil:
liMessage(n.info, errNoPragmasAllowedForX, "template") # check that no generic parameters exist:
if n.sons[genericParamsPos] != nil:
liMessage(n.info, errNoGenericParamsAllowedForX, "template")
if (n.sons[paramsPos] == nil):
if n.sons[pragmasPos].kind != nkEmpty:
LocalError(n.info, errNoPragmasAllowedForX, "template")
# check that no generic parameters exist:
if n.sons[genericParamsPos].kind != nkEmpty:
LocalError(n.info, errNoGenericParamsAllowedForX, "template")
if n.sons[paramsPos].kind == nkEmpty:
# use ``stmt`` as implicit result type
s.typ = newTypeS(tyProc, c)
s.typ.n = newNodeI(nkFormalParams, n.info)
@@ -185,7 +184,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
else:
semParamList(c, n.sons[ParamsPos], nil, s)
if n.sons[paramsPos].sons[0] == nil:
if n.sons[paramsPos].sons[0].kind == nkEmpty:
# use ``stmt`` as implicit result type
s.typ.sons[0] = newTypeS(tyStmt, c)
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
@@ -193,12 +192,13 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
IntSetInit(toBind)
n.sons[codePos] = resolveTemplateParams(c, n.sons[codePos], false, toBind)
if not (s.typ.sons[0].kind in {tyStmt, tyTypeDesc}):
n.sons[codePos] = transformToExpr(n.sons[codePos]) # only parameters are resolved, no type checking is performed
n.sons[codePos] = transformToExpr(n.sons[codePos])
# only parameters are resolved, no type checking is performed
closeScope(c.tab)
popOwner()
s.ast = n
result = n
if n.sons[codePos] == nil:
liMessage(n.info, errImplOfXexpected, s.name.s) # add identifier of template as a last step to not allow
# recursive templates
if n.sons[codePos].kind == nkEmpty:
LocalError(n.info, errImplOfXexpected, s.name.s)
# add identifier of template as a last step to not allow recursive templates:
addInterfaceDecl(c, s)

View File

@@ -30,10 +30,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyEnum, prev, c)
result.n = newNodeI(nkEnumTy, n.info)
checkMinSonsLen(n, 1)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
base = semTypeNode(c, n.sons[0].sons[0], nil)
if base.kind != tyEnum:
liMessage(n.sons[0].info, errInheritanceOnlyWithEnums)
localError(n.sons[0].info, errInheritanceOnlyWithEnums)
counter = lastOrd(base) + 1
addSon(result, base)
for i in countup(1, sonsLen(n) - 1):
@@ -44,10 +44,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
var strVal: PNode = nil
case skipTypes(v.typ, abstractInst).kind
of tyTuple:
if sonsLen(v) != 2: liMessage(v.info, errWrongNumberOfVariables)
if sonsLen(v) != 2: GlobalError(v.info, errWrongNumberOfVariables)
strVal = v.sons[1] # second tuple part is the string value
if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}:
liMessage(strVal.info, errStringLiteralExpected)
GlobalError(strVal.info, errStringLiteralExpected)
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
of tyString, tyCstring:
strVal = v
@@ -57,7 +57,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if i != 1:
if (x != counter): incl(result.flags, tfEnumHasWholes)
if x < counter:
liMessage(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
e.ast = strVal # might be nil
counter = x
of nkSym:
@@ -82,10 +82,10 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
addSon(result, base)
if base.kind == tyGenericInst: base = lastSon(base)
if base.kind != tyGenericParam:
if not isOrdinalType(base): liMessage(n.info, errOrdinalTypeExpected)
if lengthOrd(base) > MaxSetElements: liMessage(n.info, errSetTooBig)
if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected)
if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig)
else:
liMessage(n.info, errXExpectsOneTypeParam, "set")
GlobalError(n.info, errXExpectsOneTypeParam, "set")
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType =
@@ -94,7 +94,7 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
var base = semTypeNode(c, n.sons[1], nil)
addSon(result, base)
else:
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType =
@@ -103,38 +103,38 @@ proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
var base = semTypeNode(c, n.sons[0], nil)
addSon(result, base)
else:
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVar, prev, c)
if sonsLen(n) == 1:
var base = semTypeNode(c, n.sons[0], nil)
if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed)
if base.kind == tyVar: GlobalError(n.info, errVarVarTypeNotAllowed)
addSon(result, base)
else:
liMessage(n.info, errXExpectsOneTypeParam, "var")
GlobalError(n.info, errXExpectsOneTypeParam, "var")
proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyDistinct, prev, c)
if sonsLen(n) == 1: addSon(result, semTypeNode(c, n.sons[0], nil))
else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
else: GlobalError(n.info, errXExpectsOneTypeParam, "distinct")
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
checkSonsLen(n, 2)
result = newOrPrevType(tyRange, prev, c)
result.n = newNodeI(nkRange, n.info)
if (n.sons[0] == nil) or (n.sons[1] == nil):
liMessage(n.Info, errRangeIsEmpty)
if (n.sons[0].kind == nkEmpty) or (n.sons[1].kind == nkEmpty):
GlobalError(n.Info, errRangeIsEmpty)
var a = semConstExpr(c, n.sons[0])
var b = semConstExpr(c, n.sons[1])
if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch)
if not (a.typ.kind in
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
liMessage(n.info, errOrdinalTypeExpected)
GlobalError(n.info, errOrdinalTypeExpected)
if enumHasWholes(a.typ):
liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s)
if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty)
GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty)
addSon(result.n, a)
addSon(result.n, b)
addSon(result, b.typ)
@@ -143,9 +143,9 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
result = nil
if sonsLen(n) == 2:
if n.sons[1].kind == nkRange: result = semRangeAux(c, n.sons[1], prev)
else: liMessage(n.sons[0].info, errRangeExpected)
else: GlobalError(n.sons[0].info, errRangeExpected)
else:
liMessage(n.info, errXExpectsOneTypeParam, "range")
GlobalError(n.info, errXExpectsOneTypeParam, "range")
proc semArray(c: PContext, n: PNode, prev: PType): PType =
var indx, base: PType
@@ -158,13 +158,13 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
if indx.kind == tyGenericInst: indx = lastSon(indx)
if indx.kind != tyGenericParam:
if not isOrdinalType(indx):
liMessage(n.sons[1].info, errOrdinalTypeExpected)
GlobalError(n.sons[1].info, errOrdinalTypeExpected)
if enumHasWholes(indx):
liMessage(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
base = semTypeNode(c, n.sons[2], nil)
addSon(result, base)
else:
liMessage(n.info, errArrayExpectsTwoTypeParams)
GlobalError(n.info, errArrayExpectsTwoTypeParams)
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyOrdinal, prev, c)
@@ -172,46 +172,44 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
var base = semTypeNode(c, n.sons[1], nil)
if base.kind != tyGenericParam:
if not isOrdinalType(base):
liMessage(n.sons[1].info, errOrdinalTypeExpected)
GlobalError(n.sons[1].info, errOrdinalTypeExpected)
addSon(result, base)
else:
liMessage(n.info, errXExpectsOneTypeParam, "ordinal")
GlobalError(n.info, errXExpectsOneTypeParam, "ordinal")
proc semTypeIdent(c: PContext, n: PNode): PSym =
result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
if (result != nil):
markUsed(n, result)
if result.kind != skType: liMessage(n.info, errTypeExpected)
if result.kind != skType: GlobalError(n.info, errTypeExpected)
else:
liMessage(n.info, errIdentifierExpected)
GlobalError(n.info, errIdentifierExpected)
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
var
length, counter: int
typ: PType
check: TIntSet
a: PNode
field: PSym
result = newOrPrevType(tyTuple, prev, c)
result.n = newNodeI(nkRecList, n.info)
IntSetInit(check)
counter = 0
var counter = 0
for i in countup(0, sonsLen(n) - 1):
a = n.sons[i]
var a = n.sons[i]
if (a.kind != nkIdentDefs): IllFormedAst(a)
checkMinSonsLen(a, 3)
length = sonsLen(a)
if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil)
else: liMessage(a.info, errTypeExpected)
if a.sons[length - 1] != nil:
liMessage(a.sons[length - 1].info, errInitHereNotAllowed)
var length = sonsLen(a)
if a.sons[length - 2].kind != nkEmpty:
typ = semTypeNode(c, a.sons[length - 2], nil)
else: GlobalError(a.info, errTypeExpected)
if a.sons[length - 1].kind != nkEmpty:
GlobalError(a.sons[length - 1].info, errInitHereNotAllowed)
for j in countup(0, length - 3):
field = newSymS(skField, a.sons[j], c)
var field = newSymS(skField, a.sons[j], c)
field.typ = typ
field.position = counter
inc(counter)
if IntSetContainsOrIncl(check, field.name.id):
liMessage(a.sons[j].info, errAttemptToRedefine, field.name.s)
GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
addSon(result.n, newSymNode(field))
addSon(result, typ)
@@ -220,10 +218,11 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
elem: PType
isConcrete: bool
if (s.typ == nil) or (s.typ.kind != tyGenericBody):
liMessage(n.info, errCannotInstantiateX, s.name.s)
GlobalError(n.info, errCannotInstantiateX, s.name.s)
result = newOrPrevType(tyGenericInvokation, prev, c)
if (s.typ.containerID == 0): InternalError(n.info, "semtypes.semGeneric")
if sonsLen(n) != sonsLen(s.typ): liMessage(n.info, errWrongNumberOfArguments)
if sonsLen(n) != sonsLen(s.typ):
GlobalError(n.info, errWrongNumberOfArguments)
addSon(result, s.typ)
isConcrete = true # iterate over arguments:
for i in countup(1, sonsLen(n) - 1):
@@ -231,7 +230,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
if elem.kind == tyGenericParam: isConcrete = false
addSon(result, elem)
if isConcrete:
if s.ast == nil: liMessage(n.info, errCannotInstantiateX, s.name.s)
if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
result = instGenericContainer(c, n, result)
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
@@ -246,7 +245,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
elif (sfMinus in allowed) and (v.id == ord(wMinus)):
incl(result.flags, sfMinus)
else:
liMessage(n.sons[0].info, errInvalidVisibilityX, v.s)
GlobalError(n.sons[0].info, errInvalidVisibilityX, v.s)
else:
illFormedAst(n)
else:
@@ -271,8 +270,7 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
for i in countup(1, branchIndex - 1):
for j in countup(0, sonsLen(t.sons[i]) - 2):
if overlap(t.sons[i].sons[j], ex):
#MessageOut(renderTree(t));
liMessage(ex.info, errDuplicateCaseLabel)
LocalError(ex.info, errDuplicateCaseLabel)
proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) =
ex = semConstExpr(c, ex)
@@ -290,7 +288,7 @@ proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
semBranchExpr(c, t, b.sons[1])
if emptyRange(b.sons[0], b.sons[1]):
#MessageOut(renderTree(t));
liMessage(b.info, errRangeIsEmpty)
GlobalError(b.info, errRangeIsEmpty)
covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1
else:
semBranchExpr(c, t, branch.sons[i]) # NOT: `b`, because of var-param!
@@ -314,11 +312,11 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
incl(a.sons[0].sym.flags, sfDiscriminant)
covered = 0
typ = skipTypes(a.sons[0].Typ, abstractVar)
if not isOrdinalType(typ): liMessage(n.info, errSelectorMustBeOrdinal)
if not isOrdinalType(typ): GlobalError(n.info, errSelectorMustBeOrdinal)
if firstOrd(typ) < 0:
liMessage(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
GlobalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
if lengthOrd(typ) > 0x00007FFF:
liMessage(n.info, errLenXinvalid, a.sons[0].sym.name.s)
GlobalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
chckCovered = true
for i in countup(1, sonsLen(n) - 1):
b = copyTree(n.sons[i])
@@ -334,7 +332,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
addSon(a, b)
if chckCovered and (covered != lengthOrd(a.sons[0].typ)):
liMessage(a.info, errNotAllCasesCovered)
localError(a.info, errNotAllCasesCovered)
addSon(father, a)
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
@@ -370,8 +368,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
of nkRecList:
# attempt to keep the nesting at a sane level:
if father.kind == nkRecList: a = father
else: a = copyNode(n)
var a = if father.kind == nkRecList: father else: copyNode(n)
for i in countup(0, sonsLen(n) - 1):
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
if a != father: addSon(father, a)
@@ -381,11 +378,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
if (father.kind != nkRecList) and (length >= 4):
a = newNodeI(nkRecList, n.info)
else:
a = nil
if n.sons[length - 1] != nil:
liMessage(n.sons[length - 1].info, errInitHereNotAllowed)
if n.sons[length - 2] == nil: liMessage(n.info, errTypeExpected)
typ = semTypeNode(c, n.sons[length - 2], nil)
a = ast.emptyNode
if n.sons[length - 1].kind != nkEmpty:
localError(n.sons[length - 1].info, errInitHereNotAllowed)
if n.sons[length - 2].kind == nkEmpty:
GlobalError(n.info, errTypeExpected)
typ = semTypeNode(c, n.sons[length-2], nil)
for i in countup(0, sonsLen(n) - 3):
f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus})
f.typ = typ
@@ -396,10 +394,11 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
inc(pos)
if IntSetContainsOrIncl(check, f.name.id):
liMessage(n.sons[i].info, errAttemptToRedefine, f.name.s)
if a == nil: addSon(father, newSymNode(f))
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
if a.kind == nkEmpty: addSon(father, newSymNode(f))
else: addSon(a, newSymNode(f))
if a != nil: addSon(father, a)
if a.kind != nkEmpty: addSon(father, a)
of nkEmpty: nil
else: illFormedAst(n)
proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int,
@@ -435,11 +434,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
IntSetInit(check)
pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
checkSonsLen(n, 3)
if n.sons[1] != nil:
if n.sons[1].kind != nkEmpty:
base = semTypeNode(c, n.sons[1].sons[0], nil)
if base.kind == tyObject: addInheritedFields(c, check, pos, base)
else: liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
else:
else: localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
else:
base = nil
if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
result = newOrPrevType(tyObject, prev, c)
@@ -447,7 +446,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
result.n = newNodeI(nkRecList, n.info)
semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym)
if (base != nil) and (tfFinal in base.flags):
liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
cl: var TIntSet): PType =
@@ -509,11 +508,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
if a.kind != nkIdentDefs: IllFormedAst(a)
checkMinSonsLen(a, 3)
var length = sonsLen(a)
if a.sons[length - 2] != nil:
if a.sons[length - 2].kind != nkEmpty:
typ = paramType(c, a.sons[length - 2], genericParams, cl)
else:
typ = nil
if a.sons[length - 1] != nil:
if a.sons[length - 1].kind != nkEmpty:
def = semExprWithType(c, a.sons[length - 1])
# check type compability between def.typ and typ:
if typ != nil:
@@ -523,18 +522,18 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
else:
typ = def.typ
else:
def = nil
def = ast.emptyNode
for j in countup(0, length - 3):
var arg = newSymS(skParam, a.sons[j], c)
arg.typ = typ
arg.position = counter
inc(counter)
arg.ast = copyTree(def)
if def.kind != nkEmpty: arg.ast = copyTree(def)
if IntSetContainsOrIncl(check, arg.name.id):
liMessage(a.sons[j].info, errAttemptToRedefine, arg.name.s)
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
addSon(result.n, newSymNode(arg))
addSon(result, typ)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
result.sons[0] = paramType(c, n.sons[0], genericParams, cl)
res.typ = result.sons[0]
@@ -554,7 +553,7 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
Inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2)
openScope(c.tab)
if n.sons[0] != nil:
if n.sons[0].kind != nkEmpty:
addDecl(c, newSymS(skLabel, n.sons[0], c))
result = semStmtListType(c, n.sons[1], prev)
n.sons[1].typ = result
@@ -567,13 +566,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
s: PSym
t: PType
result = nil
if n == nil: return
case n.kind
of nkEmpty: nil
of nkTypeOfExpr:
result = semExprWithType(c, n, {efAllowType}).typ
of nkPar:
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
else: liMessage(n.info, errTypeExpected)
else: GlobalError(n.info, errTypeExpected)
of nkBracketExpr:
checkMinSonsLen(n, 2)
s = semTypeIdent(c, n.sons[0])
@@ -587,7 +586,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else: result = semGeneric(c, n, s, prev)
of nkIdent, nkDotExpr, nkAccQuoted:
s = semTypeIdent(c, n)
if s.typ == nil: liMessage(n.info, errTypeExpected)
if s.typ == nil: GlobalError(n.info, errTypeExpected)
if prev == nil:
result = s.typ
else:
@@ -604,7 +603,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = prev
markUsed(n, n.sym)
else:
liMessage(n.info, errTypeExpected)
GlobalError(n.info, errTypeExpected)
of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev)
of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev)
@@ -627,7 +626,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkBlockType:
result = semBlockType(c, n, prev)
else:
liMessage(n.info, errTypeExpected)
GlobalError(n.info, errTypeExpected)
#internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
@@ -665,5 +664,5 @@ proc processMagicType(c: PContext, m: PSym) =
of mStmt: setMagicType(m, tyStmt, 0)
of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return
else: liMessage(m.info, errTypeExpected)
else: GlobalError(m.info, errTypeExpected)

View File

@@ -443,7 +443,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
if containsGenericType(f): result.typ = getInstantiatedType(c, arg, m, f)
else: result.typ = f
if result.typ == nil: InternalError(arg.info, "implicitConv")
addSon(result, nil)
addSon(result, ast.emptyNode)
addSon(result, arg)
proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
@@ -578,7 +578,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
# named param
# check if m.callee has such a param:
if n.sons[a].sons[0].kind != nkIdent:
liMessage(n.sons[a].info, errNamedParamHasToBeIdent)
LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
m.state = csNoMatch
return
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
@@ -588,7 +588,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
return
if IntSetContainsOrIncl(marker, formal.position):
# already in namedParams:
liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch
return
m.baseTypeMatch = false
@@ -633,7 +633,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
formal = m.callee.n.sons[f].sym
if IntSetContainsOrIncl(marker, formal.position):
# already in namedParams:
liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch
return
m.baseTypeMatch = false
@@ -683,12 +683,13 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
var
o: TOverloadIter
x, y, z: TCandidate
#liMessage(n.info, warnUser, renderTree(n));
#Message(n.info, warnUser, renderTree(n))
var sym = initOverloadIter(o, c, f)
result = nil
if sym == nil: return
initCandidate(x, sym, initialBinding)
initCandidate(y, sym, initialBinding)
while sym != nil:
if sym.kind in filter:
initCandidate(z, sym, initialBinding)
@@ -711,7 +712,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
not sameMethodDispatcher(x.calleeSym, y.calleeSym):
if x.state != csMatch:
InternalError(n.info, "x.state is not csMatch")
liMessage(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
getProcHeader(x.calleeSym), getProcHeader(y.calleeSym),
x.calleeSym.Name.s])
else:
@@ -719,7 +720,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
markUsed(n, x.calleeSym)
if x.calleeSym.ast == nil:
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
if x.calleeSym.ast.sons[genericParamsPos] != nil:
if x.calleeSym.ast.sons[genericParamsPos].kind != nkEmpty:
# a generic proc!
x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info)
x.callee = x.calleeSym.typ

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -219,12 +219,11 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
newVar.owner = getCurrOwner(c)
IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
defs[j] = newSymNode(newVar).PTransNode
assert(it.sons[L-2] == nil)
assert(it.sons[L-2].kind == nkEmpty)
defs[L-1] = transform(c, it.sons[L-1])
result[i] = defs
proc hasContinue(n: PNode): bool =
if n == nil: return
case n.kind
of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
of nkContinueStmt: result = true
@@ -271,7 +270,6 @@ proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) =
transform(c, newTupleAccess(n, i))))
proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
if n == nil: return
case n.kind
of nkSym:
return transformSym(c, n)
@@ -311,8 +309,8 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
proc addVar(father, v: PNode) =
var vpart = newNodeI(nkIdentDefs, v.info)
addSon(vpart, v)
addSon(vpart, nil)
addSon(vpart, nil)
addSon(vpart, ast.emptyNode)
addSon(vpart, ast.emptyNode)
addSon(father, vpart)
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
@@ -515,7 +513,6 @@ proc getMagicOp(call: PNode): TMagic =
proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
container: PNode) =
# gather used vars for closure generation
if n == nil: return
case n.kind
of nkSym:
var s = n.sym
@@ -662,7 +659,6 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
result = transformSons(c, n)
proc transform(c: PTransf, n: PNode): PTransNode =
if n == nil: return
case n.kind
of nkSym:
return transformSym(c, n)
@@ -678,7 +674,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
of nkCaseStmt:
result = transformCase(c, n)
of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef:
if n.sons[genericParamsPos] == nil:
if n.sons[genericParamsPos].kind == nkEmpty:
n.sons[codePos] = PNode(transform(c, n.sons[codePos]))
if n.kind == nkMethodDef: methodDef(n.sons[namePos].sym)
result = PTransNode(n)
@@ -727,6 +723,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
result = PTransNode(cnst) # do not miss an optimization
proc processTransf(context: PPassContext, n: PNode): PNode =
if passes.skipCodegen(n): return n
var c = PTransf(context)
pushTransCon(c, newTransCon(getCurrOwner(c)))
result = PNode(transform(c, n))

View File

@@ -119,7 +119,7 @@ proc getOrdValue(n: PNode): biggestInt =
of nkCharLit..nkInt64Lit: result = n.intVal
of nkNilLit: result = 0
else:
liMessage(n.info, errOrdinalTypeExpected)
LocalError(n.info, errOrdinalTypeExpected)
result = 0
proc isCompatibleToCString(a: PType): bool =

0
tests/accept/compile/tgenericvariant.nim Normal file → Executable file
View File

0
tests/accept/compile/tnamedparams.nim Normal file → Executable file
View File

0
tests/accept/compile/toop.nim Normal file → Executable file
View File

View File

@@ -22,7 +22,7 @@ tcopy.nim;TEMP=C:\Programs\xyz\bin
tcountup.nim;0123456789
tcurrncy.nim;25
temit.nim;509
tenumhole;my value A1my value Bconc2valueCabc4abc
tenumhole.nim;my value A1my value Bconc2valueCabc4abc
texcsub.nim;caught!
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
tfinally.nim;came here 3
@@ -47,7 +47,7 @@ tmultim1.nim;7
tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit
tmultim3.nim;Hi derived!
tmultim4.nim;hello
tnamedenumfields;my value A0my value Bconc1valueCabc3abc
tnamedenumfields.nim;my value A0my value Bconc1valueCabc3abc
tnestif.nim;i == 2
tnestprc.nim;10
toop1.nim;34[]o 5
1 tack.nim 125
22 tcountup.nim 0123456789
23 tcurrncy.nim 25
24 temit.nim 509
25 tenumhole tenumhole.nim my value A1my value Bconc2valueCabc4abc
26 texcsub.nim caught!
27 texplicitgeneric1.nim Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
28 tfinally.nim came here 3
47 tmultim2.nim collide: unit, thing collide: unit, thing collide: thing, unit
48 tmultim3.nim Hi derived!
49 tmultim4.nim hello
50 tnamedenumfields tnamedenumfields.nim my value A0my value Bconc1valueCabc3abc
51 tnestif.nim i == 2
52 tnestprc.nim 10
53 toop1.nim 34[]o 5

0
tests/accept/run/tarraycons.nim Normal file → Executable file
View File

0
tests/accept/run/tcountup.nim Normal file → Executable file
View File

0
tests/accept/run/temit.nim Normal file → Executable file
View File

0
tests/accept/run/tenumhole.nim Normal file → Executable file
View File

0
tests/accept/run/texcsub.nim Normal file → Executable file
View File

0
tests/accept/run/tfloat3.nim Normal file → Executable file
View File

0
tests/accept/run/titer6.nim Normal file → Executable file
View File

View File

@@ -22,7 +22,7 @@ proc test(a, b: TThing) {.inline.} =
var
a: TThing
b, c: TUnit
collide(b, c) # ambiguous unit, thing or thing, unit? -> prefer unit, thing!
collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing!
test(b, c)
collide(a, b)
#OUT collide: unit, thing collide: unit, thing collide: thing, unit

0
tests/accept/run/tmultim4.nim Normal file → Executable file
View File

0
tests/accept/run/tnamedenumfields.nim Normal file → Executable file
View File

0
tests/accept/run/toprprec.nim Normal file → Executable file
View File

0
tests/gc/tthreads.nim Normal file → Executable file
View File

0
tests/reject/tarraycons.nim Normal file → Executable file
View File

0
tests/reject/tmethod.nim Normal file → Executable file
View File

0
tests/reject/tnamedparams.nim Normal file → Executable file
View File

0
tests/reject/twrongtupleaccess.nim Normal file → Executable file
View File

0
tests/testdata/jsontest2.json vendored Normal file → Executable file
View File

View File

@@ -1,7 +1,4 @@
- ban ``nil`` from the AST. This might also fix bugs concerning macros.
TODO:
* semantic checking (keep in mind incremental parsing!)
* code generators
- 'suggest'
- thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch

View File

@@ -61,6 +61,7 @@ Additions
- Added basic thread support via the ``threads`` core module and
the ``--threads:on`` command line switch.
- Added unary ``<`` for nice looking excluding upper bounds in ranges.
- Added ``math.floor``.
2010-10-20 Version 0.8.10 released

0
web/nimrod.ini Normal file → Executable file
View File