non-nil AST; continue after errors for IDE support

This commit is contained in:
Araq 2011-02-12 19:24:20 +01:00
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(son1, son2, ...)`` or ``nodekind(value)`` or
``nodekind(field=value)`` is used. ``nodekind(field=value)`` is used.
Some child may be missing. Then it is ``nil``. A nil child is equivalent to Some child may be missing. A missing child is a node of kind ``nnkEmpty``;
a node of kind ``nnkEmpty``. This is more or less a (useful) artifact from a child can never be nil.
the implementation. (In the compiler's implementation ``nil`` is of course
not the same as ``nnkEmpty``!)
Leaf nodes/Atoms Leaf nodes/Atoms
@ -364,7 +362,7 @@ When statement
-------------- --------------
Like the ``if`` statement, but the root has the kind ``nnkWhenStmt``. Like the ``if`` statement, but the root has the kind ``nnkWhenStmt``.
Assignment 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 random(max: int): int = return int(rand()) mod max
proc trunc*(x: float): float {.importc: "trunc", nodecl.} proc trunc*(x: float): float {.importc: "trunc", nodecl.}
proc floor*(x: float): float {.importc: "floor", nodecl.}
else: else:
proc mathrandom(): float {.importc: "Math.random", nodecl.} proc mathrandom(): float {.importc: "Math.random", nodecl.}
proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.} proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
proc random*(max: int): int = return mathfloor(mathrandom() * max) proc random*(max: int): int = return floor(mathrandom() * max)
proc randomize*() = nil proc randomize*() = nil
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.} proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
@ -208,7 +209,7 @@ else:
elif x < 0.0: elif x < 0.0:
result = -frexp(-x, exponent) result = -frexp(-x, exponent)
else: else:
var ex = mathfloor(log2(x)) var ex = floor(log2(x))
exponent = round(ex) exponent = round(ex)
result = x / pow(2.0, ex) result = x / pow(2.0, ex)
@ -227,7 +228,6 @@ else:
var y = exp(2.0*x) var y = exp(2.0*x)
return (y-1.0)/(y+1.0) return (y-1.0)/(y+1.0)
type type
TRunningStat* = object ## an accumulator for statistical data TRunningStat* = object ## an accumulator for statistical data
n*: int ## number of pushed 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 # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -44,9 +44,8 @@ proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObje
# ----------------------- str table ----------------------------------------- # ----------------------- str table -----------------------------------------
proc StrTableContains*(t: TStrTable, n: PSym): bool proc StrTableContains*(t: TStrTable, n: PSym): bool
proc StrTableAdd*(t: var TStrTable, n: PSym) proc StrTableAdd*(t: var TStrTable, n: PSym)
proc StrTableGet*(t: TStrTable, name: PIdent): 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
# the iterator scheme: # the iterator scheme:
type type
TTabIter*{.final.} = object # consider all fields here private TTabIter*{.final.} = object # consider all fields here private
@ -574,8 +573,10 @@ proc StrTableAdd(t: var TStrTable, n: PSym) =
StrTableRawInsert(t.data, n) StrTableRawInsert(t.data, n)
inc(t.counter) 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: # 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 var
h: THash h: THash
it: PSym it: PSym
@ -584,6 +585,7 @@ proc StrTableIncl(t: var TStrTable, n: PSym): bool =
it = t.data[h] it = t.data[h]
if it == nil: break if it == nil: break
if it.name.id == n.name.id: if it.name.id == n.name.id:
t.data[h] = n # overwrite it with newer definition!
return true # found it return true # found it
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
if mustRehash(len(t.data), t.counter): 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) StrTableAdd(tab.stack[tab.tos - 1], e)
proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult = 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 result = Failure
else: else:
StrTableAdd(tab.stack[at], e)
result = Success result = Success
proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult = 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)) result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = 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 = "") = proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) 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 = proc TokKindToStr*(k: TTokKind): string =
case k 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 mEcho: genEcho(p, e)
of mArrToSeq: genArrToSeq(p, e, d) of mArrToSeq: genArrToSeq(p, e, d)
of mNLen..mNError: 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) else: internalError(e.info, "genMagicExpr: " & $op)
proc genConstExpr(p: BProc, n: PNode): PRope proc genConstExpr(p: BProc, n: PNode): PRope
@ -1605,7 +1605,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
var sym = e.sym var sym = e.sym
case sym.Kind case sym.Kind
of skMethod: of skMethod:
if sym.ast.sons[codePos] == nil: if sym.ast.sons[codePos].kind == nkEmpty:
# we cannot produce code for the dispatcher yet: # we cannot produce code for the dispatcher yet:
fillProcLoc(sym) fillProcLoc(sym)
genProcPrototype(p.module, sym) genProcPrototype(p.module, sym)

View file

@ -56,22 +56,19 @@ proc genVarTuple(p: BProc, n: PNode) =
genObjectInit(p, v.typ, v.loc, true) genObjectInit(p, v.typ, v.loc, true)
proc genVarStmt(p: BProc, n: PNode) = proc genVarStmt(p: BProc, n: PNode) =
var
v: PSym
a: PNode
for i in countup(0, sonsLen(n) - 1): 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 == nkCommentStmt: continue
if a.kind == nkIdentDefs: if a.kind == nkIdentDefs:
assert(a.sons[0].kind == nkSym) assert(a.sons[0].kind == nkSym)
v = a.sons[0].sym var v = a.sons[0].sym
if sfGlobal in v.flags: if sfGlobal in v.flags:
assignGlobalVar(p, v) assignGlobalVar(p, v)
else: else:
assignLocalVar(p, v) assignLocalVar(p, v)
initVariable(p, v) # XXX: this is not required if a.sons[2] != nil, initVariable(p, v) # XXX: this is not required if a.sons[2] != nil,
# unless it is a GC'ed pointer # unless it is a GC'ed pointer
if a.sons[2] != nil: if a.sons[2].kind != nkEmpty:
genLineDir(p, a) genLineDir(p, a)
expr(p, a.sons[2], v.loc) expr(p, a.sons[2], v.loc)
genObjectInit(p, v.typ, v.loc, true) # correct position genObjectInit(p, v.typ, v.loc, true) # correct position
@ -79,13 +76,11 @@ proc genVarStmt(p: BProc, n: PNode) =
genVarTuple(p, a) genVarTuple(p, a)
proc genConstStmt(p: BProc, t: PNode) = proc genConstStmt(p: BProc, t: PNode) =
var c: PSym
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
if t.sons[i].kind == nkCommentStmt: continue if t.sons[i].kind == nkCommentStmt: continue
if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt") if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt")
c = t.sons[i].sons[0].sym # This can happen for forward consts: var c = t.sons[i].sons[0].sym
if (c.ast != nil) and (c.typ.kind in ConstantDataTypes) and if c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags):
not (lfNoDecl in c.loc.flags):
# generate the data: # generate the data:
fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown) fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
if sfImportc in c.flags: if sfImportc in c.flags:
@ -134,7 +129,7 @@ proc genIfStmt(p: BProc, n: PNode) =
proc popSafePoints(p: BProc, howMany: int) = proc popSafePoints(p: BProc, howMany: int) =
var L = p.nestedTryStmts.len 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] var stack: seq[PNode]
newSeq(stack, howMany) newSeq(stack, howMany)
for i in countup(1, howMany): for i in countup(1, howMany):
@ -154,7 +149,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
p.beforeRetNeeded = true p.beforeRetNeeded = true
popSafePoints(p, min(1, p.nestedTryStmts.len)) popSafePoints(p, min(1, p.nestedTryStmts.len))
genLineDir(p, t) 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", []) appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
proc genWhileStmt(p: BProc, t: PNode) = 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) = proc genBlock(p: BProc, t: PNode, d: var TLoc) =
inc(p.labels) inc(p.labels)
var idx = len(p.blocks) var idx = len(p.blocks)
if t.sons[0] != nil: if t.sons[0].kind != nkEmpty:
# named block? # named block?
assert(t.sons[0].kind == nkSym) assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym 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) = proc genBreakStmt(p: BProc, t: PNode) =
var idx = len(p.blocks) - 1 var idx = len(p.blocks) - 1
if t.sons[0] != nil: if t.sons[0].kind != nkEmpty:
# named break? # named break?
assert(t.sons[0].kind == nkSym) assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym var sym = t.sons[0].sym
@ -220,7 +215,7 @@ proc getRaiseFrmt(p: BProc): string =
result = "#raiseException((#E_Base*)$1, $2);$n" result = "#raiseException((#E_Base*)$1, $2);$n"
proc genRaiseStmt(p: BProc, t: PNode) = proc genRaiseStmt(p: BProc, t: PNode) =
if t.sons[0] != nil: if t.sons[0].kind != nkEmpty:
var a: TLoc var a: TLoc
InitLocExpr(p, t.sons[0], a) InitLocExpr(p, t.sons[0], a)
var e = rdLoc(a) var e = rdLoc(a)
@ -668,8 +663,6 @@ proc genStmts(p: BProc, t: PNode) =
var var
a: TLoc a: TLoc
prc: PSym prc: PSym
#assert(t <> nil);
if inCheckpoint(t.info): MessageOut(renderTree(t))
case t.kind case t.kind
of nkEmpty: of nkEmpty:
nil nil
@ -707,7 +700,7 @@ proc genStmts(p: BProc, t: PNode) =
nil nil
of nkPragma: genPragma(p, t) of nkPragma: genPragma(p, t)
of nkProcDef, nkMethodDef, nkConverterDef: of nkProcDef, nkMethodDef, nkConverterDef:
if (t.sons[genericParamsPos] == nil): if (t.sons[genericParamsPos].kind == nkEmpty):
prc = t.sons[namePos].sym prc = t.sons[namePos].sym
if (optDeadCodeElim notin gGlobalOptions and if (optDeadCodeElim notin gGlobalOptions and
sfDeadCodeElim notin getModule(prc).flags) or 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 (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
(prc.kind == skMethod): (prc.kind == skMethod):
# we have not only the header: # 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) genProc(p.module, prc)
else: internalError(t.info, "genStmts(" & $t.kind & ')') 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, proc myOpenCached(module: PSym, filename: string,
rd: PRodReader): PPassContext = rd: PRodReader): PPassContext =
if gNimDat == nil: if gNimDat == nil:
registerTypeInfoModule() registerTypeInfoModule()
#MessageOut('cgen.myOpenCached has been called ' + filename); #MessageOut('cgen.myOpenCached has been called ' + filename)
var cfile = changeFileExt(completeCFilePath(filename), cExt) var cfile = changeFileExt(completeCFilePath(filename), cExt)
var cfilenoext = changeFileExt(cfile, "") var cfilenoext = changeFileExt(cfile, "")
addFileToLink(cfilenoext) addFileToLink(cfilenoext)
registerModuleToMain(module) registerModuleToMain(module)
# XXX: this cannot be right here, initalization has to be appended during # XXX: this cannot be right here, initalization has to be appended during
# the ``myClose`` call # the ``myClose`` call
result = nil result = nil
@ -911,7 +911,7 @@ proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool =
proc myProcess(b: PPassContext, n: PNode): PNode = proc myProcess(b: PPassContext, n: PNode): PNode =
result = n result = n
if b == nil: return if b == nil or passes.skipCodegen(n): return
var m = BModule(b) var m = BModule(b)
m.initProc.options = gOptions m.initProc.options = gOptions
genStmts(m.initProc, n) genStmts(m.initProc, n)
@ -951,7 +951,7 @@ proc writeModule(m: BModule) =
proc myClose(b: PPassContext, n: PNode): PNode = proc myClose(b: PPassContext, n: PNode): PNode =
result = n result = n
if b == nil: return if b == nil or passes.skipCodegen(n): return
var m = BModule(b) var m = BModule(b)
if n != nil: if n != nil:
m.initProc.options = gOptions m.initProc.options = gOptions

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -84,7 +84,7 @@ proc stackTraceAux(x: PStackFrame) =
proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") = proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") =
messageOut("stack trace: (most recent call last)") messageOut("stack trace: (most recent call last)")
stackTraceAux(c.tos) stackTraceAux(c.tos)
liMessage(n.info, msg, arg) Fatal(n.info, msg, arg)
proc isSpecial(n: PNode): bool = proc isSpecial(n: PNode): bool =
result = (n.kind == nkExceptBranch) result = (n.kind == nkExceptBranch)
@ -414,7 +414,7 @@ proc evalEcho(c: PEvalContext, n: PNode): PNode =
proc evalExit(c: PEvalContext, n: PNode): PNode = proc evalExit(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
liMessage(n.info, hintQuitCalled) Message(n.info, hintQuitCalled)
quit(int(getOrdValue(result))) quit(int(getOrdValue(result)))
proc evalOr(c: PEvalContext, n: PNode): PNode = proc evalOr(c: PEvalContext, n: PNode): PNode =
@ -915,12 +915,12 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of mNHint: of mNHint:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
liMessage(n.info, hintUser, getStrValue(result)) Message(n.info, hintUser, getStrValue(result))
result = emptyNode result = emptyNode
of mNWarning: of mNWarning:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
liMessage(n.info, warnUser, getStrValue(result)) Message(n.info, warnUser, getStrValue(result))
result = emptyNode result = emptyNode
of mNError: of mNError:
result = evalAux(c, n.sons[1], {}) 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 # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -9,7 +9,7 @@
# This module implements Nimrod's simple filters and helpers for filters. # This module implements Nimrod's simple filters and helpers for filters.
import import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, rnimsyn llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, rnimsyn
proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream 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 # implementation
proc invalidPragma(n: PNode) = 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 = proc getArg(n: PNode, name: string, pos: int): PNode =
result = nil result = nil

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -25,9 +25,9 @@ type
close: proc (p: PPassContext, n: PNode): PNode, close: proc (p: PPassContext, n: PNode): PNode,
process: proc (p: PPassContext, topLevelStmt: 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. # 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 registerPass*(p: TPass)
proc initPass*(p: var 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. # whole program optimizations. For now, we avoid it to save a lot of memory.
proc processModule*(module: PSym, filename: string, stream: PLLStream, proc processModule*(module: PSym, filename: string, stream: PLLStream,
rd: PRodReader) 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: # the semantic checker needs these:
var var
@ -50,10 +45,21 @@ var
# implementation # 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 if (s.kind in {skMethod, skProc}) and
({sfCompilerProc, sfCompileTime} * s.flags == {}) 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 result = false
else: else:
result = true result = true

View file

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

View file

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

View file

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

View file

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

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

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # 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) result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col)
proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) = 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) = 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 = proc currInd(p: TRstParser): int =
result = p.indentStack[high(p.indentStack)] 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)) result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = 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 = "") = proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) 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) = proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
var pos = L.bufpos # use registers for pos, buf var pos = L.bufpos # use registers for pos, buf

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -30,10 +30,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyEnum, prev, c) result = newOrPrevType(tyEnum, prev, c)
result.n = newNodeI(nkEnumTy, n.info) result.n = newNodeI(nkEnumTy, n.info)
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1)
if n.sons[0] != nil: if n.sons[0].kind != nkEmpty:
base = semTypeNode(c, n.sons[0].sons[0], nil) base = semTypeNode(c, n.sons[0].sons[0], nil)
if base.kind != tyEnum: if base.kind != tyEnum:
liMessage(n.sons[0].info, errInheritanceOnlyWithEnums) localError(n.sons[0].info, errInheritanceOnlyWithEnums)
counter = lastOrd(base) + 1 counter = lastOrd(base) + 1
addSon(result, base) addSon(result, base)
for i in countup(1, sonsLen(n) - 1): 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 var strVal: PNode = nil
case skipTypes(v.typ, abstractInst).kind case skipTypes(v.typ, abstractInst).kind
of tyTuple: 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 strVal = v.sons[1] # second tuple part is the string value
if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}: if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}:
liMessage(strVal.info, errStringLiteralExpected) GlobalError(strVal.info, errStringLiteralExpected)
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
of tyString, tyCstring: of tyString, tyCstring:
strVal = v strVal = v
@ -57,7 +57,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if i != 1: if i != 1:
if (x != counter): incl(result.flags, tfEnumHasWholes) if (x != counter): incl(result.flags, tfEnumHasWholes)
if x < counter: 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 e.ast = strVal # might be nil
counter = x counter = x
of nkSym: of nkSym:
@ -82,10 +82,10 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
addSon(result, base) addSon(result, base)
if base.kind == tyGenericInst: base = lastSon(base) if base.kind == tyGenericInst: base = lastSon(base)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): liMessage(n.info, errOrdinalTypeExpected) if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected)
if lengthOrd(base) > MaxSetElements: liMessage(n.info, errSetTooBig) if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig)
else: else:
liMessage(n.info, errXExpectsOneTypeParam, "set") GlobalError(n.info, errXExpectsOneTypeParam, "set")
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType = prev: PType): PType =
@ -94,7 +94,7 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
var base = semTypeNode(c, n.sons[1], nil) var base = semTypeNode(c, n.sons[1], nil)
addSon(result, base) addSon(result, base)
else: else:
liMessage(n.info, errXExpectsOneTypeParam, kindStr) GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType = 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) var base = semTypeNode(c, n.sons[0], nil)
addSon(result, base) addSon(result, base)
else: else:
liMessage(n.info, errXExpectsOneTypeParam, kindStr) GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
proc semVarType(c: PContext, n: PNode, prev: PType): PType = proc semVarType(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVar, prev, c) result = newOrPrevType(tyVar, prev, c)
if sonsLen(n) == 1: if sonsLen(n) == 1:
var base = semTypeNode(c, n.sons[0], nil) 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) addSon(result, base)
else: else:
liMessage(n.info, errXExpectsOneTypeParam, "var") GlobalError(n.info, errXExpectsOneTypeParam, "var")
proc semDistinct(c: PContext, n: PNode, prev: PType): PType = proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyDistinct, prev, c) result = newOrPrevType(tyDistinct, prev, c)
if sonsLen(n) == 1: addSon(result, semTypeNode(c, n.sons[0], nil)) 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 = proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
if (n.kind != nkRange): InternalError(n.info, "semRangeAux") if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
checkSonsLen(n, 2) checkSonsLen(n, 2)
result = newOrPrevType(tyRange, prev, c) result = newOrPrevType(tyRange, prev, c)
result.n = newNodeI(nkRange, n.info) result.n = newNodeI(nkRange, n.info)
if (n.sons[0] == nil) or (n.sons[1] == nil): if (n.sons[0].kind == nkEmpty) or (n.sons[1].kind == nkEmpty):
liMessage(n.Info, errRangeIsEmpty) GlobalError(n.Info, errRangeIsEmpty)
var a = semConstExpr(c, n.sons[0]) var a = semConstExpr(c, n.sons[0])
var b = semConstExpr(c, n.sons[1]) 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 if not (a.typ.kind in
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}): {tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
liMessage(n.info, errOrdinalTypeExpected) GlobalError(n.info, errOrdinalTypeExpected)
if enumHasWholes(a.typ): if enumHasWholes(a.typ):
liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s) GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty) if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty)
addSon(result.n, a) addSon(result.n, a)
addSon(result.n, b) addSon(result.n, b)
addSon(result, b.typ) addSon(result, b.typ)
@ -143,9 +143,9 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
result = nil result = nil
if sonsLen(n) == 2: if sonsLen(n) == 2:
if n.sons[1].kind == nkRange: result = semRangeAux(c, n.sons[1], prev) 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: else:
liMessage(n.info, errXExpectsOneTypeParam, "range") GlobalError(n.info, errXExpectsOneTypeParam, "range")
proc semArray(c: PContext, n: PNode, prev: PType): PType = proc semArray(c: PContext, n: PNode, prev: PType): PType =
var indx, base: PType var indx, base: PType
@ -158,13 +158,13 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
if indx.kind == tyGenericInst: indx = lastSon(indx) if indx.kind == tyGenericInst: indx = lastSon(indx)
if indx.kind != tyGenericParam: if indx.kind != tyGenericParam:
if not isOrdinalType(indx): if not isOrdinalType(indx):
liMessage(n.sons[1].info, errOrdinalTypeExpected) GlobalError(n.sons[1].info, errOrdinalTypeExpected)
if enumHasWholes(indx): 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) base = semTypeNode(c, n.sons[2], nil)
addSon(result, base) addSon(result, base)
else: else:
liMessage(n.info, errArrayExpectsTwoTypeParams) GlobalError(n.info, errArrayExpectsTwoTypeParams)
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyOrdinal, prev, c) result = newOrPrevType(tyOrdinal, prev, c)
@ -172,46 +172,44 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
var base = semTypeNode(c, n.sons[1], nil) var base = semTypeNode(c, n.sons[1], nil)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): if not isOrdinalType(base):
liMessage(n.sons[1].info, errOrdinalTypeExpected) GlobalError(n.sons[1].info, errOrdinalTypeExpected)
addSon(result, base) addSon(result, base)
else: else:
liMessage(n.info, errXExpectsOneTypeParam, "ordinal") GlobalError(n.info, errXExpectsOneTypeParam, "ordinal")
proc semTypeIdent(c: PContext, n: PNode): PSym = proc semTypeIdent(c: PContext, n: PNode): PSym =
result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared}) result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
if (result != nil): if (result != nil):
markUsed(n, result) markUsed(n, result)
if result.kind != skType: liMessage(n.info, errTypeExpected) if result.kind != skType: GlobalError(n.info, errTypeExpected)
else: else:
liMessage(n.info, errIdentifierExpected) GlobalError(n.info, errIdentifierExpected)
proc semTuple(c: PContext, n: PNode, prev: PType): PType = proc semTuple(c: PContext, n: PNode, prev: PType): PType =
var var
length, counter: int
typ: PType typ: PType
check: TIntSet check: TIntSet
a: PNode
field: PSym
result = newOrPrevType(tyTuple, prev, c) result = newOrPrevType(tyTuple, prev, c)
result.n = newNodeI(nkRecList, n.info) result.n = newNodeI(nkRecList, n.info)
IntSetInit(check) IntSetInit(check)
counter = 0 var counter = 0
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = n.sons[i] var a = n.sons[i]
if (a.kind != nkIdentDefs): IllFormedAst(a) if (a.kind != nkIdentDefs): IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
length = sonsLen(a) var length = sonsLen(a)
if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil) if a.sons[length - 2].kind != nkEmpty:
else: liMessage(a.info, errTypeExpected) typ = semTypeNode(c, a.sons[length - 2], nil)
if a.sons[length - 1] != nil: else: GlobalError(a.info, errTypeExpected)
liMessage(a.sons[length - 1].info, errInitHereNotAllowed) if a.sons[length - 1].kind != nkEmpty:
GlobalError(a.sons[length - 1].info, errInitHereNotAllowed)
for j in countup(0, length - 3): 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.typ = typ
field.position = counter field.position = counter
inc(counter) inc(counter)
if IntSetContainsOrIncl(check, field.name.id): 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.n, newSymNode(field))
addSon(result, typ) addSon(result, typ)
@ -220,10 +218,11 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
elem: PType elem: PType
isConcrete: bool isConcrete: bool
if (s.typ == nil) or (s.typ.kind != tyGenericBody): 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) result = newOrPrevType(tyGenericInvokation, prev, c)
if (s.typ.containerID == 0): InternalError(n.info, "semtypes.semGeneric") 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) addSon(result, s.typ)
isConcrete = true # iterate over arguments: isConcrete = true # iterate over arguments:
for i in countup(1, sonsLen(n) - 1): 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 if elem.kind == tyGenericParam: isConcrete = false
addSon(result, elem) addSon(result, elem)
if isConcrete: 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) result = instGenericContainer(c, n, result)
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 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)): elif (sfMinus in allowed) and (v.id == ord(wMinus)):
incl(result.flags, sfMinus) incl(result.flags, sfMinus)
else: else:
liMessage(n.sons[0].info, errInvalidVisibilityX, v.s) GlobalError(n.sons[0].info, errInvalidVisibilityX, v.s)
else: else:
illFormedAst(n) illFormedAst(n)
else: else:
@ -271,8 +270,7 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
for i in countup(1, branchIndex - 1): for i in countup(1, branchIndex - 1):
for j in countup(0, sonsLen(t.sons[i]) - 2): for j in countup(0, sonsLen(t.sons[i]) - 2):
if overlap(t.sons[i].sons[j], ex): if overlap(t.sons[i].sons[j], ex):
#MessageOut(renderTree(t)); LocalError(ex.info, errDuplicateCaseLabel)
liMessage(ex.info, errDuplicateCaseLabel)
proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) = proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) =
ex = semConstExpr(c, ex) ex = semConstExpr(c, ex)
@ -290,7 +288,7 @@ proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
semBranchExpr(c, t, b.sons[1]) semBranchExpr(c, t, b.sons[1])
if emptyRange(b.sons[0], b.sons[1]): if emptyRange(b.sons[0], b.sons[1]):
#MessageOut(renderTree(t)); #MessageOut(renderTree(t));
liMessage(b.info, errRangeIsEmpty) GlobalError(b.info, errRangeIsEmpty)
covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1 covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1
else: else:
semBranchExpr(c, t, branch.sons[i]) # NOT: `b`, because of var-param! 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) incl(a.sons[0].sym.flags, sfDiscriminant)
covered = 0 covered = 0
typ = skipTypes(a.sons[0].Typ, abstractVar) 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: 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: 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 chckCovered = true
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
b = copyTree(n.sons[i]) 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) semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
addSon(a, b) addSon(a, b)
if chckCovered and (covered != lengthOrd(a.sons[0].typ)): if chckCovered and (covered != lengthOrd(a.sons[0].typ)):
liMessage(a.info, errNotAllCasesCovered) localError(a.info, errNotAllCasesCovered)
addSon(father, a) addSon(father, a)
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int, 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)) if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
of nkRecList: of nkRecList:
# attempt to keep the nesting at a sane level: # attempt to keep the nesting at a sane level:
if father.kind == nkRecList: a = father var a = if father.kind == nkRecList: father else: copyNode(n)
else: a = copyNode(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype) semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
if a != father: addSon(father, a) 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): if (father.kind != nkRecList) and (length >= 4):
a = newNodeI(nkRecList, n.info) a = newNodeI(nkRecList, n.info)
else: else:
a = nil a = ast.emptyNode
if n.sons[length - 1] != nil: if n.sons[length - 1].kind != nkEmpty:
liMessage(n.sons[length - 1].info, errInitHereNotAllowed) localError(n.sons[length - 1].info, errInitHereNotAllowed)
if n.sons[length - 2] == nil: liMessage(n.info, errTypeExpected) if n.sons[length - 2].kind == nkEmpty:
typ = semTypeNode(c, n.sons[length - 2], nil) GlobalError(n.info, errTypeExpected)
typ = semTypeNode(c, n.sons[length-2], nil)
for i in countup(0, sonsLen(n) - 3): for i in countup(0, sonsLen(n) - 3):
f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus}) f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus})
f.typ = typ 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) f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
inc(pos) inc(pos)
if IntSetContainsOrIncl(check, f.name.id): if IntSetContainsOrIncl(check, f.name.id):
liMessage(n.sons[i].info, errAttemptToRedefine, f.name.s) localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
if a == nil: addSon(father, newSymNode(f)) if a.kind == nkEmpty: addSon(father, newSymNode(f))
else: addSon(a, 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) else: illFormedAst(n)
proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int, 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) IntSetInit(check)
pos = 0 # n.sons[0] contains the pragmas (if any). We process these later... pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
checkSonsLen(n, 3) checkSonsLen(n, 3)
if n.sons[1] != nil: if n.sons[1].kind != nkEmpty:
base = semTypeNode(c, n.sons[1].sons[0], nil) base = semTypeNode(c, n.sons[1].sons[0], nil)
if base.kind == tyObject: addInheritedFields(c, check, pos, base) if base.kind == tyObject: addInheritedFields(c, check, pos, base)
else: liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects) else: localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
else: else:
base = nil base = nil
if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode") if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
result = newOrPrevType(tyObject, prev, c) result = newOrPrevType(tyObject, prev, c)
@ -447,7 +446,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
result.n = newNodeI(nkRecList, n.info) result.n = newNodeI(nkRecList, n.info)
semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym) semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym)
if (base != nil) and (tfFinal in base.flags): 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, proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
cl: var TIntSet): PType = cl: var TIntSet): PType =
@ -509,11 +508,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
if a.kind != nkIdentDefs: IllFormedAst(a) if a.kind != nkIdentDefs: IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
var length = sonsLen(a) 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) typ = paramType(c, a.sons[length - 2], genericParams, cl)
else: else:
typ = nil typ = nil
if a.sons[length - 1] != nil: if a.sons[length - 1].kind != nkEmpty:
def = semExprWithType(c, a.sons[length - 1]) def = semExprWithType(c, a.sons[length - 1])
# check type compability between def.typ and typ: # check type compability between def.typ and typ:
if typ != nil: if typ != nil:
@ -523,18 +522,18 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
else: else:
typ = def.typ typ = def.typ
else: else:
def = nil def = ast.emptyNode
for j in countup(0, length - 3): for j in countup(0, length - 3):
var arg = newSymS(skParam, a.sons[j], c) var arg = newSymS(skParam, a.sons[j], c)
arg.typ = typ arg.typ = typ
arg.position = counter arg.position = counter
inc(counter) inc(counter)
arg.ast = copyTree(def) if def.kind != nkEmpty: arg.ast = copyTree(def)
if IntSetContainsOrIncl(check, arg.name.id): 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.n, newSymNode(arg))
addSon(result, typ) addSon(result, typ)
if n.sons[0] != nil: if n.sons[0].kind != nkEmpty:
result.sons[0] = paramType(c, n.sons[0], genericParams, cl) result.sons[0] = paramType(c, n.sons[0], genericParams, cl)
res.typ = result.sons[0] res.typ = result.sons[0]
@ -554,7 +553,7 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
Inc(c.p.nestedBlockCounter) Inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab) openScope(c.tab)
if n.sons[0] != nil: if n.sons[0].kind != nkEmpty:
addDecl(c, newSymS(skLabel, n.sons[0], c)) addDecl(c, newSymS(skLabel, n.sons[0], c))
result = semStmtListType(c, n.sons[1], prev) result = semStmtListType(c, n.sons[1], prev)
n.sons[1].typ = result n.sons[1].typ = result
@ -567,13 +566,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
s: PSym s: PSym
t: PType t: PType
result = nil result = nil
if n == nil: return
case n.kind case n.kind
of nkEmpty: nil
of nkTypeOfExpr: of nkTypeOfExpr:
result = semExprWithType(c, n, {efAllowType}).typ result = semExprWithType(c, n, {efAllowType}).typ
of nkPar: of nkPar:
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
else: liMessage(n.info, errTypeExpected) else: GlobalError(n.info, errTypeExpected)
of nkBracketExpr: of nkBracketExpr:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
s = semTypeIdent(c, n.sons[0]) 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) else: result = semGeneric(c, n, s, prev)
of nkIdent, nkDotExpr, nkAccQuoted: of nkIdent, nkDotExpr, nkAccQuoted:
s = semTypeIdent(c, n) s = semTypeIdent(c, n)
if s.typ == nil: liMessage(n.info, errTypeExpected) if s.typ == nil: GlobalError(n.info, errTypeExpected)
if prev == nil: if prev == nil:
result = s.typ result = s.typ
else: else:
@ -604,7 +603,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = prev result = prev
markUsed(n, n.sym) markUsed(n, n.sym)
else: else:
liMessage(n.info, errTypeExpected) GlobalError(n.info, errTypeExpected)
of nkObjectTy: result = semObjectNode(c, n, prev) of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev) of nkTupleTy: result = semTuple(c, n, prev)
of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", 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: of nkBlockType:
result = semBlockType(c, n, prev) result = semBlockType(c, n, prev)
else: else:
liMessage(n.info, errTypeExpected) GlobalError(n.info, errTypeExpected)
#internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')'); #internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 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 mStmt: setMagicType(m, tyStmt, 0)
of mTypeDesc: setMagicType(m, tyTypeDesc, 0) of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return 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) if containsGenericType(f): result.typ = getInstantiatedType(c, arg, m, f)
else: result.typ = f else: result.typ = f
if result.typ == nil: InternalError(arg.info, "implicitConv") if result.typ == nil: InternalError(arg.info, "implicitConv")
addSon(result, nil) addSon(result, ast.emptyNode)
addSon(result, arg) addSon(result, arg)
proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, 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 # named param
# check if m.callee has such a param: # check if m.callee has such a param:
if n.sons[a].sons[0].kind != nkIdent: if n.sons[a].sons[0].kind != nkIdent:
liMessage(n.sons[a].info, errNamedParamHasToBeIdent) LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
m.state = csNoMatch m.state = csNoMatch
return return
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1) 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 return
if IntSetContainsOrIncl(marker, formal.position): if IntSetContainsOrIncl(marker, formal.position):
# already in namedParams: # already in namedParams:
liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s) LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch m.state = csNoMatch
return return
m.baseTypeMatch = false m.baseTypeMatch = false
@ -633,7 +633,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
formal = m.callee.n.sons[f].sym formal = m.callee.n.sons[f].sym
if IntSetContainsOrIncl(marker, formal.position): if IntSetContainsOrIncl(marker, formal.position):
# already in namedParams: # already in namedParams:
liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s) LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
m.state = csNoMatch m.state = csNoMatch
return return
m.baseTypeMatch = false m.baseTypeMatch = false
@ -683,12 +683,13 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
var var
o: TOverloadIter o: TOverloadIter
x, y, z: TCandidate x, y, z: TCandidate
#liMessage(n.info, warnUser, renderTree(n)); #Message(n.info, warnUser, renderTree(n))
var sym = initOverloadIter(o, c, f) var sym = initOverloadIter(o, c, f)
result = nil result = nil
if sym == nil: return if sym == nil: return
initCandidate(x, sym, initialBinding) initCandidate(x, sym, initialBinding)
initCandidate(y, sym, initialBinding) initCandidate(y, sym, initialBinding)
while sym != nil: while sym != nil:
if sym.kind in filter: if sym.kind in filter:
initCandidate(z, sym, initialBinding) initCandidate(z, sym, initialBinding)
@ -711,7 +712,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
not sameMethodDispatcher(x.calleeSym, y.calleeSym): not sameMethodDispatcher(x.calleeSym, y.calleeSym):
if x.state != csMatch: if x.state != csMatch:
InternalError(n.info, "x.state is not 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), getProcHeader(x.calleeSym), getProcHeader(y.calleeSym),
x.calleeSym.Name.s]) x.calleeSym.Name.s])
else: else:
@ -719,7 +720,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
markUsed(n, x.calleeSym) markUsed(n, x.calleeSym)
if x.calleeSym.ast == nil: if x.calleeSym.ast == nil:
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check! 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! # a generic proc!
x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info) x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info)
x.callee = x.calleeSym.typ x.callee = x.calleeSym.typ

View file

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

View file

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

View file

@ -119,7 +119,7 @@ proc getOrdValue(n: PNode): biggestInt =
of nkCharLit..nkInt64Lit: result = n.intVal of nkCharLit..nkInt64Lit: result = n.intVal
of nkNilLit: result = 0 of nkNilLit: result = 0
else: else:
liMessage(n.info, errOrdinalTypeExpected) LocalError(n.info, errOrdinalTypeExpected)
result = 0 result = 0
proc isCompatibleToCString(a: PType): bool = 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 tcountup.nim;0123456789
tcurrncy.nim;25 tcurrncy.nim;25
temit.nim;509 temit.nim;509
tenumhole;my value A1my value Bconc2valueCabc4abc tenumhole.nim;my value A1my value Bconc2valueCabc4abc
texcsub.nim;caught! texcsub.nim;caught!
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13 texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
tfinally.nim;came here 3 tfinally.nim;came here 3
@ -47,7 +47,7 @@ tmultim1.nim;7
tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit
tmultim3.nim;Hi derived! tmultim3.nim;Hi derived!
tmultim4.nim;hello tmultim4.nim;hello
tnamedenumfields;my value A0my value Bconc1valueCabc3abc tnamedenumfields.nim;my value A0my value Bconc1valueCabc3abc
tnestif.nim;i == 2 tnestif.nim;i == 2
tnestprc.nim;10 tnestprc.nim;10
toop1.nim;34[]o 5 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 var
a: TThing a: TThing
b, c: TUnit 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) test(b, c)
collide(a, b) collide(a, b)
#OUT collide: unit, thing collide: unit, thing collide: thing, unit #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. - 'suggest'
TODO:
* semantic checking (keep in mind incremental parsing!)
* code generators
- thread support: threadvar on Windows seems broken; - thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch add --deadlock_prevention:on|off switch

View file

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

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