variable dynamic lib names

This commit is contained in:
Andreas Rumpf 2009-12-15 01:50:26 +01:00
commit 7063670a2c
14 changed files with 504 additions and 766 deletions

View file

@ -145,12 +145,12 @@ type
E_Base* {.compilerproc.} = object of TObject ## base exception class; E_Base* {.compilerproc.} = object of TObject ## base exception class;
## each exception has to ## each exception has to
## inherit from `E_Base`. ## inherit from `E_Base`.
name*: cstring ## The exception's name is its Nimrod identifier. name: cstring ## The exception's name is its Nimrod identifier.
## This field is filled automatically in the ## This field is filled automatically in the
## ``raise`` statement. ## ``raise`` statement.
msg* {.exportc: "message".}: cstring ## the exception's message. Not msg* {.exportc: "message".}: string ## the exception's message. Not
## providing an ## providing an exception message
## exception message is bad style. ## is bad style.
EAsynch* = object of E_Base ## Abstract exception class for EAsynch* = object of E_Base ## Abstract exception class for
## *asynchronous exceptions* (interrupts). ## *asynchronous exceptions* (interrupts).

View file

@ -41,8 +41,8 @@ when defined(MACOSX):
LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib" LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib"
elif defined(UNIX): elif defined(UNIX):
const const
LUA_NAME* = "liblua(|5.2|5.1|5.0).so.(|0)" LUA_NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).so.(|0)" LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
else: else:
const const
LUA_NAME* = "lua(|5.2|5.1|5.0).dll" LUA_NAME* = "lua(|5.2|5.1|5.0).dll"

View file

@ -409,7 +409,8 @@ type
kind*: TLibKind kind*: TLibKind
generated*: bool # needed for the backends: generated*: bool # needed for the backends:
name*: PRope name*: PRope
path*: string path*: PNode # can be a string literal!
PLib* = ref TLib PLib* = ref TLib
TSym* = object of TIdObj TSym* = object of TIdObj
@ -949,6 +950,35 @@ proc sonsNotNil(n: PNode): bool =
proc addSonIfNotNil(father, n: PNode) = proc addSonIfNotNil(father, n: PNode) =
if n != nil: addSon(father, n) if n != nil: addSon(father, n)
proc getInt*(a: PNode): biggestInt =
case a.kind
of nkIntLit..nkInt64Lit: result = a.intVal
else:
internalError(a.info, "getInt")
result = 0
proc getFloat*(a: PNode): biggestFloat =
case a.kind
of nkFloatLit..nkFloat64Lit: result = a.floatVal
else:
internalError(a.info, "getFloat")
result = 0.0
proc getStr*(a: PNode): string =
case a.kind
of nkStrLit..nkTripleStrLit: result = a.strVal
else:
internalError(a.info, "getStr")
result = ""
proc getStrOrChar*(a: PNode): string =
case a.kind
of nkStrLit..nkTripleStrLit: result = a.strVal
of nkCharLit: result = chr(int(a.intVal)) & ""
else:
internalError(a.info, "getStrOrChar")
result = ""
proc mustRehash(length, counter: int): bool = proc mustRehash(length, counter: int): bool =
assert(length > counter) assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4) result = (length * 2 < counter * 3) or (length - counter < 4)

View file

@ -219,8 +219,7 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# This function replaces all other methods for generating # This function replaces all other methods for generating
# the assignment operation in C. # the assignment operation in C.
var ty: PType var ty = skipTypes(dest.t, abstractVarRange)
ty = skipTypes(dest.t, abstractVarRange)
case ty.kind case ty.kind
of tyRef: of tyRef:
genRefAssign(p, dest, src, flags) genRefAssign(p, dest, src, flags)

View file

@ -164,11 +164,11 @@ proc isSimpleConst(typ: PType): bool =
proc useHeader(m: BModule, sym: PSym) = proc useHeader(m: BModule, sym: PSym) =
if lfHeader in sym.loc.Flags: if lfHeader in sym.loc.Flags:
assert(sym.annex != nil) assert(sym.annex != nil)
discard lists.IncludeStr(m.headerFiles, sym.annex.path) discard lists.IncludeStr(m.headerFiles, getStr(sym.annex.path))
proc UseMagic(m: BModule, name: string) proc UseMagic(m: BModule, name: string)
include
"ccgtypes.nim" include "ccgtypes.nim"
# ------------------------------ Manager of temporaries ------------------ # ------------------------------ Manager of temporaries ------------------
@ -333,32 +333,36 @@ proc libCandidates(s: string, dest: var TStringSeq) =
add(dest, s) add(dest, s)
proc loadDynamicLib(m: BModule, lib: PLib) = proc loadDynamicLib(m: BModule, lib: PLib) =
var
tmp, loadlib: PRope
s: TStringSeq
assert(lib != nil) assert(lib != nil)
if not lib.generated: if not lib.generated:
lib.generated = true lib.generated = true
tmp = getGlobalTempName() var tmp = getGlobalTempName()
assert(lib.name == nil) assert(lib.name == nil)
lib.name = tmp # BUGFIX: useMagic has awful side-effects lib.name = tmp # BUGFIX: useMagic has awful side-effects
appff(m.s[cfsVars], "static void* $1;$n", appf(m.s[cfsVars], "static void* $1;$n", [tmp])
"$1 = linkonce global i8* zeroinitializer$n", [tmp]) if lib.path.kind in {nkStrLit..nkTripleStrLit}:
s = @[] var s: TStringSeq = @[]
libCandidates(lib.path, s) libCandidates(lib.path.strVal, s)
loadlib = nil var loadlib: PRope = nil
for i in countup(0, high(s)): for i in countup(0, high(s)):
inc(m.labels) inc(m.labels)
if i > 0: app(loadlib, "||") if i > 0: app(loadlib, "||")
appff(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n", appf(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n",
"%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n" & [tmp, getStrLit(m, s[i])])
"store i8* %MOC$4, i8** $1$n", [tmp, getStrLit(m, s[i]), appf(m.s[cfsDynLibInit],
getTypeDesc(m, getSysType(tyString)), toRope(m.labels)]) "if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n",
appff(m.s[cfsDynLibInit], [loadlib, getStrLit(m, lib.path.strVal)])
"if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n", else:
"XXX too implement", [loadlib, getStrLit(m, lib.path)]) var p = newProc(nil, m)
#appf(m.s[cfsDynLibDeinit], "if ($1 != NIM_NIL) nimUnloadLibrary($1);$n", var dest: TLoc
# [tmp]) initLocExpr(p, lib.path, dest)
app(m.s[cfsVars], p.s[cpsLocals])
app(m.s[cfsDynLibInit], p.s[cpsInit])
app(m.s[cfsDynLibInit], p.s[cpsStmts])
appf(m.s[cfsDynLibInit],
"if (!($1 = nimLoadLibrary($2))) nimLoadLibraryError($2);$n",
[tmp, rdLoc(dest)])
useMagic(m, "nimLoadLibrary") useMagic(m, "nimLoadLibrary")
useMagic(m, "nimUnloadLibrary") useMagic(m, "nimUnloadLibrary")
useMagic(m, "NimStringDesc") useMagic(m, "NimStringDesc")

View file

@ -54,9 +54,10 @@ var emptyNode: PNode
proc newStackFrame(): PStackFrame = proc newStackFrame(): PStackFrame =
new(result) new(result)
initIdNodeTable(result.mapping) initIdNodeTable(result.mapping)
result.params = @ [] result.params = @[]
proc newEvalContext(module: PSym, filename: string, optEval: bool): PEvalContext = proc newEvalContext(module: PSym, filename: string,
optEval: bool): PEvalContext =
new(result) new(result)
result.module = module result.module = module
result.optEval = optEval result.optEval = optEval
@ -70,6 +71,7 @@ proc popStackFrame(c: PEvalContext) =
c.tos = c.tos.next c.tos = c.tos.next
proc evalAux(c: PEvalContext, n: PNode): PNode proc evalAux(c: PEvalContext, n: PNode): PNode
proc stackTraceAux(x: PStackFrame) = proc stackTraceAux(x: PStackFrame) =
if x != nil: if x != nil:
stackTraceAux(x.next) stackTraceAux(x.next)
@ -85,9 +87,8 @@ proc isSpecial(n: PNode): bool =
result = (n.kind == nkExceptBranch) or (n.kind == nkEmpty) result = (n.kind == nkExceptBranch) or (n.kind == nkEmpty)
proc evalIf(c: PEvalContext, n: PNode): PNode = proc evalIf(c: PEvalContext, n: PNode): PNode =
var i, length: int var i = 0
i = 0 var length = sonsLen(n)
length = sonsLen(n)
while (i < length) and (sonsLen(n.sons[i]) >= 2): while (i < length) and (sonsLen(n.sons[i]) >= 2):
result = evalAux(c, n.sons[i].sons[0]) result = evalAux(c, n.sons[i].sons[0])
if isSpecial(result): return if isSpecial(result): return
@ -100,10 +101,9 @@ proc evalIf(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalCase(c: PEvalContext, n: PNode): PNode = proc evalCase(c: PEvalContext, n: PNode): PNode =
var res: PNode
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
if isSpecial(result): return if isSpecial(result): return
res = result var res = result
result = emptyNode result = emptyNode
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
if n.sons[i].kind == nkOfBranch: if n.sons[i].kind == nkOfBranch:
@ -114,11 +114,11 @@ proc evalCase(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, lastSon(n.sons[i])) result = evalAux(c, lastSon(n.sons[i]))
var var
gWhileCounter: int # Use a counter to prevent endless loops! gWhileCounter: int # Use a counter to prevent endless loops!
# We make this counter global, because otherwise # We make this counter global, because otherwise
# nested loops could make the compiler extremely slow. # nested loops could make the compiler extremely slow.
gNestedEvals: int # count the recursive calls to ``evalAux`` to prevent gNestedEvals: int # count the recursive calls to ``evalAux`` to prevent
# endless recursion # endless recursion
proc evalWhile(c: PEvalContext, n: PNode): PNode = proc evalWhile(c: PEvalContext, n: PNode): PNode =
while true: while true:
@ -152,8 +152,7 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
result = emptyNode # consume ``break`` token result = emptyNode # consume ``break`` token
proc evalFinally(c: PEvalContext, n, exc: PNode): PNode = proc evalFinally(c: PEvalContext, n, exc: PNode): PNode =
var finallyNode: PNode var finallyNode = lastSon(n)
finallyNode = lastSon(n)
if finallyNode.kind == nkFinally: if finallyNode.kind == nkFinally:
result = evalAux(c, finallyNode) result = evalAux(c, finallyNode)
if result.kind != nkExceptBranch: result = exc if result.kind != nkExceptBranch: result = exc
@ -161,9 +160,6 @@ proc evalFinally(c: PEvalContext, n, exc: PNode): PNode =
result = exc result = exc
proc evalTry(c: PEvalContext, n: PNode): PNode = proc evalTry(c: PEvalContext, n: PNode): PNode =
var
exc: PNode
i, length, blen: int
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
case result.kind case result.kind
of nkBreakStmt, nkReturnToken: of nkBreakStmt, nkReturnToken:
@ -172,11 +168,11 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
if sonsLen(result) >= 1: if sonsLen(result) >= 1:
# creating a nkExceptBranch without sons means that it could not be # creating a nkExceptBranch without sons means that it could not be
# evaluated # evaluated
exc = result var exc = result
i = 1 var i = 1
length = sonsLen(n) var length = sonsLen(n)
while (i < length) and (n.sons[i].kind == nkExceptBranch): while (i < length) and (n.sons[i].kind == nkExceptBranch):
blen = sonsLen(n.sons[i]) var blen = sonsLen(n.sons[i])
if blen == 1: if blen == 1:
# general except section: # general except section:
result = evalAux(c, n.sons[i].sons[0]) result = evalAux(c, n.sons[i].sons[0])
@ -194,8 +190,7 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
else: result = evalFinally(c, n, emptyNode) else: result = evalFinally(c, n, emptyNode)
proc getNullValue(typ: PType, info: TLineInfo): PNode = proc getNullValue(typ: PType, info: TLineInfo): PNode =
var t: PType var t = skipTypes(typ, abstractRange)
t = skipTypes(typ, abstractRange)
result = emptyNode result = emptyNode
case t.kind case t.kind
of tyBool, tyChar, tyInt..tyInt64: of tyBool, tyChar, tyInt..tyInt64:
@ -219,15 +214,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
else: InternalError("getNullValue") else: InternalError("getNullValue")
proc evalVar(c: PEvalContext, n: PNode): PNode = proc evalVar(c: PEvalContext, n: PNode): PNode =
var
v: PSym
a: PNode
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = n.sons[i] var a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
assert(a.kind == nkIdentDefs) assert(a.kind == nkIdentDefs)
assert(a.sons[0].kind == nkSym) assert(a.sons[0].kind == nkSym)
v = a.sons[0].sym var v = a.sons[0].sym
if a.sons[2] != nil: if a.sons[2] != nil:
result = evalAux(c, a.sons[2]) result = evalAux(c, a.sons[2])
if isSpecial(result): return if isSpecial(result): return
@ -237,14 +229,11 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalCall(c: PEvalContext, n: PNode): PNode = proc evalCall(c: PEvalContext, n: PNode): PNode =
var
d: PStackFrame
prc: PNode
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
if isSpecial(result): return if isSpecial(result): return
prc = result # bind the actual params to the local parameter var prc = result
# of a new binding # bind the actual params to the local parameter of a new binding
d = newStackFrame() var d = newStackFrame()
d.call = n d.call = n
if prc.kind == nkSym: if prc.kind == nkSym:
d.prc = prc.sym d.prc = prc.sym
@ -265,8 +254,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
proc evalVariable(c: PStackFrame, sym: PSym): PNode = proc evalVariable(c: PStackFrame, sym: PSym): PNode =
# We need to return a node to the actual value, # We need to return a node to the actual value,
# which can be modified. # which can be modified.
var x: PStackFrame var x = c
x = c
while x != nil: while x != nil:
if sfResult in sym.flags: if sfResult in sym.flags:
return x.params[0] return x.params[0]
@ -276,15 +264,12 @@ proc evalVariable(c: PStackFrame, sym: PSym): PNode =
result = emptyNode result = emptyNode
proc evalArrayAccess(c: PEvalContext, n: PNode): PNode = proc evalArrayAccess(c: PEvalContext, n: PNode): PNode =
var
x: PNode
idx: biggestInt
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
if isSpecial(result): return if isSpecial(result): return
x = result var x = result
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1])
if isSpecial(result): return if isSpecial(result): return
idx = getOrdValue(result) var idx = getOrdValue(result)
result = emptyNode result = emptyNode
case x.kind case x.kind
of nkBracket, nkPar, nkMetaNode: of nkBracket, nkPar, nkMetaNode:
@ -436,15 +421,14 @@ proc evalAnd(c: PEvalContext, n: PNode): PNode =
if result.intVal != 0: result = evalAux(c, n.sons[2]) if result.intVal != 0: result = evalAux(c, n.sons[2])
proc evalNoOpt(c: PEvalContext, n: PNode): PNode = proc evalNoOpt(c: PEvalContext, n: PNode): PNode =
result = newNodeI(nkExceptBranch, n.info) # creating a nkExceptBranch without sons means that it could not be result = newNodeI(nkExceptBranch, n.info)
# evaluated # creating a nkExceptBranch without sons means that it could not be evaluated
proc evalNew(c: PEvalContext, n: PNode): PNode = proc evalNew(c: PEvalContext, n: PNode): PNode =
var t: PType
if c.optEval: if c.optEval:
result = evalNoOpt(c, n) result = evalNoOpt(c, n)
else: else:
t = skipTypes(n.sons[1].typ, abstractVar) var t = skipTypes(n.sons[1].typ, abstractVar)
result = newNodeIT(nkRefTy, n.info, t) result = newNodeIT(nkRefTy, n.info, t)
addSon(result, getNullValue(t.sons[0], n.info)) addSon(result, getNullValue(t.sons[0], n.info))
@ -457,13 +441,10 @@ proc evalDeref(c: PEvalContext, n: PNode): PNode =
else: InternalError(n.info, "evalDeref " & $result.kind) else: InternalError(n.info, "evalDeref " & $result.kind)
proc evalAddr(c: PEvalContext, n: PNode): PNode = proc evalAddr(c: PEvalContext, n: PNode): PNode =
var
a: PNode
t: PType
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
if isSpecial(result): return if isSpecial(result): return
a = result var a = result
t = newType(tyPtr, c.module) var t = newType(tyPtr, c.module)
addSon(t, a.typ) addSon(t, a.typ)
result = newNodeIT(nkRefTy, n.info, t) result = newNodeIT(nkRefTy, n.info, t)
addSon(result, a) addSon(result, a)
@ -477,11 +458,10 @@ proc evalCheckedFieldAccess(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
proc evalUpConv(c: PEvalContext, n: PNode): PNode = proc evalUpConv(c: PEvalContext, n: PNode): PNode =
var dest, src: PType
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0])
if isSpecial(result): return if isSpecial(result): return
dest = skipTypes(n.typ, abstractPtrs) var dest = skipTypes(n.typ, abstractPtrs)
src = skipTypes(result.typ, abstractPtrs) var src = skipTypes(result.typ, abstractPtrs)
if inheritanceDiff(src, dest) > 0: if inheritanceDiff(src, dest) > 0:
stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src)) stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src))
@ -710,48 +690,27 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
k: biggestInt k: biggestInt
m = getMagic(n) m = getMagic(n)
case m case m
of mNone: of mNone: result = evalCall(c, n)
result = evalCall(c, n) of mIs: result = evalIs(c, n)
of mIs: of mSizeOf: internalError(n.info, "sizeof() should have been evaluated")
result = evalIs(c, n) of mHigh: result = evalHigh(c, n)
of mSizeOf: of mAssert: result = evalAssert(c, n)
internalError(n.info, "sizeof() should have been evaluated") of mExit: result = evalExit(c, n)
of mHigh: of mNew, mNewFinalize: result = evalNew(c, n)
result = evalHigh(c, n) of mNewSeq: result = evalNewSeq(c, n)
of mAssert: of mSwap: result = evalSwap(c, n)
result = evalAssert(c, n) of mInc: result = evalIncDec(c, n, 1)
of mExit: of ast.mDec: result = evalIncDec(c, n, - 1)
result = evalExit(c, n) of mEcho: result = evalEcho(c, n)
of mNew, mNewFinalize: of mSetLengthStr: result = evalSetLengthStr(c, n)
result = evalNew(c, n) of mSetLengthSeq: result = evalSetLengthSeq(c, n)
of mNewSeq: of mIncl: result = evalIncl(c, n)
result = evalNewSeq(c, n) of mExcl: result = evalExcl(c, n)
of mSwap: of mAnd: result = evalAnd(c, n)
result = evalSwap(c, n) of mOr: result = evalOr(c, n)
of mInc: of mAppendStrCh: result = evalAppendStrCh(c, n)
result = evalIncDec(c, n, 1) of mAppendStrStr: result = evalAppendStrStr(c, n)
of ast.mDec: of mAppendSeqElem: result = evalAppendSeqElem(c, n)
result = evalIncDec(c, n, - 1)
of mEcho:
result = evalEcho(c, n)
of mSetLengthStr:
result = evalSetLengthStr(c, n)
of mSetLengthSeq:
result = evalSetLengthSeq(c, n)
of mIncl:
result = evalIncl(c, n)
of mExcl:
result = evalExcl(c, n)
of mAnd:
result = evalAnd(c, n)
of mOr:
result = evalOr(c, n)
of mAppendStrCh:
result = evalAppendStrCh(c, n)
of mAppendStrStr:
result = evalAppendStrStr(c, n)
of mAppendSeqElem:
result = evalAppendSeqElem(c, n)
of mNLen: of mNLen:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1])
if isSpecial(result): return if isSpecial(result): return
@ -848,8 +807,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1])
if isSpecial(result): return if isSpecial(result): return
if result.kind != nkIdent: InternalError(n.info, "no symbol") if result.kind != nkIdent: InternalError(n.info, "no symbol")
of mNGetType: of mNGetType: result = evalAux(c, n.sons[1])
result = evalAux(c, n.sons[1])
of mNStrVal: of mNStrVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1])
if isSpecial(result): return if isSpecial(result): return
@ -1009,14 +967,10 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
dec(gNestedEvals) dec(gNestedEvals)
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations) if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
case n.kind # atoms: case n.kind # atoms:
of nkEmpty: of nkEmpty: result = n
result = n of nkSym: result = evalSym(c, n)
of nkSym: of nkType..pred(nkNilLit): result = copyNode(n)
result = evalSym(c, n) of nkNilLit: result = n # end of atoms
of nkType..pred(nkNilLit):
result = copyNode(n)
of nkNilLit:
result = n # end of atoms
of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit: of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit:
result = evalMagicOrCall(c, n) result = evalMagicOrCall(c, n)
of nkCurly, nkBracket, nkRange: of nkCurly, nkBracket, nkRange:
@ -1033,52 +987,29 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
if isSpecial(result): return if isSpecial(result): return
a.sons[i].sons[1] = result a.sons[i].sons[1] = result
result = a result = a
of nkBracketExpr: of nkBracketExpr: result = evalArrayAccess(c, n)
result = evalArrayAccess(c, n) of nkDotExpr: result = evalFieldAccess(c, n)
of nkDotExpr: of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n)
result = evalFieldAccess(c, n) of nkAddr, nkHiddenAddr: result = evalAddr(c, n)
of nkDerefExpr, nkHiddenDeref: of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
result = evalDeref(c, n) of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
of nkAddr, nkHiddenAddr: of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
result = evalAddr(c, n) of nkWhileStmt: result = evalWhile(c, n)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkCaseStmt: result = evalCase(c, n)
result = evalConv(c, n) of nkVarSection: result = evalVar(c, n)
of nkAsgn, nkFastAsgn: of nkTryStmt: result = evalTry(c, n)
result = evalAsgn(c, n) of nkRaiseStmt: result = evalRaise(c, n)
of nkWhenStmt, nkIfStmt, nkIfExpr: of nkReturnStmt: result = evalReturn(c, n)
result = evalIf(c, n) of nkBreakStmt, nkReturnToken: result = n
of nkWhileStmt: of nkBlockExpr, nkBlockStmt: result = evalBlock(c, n)
result = evalWhile(c, n) of nkDiscardStmt: result = evalAux(c, n.sons[0])
of nkCaseStmt: of nkCheckedFieldExpr: result = evalCheckedFieldAccess(c, n)
result = evalCase(c, n) of nkObjDownConv: result = evalAux(c, n.sons[0])
of nkVarSection: of nkObjUpConv: result = evalUpConv(c, n)
result = evalVar(c, n) of nkChckRangeF, nkChckRange64, nkChckRange: result = evalRangeChck(c, n)
of nkTryStmt: of nkStringToCString: result = evalConvStrToCStr(c, n)
result = evalTry(c, n) of nkCStringToString: result = evalConvCStrToStr(c, n)
of nkRaiseStmt: of nkPassAsOpenArray: result = evalAux(c, n.sons[0])
result = evalRaise(c, n)
of nkReturnStmt:
result = evalReturn(c, n)
of nkBreakStmt, nkReturnToken:
result = n
of nkBlockExpr, nkBlockStmt:
result = evalBlock(c, n)
of nkDiscardStmt:
result = evalAux(c, n.sons[0])
of nkCheckedFieldExpr:
result = evalCheckedFieldAccess(c, n)
of nkObjDownConv:
result = evalAux(c, n.sons[0])
of nkObjUpConv:
result = evalUpConv(c, n)
of nkChckRangeF, nkChckRange64, nkChckRange:
result = evalRangeChck(c, n)
of nkStringToCString:
result = evalConvStrToCStr(c, n)
of nkCStringToString:
result = evalConvCStrToStr(c, n)
of nkPassAsOpenArray:
result = evalAux(c, n.sons[0])
of nkStmtListExpr, nkStmtList, nkModule: of nkStmtListExpr, nkStmtList, nkModule:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = evalAux(c, n.sons[i]) result = evalAux(c, n.sons[i])
@ -1106,11 +1037,8 @@ proc eval(c: PEvalContext, n: PNode): PNode =
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ))
proc evalConstExpr(module: PSym, e: PNode): PNode = proc evalConstExpr(module: PSym, e: PNode): PNode =
var var p = newEvalContext(module, "", true)
p: PEvalContext var s = newStackFrame()
s: PStackFrame
p = newEvalContext(module, "", true)
s = newStackFrame()
s.call = e s.call = e
pushStackFrame(p, s) pushStackFrame(p, s)
result = eval(p, e) result = eval(p, e)
@ -1118,8 +1046,7 @@ proc evalConstExpr(module: PSym, e: PNode): PNode =
popStackFrame(p) popStackFrame(p)
proc myOpen(module: PSym, filename: string): PPassContext = proc myOpen(module: PSym, filename: string): PPassContext =
var c: PEvalContext var c = newEvalContext(module, filename, false)
c = newEvalContext(module, filename, false)
pushStackFrame(c, newStackFrame()) pushStackFrame(c, newStackFrame())
result = c result = c

View file

@ -11,7 +11,7 @@
import import
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, rnimsyn, os, platform, condsyms, ast, astalgo, idents, semdata, msgs, rnimsyn,
wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees
const const
FirstCallConv* = wNimcall FirstCallConv* = wNimcall
@ -78,17 +78,17 @@ proc MakeExternExport(s: PSym, extname: string) =
s.loc.r = toRope(extname) s.loc.r = toRope(extname)
incl(s.flags, sfExportc) incl(s.flags, sfExportc)
proc expectStrLit(c: PContext, n: PNode): string = proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr: if n.kind != nkExprColonExpr:
liMessage(n.info, errStringLiteralExpected) liMessage(n.info, errStringLiteralExpected)
result = ""
else: else:
n.sons[1] = c.semConstExpr(c, n.sons[1]) n.sons[1] = c.semConstExpr(c, n.sons[1])
case n.sons[1].kind case n.sons[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1].strVal of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
else: else: liMessage(n.info, errStringLiteralExpected)
liMessage(n.info, errStringLiteralExpected)
result = "" proc expectStrLit(c: PContext, n: PNode): string =
result = getStrLitNode(c, n).strVal
proc expectIntLit(c: PContext, n: PNode): int = proc expectIntLit(c: PContext, n: PNode): int =
if n.kind != nkExprColonExpr: if n.kind != nkExprColonExpr:
@ -128,23 +128,22 @@ proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
# the same # the same
result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall)) result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall))
proc onOff(c: PContext, n: PNode, op: TOptions) = proc IsTurnedOn(c: PContext, n: PNode): bool =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
case whichKeyword(n.sons[1].ident) case whichKeyword(n.sons[1].ident)
of wOn: gOptions = gOptions + op of wOn: result = true
of wOff: gOptions = gOptions - op of wOff: result = false
else: liMessage(n.info, errOnOrOffExpected) else: liMessage(n.info, errOnOrOffExpected)
else: else:
liMessage(n.info, errOnOrOffExpected) liMessage(n.info, errOnOrOffExpected)
proc onOff(c: PContext, n: PNode, op: TOptions) =
if IsTurnedOn(c, n): gOptions = gOptions + op
else: gOptions = gOptions - op
proc pragmaDeadCodeElim(c: PContext, n: PNode) = proc pragmaDeadCodeElim(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): if IsTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
case whichKeyword(n.sons[1].ident) else: excl(c.module.flags, sfDeadCodeElim)
of wOn: incl(c.module.flags, sfDeadCodeElim)
of wOff: excl(c.module.flags, sfDeadCodeElim)
else: liMessage(n.info, errOnOrOffExpected)
else:
liMessage(n.info, errOnOrOffExpected)
proc processCallConv(c: PContext, n: PNode) = proc processCallConv(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
@ -156,27 +155,31 @@ proc processCallConv(c: PContext, n: PNode) =
else: else:
liMessage(n.info, errCallConvExpected) liMessage(n.info, errCallConvExpected)
proc getLib(c: PContext, kind: TLibKind, path: string): PLib = proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
var it = PLib(c.libs.head) var it = PLib(c.libs.head)
while it != nil: while it != nil:
if it.kind == kind: if it.kind == kind:
if ospCaseInsensitive in platform.OS[targetOS].props: if trees.ExprStructuralEquivalent(it.path, path): return it
if cmpIgnoreCase(it.path, path) == 0:
return it
else:
if it.path == path:
return it
it = PLib(it.next) it = PLib(it.next)
result = newLib(kind) result = newLib(kind)
result.path = path result.path = path
Append(c.libs, result) Append(c.libs, result)
proc expectDynlibNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr: liMessage(n.info, errStringLiteralExpected)
else:
result = c.semExpr(c, n.sons[1])
if result.typ == nil or result.typ.kind != tyString:
liMessage(n.info, errStringLiteralExpected)
if result.kind == nkSym and result.sym.kind == skConst:
result = result.sym.ast # look it up
proc processDynLib(c: PContext, n: PNode, sym: PSym) = proc processDynLib(c: PContext, n: PNode, sym: PSym) =
if (sym == nil) or (sym.kind == skModule): if (sym == nil) or (sym.kind == skModule):
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic, POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
expectStrLit(c, n)) expectDynlibNode(c, n))
elif n.kind == nkExprColonExpr: elif n.kind == nkExprColonExpr:
var lib = getLib(c, libDynamic, expectStrLit(c, n)) var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
addToLib(lib, sym) addToLib(lib, sym)
incl(sym.loc.flags, lfDynamicLib) incl(sym.loc.flags, lfDynamicLib)
else: else:
@ -366,7 +369,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
noval(it) noval(it)
incl(sym.flags, sfMerge) incl(sym.flags, sfMerge)
of wHeader: of wHeader:
var lib = getLib(c, libHeader, expectStrLit(c, it)) var lib = getLib(c, libHeader, getStrLitNode(c, it))
addToLib(lib, sym) addToLib(lib, sym)
incl(sym.flags, sfImportc) incl(sym.flags, sfImportc)
incl(sym.loc.flags, lfHeader) incl(sym.loc.flags, lfHeader)

View file

@ -146,9 +146,9 @@ proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType
proc decode(r: PRodReader): string proc decode(r: PRodReader): string
proc decodeInt(r: PRodReader): int proc decodeInt(r: PRodReader): int
proc decodeBInt(r: PRodReader): biggestInt proc decodeBInt(r: PRodReader): biggestInt
proc encode(s: string): PRope = proc encode(s: string): PRope =
var res: string var res = ""
res = ""
for i in countup(0, len(s) + 0 - 1): for i in countup(0, len(s) + 0 - 1):
case s[i] case s[i]
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(res, s[i]) of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(res, s[i])
@ -156,29 +156,24 @@ proc encode(s: string): PRope =
result = toRope(res) result = toRope(res)
proc encodeIntAux(str: var string, x: BiggestInt) = proc encodeIntAux(str: var string, x: BiggestInt) =
const const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
chars: string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" var d: char
var var v = x
v, rem: biggestInt var rem: biggestInt = v mod 190
d: char
idx: int
v = x
rem = v mod 190
if (rem < 0): if (rem < 0):
str = str & '-' add(str, '-')
v = - (v div 190) v = - (v div 190)
rem = - rem rem = - rem
else: else:
v = v div 190 v = v div 190
idx = int(rem) var idx = int(rem)
if idx < 62: d = chars[idx + 0] if idx < 62: d = chars[idx + 0]
else: d = chr(idx - 62 + 128) else: d = chr(idx - 62 + 128)
if (v != 0): encodeIntAux(str, v) if (v != 0): encodeIntAux(str, v)
add(str, d) add(str, d)
proc encodeInt(x: BiggestInt): PRope = proc encodeInt(x: BiggestInt): PRope =
var res: string var res = ""
res = ""
encodeIntAux(res, x) encodeIntAux(res, x)
result = toRope(res) result = toRope(res)
@ -303,8 +298,8 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
if debugIds: registerID(result) if debugIds: registerID(result)
else: else:
InternalError(info, "decodeType: no id") InternalError(info, "decodeType: no id")
IdTablePut(gTypeTable, result, result) # here this also # here this also avoids endless recursion for recursive type
# avoids endless recursion for recursive type IdTablePut(gTypeTable, result, result)
if r.s[r.pos] == '(': result.n = decodeNode(r, UnknownLineInfo()) if r.s[r.pos] == '(': result.n = decodeNode(r, UnknownLineInfo())
if r.s[r.pos] == '$': if r.s[r.pos] == '$':
inc(r.pos) inc(r.pos)
@ -343,7 +338,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
d = decodeInt(r) d = decodeInt(r)
addSon(result, rrGetType(r, d, info)) addSon(result, rrGetType(r, d, info))
proc decodeLib(r: PRodReader): PLib = proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
result = nil result = nil
if r.s[r.pos] == '|': if r.s[r.pos] == '|':
new(result) new(result)
@ -354,11 +349,10 @@ proc decodeLib(r: PRodReader): PLib =
result.name = toRope(decode(r)) result.name = toRope(decode(r))
if r.s[r.pos] != '|': InternalError("decodeLib: 2") if r.s[r.pos] != '|': InternalError("decodeLib: 2")
inc(r.pos) inc(r.pos)
result.path = decode(r) result.path = decodeNode(r, info)
proc decodeSym(r: PRodReader, info: TLineInfo): PSym = proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
var var
k: TSymKind
id: int id: int
ident: PIdent ident: PIdent
result = nil result = nil
@ -367,7 +361,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
if r.s[r.pos] == '}': if r.s[r.pos] == '}':
inc(r.pos) inc(r.pos)
return # nil sym return # nil sym
k = TSymKind(decodeInt(r)) var k = TSymKind(decodeInt(r))
if r.s[r.pos] == '+': if r.s[r.pos] == '+':
inc(r.pos) inc(r.pos)
id = decodeInt(r) id = decodeInt(r)
@ -412,22 +406,20 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
inc(r.pos) inc(r.pos)
result.position = decodeInt(r) result.position = decodeInt(r)
else: else:
result.position = 0 # BUGFIX: this may have been misused as reader index! result.position = 0
# BUGFIX: this may have been misused as reader index!
if r.s[r.pos] == '`': if r.s[r.pos] == '`':
inc(r.pos) inc(r.pos)
result.offset = decodeInt(r) result.offset = decodeInt(r)
else: else:
result.offset = - 1 result.offset = - 1
decodeLoc(r, result.loc, result.info) decodeLoc(r, result.loc, result.info)
result.annex = decodeLib(r) result.annex = decodeLib(r, info)
proc decodeInt(r: PRodReader): int = proc decodeInt(r: PRodReader): int =
# base 190 numbers # base 190 numbers
var var i = r.pos
i: int var sign = - 1
sign: int
i = r.pos
sign = - 1
assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'}) assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
if r.s[i] == '-': if r.s[i] == '-':
inc(i) inc(i)
@ -445,11 +437,8 @@ proc decodeInt(r: PRodReader): int =
r.pos = i r.pos = i
proc decodeBInt(r: PRodReader): biggestInt = proc decodeBInt(r: PRodReader): biggestInt =
var var i = r.pos
i: int var sign: biggestInt = - 1
sign: biggestInt
i = r.pos
sign = - 1
assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'}) assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
if r.s[i] == '-': if r.s[i] == '-':
inc(i) inc(i)
@ -471,18 +460,16 @@ proc hexChar(c: char, xi: var int) =
of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0')) of '0'..'9': xi = (xi shl 4) or (ord(c) - ord('0'))
of 'a'..'f': xi = (xi shl 4) or (ord(c) - ord('a') + 10) of 'a'..'f': xi = (xi shl 4) or (ord(c) - ord('a') + 10)
of 'A'..'F': xi = (xi shl 4) or (ord(c) - ord('A') + 10) of 'A'..'F': xi = (xi shl 4) or (ord(c) - ord('A') + 10)
else: else: nil
nil
proc decode(r: PRodReader): string = proc decode(r: PRodReader): string =
var i, xi: int var i = r.pos
i = r.pos
result = "" result = ""
while true: while true:
case r.s[i] case r.s[i]
of '\\': of '\\':
inc(i, 3) inc(i, 3)
xi = 0 var xi = 0
hexChar(r.s[i - 2], xi) hexChar(r.s[i - 2], xi)
hexChar(r.s[i - 1], xi) hexChar(r.s[i - 1], xi)
add(result, chr(xi)) add(result, chr(xi))
@ -493,28 +480,23 @@ proc decode(r: PRodReader): string =
r.pos = i r.pos = i
proc skipSection(r: PRodReader) = proc skipSection(r: PRodReader) =
var c: int
if r.s[r.pos] == ':': if r.s[r.pos] == ':':
while r.s[r.pos] > '\x0A': inc(r.pos) while r.s[r.pos] > '\x0A': inc(r.pos)
elif r.s[r.pos] == '(': elif r.s[r.pos] == '(':
c = 0 # count () pairs var c = 0 # count () pairs
inc(r.pos) inc(r.pos)
while true: while true:
case r.s[r.pos] case r.s[r.pos]
of '\x0A': of '\x0A': inc(r.line)
inc(r.line) of '(': inc(c)
of '(':
inc(c)
of ')': of ')':
if c == 0: if c == 0:
inc(r.pos) inc(r.pos)
break break
elif c > 0: elif c > 0:
dec(c) dec(c)
of '\0': of '\0': break # end of file
break # end of file else: nil
else:
nil
inc(r.pos) inc(r.pos)
else: else:
InternalError("skipSection " & $(r.line)) InternalError("skipSection " & $(r.line))
@ -535,18 +517,14 @@ proc newStub(r: PRodReader, name: string, id: int): PSym =
if debugIds: registerID(result) if debugIds: registerID(result)
proc processInterf(r: PRodReader, module: PSym) = proc processInterf(r: PRodReader, module: PSym) =
var
s: PSym
w: string
key: int
if r.interfIdx == 0: InternalError("processInterf") if r.interfIdx == 0: InternalError("processInterf")
r.pos = r.interfIdx r.pos = r.interfIdx
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
w = decode(r) var w = decode(r)
inc(r.pos) inc(r.pos)
key = decodeInt(r) var key = decodeInt(r)
inc(r.pos) # #10 inc(r.pos) # #10
s = newStub(r, w, key) var s = newStub(r, w, key)
s.owner = module s.owner = module
StrTableAdd(module.tab, s) StrTableAdd(module.tab, s)
IdTablePut(r.syms, s, s) IdTablePut(r.syms, s, s)
@ -669,8 +647,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
skipSection(r) skipSection(r)
elif section == "DATA": elif section == "DATA":
r.dataIdx = r.pos + 2 # "(\10" r.dataIdx = r.pos + 2 # "(\10"
# We do not read the DATA section here! We read the needed objects on # We do not read the DATA section here! We read the needed objects on
# demand. # demand.
skipSection(r) skipSection(r)
elif section == "INIT": elif section == "INIT":
r.initIdx = r.pos + 2 # "(\10" r.initIdx = r.pos + 2 # "(\10"
@ -685,14 +663,12 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
inc(r.pos) inc(r.pos)
inc(r.line) inc(r.line)
proc newRodReader(modfilename: string, crc: TCrc32, readerIndex: int): PRodReader = proc newRodReader(modfilename: string, crc: TCrc32,
var readerIndex: int): PRodReader =
version: string
r: PRodReader
new(result) new(result)
result.files = @ [] result.files = @[]
result.modDeps = @ [] result.modDeps = @[]
r = result var r = result
r.reason = rrNone r.reason = rrNone
r.pos = 0 r.pos = 0
r.line = 1 r.line = 1
@ -704,7 +680,7 @@ proc newRodReader(modfilename: string, crc: TCrc32, readerIndex: int): PRodReade
initIITable(r.index.tab) initIITable(r.index.tab)
initIITable(r.imports.tab) # looks like a ROD file initIITable(r.imports.tab) # looks like a ROD file
inc(r.pos, 4) inc(r.pos, 4)
version = "" var version = ""
while not (r.s[r.pos] in {'\0', '\x0A'}): while not (r.s[r.pos] in {'\0', '\x0A'}):
add(version, r.s[r.pos]) add(version, r.s[r.pos])
inc(r.pos) inc(r.pos)
@ -719,12 +695,11 @@ proc newRodReader(modfilename: string, crc: TCrc32, readerIndex: int): PRodReade
result = nil result = nil
proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType = proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType =
var oldPos, d: int
result = PType(IdTableGet(gTypeTable, id)) result = PType(IdTableGet(gTypeTable, id))
if result == nil: if result == nil:
# load the type: # load the type:
oldPos = r.pos var oldPos = r.pos
d = IITableGet(r.index.tab, id) var d = IITableGet(r.index.tab, id)
if d == invalidKey: InternalError(info, "rrGetType") if d == invalidKey: InternalError(info, "rrGetType")
r.pos = d + r.dataIdx r.pos = d + r.dataIdx
result = decodeType(r, info) result = decodeType(r, info)
@ -739,39 +714,29 @@ type
TFileModuleMap = seq[TFileModuleRec] TFileModuleMap = seq[TFileModuleRec]
var gMods: TFileModuleMap = @ [] var gMods: TFileModuleMap = @[]
proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym = proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym =
# all compiled modules # all compiled modules
var oldPos: int
if rd.dataIdx == 0: InternalError(info, "dataIdx == 0") if rd.dataIdx == 0: InternalError(info, "dataIdx == 0")
oldPos = rd.pos var oldPos = rd.pos
rd.pos = offset + rd.dataIdx rd.pos = offset + rd.dataIdx
result = decodeSym(rd, info) result = decodeSym(rd, info)
rd.pos = oldPos rd.pos = oldPos
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym = proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
var
d, moduleID: int
rd: PRodReader
result = PSym(IdTableGet(r.syms, id)) result = PSym(IdTableGet(r.syms, id))
if result == nil: if result == nil:
# load the symbol: # load the symbol:
d = IITableGet(r.index.tab, id) var d = IITableGet(r.index.tab, id)
if d == invalidKey: if d == invalidKey:
moduleID = IiTableGet(r.imports.tab, id) var moduleID = IiTableGet(r.imports.tab, id)
if moduleID < 0: if moduleID < 0:
InternalError(info, InternalError(info,
"missing from both indexes: +" & ropeToStr(encodeInt(id))) # "missing from both indexes: +" & ropeToStr(encodeInt(id)))
# find # find the reader with the correct moduleID:
# the
# reader
# with
# the
# correct
# moduleID:
for i in countup(0, high(gMods)): for i in countup(0, high(gMods)):
rd = gMods[i].rd var rd = gMods[i].rd
if (rd != nil): if (rd != nil):
if (rd.moduleID == moduleID): if (rd.moduleID == moduleID):
d = IITableGet(rd.index.tab, id) d = IITableGet(rd.index.tab, id)
@ -792,56 +757,47 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
if (result != nil) and (result.kind == skStub): loadStub(result) if (result != nil) and (result.kind == skStub): loadStub(result)
proc loadInitSection(r: PRodReader): PNode = proc loadInitSection(r: PRodReader): PNode =
var d, oldPos, p: int
if (r.initIdx == 0) or (r.dataIdx == 0): InternalError("loadInitSection") if (r.initIdx == 0) or (r.dataIdx == 0): InternalError("loadInitSection")
oldPos = r.pos var oldPos = r.pos
r.pos = r.initIdx r.pos = r.initIdx
result = newNode(nkStmtList) result = newNode(nkStmtList)
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
d = decodeInt(r) var d = decodeInt(r)
inc(r.pos) # #10 inc(r.pos) # #10
p = r.pos var p = r.pos
r.pos = d + r.dataIdx r.pos = d + r.dataIdx
addSon(result, decodeNode(r, UnknownLineInfo())) addSon(result, decodeNode(r, UnknownLineInfo()))
r.pos = p r.pos = p
r.pos = oldPos r.pos = oldPos
proc loadConverters(r: PRodReader) = proc loadConverters(r: PRodReader) =
var d: int
# We have to ensure that no exported converter is a stub anymore. # We have to ensure that no exported converter is a stub anymore.
if (r.convertersIdx == 0) or (r.dataIdx == 0): if (r.convertersIdx == 0) or (r.dataIdx == 0):
InternalError("importConverters") InternalError("importConverters")
r.pos = r.convertersIdx r.pos = r.convertersIdx
while (r.s[r.pos] > '\x0A'): while (r.s[r.pos] > '\x0A'):
d = decodeInt(r) var d = decodeInt(r)
discard rrGetSym(r, d, UnknownLineInfo()) discard rrGetSym(r, d, UnknownLineInfo())
if r.s[r.pos] == ' ': inc(r.pos) if r.s[r.pos] == ' ': inc(r.pos)
proc getModuleIdx(filename: string): int = proc getModuleIdx(filename: string): int =
for i in countup(0, high(gMods)): for i in countup(0, high(gMods)):
if sameFile(gMods[i].filename, filename): if sameFile(gMods[i].filename, filename): return i
return i
result = len(gMods) result = len(gMods)
setlen(gMods, result + 1) setlen(gMods, result + 1)
proc checkDep(filename: string): TReasonForRecompile = proc checkDep(filename: string): TReasonForRecompile =
var var idx = getModuleIdx(filename)
crc: TCrc32
r: PRodReader
rodfile: string
idx: int
res: TReasonForRecompile
idx = getModuleIdx(filename)
if gMods[idx].reason != rrEmpty: if gMods[idx].reason != rrEmpty:
# reason has already been computed for this module: # reason has already been computed for this module:
return gMods[idx].reason return gMods[idx].reason
crc = crcFromFile(filename) var crc: TCrc32 = crcFromFile(filename)
gMods[idx].reason = rrNone # we need to set it here to avoid cycles gMods[idx].reason = rrNone # we need to set it here to avoid cycles
gMods[idx].filename = filename gMods[idx].filename = filename
gMods[idx].crc = crc gMods[idx].crc = crc
result = rrNone result = rrNone
r = nil var r: PRodReader = nil
rodfile = toGeneratedFile(filename, RodExt) var rodfile = toGeneratedFile(filename, RodExt)
if ExistsFile(rodfile): if ExistsFile(rodfile):
r = newRodReader(rodfile, crc, idx) r = newRodReader(rodfile, crc, idx)
if r == nil: if r == nil:
@ -853,7 +809,7 @@ proc checkDep(filename: string): TReasonForRecompile =
# NOTE: we need to process the entire module graph so that no ID will # NOTE: we need to process the entire module graph so that no ID will
# be used twice! However, compilation speed does not suffer much from # be used twice! However, compilation speed does not suffer much from
# this, since results are cached. # this, since results are cached.
res = checkDep(JoinPath(options.libpath, addFileExt("system", nimExt))) var res = checkDep(options.libpath / addFileExt("system", nimExt))
if res != rrNone: result = rrModDeps if res != rrNone: result = rrModDeps
for i in countup(0, high(r.modDeps)): for i in countup(0, high(r.modDeps)):
res = checkDep(r.modDeps[i]) res = checkDep(r.modDeps[i])
@ -870,12 +826,11 @@ proc checkDep(filename: string): TReasonForRecompile =
gMods[idx].reason = result # now we know better gMods[idx].reason = result # now we know better
proc handleSymbolFile(module: PSym, filename: string): PRodReader = proc handleSymbolFile(module: PSym, filename: string): PRodReader =
var idx: int
if not (optSymbolFiles in gGlobalOptions): if not (optSymbolFiles in gGlobalOptions):
module.id = getID() module.id = getID()
return nil return nil
discard checkDep(filename) discard checkDep(filename)
idx = getModuleIdx(filename) var idx = getModuleIdx(filename)
if gMods[idx].reason == rrEmpty: InternalError("handleSymbolFile") if gMods[idx].reason == rrEmpty: InternalError("handleSymbolFile")
result = gMods[idx].rd result = gMods[idx].rd
if result != nil: if result != nil:
@ -888,26 +843,22 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader =
module.id = getID() module.id = getID()
proc GetCRC(filename: string): TCrc32 = proc GetCRC(filename: string): TCrc32 =
var idx: int var idx = getModuleIdx(filename)
idx = getModuleIdx(filename)
result = gMods[idx].crc result = gMods[idx].crc
proc loadStub(s: PSym) = proc loadStub(s: PSym) =
var
rd: PRodReader
d, theId: int
rs: PSym
if s.kind != skStub: if s.kind != skStub:
InternalError("loadStub") #MessageOut('loading stub: ' + s.name.s); InternalError("loadStub") #MessageOut('loading stub: ' + s.name.s);
rd = gMods[s.position].rd var rd = gMods[s.position].rd
theId = s.id # used for later check var theId = s.id # used for later check
d = IITableGet(rd.index.tab, s.id) var d = IITableGet(rd.index.tab, s.id)
if d == invalidKey: InternalError("loadStub: invalid key") if d == invalidKey: InternalError("loadStub: invalid key")
rs = decodeSymSafePos(rd, d, UnknownLineInfo()) var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
if rs != s: if rs != s:
InternalError(rs.info, "loadStub: wrong symbol") InternalError(rs.info, "loadStub: wrong symbol")
elif rs.id != theId: elif rs.id != theId:
InternalError(rs.info, "loadStub: wrong ID") #MessageOut('loaded stub: ' + s.name.s); InternalError(rs.info, "loadStub: wrong ID")
#MessageOut('loaded stub: ' + s.name.s);
InitIdTable(gTypeTable) InitIdTable(gTypeTable)
InitStrTable(rodCompilerProcs) InitStrTable(rodCompilerProcs)

View file

@ -49,11 +49,10 @@ proc encodeStr(w: PRodWriter, s: string): PRope =
result = encode(s) result = encode(s)
proc processStacks(w: PRodWriter) proc processStacks(w: PRodWriter)
proc getDefines(): PRope = proc getDefines(): PRope =
var var it: TTabIter
it: TTabIter var s = InitTabIter(it, gSymbols)
s: PSym
s = InitTabIter(it, gSymbols)
result = nil result = nil
while s != nil: while s != nil:
if s.position == 1: if s.position == 1:
@ -96,39 +95,38 @@ proc addInclDep(w: PRodWriter, dep: string) =
app(w.inclDeps, rodNL) app(w.inclDeps, rodNL)
proc pushType(w: PRodWriter, t: PType) = proc pushType(w: PRodWriter, t: PType) =
var L: int
# check so that the stack does not grow too large: # check so that the stack does not grow too large:
if IiTableGet(w.index.tab, t.id) == invalidKey: if IiTableGet(w.index.tab, t.id) == invalidKey:
L = len(w.tstack) var L = len(w.tstack)
setlen(w.tstack, L + 1) setlen(w.tstack, L + 1)
w.tstack[L] = t w.tstack[L] = t
proc pushSym(w: PRodWriter, s: PSym) = proc pushSym(w: PRodWriter, s: PSym) =
var L: int
# check so that the stack does not grow too large: # check so that the stack does not grow too large:
if IiTableGet(w.index.tab, s.id) == invalidKey: if IiTableGet(w.index.tab, s.id) == invalidKey:
L = len(w.sstack) var L = len(w.sstack)
setlen(w.sstack, L + 1) setlen(w.sstack, L + 1)
w.sstack[L] = s w.sstack[L] = s
proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode): PRope = proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode): PRope =
var f: TNodeFlags
if n == nil: if n == nil:
# nil nodes have to be stored too: # nil nodes have to be stored too:
return toRope("()") return toRope("()")
result = toRope("(") result = toRope("(")
app(result, encodeInt(ord(n.kind))) # we do not write comments for now app(result, encodeInt(ord(n.kind)))
# Line information takes easily 20% or more of the filesize! Therefore we # we do not write comments for now
# omit line information if it is the same as the father's line information: # Line information takes easily 20% or more of the filesize! Therefore we
# omit line information if it is the same as the father's line information:
if (finfo.fileIndex != n.info.fileIndex): if (finfo.fileIndex != n.info.fileIndex):
appf(result, "?$1,$2,$3", [encodeInt(n.info.col), encodeInt(n.info.line), appf(result, "?$1,$2,$3", [encodeInt(n.info.col), encodeInt(n.info.line),
encodeInt(fileIdx(w, toFilename(n.info)))]) encodeInt(fileIdx(w, toFilename(n.info)))])
elif (finfo.line != n.info.line): elif (finfo.line != n.info.line):
appf(result, "?$1,$2", [encodeInt(n.info.col), encodeInt(n.info.line)]) appf(result, "?$1,$2", [encodeInt(n.info.col), encodeInt(n.info.line)])
elif (finfo.col != n.info.col): elif (finfo.col != n.info.col):
appf(result, "?$1", [encodeInt(n.info.col)]) # No need to output the file index, as this is the serialization of one appf(result, "?$1", [encodeInt(n.info.col)])
# file. # No need to output the file index, as this is the serialization of one
f = n.flags * PersistentNodeFlags # file.
var f = n.flags * PersistentNodeFlags
if f != {}: appf(result, "$$$1", [encodeInt(cast[int32](f))]) if f != {}: appf(result, "$$$1", [encodeInt(cast[int32](f))])
if n.typ != nil: if n.typ != nil:
appf(result, "^$1", [encodeInt(n.typ.id)]) appf(result, "^$1", [encodeInt(n.typ.id)])
@ -191,11 +189,11 @@ proc encodeType(w: PRodWriter, t: PType): PRope =
appf(result, "^$1", [encodeInt(t.sons[i].id)]) appf(result, "^$1", [encodeInt(t.sons[i].id)])
pushType(w, t.sons[i]) pushType(w, t.sons[i])
proc encodeLib(w: PRodWriter, lib: PLib): PRope = proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo): PRope =
result = nil result = nil
appf(result, "|$1", [encodeInt(ord(lib.kind))]) appf(result, "|$1", [encodeInt(ord(lib.kind))])
appf(result, "|$1", [encodeStr(w, ropeToStr(lib.name))]) appf(result, "|$1", [encodeStr(w, ropeToStr(lib.name))])
appf(result, "|$1", [encodeStr(w, lib.path)]) appf(result, "|$1", [encodeNode(w, info, lib.path)])
proc encodeSym(w: PRodWriter, s: PSym): PRope = proc encodeSym(w: PRodWriter, s: PSym): PRope =
var var
@ -235,7 +233,7 @@ proc encodeSym(w: PRodWriter, s: PSym): PRope =
if s.position != 0: appf(result, "%$1", [encodeInt(s.position)]) if s.position != 0: appf(result, "%$1", [encodeInt(s.position)])
if s.offset != - 1: appf(result, "`$1", [encodeInt(s.offset)]) if s.offset != - 1: appf(result, "`$1", [encodeInt(s.offset)])
app(result, encodeLoc(w, s.loc)) app(result, encodeLoc(w, s.loc))
if s.annex != nil: app(result, encodeLib(w, s.annex)) if s.annex != nil: app(result, encodeLib(w, s.annex, s.info))
proc addToIndex(w: var TIndex, key, val: int) = proc addToIndex(w: var TIndex, key, val: int) =
if key - w.lastIdxKey == 1: if key - w.lastIdxKey == 1:
@ -367,10 +365,11 @@ proc writeRod(w: PRodWriter) =
app(content, toRope(')' & rodNL)) app(content, toRope(')' & rodNL))
app(content, toRope("DATA(" & rodNL)) app(content, toRope("DATA(" & rodNL))
app(content, w.data) app(content, w.data)
app(content, toRope(')' & rodNL)) #MessageOut('interf ' + ToString(ropeLen(w.interf))); app(content, toRope(')' & rodNL))
#MessageOut('index ' + ToString(ropeLen(w.indexRope))); #MessageOut('interf ' + ToString(ropeLen(w.interf)));
#MessageOut('init ' + ToString(ropeLen(w.init))); #MessageOut('index ' + ToString(ropeLen(w.indexRope)));
#MessageOut('data ' + ToString(ropeLen(w.data))); #MessageOut('init ' + ToString(ropeLen(w.init)));
#MessageOut('data ' + ToString(ropeLen(w.data)));
writeRope(content, completeGeneratedFilePath(changeFileExt(w.filename, "rod"))) writeRope(content, completeGeneratedFilePath(changeFileExt(w.filename, "rod")))
proc process(c: PPassContext, n: PNode): PNode = proc process(c: PPassContext, n: PNode): PNode =
@ -411,16 +410,17 @@ proc process(c: PPassContext, n: PNode): PNode =
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.sons[0].kind != nkSym: InternalError(a.info, "rodwrite.process") if a.sons[0].kind != nkSym: InternalError(a.info, "rodwrite.process")
s = a.sons[0].sym s = a.sons[0].sym
addInterfaceSym(w, s) # this takes care of enum fields too addInterfaceSym(w, s)
# Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum # this takes care of enum fields too
# type aliasing! Otherwise the same enum symbol would be included # Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum
# several times! # type aliasing! Otherwise the same enum symbol would be included
# # several times!
# if (a.sons[2] <> nil) and (a.sons[2].kind = nkEnumTy) then begin #
# a := s.typ.n; # if (a.sons[2] <> nil) and (a.sons[2].kind = nkEnumTy) then begin
# for j := 0 to sonsLen(a)-1 do # a := s.typ.n;
# addInterfaceSym(w, a.sons[j].sym); # for j := 0 to sonsLen(a)-1 do
# end # addInterfaceSym(w, a.sons[j].sym);
# end
of nkImportStmt: of nkImportStmt:
for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleFile(n.sons[i])) for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleFile(n.sons[i]))
addStmt(w, n) addStmt(w, n)
@ -435,15 +435,13 @@ proc process(c: PPassContext, n: PNode): PNode =
nil nil
proc myOpen(module: PSym, filename: string): PPassContext = proc myOpen(module: PSym, filename: string): PPassContext =
var w: PRodWriter
if module.id < 0: InternalError("rodwrite: module ID not set") if module.id < 0: InternalError("rodwrite: module ID not set")
w = newRodWriter(filename, rodread.GetCRC(filename), module) var w = newRodWriter(filename, rodread.GetCRC(filename), module)
rawAddInterfaceSym(w, module) rawAddInterfaceSym(w, module)
result = w result = w
proc myClose(c: PPassContext, n: PNode): PNode = proc myClose(c: PPassContext, n: PNode): PNode =
var w: PRodWriter var w = PRodWriter(c)
w = PRodWriter(c)
writeRod(w) writeRod(w)
result = n result = n

View file

@ -9,8 +9,7 @@
# This module implements the semantic checking pass. # This module implements the semantic checking pass.
import #var import
# point: array [0..3] of int;
strutils, nhashes, lists, options, scanner, ast, astalgo, trees, treetab, strutils, nhashes, lists, options, scanner, ast, astalgo, trees, treetab,
wordrecg, ropes, msgs, os, condsyms, idents, rnimsyn, types, platform, math, wordrecg, ropes, msgs, os, condsyms, idents, rnimsyn, types, platform, math,
magicsys, pnimsyn, nversion, nimsets, semdata, evals, semfold, importer, magicsys, pnimsyn, nversion, nimsets, semdata, evals, semfold, importer,
@ -20,8 +19,7 @@ proc semPass*(): TPass
# implementation # implementation
proc considerAcc(n: PNode): PIdent = proc considerAcc(n: PNode): PIdent =
var x: PNode var x = n
x = n
if x.kind == nkAccQuoted: x = x.sons[0] if x.kind == nkAccQuoted: x = x.sons[0]
case x.kind case x.kind
of nkIdent: result = x.ident of nkIdent: result = x.ident
@ -62,6 +60,7 @@ proc addParams(c: PContext, n: PNode)
proc addResult(c: PContext, t: PType, info: TLineInfo) proc addResult(c: PContext, t: PType, info: TLineInfo)
proc addResultNode(c: PContext, n: PNode) proc addResultNode(c: PContext, n: PNode)
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
proc semConstExpr(c: PContext, n: PNode): PNode = proc semConstExpr(c: PContext, n: PNode): PNode =
result = semExprWithType(c, n) result = semExprWithType(c, n)
if result == nil: if result == nil:
@ -71,8 +70,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
if result == nil: liMessage(n.info, errConstExprExpected) if result == nil: liMessage(n.info, errConstExprExpected)
proc semAndEvalConstExpr(c: PContext, n: PNode): PNode = proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
var e: PNode var e = semExprWithType(c, n)
e = semExprWithType(c, n)
if e == nil: if e == nil:
liMessage(n.info, errConstExprExpected) liMessage(n.info, errConstExprExpected)
return nil return nil
@ -91,19 +89,16 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
of tyTypeDesc: result.typ = semTypeNode(c, result, nil) of tyTypeDesc: result.typ = semTypeNode(c, result, nil)
else: liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0])) else: liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
include include "semtempl.nim"
"semtempl.nim"
proc semMacroExpr(c: PContext, n: PNode, sym: PSym, semCheck: bool = true): PNode = proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
var semCheck: bool = true): PNode =
p: PEvalContext
s: PStackFrame
inc(evalTemplateCounter) inc(evalTemplateCounter)
if evalTemplateCounter > 100: if evalTemplateCounter > 100:
liMessage(n.info, errTemplateInstantiationTooNested) liMessage(n.info, errTemplateInstantiationTooNested)
markUsed(n, sym) markUsed(n, sym)
p = newEvalContext(c.module, "", false) var p = newEvalContext(c.module, "", false)
s = newStackFrame() var s = newStackFrame()
s.call = n s.call = n
setlen(s.params, 2) setlen(s.params, 2)
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0]) s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
@ -116,11 +111,7 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym, semCheck: bool = true): PNod
if semCheck: result = semAfterMacroCall(c, result, sym) if semCheck: result = semAfterMacroCall(c, result, sym)
dec(evalTemplateCounter) dec(evalTemplateCounter)
include include "seminst.nim", "sigmatch.nim"
"seminst.nim"
include
"sigmatch.nim"
proc CheckBool(t: PNode) = proc CheckBool(t: PNode) =
if (t.Typ == nil) or if (t.Typ == nil) or
@ -132,37 +123,27 @@ proc typeMismatch(n: PNode, formal, actual: PType) =
typeToString(actual) & ") " & typeToString(actual) & ") " &
`%`(msgKindToString(errButExpectedX), [typeToString(formal)])) `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
include include "semtypes.nim", "semexprs.nim", "semgnrc.nim", "semstmts.nim"
"semtypes.nim"
include
"semexprs.nim"
include
"semgnrc.nim"
include
"semstmts.nim"
proc addCodeForGenerics(c: PContext, n: PNode) = proc addCodeForGenerics(c: PContext, n: PNode) =
var
prc: PSym
it: PNode
for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1): for i in countup(c.lastGenericIdx, sonsLen(c.generics) - 1):
it = c.generics.sons[i].sons[1] var it = c.generics.sons[i].sons[1]
if it.kind != nkSym: InternalError("addCodeForGenerics") if it.kind != nkSym: InternalError("addCodeForGenerics")
prc = it.sym var prc = it.sym
if (prc.kind in {skProc, skMethod, skConverter}) and (prc.magic == mNone): if (prc.kind in {skProc, skMethod, skConverter}) and (prc.magic == mNone):
if (prc.ast == nil) or (prc.ast.sons[codePos] == nil): if (prc.ast == nil) or (prc.ast.sons[codePos] == nil):
InternalError(prc.info, "no code for " & prc.name.s) InternalError(prc.info, "no code for " & prc.name.s)
addSon(n, prc.ast) addSon(n, prc.ast)
c.lastGenericIdx = sonsLen(c.generics) c.lastGenericIdx = sonsLen(c.generics)
proc semExprNoFlags(c: PContext, n: PNode): PNode =
result = semExpr(c, n, {})
proc myOpen(module: PSym, filename: string): PPassContext = proc myOpen(module: PSym, filename: string): PPassContext =
var c: PContext var c = newContext(module, filename)
c = newContext(module, filename)
if (c.p != nil): InternalError(module.info, "sem.myOpen") if (c.p != nil): InternalError(module.info, "sem.myOpen")
c.semConstExpr = semConstExpr c.semConstExpr = semConstExpr
c.semExpr = semExprNoFlags
c.p = newProcCon(module) c.p = newProcCon(module)
pushOwner(c.module) pushOwner(c.module)
openScope(c.tab) # scope for imported symbols openScope(c.tab) # scope for imported symbols
@ -177,20 +158,17 @@ proc myOpen(module: PSym, filename: string): PPassContext =
result = c result = c
proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext = proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext =
var c: PContext var c = PContext(myOpen(module, filename))
c = PContext(myOpen(module, filename))
c.fromCache = true c.fromCache = true
result = c result = c
proc myProcess(context: PPassContext, n: PNode): PNode = proc myProcess(context: PPassContext, n: PNode): PNode =
var
c: PContext
a: PNode
result = nil result = nil
c = PContext(context) var c = PContext(context)
result = semStmt(c, n) # BUGFIX: process newly generated generics here, not at the end! result = semStmt(c, n)
# BUGFIX: process newly generated generics here, not at the end!
if sonsLen(c.generics) > 0: if sonsLen(c.generics) > 0:
a = newNodeI(nkStmtList, n.info) var a = newNodeI(nkStmtList, n.info)
addCodeForGenerics(c, a) addCodeForGenerics(c, a)
if sonsLen(a) > 0: if sonsLen(a) > 0:
# a generic has been added to `a`: # a generic has been added to `a`:
@ -198,8 +176,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
result = a result = a
proc myClose(context: PPassContext, n: PNode): PNode = proc myClose(context: PPassContext, n: PNode): PNode =
var c: PContext var c = PContext(context)
c = PContext(context)
closeScope(c.tab) # close module's scope closeScope(c.tab) # close module's scope
rawCloseScope(c.tab) # imported symbols; don't check for unused ones! rawCloseScope(c.tab) # imported symbols; don't check for unused ones!
if n == nil: if n == nil:

View file

@ -15,7 +15,8 @@ import
magicsys, nversion, nimsets, pnimsyn, times, passes, rodread magicsys, nversion, nimsets, pnimsyn, times, passes, rodread
type type
TOptionEntry* = object of lists.TListEntry # entries to put on a stack for pragma parsing TOptionEntry* = object of lists.TListEntry # entries to put on a
# stack for pragma parsing
options*: TOptions options*: TOptions
defaultCC*: TCallingConvention defaultCC*: TCallingConvention
dynlib*: PLib dynlib*: PLib
@ -46,15 +47,16 @@ type
optionStack*: TLinkedList optionStack*: TLinkedList
libs*: TLinkedList # all libs used by this module libs*: TLinkedList # all libs used by this module
fromCache*: bool # is the module read from a cache? fromCache*: bool # is the module read from a cache?
semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas module semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
semExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
includedFiles*: TIntSet # used to detect recursive include files includedFiles*: TIntSet # used to detect recursive include files
filename*: string # the module's filename filename*: string # the module's filename
var gInstTypes*: TIdTable var gInstTypes*: TIdTable # map PType to PType
proc newContext*(module: PSym, nimfile: string): PContext proc newContext*(module: PSym, nimfile: string): PContext
# map PType to PType
proc newProcCon*(owner: PSym): PProcCon proc newProcCon*(owner: PSym): PProcCon
proc lastOptionEntry*(c: PContext): POptionEntry proc lastOptionEntry*(c: PContext): POptionEntry
proc newOptionEntry*(): POptionEntry proc newOptionEntry*(): POptionEntry
@ -70,15 +72,15 @@ proc illFormedAst*(n: PNode)
proc getSon*(n: PNode, indx: int): PNode proc getSon*(n: PNode, indx: int): PNode
proc checkSonsLen*(n: PNode, length: int) proc checkSonsLen*(n: PNode, length: int)
proc checkMinSonsLen*(n: PNode, length: int) proc checkMinSonsLen*(n: PNode, length: int)
# owner handling:
# owner handling:
proc getCurrOwner*(): PSym proc getCurrOwner*(): PSym
proc PushOwner*(owner: PSym) proc PushOwner*(owner: PSym)
proc PopOwner*() proc PopOwner*()
# implementation # implementation
var gOwners: seq[PSym] var gOwners: seq[PSym] = @[]
gOwners = @ []
proc getCurrOwner(): PSym = proc getCurrOwner(): PSym =
# owner stack (used for initializing the # owner stack (used for initializing the
# owner field of syms) # owner field of syms)
@ -88,14 +90,10 @@ proc getCurrOwner(): PSym =
result = gOwners[high(gOwners)] result = gOwners[high(gOwners)]
proc PushOwner(owner: PSym) = proc PushOwner(owner: PSym) =
var length: int add(gOwners, owner)
length = len(gOwners)
setlen(gOwners, length + 1)
gOwners[length] = owner
proc PopOwner() = proc PopOwner() =
var length: int var length = len(gOwners)
length = len(gOwners)
if (length <= 0): InternalError("popOwner") if (length <= 0): InternalError("popOwner")
setlen(gOwners, length - 1) setlen(gOwners, length - 1)
@ -128,8 +126,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
IntSetInit(result.includedFiles) IntSetInit(result.includedFiles)
proc addConverter(c: PContext, conv: PSym) = proc addConverter(c: PContext, conv: PSym) =
var L: int var L = len(c.converters)
L = len(c.converters)
for i in countup(0, L - 1): for i in countup(0, L - 1):
if c.converters[i].id == conv.id: return if c.converters[i].id == conv.id: return
setlen(c.converters, L + 1) setlen(c.converters, L + 1)
@ -162,9 +159,9 @@ proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
dest.owner = getCurrOwner() dest.owner = getCurrOwner()
dest.size = - 1 dest.size = - 1
proc makeRangeType(c: PContext, first, last: biggestInt, info: TLineInfo): PType = proc makeRangeType(c: PContext, first, last: biggestInt,
var n: PNode info: TLineInfo): PType =
n = newNodeI(nkRange, info) var n = newNodeI(nkRange, info)
addSon(n, newIntNode(nkIntLit, first)) addSon(n, newIntNode(nkIntLit, first))
addSon(n, newIntNode(nkIntLit, last)) addSon(n, newIntNode(nkIntLit, last))
result = newTypeS(tyRange, c) result = newTypeS(tyRange, c)

View file

@ -14,7 +14,7 @@ import
strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times, strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times,
nversion, platform, math, msgs, os, condsyms, idents, rnimsyn, types nversion, platform, math, msgs, os, condsyms, idents, rnimsyn, types
proc getConstExpr*(module: PSym, n: PNode): PNode proc getConstExpr*(m: PSym, n: PNode): PNode
# evaluates the constant expression or returns nil if it is no constant # evaluates the constant expression or returns nil if it is no constant
# expression # expression
proc evalOp*(m: TMagic, n, a, b, c: PNode): PNode proc evalOp*(m: TMagic, n, a, b, c: PNode): PNode
@ -22,10 +22,7 @@ proc leValueConv*(a, b: PNode): bool
proc newIntNodeT*(intVal: BiggestInt, n: PNode): PNode proc newIntNodeT*(intVal: BiggestInt, n: PNode): PNode
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode): PNode proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode): PNode
proc newStrNodeT*(strVal: string, n: PNode): PNode proc newStrNodeT*(strVal: string, n: PNode): PNode
proc getInt*(a: PNode): biggestInt
proc getFloat*(a: PNode): biggestFloat
proc getStr*(a: PNode): string
proc getStrOrChar*(a: PNode): string
# implementation # implementation
proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode = proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode =
@ -46,35 +43,6 @@ proc newStrNodeT(strVal: string, n: PNode): PNode =
result.typ = n.typ result.typ = n.typ
result.info = n.info result.info = n.info
proc getInt(a: PNode): biggestInt =
case a.kind
of nkIntLit..nkInt64Lit: result = a.intVal
else:
internalError(a.info, "getInt")
result = 0
proc getFloat(a: PNode): biggestFloat =
case a.kind
of nkFloatLit..nkFloat64Lit: result = a.floatVal
else:
internalError(a.info, "getFloat")
result = 0.0
proc getStr(a: PNode): string =
case a.kind
of nkStrLit..nkTripleStrLit: result = a.strVal
else:
internalError(a.info, "getStr")
result = ""
proc getStrOrChar(a: PNode): string =
case a.kind
of nkStrLit..nkTripleStrLit: result = a.strVal
of nkCharLit: result = chr(int(a.intVal)) & ""
else:
internalError(a.info, "getStrOrChar")
result = ""
proc enumValToString(a: PNode): string = proc enumValToString(a: PNode): string =
var var
n: PNode n: PNode
@ -93,56 +61,35 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
# b and c may be nil # b and c may be nil
result = nil result = nil
case m case m
of mOrd: of mOrd: result = newIntNodeT(getOrdValue(a), n)
result = newIntNodeT(getOrdValue(a), n) of mChr: result = newIntNodeT(getInt(a), n)
of mChr: of mUnaryMinusI, mUnaryMinusI64: result = newIntNodeT(- getInt(a), n)
result = newIntNodeT(getInt(a), n) of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n)
of mUnaryMinusI, mUnaryMinusI64: of mNot: result = newIntNodeT(1 - getInt(a), n)
result = newIntNodeT(- getInt(a), n) of mCard: result = newIntNodeT(nimsets.cardSet(a), n)
of mUnaryMinusF64: of mBitnotI, mBitnotI64: result = newIntNodeT(not getInt(a), n)
result = newFloatNodeT(- getFloat(a), n) of mLengthStr: result = newIntNodeT(len(getStr(a)), n)
of mNot: of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n)
result = newIntNodeT(1 - getInt(a), n) of mLengthSeq, mLengthOpenArray: result = newIntNodeT(sonsLen(a), n) # BUGFIX
of mCard: of mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64: result = a # throw `+` away
result = newIntNodeT(nimsets.cardSet(a), n)
of mBitnotI, mBitnotI64:
result = newIntNodeT(not getInt(a), n)
of mLengthStr:
result = newIntNodeT(len(getStr(a)), n)
of mLengthArray:
result = newIntNodeT(lengthOrd(a.typ), n)
of mLengthSeq, mLengthOpenArray:
result = newIntNodeT(sonsLen(a), n) # BUGFIX
of mUnaryPlusI, mUnaryPlusI64, mUnaryPlusF64:
result = a # throw `+` away
of mToFloat, mToBiggestFloat: of mToFloat, mToBiggestFloat:
result = newFloatNodeT(toFloat(int(getInt(a))), n) result = newFloatNodeT(toFloat(int(getInt(a))), n)
of mToInt, mToBiggestInt: of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n)
result = newIntNodeT(system.toInt(getFloat(a)), n) of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n)
of mAbsF64:
result = newFloatNodeT(abs(getFloat(a)), n)
of mAbsI, mAbsI64: of mAbsI, mAbsI64:
if getInt(a) >= 0: result = a if getInt(a) >= 0: result = a
else: result = newIntNodeT(- getInt(a), n) else: result = newIntNodeT(- getInt(a), n)
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64: of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
# byte(-128) = 1...1..1000_0000'64 --> 0...0..1000_0000'64 # byte(-128) = 1...1..1000_0000'64 --> 0...0..1000_0000'64
result = newIntNodeT(getInt(a) and (`shl`(1, getSize(a.typ) * 8) - 1), n) result = newIntNodeT(getInt(a) and (`shl`(1, getSize(a.typ) * 8) - 1), n)
of mToU8: of mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n)
result = newIntNodeT(getInt(a) and 0x000000FF, n) of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n)
of mToU16: of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n)
result = newIntNodeT(getInt(a) and 0x0000FFFF, n) of mSucc: result = newIntNodeT(getOrdValue(a) + getInt(b), n)
of mToU32: of mPred: result = newIntNodeT(getOrdValue(a) - getInt(b), n)
result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n) of mAddI, mAddI64: result = newIntNodeT(getInt(a) + getInt(b), n)
of mSucc: of mSubI, mSubI64: result = newIntNodeT(getInt(a) - getInt(b), n)
result = newIntNodeT(getOrdValue(a) + getInt(b), n) of mMulI, mMulI64: result = newIntNodeT(getInt(a) * getInt(b), n)
of mPred:
result = newIntNodeT(getOrdValue(a) - getInt(b), n)
of mAddI, mAddI64:
result = newIntNodeT(getInt(a) + getInt(b), n)
of mSubI, mSubI64:
result = newIntNodeT(getInt(a) - getInt(b), n)
of mMulI, mMulI64:
result = newIntNodeT(getInt(a) * getInt(b), n)
of mMinI, mMinI64: of mMinI, mMinI64:
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n) if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n)
else: result = newIntNodeT(getInt(a), n) else: result = newIntNodeT(getInt(a), n)
@ -163,16 +110,11 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n) of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n)
of tyInt64, tyInt: result = newIntNodeT(`shr`(getInt(a), getInt(b)), n) of tyInt64, tyInt: result = newIntNodeT(`shr`(getInt(a), getInt(b)), n)
else: InternalError(n.info, "constant folding for shl") else: InternalError(n.info, "constant folding for shl")
of mDivI, mDivI64: of mDivI, mDivI64: result = newIntNodeT(getInt(a) div getInt(b), n)
result = newIntNodeT(getInt(a) div getInt(b), n) of mModI, mModI64: result = newIntNodeT(getInt(a) mod getInt(b), n)
of mModI, mModI64: of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n)
result = newIntNodeT(getInt(a) mod getInt(b), n) of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n)
of mAddF64: of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n)
result = newFloatNodeT(getFloat(a) + getFloat(b), n)
of mSubF64:
result = newFloatNodeT(getFloat(a) - getFloat(b), n)
of mMulF64:
result = newFloatNodeT(getFloat(a) * getFloat(b), n)
of mDivF64: of mDivF64:
if getFloat(b) == 0.0: if getFloat(b) == 0.0:
if getFloat(a) == 0.0: result = newFloatNodeT(NaN, n) if getFloat(a) == 0.0: result = newFloatNodeT(NaN, n)
@ -185,50 +127,33 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
of mMinF64: of mMinF64:
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n) if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n)
else: result = newFloatNodeT(getFloat(a), n) else: result = newFloatNodeT(getFloat(a), n)
of mIsNil: of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n)
result = newIntNodeT(ord(a.kind == nkNilLit), n)
of mLtI, mLtI64, mLtB, mLtEnum, mLtCh: of mLtI, mLtI64, mLtB, mLtEnum, mLtCh:
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n) result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n)
of mLeI, mLeI64, mLeB, mLeEnum, mLeCh: of mLeI, mLeI64, mLeB, mLeEnum, mLeCh:
result = newIntNodeT(ord(getOrdValue(a) <= getOrdValue(b)), n) result = newIntNodeT(ord(getOrdValue(a) <= getOrdValue(b)), n)
of mEqI, mEqI64, mEqB, mEqEnum, mEqCh: of mEqI, mEqI64, mEqB, mEqEnum, mEqCh:
result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n) # operators for floats result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n)
of mLtF64: of mLtF64: result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n)
result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n) of mLeF64: result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n)
of mLeF64: of mEqF64: result = newIntNodeT(ord(getFloat(a) == getFloat(b)), n)
result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n) of mLtStr: result = newIntNodeT(ord(getStr(a) < getStr(b)), n)
of mEqF64: of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n)
result = newIntNodeT(ord(getFloat(a) == getFloat(b)), n) # operators for strings of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n)
of mLtStr:
result = newIntNodeT(ord(getStr(a) < getStr(b)), n)
of mLeStr:
result = newIntNodeT(ord(getStr(a) <= getStr(b)), n)
of mEqStr:
result = newIntNodeT(ord(getStr(a) == getStr(b)), n)
of mLtU, mLtU64: of mLtU, mLtU64:
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n) result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n)
of mLeU, mLeU64: of mLeU, mLeU64:
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n) result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n)
of mBitandI, mBitandI64, mAnd: of mBitandI, mBitandI64, mAnd: result = newIntNodeT(getInt(a) and getInt(b), n)
result = newIntNodeT(getInt(a) and getInt(b), n) of mBitorI, mBitorI64, mOr: result = newIntNodeT(getInt(a) or getInt(b), n)
of mBitorI, mBitorI64, mOr: of mBitxorI, mBitxorI64, mXor: result = newIntNodeT(getInt(a) xor getInt(b), n)
result = newIntNodeT(getInt(a) or getInt(b), n) of mAddU, mAddU64: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n)
of mBitxorI, mBitxorI64, mXor: of mSubU, mSubU64: result = newIntNodeT(`-%`(getInt(a), getInt(b)), n)
result = newIntNodeT(getInt(a) xor getInt(b), n) of mMulU, mMulU64: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n)
of mAddU, mAddU64: of mModU, mModU64: result = newIntNodeT(`%%`(getInt(a), getInt(b)), n)
result = newIntNodeT(`+%`(getInt(a), getInt(b)), n) of mDivU, mDivU64: result = newIntNodeT(`/%`(getInt(a), getInt(b)), n)
of mSubU, mSubU64: of mLeSet: result = newIntNodeT(Ord(containsSets(a, b)), n)
result = newIntNodeT(`-%`(getInt(a), getInt(b)), n) of mEqSet: result = newIntNodeT(Ord(equalSets(a, b)), n)
of mMulU, mMulU64:
result = newIntNodeT(`*%`(getInt(a), getInt(b)), n)
of mModU, mModU64:
result = newIntNodeT(`%%`(getInt(a), getInt(b)), n)
of mDivU, mDivU64:
result = newIntNodeT(`/%`(getInt(a), getInt(b)), n)
of mLeSet:
result = newIntNodeT(Ord(containsSets(a, b)), n)
of mEqSet:
result = newIntNodeT(Ord(equalSets(a, b)), n)
of mLtSet: of mLtSet:
result = newIntNodeT(Ord(containsSets(a, b) and not equalSets(a, b)), n) result = newIntNodeT(Ord(containsSets(a, b) and not equalSets(a, b)), n)
of mMulSet: of mMulSet:
@ -243,32 +168,24 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
of mSymDiffSet: of mSymDiffSet:
result = nimsets.symdiffSets(a, b) result = nimsets.symdiffSets(a, b)
result.info = n.info result.info = n.info
of mConStrStr: of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n)
result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n) of mInSet: result = newIntNodeT(Ord(inSet(a, b)), n)
of mInSet:
result = newIntNodeT(Ord(inSet(a, b)), n)
of mRepr: of mRepr:
# BUGFIX: we cannot eval mRepr here. But this means that it is not # BUGFIX: we cannot eval mRepr here. But this means that it is not
# available for interpretation. I don't know how to fix this. # available for interpretation. I don't know how to fix this.
#result := newStrNodeT(renderTree(a, {@set}[renderNoComments]), n); #result := newStrNodeT(renderTree(a, {@set}[renderNoComments]), n);
of mIntToStr, mInt64ToStr: of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n)
result = newStrNodeT($(getOrdValue(a)), n)
of mBoolToStr: of mBoolToStr:
if getOrdValue(a) == 0: result = newStrNodeT("false", n) if getOrdValue(a) == 0: result = newStrNodeT("false", n)
else: result = newStrNodeT("true", n) else: result = newStrNodeT("true", n)
of mCopyStr: of mCopyStr: result = newStrNodeT(copy(getStr(a), int(getOrdValue(b))), n)
result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)) + 0), n)
of mCopyStrLast: of mCopyStrLast:
result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)) + 0, result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)),
int(getOrdValue(c)) + 0), n) int(getOrdValue(c))), n)
of mFloatToStr: of mFloatToStr: result = newStrNodeT($(getFloat(a)), n)
result = newStrNodeT($(getFloat(a)), n) of mCStrToStr, mCharToStr: result = newStrNodeT(getStrOrChar(a), n)
of mCStrToStr, mCharToStr: of mStrToStr: result = a
result = newStrNodeT(getStrOrChar(a), n) of mEnumToStr: result = newStrNodeT(enumValToString(a), n)
of mStrToStr:
result = a
of mEnumToStr:
result = newStrNodeT(enumValToString(a), n)
of mArrToSeq: of mArrToSeq:
result = copyTree(a) result = copyTree(a)
result.typ = n.typ result.typ = n.typ
@ -278,15 +195,13 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
else: InternalError(a.info, "evalOp(" & $m & ')') else: InternalError(a.info, "evalOp(" & $m & ')')
proc getConstIfExpr(c: PSym, n: PNode): PNode = proc getConstIfExpr(c: PSym, n: PNode): PNode =
var it, e: PNode
result = nil result = nil
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
it = n.sons[i] var it = n.sons[i]
case it.kind case it.kind
of nkElifExpr: of nkElifExpr:
e = getConstExpr(c, it.sons[0]) var e = getConstExpr(c, it.sons[0])
if e == nil: if e == nil: return nil
return nil
if getOrdValue(e) != 0: if getOrdValue(e) != 0:
if result == nil: if result == nil:
result = getConstExpr(c, it.sons[1]) result = getConstExpr(c, it.sons[1])
@ -297,10 +212,9 @@ proc getConstIfExpr(c: PSym, n: PNode): PNode =
proc partialAndExpr(c: PSym, n: PNode): PNode = proc partialAndExpr(c: PSym, n: PNode): PNode =
# partial evaluation # partial evaluation
var a, b: PNode
result = n result = n
a = getConstExpr(c, n.sons[1]) var a = getConstExpr(c, n.sons[1])
b = getConstExpr(c, n.sons[2]) var b = getConstExpr(c, n.sons[2])
if a != nil: if a != nil:
if getInt(a) == 0: result = a if getInt(a) == 0: result = a
elif b != nil: result = b elif b != nil: result = b
@ -311,10 +225,9 @@ proc partialAndExpr(c: PSym, n: PNode): PNode =
proc partialOrExpr(c: PSym, n: PNode): PNode = proc partialOrExpr(c: PSym, n: PNode): PNode =
# partial evaluation # partial evaluation
var a, b: PNode
result = n result = n
a = getConstExpr(c, n.sons[1]) var a = getConstExpr(c, n.sons[1])
b = getConstExpr(c, n.sons[2]) var b = getConstExpr(c, n.sons[2])
if a != nil: if a != nil:
if getInt(a) != 0: result = a if getInt(a) != 0: result = a
elif b != nil: result = b elif b != nil: result = b
@ -338,20 +251,16 @@ proc leValueConv(a, b: PNode): bool =
else: InternalError(a.info, "leValueConv") else: InternalError(a.info, "leValueConv")
else: InternalError(a.info, "leValueConv") else: InternalError(a.info, "leValueConv")
proc getConstExpr(module: PSym, n: PNode): PNode = proc getConstExpr(m: PSym, n: PNode): PNode =
var
s: PSym
a, b, c: PNode
result = nil result = nil
case n.kind case n.kind
of nkSym: of nkSym:
s = n.sym var s = n.sym
if s.kind == skEnumField: if s.kind == skEnumField:
result = newIntNodeT(s.position, n) result = newIntNodeT(s.position, n)
elif (s.kind == skConst): elif (s.kind == skConst):
case s.magic case s.magic
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in module.flags), of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
n)
of mCompileDate: result = newStrNodeT(times.getDateStr(), n) of mCompileDate: result = newStrNodeT(times.getDateStr(), n)
of mCompileTime: result = newStrNodeT(times.getClockStr(), n) of mCompileTime: result = newStrNodeT(times.getClockStr(), n)
of mNimrodVersion: result = newStrNodeT(VersionAsString, n) of mNimrodVersion: result = newStrNodeT(VersionAsString, n)
@ -364,29 +273,28 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
of mNaN: result = newFloatNodeT(NaN, n) of mNaN: result = newFloatNodeT(NaN, n)
of mInf: result = newFloatNodeT(Inf, n) of mInf: result = newFloatNodeT(Inf, n)
of mNegInf: result = newFloatNodeT(NegInf, n) of mNegInf: result = newFloatNodeT(NegInf, n)
else: else: result = copyTree(s.ast)
result = copyTree(s.ast) # BUGFIX
elif s.kind in {skProc, skMethod}: # BUGFIX elif s.kind in {skProc, skMethod}: # BUGFIX
result = n result = n
of nkCharLit..nkNilLit: of nkCharLit..nkNilLit:
result = copyNode(n) result = copyNode(n)
of nkIfExpr: of nkIfExpr:
result = getConstIfExpr(module, n) result = getConstIfExpr(m, n)
of nkCall, nkCommand, nkCallStrLit: of nkCall, nkCommand, nkCallStrLit:
if (n.sons[0].kind != nkSym): return if (n.sons[0].kind != nkSym): return
s = n.sons[0].sym var s = n.sons[0].sym
if (s.kind != skProc): return if (s.kind != skProc): return
try: try:
case s.magic case s.magic
of mNone: of mNone:
return # XXX: if it has no sideEffect, it should be evaluated return # XXX: if it has no sideEffect, it should be evaluated
of mSizeOf: of mSizeOf:
a = n.sons[1] var a = n.sons[1]
if computeSize(a.typ) < 0: if computeSize(a.typ) < 0:
liMessage(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof") liMessage(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof")
if a.typ.kind in {tyArray, tyObject, tyTuple}: if a.typ.kind in {tyArray, tyObject, tyTuple}:
result = nil # XXX: size computation for complex types result = nil
# is still wrong # XXX: size computation for complex types is still wrong
else: else:
result = newIntNodeT(getSize(a.typ), n) result = newIntNodeT(getSize(a.typ), n)
of mLow: of mLow:
@ -396,13 +304,14 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
{tyOpenArray, tySequence, tyString}): {tyOpenArray, tySequence, tyString}):
result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)), n) result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)), n)
else: else:
a = getConstExpr(module, n.sons[1]) var a = getConstExpr(m, n.sons[1])
var b, c: PNode
if a == nil: return if a == nil: return
if sonsLen(n) > 2: if sonsLen(n) > 2:
b = getConstExpr(module, n.sons[2]) b = getConstExpr(m, n.sons[2])
if b == nil: return if b == nil: return
if sonsLen(n) > 3: if sonsLen(n) > 3:
c = getConstExpr(module, n.sons[3]) c = getConstExpr(m, n.sons[3])
if c == nil: return if c == nil: return
else: else:
b = nil b = nil
@ -412,22 +321,21 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
except EDivByZero: except EDivByZero:
liMessage(n.info, errConstantDivisionByZero) liMessage(n.info, errConstantDivisionByZero)
of nkAddr: of nkAddr:
a = getConstExpr(module, n.sons[0]) var a = getConstExpr(m, n.sons[0])
if a != nil: if a != nil:
result = n result = n
n.sons[0] = a n.sons[0] = a
of nkBracket: of nkBracket:
result = copyTree(n) result = copyTree(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = getConstExpr(module, n.sons[i]) var a = getConstExpr(m, n.sons[i])
if a == nil: if a == nil: return nil
return nil
result.sons[i] = a result.sons[i] = a
incl(result.flags, nfAllConst) incl(result.flags, nfAllConst)
of nkRange: of nkRange:
a = getConstExpr(module, n.sons[0]) var a = getConstExpr(m, n.sons[0])
if a == nil: return if a == nil: return
b = getConstExpr(module, n.sons[1]) var b = getConstExpr(m, n.sons[1])
if b == nil: return if b == nil: return
result = copyNode(n) result = copyNode(n)
addSon(result, a) addSon(result, a)
@ -435,9 +343,8 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
of nkCurly: of nkCurly:
result = copyTree(n) result = copyTree(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = getConstExpr(module, n.sons[i]) var a = getConstExpr(m, n.sons[i])
if a == nil: if a == nil: return nil
return nil
result.sons[i] = a result.sons[i] = a
incl(result.flags, nfAllConst) incl(result.flags, nfAllConst)
of nkPar: of nkPar:
@ -445,19 +352,17 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
result = copyTree(n) result = copyTree(n)
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr): if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = getConstExpr(module, n.sons[i].sons[1]) var a = getConstExpr(m, n.sons[i].sons[1])
if a == nil: if a == nil: return nil
return nil
result.sons[i].sons[1] = a result.sons[i].sons[1] = a
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = getConstExpr(module, n.sons[i]) var a = getConstExpr(m, n.sons[i])
if a == nil: if a == nil: return nil
return nil
result.sons[i] = a result.sons[i] = a
incl(result.flags, nfAllConst) incl(result.flags, nfAllConst)
of nkChckRangeF, nkChckRange64, nkChckRange: of nkChckRangeF, nkChckRange64, nkChckRange:
a = getConstExpr(module, n.sons[0]) var a = getConstExpr(m, n.sons[0])
if a == nil: return if a == nil: return
if leValueConv(n.sons[1], a) and leValueConv(a, n.sons[2]): if leValueConv(n.sons[1], a) and leValueConv(a, n.sons[2]):
result = a # a <= x and x <= b result = a # a <= x and x <= b
@ -467,12 +372,12 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
msgKindToString(errIllegalConvFromXtoY), msgKindToString(errIllegalConvFromXtoY),
[typeToString(n.sons[0].typ), typeToString(n.typ)])) [typeToString(n.sons[0].typ), typeToString(n.typ)]))
of nkStringToCString, nkCStringToString: of nkStringToCString, nkCStringToString:
a = getConstExpr(module, n.sons[0]) var a = getConstExpr(m, n.sons[0])
if a == nil: return if a == nil: return
result = a result = a
result.typ = n.typ result.typ = n.typ
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast: of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
a = getConstExpr(module, n.sons[1]) var a = getConstExpr(m, n.sons[1])
if a == nil: return if a == nil: return
case skipTypes(n.typ, abstractRange).kind case skipTypes(n.typ, abstractRange).kind
of tyInt..tyInt64: of tyInt..tyInt64:

View file

@ -118,11 +118,9 @@ proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode =
addSon(result, ri) addSon(result, ri)
proc transformSym(c: PTransf, n: PNode): PNode = proc transformSym(c: PTransf, n: PNode): PNode =
var var b: PNode
tc: PTransCon
b: PNode
if (n.kind != nkSym): internalError(n.info, "transformSym") if (n.kind != nkSym): internalError(n.info, "transformSym")
tc = c.transCon var tc = c.transCon
if sfBorrow in n.sym.flags: if sfBorrow in n.sym.flags:
# simply exchange the symbol: # simply exchange the symbol:
b = n.sym.ast.sons[codePos] b = n.sym.ast.sons[codePos]
@ -162,19 +160,15 @@ proc transformContinueAux(c: PTransf, n: PNode, labl: PSym, counter: var int) =
proc transformContinue(c: PTransf, n: PNode): PNode = proc transformContinue(c: PTransf, n: PNode): PNode =
# we transform the continue statement into a block statement # we transform the continue statement into a block statement
var
counter: int
x: PNode
labl: PSym
result = n result = n
for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i]) for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i])
counter = 0 var counter = 0
labl = newSym(skLabel, nil, getCurrOwner(c)) var labl = newSym(skLabel, nil, getCurrOwner(c))
labl.name = getIdent(genPrefix & $(labl.id)) labl.name = getIdent(genPrefix & $(labl.id))
labl.info = result.info labl.info = result.info
transformContinueAux(c, result, labl, counter) transformContinueAux(c, result, labl, counter)
if counter > 0: if counter > 0:
x = newNodeI(nkBlockStmt, result.info) var x = newNodeI(nkBlockStmt, result.info)
addSon(x, newSymNode(labl)) addSon(x, newSymNode(labl))
addSon(x, result) addSon(x, result)
result = x result = x
@ -189,10 +183,9 @@ proc skipConv(n: PNode): PNode =
else: result = n else: result = n
proc newTupleAccess(tup: PNode, i: int): PNode = proc newTupleAccess(tup: PNode, i: int): PNode =
var lit: PNode
result = newNodeIT(nkBracketExpr, tup.info, tup.typ.sons[i]) result = newNodeIT(nkBracketExpr, tup.info, tup.typ.sons[i])
addSon(result, copyTree(tup)) addSon(result, copyTree(tup))
lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt)) var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
lit.intVal = i lit.intVal = i
addSon(result, lit) addSon(result, lit)
@ -203,9 +196,8 @@ proc unpackTuple(c: PTransf, n, father: PNode) =
transform(c, newTupleAccess(n, i)))) transform(c, newTupleAccess(n, i))))
proc transformYield(c: PTransf, n: PNode): PNode = proc transformYield(c: PTransf, n: PNode): PNode =
var e: PNode
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
e = n.sons[0] var e = n.sons[0]
if skipTypes(e.typ, {tyGenericInst}).kind == tyTuple: if skipTypes(e.typ, {tyGenericInst}).kind == tyTuple:
e = skipConv(e) e = skipConv(e)
if e.kind == nkPar: if e.kind == nkPar:
@ -220,10 +212,6 @@ proc transformYield(c: PTransf, n: PNode): PNode =
addSon(result, transform(c, lastSon(c.transCon.forStmt))) addSon(result, transform(c, lastSon(c.transCon.forStmt)))
proc inlineIter(c: PTransf, n: PNode): PNode = proc inlineIter(c: PTransf, n: PNode): PNode =
var
L: int
it: PNode
newVar: PSym
result = n result = n
if n == nil: return if n == nil: return
case n.kind case n.kind
@ -234,13 +222,14 @@ proc inlineIter(c: PTransf, n: PNode): PNode =
of nkVarSection: of nkVarSection:
result = copyTree(n) result = copyTree(n)
for i in countup(0, sonsLen(result) - 1): for i in countup(0, sonsLen(result) - 1):
it = result.sons[i] var it = result.sons[i]
if it.kind == nkCommentStmt: continue if it.kind == nkCommentStmt: continue
if it.kind == nkIdentDefs: if it.kind == nkIdentDefs:
if (it.sons[0].kind != nkSym): InternalError(it.info, "inlineIter") if (it.sons[0].kind != nkSym): InternalError(it.info, "inlineIter")
newVar = copySym(it.sons[0].sym) var newVar = copySym(it.sons[0].sym)
incl(newVar.flags, sfFromGeneric) # fixes a strange bug for rodgen: incl(newVar.flags, sfFromGeneric)
#include(it.sons[0].sym.flags, sfFromGeneric); # fixes a strange bug for rodgen:
#include(it.sons[0].sym.flags, sfFromGeneric);
newVar.owner = getCurrOwner(c) newVar.owner = getCurrOwner(c)
IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar)) IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
it.sons[0] = newSymNode(newVar) it.sons[0] = newSymNode(newVar)
@ -248,9 +237,9 @@ proc inlineIter(c: PTransf, n: PNode): PNode =
else: else:
if it.kind != nkVarTuple: if it.kind != nkVarTuple:
InternalError(it.info, "inlineIter: not nkVarTuple") InternalError(it.info, "inlineIter: not nkVarTuple")
L = sonsLen(it) var L = sonsLen(it)
for j in countup(0, L - 3): for j in countup(0, L - 3):
newVar = copySym(it.sons[j].sym) var newVar = copySym(it.sons[j].sym)
incl(newVar.flags, sfFromGeneric) incl(newVar.flags, sfFromGeneric)
newVar.owner = getCurrOwner(c) newVar.owner = getCurrOwner(c)
IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar)) IdNodeTablePut(c.transCon.mapping, it.sons[j].sym, newSymNode(newVar))
@ -263,25 +252,23 @@ proc inlineIter(c: PTransf, n: PNode): PNode =
result = transform(c, result) result = transform(c, result)
proc addVar(father, v: PNode) = proc addVar(father, v: PNode) =
var vpart: PNode var vpart = newNodeI(nkIdentDefs, v.info)
vpart = newNodeI(nkIdentDefs, v.info)
addSon(vpart, v) addSon(vpart, v)
addSon(vpart, nil) addSon(vpart, nil)
addSon(vpart, nil) addSon(vpart, nil)
addSon(father, vpart) addSon(father, vpart)
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
var m: PNode
case n.sons[0].kind case n.sons[0].kind
of nkObjUpConv, nkObjDownConv, nkPassAsOpenArray, nkChckRange, nkChckRangeF, of nkObjUpConv, nkObjDownConv, nkPassAsOpenArray, nkChckRange, nkChckRangeF,
nkChckRange64: nkChckRange64:
m = n.sons[0].sons[0] var m = n.sons[0].sons[0]
if (m.kind == a) or (m.kind == b): if (m.kind == a) or (m.kind == b):
# addr ( nkPassAsOpenArray ( deref ( x ) ) ) --> nkPassAsOpenArray(x) # addr ( nkPassAsOpenArray ( deref ( x ) ) ) --> nkPassAsOpenArray(x)
n.sons[0].sons[0] = m.sons[0] n.sons[0].sons[0] = m.sons[0]
return transform(c, n.sons[0]) return transform(c, n.sons[0])
of nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv:
m = n.sons[0].sons[1] var m = n.sons[0].sons[1]
if (m.kind == a) or (m.kind == b): if (m.kind == a) or (m.kind == b):
# addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
n.sons[0].sons[1] = m.sons[0] n.sons[0].sons[1] = m.sons[0]
@ -294,13 +281,10 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
result = n result = n
proc transformConv(c: PTransf, n: PNode): PNode = proc transformConv(c: PTransf, n: PNode): PNode =
var
source, dest: PType
diff: int
n.sons[1] = transform(c, n.sons[1]) n.sons[1] = transform(c, n.sons[1])
result = n # numeric types need range checks: result = n # numeric types need range checks:
dest = skipTypes(n.typ, abstractVarRange) var dest = skipTypes(n.typ, abstractVarRange)
source = skipTypes(n.sons[1].typ, abstractVarRange) var source = skipTypes(n.sons[1].typ, abstractVarRange)
case dest.kind case dest.kind
of tyInt..tyInt64, tyEnum, tyChar, tyBool: of tyInt..tyInt64, tyEnum, tyChar, tyBool:
if (firstOrd(dest) <= firstOrd(source)) and if (firstOrd(dest) <= firstOrd(source)) and
@ -340,7 +324,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
dest = skipTypes(dest, abstractPtrs) dest = skipTypes(dest, abstractPtrs)
source = skipTypes(source, abstractPtrs) source = skipTypes(source, abstractPtrs)
if source.kind == tyObject: if source.kind == tyObject:
diff = inheritanceDiff(dest, source) var diff = inheritanceDiff(dest, source)
if diff < 0: if diff < 0:
result = newNodeIT(nkObjUpConv, n.info, n.typ) result = newNodeIT(nkObjUpConv, n.info, n.typ)
addSon(result, n.sons[1]) addSon(result, n.sons[1])
@ -350,7 +334,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
else: else:
result = n.sons[1] result = n.sons[1]
of tyObject: of tyObject:
diff = inheritanceDiff(dest, source) var diff = inheritanceDiff(dest, source)
if diff < 0: if diff < 0:
result = newNodeIT(nkObjUpConv, n.info, n.typ) result = newNodeIT(nkObjUpConv, n.info, n.typ)
addSon(result, n.sons[1]) addSon(result, n.sons[1])
@ -360,7 +344,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
else: else:
result = n.sons[1] result = n.sons[1]
of tyGenericParam, tyOrdinal: of tyGenericParam, tyOrdinal:
result = n.sons[1] # happens sometimes for generated assignments, etc. result = n.sons[1] # happens sometimes for generated assignments, etc.
else: else:
nil nil
@ -393,45 +377,42 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
proc transformFor(c: PTransf, n: PNode): PNode = proc transformFor(c: PTransf, n: PNode): PNode =
# generate access statements for the parameters (unless they are constant) # generate access statements for the parameters (unless they are constant)
# put mapping from formal parameters to actual parameters # put mapping from formal parameters to actual parameters
var
length: int
call, v, body, arg: PNode
newC: PTransCon
temp, formal: PSym
if (n.kind != nkForStmt): InternalError(n.info, "transformFor") if (n.kind != nkForStmt): InternalError(n.info, "transformFor")
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
length = sonsLen(n) var length = sonsLen(n)
n.sons[length - 1] = transformContinue(c, n.sons[length - 1]) n.sons[length - 1] = transformContinue(c, n.sons[length - 1])
v = newNodeI(nkVarSection, n.info) var v = newNodeI(nkVarSection, n.info)
for i in countup(0, length - 3): for i in countup(0, length - 3):
addVar(v, copyTree(n.sons[i])) # declare new vars addVar(v, copyTree(n.sons[i])) # declare new vars
addSon(result, v) addSon(result, v)
newC = newTransCon() var newC = newTransCon()
call = n.sons[length - 2] var call = n.sons[length - 2]
if (call.kind != nkCall) or (call.sons[0].kind != nkSym): if (call.kind != nkCall) or (call.sons[0].kind != nkSym):
InternalError(call.info, "transformFor") InternalError(call.info, "transformFor")
newC.owner = call.sons[0].sym newC.owner = call.sons[0].sym
newC.forStmt = n newC.forStmt = n
if (newC.owner.kind != skIterator): if (newC.owner.kind != skIterator):
InternalError(call.info, "transformFor") # generate access statements for the parameters (unless they are constant) InternalError(call.info, "transformFor")
# generate access statements for the parameters (unless they are constant)
pushTransCon(c, newC) pushTransCon(c, newC)
for i in countup(1, sonsLen(call) - 1): for i in countup(1, sonsLen(call) - 1):
arg = skipPassAsOpenArray(transform(c, call.sons[i])) var arg = skipPassAsOpenArray(transform(c, call.sons[i]))
formal = skipTypes(newC.owner.typ, abstractInst).n.sons[i].sym #if IdentEq(newc.Owner.name, 'items') then var formal = skipTypes(newC.owner.typ, abstractInst).n.sons[i].sym
# liMessage(arg.info, warnUser, 'items: ' + nodeKindToStr[arg.kind]); #if IdentEq(newc.Owner.name, 'items') then
# liMessage(arg.info, warnUser, 'items: ' + nodeKindToStr[arg.kind]);
case putArgInto(arg, formal.typ) case putArgInto(arg, formal.typ)
of paDirectMapping: of paDirectMapping:
IdNodeTablePut(newC.mapping, formal, arg) IdNodeTablePut(newC.mapping, formal, arg)
of paFastAsgn: of paFastAsgn:
# generate a temporary and produce an assignment statement: # generate a temporary and produce an assignment statement:
temp = newTemp(c, formal.typ, formal.info) var temp = newTemp(c, formal.typ, formal.info)
addVar(v, newSymNode(temp)) addVar(v, newSymNode(temp))
addSon(result, newAsgnStmt(c, newSymNode(temp), arg)) addSon(result, newAsgnStmt(c, newSymNode(temp), arg))
IdNodeTablePut(newC.mapping, formal, newSymNode(temp)) IdNodeTablePut(newC.mapping, formal, newSymNode(temp))
of paVarAsgn: of paVarAsgn:
assert(skipTypes(formal.typ, abstractInst).kind == tyVar) assert(skipTypes(formal.typ, abstractInst).kind == tyVar)
InternalError(arg.info, "not implemented: pass to var parameter") InternalError(arg.info, "not implemented: pass to var parameter")
body = newC.owner.ast.sons[codePos] var body = newC.owner.ast.sons[codePos]
pushInfoContext(n.info) pushInfoContext(n.info)
addSon(result, inlineIter(c, body)) addSon(result, inlineIter(c, body))
popInfoContext() popInfoContext()
@ -447,14 +428,11 @@ proc getMagicOp(call: PNode): TMagic =
proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym, proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
container: PNode) = container: PNode) =
# gather used vars for closure generation # gather used vars for closure generation
var
s: PSym
found: bool
if n == nil: return if n == nil: return
case n.kind case n.kind
of nkSym: of nkSym:
s = n.sym var s = n.sym
found = false var found = false
case s.kind case s.kind
of skVar: found = not (sfGlobal in s.flags) of skVar: found = not (sfGlobal in s.flags)
of skTemp, skForVar, skParam: found = true of skTemp, skForVar, skParam: found = true
@ -476,10 +454,9 @@ proc addFormalParam(routine: PSym, param: PSym) =
proc indirectAccess(a, b: PSym): PNode = proc indirectAccess(a, b: PSym): PNode =
# returns a^ .b as a node # returns a^ .b as a node
var x, y, deref: PNode var x = newSymNode(a)
x = newSymNode(a) var y = newSymNode(b)
y = newSymNode(b) var deref = newNodeI(nkDerefExpr, x.info)
deref = newNodeI(nkDerefExpr, x.info)
deref.typ = x.typ.sons[0] deref.typ = x.typ.sons[0]
addSon(deref, x) addSon(deref, x)
result = newNodeI(nkDotExpr, x.info) result = newNodeI(nkDotExpr, x.info)
@ -488,29 +465,26 @@ proc indirectAccess(a, b: PSym): PNode =
result.typ = y.typ result.typ = y.typ
proc transformLambda(c: PTransf, n: PNode): PNode = proc transformLambda(c: PTransf, n: PNode): PNode =
var var marked: TIntSet
marked: TIntSet
closure: PNode
s, param: PSym
cl, p: PType
newC: PTransCon
result = n result = n
IntSetInit(marked) IntSetInit(marked)
if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda") if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda")
s = n.sons[namePos].sym var s = n.sons[namePos].sym
closure = newNodeI(nkRecList, n.sons[codePos].info) var closure = newNodeI(nkRecList, n.sons[codePos].info)
gatherVars(c, n.sons[codePos], marked, s, closure) # add closure type to the param list (even if closure is empty!): gatherVars(c, n.sons[codePos], marked, s, closure)
cl = newType(tyObject, s) # add closure type to the param list (even if closure is empty!):
var cl = newType(tyObject, s)
cl.n = closure cl.n = closure
addSon(cl, nil) # no super class addSon(cl, nil) # no super class
p = newType(tyRef, s) var p = newType(tyRef, s)
addSon(p, cl) addSon(p, cl)
param = newSym(skParam, getIdent(genPrefix & "Cl"), s) var param = newSym(skParam, getIdent(genPrefix & "Cl"), s)
param.typ = p param.typ = p
addFormalParam(s, param) # all variables that are accessed should be accessed by the new closure addFormalParam(s, param)
# parameter: # all variables that are accessed should be accessed by the new closure
# parameter:
if sonsLen(closure) > 0: if sonsLen(closure) > 0:
newC = newTransCon() var newC = newTransCon()
for i in countup(0, sonsLen(closure) - 1): for i in countup(0, sonsLen(closure) - 1):
IdNodeTablePut(newC.mapping, closure.sons[i].sym, IdNodeTablePut(newC.mapping, closure.sons[i].sym,
indirectAccess(param, closure.sons[i].sym)) indirectAccess(param, closure.sons[i].sym))
@ -521,18 +495,15 @@ proc transformLambda(c: PTransf, n: PNode): PNode =
proc transformCase(c: PTransf, n: PNode): PNode = proc transformCase(c: PTransf, n: PNode): PNode =
# removes `elif` branches of a case stmt # removes `elif` branches of a case stmt
# adds ``else: nil`` if needed for the code generator # adds ``else: nil`` if needed for the code generator
var var length = sonsLen(n)
length, i: int var i = length - 1
ifs, elsen: PNode
length = sonsLen(n)
i = length - 1
if n.sons[i].kind == nkElse: dec(i) if n.sons[i].kind == nkElse: dec(i)
if n.sons[i].kind == nkElifBranch: if n.sons[i].kind == nkElifBranch:
while n.sons[i].kind == nkElifBranch: dec(i) while n.sons[i].kind == nkElifBranch: dec(i)
if (n.sons[i].kind != nkOfBranch): if (n.sons[i].kind != nkOfBranch):
InternalError(n.sons[i].info, "transformCase") InternalError(n.sons[i].info, "transformCase")
ifs = newNodeI(nkIfStmt, n.sons[i + 1].info) var ifs = newNodeI(nkIfStmt, n.sons[i + 1].info)
elsen = newNodeI(nkElse, ifs.info) var elsen = newNodeI(nkElse, ifs.info)
for j in countup(i + 1, length - 1): addSon(ifs, n.sons[j]) for j in countup(i + 1, length - 1): addSon(ifs, n.sons[j])
setlen(n.sons, i + 2) setlen(n.sons, i + 2)
addSon(elsen, ifs) addSon(elsen, ifs)
@ -541,7 +512,7 @@ proc transformCase(c: PTransf, n: PNode): PNode =
not (skipTypes(n.sons[0].Typ, abstractVarRange).Kind in not (skipTypes(n.sons[0].Typ, abstractVarRange).Kind in
{tyInt..tyInt64, tyChar, tyEnum}): {tyInt..tyInt64, tyChar, tyEnum}):
#MessageOut(renderTree(n)); #MessageOut(renderTree(n));
elsen = newNodeI(nkElse, n.info) var elsen = newNodeI(nkElse, n.info)
addSon(elsen, newNodeI(nkNilLit, n.info)) addSon(elsen, newNodeI(nkNilLit, n.info))
addSon(n, elsen) addSon(n, elsen)
result = n result = n
@ -566,20 +537,15 @@ proc getMergeOp(n: PNode): PSym =
nil nil
proc flattenTreeAux(d, a: PNode, op: PSym) = proc flattenTreeAux(d, a: PNode, op: PSym) =
var op2: PSym var op2 = getMergeOp(a)
op2 = getMergeOp(a)
if (op2 != nil) and if (op2 != nil) and
((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)): # a is a ((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)):
# "leaf", so
# add
# it:
for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op) for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op)
else: else:
addSon(d, copyTree(a)) addSon(d, copyTree(a))
proc flattenTree(root: PNode): PNode = proc flattenTree(root: PNode): PNode =
var op: PSym var op = getMergeOp(root)
op = getMergeOp(root)
if op != nil: if op != nil:
result = copyNode(root) result = copyNode(root)
addSon(result, copyTree(root.sons[0])) addSon(result, copyTree(root.sons[0]))
@ -588,21 +554,17 @@ proc flattenTree(root: PNode): PNode =
result = root result = root
proc transformCall(c: PTransf, n: PNode): PNode = proc transformCall(c: PTransf, n: PNode): PNode =
var
j: int
m, a: PNode
op: PSym
result = flattenTree(n) result = flattenTree(n)
for i in countup(0, sonsLen(result) - 1): for i in countup(0, sonsLen(result) - 1):
result.sons[i] = transform(c, result.sons[i]) result.sons[i] = transform(c, result.sons[i])
op = getMergeOp(result) var op = getMergeOp(result)
if (op != nil) and (op.magic != mNone) and (sonsLen(result) >= 3): if (op != nil) and (op.magic != mNone) and (sonsLen(result) >= 3):
m = result var m = result
result = newNodeIT(nkCall, m.info, m.typ) result = newNodeIT(nkCall, m.info, m.typ)
addSon(result, copyTree(m.sons[0])) addSon(result, copyTree(m.sons[0]))
j = 1 var j = 1
while j < sonsLen(m): while j < sonsLen(m):
a = m.sons[j] var a = m.sons[j]
inc(j) inc(j)
if isConstExpr(a): if isConstExpr(a):
while (j < sonsLen(m)) and isConstExpr(m.sons[j]): while (j < sonsLen(m)) and isConstExpr(m.sons[j]):
@ -616,11 +578,8 @@ proc transformCall(c: PTransf, n: PNode): PNode =
result = methodCall(result) result = methodCall(result)
proc transform(c: PTransf, n: PNode): PNode = proc transform(c: PTransf, n: PNode): PNode =
var cnst: PNode
result = n result = n
if n == nil: if n == nil: return
return #if ToLinenumber(n.info) = 32 then
# MessageOut(RenderTree(n));
case n.kind case n.kind
of nkSym: of nkSym:
return transformSym(c, n) return transformSym(c, n)
@ -657,16 +616,16 @@ proc transform(c: PTransf, n: PNode): PNode =
of nkCommentStmt, nkTemplateDef: of nkCommentStmt, nkTemplateDef:
return return
of nkConstSection: of nkConstSection:
return # do not replace ``const c = 3`` with ``const 3 = 3`` # do not replace ``const c = 3`` with ``const 3 = 3``
return
else: else:
for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i]) for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i])
cnst = getConstExpr(c.module, result) var cnst = getConstExpr(c.module, result)
if cnst != nil: if cnst != nil:
result = cnst # do not miss an optimization result = cnst # do not miss an optimization
proc processTransf(context: PPassContext, n: PNode): PNode = proc processTransf(context: PPassContext, n: PNode): PNode =
var c: PTransf var c = PTransf(context)
c = PTransf(context)
result = transform(c, n) result = transform(c, n)
proc openTransf(module: PSym, filename: string): PPassContext = proc openTransf(module: PSym, filename: string): PPassContext =

View file

@ -13,7 +13,7 @@ import
ast, astalgo, scanner, msgs, strutils ast, astalgo, scanner, msgs, strutils
proc getMagic*(op: PNode): TMagic proc getMagic*(op: PNode): TMagic
# function getConstExpr(const t: TNode; out res: TNode): Boolean;
proc isConstExpr*(n: PNode): bool proc isConstExpr*(n: PNode): bool
proc flattenTree*(root: PNode, op: TMagic): PNode proc flattenTree*(root: PNode, op: TMagic): PNode
proc TreeToSym*(t: PNode): PSym proc TreeToSym*(t: PNode): PSym
@ -32,12 +32,11 @@ proc hasSon(father, son: PNode): bool =
result = false result = false
proc cyclicTreeAux(n, s: PNode): bool = proc cyclicTreeAux(n, s: PNode): bool =
var m: int
if n == nil: if n == nil:
return false return false
if hasSon(s, n): if hasSon(s, n):
return true return true
m = sonsLen(s) var m = sonsLen(s)
addSon(s, n) addSon(s, n)
if not (n.kind in {nkEmpty..nkNilLit}): if not (n.kind in {nkEmpty..nkNilLit}):
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
@ -47,8 +46,7 @@ proc cyclicTreeAux(n, s: PNode): bool =
delSon(s, m) delSon(s, m)
proc cyclicTree(n: PNode): bool = proc cyclicTree(n: PNode): bool =
var s: PNode var s = newNodeI(nkEmpty, n.info)
s = newNodeI(nkEmpty, n.info)
result = cyclicTreeAux(n, s) result = cyclicTreeAux(n, s)
proc ExprStructuralEquivalent(a, b: PNode): bool = proc ExprStructuralEquivalent(a, b: PNode): bool =
@ -57,18 +55,14 @@ proc ExprStructuralEquivalent(a, b: PNode): bool =
result = true result = true
elif (a != nil) and (b != nil) and (a.kind == b.kind): elif (a != nil) and (b != nil) and (a.kind == b.kind):
case a.kind case a.kind
of nkSym: # don't go nuts here: same symbol as string is enough: of nkSym:
# don't go nuts here: same symbol as string is enough:
result = a.sym.name.id == b.sym.name.id result = a.sym.name.id == b.sym.name.id
of nkIdent: of nkIdent: result = a.ident.id == b.ident.id
result = a.ident.id == b.ident.id of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
of nkCharLit..nkInt64Lit: of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
result = a.intVal == b.intVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkFloatLit..nkFloat64Lit: of nkEmpty, nkNilLit, nkType: result = true
result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit:
result = a.strVal == b.strVal
of nkEmpty, nkNilLit, nkType:
result = true
else: else:
if sonsLen(a) == sonsLen(b): if sonsLen(a) == sonsLen(b):
for i in countup(0, sonsLen(a) - 1): for i in countup(0, sonsLen(a) - 1):
@ -85,18 +79,14 @@ proc sameTree(a, b: PNode): bool =
if a.info.col != b.info.col: if a.info.col != b.info.col:
return #if a.info.fileIndex <> b.info.fileIndex then exit; return #if a.info.fileIndex <> b.info.fileIndex then exit;
case a.kind case a.kind
of nkSym: # don't go nuts here: same symbol as string is enough: of nkSym:
# don't go nuts here: same symbol as string is enough:
result = a.sym.name.id == b.sym.name.id result = a.sym.name.id == b.sym.name.id
of nkIdent: of nkIdent: result = a.ident.id == b.ident.id
result = a.ident.id == b.ident.id of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
of nkCharLit..nkInt64Lit: of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
result = a.intVal == b.intVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkFloatLit..nkFloat64Lit: of nkEmpty, nkNilLit, nkType: result = true
result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit:
result = a.strVal == b.strVal
of nkEmpty, nkNilLit, nkType:
result = true
else: else:
if sonsLen(a) == sonsLen(b): if sonsLen(a) == sonsLen(b):
for i in countup(0, sonsLen(a) - 1): for i in countup(0, sonsLen(a) - 1):
@ -118,8 +108,7 @@ proc getMagic(op: PNode): TMagic =
case op.kind case op.kind
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit: of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit:
case op.sons[0].Kind case op.sons[0].Kind
of nkSym: of nkSym: result = op.sons[0].sym.magic
result = op.sons[0].sym.magic
else: result = mNone else: result = mNone
else: result = mNone else: result = mNone
@ -146,7 +135,6 @@ proc flattenTree(root: PNode, op: TMagic): PNode =
flattenTreeAux(result, root, op) flattenTreeAux(result, root, op)
proc SwapOperands(op: PNode) = proc SwapOperands(op: PNode) =
var tmp: PNode var tmp = op.sons[1]
tmp = op.sons[1]
op.sons[1] = op.sons[2] op.sons[1] = op.sons[2]
op.sons[2] = tmp op.sons[2] = tmp