non-nil AST; continue after errors for IDE support
This commit is contained in:
parent
27dc54cbda
commit
5b28d08203
84 changed files with 678 additions and 722 deletions
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable 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
|
||||||
|
|
|
||||||
0
doc/lib.txt
Normal file → Executable file
0
doc/lib.txt
Normal file → Executable file
0
examples/httpserver2.nim
Normal file → Executable file
0
examples/httpserver2.nim
Normal file → Executable file
0
icons/koch.rc
Normal file → Executable file
0
icons/koch.rc
Normal file → Executable file
0
icons/koch.res
Normal file → Executable file
0
icons/koch.res
Normal file → Executable file
0
icons/nimrod.rc
Normal file → Executable file
0
icons/nimrod.rc
Normal file → Executable file
0
icons/nimrod.res
Normal file → Executable file
0
icons/nimrod.res
Normal file → Executable file
0
koch.nim
Normal file → Executable file
0
koch.nim
Normal file → Executable file
0
lib/core/marshal.nim
Normal file → Executable file
0
lib/core/marshal.nim
Normal file → Executable file
0
lib/core/threads.nim
Normal file → Executable file
0
lib/core/threads.nim
Normal file → Executable file
0
lib/impure/ssl.nim
Normal file → Executable file
0
lib/impure/ssl.nim
Normal file → Executable file
0
lib/pure/base64.nim
Normal file → Executable file
0
lib/pure/base64.nim
Normal file → Executable file
0
lib/pure/cookies.nim
Normal file → Executable file
0
lib/pure/cookies.nim
Normal file → Executable 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
0
lib/pure/scgi.nim
Normal file → Executable file
0
lib/pure/smtp.nim
Normal file → Executable file
0
lib/pure/smtp.nim
Normal file → Executable file
0
lib/wrappers/claro.nim
Normal file → Executable file
0
lib/wrappers/claro.nim
Normal file → Executable file
0
lib/wrappers/openssl.nim
Normal file → Executable file
0
lib/wrappers/openssl.nim
Normal file → Executable file
0
lib/wrappers/pcre.nim
Normal file → Executable file
0
lib/wrappers/pcre.nim
Normal file → Executable 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.
|
||||||
|
|
@ -45,8 +45,7 @@ proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObje
|
||||||
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 =
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 & ')')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -891,7 +891,7 @@ 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)
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
0
rod/extccomp.nim
Normal file → Executable 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.
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
@ -164,17 +156,11 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||||
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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
145
rod/msgs.nim
145
rod/msgs.nim
|
|
@ -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",
|
||||||
|
|
@ -372,8 +371,8 @@ type
|
||||||
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)}
|
||||||
|
|
@ -382,8 +381,9 @@ var
|
||||||
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)
|
|
||||||
msgContext[length] = info
|
|
||||||
|
|
||||||
proc popInfoContext() =
|
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 InternalError(info: TLineInfo, errMsg: string) =
|
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||||
|
liMessage(info, msg, arg, doAbort)
|
||||||
|
|
||||||
|
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
0
rod/nimrod.ini
Normal file → Executable file
0
rod/nimrod.nim
Normal file → Executable file
0
rod/nimrod.nim
Normal file → Executable 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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
0
rod/rodutils.nim
Normal file → Executable 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)]
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
45
rod/sem.nim
45
rod/sem.nim
|
|
@ -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,9 +166,7 @@ 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
|
|
||||||
var c = PContext(context)
|
|
||||||
result = semStmt(c, n)
|
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:
|
||||||
|
|
@ -176,9 +174,20 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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) =
|
proc checkMinSonsLen*(n: PNode, length: int) =
|
||||||
if (n == nil) or (sonsLen(n) != length): illFormedAst(n)
|
if sonsLen(n) < length: illFormedAst(n)
|
||||||
|
|
||||||
proc checkMinSonsLen(n: PNode, length: int) =
|
|
||||||
if (n == nil) or (sonsLen(n) < length): illFormedAst(n)
|
|
||||||
|
|
||||||
initIdTable(gInstTypes)
|
initIdTable(gInstTypes)
|
||||||
|
|
|
||||||
185
rod/semexprs.nim
185
rod/semexprs.nim
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
265
rod/semstmts.nim
265
rod/semstmts.nim
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
153
rod/semtypes.nim
153
rod/semtypes.nim
|
|
@ -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,10 +434,10 @@ 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")
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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
0
tests/accept/compile/tgenericvariant.nim
Normal file → Executable file
0
tests/accept/compile/tnamedparams.nim
Normal file → Executable file
0
tests/accept/compile/tnamedparams.nim
Normal file → Executable file
0
tests/accept/compile/toop.nim
Normal file → Executable file
0
tests/accept/compile/toop.nim
Normal file → Executable 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
|
||||||
|
|
|
||||||
|
0
tests/accept/run/tarraycons.nim
Normal file → Executable file
0
tests/accept/run/tarraycons.nim
Normal file → Executable file
0
tests/accept/run/tcountup.nim
Normal file → Executable file
0
tests/accept/run/tcountup.nim
Normal file → Executable file
0
tests/accept/run/temit.nim
Normal file → Executable file
0
tests/accept/run/temit.nim
Normal file → Executable file
0
tests/accept/run/tenumhole.nim
Normal file → Executable file
0
tests/accept/run/tenumhole.nim
Normal file → Executable file
0
tests/accept/run/texcsub.nim
Normal file → Executable file
0
tests/accept/run/texcsub.nim
Normal file → Executable file
0
tests/accept/run/tfloat3.nim
Normal file → Executable file
0
tests/accept/run/tfloat3.nim
Normal file → Executable file
0
tests/accept/run/titer6.nim
Normal file → Executable file
0
tests/accept/run/titer6.nim
Normal file → Executable 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
0
tests/accept/run/tmultim4.nim
Normal file → Executable file
0
tests/accept/run/tnamedenumfields.nim
Normal file → Executable file
0
tests/accept/run/tnamedenumfields.nim
Normal file → Executable file
0
tests/accept/run/toprprec.nim
Normal file → Executable file
0
tests/accept/run/toprprec.nim
Normal file → Executable file
0
tests/gc/tthreads.nim
Normal file → Executable file
0
tests/gc/tthreads.nim
Normal file → Executable file
0
tests/reject/tarraycons.nim
Normal file → Executable file
0
tests/reject/tarraycons.nim
Normal file → Executable file
0
tests/reject/tmethod.nim
Normal file → Executable file
0
tests/reject/tmethod.nim
Normal file → Executable file
0
tests/reject/tnamedparams.nim
Normal file → Executable file
0
tests/reject/tnamedparams.nim
Normal file → Executable file
0
tests/reject/twrongtupleaccess.nim
Normal file → Executable file
0
tests/reject/twrongtupleaccess.nim
Normal file → Executable file
0
tests/testdata/jsontest2.json
vendored
Normal file → Executable file
0
tests/testdata/jsontest2.json
vendored
Normal file → Executable file
5
todo.txt
5
todo.txt
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
0
web/nimrod.ini
Normal file → Executable file
Loading…
Add table
Add a link
Reference in a new issue