mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-05 13:10:50 +00:00
non-nil AST; continue after errors for IDE support
This commit is contained in:
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(field=value)`` is used.
|
||||
|
||||
Some child may be missing. Then it is ``nil``. A nil child is equivalent to
|
||||
a node of kind ``nnkEmpty``. This is more or less a (useful) artifact from
|
||||
the implementation. (In the compiler's implementation ``nil`` is of course
|
||||
not the same as ``nnkEmpty``!)
|
||||
Some child may be missing. A missing child is a node of kind ``nnkEmpty``;
|
||||
a child can never be nil.
|
||||
|
||||
|
||||
Leaf nodes/Atoms
|
||||
@@ -364,7 +362,7 @@ When statement
|
||||
--------------
|
||||
|
||||
Like the ``if`` statement, but the root has the kind ``nnkWhenStmt``.
|
||||
|
||||
|
||||
|
||||
Assignment
|
||||
----------
|
||||
|
||||
0
doc/lib.txt
Normal file → Executable file
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
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 trunc*(x: float): float {.importc: "trunc", nodecl.}
|
||||
proc floor*(x: float): float {.importc: "floor", nodecl.}
|
||||
|
||||
else:
|
||||
proc mathrandom(): float {.importc: "Math.random", nodecl.}
|
||||
proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.}
|
||||
proc random*(max: int): int = return mathfloor(mathrandom() * max)
|
||||
proc floor*(x: float): float {.importc: "Math.floor", nodecl.}
|
||||
proc random*(max: int): int = return floor(mathrandom() * max)
|
||||
proc randomize*() = nil
|
||||
|
||||
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
|
||||
@@ -208,7 +209,7 @@ else:
|
||||
elif x < 0.0:
|
||||
result = -frexp(-x, exponent)
|
||||
else:
|
||||
var ex = mathfloor(log2(x))
|
||||
var ex = floor(log2(x))
|
||||
exponent = round(ex)
|
||||
result = x / pow(2.0, ex)
|
||||
|
||||
@@ -227,7 +228,6 @@ else:
|
||||
var y = exp(2.0*x)
|
||||
return (y-1.0)/(y+1.0)
|
||||
|
||||
|
||||
type
|
||||
TRunningStat* = object ## an accumulator for statistical data
|
||||
n*: int ## number of pushed data
|
||||
|
||||
0
lib/pure/scgi.nim
Normal file → Executable file
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
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -44,9 +44,8 @@ proc TableSearch*(t: TTable, key, closure: PObject, comparator: TCmpProc): PObje
|
||||
# ----------------------- str table -----------------------------------------
|
||||
proc StrTableContains*(t: TStrTable, n: PSym): bool
|
||||
proc StrTableAdd*(t: var TStrTable, n: PSym)
|
||||
proc StrTableGet*(t: TStrTable, name: PIdent): PSym
|
||||
proc StrTableIncl*(t: var TStrTable, n: PSym): bool
|
||||
# returns true if n is already in the string table
|
||||
proc StrTableGet*(t: TStrTable, name: PIdent): PSym
|
||||
|
||||
# the iterator scheme:
|
||||
type
|
||||
TTabIter*{.final.} = object # consider all fields here private
|
||||
@@ -574,8 +573,10 @@ proc StrTableAdd(t: var TStrTable, n: PSym) =
|
||||
StrTableRawInsert(t.data, n)
|
||||
inc(t.counter)
|
||||
|
||||
proc StrTableIncl(t: var TStrTable, n: PSym): bool =
|
||||
proc StrTableIncl*(t: var TStrTable, n: PSym): bool =
|
||||
# returns true if n is already in the string table:
|
||||
# It is essential that `n` is written nevertheless!
|
||||
# This way the newest redefinition is picked by the semantic analyses!
|
||||
var
|
||||
h: THash
|
||||
it: PSym
|
||||
@@ -584,6 +585,7 @@ proc StrTableIncl(t: var TStrTable, n: PSym): bool =
|
||||
it = t.data[h]
|
||||
if it == nil: break
|
||||
if it.name.id == n.name.id:
|
||||
t.data[h] = n # overwrite it with newer definition!
|
||||
return true # found it
|
||||
h = nextTry(h, high(t.data))
|
||||
if mustRehash(len(t.data), t.counter):
|
||||
@@ -661,10 +663,9 @@ proc SymTabAdd(tab: var TSymTab, e: PSym) =
|
||||
StrTableAdd(tab.stack[tab.tos - 1], e)
|
||||
|
||||
proc SymTabAddUniqueAt(tab: var TSymTab, e: PSym, at: Natural): TResult =
|
||||
if StrTableGet(tab.stack[at], e.name) != nil:
|
||||
if StrTableIncl(tab.stack[at], e):
|
||||
result = Failure
|
||||
else:
|
||||
StrTableAdd(tab.stack[at], e)
|
||||
result = Success
|
||||
|
||||
proc SymTabAddUnique(tab: var TSymTab, e: PSym): TResult =
|
||||
|
||||
@@ -130,11 +130,11 @@ proc getLineInfo*(L: TLexer): TLineInfo =
|
||||
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
|
||||
|
||||
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
|
||||
msgs.liMessage(getLineInfo(L), msg, arg)
|
||||
msgs.GenericMessage(getLineInfo(L), msg, arg)
|
||||
|
||||
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
|
||||
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
|
||||
msgs.liMessage(info, msg, arg)
|
||||
msgs.GenericMessage(info, msg, arg)
|
||||
|
||||
proc TokKindToStr*(k: TTokKind): string =
|
||||
case k
|
||||
|
||||
@@ -1439,7 +1439,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mEcho: genEcho(p, e)
|
||||
of mArrToSeq: genArrToSeq(p, e, d)
|
||||
of mNLen..mNError:
|
||||
liMessage(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s)
|
||||
localError(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s)
|
||||
else: internalError(e.info, "genMagicExpr: " & $op)
|
||||
|
||||
proc genConstExpr(p: BProc, n: PNode): PRope
|
||||
@@ -1605,7 +1605,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
||||
var sym = e.sym
|
||||
case sym.Kind
|
||||
of skMethod:
|
||||
if sym.ast.sons[codePos] == nil:
|
||||
if sym.ast.sons[codePos].kind == nkEmpty:
|
||||
# we cannot produce code for the dispatcher yet:
|
||||
fillProcLoc(sym)
|
||||
genProcPrototype(p.module, sym)
|
||||
|
||||
@@ -56,22 +56,19 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
genObjectInit(p, v.typ, v.loc, true)
|
||||
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
var
|
||||
v: PSym
|
||||
a: PNode
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind == nkIdentDefs:
|
||||
assert(a.sons[0].kind == nkSym)
|
||||
v = a.sons[0].sym
|
||||
var v = a.sons[0].sym
|
||||
if sfGlobal in v.flags:
|
||||
assignGlobalVar(p, v)
|
||||
else:
|
||||
assignLocalVar(p, v)
|
||||
initVariable(p, v) # XXX: this is not required if a.sons[2] != nil,
|
||||
# unless it is a GC'ed pointer
|
||||
if a.sons[2] != nil:
|
||||
if a.sons[2].kind != nkEmpty:
|
||||
genLineDir(p, a)
|
||||
expr(p, a.sons[2], v.loc)
|
||||
genObjectInit(p, v.typ, v.loc, true) # correct position
|
||||
@@ -79,13 +76,11 @@ proc genVarStmt(p: BProc, n: PNode) =
|
||||
genVarTuple(p, a)
|
||||
|
||||
proc genConstStmt(p: BProc, t: PNode) =
|
||||
var c: PSym
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
if t.sons[i].kind == nkCommentStmt: continue
|
||||
if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt")
|
||||
c = t.sons[i].sons[0].sym # This can happen for forward consts:
|
||||
if (c.ast != nil) and (c.typ.kind in ConstantDataTypes) and
|
||||
not (lfNoDecl in c.loc.flags):
|
||||
var c = t.sons[i].sons[0].sym
|
||||
if c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags):
|
||||
# generate the data:
|
||||
fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
|
||||
if sfImportc in c.flags:
|
||||
@@ -134,7 +129,7 @@ proc genIfStmt(p: BProc, n: PNode) =
|
||||
|
||||
proc popSafePoints(p: BProc, howMany: int) =
|
||||
var L = p.nestedTryStmts.len
|
||||
# danger of endless recursion! we workaround this here, by a temp stack
|
||||
# danger of endless recursion! we workaround this here by a temp stack
|
||||
var stack: seq[PNode]
|
||||
newSeq(stack, howMany)
|
||||
for i in countup(1, howMany):
|
||||
@@ -154,7 +149,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
||||
p.beforeRetNeeded = true
|
||||
popSafePoints(p, min(1, p.nestedTryStmts.len))
|
||||
genLineDir(p, t)
|
||||
if (t.sons[0] != nil): genStmts(p, t.sons[0])
|
||||
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
|
||||
appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
|
||||
|
||||
proc genWhileStmt(p: BProc, t: PNode) =
|
||||
@@ -185,7 +180,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||
proc genBlock(p: BProc, t: PNode, d: var TLoc) =
|
||||
inc(p.labels)
|
||||
var idx = len(p.blocks)
|
||||
if t.sons[0] != nil:
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
# named block?
|
||||
assert(t.sons[0].kind == nkSym)
|
||||
var sym = t.sons[0].sym
|
||||
@@ -202,7 +197,7 @@ proc genBlock(p: BProc, t: PNode, d: var TLoc) =
|
||||
|
||||
proc genBreakStmt(p: BProc, t: PNode) =
|
||||
var idx = len(p.blocks) - 1
|
||||
if t.sons[0] != nil:
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
# named break?
|
||||
assert(t.sons[0].kind == nkSym)
|
||||
var sym = t.sons[0].sym
|
||||
@@ -220,7 +215,7 @@ proc getRaiseFrmt(p: BProc): string =
|
||||
result = "#raiseException((#E_Base*)$1, $2);$n"
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if t.sons[0] != nil:
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
var a: TLoc
|
||||
InitLocExpr(p, t.sons[0], a)
|
||||
var e = rdLoc(a)
|
||||
@@ -668,8 +663,6 @@ proc genStmts(p: BProc, t: PNode) =
|
||||
var
|
||||
a: TLoc
|
||||
prc: PSym
|
||||
#assert(t <> nil);
|
||||
if inCheckpoint(t.info): MessageOut(renderTree(t))
|
||||
case t.kind
|
||||
of nkEmpty:
|
||||
nil
|
||||
@@ -707,7 +700,7 @@ proc genStmts(p: BProc, t: PNode) =
|
||||
nil
|
||||
of nkPragma: genPragma(p, t)
|
||||
of nkProcDef, nkMethodDef, nkConverterDef:
|
||||
if (t.sons[genericParamsPos] == nil):
|
||||
if (t.sons[genericParamsPos].kind == nkEmpty):
|
||||
prc = t.sons[namePos].sym
|
||||
if (optDeadCodeElim notin gGlobalOptions and
|
||||
sfDeadCodeElim notin getModule(prc).flags) or
|
||||
@@ -715,7 +708,7 @@ proc genStmts(p: BProc, t: PNode) =
|
||||
(sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
|
||||
(prc.kind == skMethod):
|
||||
# we have not only the header:
|
||||
if (t.sons[codePos] != nil) or (lfDynamicLib in prc.loc.flags):
|
||||
if (t.sons[codePos].kind != nkEmpty) or (lfDynamicLib in prc.loc.flags):
|
||||
genProc(p.module, prc)
|
||||
else: internalError(t.info, "genStmts(" & $t.kind & ')')
|
||||
|
||||
|
||||
10
rod/cgen.nim
10
rod/cgen.nim
@@ -890,12 +890,12 @@ proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
proc myOpenCached(module: PSym, filename: string,
|
||||
rd: PRodReader): PPassContext =
|
||||
if gNimDat == nil:
|
||||
registerTypeInfoModule()
|
||||
#MessageOut('cgen.myOpenCached has been called ' + filename);
|
||||
registerTypeInfoModule()
|
||||
#MessageOut('cgen.myOpenCached has been called ' + filename)
|
||||
var cfile = changeFileExt(completeCFilePath(filename), cExt)
|
||||
var cfilenoext = changeFileExt(cfile, "")
|
||||
addFileToLink(cfilenoext)
|
||||
registerModuleToMain(module)
|
||||
registerModuleToMain(module)
|
||||
# XXX: this cannot be right here, initalization has to be appended during
|
||||
# the ``myClose`` call
|
||||
result = nil
|
||||
@@ -911,7 +911,7 @@ proc shouldRecompile(code: PRope, cfile, cfilenoext: string): bool =
|
||||
|
||||
proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
if b == nil: return
|
||||
if b == nil or passes.skipCodegen(n): return
|
||||
var m = BModule(b)
|
||||
m.initProc.options = gOptions
|
||||
genStmts(m.initProc, n)
|
||||
@@ -951,7 +951,7 @@ proc writeModule(m: BModule) =
|
||||
|
||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
if b == nil: return
|
||||
if b == nil or passes.skipCodegen(n): return
|
||||
var m = BModule(b)
|
||||
if n != nil:
|
||||
m.initProc.options = gOptions
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This module implements code generation for multi methods.
|
||||
## This module implements code generation for multi methods.
|
||||
|
||||
import
|
||||
options, ast, astalgo, msgs, idents, rnimsyn, types, magicsys
|
||||
|
||||
proc methodDef*(s: PSym)
|
||||
proc methodCall*(n: PNode): PNode
|
||||
proc generateMethodDispatchers*(): PNode
|
||||
# implementation
|
||||
|
||||
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
||||
var
|
||||
dest, source: PType
|
||||
@@ -40,7 +35,7 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc methodCall(n: PNode): PNode =
|
||||
proc methodCall*(n: PNode): PNode =
|
||||
var disp: PSym
|
||||
result = n
|
||||
disp = lastSon(result.sons[0].sym.ast).sym
|
||||
@@ -76,7 +71,7 @@ proc sameMethodBucket(a, b: PSym): bool =
|
||||
return
|
||||
result = true
|
||||
|
||||
proc methodDef(s: PSym) =
|
||||
proc methodDef*(s: PSym) =
|
||||
var
|
||||
L, q: int
|
||||
disp: PSym
|
||||
@@ -86,12 +81,12 @@ proc methodDef(s: PSym) =
|
||||
add(gMethods[i], s) # store a symbol to the dispatcher:
|
||||
addSon(s.ast, lastSon(gMethods[i][0].ast))
|
||||
return
|
||||
add(gMethods, @ [s]) # create a new dispatcher:
|
||||
add(gMethods, @[s]) # create a new dispatcher:
|
||||
disp = copySym(s)
|
||||
disp.typ = copyType(disp.typ, disp.typ.owner, false)
|
||||
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
|
||||
disp.ast = copyTree(s.ast)
|
||||
disp.ast.sons[codePos] = nil
|
||||
disp.ast.sons[codePos] = ast.emptyNode
|
||||
if s.typ.sons[0] != nil:
|
||||
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
|
||||
addSon(s.ast, newSymNode(disp))
|
||||
@@ -188,7 +183,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
|
||||
addSon(disp, a)
|
||||
result.ast.sons[codePos] = disp
|
||||
|
||||
proc generateMethodDispatchers(): PNode =
|
||||
proc generateMethodDispatchers*(): PNode =
|
||||
var relevantCols: TIntSet
|
||||
result = newNode(nkStmtList)
|
||||
for bucket in countup(0, len(gMethods) - 1):
|
||||
|
||||
@@ -152,7 +152,7 @@ proc writeCommandLineUsage() =
|
||||
helpWritten = true
|
||||
|
||||
proc InvalidCmdLineOption(pass: TCmdLinePass, switch: string, info: TLineInfo) =
|
||||
liMessage(info, errInvalidCmdLineOption, switch)
|
||||
LocalError(info, errInvalidCmdLineOption, switch)
|
||||
|
||||
proc splitSwitch(switch: string, cmd, arg: var string, pass: TCmdLinePass,
|
||||
info: TLineInfo) =
|
||||
@@ -174,20 +174,20 @@ proc ProcessOnOffSwitch(op: TOptions, arg: string, pass: TCmdlinePass,
|
||||
case whichKeyword(arg)
|
||||
of wOn: gOptions = gOptions + op
|
||||
of wOff: gOptions = gOptions - op
|
||||
else: liMessage(info, errOnOrOffExpectedButXFound, arg)
|
||||
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
|
||||
|
||||
proc ProcessOnOffSwitchG(op: TGlobalOptions, arg: string, pass: TCmdlinePass,
|
||||
info: TLineInfo) =
|
||||
case whichKeyword(arg)
|
||||
of wOn: gGlobalOptions = gGlobalOptions + op
|
||||
of wOff: gGlobalOptions = gGlobalOptions - op
|
||||
else: liMessage(info, errOnOrOffExpectedButXFound, arg)
|
||||
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
|
||||
|
||||
proc ExpectArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
if arg == "": liMessage(info, errCmdLineArgExpected, switch)
|
||||
if arg == "": LocalError(info, errCmdLineArgExpected, switch)
|
||||
|
||||
proc ExpectNoArg(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
if arg != "": liMessage(info, errCmdLineNoArgExpected, switch)
|
||||
if arg != "": LocalError(info, errCmdLineNoArgExpected, switch)
|
||||
|
||||
proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
|
||||
info: TLineInfo) =
|
||||
@@ -212,7 +212,7 @@ proc ProcessSpecificNote(arg: string, state: TSpecialWord, pass: TCmdlinePass,
|
||||
case whichKeyword(copy(arg, i))
|
||||
of wOn: incl(gNotes, n)
|
||||
of wOff: excl(gNotes, n)
|
||||
else: liMessage(info, errOnOrOffExpectedButXFound, arg)
|
||||
else: LocalError(info, errOnOrOffExpectedButXFound, arg)
|
||||
|
||||
proc processCompile(filename: string) =
|
||||
var found = findFile(filename)
|
||||
@@ -228,13 +228,13 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
||||
of wBoehm: result = contains(gGlobalOptions, optBoehmGC)
|
||||
of wRefc: result = contains(gGlobalOptions, optRefcGC)
|
||||
of wNone: result = gGlobalOptions * {optBoehmGC, optRefcGC} == {}
|
||||
else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
of wOpt:
|
||||
case whichKeyword(arg)
|
||||
of wSpeed: result = contains(gOptions, optOptimizeSpeed)
|
||||
of wSize: result = contains(gOptions, optOptimizeSize)
|
||||
of wNone: result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {}
|
||||
else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
|
||||
else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
|
||||
else: InvalidCmdLineOption(passCmd1, switch, info)
|
||||
|
||||
proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
||||
@@ -285,7 +285,7 @@ proc addPathRec(dir: string, info: TLineInfo) =
|
||||
if k == pcDir and p[pos] != '.':
|
||||
addPathRec(p, info)
|
||||
if not contains(options.searchPaths, p):
|
||||
liMessage(info, hintPath, p)
|
||||
Message(info, hintPath, p)
|
||||
lists.PrependStr(options.searchPaths, p)
|
||||
|
||||
proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
@@ -346,7 +346,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
excl(gGlobalOptions, optRefcGC)
|
||||
excl(gGlobalOptions, optBoehmGC)
|
||||
defineSymbol("nogc")
|
||||
else: liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
else: LocalError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||
of wWarnings, wW: ProcessOnOffSwitch({optWarns}, arg, pass, info)
|
||||
of wWarning: ProcessSpecificNote(arg, wWarning, pass, info)
|
||||
of wHint: ProcessSpecificNote(arg, wHint, pass, info)
|
||||
@@ -388,7 +388,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
of wNone:
|
||||
excl(gOptions, optOptimizeSpeed)
|
||||
excl(gOptions, optOptimizeSize)
|
||||
else: liMessage(info, errNoneSpeedOrSizeExpectedButXFound, arg)
|
||||
else: LocalError(info, errNoneSpeedOrSizeExpectedButXFound, arg)
|
||||
of wApp:
|
||||
expectArg(switch, arg, pass, info)
|
||||
case whichKeyword(arg)
|
||||
@@ -401,7 +401,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
incl(gGlobalOptions, optGenDynLib)
|
||||
excl(gGlobalOptions, optGenGuiApp)
|
||||
defineSymbol("library")
|
||||
else: liMessage(info, errGuiConsoleOrLibExpectedButXFound, arg)
|
||||
else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
|
||||
of wListDef:
|
||||
expectNoArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: condsyms.listSymbols()
|
||||
@@ -427,8 +427,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
expectArg(switch, arg, pass, info)
|
||||
if (pass == passCmd1):
|
||||
theOS = platform.NameToOS(arg)
|
||||
if theOS == osNone: liMessage(info, errUnknownOS, arg)
|
||||
if theOS != platform.hostOS:
|
||||
if theOS == osNone: LocalError(info, errUnknownOS, arg)
|
||||
elif theOS != platform.hostOS:
|
||||
setTarget(theOS, targetCPU)
|
||||
incl(gGlobalOptions, optCompileOnly)
|
||||
condsyms.InitDefines()
|
||||
@@ -436,8 +436,8 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
expectArg(switch, arg, pass, info)
|
||||
if (pass == passCmd1):
|
||||
cpu = platform.NameToCPU(arg)
|
||||
if cpu == cpuNone: liMessage(info, errUnknownCPU, arg)
|
||||
if cpu != platform.hostCPU:
|
||||
if cpu == cpuNone: LocalError(info, errUnknownCPU, arg)
|
||||
elif cpu != platform.hostCPU:
|
||||
setTarget(targetOS, cpu)
|
||||
incl(gGlobalOptions, optCompileOnly)
|
||||
condsyms.InitDefines()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -547,7 +547,7 @@ proc genRaiseStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
a: TCompRes
|
||||
typ: PType
|
||||
genLineDir(p, n, r)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
gen(p, n.sons[0], a)
|
||||
if a.com != nil: appf(r.com, "$1;$n", [a.com])
|
||||
typ = skipTypes(n.sons[0].typ, abstractPtrs)
|
||||
@@ -610,7 +610,7 @@ proc genBlock(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
sym: PSym
|
||||
inc(p.unique)
|
||||
idx = len(p.blocks)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
# named block?
|
||||
if (n.sons[0].kind != nkSym): InternalError(n.info, "genBlock")
|
||||
sym = n.sons[0].sym
|
||||
@@ -633,7 +633,7 @@ proc genBreakStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
sym: PSym
|
||||
genLineDir(p, n, r)
|
||||
idx = len(p.blocks) - 1
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
# named break?
|
||||
assert(n.sons[0].kind == nkSym)
|
||||
sym = n.sons[0].sym
|
||||
@@ -991,7 +991,7 @@ proc genVarInit(p: var TProc, v: PSym, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
a: TCompRes
|
||||
s: PRope
|
||||
if n == nil:
|
||||
if n.kind == nkEmpty:
|
||||
appf(r.com, "var $1 = $2;$n",
|
||||
[mangleName(v), createVar(p, v.typ, isIndirect(v))])
|
||||
else:
|
||||
@@ -1135,7 +1135,7 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
of mExcl: binaryStmt(p, n, r, "", "delete $1[$2]")
|
||||
of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
|
||||
of mNLen..mNError:
|
||||
liMessage(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
|
||||
localError(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
|
||||
of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
|
||||
of mEcho: genEcho(p, n, r)
|
||||
else:
|
||||
@@ -1231,7 +1231,7 @@ proc genReturnStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
var a: TCompRes
|
||||
if p.procDef == nil: InternalError(n.info, "genReturnStmt")
|
||||
p.BeforeRetNeeded = true
|
||||
if (n.sons[0] != nil):
|
||||
if (n.sons[0].kind != nkEmpty):
|
||||
genStmt(p, n.sons[0], a)
|
||||
if a.com != nil: appf(r.com, "$1;$n", mergeStmt(a))
|
||||
else:
|
||||
@@ -1297,7 +1297,7 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
r.com = nil
|
||||
r.res = nil
|
||||
case n.kind
|
||||
of nkNilLit: nil
|
||||
of nkNilLit, nkEmpty: nil
|
||||
of nkStmtList:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
genStmt(p, n.sons[i], a)
|
||||
@@ -1324,9 +1324,9 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma:
|
||||
nil
|
||||
of nkProcDef, nkMethodDef, nkConverterDef:
|
||||
if (n.sons[genericParamsPos] == nil):
|
||||
if (n.sons[genericParamsPos].kind == nkEmpty):
|
||||
var prc = n.sons[namePos].sym
|
||||
if (n.sons[codePos] != nil) and not (lfNoDecl in prc.loc.flags):
|
||||
if (n.sons[codePos].kind != nkEmpty) and not (lfNoDecl in prc.loc.flags):
|
||||
genProc(p, n, r)
|
||||
else:
|
||||
discard mangleName(prc)
|
||||
@@ -1391,6 +1391,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
of nkCStringToString: convCStrToStr(p, n, r)
|
||||
of nkPassAsOpenArray: gen(p, n.sons[0], r)
|
||||
of nkStmtListExpr: genStmtListExpr(p, n, r)
|
||||
of nkEmpty: nil
|
||||
else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
|
||||
|
||||
var globals: PGlobals
|
||||
@@ -1416,6 +1417,7 @@ proc genModule(p: var TProc, n: PNode, r: var TCompRes) =
|
||||
makeCString(toFilename(p.module.module.info)), r.com])
|
||||
|
||||
proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
if passes.skipCodegen(n): return n
|
||||
var
|
||||
p: TProc
|
||||
r: TCompRes
|
||||
@@ -1428,6 +1430,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
app(p.globals.code, mergeStmt(r))
|
||||
|
||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||
if passes.skipCodegen(n): return n
|
||||
result = myProcess(b, n)
|
||||
var m = BModule(b)
|
||||
if sfMainModule in m.module.flags:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -84,7 +84,7 @@ proc stackTraceAux(x: PStackFrame) =
|
||||
proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") =
|
||||
messageOut("stack trace: (most recent call last)")
|
||||
stackTraceAux(c.tos)
|
||||
liMessage(n.info, msg, arg)
|
||||
Fatal(n.info, msg, arg)
|
||||
|
||||
proc isSpecial(n: PNode): bool =
|
||||
result = (n.kind == nkExceptBranch)
|
||||
@@ -414,7 +414,7 @@ proc evalEcho(c: PEvalContext, n: PNode): PNode =
|
||||
proc evalExit(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
liMessage(n.info, hintQuitCalled)
|
||||
Message(n.info, hintQuitCalled)
|
||||
quit(int(getOrdValue(result)))
|
||||
|
||||
proc evalOr(c: PEvalContext, n: PNode): PNode =
|
||||
@@ -915,12 +915,12 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
of mNHint:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
liMessage(n.info, hintUser, getStrValue(result))
|
||||
Message(n.info, hintUser, getStrValue(result))
|
||||
result = emptyNode
|
||||
of mNWarning:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
liMessage(n.info, warnUser, getStrValue(result))
|
||||
Message(n.info, warnUser, getStrValue(result))
|
||||
result = emptyNode
|
||||
of mNError:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
|
||||
0
rod/extccomp.nim
Normal file → Executable file
0
rod/extccomp.nim
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
# This module implements Nimrod's simple filters and helpers for filters.
|
||||
|
||||
import
|
||||
import
|
||||
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, rnimsyn
|
||||
|
||||
proc filterReplace*(stdin: PLLStream, filename: string, call: PNode): PLLStream
|
||||
@@ -21,7 +21,7 @@ proc boolArg*(n: PNode, name: string, pos: int, default: bool): bool
|
||||
# implementation
|
||||
|
||||
proc invalidPragma(n: PNode) =
|
||||
liMessage(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
|
||||
LocalError(n.info, errXNotAllowedHere, renderTree(n, {renderNoComments}))
|
||||
|
||||
proc getArg(n: PNode, name: string, pos: int): PNode =
|
||||
result = nil
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -22,7 +22,7 @@ proc getModuleFile*(n: PNode): string
|
||||
proc findModule(info: TLineInfo, modulename: string): string =
|
||||
# returns path to module
|
||||
result = options.FindFile(AddFileExt(modulename, nimExt))
|
||||
if result == "": liMessage(info, errCannotOpenFile, modulename)
|
||||
if result == "": Fatal(info, errCannotOpenFile, modulename)
|
||||
|
||||
proc getModuleFile(n: PNode): string =
|
||||
case n.kind
|
||||
@@ -73,7 +73,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
proc importSymbol(c: PContext, ident: PNode, fromMod: PSym) =
|
||||
if (ident.kind != nkIdent): InternalError(ident.info, "importSymbol")
|
||||
var s = StrTableGet(fromMod.tab, ident.ident)
|
||||
if s == nil: liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s)
|
||||
if s == nil: GlobalError(ident.info, errUndeclaredIdentifier, ident.ident.s)
|
||||
if s.kind == skStub: loadStub(s)
|
||||
if not (s.Kind in ExportableSymKinds):
|
||||
InternalError(ident.info, "importSymbol: 2")
|
||||
@@ -106,7 +106,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
|
||||
var f = getModuleFile(n.sons[i])
|
||||
var m = gImportModule(f)
|
||||
if sfDeprecated in m.flags:
|
||||
liMessage(n.sons[i].info, warnDeprecated, m.name.s)
|
||||
Message(n.sons[i].info, warnDeprecated, m.name.s)
|
||||
# ``addDecl`` needs to be done before ``importAllSymbols``!
|
||||
addDecl(c, m) # add symbol to symbol table of module
|
||||
importAllSymbols(c, m)
|
||||
|
||||
@@ -35,24 +35,24 @@ proc CloseScope*(tab: var TSymTab) =
|
||||
s = InitTabIter(it, tab.stack[tab.tos - 1])
|
||||
while s != nil:
|
||||
if sfForward in s.flags:
|
||||
liMessage(s.info, errImplOfXexpected, getSymRepr(s))
|
||||
LocalError(s.info, errImplOfXexpected, getSymRepr(s))
|
||||
elif ({sfUsed, sfInInterface} * s.flags == {}) and
|
||||
(optHints in s.options): # BUGFIX: check options in s!
|
||||
if not (s.kind in {skForVar, skParam, skMethod, skUnknown}):
|
||||
liMessage(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
|
||||
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
|
||||
s = NextIter(it, tab.stack[tab.tos - 1])
|
||||
astalgo.rawCloseScope(tab)
|
||||
|
||||
proc AddSym*(t: var TStrTable, n: PSym) =
|
||||
if StrTableIncl(t, n): liMessage(n.info, errAttemptToRedefine, n.name.s)
|
||||
if StrTableIncl(t, n): LocalError(n.info, errAttemptToRedefine, n.name.s)
|
||||
|
||||
proc addDecl*(c: PContext, sym: PSym) =
|
||||
if SymTabAddUnique(c.tab, sym) == Failure:
|
||||
liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
|
||||
LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
|
||||
|
||||
proc addDeclAt*(c: PContext, sym: PSym, at: Natural) =
|
||||
if SymTabAddUniqueAt(c.tab, sym, at) == Failure:
|
||||
liMessage(sym.info, errAttemptToRedefine, sym.Name.s)
|
||||
LocalError(sym.info, errAttemptToRedefine, sym.Name.s)
|
||||
|
||||
proc AddInterfaceDeclAux(c: PContext, sym: PSym) =
|
||||
if (sfInInterface in sym.flags):
|
||||
@@ -66,12 +66,13 @@ proc addInterfaceDeclAt*(c: PContext, sym: PSym, at: Natural) =
|
||||
AddInterfaceDeclAux(c, sym)
|
||||
|
||||
proc addOverloadableSymAt*(c: PContext, fn: PSym, at: Natural) =
|
||||
if not (fn.kind in OverloadableSyms):
|
||||
if fn.kind notin OverloadableSyms:
|
||||
InternalError(fn.info, "addOverloadableSymAt")
|
||||
var check = StrTableGet(c.tab.stack[at], fn.name)
|
||||
if (check != nil) and not (check.Kind in OverloadableSyms):
|
||||
liMessage(fn.info, errAttemptToRedefine, fn.Name.s)
|
||||
SymTabAddAt(c.tab, fn, at)
|
||||
if check != nil and check.Kind notin OverloadableSyms:
|
||||
LocalError(fn.info, errAttemptToRedefine, fn.Name.s)
|
||||
else:
|
||||
SymTabAddAt(c.tab, fn, at)
|
||||
|
||||
proc addInterfaceDecl*(c: PContext, sym: PSym) =
|
||||
# it adds the symbol to the interface if appropriate
|
||||
@@ -89,17 +90,13 @@ proc lookUp*(c: PContext, n: PNode): PSym =
|
||||
of nkAccQuoted:
|
||||
result = lookup(c, n.sons[0])
|
||||
of nkSym:
|
||||
#
|
||||
# result := SymtabGet(c.Tab, n.sym.name);
|
||||
# if result = nil then
|
||||
# liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s);
|
||||
result = n.sym
|
||||
of nkIdent:
|
||||
result = SymtabGet(c.Tab, n.ident)
|
||||
if result == nil: liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
else: InternalError(n.info, "lookUp")
|
||||
if IntSetContains(c.AmbiguousSymbols, result.id):
|
||||
liMessage(n.info, errUseQualifier, result.name.s)
|
||||
LocalError(n.info, errUseQualifier, result.name.s)
|
||||
if result.kind == skStub: loadStub(result)
|
||||
|
||||
type
|
||||
@@ -111,20 +108,15 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
of nkIdent:
|
||||
result = SymtabGet(c.Tab, n.ident)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
elif checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols,
|
||||
result.id):
|
||||
liMessage(n.info, errUseQualifier, n.ident.s)
|
||||
GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
elif checkAmbiguity in flags and result != nil and
|
||||
IntSetContains(c.AmbiguousSymbols, result.id):
|
||||
LocalError(n.info, errUseQualifier, n.ident.s)
|
||||
of nkSym:
|
||||
#
|
||||
# result = SymtabGet(c.Tab, n.sym.name)
|
||||
# if result == nil:
|
||||
# liMessage(n.info, errUndeclaredIdentifier, n.sym.name.s)
|
||||
# else
|
||||
result = n.sym
|
||||
if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols,
|
||||
result.id):
|
||||
liMessage(n.info, errUseQualifier, n.sym.name.s)
|
||||
LocalError(n.info, errUseQualifier, n.sym.name.s)
|
||||
of nkDotExpr:
|
||||
result = nil
|
||||
var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
|
||||
@@ -141,9 +133,10 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
else:
|
||||
result = StrTableGet(m.tab, ident)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
liMessage(n.sons[1].info, errUndeclaredIdentifier, ident.s)
|
||||
GlobalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
|
||||
elif checkUndeclared in flags:
|
||||
liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
|
||||
GlobalError(n.sons[1].info, errIdentifierExpected,
|
||||
renderTree(n.sons[1]))
|
||||
of nkAccQuoted:
|
||||
result = QualifiedLookup(c, n.sons[0], flags)
|
||||
else:
|
||||
@@ -151,7 +144,6 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
if (result != nil) and (result.kind == skStub): loadStub(result)
|
||||
|
||||
proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
var ident: PIdent
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
@@ -163,18 +155,12 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident)
|
||||
of nkSym:
|
||||
result = n.sym
|
||||
o.mode = oimDone
|
||||
# o.stackPtr = c.tab.tos
|
||||
# o.mode = oimNoQualifier
|
||||
# while result == nil:
|
||||
# dec(o.stackPtr)
|
||||
# if o.stackPtr < 0: break
|
||||
# result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.sym.name)
|
||||
o.mode = oimDone
|
||||
of nkDotExpr:
|
||||
o.mode = oimOtherModule
|
||||
o.m = qualifiedLookUp(c, n.sons[0])
|
||||
if (o.m != nil) and (o.m.kind == skModule):
|
||||
ident = nil
|
||||
var ident: PIdent = nil
|
||||
if (n.sons[1].kind == nkIdent):
|
||||
ident = n.sons[1].ident
|
||||
elif (n.sons[1].kind == nkAccQuoted) and
|
||||
@@ -188,7 +174,8 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
else:
|
||||
result = InitIdentIter(o.it, o.m.tab, ident)
|
||||
else:
|
||||
liMessage(n.sons[1].info, errIdentifierExpected, renderTree(n.sons[1]))
|
||||
GlobalError(n.sons[1].info, errIdentifierExpected,
|
||||
renderTree(n.sons[1]))
|
||||
of nkAccQuoted:
|
||||
result = InitOverloadIter(o, c, n.sons[0])
|
||||
of nkSymChoice:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -73,7 +73,7 @@ proc importModule(filename: string): PSym =
|
||||
# compile the module
|
||||
result = compileModule(filename, false, false)
|
||||
elif sfSystemModule in result.flags:
|
||||
liMessage(result.info, errAttemptToRedefine, result.Name.s)
|
||||
LocalError(result.info, errAttemptToRedefine, result.Name.s)
|
||||
|
||||
proc CompileModule(filename: string, isMainFile, isSystemFile: bool): PSym =
|
||||
var rd: PRodReader = nil
|
||||
@@ -177,7 +177,7 @@ proc CommandScan(filename: string) =
|
||||
|
||||
proc WantFile(filename: string) =
|
||||
if filename == "":
|
||||
liMessage(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
|
||||
Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
|
||||
|
||||
proc MainCommand(cmd, filename: string) =
|
||||
appendStr(searchPaths, options.libpath)
|
||||
|
||||
151
rod/msgs.nim
151
rod/msgs.nim
@@ -343,7 +343,6 @@ const
|
||||
"RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported",
|
||||
"CommentXIgnored", "XisPassedToProcVar", "User"]
|
||||
|
||||
const
|
||||
HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong",
|
||||
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
||||
@@ -371,19 +370,20 @@ type
|
||||
# only 8 bytes.
|
||||
line*, col*: int16
|
||||
fileIndex*: int32
|
||||
|
||||
ERecoverableError* = object of EInvalidValue
|
||||
|
||||
|
||||
proc UnknownLineInfo*(): TLineInfo
|
||||
|
||||
var
|
||||
var
|
||||
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)}
|
||||
gErrorCounter*: int = 0 # counts the number of errors
|
||||
gHintCounter*: int = 0
|
||||
gWarnCounter*: int = 0
|
||||
gErrorMax*: int = 1 # stop after gErrorMax errors
|
||||
|
||||
const # this format is understood by many text editors: it is the same that
|
||||
# Borland and Freepascal use
|
||||
# this format is understood by many text editors: it is the same that
|
||||
# Borland and Freepascal use
|
||||
const
|
||||
PosErrorFormat* = "$1($2, $3) Error: $4"
|
||||
PosWarningFormat* = "$1($2, $3) Warning: $4"
|
||||
PosHintFormat* = "$1($2, $3) Hint: $4"
|
||||
@@ -391,47 +391,22 @@ const # this format is understood by many text editors: it is the same that
|
||||
RawWarningFormat* = "Warning: $1"
|
||||
RawHintFormat* = "Hint: $1"
|
||||
|
||||
proc MessageOut*(s: string)
|
||||
proc rawMessage*(msg: TMsgKind, arg: string)
|
||||
proc rawMessage*(msg: TMsgKind, args: openarray[string])
|
||||
proc liMessage*(info: TLineInfo, msg: TMsgKind, arg: string = "")
|
||||
proc InternalError*(info: TLineInfo, errMsg: string)
|
||||
proc InternalError*(errMsg: string)
|
||||
proc newLineInfo*(filename: string, line, col: int): TLineInfo
|
||||
proc ToFilename*(info: TLineInfo): string
|
||||
proc toColumn*(info: TLineInfo): int
|
||||
proc ToLinenumber*(info: TLineInfo): int
|
||||
proc MsgKindToString*(kind: TMsgKind): string
|
||||
# checkpoints are used for debugging:
|
||||
proc checkpoint*(info: TLineInfo, filename: string, line: int): bool
|
||||
proc addCheckpoint*(info: TLineInfo)
|
||||
proc addCheckpoint*(filename: string, line: int)
|
||||
proc inCheckpoint*(current: TLineInfo): bool
|
||||
# prints the line information if in checkpoint
|
||||
proc pushInfoContext*(info: TLineInfo)
|
||||
proc popInfoContext*()
|
||||
proc includeFilename*(f: string): int
|
||||
# implementation
|
||||
|
||||
proc UnknownLineInfo(): TLineInfo =
|
||||
result.line = int16(- 1)
|
||||
result.col = int16(- 1)
|
||||
result.fileIndex = - 1
|
||||
proc UnknownLineInfo*(): TLineInfo =
|
||||
result.line = int16(-1)
|
||||
result.col = int16(-1)
|
||||
result.fileIndex = -1
|
||||
|
||||
var
|
||||
filenames: seq[string] = @ []
|
||||
msgContext: seq[TLineInfo] = @ []
|
||||
|
||||
proc pushInfoContext(info: TLineInfo) =
|
||||
var length: int
|
||||
length = len(msgContext)
|
||||
setlen(msgContext, length + 1)
|
||||
msgContext[length] = info
|
||||
|
||||
proc popInfoContext() =
|
||||
proc pushInfoContext*(info: TLineInfo) =
|
||||
msgContext.add(info)
|
||||
|
||||
proc popInfoContext*() =
|
||||
setlen(msgContext, len(msgContext) - 1)
|
||||
|
||||
proc includeFilename(f: string): int =
|
||||
proc includeFilename*(f: string): int =
|
||||
for i in countdown(high(filenames), low(filenames)):
|
||||
if filenames[i] == f:
|
||||
return i
|
||||
@@ -439,53 +414,51 @@ proc includeFilename(f: string): int =
|
||||
setlen(filenames, result + 1)
|
||||
filenames[result] = f
|
||||
|
||||
proc checkpoint(info: TLineInfo, filename: string, line: int): bool =
|
||||
proc newLineInfo*(filename: string, line, col: int): TLineInfo =
|
||||
result.fileIndex = includeFilename(filename)
|
||||
result.line = int16(line)
|
||||
result.col = int16(col)
|
||||
|
||||
proc ToFilename*(info: TLineInfo): string =
|
||||
if info.fileIndex == - 1: result = "???"
|
||||
else: result = filenames[info.fileIndex]
|
||||
|
||||
proc ToLinenumber*(info: TLineInfo): int =
|
||||
result = info.line
|
||||
|
||||
proc toColumn*(info: TLineInfo): int =
|
||||
result = info.col
|
||||
|
||||
proc checkpoint*(info: TLineInfo, filename: string, line: int): bool =
|
||||
result = (int(info.line) == line) and
|
||||
(ChangeFileExt(extractFilename(filenames[info.fileIndex]), "") ==
|
||||
filename)
|
||||
|
||||
var checkPoints: seq[TLineInfo] = @[]
|
||||
|
||||
proc addCheckpoint(info: TLineInfo) =
|
||||
var length: int
|
||||
length = len(checkPoints)
|
||||
setlen(checkPoints, length + 1)
|
||||
checkPoints[length] = info
|
||||
proc addCheckpoint*(info: TLineInfo) =
|
||||
checkPoints.add(info)
|
||||
|
||||
proc addCheckpoint(filename: string, line: int) =
|
||||
proc addCheckpoint*(filename: string, line: int) =
|
||||
addCheckpoint(newLineInfo(filename, line, - 1))
|
||||
|
||||
proc newLineInfo(filename: string, line, col: int): TLineInfo =
|
||||
result.fileIndex = includeFilename(filename)
|
||||
result.line = int16(line)
|
||||
result.col = int16(col)
|
||||
|
||||
proc ToFilename(info: TLineInfo): string =
|
||||
if info.fileIndex == - 1: result = "???"
|
||||
else: result = filenames[info.fileIndex]
|
||||
|
||||
proc ToLinenumber(info: TLineInfo): int =
|
||||
result = info.line
|
||||
|
||||
proc toColumn(info: TLineInfo): int =
|
||||
result = info.col
|
||||
|
||||
proc MessageOut(s: string) =
|
||||
proc MessageOut*(s: string) =
|
||||
# change only this proc to put it elsewhere
|
||||
Writeln(stdout, s)
|
||||
|
||||
proc coordToStr(coord: int): string =
|
||||
if coord == - 1: result = "???"
|
||||
else: result = $(coord)
|
||||
if coord == -1: result = "???"
|
||||
else: result = $coord
|
||||
|
||||
proc MsgKindToString(kind: TMsgKind): string =
|
||||
proc MsgKindToString*(kind: TMsgKind): string =
|
||||
# later versions may provide translated error messages
|
||||
result = msgKindToStr[kind]
|
||||
|
||||
proc getMessageStr(msg: TMsgKind, arg: string): string =
|
||||
result = `%`(msgKindToString(msg), [arg])
|
||||
|
||||
proc inCheckpoint(current: TLineInfo): bool =
|
||||
proc inCheckpoint*(current: TLineInfo): bool =
|
||||
## prints the line information if in checkpoint
|
||||
result = false
|
||||
if not (optCheckpoints in gOptions):
|
||||
return # ignore all checkpoints
|
||||
@@ -496,7 +469,10 @@ proc inCheckpoint(current: TLineInfo): bool =
|
||||
coordToStr(current.line), coordToStr(current.col)]))
|
||||
return true
|
||||
|
||||
proc handleError(msg: TMsgKind) =
|
||||
type
|
||||
TErrorHandling = enum doNothing, doAbort, doRaise
|
||||
|
||||
proc handleError(msg: TMsgKind, eh: TErrorHandling) =
|
||||
if msg == errInternal:
|
||||
assert(false) # we want a stack trace here
|
||||
if (msg >= fatalMin) and (msg <= fatalMax):
|
||||
@@ -504,9 +480,12 @@ proc handleError(msg: TMsgKind) =
|
||||
quit(1)
|
||||
if (msg >= errMin) and (msg <= errMax):
|
||||
inc(gErrorCounter)
|
||||
if gErrorCounter >= gErrorMax:
|
||||
options.gExitcode = 1'i8
|
||||
if gErrorCounter >= gErrorMax or eh == doAbort:
|
||||
if gVerbosity >= 3: assert(false)
|
||||
quit(1) # one error stops the compiler
|
||||
elif eh == doRaise:
|
||||
raise newException(ERecoverableError, "")
|
||||
|
||||
proc sameLineInfo(a, b: TLineInfo): bool =
|
||||
result = (a.line == b.line) and (a.fileIndex == b.fileIndex)
|
||||
@@ -523,7 +502,7 @@ proc writeContext(lastinfo: TLineInfo) =
|
||||
getMessageStr(errInstantiationFrom, "")]))
|
||||
info = msgContext[i]
|
||||
|
||||
proc rawMessage(msg: TMsgKind, args: openarray[string]) =
|
||||
proc rawMessage*(msg: TMsgKind, args: openarray[string]) =
|
||||
var frmt: string
|
||||
case msg
|
||||
of errMin..errMax:
|
||||
@@ -542,12 +521,13 @@ proc rawMessage(msg: TMsgKind, args: openarray[string]) =
|
||||
else:
|
||||
assert(false) # cannot happen
|
||||
MessageOut(`%`(frmt, `%`(msgKindToString(msg), args)))
|
||||
handleError(msg)
|
||||
handleError(msg, doAbort)
|
||||
|
||||
proc rawMessage(msg: TMsgKind, arg: string) =
|
||||
proc rawMessage*(msg: TMsgKind, arg: string) =
|
||||
rawMessage(msg, [arg])
|
||||
|
||||
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string = "") =
|
||||
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
||||
eh: TErrorHandling) =
|
||||
var frmt: string
|
||||
case msg
|
||||
of errMin..errMax:
|
||||
@@ -567,12 +547,29 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string = "") =
|
||||
assert(false) # cannot happen
|
||||
MessageOut(`%`(frmt, [toFilename(info), coordToStr(info.line),
|
||||
coordToStr(info.col), getMessageStr(msg, arg)]))
|
||||
handleError(msg)
|
||||
handleError(msg, doAbort)
|
||||
|
||||
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
liMessage(info, msg, arg, doAbort)
|
||||
|
||||
proc InternalError(info: TLineInfo, errMsg: string) =
|
||||
proc GlobalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
liMessage(info, msg, arg, doRaise)
|
||||
|
||||
proc LocalError*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
liMessage(info, msg, arg, doNothing)
|
||||
|
||||
proc Message*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
liMessage(info, msg, arg, doNothing)
|
||||
|
||||
proc GenericMessage*(info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
## does the right thing for old code that is written with "abort on first
|
||||
## error" in mind.
|
||||
liMessage(info, msg, arg, doAbort)
|
||||
|
||||
proc InternalError*(info: TLineInfo, errMsg: string) =
|
||||
writeContext(info)
|
||||
liMessage(info, errInternal, errMsg)
|
||||
liMessage(info, errInternal, errMsg, doAbort)
|
||||
|
||||
proc InternalError(errMsg: string) =
|
||||
proc InternalError*(errMsg: string) =
|
||||
writeContext(UnknownLineInfo())
|
||||
rawMessage(errInternal, errMsg)
|
||||
|
||||
0
rod/nimrod.ini
Normal file → Executable file
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))
|
||||
|
||||
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
|
||||
msgs.liMessage(getLineInfo(L), msg, arg)
|
||||
msgs.GenericMessage(getLineInfo(L), msg, arg)
|
||||
|
||||
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
|
||||
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
|
||||
msgs.liMessage(info, msg, arg)
|
||||
msgs.GenericMessage(info, msg, arg)
|
||||
|
||||
proc TokKindToStr*(k: TTokKind): string =
|
||||
case k
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -12,10 +12,6 @@
|
||||
import
|
||||
strutils, ast, astalgo, passes, msgs, options
|
||||
|
||||
proc verbosePass*(): TPass
|
||||
proc cleanupPass*(): TPass
|
||||
# implementation
|
||||
|
||||
proc verboseOpen(s: PSym, filename: string): PPassContext =
|
||||
#MessageOut('compiling ' + s.name.s);
|
||||
result = nil # we don't need a context
|
||||
@@ -24,9 +20,9 @@ proc verboseOpen(s: PSym, filename: string): PPassContext =
|
||||
proc verboseProcess(context: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
if context != nil: InternalError("logpass: context is not nil")
|
||||
if gVerbosity == 3: liMessage(n.info, hintProcessing, $(ast.gid))
|
||||
if gVerbosity == 3: Message(n.info, hintProcessing, $ast.gid)
|
||||
|
||||
proc verbosePass(): TPass =
|
||||
proc verbosePass*(): TPass =
|
||||
initPass(result)
|
||||
result.open = verboseOpen
|
||||
result.process = verboseProcess
|
||||
@@ -43,11 +39,11 @@ proc cleanUp(c: PPassContext, n: PNode): PNode =
|
||||
if (n.sons[namePos].kind == nkSym):
|
||||
s = n.sons[namePos].sym
|
||||
if not (sfDeadCodeElim in getModule(s).flags) and not astNeeded(s):
|
||||
s.ast.sons[codePos] = nil # free the memory
|
||||
s.ast.sons[codePos] = ast.emptyNode # free the memory
|
||||
else:
|
||||
nil
|
||||
|
||||
proc cleanupPass(): TPass =
|
||||
proc cleanupPass*(): TPass =
|
||||
initPass(result)
|
||||
result.process = cleanUp
|
||||
result.close = cleanUp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -25,9 +25,9 @@ type
|
||||
close: proc (p: PPassContext, n: PNode): PNode,
|
||||
process: proc (p: PPassContext, topLevelStmt: PNode): PNode]
|
||||
|
||||
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
|
||||
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
|
||||
# nodes. These are passed to the other close procedures.
|
||||
# This mechanism is needed for the instantiation of generics.
|
||||
# This mechanism used to be used for the instantiation of generics.
|
||||
|
||||
proc registerPass*(p: TPass)
|
||||
proc initPass*(p: var TPass)
|
||||
@@ -37,11 +37,6 @@ proc initPass*(p: var TPass)
|
||||
# whole program optimizations. For now, we avoid it to save a lot of memory.
|
||||
proc processModule*(module: PSym, filename: string, stream: PLLStream,
|
||||
rd: PRodReader)
|
||||
proc astNeeded*(s: PSym): bool
|
||||
# The ``rodwrite`` module uses this to determine if the body of a proc
|
||||
# needs to be stored. The passes manager frees s.sons[codePos] when
|
||||
# appropriate to free the procedure body's memory. This is important
|
||||
# to keep memory usage down.
|
||||
|
||||
# the semantic checker needs these:
|
||||
var
|
||||
@@ -50,10 +45,21 @@ var
|
||||
|
||||
# implementation
|
||||
|
||||
proc astNeeded(s: PSym): bool =
|
||||
proc skipCodegen*(n: PNode): bool {.inline.} =
|
||||
# can be used by codegen passes to determine whether they should do
|
||||
# something with `n`. Currently, this ignores `n` and uses the global
|
||||
# error count instead.
|
||||
result = msgs.gErrorCounter > 0
|
||||
|
||||
proc astNeeded*(s: PSym): bool =
|
||||
# The ``rodwrite`` module uses this to determine if the body of a proc
|
||||
# needs to be stored. The passes manager frees s.sons[codePos] when
|
||||
# appropriate to free the procedure body's memory. This is important
|
||||
# to keep memory usage down.
|
||||
if (s.kind in {skMethod, skProc}) and
|
||||
({sfCompilerProc, sfCompileTime} * s.flags == {}) and
|
||||
(s.typ.callConv != ccInline) and (s.ast.sons[genericParamsPos] == nil):
|
||||
(s.typ.callConv != ccInline) and
|
||||
(s.ast.sons[genericParamsPos].kind == nkEmpty):
|
||||
result = false
|
||||
else:
|
||||
result = true
|
||||
|
||||
@@ -117,7 +117,7 @@ proc indAndComment(p: var TParser, n: PNode) =
|
||||
var info = parLineInfo(p)
|
||||
getTok(p)
|
||||
if p.tok.tokType == tkComment: skipComment(p, n)
|
||||
else: liMessage(info, errInvalidIndentation)
|
||||
else: LocalError(info, errInvalidIndentation)
|
||||
else:
|
||||
skipComment(p, n)
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ proc pragmaAsm*(c: PContext, n: PNode): char
|
||||
# implementation
|
||||
|
||||
proc invalidPragma(n: PNode) =
|
||||
liMessage(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
|
||||
LocalError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
|
||||
|
||||
proc pragmaAsm(c: PContext, n: PNode): char =
|
||||
result = '\0'
|
||||
@@ -82,27 +82,24 @@ proc MakeExternExport(s: PSym, extname: string) =
|
||||
|
||||
proc getStrLitNode(c: PContext, n: PNode): PNode =
|
||||
if n.kind != nkExprColonExpr:
|
||||
liMessage(n.info, errStringLiteralExpected)
|
||||
GlobalError(n.info, errStringLiteralExpected)
|
||||
else:
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
case n.sons[1].kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
|
||||
else: liMessage(n.info, errStringLiteralExpected)
|
||||
else: GlobalError(n.info, errStringLiteralExpected)
|
||||
|
||||
proc expectStrLit(c: PContext, n: PNode): string =
|
||||
result = getStrLitNode(c, n).strVal
|
||||
|
||||
proc expectIntLit(c: PContext, n: PNode): int =
|
||||
if n.kind != nkExprColonExpr:
|
||||
liMessage(n.info, errIntLiteralExpected)
|
||||
result = 0
|
||||
LocalError(n.info, errIntLiteralExpected)
|
||||
else:
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
case n.sons[1].kind
|
||||
of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal)
|
||||
else:
|
||||
liMessage(n.info, errIntLiteralExpected)
|
||||
result = 0
|
||||
else: LocalError(n.info, errIntLiteralExpected)
|
||||
|
||||
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
||||
if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
|
||||
@@ -112,7 +109,9 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||
var v: string
|
||||
#if not (sfSystemModule in c.module.flags) then
|
||||
# liMessage(n.info, errMagicOnlyInSystem);
|
||||
if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
|
||||
if n.kind != nkExprColonExpr:
|
||||
LocalError(n.info, errStringLiteralExpected)
|
||||
return
|
||||
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
|
||||
else: v = expectStrLit(c, n)
|
||||
incl(s.flags, sfImportc)
|
||||
@@ -123,7 +122,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||
if copy($m, 1) == v:
|
||||
s.magic = m
|
||||
return
|
||||
liMessage(n.info, warnUnknownMagic, v)
|
||||
Message(n.info, warnUnknownMagic, v)
|
||||
|
||||
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
||||
# this assumes that the order of special words and calling conventions is
|
||||
@@ -135,9 +134,9 @@ proc IsTurnedOn(c: PContext, n: PNode): bool =
|
||||
case whichKeyword(n.sons[1].ident)
|
||||
of wOn: result = true
|
||||
of wOff: result = false
|
||||
else: liMessage(n.info, errOnOrOffExpected)
|
||||
else: LocalError(n.info, errOnOrOffExpected)
|
||||
else:
|
||||
liMessage(n.info, errOnOrOffExpected)
|
||||
LocalError(n.info, errOnOrOffExpected)
|
||||
|
||||
proc onOff(c: PContext, n: PNode, op: TOptions) =
|
||||
if IsTurnedOn(c, n): gOptions = gOptions + op
|
||||
@@ -153,9 +152,9 @@ proc processCallConv(c: PContext, n: PNode) =
|
||||
case sw
|
||||
of firstCallConv..lastCallConv:
|
||||
POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
|
||||
else: liMessage(n.info, errCallConvExpected)
|
||||
else: LocalError(n.info, errCallConvExpected)
|
||||
else:
|
||||
liMessage(n.info, errCallConvExpected)
|
||||
LocalError(n.info, errCallConvExpected)
|
||||
|
||||
proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
|
||||
var it = PLib(c.libs.head)
|
||||
@@ -168,13 +167,13 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
|
||||
Append(c.libs, result)
|
||||
|
||||
proc expectDynlibNode(c: PContext, n: PNode): PNode =
|
||||
if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
|
||||
if n.kind != nkExprColonExpr: GlobalError(n.info, errStringLiteralExpected)
|
||||
else:
|
||||
result = c.semExpr(c, n.sons[1])
|
||||
if result.kind == nkSym and result.sym.kind == skConst:
|
||||
result = result.sym.ast # look it up
|
||||
if result.typ == nil or result.typ.kind != tyString:
|
||||
liMessage(n.info, errStringLiteralExpected)
|
||||
GlobalError(n.info, errStringLiteralExpected)
|
||||
|
||||
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||
if (sym == nil) or (sym.kind == skModule):
|
||||
@@ -208,7 +207,7 @@ proc processNote(c: PContext, n: PNode) =
|
||||
case whichKeyword(n.sons[1].ident)
|
||||
of wOn: incl(gNotes, nk)
|
||||
of wOff: excl(gNotes, nk)
|
||||
else: liMessage(n.info, errOnOrOffExpected)
|
||||
else: LocalError(n.info, errOnOrOffExpected)
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
@@ -254,8 +253,8 @@ proc processOption(c: PContext, n: PNode) =
|
||||
of wNone:
|
||||
excl(gOptions, optOptimizeSpeed)
|
||||
excl(gOptions, optOptimizeSize)
|
||||
else: liMessage(n.info, errNoneSpeedOrSizeExpected)
|
||||
else: liMessage(n.info, errOptionExpected)
|
||||
else: LocalError(n.info, errNoneSpeedOrSizeExpected)
|
||||
else: LocalError(n.info, errOptionExpected)
|
||||
|
||||
proc processPush(c: PContext, n: PNode, start: int) =
|
||||
var x = newOptionEntry()
|
||||
@@ -271,7 +270,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
|
||||
|
||||
proc processPop(c: PContext, n: PNode) =
|
||||
if c.optionStack.counter <= 1:
|
||||
liMessage(n.info, errAtPopWithoutPush)
|
||||
LocalError(n.info, errAtPopWithoutPush)
|
||||
else:
|
||||
gOptions = POptionEntry(c.optionStack.tail).options
|
||||
#liMessage(n.info, warnUser, ropeToStr(optionsToStr(gOptions)));
|
||||
@@ -281,14 +280,14 @@ proc processPop(c: PContext, n: PNode) =
|
||||
proc processDefine(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
DefineSymbol(n.sons[1].ident.s)
|
||||
liMessage(n.info, warnDeprecated, "define")
|
||||
Message(n.info, warnDeprecated, "define")
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
proc processUndef(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
UndefSymbol(n.sons[1].ident.s)
|
||||
liMessage(n.info, warnDeprecated, "undef")
|
||||
Message(n.info, warnDeprecated, "undef")
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
@@ -329,7 +328,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
result = copyNode(n)
|
||||
var str = n.sons[1].strVal
|
||||
if str == "": liMessage(n.info, errEmptyAsm)
|
||||
if str == "": GlobalError(n.info, errEmptyAsm)
|
||||
# now parse the string literal and substitute symbols:
|
||||
var a = 0
|
||||
while true:
|
||||
@@ -392,14 +391,16 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
of wExtern: setExternName(sym, expectStrLit(c, it))
|
||||
of wAlign:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
sym.typ.align = expectIntLit(c, it)
|
||||
if not IsPowerOfTwo(sym.typ.align) and (sym.typ.align != 0):
|
||||
liMessage(it.info, errPowerOfTwoExpected)
|
||||
var align = expectIntLit(c, it)
|
||||
if not IsPowerOfTwo(align) and align != 0:
|
||||
LocalError(it.info, errPowerOfTwoExpected)
|
||||
else:
|
||||
sym.typ.align = align
|
||||
of wSize:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
var size = expectIntLit(c, it)
|
||||
if not IsPowerOfTwo(size) or size <= 0 or size > 8:
|
||||
liMessage(it.info, errPowerOfTwoExpected)
|
||||
LocalError(it.info, errPowerOfTwoExpected)
|
||||
else:
|
||||
sym.typ.size = size
|
||||
of wNodecl:
|
||||
@@ -477,12 +478,10 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
of wTypeCheck:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfTypeCheck)
|
||||
of wHint: liMessage(it.info, hintUser, expectStrLit(c, it))
|
||||
of wWarning: liMessage(it.info, warnUser, expectStrLit(c, it))
|
||||
of wError: liMessage(it.info, errUser, expectStrLit(c, it))
|
||||
of wFatal:
|
||||
liMessage(it.info, errUser, expectStrLit(c, it))
|
||||
quit(1)
|
||||
of wHint: Message(it.info, hintUser, expectStrLit(c, it))
|
||||
of wWarning: Message(it.info, warnUser, expectStrLit(c, it))
|
||||
of wError: LocalError(it.info, errUser, expectStrLit(c, it))
|
||||
of wFatal: Fatal(it.info, errUser, expectStrLit(c, it))
|
||||
of wDefine: processDefine(c, it)
|
||||
of wUndef: processUndef(c, it)
|
||||
of wCompile: processCompile(c, it)
|
||||
@@ -515,7 +514,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
else: processNote(c, it)
|
||||
if (sym != nil) and (sym.kind != skModule):
|
||||
if (lfExportLib in sym.loc.flags) and not (sfExportc in sym.flags):
|
||||
liMessage(n.info, errDynlibRequiresExportc)
|
||||
LocalError(n.info, errDynlibRequiresExportc)
|
||||
var lib = POptionEntry(c.optionstack.tail).dynlib
|
||||
if ({lfDynamicLib, lfHeader} * sym.loc.flags == {}) and
|
||||
(sfImportc in sym.flags) and (lib != nil):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -50,7 +50,7 @@ proc SearchForProc(c: PContext, fn: PSym, tos: int): PSym =
|
||||
of paramsEqual:
|
||||
return
|
||||
of paramsIncompatible:
|
||||
liMessage(fn.info, errNotOverloadable, fn.name.s)
|
||||
LocalError(fn.info, errNotOverloadable, fn.name.s)
|
||||
return
|
||||
of paramsNotEqual:
|
||||
nil
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -94,7 +94,7 @@ proc parseLine(p: var TTmplParser) =
|
||||
dec(p.indent, 2)
|
||||
else:
|
||||
p.info.col = int16(j)
|
||||
liMessage(p.info, errXNotAllowedHere, "end")
|
||||
LocalError(p.info, errXNotAllowedHere, "end")
|
||||
LLStreamWrite(p.outp, repeatChar(p.indent))
|
||||
LLStreamWrite(p.outp, "#end")
|
||||
of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator,
|
||||
@@ -163,7 +163,8 @@ proc parseLine(p: var TTmplParser) =
|
||||
while true:
|
||||
case p.x[j]
|
||||
of '\0':
|
||||
liMessage(p.info, errXExpected, "}")
|
||||
LocalError(p.info, errXExpected, "}")
|
||||
break
|
||||
of '{':
|
||||
inc(j)
|
||||
inc(curly)
|
||||
@@ -196,7 +197,7 @@ proc parseLine(p: var TTmplParser) =
|
||||
inc(j)
|
||||
else:
|
||||
p.info.col = int16(j)
|
||||
liMessage(p.info, errInvalidExpression, "$")
|
||||
LocalError(p.info, errInvalidExpression, "$")
|
||||
else:
|
||||
LLStreamWrite(p.outp, p.x[j])
|
||||
inc(j)
|
||||
|
||||
0
rod/rodutils.nim
Normal file → Executable file
0
rod/rodutils.nim
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -288,10 +288,10 @@ proc tokInfo(p: TRstParser, tok: TToken): TLineInfo =
|
||||
result = newLineInfo(p.filename, p.line + tok.line, p.col + tok.col)
|
||||
|
||||
proc rstMessage(p: TRstParser, msgKind: TMsgKind, arg: string) =
|
||||
liMessage(tokInfo(p, p.tok[p.idx]), msgKind, arg)
|
||||
GenericMessage(tokInfo(p, p.tok[p.idx]), msgKind, arg)
|
||||
|
||||
proc rstMessage(p: TRstParser, msgKind: TMsgKind) =
|
||||
liMessage(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol)
|
||||
GenericMessage(tokInfo(p, p.tok[p.idx]), msgKind, p.tok[p.idx].symbol)
|
||||
|
||||
proc currInd(p: TRstParser): int =
|
||||
result = p.indentStack[high(p.indentStack)]
|
||||
|
||||
@@ -223,11 +223,11 @@ proc getLineInfo(L: TLexer): TLineInfo =
|
||||
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
|
||||
|
||||
proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") =
|
||||
msgs.liMessage(getLineInfo(L), msg, arg)
|
||||
msgs.Message(getLineInfo(L), msg, arg)
|
||||
|
||||
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
|
||||
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
|
||||
msgs.liMessage(info, msg, arg)
|
||||
msgs.Message(info, msg, arg)
|
||||
|
||||
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
|
||||
var pos = L.bufpos # use registers for pos, buf
|
||||
|
||||
47
rod/sem.nim
47
rod/sem.nim
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -25,7 +25,7 @@ proc considerAcc(n: PNode): PIdent =
|
||||
of nkIdent: result = x.ident
|
||||
of nkSym: result = x.sym.name
|
||||
else:
|
||||
liMessage(n.info, errIdentifierExpected, renderTree(n))
|
||||
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||
result = nil
|
||||
|
||||
proc isTopLevel(c: PContext): bool =
|
||||
@@ -37,7 +37,7 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
|
||||
proc markUsed(n: PNode, s: PSym) =
|
||||
incl(s.flags, sfUsed)
|
||||
if sfDeprecated in s.flags: liMessage(n.info, warnDeprecated, s.name.s)
|
||||
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
|
||||
|
||||
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym
|
||||
# identifier with visability
|
||||
@@ -65,22 +65,22 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
|
||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
result = semExprWithType(c, n)
|
||||
if result == nil:
|
||||
liMessage(n.info, errConstExprExpected)
|
||||
GlobalError(n.info, errConstExprExpected)
|
||||
return
|
||||
result = getConstExpr(c.module, result)
|
||||
if result == nil: liMessage(n.info, errConstExprExpected)
|
||||
if result == nil: GlobalError(n.info, errConstExprExpected)
|
||||
|
||||
proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
|
||||
var e = semExprWithType(c, n)
|
||||
if e == nil:
|
||||
liMessage(n.info, errConstExprExpected)
|
||||
GlobalError(n.info, errConstExprExpected)
|
||||
return nil
|
||||
result = getConstExpr(c.module, e)
|
||||
if result == nil:
|
||||
#writeln(output, renderTree(n));
|
||||
result = evalConstExpr(c.module, e)
|
||||
if (result == nil) or (result.kind == nkEmpty):
|
||||
liMessage(n.info, errConstExprExpected)
|
||||
GlobalError(n.info, errConstExprExpected)
|
||||
|
||||
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = n
|
||||
@@ -91,7 +91,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = semExpr(c, result) # semExprWithType(c, result)
|
||||
of tyStmt: result = semStmt(c, result)
|
||||
of tyTypeDesc: result.typ = semTypeNode(c, result, nil)
|
||||
else: liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
||||
else: GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
||||
|
||||
include "semtempl.nim"
|
||||
|
||||
@@ -99,7 +99,7 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||
semCheck: bool = true): PNode =
|
||||
inc(evalTemplateCounter)
|
||||
if evalTemplateCounter > 100:
|
||||
liMessage(n.info, errTemplateInstantiationTooNested)
|
||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||
markUsed(n, sym)
|
||||
var p = newEvalContext(c.module, "", false)
|
||||
var s = newStackFrame()
|
||||
@@ -111,23 +111,23 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||
discard eval(p, sym.ast.sons[codePos])
|
||||
result = s.params[0]
|
||||
popStackFrame(p)
|
||||
if cyclicTree(result): liMessage(n.info, errCyclicTree)
|
||||
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
|
||||
if semCheck: result = semAfterMacroCall(c, result, sym)
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
include "seminst.nim", "sigmatch.nim"
|
||||
include seminst, sigmatch
|
||||
|
||||
proc CheckBool(t: PNode) =
|
||||
if (t.Typ == nil) or
|
||||
(skipTypes(t.Typ, {tyGenericInst, tyVar, tyOrdinal}).kind != tyBool):
|
||||
liMessage(t.Info, errExprMustBeBool)
|
||||
LocalError(t.Info, errExprMustBeBool)
|
||||
|
||||
proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||
liMessage(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
|
||||
GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
|
||||
typeToString(actual) & ") " &
|
||||
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
|
||||
|
||||
include "semtypes.nim", "semexprs.nim", "semgnrc.nim", "semstmts.nim"
|
||||
include semtypes, semexprs, semgnrc, semstmts
|
||||
|
||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||
for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1):
|
||||
@@ -166,19 +166,28 @@ proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext
|
||||
c.fromCache = true
|
||||
result = c
|
||||
|
||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
result = nil
|
||||
var c = PContext(context)
|
||||
result = semStmt(c, n)
|
||||
proc SemStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
|
||||
result = semStmt(c, n)
|
||||
# BUGFIX: process newly generated generics here, not at the end!
|
||||
if sonsLen(c.generics) > 0:
|
||||
var a = newNodeI(nkStmtList, n.info)
|
||||
addCodeForGenerics(c, a)
|
||||
if sonsLen(a) > 0:
|
||||
# a generic has been added to `a`:
|
||||
addSonIfNotNil(a, result)
|
||||
if result.kind != nkEmpty: addSon(a, result)
|
||||
result = a
|
||||
|
||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
# no need for an expensive 'try' if we stop after the first error anyway:
|
||||
if msgs.gErrorMax <= 1:
|
||||
result = SemStmtAndGenerateGenerics(c, n)
|
||||
else:
|
||||
try:
|
||||
result = SemStmtAndGenerateGenerics(c, n)
|
||||
except ERecoverableError:
|
||||
result = ast.emptyNode
|
||||
|
||||
proc myClose(context: PPassContext, n: PNode): PNode =
|
||||
var c = PContext(context)
|
||||
closeScope(c.tab) # close module's scope
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -69,10 +69,6 @@ proc makeVarType*(c: PContext, baseType: PType): PType
|
||||
proc newTypeS*(kind: TTypeKind, c: PContext): PType
|
||||
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext)
|
||||
proc makeRangeType*(c: PContext, first, last: biggestInt, info: TLineInfo): PType
|
||||
proc illFormedAst*(n: PNode)
|
||||
proc getSon*(n: PNode, indx: int): PNode
|
||||
proc checkSonsLen*(n: PNode, length: int)
|
||||
proc checkMinSonsLen*(n: PNode, length: int)
|
||||
|
||||
# owner handling:
|
||||
proc getCurrOwner*(): PSym
|
||||
@@ -122,7 +118,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
|
||||
append(result.optionStack, newOptionEntry())
|
||||
result.module = module
|
||||
result.generics = newNode(nkStmtList)
|
||||
result.converters = @ []
|
||||
result.converters = @[]
|
||||
result.filename = nimfile
|
||||
IntSetInit(result.includedFiles)
|
||||
initStrTable(result.userPragmas)
|
||||
@@ -140,7 +136,7 @@ proc newLib(kind: TLibKind): PLib =
|
||||
|
||||
proc addToLib(lib: PLib, sym: PSym) =
|
||||
#ObjectSetIncl(lib.syms, sym);
|
||||
if sym.annex != nil: liMessage(sym.info, errInvalidPragma)
|
||||
if sym.annex != nil: LocalError(sym.info, errInvalidPragma)
|
||||
sym.annex = lib
|
||||
|
||||
proc makePtrType(c: PContext, baseType: PType): PType =
|
||||
@@ -170,20 +166,13 @@ proc makeRangeType(c: PContext, first, last: biggestInt,
|
||||
result.n = n
|
||||
addSon(result, getSysType(tyInt)) # basetype of range
|
||||
|
||||
proc illFormedAst(n: PNode) =
|
||||
liMessage(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
|
||||
proc illFormedAst*(n: PNode) =
|
||||
GlobalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
|
||||
|
||||
proc getSon(n: PNode, indx: int): PNode =
|
||||
if (n != nil) and (indx < sonsLen(n)):
|
||||
result = n.sons[indx]
|
||||
else:
|
||||
illFormedAst(n)
|
||||
result = nil
|
||||
|
||||
proc checkSonsLen(n: PNode, length: int) =
|
||||
if (n == nil) or (sonsLen(n) != length): illFormedAst(n)
|
||||
proc checkSonsLen*(n: PNode, length: int) =
|
||||
if sonsLen(n) != length: illFormedAst(n)
|
||||
|
||||
proc checkMinSonsLen(n: PNode, length: int) =
|
||||
if (n == nil) or (sonsLen(n) < length): illFormedAst(n)
|
||||
proc checkMinSonsLen*(n: PNode, length: int) =
|
||||
if sonsLen(n) < length: illFormedAst(n)
|
||||
|
||||
initIdTable(gInstTypes)
|
||||
|
||||
187
rod/semexprs.nim
187
rod/semexprs.nim
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -23,22 +23,24 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semExpr(c, n, flags)
|
||||
if result == nil: InternalError("semExprWithType")
|
||||
if (result.typ == nil):
|
||||
liMessage(n.info, errExprXHasNoType, renderTree(result, {renderNoComments}))
|
||||
if result.typ.kind == tyVar:
|
||||
var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
|
||||
addSon(d, result)
|
||||
result = d
|
||||
|
||||
if result.kind == nkEmpty: InternalError("semExprWithType")
|
||||
if result.typ != nil:
|
||||
if result.typ.kind == tyVar:
|
||||
var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])
|
||||
addSon(d, result)
|
||||
result = d
|
||||
else:
|
||||
GlobalError(n.info, errExprXHasNoType,
|
||||
renderTree(result, {renderNoComments}))
|
||||
|
||||
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
if s.kind == skType and efAllowType notin flags:
|
||||
liMessage(n.info, errATypeHasNoValue)
|
||||
GlobalError(n.info, errATypeHasNoValue)
|
||||
case s.kind
|
||||
of skProc, skMethod, skIterator, skConverter:
|
||||
if not (sfProcVar in s.flags) and (s.typ.callConv == ccDefault) and
|
||||
(getModule(s).id != c.module.id):
|
||||
liMessage(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||
result = symChoice(c, n, s)
|
||||
of skConst:
|
||||
#
|
||||
@@ -79,7 +81,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
|
||||
var diff = inheritanceDiff(castDest, src)
|
||||
if diff == high(int):
|
||||
liMessage(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
|
||||
GlobalError(info, errGenerated, `%`(MsgKindToString(errIllegalConvFromXtoY), [
|
||||
typeToString(src), typeToString(castDest)]))
|
||||
|
||||
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||
@@ -88,7 +90,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||
if sameType(castDest, src):
|
||||
# don't annoy conversions that may be needed on another processor:
|
||||
if not (castDest.kind in {tyInt..tyFloat128, tyNil}):
|
||||
liMessage(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
|
||||
Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
|
||||
return
|
||||
var d = skipTypes(castDest, abstractVar)
|
||||
var s = skipTypes(src, abstractVar)
|
||||
@@ -96,9 +98,9 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||
d = base(d)
|
||||
s = base(s)
|
||||
if d == nil:
|
||||
liMessage(info, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
|
||||
GlobalError(info, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
|
||||
typeToString(src), typeToString(castDest)]))
|
||||
if (d.Kind == tyObject) and (s.Kind == tyObject):
|
||||
elif d.Kind == tyObject and s.Kind == tyObject:
|
||||
checkConversionBetweenObjects(info, d, s)
|
||||
elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
|
||||
(skipTypes(src, abstractVarRange).Kind in IntegralTypes):
|
||||
@@ -109,7 +111,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||
of isNone, isGeneric:
|
||||
if not equalOrDistinctOf(castDest, src) and
|
||||
not equalOrDistinctOf(src, castDest):
|
||||
liMessage(info, errGenerated, `%`(
|
||||
GlobalError(info, errGenerated, `%`(
|
||||
MsgKindToString(errIllegalConvFromXtoY),
|
||||
[typeToString(src), typeToString(castDest)]))
|
||||
else:
|
||||
@@ -134,7 +136,7 @@ proc isCastable(dst, src: PType): bool =
|
||||
(skipTypes(src, abstractInst).kind in {tyInt..tyFloat128})
|
||||
|
||||
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
||||
if sonsLen(n) != 2: liMessage(n.info, errConvNeedsOneArg)
|
||||
if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg)
|
||||
result = newNodeI(nkConv, n.info)
|
||||
result.typ = semTypeNode(c, n.sons[0], nil)
|
||||
addSon(result, copyTree(n.sons[0]))
|
||||
@@ -147,10 +149,10 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
||||
if sameType(result.typ, op.sons[i].typ):
|
||||
markUsed(n, op.sons[i].sym)
|
||||
return op.sons[i]
|
||||
liMessage(n.info, errUseQualifier, op.sons[0].sym.name.s)
|
||||
localError(n.info, errUseQualifier, op.sons[0].sym.name.s)
|
||||
|
||||
proc semCast(c: PContext, n: PNode): PNode =
|
||||
if optSafeCode in gGlobalOptions: liMessage(n.info, errCastNotInSafeMode)
|
||||
if optSafeCode in gGlobalOptions: localError(n.info, errCastNotInSafeMode)
|
||||
incl(c.p.owner.flags, sfSideEffect)
|
||||
checkSonsLen(n, 2)
|
||||
result = newNodeI(nkCast, n.info)
|
||||
@@ -158,13 +160,13 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||
addSon(result, copyTree(n.sons[0]))
|
||||
addSon(result, semExprWithType(c, n.sons[1]))
|
||||
if not isCastable(result.typ, result.sons[1].Typ):
|
||||
liMessage(result.info, errExprCannotBeCastedToX, typeToString(result.Typ))
|
||||
GlobalError(result.info, errExprCannotBeCastedToX, typeToString(result.Typ))
|
||||
|
||||
proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
const
|
||||
opToStr: array[mLow..mHigh, string] = ["low", "high"]
|
||||
if sonsLen(n) != 2:
|
||||
liMessage(n.info, errXExpectsTypeOrValue, opToStr[m])
|
||||
GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
|
||||
else:
|
||||
n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
||||
var typ = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
@@ -175,11 +177,11 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
n.typ = n.sons[1].typ.sons[0] # indextype
|
||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum:
|
||||
n.typ = n.sons[1].typ
|
||||
else: liMessage(n.info, errInvalidArgForX, opToStr[m])
|
||||
else: GlobalError(n.info, errInvalidArgForX, opToStr[m])
|
||||
result = n
|
||||
|
||||
proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) != 2: liMessage(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||
if sonsLen(n) != 2: GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
|
||||
else: n.sons[1] = semExprWithType(c, n.sons[1], {efAllowType})
|
||||
n.typ = getSysType(tyInt)
|
||||
result = n
|
||||
@@ -190,20 +192,22 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||
n.sons[2] = semExprWithType(c, n.sons[2], {efAllowType})
|
||||
var a = n.sons[1].typ
|
||||
var b = n.sons[2].typ
|
||||
if (b.kind != tyObject) or (a.kind != tyObject):
|
||||
liMessage(n.info, errIsExpectsObjectTypes)
|
||||
while (b != nil) and (b.id != a.id): b = b.sons[0]
|
||||
if b == nil: liMessage(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||
# a and b can be nil in case of an error:
|
||||
if a != nil and b != nil:
|
||||
if (b.kind != tyObject) or (a.kind != tyObject):
|
||||
GlobalError(n.info, errIsExpectsObjectTypes)
|
||||
while (b != nil) and (b.id != a.id): b = b.sons[0]
|
||||
if b == nil:
|
||||
GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||
n.typ = getSysType(tyBool)
|
||||
else:
|
||||
liMessage(n.info, errIsExpectsTwoArguments)
|
||||
GlobalError(n.info, errIsExpectsTwoArguments)
|
||||
result = n
|
||||
|
||||
proc semOpAux(c: PContext, n: PNode) =
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkExprEqExpr:
|
||||
checkSonsLen(a, 2)
|
||||
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
|
||||
var info = a.sons[0].info
|
||||
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
|
||||
a.sons[1] = semExprWithType(c, a.sons[1])
|
||||
@@ -223,9 +227,6 @@ proc overloadedCallOpr(c: PContext, n: PNode): PNode =
|
||||
result = semExpr(c, result)
|
||||
|
||||
proc changeType(n: PNode, newType: PType) =
|
||||
var
|
||||
f: PSym
|
||||
a, m: PNode
|
||||
case n.kind
|
||||
of nkCurly, nkBracket:
|
||||
for i in countup(0, sonsLen(n) - 1): changeType(n.sons[i], elemType(newType))
|
||||
@@ -235,22 +236,21 @@ proc changeType(n: PNode, newType: PType) =
|
||||
if newType.n == nil: InternalError(n.info, "changeType: no tuple fields")
|
||||
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
m = n.sons[i].sons[0]
|
||||
var m = n.sons[i].sons[0]
|
||||
if m.kind != nkSym:
|
||||
internalError(m.info, "changeType(): invalid tuple constr")
|
||||
f = getSymFromList(newType.n, m.sym.name)
|
||||
var f = getSymFromList(newType.n, m.sym.name)
|
||||
if f == nil: internalError(m.info, "changeType(): invalid identifier")
|
||||
changeType(n.sons[i].sons[1], f.typ)
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
m = n.sons[i]
|
||||
a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
|
||||
var m = n.sons[i]
|
||||
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
|
||||
addSon(a, newSymNode(newType.n.sons[i].sym))
|
||||
addSon(a, m)
|
||||
changeType(m, newType.sons[i])
|
||||
n.sons[i] = a
|
||||
else:
|
||||
nil
|
||||
else: nil
|
||||
n.typ = newType
|
||||
|
||||
proc semArrayConstr(c: PContext, n: PNode): PNode =
|
||||
@@ -263,7 +263,7 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
|
||||
var x = n.sons[0]
|
||||
var lastIndex: biggestInt = 0
|
||||
var indexType = getSysType(tyInt)
|
||||
if x.kind == nkExprColonExpr:
|
||||
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||
var idx = semConstExpr(c, x.sons[0])
|
||||
lastIndex = getOrdValue(idx)
|
||||
indexType = idx.typ
|
||||
@@ -273,11 +273,11 @@ proc semArrayConstr(c: PContext, n: PNode): PNode =
|
||||
var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyOrdinal})
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
x = n.sons[i]
|
||||
if x.kind == nkExprColonExpr:
|
||||
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||
var idx = semConstExpr(c, x.sons[0])
|
||||
idx = fitNode(c, indexType, idx)
|
||||
if lastIndex+1 != getOrdValue(idx):
|
||||
liMessage(x.info, errInvalidOrderInArrayConstructor)
|
||||
localError(x.info, errInvalidOrderInArrayConstructor)
|
||||
x = x.sons[1]
|
||||
|
||||
n.sons[i] = semExprWithType(c, x)
|
||||
@@ -334,7 +334,6 @@ proc isAssignable(n: PNode): TAssignableResult =
|
||||
of nkSym:
|
||||
if (n.sym.kind in {skVar, skTemp}): result = arLValue
|
||||
of nkDotExpr:
|
||||
checkMinSonsLen(n, 1)
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
else:
|
||||
@@ -342,7 +341,6 @@ proc isAssignable(n: PNode): TAssignableResult =
|
||||
if (result == arLValue) and (sfDiscriminant in n.sons[1].sym.flags):
|
||||
result = arDiscriminant
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 1)
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind in {tyVar, tyPtr, tyRef}:
|
||||
result = arLValue
|
||||
else:
|
||||
@@ -368,7 +366,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
|
||||
addSon(result, n)
|
||||
if isAssignable(n) != arLValue:
|
||||
liMessage(n.info, errVarForOutParamNeeded)
|
||||
localError(n.info, errVarForOutParamNeeded)
|
||||
|
||||
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -403,7 +401,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
if i < sonsLen(t) and skipTypes(t.sons[i], abstractInst).kind == tyVar:
|
||||
if isAssignable(n.sons[i]) != arLValue:
|
||||
liMessage(n.sons[i].info, errVarForOutParamNeeded)
|
||||
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
||||
return
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
if (i < sonsLen(t)) and
|
||||
@@ -421,7 +419,7 @@ proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
|
||||
InternalError("semDirectCallAnalyseEffects")
|
||||
var callee = result.sons[0].sym
|
||||
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
|
||||
liMessage(n.info, errRecursiveDependencyX, callee.name.s)
|
||||
GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
|
||||
if not (sfNoSideEffect in callee.flags):
|
||||
if (sfForward in callee.flags) or
|
||||
({sfImportc, sfSideEffect} * callee.flags != {}):
|
||||
@@ -456,7 +454,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
add(msg, typeToString(n.sons[i].typ))
|
||||
add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
|
||||
typeToString(n.sons[0].typ))
|
||||
liMessage(n.Info, errGenerated, msg)
|
||||
GlobalError(n.Info, errGenerated, msg)
|
||||
result = nil
|
||||
else:
|
||||
result = m.call
|
||||
@@ -471,8 +469,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
n.sons[0] = prc
|
||||
result = semDirectCallAnalyseEffects(c, n, flags)
|
||||
if result == nil:
|
||||
liMessage(n.info, errExprXCannotBeCalled,
|
||||
renderTree(n, {renderNoComments}))
|
||||
GlobalError(n.info, errExprXCannotBeCalled,
|
||||
renderTree(n, {renderNoComments}))
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
|
||||
@@ -482,7 +480,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = semDirectCallAnalyseEffects(c, n, flags)
|
||||
if result == nil:
|
||||
result = overloadedCallOpr(c, n)
|
||||
if result == nil: liMessage(n.Info, errGenerated, getNotFoundError(c, n))
|
||||
if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
|
||||
@@ -517,12 +515,12 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
|
||||
else:
|
||||
result = StrTableGet(m.tab, ident)
|
||||
else:
|
||||
liMessage(n.sons[1].info, errIdentifierExpected, "")
|
||||
GlobalError(n.sons[1].info, errIdentifierExpected, "")
|
||||
of nkAccQuoted:
|
||||
checkSonsLen(n, 1)
|
||||
result = lookupForDefined(c, n.sons[0], onlyCurrentScope)
|
||||
else:
|
||||
liMessage(n.info, errIdentifierExpected, renderTree(n))
|
||||
GlobalError(n.info, errIdentifierExpected, renderTree(n))
|
||||
result = nil
|
||||
|
||||
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
|
||||
@@ -588,7 +586,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||
else:
|
||||
if check == nil:
|
||||
check = newNodeI(nkCheckedFieldExpr, n.info)
|
||||
addSon(check, nil) # make space for access node
|
||||
addSon(check, ast.emptyNode) # make space for access node
|
||||
s = newNodeI(nkCurly, n.info)
|
||||
for j in countup(0, sonsLen(it) - 2): addSon(s, copyTree(it.sons[j]))
|
||||
inExpr = newNodeI(nkCall, n.info)
|
||||
@@ -602,7 +600,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
|
||||
if result != nil:
|
||||
if check == nil:
|
||||
check = newNodeI(nkCheckedFieldExpr, n.info)
|
||||
addSon(check, nil) # make space for access node
|
||||
addSon(check, ast.emptyNode) # make space for access node
|
||||
inExpr = newNodeI(nkCall, n.info)
|
||||
addSon(inExpr, newIdentNode(getIdent("in"), n.info))
|
||||
addSon(inExpr, copyTree(r.sons[0]))
|
||||
@@ -653,10 +651,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.typ = ty
|
||||
markUsed(n, f)
|
||||
else:
|
||||
liMessage(n.sons[1].info, errEnumHasNoValueX, i.s)
|
||||
GlobalError(n.sons[1].info, errEnumHasNoValueX, i.s)
|
||||
return
|
||||
elif not (efAllowType in flags) and isTypeExpr(n.sons[0]):
|
||||
liMessage(n.sons[0].info, errATypeHasNoValue)
|
||||
GlobalError(n.sons[0].info, errATypeHasNoValue)
|
||||
return
|
||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||
var check: PNode = nil
|
||||
@@ -705,27 +703,27 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
addSon(result, newIdentNode(i, n.info))
|
||||
addSon(result, copyTree(n[0]))
|
||||
else:
|
||||
liMessage(n.Info, errUndeclaredFieldX, i.s)
|
||||
GlobalError(n.Info, errUndeclaredFieldX, i.s)
|
||||
|
||||
proc whichSliceOpr(n: PNode): string =
|
||||
if (n.sons[0] == nil):
|
||||
if (n.sons[1] == nil): result = "[..]"
|
||||
if n.sons[0].kind == nkEmpty:
|
||||
if n.sons[1].kind == nkEmpty: result = "[..]"
|
||||
else: result = "[..$]"
|
||||
elif (n.sons[1] == nil):
|
||||
elif n.sons[1].kind == nkEmpty:
|
||||
result = "[$..]"
|
||||
else:
|
||||
result = "[$..$]"
|
||||
|
||||
proc addSliceOpr(result: var string, n: PNode) =
|
||||
if n[0] == nil:
|
||||
if n[1] == nil: result.add("..")
|
||||
if n[0].kind == nkEmpty:
|
||||
if n[1].kind == nkEmpty: result.add("..")
|
||||
else: result.add("..$")
|
||||
elif n[1] == nil: result.add("$..")
|
||||
elif n[1].kind == nkEmpty: result.add("$..")
|
||||
else: result.add("$..$")
|
||||
|
||||
proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
|
||||
result = newNodeI(nkCall, n.info)
|
||||
add(result, nil) # fill with the correct node later
|
||||
add(result, ast.emptyNode) # fill with the correct node later
|
||||
add(result, n[0])
|
||||
var opr = "["
|
||||
for i in 1..n.len-1:
|
||||
@@ -734,8 +732,8 @@ proc buildOverloadedSubscripts(n: PNode, inAsgn: bool): PNode =
|
||||
# we have a slice argument
|
||||
checkSonsLen(n[i], 2)
|
||||
addSliceOpr(opr, n[i])
|
||||
addSonIfNotNil(result, n[i][0])
|
||||
addSonIfNotNil(result, n[i][1])
|
||||
addSon(result, n[i][0])
|
||||
addSon(result, n[i][1])
|
||||
else:
|
||||
add(result, n[i])
|
||||
if inAsgn: add(opr, "]=")
|
||||
@@ -757,7 +755,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var indexType = if arr.kind == tyArray: arr.sons[0] else: getSysType(tyInt)
|
||||
var arg = IndexTypesMatch(c, indexType, n.sons[1].typ, n.sons[1])
|
||||
if arg != nil: n.sons[1] = arg
|
||||
else: liMessage(n.info, errIndexTypesDoNotMatch)
|
||||
else: GlobalError(n.info, errIndexTypesDoNotMatch)
|
||||
result = n
|
||||
result.typ = elemType(arr)
|
||||
of tyTuple:
|
||||
@@ -769,9 +767,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
{tyInt..tyInt64}:
|
||||
var idx = getOrdValue(n.sons[1])
|
||||
if (idx >= 0) and (idx < sonsLen(arr)): n.typ = arr.sons[int(idx)]
|
||||
else: liMessage(n.info, errInvalidIndexValueForTuple)
|
||||
else: GlobalError(n.info, errInvalidIndexValueForTuple)
|
||||
else:
|
||||
liMessage(n.info, errIndexTypesDoNotMatch)
|
||||
GlobalError(n.info, errIndexTypesDoNotMatch)
|
||||
result = n
|
||||
else: nil
|
||||
|
||||
@@ -779,21 +777,7 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = semSubscript(c, n, flags)
|
||||
if result == nil:
|
||||
# overloaded [] operator:
|
||||
when false:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
if n.sons[1].kind == nkRange:
|
||||
checkSonsLen(n.sons[1], 2)
|
||||
addSon(result, newIdentNode(getIdent(whichSliceOpr(n.sons[1])), n.info))
|
||||
addSon(result, n.sons[0])
|
||||
addSonIfNotNil(result, n.sons[1].sons[0])
|
||||
addSonIfNotNil(result, n.sons[1].sons[1])
|
||||
else:
|
||||
addSon(result, newIdentNode(getIdent("[]"), n.info))
|
||||
addSon(result, n.sons[0])
|
||||
addSon(result, n.sons[1])
|
||||
result = semExpr(c, result)
|
||||
else:
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, inAsgn=false))
|
||||
|
||||
proc semIfExpr(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -839,7 +823,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
|
||||
if typ == nil:
|
||||
typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
|
||||
if not isOrdinalType(typ):
|
||||
liMessage(n.info, errOrdinalTypeExpected)
|
||||
GlobalError(n.info, errOrdinalTypeExpected)
|
||||
return
|
||||
if lengthOrd(typ) > MaxSetElements:
|
||||
typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
|
||||
@@ -871,11 +855,11 @@ proc checkPar(n: PNode): TParKind =
|
||||
if result == paTupleFields:
|
||||
if (n.sons[i].kind != nkExprColonExpr) or
|
||||
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
|
||||
liMessage(n.sons[i].info, errNamedExprExpected)
|
||||
GlobalError(n.sons[i].info, errNamedExprExpected)
|
||||
return paNone
|
||||
else:
|
||||
if n.sons[i].kind == nkExprColonExpr:
|
||||
liMessage(n.sons[i].info, errNamedExprNotAllowed)
|
||||
GlobalError(n.sons[i].info, errNamedExprNotAllowed)
|
||||
return paNone
|
||||
|
||||
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
||||
@@ -892,7 +876,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
||||
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
|
||||
else: id = n.sons[i].sons[0].sym.name
|
||||
if IntSetContainsOrIncl(ids, id.id):
|
||||
liMessage(n.sons[i].info, errFieldInitTwice, id.s)
|
||||
localError(n.sons[i].info, errFieldInitTwice, id.s)
|
||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
|
||||
var f = newSymS(skField, n.sons[i].sons[0], c)
|
||||
f.typ = n.sons[i].sons[1].typ
|
||||
@@ -925,7 +909,7 @@ proc semBlockExpr(c: PContext, n: PNode): PNode =
|
||||
Inc(c.p.nestedBlockCounter)
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab) # BUGFIX: label is in the scope of block!
|
||||
if n.sons[0] != nil: addDecl(c, newSymS(skLabel, n.sons[0], c))
|
||||
if n.sons[0].kind != nkEmpty: addDecl(c, newSymS(skLabel, n.sons[0], c))
|
||||
n.sons[1] = semStmtListExpr(c, n.sons[1])
|
||||
n.typ = n.sons[1].typ
|
||||
closeScope(c.tab)
|
||||
@@ -935,7 +919,7 @@ proc isCallExpr(n: PNode): bool =
|
||||
result = n.kind in {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit}
|
||||
|
||||
proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode =
|
||||
proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
checkMinSonsLen(n, 2)
|
||||
var a: PNode
|
||||
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
|
||||
@@ -957,23 +941,18 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck: bool = true): PNode =
|
||||
addSon(result, n.sons[0].sons[i])
|
||||
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
|
||||
result = semTemplateExpr(c, result, s, semCheck)
|
||||
else: liMessage(n.info, errXisNoMacroOrTemplate, s.name.s)
|
||||
else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
|
||||
else:
|
||||
liMessage(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
|
||||
GlobalError(n.info, errInvalidExpressionX, renderTree(a, {renderNoComments}))
|
||||
|
||||
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = n
|
||||
if n == nil: return
|
||||
if nfSem in n.flags: return
|
||||
case n.kind # atoms:
|
||||
of nkIdent:
|
||||
var s = lookUp(c, n)
|
||||
result = semSym(c, n, s, flags)
|
||||
of nkSym:
|
||||
#s := n.sym;
|
||||
# include(s.flags, sfUsed);
|
||||
# if (s.kind = skType) and not (efAllowType in flags) then
|
||||
# liMessage(n.info, errATypeHasNoValue);
|
||||
# because of the changed symbol binding, this does not mean that we
|
||||
# don't have to check the symbol for semantics here again!
|
||||
result = semSym(c, n, n.sym, flags)
|
||||
@@ -982,7 +961,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkNilLit:
|
||||
result.typ = getSysType(tyNil)
|
||||
of nkType:
|
||||
if not (efAllowType in flags): liMessage(n.info, errATypeHasNoValue)
|
||||
if not (efAllowType in flags): GlobalError(n.info, errATypeHasNoValue)
|
||||
n.typ = semTypeNode(c, n, nil)
|
||||
of nkIntLit:
|
||||
if result.typ == nil: result.typ = getSysType(tyInt)
|
||||
@@ -1020,7 +999,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of skMacro: result = semMacroExpr(c, n, s)
|
||||
of skTemplate: result = semTemplateExpr(c, n, s)
|
||||
of skType:
|
||||
if n.kind != nkCall: liMessage(n.info, errXisNotCallable, s.name.s)
|
||||
if n.kind != nkCall: GlobalError(n.info, errXisNotCallable, s.name.s)
|
||||
# XXX does this check make any sense?
|
||||
result = semConv(c, n, s)
|
||||
of skProc, skMethod, skConverter, skIterator:
|
||||
@@ -1062,14 +1041,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar})
|
||||
case t.kind
|
||||
of tyRef, tyPtr: n.typ = t.sons[0]
|
||||
else: liMessage(n.sons[0].info, errCircumNeedsPointer)
|
||||
else: GlobalError(n.sons[0].info, errCircumNeedsPointer)
|
||||
result = n
|
||||
of nkAddr:
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
if isAssignable(n.sons[0]) != arLValue:
|
||||
liMessage(n.info, errExprHasNoAddress)
|
||||
GlobalError(n.info, errExprHasNoAddress)
|
||||
n.typ = makePtrType(c, n.sons[0].typ)
|
||||
of nkHiddenAddr, nkHiddenDeref:
|
||||
checkSonsLen(n, 1)
|
||||
@@ -1091,8 +1070,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
of nkCheckedFieldExpr:
|
||||
checkMinSonsLen(n, 2)
|
||||
of nkSymChoice:
|
||||
liMessage(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
||||
GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
|
||||
else:
|
||||
#InternalError(n.info, nodeKindToStr[n.kind]);
|
||||
liMessage(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
|
||||
GlobalError(n.info, errInvalidExpressionX, renderTree(n, {renderNoComments}))
|
||||
incl(result.flags, nfSem)
|
||||
|
||||
@@ -334,8 +334,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
of mSizeOf:
|
||||
var a = n.sons[1]
|
||||
if computeSize(a.typ) < 0:
|
||||
liMessage(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof")
|
||||
if a.typ.kind in {tyArray, tyObject, tyTuple}:
|
||||
LocalError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
||||
"sizeof")
|
||||
result = nil
|
||||
elif a.typ.kind in {tyArray, tyObject, tyTuple}:
|
||||
result = nil
|
||||
# XXX: size computation for complex types is still wrong
|
||||
else:
|
||||
@@ -345,7 +347,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
of mHigh:
|
||||
if not (skipTypes(n.sons[1].typ, abstractVar).kind in
|
||||
{tyOpenArray, tySequence, tyString}):
|
||||
result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)), n)
|
||||
result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)),
|
||||
n)
|
||||
of mLengthOpenArray:
|
||||
var a = n.sons[1]
|
||||
if a.kind == nkPassAsOpenArray: a = a.sons[0]
|
||||
@@ -357,9 +360,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
else:
|
||||
result = magicCall(m, n)
|
||||
except EOverflow:
|
||||
liMessage(n.info, errOverOrUnderflow)
|
||||
LocalError(n.info, errOverOrUnderflow)
|
||||
except EDivByZero:
|
||||
liMessage(n.info, errConstantDivisionByZero)
|
||||
LocalError(n.info, errConstantDivisionByZero)
|
||||
of nkAddr:
|
||||
var a = getConstExpr(m, n.sons[0])
|
||||
if a != nil:
|
||||
@@ -408,7 +411,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result = a # a <= x and x <= b
|
||||
result.typ = n.typ
|
||||
else:
|
||||
liMessage(n.info, errGenerated, `%`(
|
||||
LocalError(n.info, errGenerated, `%`(
|
||||
msgKindToString(errIllegalConvFromXtoY),
|
||||
[typeToString(n.sons[0].typ), typeToString(n.typ)]))
|
||||
of nkStringToCString, nkCStringToString:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -55,7 +55,7 @@ proc getIdentNode(n: PNode): PNode =
|
||||
of nkIdent: result = n
|
||||
else:
|
||||
illFormedAst(n)
|
||||
result = nil
|
||||
result = n
|
||||
|
||||
# of nkAccQuoted:
|
||||
# s = lookUp(c, n)
|
||||
@@ -67,21 +67,20 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
L: int
|
||||
a: PNode
|
||||
result = n
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
var s = SymtabGet(c.Tab, n.ident)
|
||||
if s == nil:
|
||||
# no error if symbol cannot be bound, unless in ``bind`` context:
|
||||
if withinBind in flags:
|
||||
liMessage(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
localError(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
else:
|
||||
if withinBind in flags: result = symChoice(c, n, s)
|
||||
else: result = semGenericStmtSymbol(c, n, s)
|
||||
of nkDotExpr:
|
||||
var s = QualifiedLookUp(c, n, {})
|
||||
if s != nil: result = semGenericStmtSymbol(c, n, s)
|
||||
of nkSym..nkNilLit:
|
||||
of nkEmpty, nkSym..nkNilLit:
|
||||
nil
|
||||
of nkBind:
|
||||
result = semGenericStmt(c, n.sons[0], {withinBind})
|
||||
@@ -138,7 +137,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
of nkBlockStmt, nkBlockExpr, nkBlockType:
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab)
|
||||
if n.sons[0] != nil: addDecl(c, newSymS(skUnknown, n.sons[0], c))
|
||||
if n.sons[0].kind != nkEmpty: addDecl(c, newSymS(skUnknown, n.sons[0], c))
|
||||
n.sons[1] = semGenericStmt(c, n.sons[1])
|
||||
closeScope(c.tab)
|
||||
of nkTryStmt:
|
||||
@@ -193,7 +192,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkTypeDef): IllFormedAst(a)
|
||||
checkSonsLen(a, 3)
|
||||
if a.sons[1] != nil:
|
||||
if a.sons[1].kind != nkEmpty:
|
||||
openScope(c.tab)
|
||||
a.sons[1] = semGenericStmt(c, a.sons[1])
|
||||
a.sons[2] = semGenericStmt(c, a.sons[2], {withinTypeDesc})
|
||||
@@ -202,7 +201,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
a.sons[2] = semGenericStmt(c, a.sons[2], {withinTypeDesc})
|
||||
of nkEnumTy:
|
||||
checkMinSonsLen(n, 1)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
case n.sons[i].kind
|
||||
@@ -214,7 +213,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
nil
|
||||
of nkFormalParams:
|
||||
checkMinSonsLen(n, 1)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
@@ -231,8 +230,8 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
|
||||
addDecl(c, newSymS(skUnknown, getIdentNode(n.sons[0]), c))
|
||||
openScope(c.tab)
|
||||
n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos])
|
||||
if n.sons[paramsPos] != nil:
|
||||
if n.sons[paramsPos].sons[0] != nil:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
if n.sons[paramsPos].sons[0].kind != nkEmpty:
|
||||
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
|
||||
n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos])
|
||||
n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -48,7 +48,9 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
|
||||
var s = newSym(skType, q.name, getCurrOwner())
|
||||
var t = PType(IdTableGet(pt, q.typ))
|
||||
if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
|
||||
if t == nil:
|
||||
LocalError(a.info, errCannotInstantiateX, s.name.s)
|
||||
break
|
||||
if (t.kind == tyGenericParam):
|
||||
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
|
||||
s.typ = t
|
||||
@@ -94,13 +96,14 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
result.ast = n
|
||||
pushOwner(result)
|
||||
openScope(c.tab)
|
||||
if (n.sons[genericParamsPos] == nil):
|
||||
if (n.sons[genericParamsPos].kind == nkEmpty):
|
||||
InternalError(n.info, "generateInstance")
|
||||
n.sons[namePos] = newSymNode(result)
|
||||
pushInfoContext(info)
|
||||
instantiateGenericParamList(c, n.sons[genericParamsPos], pt)
|
||||
n.sons[genericParamsPos] = nil # semantic checking for the parameters:
|
||||
if n.sons[paramsPos] != nil:
|
||||
n.sons[genericParamsPos] = ast.emptyNode
|
||||
# semantic checking for the parameters:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[ParamsPos], nil, result)
|
||||
addParams(c, result.typ.n)
|
||||
else:
|
||||
@@ -112,7 +115,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
# add it here, so that recursive generic procs are possible:
|
||||
GenericCacheAdd(c, fn, result)
|
||||
addDecl(c, result)
|
||||
if n.sons[codePos] != nil:
|
||||
if n.sons[codePos].kind != nkEmpty:
|
||||
c.p = newProcCon(result)
|
||||
if result.kind in {skProc, skMethod, skConverter}:
|
||||
addResult(c, result.typ.sons[0], n.info)
|
||||
@@ -129,11 +132,11 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
|
||||
proc checkConstructedType(info: TLineInfo, t: PType) =
|
||||
if (tfAcyclic in t.flags) and (skipTypes(t, abstractInst).kind != tyObject):
|
||||
liMessage(info, errInvalidPragmaX, "acyclic")
|
||||
if computeSize(t) < 0:
|
||||
liMessage(info, errIllegalRecursionInTypeX, typeToString(t))
|
||||
if (t.kind == tyVar) and (t.sons[0].kind == tyVar):
|
||||
liMessage(info, errVarVarTypeNotAllowed)
|
||||
LocalError(info, errInvalidPragmaX, "acyclic")
|
||||
elif computeSize(t) < 0:
|
||||
LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
|
||||
elif (t.kind == tyVar) and (t.sons[0].kind == tyVar):
|
||||
LocalError(info, errVarVarTypeNotAllowed)
|
||||
|
||||
type
|
||||
TReplTypeVars{.final.} = object
|
||||
@@ -162,8 +165,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
|
||||
|
||||
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
if s == nil:
|
||||
return nil
|
||||
if s == nil: return nil
|
||||
result = PSym(idTableGet(cl.symMap, s))
|
||||
if result == nil:
|
||||
result = copySym(s, false)
|
||||
@@ -176,7 +178,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
|
||||
result = PType(idTableGet(cl.typeMap, t))
|
||||
if result == nil:
|
||||
liMessage(t.sym.info, errCannotInstantiateX, typeToString(t))
|
||||
GlobalError(t.sym.info, errCannotInstantiateX, typeToString(t))
|
||||
elif result.kind == tyGenericParam:
|
||||
InternalError(cl.info, "substitution with generic parameter")
|
||||
|
||||
@@ -210,7 +212,8 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
|
||||
idTablePut(gInstTypes, header, result)
|
||||
newbody = ReplaceTypeVarsT(cl, lastSon(body))
|
||||
newbody.n = ReplaceTypeVarsN(cl, lastSon(body).n)
|
||||
addSon(result, newbody) #writeln(output, ropeToStr(Typetoyaml(newbody)));
|
||||
addSon(result, newbody)
|
||||
#writeln(output, ropeToStr(Typetoyaml(newbody)));
|
||||
checkConstructedType(cl.info, newbody)
|
||||
of tyGenericBody:
|
||||
InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
|
||||
@@ -222,7 +225,7 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
|
||||
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
||||
result.n = ReplaceTypeVarsN(cl, result.n)
|
||||
if result.Kind in GenericTypes:
|
||||
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
|
||||
LocalError(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
|
||||
#writeln(output, ropeToStr(Typetoyaml(result)))
|
||||
#checkConstructedType(cl.info, result)
|
||||
|
||||
|
||||
265
rod/semstmts.nim
265
rod/semstmts.nim
@@ -12,13 +12,12 @@
|
||||
proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||
result = semExpr(c, n)
|
||||
if result.typ != nil and result.typ.kind != tyStmt:
|
||||
liMessage(n.info, errDiscardValue)
|
||||
localError(n.info, errDiscardValue)
|
||||
|
||||
proc semWhen(c: PContext, n: PNode): PNode =
|
||||
result = nil
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n)
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
@@ -43,7 +42,6 @@ proc semIf(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n)
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
@@ -61,12 +59,12 @@ proc semDiscard(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
if n.sons[0].typ == nil: liMessage(n.info, errInvalidDiscard)
|
||||
if n.sons[0].typ == nil: localError(n.info, errInvalidDiscard)
|
||||
|
||||
proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
var s: PSym
|
||||
case n.sons[0].kind
|
||||
of nkIdent: s = lookUp(c, n.sons[0])
|
||||
@@ -78,19 +76,20 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
||||
incl(s.flags, sfUsed)
|
||||
n.sons[0] = x
|
||||
else:
|
||||
liMessage(n.info, errInvalidControlFlowX, s.name.s)
|
||||
localError(n.info, errInvalidControlFlowX, s.name.s)
|
||||
elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0):
|
||||
liMessage(n.info, errInvalidControlFlowX, renderTree(n, {renderNoComments}))
|
||||
localError(n.info, errInvalidControlFlowX,
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
||||
proc semBlock(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
Inc(c.p.nestedBlockCounter)
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab) # BUGFIX: label is in the scope of block!
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
var labl = newSymS(skLabel, n.sons[0], c)
|
||||
addDecl(c, labl)
|
||||
n.sons[0] = newSymNode(labl) # BUGFIX
|
||||
n.sons[0] = newSymNode(labl)
|
||||
n.sons[1] = semStmt(c, n.sons[1])
|
||||
closeScope(c.tab)
|
||||
Dec(c.p.nestedBlockCounter)
|
||||
@@ -132,7 +131,9 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
chckCovered = true
|
||||
of tyFloat..tyFloat128, tyString:
|
||||
nil
|
||||
else: liMessage(n.info, errSelectorMustBeOfCertainTypes)
|
||||
else:
|
||||
LocalError(n.info, errSelectorMustBeOfCertainTypes)
|
||||
return
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
var x = n.sons[i]
|
||||
case x.kind
|
||||
@@ -153,7 +154,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
x.sons[0] = semStmtScope(c, x.sons[0])
|
||||
else: illFormedAst(x)
|
||||
if chckCovered and (covered != toCover(n.sons[0].typ)):
|
||||
liMessage(n.info, errNotAllCasesCovered)
|
||||
localError(n.info, errNotAllCasesCovered)
|
||||
closeScope(c.tab)
|
||||
|
||||
proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
|
||||
@@ -170,7 +171,7 @@ proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
else:
|
||||
liMessage(n.Info, errUndeclaredFieldX, id.s)
|
||||
globalError(n.Info, errUndeclaredFieldX, id.s)
|
||||
|
||||
proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, 2)
|
||||
@@ -197,7 +198,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
var le = a.typ
|
||||
if skipTypes(le, {tyGenericInst}).kind != tyVar and IsAssignable(a) == arNone:
|
||||
# Direct assignment to a discriminant is allowed!
|
||||
liMessage(a.info, errXCannotBeAssignedTo, renderTree(a, {renderNoComments}))
|
||||
localError(a.info, errXCannotBeAssignedTo,
|
||||
renderTree(a, {renderNoComments}))
|
||||
else:
|
||||
n.sons[1] = fitNode(c, le, n.sons[1])
|
||||
fixAbstractType(c, n)
|
||||
@@ -210,83 +212,84 @@ proc SemReturn(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
if not (c.p.owner.kind in {skConverter, skMethod, skProc, skMacro}):
|
||||
liMessage(n.info, errXNotAllowedHere, "\'return\'")
|
||||
if (n.sons[0] != nil):
|
||||
globalError(n.info, errXNotAllowedHere, "\'return\'")
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
|
||||
restype = c.p.owner.typ.sons[0]
|
||||
if (restype != nil):
|
||||
if restype != nil:
|
||||
a = newNodeI(nkAsgn, n.sons[0].info)
|
||||
n.sons[0] = fitNode(c, restype, n.sons[0])
|
||||
# optimize away ``return result``, because it would be transformed
|
||||
# to ``result = result; return``:
|
||||
if (n.sons[0].kind == nkSym) and (sfResult in n.sons[0].sym.flags):
|
||||
n.sons[0] = nil
|
||||
n.sons[0] = ast.emptyNode
|
||||
else:
|
||||
if (c.p.resultSym == nil): InternalError(n.info, "semReturn")
|
||||
addSon(a, semExprWithType(c, newSymNode(c.p.resultSym)))
|
||||
addSon(a, n.sons[0])
|
||||
n.sons[0] = a
|
||||
else:
|
||||
liMessage(n.info, errCannotReturnExpr)
|
||||
localError(n.info, errCannotReturnExpr)
|
||||
|
||||
proc SemYield(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
if (c.p.owner == nil) or (c.p.owner.kind != skIterator):
|
||||
liMessage(n.info, errYieldNotAllowedHere)
|
||||
if (n.sons[0] != nil):
|
||||
GlobalError(n.info, errYieldNotAllowedHere)
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
|
||||
var restype = c.p.owner.typ.sons[0]
|
||||
if (restype != nil):
|
||||
if restype != nil:
|
||||
n.sons[0] = fitNode(c, restype, n.sons[0])
|
||||
if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
|
||||
else:
|
||||
liMessage(n.info, errCannotReturnExpr)
|
||||
localError(n.info, errCannotReturnExpr)
|
||||
|
||||
proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
|
||||
result = fitNode(c, typ, n)
|
||||
if (result.kind in {nkHiddenStdConv, nkHiddenSubConv}):
|
||||
if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
|
||||
changeType(result.sons[1], typ)
|
||||
result = result.sons[1]
|
||||
elif not sameType(result.typ, typ):
|
||||
changeType(result, typ)
|
||||
|
||||
proc semVar(c: PContext, n: PNode): PNode =
|
||||
var
|
||||
length: int
|
||||
a, b, def: PNode
|
||||
typ, tup: PType
|
||||
v: PSym
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
|
||||
checkMinSonsLen(a, 3)
|
||||
length = sonsLen(a)
|
||||
if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil)
|
||||
else: typ = nil
|
||||
if a.sons[length - 1] != nil:
|
||||
def = semExprWithType(c, a.sons[length - 1])
|
||||
var length = sonsLen(a)
|
||||
var typ: PType
|
||||
if a.sons[length-2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a.sons[length-2], nil)
|
||||
else:
|
||||
typ = nil
|
||||
var def: PNode
|
||||
if a.sons[length-1].kind != nkEmpty:
|
||||
def = semExprWithType(c, a.sons[length-1])
|
||||
# BUGFIX: ``fitNode`` is needed here!
|
||||
# check type compability between def.typ and typ:
|
||||
if (typ != nil): def = fitNode(c, typ, def)
|
||||
if typ != nil: def = fitNode(c, typ, def)
|
||||
else: typ = def.typ
|
||||
else:
|
||||
def = nil
|
||||
def = ast.emptyNode
|
||||
if not typeAllowed(typ, skVar):
|
||||
liMessage(a.info, errXisNoType, typeToString(typ))
|
||||
tup = skipTypes(typ, {tyGenericInst})
|
||||
GlobalError(a.info, errXisNoType, typeToString(typ))
|
||||
var tup = skipTypes(typ, {tyGenericInst})
|
||||
if a.kind == nkVarTuple:
|
||||
if tup.kind != tyTuple: liMessage(a.info, errXExpected, "tuple")
|
||||
if tup.kind != tyTuple: GlobalError(a.info, errXExpected, "tuple")
|
||||
if length - 2 != sonsLen(tup):
|
||||
liMessage(a.info, errWrongNumberOfVariables)
|
||||
GlobalError(a.info, errWrongNumberOfVariables)
|
||||
b = newNodeI(nkVarTuple, a.info)
|
||||
newSons(b, length)
|
||||
b.sons[length - 2] = nil # no type desc
|
||||
b.sons[length - 2] = ast.emptyNode # no type desc
|
||||
b.sons[length - 1] = def
|
||||
addSon(result, b)
|
||||
for j in countup(0, length - 3):
|
||||
var v: PSym
|
||||
if (c.p.owner.kind == skModule):
|
||||
v = semIdentWithPragma(c, skVar, a.sons[j], {sfStar, sfMinus})
|
||||
incl(v.flags, sfGlobal)
|
||||
@@ -298,7 +301,7 @@ proc semVar(c: PContext, n: PNode): PNode =
|
||||
v.typ = typ
|
||||
b = newNodeI(nkIdentDefs, a.info)
|
||||
addSon(b, newSymNode(v))
|
||||
addSon(b, nil) # no type description
|
||||
addSon(b, ast.emptyNode) # no type description
|
||||
addSon(b, copyTree(def))
|
||||
addSon(result, b)
|
||||
else:
|
||||
@@ -306,57 +309,53 @@ proc semVar(c: PContext, n: PNode): PNode =
|
||||
b.sons[j] = newSymNode(v)
|
||||
|
||||
proc semConst(c: PContext, n: PNode): PNode =
|
||||
var
|
||||
a, def, b: PNode
|
||||
v: PSym
|
||||
typ: PType
|
||||
result = copyNode(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkConstDef): IllFormedAst(a)
|
||||
checkSonsLen(a, 3)
|
||||
var v: PSym
|
||||
if (c.p.owner.kind == skModule):
|
||||
v = semIdentWithPragma(c, skConst, a.sons[0], {sfStar, sfMinus})
|
||||
incl(v.flags, sfGlobal)
|
||||
else:
|
||||
v = semIdentWithPragma(c, skConst, a.sons[0], {})
|
||||
if a.sons[1] != nil: typ = semTypeNode(c, a.sons[1], nil)
|
||||
else: typ = nil
|
||||
def = semAndEvalConstExpr(c, a.sons[2])
|
||||
var typ: PType = nil
|
||||
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
|
||||
var def = semAndEvalConstExpr(c, a.sons[2])
|
||||
# check type compability between def.typ and typ:
|
||||
if (typ != nil):
|
||||
def = fitRemoveHiddenConv(c, typ, def)
|
||||
else:
|
||||
typ = def.typ
|
||||
if not typeAllowed(typ, skConst):
|
||||
liMessage(a.info, errXisNoType, typeToString(typ))
|
||||
GlobalError(a.info, errXisNoType, typeToString(typ))
|
||||
v.typ = typ
|
||||
v.ast = def # no need to copy
|
||||
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
|
||||
addInterfaceDecl(c, v)
|
||||
b = newNodeI(nkConstDef, a.info)
|
||||
var b = newNodeI(nkConstDef, a.info)
|
||||
addSon(b, newSymNode(v))
|
||||
addSon(b, nil) # no type description
|
||||
addSon(b, ast.emptyNode) # no type description
|
||||
addSon(b, copyTree(def))
|
||||
addSon(result, b)
|
||||
|
||||
proc semFor(c: PContext, n: PNode): PNode =
|
||||
var
|
||||
length: int
|
||||
v, countup: PSym
|
||||
iter: PType
|
||||
countupNode, call: PNode
|
||||
result = n
|
||||
checkMinSonsLen(n, 3)
|
||||
length = sonsLen(n)
|
||||
var length = sonsLen(n)
|
||||
openScope(c.tab)
|
||||
if n.sons[length - 2].kind == nkRange:
|
||||
checkSonsLen(n.sons[length - 2], 2)
|
||||
# convert ``in 3..5`` to ``in countup(3, 5)``
|
||||
countupNode = newNodeI(nkCall, n.sons[length - 2].info)
|
||||
countUp = StrTableGet(magicsys.systemModule.Tab, getIdent("countup"))
|
||||
if (countUp == nil): liMessage(countupNode.info, errSystemNeeds, "countup")
|
||||
if countUp == nil: GlobalError(countupNode.info, errSystemNeeds, "countup")
|
||||
newSons(countupNode, 3)
|
||||
countupnode.sons[0] = newSymNode(countup)
|
||||
countupNode.sons[1] = n.sons[length - 2].sons[0]
|
||||
@@ -366,16 +365,16 @@ proc semFor(c: PContext, n: PNode): PNode =
|
||||
call = n.sons[length - 2]
|
||||
if (call.kind != nkCall) or (call.sons[0].kind != nkSym) or
|
||||
(call.sons[0].sym.kind != skIterator):
|
||||
liMessage(n.sons[length - 2].info, errIteratorExpected)
|
||||
GlobalError(n.sons[length - 2].info, errIteratorExpected)
|
||||
iter = skipTypes(n.sons[length - 2].typ, {tyGenericInst})
|
||||
if iter.kind != tyTuple:
|
||||
if length != 3: liMessage(n.info, errWrongNumberOfVariables)
|
||||
if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
|
||||
v = newSymS(skForVar, n.sons[0], c)
|
||||
v.typ = iter
|
||||
n.sons[0] = newSymNode(v)
|
||||
addDecl(c, v)
|
||||
else:
|
||||
if length - 2 != sonsLen(iter): liMessage(n.info, errWrongNumberOfVariables)
|
||||
if length-2 != sonsLen(iter): GlobalError(n.info, errWrongNumberOfVariables)
|
||||
for i in countup(0, length - 3):
|
||||
v = newSymS(skForVar, n.sons[i], c)
|
||||
v.typ = iter.sons[i]
|
||||
@@ -389,11 +388,11 @@ proc semFor(c: PContext, n: PNode): PNode =
|
||||
proc semRaise(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
checkSonsLen(n, 1)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
var typ = n.sons[0].typ
|
||||
if (typ.kind != tyRef) or (typ.sons[0].kind != tyObject):
|
||||
liMessage(n.info, errExprCannotBeRaised)
|
||||
localError(n.info, errExprCannotBeRaised)
|
||||
|
||||
proc semTry(c: PContext, n: PNode): PNode =
|
||||
var check: TIntSet
|
||||
@@ -409,12 +408,12 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||
for j in countup(0, length - 2):
|
||||
var typ = semTypeNode(c, a.sons[j], nil)
|
||||
if typ.kind == tyRef: typ = typ.sons[0]
|
||||
if (typ.kind != tyObject):
|
||||
liMessage(a.sons[j].info, errExprCannotBeRaised)
|
||||
if typ.kind != tyObject:
|
||||
GlobalError(a.sons[j].info, errExprCannotBeRaised)
|
||||
a.sons[j] = newNodeI(nkType, a.sons[j].info)
|
||||
a.sons[j].typ = typ
|
||||
if IntSetContainsOrIncl(check, typ.id):
|
||||
liMessage(a.sons[j].info, errExceptionAlreadyHandled)
|
||||
localError(a.sons[j].info, errExceptionAlreadyHandled)
|
||||
elif a.kind != nkFinally:
|
||||
illFormedAst(n)
|
||||
# last child of an nkExcept/nkFinally branch is a statement:
|
||||
@@ -423,16 +422,16 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
result = copyNode(n)
|
||||
if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkIdentDefs: illFormedAst(n)
|
||||
var L = sonsLen(a)
|
||||
var def = a.sons[L - 1]
|
||||
var def = a.sons[L-1]
|
||||
var typ: PType
|
||||
if a.sons[L - 2] != nil: typ = semTypeNode(c, a.sons[L - 2], nil)
|
||||
elif def != nil: typ = newTypeS(tyExpr, c)
|
||||
if a.sons[L-2].kind != nkEmpty: typ = semTypeNode(c, a.sons[L-2], nil)
|
||||
elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
|
||||
else: typ = nil
|
||||
for j in countup(0, L - 3):
|
||||
for j in countup(0, L-3):
|
||||
var s: PSym
|
||||
if (typ == nil) or (typ.kind == tyTypeDesc):
|
||||
s = newSymS(skType, a.sons[j], c)
|
||||
@@ -441,7 +440,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
# not a type param, but an expression
|
||||
s = newSymS(skGenericParam, a.sons[j], c)
|
||||
s.typ = typ
|
||||
s.ast = def
|
||||
if def.kind != nkEmpty: s.ast = def
|
||||
s.typ.sym = s
|
||||
if father != nil: addSon(father, s.typ)
|
||||
s.position = i
|
||||
@@ -451,7 +450,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
proc addGenericParamListToScope(c: PContext, n: PNode) =
|
||||
if n.kind != nkGenericParams:
|
||||
InternalError(n.info, "addGenericParamListToScope")
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkSym: internalError(a.info, "addGenericParamListToScope")
|
||||
addDecl(c, a.sym)
|
||||
@@ -466,7 +465,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if (a.kind != nkTypeDef): IllFormedAst(a)
|
||||
if a.kind != nkTypeDef: IllFormedAst(a)
|
||||
checkSonsLen(a, 3)
|
||||
if (c.p.owner.kind == skModule):
|
||||
s = semIdentWithPragma(c, skType, a.sons[0], {sfStar, sfMinus})
|
||||
@@ -488,10 +487,10 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(a, 3)
|
||||
if (a.sons[0].kind != nkSym): IllFormedAst(a)
|
||||
s = a.sons[0].sym
|
||||
if (s.magic == mNone) and (a.sons[2] == nil):
|
||||
liMessage(a.info, errImplOfXexpected, s.name.s)
|
||||
if (s.magic == mNone) and (a.sons[2].kind == nkEmpty):
|
||||
GlobalError(a.info, errImplOfXexpected, s.name.s)
|
||||
if s.magic != mNone: processMagicType(c, s)
|
||||
if a.sons[1] != nil:
|
||||
if a.sons[1].kind != nkEmpty:
|
||||
# We have a generic type declaration here. In generic types,
|
||||
# symbol lookup needs to be done here.
|
||||
openScope(c.tab)
|
||||
@@ -508,7 +507,7 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
|
||||
s.typ.sons[sonsLen(s.typ) - 1] = body #debug(s.typ);
|
||||
popOwner()
|
||||
closeScope(c.tab)
|
||||
elif a.sons[2] != nil:
|
||||
elif a.sons[2].kind != nkEmpty:
|
||||
# process the type's body:
|
||||
pushOwner(s)
|
||||
t = semTypeNode(c, a.sons[2], s.typ)
|
||||
@@ -523,9 +522,8 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
|
||||
if (a.sons[0].kind != nkSym): IllFormedAst(a)
|
||||
s = a.sons[0].sym
|
||||
# compute the type's size and check for illegal recursions:
|
||||
if a.sons[1] == nil:
|
||||
if (a.sons[2] != nil) and
|
||||
(a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}):
|
||||
if a.sons[1].kind == nkEmpty:
|
||||
if (a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}):
|
||||
# type aliases are hard:
|
||||
#MessageOut('for type ' + typeToString(s.typ));
|
||||
t = semTypeNode(c, a.sons[2], nil)
|
||||
@@ -538,21 +536,23 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
|
||||
s.typ = semProcTypeNode(c, n, genericParams, nil)
|
||||
|
||||
proc addParams(c: PContext, n: PNode) =
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
for i in countup(1, sonsLen(n)-1):
|
||||
if (n.sons[i].kind != nkSym): InternalError(n.info, "addParams")
|
||||
addDecl(c, n.sons[i].sym)
|
||||
|
||||
proc semBorrow(c: PContext, n: PNode, s: PSym) =
|
||||
# search for the correct alias:
|
||||
var b = SearchForBorrowProc(c, s, c.tab.tos - 2)
|
||||
if b == nil:
|
||||
liMessage(n.info, errNoSymbolToBorrowFromFound) # store the alias:
|
||||
n.sons[codePos] = newSymNode(b)
|
||||
if b != nil:
|
||||
# store the alias:
|
||||
n.sons[codePos] = newSymNode(b)
|
||||
else:
|
||||
LocalError(n.info, errNoSymbolToBorrowFromFound)
|
||||
|
||||
proc sideEffectsCheck(c: PContext, s: PSym) =
|
||||
if {sfNoSideEffect, sfSideEffect} * s.flags ==
|
||||
{sfNoSideEffect, sfSideEffect}:
|
||||
liMessage(s.info, errXhasSideEffects, s.name.s)
|
||||
LocalError(s.info, errXhasSideEffects, s.name.s)
|
||||
|
||||
proc addResult(c: PContext, t: PType, info: TLineInfo) =
|
||||
if t != nil:
|
||||
@@ -577,26 +577,27 @@ proc semLambda(c: PContext, n: PNode): PNode =
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
pushOwner(s)
|
||||
openScope(c.tab)
|
||||
if (n.sons[genericParamsPos] != nil):
|
||||
if (n.sons[genericParamsPos].kind != nkEmpty):
|
||||
illFormedAst(n) # process parameters:
|
||||
if n.sons[paramsPos] != nil:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[ParamsPos], nil, s)
|
||||
addParams(c, s.typ.n)
|
||||
else:
|
||||
s.typ = newTypeS(tyProc, c)
|
||||
addSon(s.typ, nil)
|
||||
s.typ.callConv = ccClosure
|
||||
if n.sons[pragmasPos] != nil: pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
|
||||
if n.sons[pragmasPos].kind != nkEmpty:
|
||||
pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
|
||||
s.options = gOptions
|
||||
if n.sons[codePos] != nil:
|
||||
if n.sons[codePos].kind != nkEmpty:
|
||||
if sfImportc in s.flags:
|
||||
liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||
c.p = newProcCon(s)
|
||||
addResult(c, s.typ.sons[0], n.info)
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
addResultNode(c, n)
|
||||
else:
|
||||
liMessage(n.info, errImplOfXexpected, s.name.s)
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
closeScope(c.tab) # close scope for parameters
|
||||
popOwner()
|
||||
c.p = oldP # restore
|
||||
@@ -620,16 +621,16 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
s.ast = n
|
||||
pushOwner(s)
|
||||
openScope(c.tab)
|
||||
if n.sons[genericParamsPos] != nil:
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
|
||||
gp = n.sons[genericParamsPos]
|
||||
else:
|
||||
gp = newNodeI(nkGenericParams, n.info)
|
||||
# process parameters:
|
||||
if n.sons[paramsPos] != nil:
|
||||
if n.sons[paramsPos].kind != nkEmpty:
|
||||
semParamList(c, n.sons[ParamsPos], gp, s)
|
||||
if sonsLen(gp) > 0:
|
||||
if n.sons[genericParamsPos] == nil:
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
# we have a list of implicit type parameters:
|
||||
n.sons[genericParamsPos] = gp
|
||||
# check for semantics again:
|
||||
@@ -651,16 +652,17 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
|
||||
else:
|
||||
addInterfaceDeclAt(c, s, c.tab.tos - 2)
|
||||
if n.sons[pragmasPos] != nil: pragma(c, s, n.sons[pragmasPos], validPragmas)
|
||||
if n.sons[pragmasPos].kind != nkEmpty:
|
||||
pragma(c, s, n.sons[pragmasPos], validPragmas)
|
||||
else:
|
||||
if n.sons[pragmasPos] != nil:
|
||||
liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
|
||||
if n.sons[pragmasPos].kind != nkEmpty:
|
||||
LocalError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc)
|
||||
if sfForward notin proto.flags:
|
||||
liMessage(n.info, errAttemptToRedefineX, proto.name.s)
|
||||
LocalError(n.info, errAttemptToRedefineX, proto.name.s)
|
||||
excl(proto.flags, sfForward)
|
||||
closeScope(c.tab) # close scope with wrong parameter symbols
|
||||
openScope(c.tab) # open scope for old (correct) parameter symbols
|
||||
if proto.ast.sons[genericParamsPos] != nil:
|
||||
if proto.ast.sons[genericParamsPos].kind != nkEmpty:
|
||||
addGenericParamListToScope(c, proto.ast.sons[genericParamsPos])
|
||||
addParams(c, proto.typ.n)
|
||||
proto.info = s.info # more accurate line information
|
||||
@@ -674,27 +676,27 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
popOwner()
|
||||
pushOwner(s)
|
||||
s.options = gOptions
|
||||
if n.sons[codePos] != nil:
|
||||
# for DLL generation, it is annoying to check for sfImportc!
|
||||
if n.sons[codePos].kind != nkEmpty:
|
||||
# for DLL generation it is annoying to check for sfImportc!
|
||||
if sfBorrow in s.flags:
|
||||
liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||
if (n.sons[genericParamsPos] == nil):
|
||||
LocalError(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s)
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
c.p = newProcCon(s)
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||
addResult(c, s.typ.sons[0], n.info)
|
||||
if sfImportc notin s.flags:
|
||||
# no semantic checking for importc:
|
||||
n.sons[codePos] = semStmtScope(c, n.sons[codePos])
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator): addResultNode(c, n)
|
||||
if s.typ.sons[0] != nil and kind != skIterator: addResultNode(c, n)
|
||||
else:
|
||||
if (s.typ.sons[0] != nil) and (kind != skIterator):
|
||||
if s.typ.sons[0] != nil and kind != skIterator:
|
||||
addDecl(c, newSym(skUnknown, getIdent("result"), nil))
|
||||
n.sons[codePos] = semGenericStmtScope(c, n.sons[codePos])
|
||||
if sfImportc in s.flags:
|
||||
# so we just ignore the body after semantic checking for importc:
|
||||
n.sons[codePos] = nil
|
||||
n.sons[codePos] = ast.emptyNode
|
||||
else:
|
||||
if proto != nil: liMessage(n.info, errImplOfXexpected, proto.name.s)
|
||||
if proto != nil: LocalError(n.info, errImplOfXexpected, proto.name.s)
|
||||
if {sfImportc, sfBorrow} * s.flags == {}: incl(s.flags, sfForward)
|
||||
elif sfBorrow in s.flags: semBorrow(c, n, s)
|
||||
sideEffectsCheck(c, s)
|
||||
@@ -706,14 +708,16 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
||||
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "iterator")
|
||||
if n.sons[codePos] == nil: liMessage(n.info, errImplOfXexpected, s.name.s)
|
||||
if t.sons[0] == nil:
|
||||
LocalError(n.info, errXNeedsReturnType, "iterator")
|
||||
if n.sons[codePos].kind == nkEmpty:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
|
||||
proc semProc(c: PContext, n: PNode): PNode =
|
||||
result = semProcAux(c, n, skProc, procPragmas)
|
||||
|
||||
proc semMethod(c: PContext, n: PNode): PNode =
|
||||
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "method")
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "method")
|
||||
result = semProcAux(c, n, skMethod, methodPragmas)
|
||||
|
||||
var s = result.sons[namePos].sym
|
||||
@@ -728,30 +732,31 @@ proc semMethod(c: PContext, n: PNode): PNode =
|
||||
# XXX this not really correct way to do it: Perhaps it should be done after
|
||||
# generic instantiation. Well it's good enough for now:
|
||||
if not hasObjParam:
|
||||
liMessage(n.info, errXNeedsParamObjectType, "method")
|
||||
LocalError(n.info, errXNeedsParamObjectType, "method")
|
||||
|
||||
proc semConverterDef(c: PContext, n: PNode): PNode =
|
||||
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "converter")
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "converter")
|
||||
checkSonsLen(n, codePos + 1)
|
||||
if n.sons[genericParamsPos] != nil:
|
||||
liMessage(n.info, errNoGenericParamsAllowedForX, "converter")
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
LocalError(n.info, errNoGenericParamsAllowedForX, "converter")
|
||||
result = semProcAux(c, n, skConverter, converterPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "converter")
|
||||
if sonsLen(t) != 2: liMessage(n.info, errXRequiresOneArgument, "converter")
|
||||
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "converter")
|
||||
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "converter")
|
||||
addConverter(c, s)
|
||||
|
||||
proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, codePos + 1)
|
||||
if n.sons[genericParamsPos] != nil:
|
||||
liMessage(n.info, errNoGenericParamsAllowedForX, "macro")
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
LocalError(n.info, errNoGenericParamsAllowedForX, "macro")
|
||||
result = semProcAux(c, n, skMacro, macroPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: liMessage(n.info, errXNeedsReturnType, "macro")
|
||||
if sonsLen(t) != 2: liMessage(n.info, errXRequiresOneArgument, "macro")
|
||||
if n.sons[codePos] == nil: liMessage(n.info, errImplOfXexpected, s.name.s)
|
||||
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
|
||||
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "macro")
|
||||
if n.sons[codePos].kind == nkEmpty:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
|
||||
proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
@@ -760,7 +765,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
|
||||
var f = getModuleFile(n.sons[i])
|
||||
var fileIndex = includeFilename(f)
|
||||
if IntSetContainsOrIncl(c.includedFiles, fileIndex):
|
||||
liMessage(n.info, errRecursiveDependencyX, f)
|
||||
GlobalError(n.info, errRecursiveDependencyX, f)
|
||||
addSon(result, semStmt(c, gIncludeFile(f)))
|
||||
IntSetExcl(c.includedFiles, fileIndex)
|
||||
|
||||
@@ -771,7 +776,6 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
const # must be last statements in a block:
|
||||
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
||||
result = n
|
||||
if n == nil: return
|
||||
if nfSem in n.flags: return
|
||||
case n.kind
|
||||
of nkAsgn: result = semAsgn(c, n)
|
||||
@@ -783,12 +787,11 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
var length = sonsLen(n)
|
||||
for i in countup(0, length - 1):
|
||||
n.sons[i] = semStmt(c, n.sons[i])
|
||||
if (n.sons[i].kind in LastBlockStmts):
|
||||
if n.sons[i].kind in LastBlockStmts:
|
||||
for j in countup(i + 1, length - 1):
|
||||
case n.sons[j].kind
|
||||
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty:
|
||||
nil
|
||||
else: liMessage(n.sons[j].info, errStmtInvalidAfterReturn)
|
||||
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty: nil
|
||||
else: localError(n.sons[j].info, errStmtInvalidAfterReturn)
|
||||
of nkRaiseStmt: result = semRaise(c, n)
|
||||
of nkVarSection: result = semVar(c, n)
|
||||
of nkConstSection: result = semConst(c, n)
|
||||
@@ -812,15 +815,15 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
of nkMacroDef: result = semMacroDef(c, n)
|
||||
of nkTemplateDef: result = semTemplateDef(c, n)
|
||||
of nkImportStmt:
|
||||
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "import")
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "import")
|
||||
result = evalImport(c, n)
|
||||
of nkFromStmt:
|
||||
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "from")
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "from")
|
||||
result = evalFrom(c, n)
|
||||
of nkIncludeStmt:
|
||||
if not isTopLevel(c): liMessage(n.info, errXOnlyAtModuleScope, "include")
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
|
||||
result = evalInclude(c, n)
|
||||
else: liMessage(n.info, errStmtExpected)
|
||||
else: LocalError(n.info, errStmtExpected)
|
||||
if result == nil: InternalError(n.info, "SemStmt: result = nil")
|
||||
incl(result.flags, nfSem)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
proc isExpr(n: PNode): bool =
|
||||
# returns true if ``n`` looks like an expression
|
||||
if n == nil:
|
||||
return false
|
||||
case n.kind
|
||||
of nkIdent..nkNilLit:
|
||||
result = true
|
||||
@@ -23,8 +21,6 @@ proc isExpr(n: PNode): bool =
|
||||
|
||||
proc isTypeDesc(n: PNode): bool =
|
||||
# returns true if ``n`` looks like a type desc
|
||||
if n == nil:
|
||||
return false
|
||||
case n.kind
|
||||
of nkIdent, nkSym, nkType:
|
||||
result = true
|
||||
@@ -38,12 +34,9 @@ proc isTypeDesc(n: PNode): bool =
|
||||
else: result = false
|
||||
|
||||
proc evalTemplateAux(c: PContext, templ, actual: PNode, sym: PSym): PNode =
|
||||
var p: PSym
|
||||
if templ == nil:
|
||||
return nil
|
||||
case templ.kind
|
||||
of nkSym:
|
||||
p = templ.sym
|
||||
var p = templ.sym
|
||||
if (p.kind == skParam) and (p.owner.id == sym.id):
|
||||
result = copyTree(actual.sons[p.position])
|
||||
else:
|
||||
@@ -63,32 +56,38 @@ proc evalTemplateArgs(c: PContext, n: PNode, s: PSym): PNode =
|
||||
var
|
||||
f, a: int
|
||||
arg: PNode
|
||||
f = sonsLen(s.typ) # if the template has zero arguments, it can be called without ``()``
|
||||
# `n` is then a nkSym or something similar
|
||||
f = sonsLen(s.typ)
|
||||
# if the template has zero arguments, it can be called without ``()``
|
||||
# `n` is then a nkSym or something similar
|
||||
case n.kind
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||
a = sonsLen(n)
|
||||
else: a = 0
|
||||
if a > f: liMessage(n.info, errWrongNumberOfArguments)
|
||||
if a > f: LocalError(n.info, errWrongNumberOfArguments)
|
||||
result = copyNode(n)
|
||||
for i in countup(1, f - 1):
|
||||
if i < a: arg = n.sons[i]
|
||||
else: arg = copyTree(s.typ.n.sons[i].sym.ast)
|
||||
if arg == nil: liMessage(n.info, errWrongNumberOfArguments)
|
||||
if not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}):
|
||||
if arg == nil or arg.kind == nkEmpty:
|
||||
LocalError(n.info, errWrongNumberOfArguments)
|
||||
elif not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}):
|
||||
# concrete type means semantic checking for argument:
|
||||
# XXX This is horrible! Better make semantic checking use some kind
|
||||
# of fixpoint iteration ...
|
||||
arg = fitNode(c, s.typ.sons[i], semExprWithType(c, arg))
|
||||
addSon(result, arg)
|
||||
|
||||
proc evalTemplate(c: PContext, n: PNode, sym: PSym): PNode =
|
||||
var args: PNode
|
||||
inc(evalTemplateCounter)
|
||||
if evalTemplateCounter > 100:
|
||||
liMessage(n.info, errTemplateInstantiationTooNested)
|
||||
# replace each param by the corresponding node:
|
||||
args = evalTemplateArgs(c, n, sym)
|
||||
result = evalTemplateAux(c, sym.ast.sons[codePos], args, sym)
|
||||
dec(evalTemplateCounter)
|
||||
if evalTemplateCounter <= 100:
|
||||
# replace each param by the corresponding node:
|
||||
args = evalTemplateArgs(c, n, sym)
|
||||
result = evalTemplateAux(c, sym.ast.sons[codePos], args, sym)
|
||||
dec(evalTemplateCounter)
|
||||
else:
|
||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||
result = n
|
||||
|
||||
proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
|
||||
var
|
||||
@@ -116,8 +115,6 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
|
||||
toBind: var TIntSet): PNode =
|
||||
var s: PSym
|
||||
if n == nil:
|
||||
return nil
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
if not withinBind and not IntSetContains(toBind, n.ident.id):
|
||||
@@ -130,7 +127,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
|
||||
else:
|
||||
IntSetIncl(toBind, n.ident.id)
|
||||
result = symChoice(c, n, lookup(c, n))
|
||||
of nkSym..nkNilLit: # atom
|
||||
of nkEmpty, nkSym..nkNilLit: # atom
|
||||
result = n
|
||||
of nkBind:
|
||||
result = resolveTemplateParams(c, n.sons[0], true, toBind)
|
||||
@@ -155,7 +152,8 @@ proc transformToExpr(n: PNode): PNode =
|
||||
if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
|
||||
else: n.kind = nkStmtListExpr
|
||||
of nkBlockStmt:
|
||||
n.kind = nkBlockExpr #nkIfStmt: n.kind := nkIfExpr; // this is not correct!
|
||||
n.kind = nkBlockExpr
|
||||
#nkIfStmt: n.kind := nkIfExpr; // this is not correct!
|
||||
else:
|
||||
nil
|
||||
|
||||
@@ -173,11 +171,12 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
pushOwner(s)
|
||||
openScope(c.tab)
|
||||
n.sons[namePos] = newSymNode(s) # check that no pragmas exist:
|
||||
if n.sons[pragmasPos] != nil:
|
||||
liMessage(n.info, errNoPragmasAllowedForX, "template") # check that no generic parameters exist:
|
||||
if n.sons[genericParamsPos] != nil:
|
||||
liMessage(n.info, errNoGenericParamsAllowedForX, "template")
|
||||
if (n.sons[paramsPos] == nil):
|
||||
if n.sons[pragmasPos].kind != nkEmpty:
|
||||
LocalError(n.info, errNoPragmasAllowedForX, "template")
|
||||
# check that no generic parameters exist:
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
LocalError(n.info, errNoGenericParamsAllowedForX, "template")
|
||||
if n.sons[paramsPos].kind == nkEmpty:
|
||||
# use ``stmt`` as implicit result type
|
||||
s.typ = newTypeS(tyProc, c)
|
||||
s.typ.n = newNodeI(nkFormalParams, n.info)
|
||||
@@ -185,7 +184,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
|
||||
else:
|
||||
semParamList(c, n.sons[ParamsPos], nil, s)
|
||||
if n.sons[paramsPos].sons[0] == nil:
|
||||
if n.sons[paramsPos].sons[0].kind == nkEmpty:
|
||||
# use ``stmt`` as implicit result type
|
||||
s.typ.sons[0] = newTypeS(tyStmt, c)
|
||||
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
|
||||
@@ -193,12 +192,13 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
IntSetInit(toBind)
|
||||
n.sons[codePos] = resolveTemplateParams(c, n.sons[codePos], false, toBind)
|
||||
if not (s.typ.sons[0].kind in {tyStmt, tyTypeDesc}):
|
||||
n.sons[codePos] = transformToExpr(n.sons[codePos]) # only parameters are resolved, no type checking is performed
|
||||
n.sons[codePos] = transformToExpr(n.sons[codePos])
|
||||
# only parameters are resolved, no type checking is performed
|
||||
closeScope(c.tab)
|
||||
popOwner()
|
||||
s.ast = n
|
||||
result = n
|
||||
if n.sons[codePos] == nil:
|
||||
liMessage(n.info, errImplOfXexpected, s.name.s) # add identifier of template as a last step to not allow
|
||||
# recursive templates
|
||||
if n.sons[codePos].kind == nkEmpty:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
# add identifier of template as a last step to not allow recursive templates:
|
||||
addInterfaceDecl(c, s)
|
||||
|
||||
155
rod/semtypes.nim
155
rod/semtypes.nim
@@ -30,10 +30,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyEnum, prev, c)
|
||||
result.n = newNodeI(nkEnumTy, n.info)
|
||||
checkMinSonsLen(n, 1)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
base = semTypeNode(c, n.sons[0].sons[0], nil)
|
||||
if base.kind != tyEnum:
|
||||
liMessage(n.sons[0].info, errInheritanceOnlyWithEnums)
|
||||
localError(n.sons[0].info, errInheritanceOnlyWithEnums)
|
||||
counter = lastOrd(base) + 1
|
||||
addSon(result, base)
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
@@ -44,10 +44,10 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
var strVal: PNode = nil
|
||||
case skipTypes(v.typ, abstractInst).kind
|
||||
of tyTuple:
|
||||
if sonsLen(v) != 2: liMessage(v.info, errWrongNumberOfVariables)
|
||||
if sonsLen(v) != 2: GlobalError(v.info, errWrongNumberOfVariables)
|
||||
strVal = v.sons[1] # second tuple part is the string value
|
||||
if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}:
|
||||
liMessage(strVal.info, errStringLiteralExpected)
|
||||
GlobalError(strVal.info, errStringLiteralExpected)
|
||||
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
|
||||
of tyString, tyCstring:
|
||||
strVal = v
|
||||
@@ -57,7 +57,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
if i != 1:
|
||||
if (x != counter): incl(result.flags, tfEnumHasWholes)
|
||||
if x < counter:
|
||||
liMessage(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
|
||||
GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
|
||||
e.ast = strVal # might be nil
|
||||
counter = x
|
||||
of nkSym:
|
||||
@@ -82,10 +82,10 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||
addSon(result, base)
|
||||
if base.kind == tyGenericInst: base = lastSon(base)
|
||||
if base.kind != tyGenericParam:
|
||||
if not isOrdinalType(base): liMessage(n.info, errOrdinalTypeExpected)
|
||||
if lengthOrd(base) > MaxSetElements: liMessage(n.info, errSetTooBig)
|
||||
if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected)
|
||||
if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, "set")
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, "set")
|
||||
|
||||
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
prev: PType): PType =
|
||||
@@ -94,7 +94,7 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
|
||||
proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
prev: PType): PType =
|
||||
@@ -103,38 +103,38 @@ proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
|
||||
var base = semTypeNode(c, n.sons[0], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
|
||||
|
||||
proc semVarType(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyVar, prev, c)
|
||||
if sonsLen(n) == 1:
|
||||
var base = semTypeNode(c, n.sons[0], nil)
|
||||
if base.kind == tyVar: liMessage(n.info, errVarVarTypeNotAllowed)
|
||||
if base.kind == tyVar: GlobalError(n.info, errVarVarTypeNotAllowed)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, "var")
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, "var")
|
||||
|
||||
proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyDistinct, prev, c)
|
||||
if sonsLen(n) == 1: addSon(result, semTypeNode(c, n.sons[0], nil))
|
||||
else: liMessage(n.info, errXExpectsOneTypeParam, "distinct")
|
||||
else: GlobalError(n.info, errXExpectsOneTypeParam, "distinct")
|
||||
|
||||
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
|
||||
if (n.kind != nkRange): InternalError(n.info, "semRangeAux")
|
||||
checkSonsLen(n, 2)
|
||||
result = newOrPrevType(tyRange, prev, c)
|
||||
result.n = newNodeI(nkRange, n.info)
|
||||
if (n.sons[0] == nil) or (n.sons[1] == nil):
|
||||
liMessage(n.Info, errRangeIsEmpty)
|
||||
if (n.sons[0].kind == nkEmpty) or (n.sons[1].kind == nkEmpty):
|
||||
GlobalError(n.Info, errRangeIsEmpty)
|
||||
var a = semConstExpr(c, n.sons[0])
|
||||
var b = semConstExpr(c, n.sons[1])
|
||||
if not sameType(a.typ, b.typ): liMessage(n.info, errPureTypeMismatch)
|
||||
if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch)
|
||||
if not (a.typ.kind in
|
||||
{tyInt..tyInt64, tyEnum, tyBool, tyChar, tyFloat..tyFloat128}):
|
||||
liMessage(n.info, errOrdinalTypeExpected)
|
||||
GlobalError(n.info, errOrdinalTypeExpected)
|
||||
if enumHasWholes(a.typ):
|
||||
liMessage(n.info, errEnumXHasHoles, a.typ.sym.name.s)
|
||||
if not leValue(a, b): liMessage(n.Info, errRangeIsEmpty)
|
||||
GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
|
||||
if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty)
|
||||
addSon(result.n, a)
|
||||
addSon(result.n, b)
|
||||
addSon(result, b.typ)
|
||||
@@ -143,9 +143,9 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = nil
|
||||
if sonsLen(n) == 2:
|
||||
if n.sons[1].kind == nkRange: result = semRangeAux(c, n.sons[1], prev)
|
||||
else: liMessage(n.sons[0].info, errRangeExpected)
|
||||
else: GlobalError(n.sons[0].info, errRangeExpected)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, "range")
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, "range")
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var indx, base: PType
|
||||
@@ -158,13 +158,13 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
if indx.kind == tyGenericInst: indx = lastSon(indx)
|
||||
if indx.kind != tyGenericParam:
|
||||
if not isOrdinalType(indx):
|
||||
liMessage(n.sons[1].info, errOrdinalTypeExpected)
|
||||
GlobalError(n.sons[1].info, errOrdinalTypeExpected)
|
||||
if enumHasWholes(indx):
|
||||
liMessage(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
|
||||
GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
|
||||
base = semTypeNode(c, n.sons[2], nil)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errArrayExpectsTwoTypeParams)
|
||||
GlobalError(n.info, errArrayExpectsTwoTypeParams)
|
||||
|
||||
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = newOrPrevType(tyOrdinal, prev, c)
|
||||
@@ -172,46 +172,44 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base = semTypeNode(c, n.sons[1], nil)
|
||||
if base.kind != tyGenericParam:
|
||||
if not isOrdinalType(base):
|
||||
liMessage(n.sons[1].info, errOrdinalTypeExpected)
|
||||
GlobalError(n.sons[1].info, errOrdinalTypeExpected)
|
||||
addSon(result, base)
|
||||
else:
|
||||
liMessage(n.info, errXExpectsOneTypeParam, "ordinal")
|
||||
GlobalError(n.info, errXExpectsOneTypeParam, "ordinal")
|
||||
|
||||
proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
result = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
|
||||
if (result != nil):
|
||||
markUsed(n, result)
|
||||
if result.kind != skType: liMessage(n.info, errTypeExpected)
|
||||
if result.kind != skType: GlobalError(n.info, errTypeExpected)
|
||||
else:
|
||||
liMessage(n.info, errIdentifierExpected)
|
||||
GlobalError(n.info, errIdentifierExpected)
|
||||
|
||||
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
var
|
||||
length, counter: int
|
||||
typ: PType
|
||||
check: TIntSet
|
||||
a: PNode
|
||||
field: PSym
|
||||
result = newOrPrevType(tyTuple, prev, c)
|
||||
result.n = newNodeI(nkRecList, n.info)
|
||||
IntSetInit(check)
|
||||
counter = 0
|
||||
var counter = 0
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
var a = n.sons[i]
|
||||
if (a.kind != nkIdentDefs): IllFormedAst(a)
|
||||
checkMinSonsLen(a, 3)
|
||||
length = sonsLen(a)
|
||||
if a.sons[length - 2] != nil: typ = semTypeNode(c, a.sons[length - 2], nil)
|
||||
else: liMessage(a.info, errTypeExpected)
|
||||
if a.sons[length - 1] != nil:
|
||||
liMessage(a.sons[length - 1].info, errInitHereNotAllowed)
|
||||
var length = sonsLen(a)
|
||||
if a.sons[length - 2].kind != nkEmpty:
|
||||
typ = semTypeNode(c, a.sons[length - 2], nil)
|
||||
else: GlobalError(a.info, errTypeExpected)
|
||||
if a.sons[length - 1].kind != nkEmpty:
|
||||
GlobalError(a.sons[length - 1].info, errInitHereNotAllowed)
|
||||
for j in countup(0, length - 3):
|
||||
field = newSymS(skField, a.sons[j], c)
|
||||
var field = newSymS(skField, a.sons[j], c)
|
||||
field.typ = typ
|
||||
field.position = counter
|
||||
inc(counter)
|
||||
if IntSetContainsOrIncl(check, field.name.id):
|
||||
liMessage(a.sons[j].info, errAttemptToRedefine, field.name.s)
|
||||
GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
|
||||
addSon(result.n, newSymNode(field))
|
||||
addSon(result, typ)
|
||||
|
||||
@@ -220,10 +218,11 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
elem: PType
|
||||
isConcrete: bool
|
||||
if (s.typ == nil) or (s.typ.kind != tyGenericBody):
|
||||
liMessage(n.info, errCannotInstantiateX, s.name.s)
|
||||
GlobalError(n.info, errCannotInstantiateX, s.name.s)
|
||||
result = newOrPrevType(tyGenericInvokation, prev, c)
|
||||
if (s.typ.containerID == 0): InternalError(n.info, "semtypes.semGeneric")
|
||||
if sonsLen(n) != sonsLen(s.typ): liMessage(n.info, errWrongNumberOfArguments)
|
||||
if sonsLen(n) != sonsLen(s.typ):
|
||||
GlobalError(n.info, errWrongNumberOfArguments)
|
||||
addSon(result, s.typ)
|
||||
isConcrete = true # iterate over arguments:
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
@@ -231,7 +230,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
if elem.kind == tyGenericParam: isConcrete = false
|
||||
addSon(result, elem)
|
||||
if isConcrete:
|
||||
if s.ast == nil: liMessage(n.info, errCannotInstantiateX, s.name.s)
|
||||
if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
|
||||
result = instGenericContainer(c, n, result)
|
||||
|
||||
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
@@ -246,7 +245,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
|
||||
elif (sfMinus in allowed) and (v.id == ord(wMinus)):
|
||||
incl(result.flags, sfMinus)
|
||||
else:
|
||||
liMessage(n.sons[0].info, errInvalidVisibilityX, v.s)
|
||||
GlobalError(n.sons[0].info, errInvalidVisibilityX, v.s)
|
||||
else:
|
||||
illFormedAst(n)
|
||||
else:
|
||||
@@ -271,8 +270,7 @@ proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
|
||||
for i in countup(1, branchIndex - 1):
|
||||
for j in countup(0, sonsLen(t.sons[i]) - 2):
|
||||
if overlap(t.sons[i].sons[j], ex):
|
||||
#MessageOut(renderTree(t));
|
||||
liMessage(ex.info, errDuplicateCaseLabel)
|
||||
LocalError(ex.info, errDuplicateCaseLabel)
|
||||
|
||||
proc semBranchExpr(c: PContext, t: PNode, ex: var PNode) =
|
||||
ex = semConstExpr(c, ex)
|
||||
@@ -290,7 +288,7 @@ proc SemCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||
semBranchExpr(c, t, b.sons[1])
|
||||
if emptyRange(b.sons[0], b.sons[1]):
|
||||
#MessageOut(renderTree(t));
|
||||
liMessage(b.info, errRangeIsEmpty)
|
||||
GlobalError(b.info, errRangeIsEmpty)
|
||||
covered = covered + getOrdValue(b.sons[1]) - getOrdValue(b.sons[0]) + 1
|
||||
else:
|
||||
semBranchExpr(c, t, branch.sons[i]) # NOT: `b`, because of var-param!
|
||||
@@ -314,11 +312,11 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
incl(a.sons[0].sym.flags, sfDiscriminant)
|
||||
covered = 0
|
||||
typ = skipTypes(a.sons[0].Typ, abstractVar)
|
||||
if not isOrdinalType(typ): liMessage(n.info, errSelectorMustBeOrdinal)
|
||||
if not isOrdinalType(typ): GlobalError(n.info, errSelectorMustBeOrdinal)
|
||||
if firstOrd(typ) < 0:
|
||||
liMessage(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
|
||||
GlobalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
|
||||
if lengthOrd(typ) > 0x00007FFF:
|
||||
liMessage(n.info, errLenXinvalid, a.sons[0].sym.name.s)
|
||||
GlobalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
|
||||
chckCovered = true
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
b = copyTree(n.sons[i])
|
||||
@@ -334,7 +332,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
|
||||
addSon(a, b)
|
||||
if chckCovered and (covered != lengthOrd(a.sons[0].typ)):
|
||||
liMessage(a.info, errNotAllCasesCovered)
|
||||
localError(a.info, errNotAllCasesCovered)
|
||||
addSon(father, a)
|
||||
|
||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
@@ -370,8 +368,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
|
||||
of nkRecList:
|
||||
# attempt to keep the nesting at a sane level:
|
||||
if father.kind == nkRecList: a = father
|
||||
else: a = copyNode(n)
|
||||
var a = if father.kind == nkRecList: father else: copyNode(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
|
||||
if a != father: addSon(father, a)
|
||||
@@ -381,11 +378,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
if (father.kind != nkRecList) and (length >= 4):
|
||||
a = newNodeI(nkRecList, n.info)
|
||||
else:
|
||||
a = nil
|
||||
if n.sons[length - 1] != nil:
|
||||
liMessage(n.sons[length - 1].info, errInitHereNotAllowed)
|
||||
if n.sons[length - 2] == nil: liMessage(n.info, errTypeExpected)
|
||||
typ = semTypeNode(c, n.sons[length - 2], nil)
|
||||
a = ast.emptyNode
|
||||
if n.sons[length - 1].kind != nkEmpty:
|
||||
localError(n.sons[length - 1].info, errInitHereNotAllowed)
|
||||
if n.sons[length - 2].kind == nkEmpty:
|
||||
GlobalError(n.info, errTypeExpected)
|
||||
typ = semTypeNode(c, n.sons[length-2], nil)
|
||||
for i in countup(0, sonsLen(n) - 3):
|
||||
f = semIdentWithPragma(c, skField, n.sons[i], {sfStar, sfMinus})
|
||||
f.typ = typ
|
||||
@@ -396,10 +394,11 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
|
||||
inc(pos)
|
||||
if IntSetContainsOrIncl(check, f.name.id):
|
||||
liMessage(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
||||
if a == nil: addSon(father, newSymNode(f))
|
||||
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
||||
if a.kind == nkEmpty: addSon(father, newSymNode(f))
|
||||
else: addSon(a, newSymNode(f))
|
||||
if a != nil: addSon(father, a)
|
||||
if a.kind != nkEmpty: addSon(father, a)
|
||||
of nkEmpty: nil
|
||||
else: illFormedAst(n)
|
||||
|
||||
proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int,
|
||||
@@ -435,11 +434,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
IntSetInit(check)
|
||||
pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
|
||||
checkSonsLen(n, 3)
|
||||
if n.sons[1] != nil:
|
||||
if n.sons[1].kind != nkEmpty:
|
||||
base = semTypeNode(c, n.sons[1].sons[0], nil)
|
||||
if base.kind == tyObject: addInheritedFields(c, check, pos, base)
|
||||
else: liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
|
||||
else:
|
||||
else: localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
|
||||
else:
|
||||
base = nil
|
||||
if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
|
||||
result = newOrPrevType(tyObject, prev, c)
|
||||
@@ -447,7 +446,7 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result.n = newNodeI(nkRecList, n.info)
|
||||
semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym)
|
||||
if (base != nil) and (tfFinal in base.flags):
|
||||
liMessage(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
|
||||
localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
|
||||
|
||||
proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
|
||||
cl: var TIntSet): PType =
|
||||
@@ -509,11 +508,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||
if a.kind != nkIdentDefs: IllFormedAst(a)
|
||||
checkMinSonsLen(a, 3)
|
||||
var length = sonsLen(a)
|
||||
if a.sons[length - 2] != nil:
|
||||
if a.sons[length - 2].kind != nkEmpty:
|
||||
typ = paramType(c, a.sons[length - 2], genericParams, cl)
|
||||
else:
|
||||
typ = nil
|
||||
if a.sons[length - 1] != nil:
|
||||
if a.sons[length - 1].kind != nkEmpty:
|
||||
def = semExprWithType(c, a.sons[length - 1])
|
||||
# check type compability between def.typ and typ:
|
||||
if typ != nil:
|
||||
@@ -523,18 +522,18 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType): PType =
|
||||
else:
|
||||
typ = def.typ
|
||||
else:
|
||||
def = nil
|
||||
def = ast.emptyNode
|
||||
for j in countup(0, length - 3):
|
||||
var arg = newSymS(skParam, a.sons[j], c)
|
||||
arg.typ = typ
|
||||
arg.position = counter
|
||||
inc(counter)
|
||||
arg.ast = copyTree(def)
|
||||
if def.kind != nkEmpty: arg.ast = copyTree(def)
|
||||
if IntSetContainsOrIncl(check, arg.name.id):
|
||||
liMessage(a.sons[j].info, errAttemptToRedefine, arg.name.s)
|
||||
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
|
||||
addSon(result.n, newSymNode(arg))
|
||||
addSon(result, typ)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
result.sons[0] = paramType(c, n.sons[0], genericParams, cl)
|
||||
res.typ = result.sons[0]
|
||||
|
||||
@@ -554,7 +553,7 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
|
||||
Inc(c.p.nestedBlockCounter)
|
||||
checkSonsLen(n, 2)
|
||||
openScope(c.tab)
|
||||
if n.sons[0] != nil:
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
addDecl(c, newSymS(skLabel, n.sons[0], c))
|
||||
result = semStmtListType(c, n.sons[1], prev)
|
||||
n.sons[1].typ = result
|
||||
@@ -567,13 +566,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
s: PSym
|
||||
t: PType
|
||||
result = nil
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkEmpty: nil
|
||||
of nkTypeOfExpr:
|
||||
result = semExprWithType(c, n, {efAllowType}).typ
|
||||
of nkPar:
|
||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||
else: liMessage(n.info, errTypeExpected)
|
||||
else: GlobalError(n.info, errTypeExpected)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 2)
|
||||
s = semTypeIdent(c, n.sons[0])
|
||||
@@ -587,7 +586,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
else: result = semGeneric(c, n, s, prev)
|
||||
of nkIdent, nkDotExpr, nkAccQuoted:
|
||||
s = semTypeIdent(c, n)
|
||||
if s.typ == nil: liMessage(n.info, errTypeExpected)
|
||||
if s.typ == nil: GlobalError(n.info, errTypeExpected)
|
||||
if prev == nil:
|
||||
result = s.typ
|
||||
else:
|
||||
@@ -604,7 +603,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = prev
|
||||
markUsed(n, n.sym)
|
||||
else:
|
||||
liMessage(n.info, errTypeExpected)
|
||||
GlobalError(n.info, errTypeExpected)
|
||||
of nkObjectTy: result = semObjectNode(c, n, prev)
|
||||
of nkTupleTy: result = semTuple(c, n, prev)
|
||||
of nkRefTy: result = semAnyRef(c, n, tyRef, "ref", prev)
|
||||
@@ -627,7 +626,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkBlockType:
|
||||
result = semBlockType(c, n, prev)
|
||||
else:
|
||||
liMessage(n.info, errTypeExpected)
|
||||
GlobalError(n.info, errTypeExpected)
|
||||
#internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
|
||||
|
||||
proc setMagicType(m: PSym, kind: TTypeKind, size: int) =
|
||||
@@ -665,5 +664,5 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
of mStmt: setMagicType(m, tyStmt, 0)
|
||||
of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
|
||||
of mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: return
|
||||
else: liMessage(m.info, errTypeExpected)
|
||||
else: GlobalError(m.info, errTypeExpected)
|
||||
|
||||
|
||||
@@ -443,7 +443,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||
if containsGenericType(f): result.typ = getInstantiatedType(c, arg, m, f)
|
||||
else: result.typ = f
|
||||
if result.typ == nil: InternalError(arg.info, "implicitConv")
|
||||
addSon(result, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
addSon(result, arg)
|
||||
|
||||
proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
@@ -578,7 +578,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
|
||||
# named param
|
||||
# check if m.callee has such a param:
|
||||
if n.sons[a].sons[0].kind != nkIdent:
|
||||
liMessage(n.sons[a].info, errNamedParamHasToBeIdent)
|
||||
LocalError(n.sons[a].info, errNamedParamHasToBeIdent)
|
||||
m.state = csNoMatch
|
||||
return
|
||||
formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
|
||||
@@ -588,7 +588,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
|
||||
return
|
||||
if IntSetContainsOrIncl(marker, formal.position):
|
||||
# already in namedParams:
|
||||
liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||
m.state = csNoMatch
|
||||
return
|
||||
m.baseTypeMatch = false
|
||||
@@ -633,7 +633,7 @@ proc matches(c: PContext, n: PNode, m: var TCandidate) =
|
||||
formal = m.callee.n.sons[f].sym
|
||||
if IntSetContainsOrIncl(marker, formal.position):
|
||||
# already in namedParams:
|
||||
liMessage(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||
m.state = csNoMatch
|
||||
return
|
||||
m.baseTypeMatch = false
|
||||
@@ -683,12 +683,13 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
|
||||
var
|
||||
o: TOverloadIter
|
||||
x, y, z: TCandidate
|
||||
#liMessage(n.info, warnUser, renderTree(n));
|
||||
#Message(n.info, warnUser, renderTree(n))
|
||||
var sym = initOverloadIter(o, c, f)
|
||||
result = nil
|
||||
if sym == nil: return
|
||||
initCandidate(x, sym, initialBinding)
|
||||
initCandidate(y, sym, initialBinding)
|
||||
|
||||
while sym != nil:
|
||||
if sym.kind in filter:
|
||||
initCandidate(z, sym, initialBinding)
|
||||
@@ -711,7 +712,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
|
||||
not sameMethodDispatcher(x.calleeSym, y.calleeSym):
|
||||
if x.state != csMatch:
|
||||
InternalError(n.info, "x.state is not csMatch")
|
||||
liMessage(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
|
||||
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
|
||||
getProcHeader(x.calleeSym), getProcHeader(y.calleeSym),
|
||||
x.calleeSym.Name.s])
|
||||
else:
|
||||
@@ -719,7 +720,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
|
||||
markUsed(n, x.calleeSym)
|
||||
if x.calleeSym.ast == nil:
|
||||
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
|
||||
if x.calleeSym.ast.sons[genericParamsPos] != nil:
|
||||
if x.calleeSym.ast.sons[genericParamsPos].kind != nkEmpty:
|
||||
# a generic proc!
|
||||
x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
||||
x.callee = x.calleeSym.typ
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -219,12 +219,11 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
|
||||
newVar.owner = getCurrOwner(c)
|
||||
IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
|
||||
defs[j] = newSymNode(newVar).PTransNode
|
||||
assert(it.sons[L-2] == nil)
|
||||
assert(it.sons[L-2].kind == nkEmpty)
|
||||
defs[L-1] = transform(c, it.sons[L-1])
|
||||
result[i] = defs
|
||||
|
||||
proc hasContinue(n: PNode): bool =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
|
||||
of nkContinueStmt: result = true
|
||||
@@ -271,7 +270,6 @@ proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) =
|
||||
transform(c, newTupleAccess(n, i))))
|
||||
|
||||
proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkSym:
|
||||
return transformSym(c, n)
|
||||
@@ -311,8 +309,8 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
|
||||
proc addVar(father, v: PNode) =
|
||||
var vpart = newNodeI(nkIdentDefs, v.info)
|
||||
addSon(vpart, v)
|
||||
addSon(vpart, nil)
|
||||
addSon(vpart, nil)
|
||||
addSon(vpart, ast.emptyNode)
|
||||
addSon(vpart, ast.emptyNode)
|
||||
addSon(father, vpart)
|
||||
|
||||
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
|
||||
@@ -515,7 +513,6 @@ proc getMagicOp(call: PNode): TMagic =
|
||||
proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
|
||||
container: PNode) =
|
||||
# gather used vars for closure generation
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkSym:
|
||||
var s = n.sym
|
||||
@@ -662,7 +659,6 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
|
||||
result = transformSons(c, n)
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkSym:
|
||||
return transformSym(c, n)
|
||||
@@ -678,7 +674,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
of nkCaseStmt:
|
||||
result = transformCase(c, n)
|
||||
of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef:
|
||||
if n.sons[genericParamsPos] == nil:
|
||||
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||
n.sons[codePos] = PNode(transform(c, n.sons[codePos]))
|
||||
if n.kind == nkMethodDef: methodDef(n.sons[namePos].sym)
|
||||
result = PTransNode(n)
|
||||
@@ -727,6 +723,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
result = PTransNode(cnst) # do not miss an optimization
|
||||
|
||||
proc processTransf(context: PPassContext, n: PNode): PNode =
|
||||
if passes.skipCodegen(n): return n
|
||||
var c = PTransf(context)
|
||||
pushTransCon(c, newTransCon(getCurrOwner(c)))
|
||||
result = PNode(transform(c, n))
|
||||
|
||||
@@ -119,7 +119,7 @@ proc getOrdValue(n: PNode): biggestInt =
|
||||
of nkCharLit..nkInt64Lit: result = n.intVal
|
||||
of nkNilLit: result = 0
|
||||
else:
|
||||
liMessage(n.info, errOrdinalTypeExpected)
|
||||
LocalError(n.info, errOrdinalTypeExpected)
|
||||
result = 0
|
||||
|
||||
proc isCompatibleToCString(a: PType): bool =
|
||||
|
||||
0
tests/accept/compile/tgenericvariant.nim
Normal file → Executable file
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
|
||||
tcurrncy.nim;25
|
||||
temit.nim;509
|
||||
tenumhole;my value A1my value Bconc2valueCabc4abc
|
||||
tenumhole.nim;my value A1my value Bconc2valueCabc4abc
|
||||
texcsub.nim;caught!
|
||||
texplicitgeneric1.nim;Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13
|
||||
tfinally.nim;came here 3
|
||||
@@ -47,7 +47,7 @@ tmultim1.nim;7
|
||||
tmultim2.nim;collide: unit, thing collide: unit, thing collide: thing, unit
|
||||
tmultim3.nim;Hi derived!
|
||||
tmultim4.nim;hello
|
||||
tnamedenumfields;my value A0my value Bconc1valueCabc3abc
|
||||
tnamedenumfields.nim;my value A0my value Bconc1valueCabc3abc
|
||||
tnestif.nim;i == 2
|
||||
tnestprc.nim;10
|
||||
toop1.nim;34[]o 5
|
||||
|
||||
|
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
|
||||
a: TThing
|
||||
b, c: TUnit
|
||||
collide(b, c) # ambiguous unit, thing or thing, unit? -> prefer unit, thing!
|
||||
collide(b, c) # ambiguous (unit, thing) or (thing, unit)? -> prefer unit, thing!
|
||||
test(b, c)
|
||||
collide(a, b)
|
||||
#OUT collide: unit, thing collide: unit, thing collide: thing, unit
|
||||
|
||||
0
tests/accept/run/tmultim4.nim
Normal file → Executable file
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.
|
||||
TODO:
|
||||
* semantic checking (keep in mind incremental parsing!)
|
||||
* code generators
|
||||
- 'suggest'
|
||||
|
||||
- thread support: threadvar on Windows seems broken;
|
||||
add --deadlock_prevention:on|off switch
|
||||
|
||||
@@ -61,6 +61,7 @@ Additions
|
||||
- Added basic thread support via the ``threads`` core module and
|
||||
the ``--threads:on`` command line switch.
|
||||
- Added unary ``<`` for nice looking excluding upper bounds in ranges.
|
||||
- Added ``math.floor``.
|
||||
|
||||
|
||||
2010-10-20 Version 0.8.10 released
|
||||
|
||||
0
web/nimrod.ini
Normal file → Executable file
0
web/nimrod.ini
Normal file → Executable file
Reference in New Issue
Block a user