mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 18:02:05 +00:00
variable dynamic lib names
This commit is contained in:
@@ -145,12 +145,12 @@ type
|
||||
E_Base* {.compilerproc.} = object of TObject ## base exception class;
|
||||
## each exception has to
|
||||
## 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
|
||||
## ``raise`` statement.
|
||||
msg* {.exportc: "message".}: cstring ## the exception's message. Not
|
||||
## providing an
|
||||
## exception message is bad style.
|
||||
msg* {.exportc: "message".}: string ## the exception's message. Not
|
||||
## providing an exception message
|
||||
## is bad style.
|
||||
|
||||
EAsynch* = object of E_Base ## Abstract exception class for
|
||||
## *asynchronous exceptions* (interrupts).
|
||||
|
||||
@@ -41,8 +41,8 @@ when defined(MACOSX):
|
||||
LUA_LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib"
|
||||
elif defined(UNIX):
|
||||
const
|
||||
LUA_NAME* = "liblua(|5.2|5.1|5.0).so.(|0)"
|
||||
LUA_LIB_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)"
|
||||
else:
|
||||
const
|
||||
LUA_NAME* = "lua(|5.2|5.1|5.0).dll"
|
||||
|
||||
32
rod/ast.nim
32
rod/ast.nim
@@ -409,7 +409,8 @@ type
|
||||
kind*: TLibKind
|
||||
generated*: bool # needed for the backends:
|
||||
name*: PRope
|
||||
path*: string
|
||||
path*: PNode # can be a string literal!
|
||||
|
||||
|
||||
PLib* = ref TLib
|
||||
TSym* = object of TIdObj
|
||||
@@ -949,6 +950,35 @@ proc sonsNotNil(n: PNode): bool =
|
||||
proc addSonIfNotNil(father, n: PNode) =
|
||||
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 =
|
||||
assert(length > counter)
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
@@ -219,8 +219,7 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||
# This function replaces all other methods for generating
|
||||
# the assignment operation in C.
|
||||
var ty: PType
|
||||
ty = skipTypes(dest.t, abstractVarRange)
|
||||
var ty = skipTypes(dest.t, abstractVarRange)
|
||||
case ty.kind
|
||||
of tyRef:
|
||||
genRefAssign(p, dest, src, flags)
|
||||
|
||||
54
rod/cgen.nim
54
rod/cgen.nim
@@ -164,11 +164,11 @@ proc isSimpleConst(typ: PType): bool =
|
||||
proc useHeader(m: BModule, sym: PSym) =
|
||||
if lfHeader in sym.loc.Flags:
|
||||
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)
|
||||
include
|
||||
"ccgtypes.nim"
|
||||
|
||||
include "ccgtypes.nim"
|
||||
|
||||
# ------------------------------ Manager of temporaries ------------------
|
||||
|
||||
@@ -333,32 +333,36 @@ proc libCandidates(s: string, dest: var TStringSeq) =
|
||||
add(dest, s)
|
||||
|
||||
proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
var
|
||||
tmp, loadlib: PRope
|
||||
s: TStringSeq
|
||||
assert(lib != nil)
|
||||
if not lib.generated:
|
||||
lib.generated = true
|
||||
tmp = getGlobalTempName()
|
||||
var tmp = getGlobalTempName()
|
||||
assert(lib.name == nil)
|
||||
lib.name = tmp # BUGFIX: useMagic has awful side-effects
|
||||
appff(m.s[cfsVars], "static void* $1;$n",
|
||||
"$1 = linkonce global i8* zeroinitializer$n", [tmp])
|
||||
s = @[]
|
||||
libCandidates(lib.path, s)
|
||||
loadlib = nil
|
||||
for i in countup(0, high(s)):
|
||||
inc(m.labels)
|
||||
if i > 0: app(loadlib, "||")
|
||||
appff(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n",
|
||||
"%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n" &
|
||||
"store i8* %MOC$4, i8** $1$n", [tmp, getStrLit(m, s[i]),
|
||||
getTypeDesc(m, getSysType(tyString)), toRope(m.labels)])
|
||||
appff(m.s[cfsDynLibInit],
|
||||
"if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n",
|
||||
"XXX too implement", [loadlib, getStrLit(m, lib.path)])
|
||||
#appf(m.s[cfsDynLibDeinit], "if ($1 != NIM_NIL) nimUnloadLibrary($1);$n",
|
||||
# [tmp])
|
||||
lib.name = tmp # BUGFIX: useMagic has awful side-effects
|
||||
appf(m.s[cfsVars], "static void* $1;$n", [tmp])
|
||||
if lib.path.kind in {nkStrLit..nkTripleStrLit}:
|
||||
var s: TStringSeq = @[]
|
||||
libCandidates(lib.path.strVal, s)
|
||||
var loadlib: PRope = nil
|
||||
for i in countup(0, high(s)):
|
||||
inc(m.labels)
|
||||
if i > 0: app(loadlib, "||")
|
||||
appf(loadlib, "($1 = nimLoadLibrary((NimStringDesc*) &$2))$n",
|
||||
[tmp, getStrLit(m, s[i])])
|
||||
appf(m.s[cfsDynLibInit],
|
||||
"if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n",
|
||||
[loadlib, getStrLit(m, lib.path.strVal)])
|
||||
else:
|
||||
var p = newProc(nil, m)
|
||||
var dest: TLoc
|
||||
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, "nimUnloadLibrary")
|
||||
useMagic(m, "NimStringDesc")
|
||||
|
||||
243
rod/evals.nim
243
rod/evals.nim
@@ -54,9 +54,10 @@ var emptyNode: PNode
|
||||
proc newStackFrame(): PStackFrame =
|
||||
new(result)
|
||||
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)
|
||||
result.module = module
|
||||
result.optEval = optEval
|
||||
@@ -70,6 +71,7 @@ proc popStackFrame(c: PEvalContext) =
|
||||
c.tos = c.tos.next
|
||||
|
||||
proc evalAux(c: PEvalContext, n: PNode): PNode
|
||||
|
||||
proc stackTraceAux(x: PStackFrame) =
|
||||
if x != nil:
|
||||
stackTraceAux(x.next)
|
||||
@@ -85,9 +87,8 @@ proc isSpecial(n: PNode): bool =
|
||||
result = (n.kind == nkExceptBranch) or (n.kind == nkEmpty)
|
||||
|
||||
proc evalIf(c: PEvalContext, n: PNode): PNode =
|
||||
var i, length: int
|
||||
i = 0
|
||||
length = sonsLen(n)
|
||||
var i = 0
|
||||
var length = sonsLen(n)
|
||||
while (i < length) and (sonsLen(n.sons[i]) >= 2):
|
||||
result = evalAux(c, n.sons[i].sons[0])
|
||||
if isSpecial(result): return
|
||||
@@ -100,10 +101,9 @@ proc evalIf(c: PEvalContext, n: PNode): PNode =
|
||||
result = emptyNode
|
||||
|
||||
proc evalCase(c: PEvalContext, n: PNode): PNode =
|
||||
var res: PNode
|
||||
result = evalAux(c, n.sons[0])
|
||||
if isSpecial(result): return
|
||||
res = result
|
||||
var res = result
|
||||
result = emptyNode
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
if n.sons[i].kind == nkOfBranch:
|
||||
@@ -114,11 +114,11 @@ proc evalCase(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, lastSon(n.sons[i]))
|
||||
|
||||
var
|
||||
gWhileCounter: int # Use a counter to prevent endless loops!
|
||||
# We make this counter global, because otherwise
|
||||
# nested loops could make the compiler extremely slow.
|
||||
gNestedEvals: int # count the recursive calls to ``evalAux`` to prevent
|
||||
# endless recursion
|
||||
gWhileCounter: int # Use a counter to prevent endless loops!
|
||||
# We make this counter global, because otherwise
|
||||
# nested loops could make the compiler extremely slow.
|
||||
gNestedEvals: int # count the recursive calls to ``evalAux`` to prevent
|
||||
# endless recursion
|
||||
|
||||
proc evalWhile(c: PEvalContext, n: PNode): PNode =
|
||||
while true:
|
||||
@@ -152,8 +152,7 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
|
||||
result = emptyNode # consume ``break`` token
|
||||
|
||||
proc evalFinally(c: PEvalContext, n, exc: PNode): PNode =
|
||||
var finallyNode: PNode
|
||||
finallyNode = lastSon(n)
|
||||
var finallyNode = lastSon(n)
|
||||
if finallyNode.kind == nkFinally:
|
||||
result = evalAux(c, finallyNode)
|
||||
if result.kind != nkExceptBranch: result = exc
|
||||
@@ -161,9 +160,6 @@ proc evalFinally(c: PEvalContext, n, exc: PNode): PNode =
|
||||
result = exc
|
||||
|
||||
proc evalTry(c: PEvalContext, n: PNode): PNode =
|
||||
var
|
||||
exc: PNode
|
||||
i, length, blen: int
|
||||
result = evalAux(c, n.sons[0])
|
||||
case result.kind
|
||||
of nkBreakStmt, nkReturnToken:
|
||||
@@ -172,11 +168,11 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
|
||||
if sonsLen(result) >= 1:
|
||||
# creating a nkExceptBranch without sons means that it could not be
|
||||
# evaluated
|
||||
exc = result
|
||||
i = 1
|
||||
length = sonsLen(n)
|
||||
var exc = result
|
||||
var i = 1
|
||||
var length = sonsLen(n)
|
||||
while (i < length) and (n.sons[i].kind == nkExceptBranch):
|
||||
blen = sonsLen(n.sons[i])
|
||||
var blen = sonsLen(n.sons[i])
|
||||
if blen == 1:
|
||||
# general except section:
|
||||
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)
|
||||
|
||||
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
var t: PType
|
||||
t = skipTypes(typ, abstractRange)
|
||||
var t = skipTypes(typ, abstractRange)
|
||||
result = emptyNode
|
||||
case t.kind
|
||||
of tyBool, tyChar, tyInt..tyInt64:
|
||||
@@ -219,15 +214,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
else: InternalError("getNullValue")
|
||||
|
||||
proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||
var
|
||||
v: PSym
|
||||
a: PNode
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
assert(a.kind == nkIdentDefs)
|
||||
assert(a.sons[0].kind == nkSym)
|
||||
v = a.sons[0].sym
|
||||
var v = a.sons[0].sym
|
||||
if a.sons[2] != nil:
|
||||
result = evalAux(c, a.sons[2])
|
||||
if isSpecial(result): return
|
||||
@@ -237,14 +229,11 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||
result = emptyNode
|
||||
|
||||
proc evalCall(c: PEvalContext, n: PNode): PNode =
|
||||
var
|
||||
d: PStackFrame
|
||||
prc: PNode
|
||||
result = evalAux(c, n.sons[0])
|
||||
if isSpecial(result): return
|
||||
prc = result # bind the actual params to the local parameter
|
||||
# of a new binding
|
||||
d = newStackFrame()
|
||||
var prc = result
|
||||
# bind the actual params to the local parameter of a new binding
|
||||
var d = newStackFrame()
|
||||
d.call = n
|
||||
if prc.kind == nkSym:
|
||||
d.prc = prc.sym
|
||||
@@ -265,8 +254,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
|
||||
proc evalVariable(c: PStackFrame, sym: PSym): PNode =
|
||||
# We need to return a node to the actual value,
|
||||
# which can be modified.
|
||||
var x: PStackFrame
|
||||
x = c
|
||||
var x = c
|
||||
while x != nil:
|
||||
if sfResult in sym.flags:
|
||||
return x.params[0]
|
||||
@@ -276,15 +264,12 @@ proc evalVariable(c: PStackFrame, sym: PSym): PNode =
|
||||
result = emptyNode
|
||||
|
||||
proc evalArrayAccess(c: PEvalContext, n: PNode): PNode =
|
||||
var
|
||||
x: PNode
|
||||
idx: biggestInt
|
||||
result = evalAux(c, n.sons[0])
|
||||
if isSpecial(result): return
|
||||
x = result
|
||||
var x = result
|
||||
result = evalAux(c, n.sons[1])
|
||||
if isSpecial(result): return
|
||||
idx = getOrdValue(result)
|
||||
var idx = getOrdValue(result)
|
||||
result = emptyNode
|
||||
case x.kind
|
||||
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])
|
||||
|
||||
proc evalNoOpt(c: PEvalContext, n: PNode): PNode =
|
||||
result = newNodeI(nkExceptBranch, n.info) # creating a nkExceptBranch without sons means that it could not be
|
||||
# evaluated
|
||||
result = newNodeI(nkExceptBranch, n.info)
|
||||
# creating a nkExceptBranch without sons means that it could not be evaluated
|
||||
|
||||
proc evalNew(c: PEvalContext, n: PNode): PNode =
|
||||
var t: PType
|
||||
if c.optEval:
|
||||
result = evalNoOpt(c, n)
|
||||
else:
|
||||
t = skipTypes(n.sons[1].typ, abstractVar)
|
||||
var t = skipTypes(n.sons[1].typ, abstractVar)
|
||||
result = newNodeIT(nkRefTy, n.info, t)
|
||||
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)
|
||||
|
||||
proc evalAddr(c: PEvalContext, n: PNode): PNode =
|
||||
var
|
||||
a: PNode
|
||||
t: PType
|
||||
result = evalAux(c, n.sons[0])
|
||||
if isSpecial(result): return
|
||||
a = result
|
||||
t = newType(tyPtr, c.module)
|
||||
var a = result
|
||||
var t = newType(tyPtr, c.module)
|
||||
addSon(t, a.typ)
|
||||
result = newNodeIT(nkRefTy, n.info, t)
|
||||
addSon(result, a)
|
||||
@@ -477,11 +458,10 @@ proc evalCheckedFieldAccess(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[0])
|
||||
|
||||
proc evalUpConv(c: PEvalContext, n: PNode): PNode =
|
||||
var dest, src: PType
|
||||
result = evalAux(c, n.sons[0])
|
||||
if isSpecial(result): return
|
||||
dest = skipTypes(n.typ, abstractPtrs)
|
||||
src = skipTypes(result.typ, abstractPtrs)
|
||||
var dest = skipTypes(n.typ, abstractPtrs)
|
||||
var src = skipTypes(result.typ, abstractPtrs)
|
||||
if inheritanceDiff(src, dest) > 0:
|
||||
stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src))
|
||||
|
||||
@@ -710,48 +690,27 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
k: biggestInt
|
||||
m = getMagic(n)
|
||||
case m
|
||||
of mNone:
|
||||
result = evalCall(c, n)
|
||||
of mIs:
|
||||
result = evalIs(c, n)
|
||||
of mSizeOf:
|
||||
internalError(n.info, "sizeof() should have been evaluated")
|
||||
of mHigh:
|
||||
result = evalHigh(c, n)
|
||||
of mAssert:
|
||||
result = evalAssert(c, n)
|
||||
of mExit:
|
||||
result = evalExit(c, n)
|
||||
of mNew, mNewFinalize:
|
||||
result = evalNew(c, n)
|
||||
of mNewSeq:
|
||||
result = evalNewSeq(c, n)
|
||||
of mSwap:
|
||||
result = evalSwap(c, n)
|
||||
of mInc:
|
||||
result = evalIncDec(c, n, 1)
|
||||
of ast.mDec:
|
||||
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 mNone: result = evalCall(c, n)
|
||||
of mIs: result = evalIs(c, n)
|
||||
of mSizeOf: internalError(n.info, "sizeof() should have been evaluated")
|
||||
of mHigh: result = evalHigh(c, n)
|
||||
of mAssert: result = evalAssert(c, n)
|
||||
of mExit: result = evalExit(c, n)
|
||||
of mNew, mNewFinalize: result = evalNew(c, n)
|
||||
of mNewSeq: result = evalNewSeq(c, n)
|
||||
of mSwap: result = evalSwap(c, n)
|
||||
of mInc: result = evalIncDec(c, n, 1)
|
||||
of ast.mDec: 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:
|
||||
result = evalAux(c, n.sons[1])
|
||||
if isSpecial(result): return
|
||||
@@ -848,8 +807,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[1])
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkIdent: InternalError(n.info, "no symbol")
|
||||
of mNGetType:
|
||||
result = evalAux(c, n.sons[1])
|
||||
of mNGetType: result = evalAux(c, n.sons[1])
|
||||
of mNStrVal:
|
||||
result = evalAux(c, n.sons[1])
|
||||
if isSpecial(result): return
|
||||
@@ -1009,14 +967,10 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
|
||||
dec(gNestedEvals)
|
||||
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
|
||||
case n.kind # atoms:
|
||||
of nkEmpty:
|
||||
result = n
|
||||
of nkSym:
|
||||
result = evalSym(c, n)
|
||||
of nkType..pred(nkNilLit):
|
||||
result = copyNode(n)
|
||||
of nkNilLit:
|
||||
result = n # end of atoms
|
||||
of nkEmpty: result = n
|
||||
of nkSym: result = evalSym(c, n)
|
||||
of nkType..pred(nkNilLit): result = copyNode(n)
|
||||
of nkNilLit: result = n # end of atoms
|
||||
of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit:
|
||||
result = evalMagicOrCall(c, n)
|
||||
of nkCurly, nkBracket, nkRange:
|
||||
@@ -1033,52 +987,29 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
|
||||
if isSpecial(result): return
|
||||
a.sons[i].sons[1] = result
|
||||
result = a
|
||||
of nkBracketExpr:
|
||||
result = evalArrayAccess(c, n)
|
||||
of nkDotExpr:
|
||||
result = evalFieldAccess(c, n)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
result = evalDeref(c, n)
|
||||
of nkAddr, nkHiddenAddr:
|
||||
result = evalAddr(c, n)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
result = evalConv(c, n)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
result = evalAsgn(c, n)
|
||||
of nkWhenStmt, nkIfStmt, nkIfExpr:
|
||||
result = evalIf(c, n)
|
||||
of nkWhileStmt:
|
||||
result = evalWhile(c, n)
|
||||
of nkCaseStmt:
|
||||
result = evalCase(c, n)
|
||||
of nkVarSection:
|
||||
result = evalVar(c, n)
|
||||
of nkTryStmt:
|
||||
result = evalTry(c, n)
|
||||
of nkRaiseStmt:
|
||||
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 nkBracketExpr: result = evalArrayAccess(c, n)
|
||||
of nkDotExpr: result = evalFieldAccess(c, n)
|
||||
of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n)
|
||||
of nkAddr, nkHiddenAddr: result = evalAddr(c, n)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
|
||||
of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
|
||||
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
|
||||
of nkWhileStmt: result = evalWhile(c, n)
|
||||
of nkCaseStmt: result = evalCase(c, n)
|
||||
of nkVarSection: result = evalVar(c, n)
|
||||
of nkTryStmt: result = evalTry(c, n)
|
||||
of nkRaiseStmt: 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:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result = evalAux(c, n.sons[i])
|
||||
@@ -1106,11 +1037,8 @@ proc eval(c: PEvalContext, n: PNode): PNode =
|
||||
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ))
|
||||
|
||||
proc evalConstExpr(module: PSym, e: PNode): PNode =
|
||||
var
|
||||
p: PEvalContext
|
||||
s: PStackFrame
|
||||
p = newEvalContext(module, "", true)
|
||||
s = newStackFrame()
|
||||
var p = newEvalContext(module, "", true)
|
||||
var s = newStackFrame()
|
||||
s.call = e
|
||||
pushStackFrame(p, s)
|
||||
result = eval(p, e)
|
||||
@@ -1118,8 +1046,7 @@ proc evalConstExpr(module: PSym, e: PNode): PNode =
|
||||
popStackFrame(p)
|
||||
|
||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
var c: PEvalContext
|
||||
c = newEvalContext(module, filename, false)
|
||||
var c = newEvalContext(module, filename, false)
|
||||
pushStackFrame(c, newStackFrame())
|
||||
result = c
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
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
|
||||
FirstCallConv* = wNimcall
|
||||
@@ -78,17 +78,17 @@ proc MakeExternExport(s: PSym, extname: string) =
|
||||
s.loc.r = toRope(extname)
|
||||
incl(s.flags, sfExportc)
|
||||
|
||||
proc expectStrLit(c: PContext, n: PNode): string =
|
||||
proc getStrLitNode(c: PContext, n: PNode): PNode =
|
||||
if n.kind != nkExprColonExpr:
|
||||
liMessage(n.info, errStringLiteralExpected)
|
||||
result = ""
|
||||
else:
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
case n.sons[1].kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1].strVal
|
||||
else:
|
||||
liMessage(n.info, errStringLiteralExpected)
|
||||
result = ""
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
|
||||
else: liMessage(n.info, errStringLiteralExpected)
|
||||
|
||||
proc expectStrLit(c: PContext, n: PNode): string =
|
||||
result = getStrLitNode(c, n).strVal
|
||||
|
||||
proc expectIntLit(c: PContext, n: PNode): int =
|
||||
if n.kind != nkExprColonExpr:
|
||||
@@ -128,23 +128,22 @@ proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
||||
# the same
|
||||
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):
|
||||
case whichKeyword(n.sons[1].ident)
|
||||
of wOn: gOptions = gOptions + op
|
||||
of wOff: gOptions = gOptions - op
|
||||
of wOn: result = true
|
||||
of wOff: result = false
|
||||
else: liMessage(n.info, errOnOrOffExpected)
|
||||
else:
|
||||
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) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
case whichKeyword(n.sons[1].ident)
|
||||
of wOn: incl(c.module.flags, sfDeadCodeElim)
|
||||
of wOff: excl(c.module.flags, sfDeadCodeElim)
|
||||
else: liMessage(n.info, errOnOrOffExpected)
|
||||
else:
|
||||
liMessage(n.info, errOnOrOffExpected)
|
||||
if IsTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
|
||||
else: excl(c.module.flags, sfDeadCodeElim)
|
||||
|
||||
proc processCallConv(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
@@ -156,27 +155,31 @@ proc processCallConv(c: PContext, n: PNode) =
|
||||
else:
|
||||
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)
|
||||
while it != nil:
|
||||
if it.kind == kind:
|
||||
if ospCaseInsensitive in platform.OS[targetOS].props:
|
||||
if cmpIgnoreCase(it.path, path) == 0:
|
||||
return it
|
||||
else:
|
||||
if it.path == path:
|
||||
return it
|
||||
if trees.ExprStructuralEquivalent(it.path, path): return it
|
||||
it = PLib(it.next)
|
||||
result = newLib(kind)
|
||||
result.path = path
|
||||
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) =
|
||||
if (sym == nil) or (sym.kind == skModule):
|
||||
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
|
||||
expectStrLit(c, n))
|
||||
expectDynlibNode(c, n))
|
||||
elif n.kind == nkExprColonExpr:
|
||||
var lib = getLib(c, libDynamic, expectStrLit(c, n))
|
||||
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
|
||||
addToLib(lib, sym)
|
||||
incl(sym.loc.flags, lfDynamicLib)
|
||||
else:
|
||||
@@ -366,7 +369,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
noval(it)
|
||||
incl(sym.flags, sfMerge)
|
||||
of wHeader:
|
||||
var lib = getLib(c, libHeader, expectStrLit(c, it))
|
||||
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
||||
addToLib(lib, sym)
|
||||
incl(sym.flags, sfImportc)
|
||||
incl(sym.loc.flags, lfHeader)
|
||||
|
||||
185
rod/rodread.nim
185
rod/rodread.nim
@@ -146,9 +146,9 @@ proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType
|
||||
proc decode(r: PRodReader): string
|
||||
proc decodeInt(r: PRodReader): int
|
||||
proc decodeBInt(r: PRodReader): biggestInt
|
||||
|
||||
proc encode(s: string): PRope =
|
||||
var res: string
|
||||
res = ""
|
||||
var res = ""
|
||||
for i in countup(0, len(s) + 0 - 1):
|
||||
case 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)
|
||||
|
||||
proc encodeIntAux(str: var string, x: BiggestInt) =
|
||||
const
|
||||
chars: string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
var
|
||||
v, rem: biggestInt
|
||||
d: char
|
||||
idx: int
|
||||
v = x
|
||||
rem = v mod 190
|
||||
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
var d: char
|
||||
var v = x
|
||||
var rem: biggestInt = v mod 190
|
||||
if (rem < 0):
|
||||
str = str & '-'
|
||||
add(str, '-')
|
||||
v = - (v div 190)
|
||||
rem = - rem
|
||||
else:
|
||||
v = v div 190
|
||||
idx = int(rem)
|
||||
var idx = int(rem)
|
||||
if idx < 62: d = chars[idx + 0]
|
||||
else: d = chr(idx - 62 + 128)
|
||||
if (v != 0): encodeIntAux(str, v)
|
||||
add(str, d)
|
||||
|
||||
proc encodeInt(x: BiggestInt): PRope =
|
||||
var res: string
|
||||
res = ""
|
||||
var res = ""
|
||||
encodeIntAux(res, x)
|
||||
result = toRope(res)
|
||||
|
||||
@@ -303,8 +298,8 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
|
||||
if debugIds: registerID(result)
|
||||
else:
|
||||
InternalError(info, "decodeType: no id")
|
||||
IdTablePut(gTypeTable, result, result) # here this also
|
||||
# avoids endless recursion for recursive type
|
||||
# here this also 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] == '$':
|
||||
inc(r.pos)
|
||||
@@ -343,7 +338,7 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
|
||||
d = decodeInt(r)
|
||||
addSon(result, rrGetType(r, d, info))
|
||||
|
||||
proc decodeLib(r: PRodReader): PLib =
|
||||
proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
|
||||
result = nil
|
||||
if r.s[r.pos] == '|':
|
||||
new(result)
|
||||
@@ -354,11 +349,10 @@ proc decodeLib(r: PRodReader): PLib =
|
||||
result.name = toRope(decode(r))
|
||||
if r.s[r.pos] != '|': InternalError("decodeLib: 2")
|
||||
inc(r.pos)
|
||||
result.path = decode(r)
|
||||
result.path = decodeNode(r, info)
|
||||
|
||||
proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||
var
|
||||
k: TSymKind
|
||||
id: int
|
||||
ident: PIdent
|
||||
result = nil
|
||||
@@ -367,7 +361,7 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||
if r.s[r.pos] == '}':
|
||||
inc(r.pos)
|
||||
return # nil sym
|
||||
k = TSymKind(decodeInt(r))
|
||||
var k = TSymKind(decodeInt(r))
|
||||
if r.s[r.pos] == '+':
|
||||
inc(r.pos)
|
||||
id = decodeInt(r)
|
||||
@@ -412,22 +406,20 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
|
||||
inc(r.pos)
|
||||
result.position = decodeInt(r)
|
||||
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] == '`':
|
||||
inc(r.pos)
|
||||
result.offset = decodeInt(r)
|
||||
else:
|
||||
result.offset = - 1
|
||||
decodeLoc(r, result.loc, result.info)
|
||||
result.annex = decodeLib(r)
|
||||
result.annex = decodeLib(r, info)
|
||||
|
||||
proc decodeInt(r: PRodReader): int =
|
||||
# base 190 numbers
|
||||
var
|
||||
i: int
|
||||
sign: int
|
||||
i = r.pos
|
||||
sign = - 1
|
||||
var i = r.pos
|
||||
var sign = - 1
|
||||
assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
||||
if r.s[i] == '-':
|
||||
inc(i)
|
||||
@@ -445,11 +437,8 @@ proc decodeInt(r: PRodReader): int =
|
||||
r.pos = i
|
||||
|
||||
proc decodeBInt(r: PRodReader): biggestInt =
|
||||
var
|
||||
i: int
|
||||
sign: biggestInt
|
||||
i = r.pos
|
||||
sign = - 1
|
||||
var i = r.pos
|
||||
var sign: biggestInt = - 1
|
||||
assert(r.s[i] in {'a'..'z', 'A'..'Z', '0'..'9', '-', '\x80'..'\xFF'})
|
||||
if r.s[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 '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:
|
||||
nil
|
||||
else: nil
|
||||
|
||||
proc decode(r: PRodReader): string =
|
||||
var i, xi: int
|
||||
i = r.pos
|
||||
var i = r.pos
|
||||
result = ""
|
||||
while true:
|
||||
case r.s[i]
|
||||
of '\\':
|
||||
inc(i, 3)
|
||||
xi = 0
|
||||
var xi = 0
|
||||
hexChar(r.s[i - 2], xi)
|
||||
hexChar(r.s[i - 1], xi)
|
||||
add(result, chr(xi))
|
||||
@@ -493,28 +480,23 @@ proc decode(r: PRodReader): string =
|
||||
r.pos = i
|
||||
|
||||
proc skipSection(r: PRodReader) =
|
||||
var c: int
|
||||
if r.s[r.pos] == ':':
|
||||
while r.s[r.pos] > '\x0A': inc(r.pos)
|
||||
elif r.s[r.pos] == '(':
|
||||
c = 0 # count () pairs
|
||||
var c = 0 # count () pairs
|
||||
inc(r.pos)
|
||||
while true:
|
||||
case r.s[r.pos]
|
||||
of '\x0A':
|
||||
inc(r.line)
|
||||
of '(':
|
||||
inc(c)
|
||||
of '\x0A': inc(r.line)
|
||||
of '(': inc(c)
|
||||
of ')':
|
||||
if c == 0:
|
||||
inc(r.pos)
|
||||
break
|
||||
elif c > 0:
|
||||
dec(c)
|
||||
of '\0':
|
||||
break # end of file
|
||||
else:
|
||||
nil
|
||||
of '\0': break # end of file
|
||||
else: nil
|
||||
inc(r.pos)
|
||||
else:
|
||||
InternalError("skipSection " & $(r.line))
|
||||
@@ -535,18 +517,14 @@ proc newStub(r: PRodReader, name: string, id: int): PSym =
|
||||
if debugIds: registerID(result)
|
||||
|
||||
proc processInterf(r: PRodReader, module: PSym) =
|
||||
var
|
||||
s: PSym
|
||||
w: string
|
||||
key: int
|
||||
if r.interfIdx == 0: InternalError("processInterf")
|
||||
r.pos = r.interfIdx
|
||||
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||
w = decode(r)
|
||||
var w = decode(r)
|
||||
inc(r.pos)
|
||||
key = decodeInt(r)
|
||||
var key = decodeInt(r)
|
||||
inc(r.pos) # #10
|
||||
s = newStub(r, w, key)
|
||||
var s = newStub(r, w, key)
|
||||
s.owner = module
|
||||
StrTableAdd(module.tab, s)
|
||||
IdTablePut(r.syms, s, s)
|
||||
@@ -669,8 +647,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||
skipSection(r)
|
||||
elif section == "DATA":
|
||||
r.dataIdx = r.pos + 2 # "(\10"
|
||||
# We do not read the DATA section here! We read the needed objects on
|
||||
# demand.
|
||||
# We do not read the DATA section here! We read the needed objects on
|
||||
# demand.
|
||||
skipSection(r)
|
||||
elif section == "INIT":
|
||||
r.initIdx = r.pos + 2 # "(\10"
|
||||
@@ -685,14 +663,12 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
|
||||
inc(r.pos)
|
||||
inc(r.line)
|
||||
|
||||
proc newRodReader(modfilename: string, crc: TCrc32, readerIndex: int): PRodReader =
|
||||
var
|
||||
version: string
|
||||
r: PRodReader
|
||||
proc newRodReader(modfilename: string, crc: TCrc32,
|
||||
readerIndex: int): PRodReader =
|
||||
new(result)
|
||||
result.files = @ []
|
||||
result.modDeps = @ []
|
||||
r = result
|
||||
result.files = @[]
|
||||
result.modDeps = @[]
|
||||
var r = result
|
||||
r.reason = rrNone
|
||||
r.pos = 0
|
||||
r.line = 1
|
||||
@@ -704,7 +680,7 @@ proc newRodReader(modfilename: string, crc: TCrc32, readerIndex: int): PRodReade
|
||||
initIITable(r.index.tab)
|
||||
initIITable(r.imports.tab) # looks like a ROD file
|
||||
inc(r.pos, 4)
|
||||
version = ""
|
||||
var version = ""
|
||||
while not (r.s[r.pos] in {'\0', '\x0A'}):
|
||||
add(version, r.s[r.pos])
|
||||
inc(r.pos)
|
||||
@@ -719,12 +695,11 @@ proc newRodReader(modfilename: string, crc: TCrc32, readerIndex: int): PRodReade
|
||||
result = nil
|
||||
|
||||
proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType =
|
||||
var oldPos, d: int
|
||||
result = PType(IdTableGet(gTypeTable, id))
|
||||
if result == nil:
|
||||
# load the type:
|
||||
oldPos = r.pos
|
||||
d = IITableGet(r.index.tab, id)
|
||||
var oldPos = r.pos
|
||||
var d = IITableGet(r.index.tab, id)
|
||||
if d == invalidKey: InternalError(info, "rrGetType")
|
||||
r.pos = d + r.dataIdx
|
||||
result = decodeType(r, info)
|
||||
@@ -739,39 +714,29 @@ type
|
||||
|
||||
TFileModuleMap = seq[TFileModuleRec]
|
||||
|
||||
var gMods: TFileModuleMap = @ []
|
||||
var gMods: TFileModuleMap = @[]
|
||||
|
||||
proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym =
|
||||
# all compiled modules
|
||||
var oldPos: int
|
||||
if rd.dataIdx == 0: InternalError(info, "dataIdx == 0")
|
||||
oldPos = rd.pos
|
||||
var oldPos = rd.pos
|
||||
rd.pos = offset + rd.dataIdx
|
||||
result = decodeSym(rd, info)
|
||||
rd.pos = oldPos
|
||||
|
||||
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
|
||||
var
|
||||
d, moduleID: int
|
||||
rd: PRodReader
|
||||
result = PSym(IdTableGet(r.syms, id))
|
||||
if result == nil:
|
||||
# load the symbol:
|
||||
d = IITableGet(r.index.tab, id)
|
||||
var d = IITableGet(r.index.tab, id)
|
||||
if d == invalidKey:
|
||||
moduleID = IiTableGet(r.imports.tab, id)
|
||||
var moduleID = IiTableGet(r.imports.tab, id)
|
||||
if moduleID < 0:
|
||||
InternalError(info,
|
||||
"missing from both indexes: +" & ropeToStr(encodeInt(id))) #
|
||||
# find
|
||||
# the
|
||||
# reader
|
||||
# with
|
||||
# the
|
||||
# correct
|
||||
# moduleID:
|
||||
"missing from both indexes: +" & ropeToStr(encodeInt(id)))
|
||||
# find the reader with the correct moduleID:
|
||||
for i in countup(0, high(gMods)):
|
||||
rd = gMods[i].rd
|
||||
var rd = gMods[i].rd
|
||||
if (rd != nil):
|
||||
if (rd.moduleID == moduleID):
|
||||
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)
|
||||
|
||||
proc loadInitSection(r: PRodReader): PNode =
|
||||
var d, oldPos, p: int
|
||||
if (r.initIdx == 0) or (r.dataIdx == 0): InternalError("loadInitSection")
|
||||
oldPos = r.pos
|
||||
var oldPos = r.pos
|
||||
r.pos = r.initIdx
|
||||
result = newNode(nkStmtList)
|
||||
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
|
||||
d = decodeInt(r)
|
||||
var d = decodeInt(r)
|
||||
inc(r.pos) # #10
|
||||
p = r.pos
|
||||
var p = r.pos
|
||||
r.pos = d + r.dataIdx
|
||||
addSon(result, decodeNode(r, UnknownLineInfo()))
|
||||
r.pos = p
|
||||
r.pos = oldPos
|
||||
|
||||
proc loadConverters(r: PRodReader) =
|
||||
var d: int
|
||||
# We have to ensure that no exported converter is a stub anymore.
|
||||
if (r.convertersIdx == 0) or (r.dataIdx == 0):
|
||||
InternalError("importConverters")
|
||||
r.pos = r.convertersIdx
|
||||
while (r.s[r.pos] > '\x0A'):
|
||||
d = decodeInt(r)
|
||||
var d = decodeInt(r)
|
||||
discard rrGetSym(r, d, UnknownLineInfo())
|
||||
if r.s[r.pos] == ' ': inc(r.pos)
|
||||
|
||||
proc getModuleIdx(filename: string): int =
|
||||
for i in countup(0, high(gMods)):
|
||||
if sameFile(gMods[i].filename, filename):
|
||||
return i
|
||||
if sameFile(gMods[i].filename, filename): return i
|
||||
result = len(gMods)
|
||||
setlen(gMods, result + 1)
|
||||
|
||||
proc checkDep(filename: string): TReasonForRecompile =
|
||||
var
|
||||
crc: TCrc32
|
||||
r: PRodReader
|
||||
rodfile: string
|
||||
idx: int
|
||||
res: TReasonForRecompile
|
||||
idx = getModuleIdx(filename)
|
||||
var idx = getModuleIdx(filename)
|
||||
if gMods[idx].reason != rrEmpty:
|
||||
# reason has already been computed for this module:
|
||||
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].filename = filename
|
||||
gMods[idx].crc = crc
|
||||
result = rrNone
|
||||
r = nil
|
||||
rodfile = toGeneratedFile(filename, RodExt)
|
||||
var r: PRodReader = nil
|
||||
var rodfile = toGeneratedFile(filename, RodExt)
|
||||
if ExistsFile(rodfile):
|
||||
r = newRodReader(rodfile, crc, idx)
|
||||
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
|
||||
# be used twice! However, compilation speed does not suffer much from
|
||||
# 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
|
||||
for i in countup(0, high(r.modDeps)):
|
||||
res = checkDep(r.modDeps[i])
|
||||
@@ -870,12 +826,11 @@ proc checkDep(filename: string): TReasonForRecompile =
|
||||
gMods[idx].reason = result # now we know better
|
||||
|
||||
proc handleSymbolFile(module: PSym, filename: string): PRodReader =
|
||||
var idx: int
|
||||
if not (optSymbolFiles in gGlobalOptions):
|
||||
module.id = getID()
|
||||
return nil
|
||||
discard checkDep(filename)
|
||||
idx = getModuleIdx(filename)
|
||||
var idx = getModuleIdx(filename)
|
||||
if gMods[idx].reason == rrEmpty: InternalError("handleSymbolFile")
|
||||
result = gMods[idx].rd
|
||||
if result != nil:
|
||||
@@ -888,26 +843,22 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader =
|
||||
module.id = getID()
|
||||
|
||||
proc GetCRC(filename: string): TCrc32 =
|
||||
var idx: int
|
||||
idx = getModuleIdx(filename)
|
||||
var idx = getModuleIdx(filename)
|
||||
result = gMods[idx].crc
|
||||
|
||||
proc loadStub(s: PSym) =
|
||||
var
|
||||
rd: PRodReader
|
||||
d, theId: int
|
||||
rs: PSym
|
||||
if s.kind != skStub:
|
||||
InternalError("loadStub") #MessageOut('loading stub: ' + s.name.s);
|
||||
rd = gMods[s.position].rd
|
||||
theId = s.id # used for later check
|
||||
d = IITableGet(rd.index.tab, s.id)
|
||||
var rd = gMods[s.position].rd
|
||||
var theId = s.id # used for later check
|
||||
var d = IITableGet(rd.index.tab, s.id)
|
||||
if d == invalidKey: InternalError("loadStub: invalid key")
|
||||
rs = decodeSymSafePos(rd, d, UnknownLineInfo())
|
||||
var rs = decodeSymSafePos(rd, d, UnknownLineInfo())
|
||||
if rs != s:
|
||||
InternalError(rs.info, "loadStub: wrong symbol")
|
||||
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)
|
||||
InitStrTable(rodCompilerProcs)
|
||||
InitStrTable(rodCompilerProcs)
|
||||
|
||||
@@ -49,11 +49,10 @@ proc encodeStr(w: PRodWriter, s: string): PRope =
|
||||
result = encode(s)
|
||||
|
||||
proc processStacks(w: PRodWriter)
|
||||
|
||||
proc getDefines(): PRope =
|
||||
var
|
||||
it: TTabIter
|
||||
s: PSym
|
||||
s = InitTabIter(it, gSymbols)
|
||||
var it: TTabIter
|
||||
var s = InitTabIter(it, gSymbols)
|
||||
result = nil
|
||||
while s != nil:
|
||||
if s.position == 1:
|
||||
@@ -96,39 +95,38 @@ proc addInclDep(w: PRodWriter, dep: string) =
|
||||
app(w.inclDeps, rodNL)
|
||||
|
||||
proc pushType(w: PRodWriter, t: PType) =
|
||||
var L: int
|
||||
# check so that the stack does not grow too large:
|
||||
if IiTableGet(w.index.tab, t.id) == invalidKey:
|
||||
L = len(w.tstack)
|
||||
var L = len(w.tstack)
|
||||
setlen(w.tstack, L + 1)
|
||||
w.tstack[L] = t
|
||||
|
||||
proc pushSym(w: PRodWriter, s: PSym) =
|
||||
var L: int
|
||||
# check so that the stack does not grow too large:
|
||||
if IiTableGet(w.index.tab, s.id) == invalidKey:
|
||||
L = len(w.sstack)
|
||||
var L = len(w.sstack)
|
||||
setlen(w.sstack, L + 1)
|
||||
w.sstack[L] = s
|
||||
|
||||
proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode): PRope =
|
||||
var f: TNodeFlags
|
||||
if n == nil:
|
||||
# nil nodes have to be stored too:
|
||||
return toRope("()")
|
||||
result = toRope("(")
|
||||
app(result, encodeInt(ord(n.kind))) # we do not write comments for now
|
||||
# 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:
|
||||
app(result, encodeInt(ord(n.kind)))
|
||||
# we do not write comments for now
|
||||
# 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):
|
||||
appf(result, "?$1,$2,$3", [encodeInt(n.info.col), encodeInt(n.info.line),
|
||||
encodeInt(fileIdx(w, toFilename(n.info)))])
|
||||
elif (finfo.line != n.info.line):
|
||||
appf(result, "?$1,$2", [encodeInt(n.info.col), encodeInt(n.info.line)])
|
||||
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
|
||||
# file.
|
||||
f = n.flags * PersistentNodeFlags
|
||||
appf(result, "?$1", [encodeInt(n.info.col)])
|
||||
# No need to output the file index, as this is the serialization of one
|
||||
# file.
|
||||
var f = n.flags * PersistentNodeFlags
|
||||
if f != {}: appf(result, "$$$1", [encodeInt(cast[int32](f))])
|
||||
if n.typ != nil:
|
||||
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)])
|
||||
pushType(w, t.sons[i])
|
||||
|
||||
proc encodeLib(w: PRodWriter, lib: PLib): PRope =
|
||||
proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo): PRope =
|
||||
result = nil
|
||||
appf(result, "|$1", [encodeInt(ord(lib.kind))])
|
||||
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 =
|
||||
var
|
||||
@@ -235,7 +233,7 @@ proc encodeSym(w: PRodWriter, s: PSym): PRope =
|
||||
if s.position != 0: appf(result, "%$1", [encodeInt(s.position)])
|
||||
if s.offset != - 1: appf(result, "`$1", [encodeInt(s.offset)])
|
||||
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) =
|
||||
if key - w.lastIdxKey == 1:
|
||||
@@ -367,10 +365,11 @@ proc writeRod(w: PRodWriter) =
|
||||
app(content, toRope(')' & rodNL))
|
||||
app(content, toRope("DATA(" & rodNL))
|
||||
app(content, w.data)
|
||||
app(content, toRope(')' & rodNL)) #MessageOut('interf ' + ToString(ropeLen(w.interf)));
|
||||
#MessageOut('index ' + ToString(ropeLen(w.indexRope)));
|
||||
#MessageOut('init ' + ToString(ropeLen(w.init)));
|
||||
#MessageOut('data ' + ToString(ropeLen(w.data)));
|
||||
app(content, toRope(')' & rodNL))
|
||||
#MessageOut('interf ' + ToString(ropeLen(w.interf)));
|
||||
#MessageOut('index ' + ToString(ropeLen(w.indexRope)));
|
||||
#MessageOut('init ' + ToString(ropeLen(w.init)));
|
||||
#MessageOut('data ' + ToString(ropeLen(w.data)));
|
||||
writeRope(content, completeGeneratedFilePath(changeFileExt(w.filename, "rod")))
|
||||
|
||||
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.sons[0].kind != nkSym: InternalError(a.info, "rodwrite.process")
|
||||
s = a.sons[0].sym
|
||||
addInterfaceSym(w, s) # this takes care of enum fields too
|
||||
# Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum
|
||||
# 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;
|
||||
# for j := 0 to sonsLen(a)-1 do
|
||||
# addInterfaceSym(w, a.sons[j].sym);
|
||||
# end
|
||||
addInterfaceSym(w, s)
|
||||
# this takes care of enum fields too
|
||||
# Note: The check for ``s.typ.kind = tyEnum`` is wrong for enum
|
||||
# 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;
|
||||
# for j := 0 to sonsLen(a)-1 do
|
||||
# addInterfaceSym(w, a.sons[j].sym);
|
||||
# end
|
||||
of nkImportStmt:
|
||||
for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleFile(n.sons[i]))
|
||||
addStmt(w, n)
|
||||
@@ -435,15 +435,13 @@ proc process(c: PPassContext, n: PNode): PNode =
|
||||
nil
|
||||
|
||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
var w: PRodWriter
|
||||
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)
|
||||
result = w
|
||||
|
||||
proc myClose(c: PPassContext, n: PNode): PNode =
|
||||
var w: PRodWriter
|
||||
w = PRodWriter(c)
|
||||
var w = PRodWriter(c)
|
||||
writeRod(w)
|
||||
result = n
|
||||
|
||||
@@ -454,4 +452,4 @@ proc rodwritePass(): TPass =
|
||||
result.close = myClose
|
||||
result.process = process
|
||||
|
||||
IntSetInit(debugWritten)
|
||||
IntSetInit(debugWritten)
|
||||
|
||||
71
rod/sem.nim
71
rod/sem.nim
@@ -9,8 +9,7 @@
|
||||
|
||||
# This module implements the semantic checking pass.
|
||||
|
||||
import #var
|
||||
# point: array [0..3] of int;
|
||||
import
|
||||
strutils, nhashes, lists, options, scanner, ast, astalgo, trees, treetab,
|
||||
wordrecg, ropes, msgs, os, condsyms, idents, rnimsyn, types, platform, math,
|
||||
magicsys, pnimsyn, nversion, nimsets, semdata, evals, semfold, importer,
|
||||
@@ -20,8 +19,7 @@ proc semPass*(): TPass
|
||||
# implementation
|
||||
|
||||
proc considerAcc(n: PNode): PIdent =
|
||||
var x: PNode
|
||||
x = n
|
||||
var x = n
|
||||
if x.kind == nkAccQuoted: x = x.sons[0]
|
||||
case x.kind
|
||||
of nkIdent: result = x.ident
|
||||
@@ -62,6 +60,7 @@ proc addParams(c: PContext, n: PNode)
|
||||
proc addResult(c: PContext, t: PType, info: TLineInfo)
|
||||
proc addResultNode(c: PContext, n: PNode)
|
||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
|
||||
|
||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
result = semExprWithType(c, n)
|
||||
if result == nil:
|
||||
@@ -71,8 +70,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
if result == nil: liMessage(n.info, errConstExprExpected)
|
||||
|
||||
proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
|
||||
var e: PNode
|
||||
e = semExprWithType(c, n)
|
||||
var e = semExprWithType(c, n)
|
||||
if e == nil:
|
||||
liMessage(n.info, errConstExprExpected)
|
||||
return nil
|
||||
@@ -91,19 +89,16 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||
of tyTypeDesc: result.typ = semTypeNode(c, result, nil)
|
||||
else: liMessage(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
||||
|
||||
include
|
||||
"semtempl.nim"
|
||||
include "semtempl.nim"
|
||||
|
||||
proc semMacroExpr(c: PContext, n: PNode, sym: PSym, semCheck: bool = true): PNode =
|
||||
var
|
||||
p: PEvalContext
|
||||
s: PStackFrame
|
||||
proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||
semCheck: bool = true): PNode =
|
||||
inc(evalTemplateCounter)
|
||||
if evalTemplateCounter > 100:
|
||||
liMessage(n.info, errTemplateInstantiationTooNested)
|
||||
markUsed(n, sym)
|
||||
p = newEvalContext(c.module, "", false)
|
||||
s = newStackFrame()
|
||||
var p = newEvalContext(c.module, "", false)
|
||||
var s = newStackFrame()
|
||||
s.call = n
|
||||
setlen(s.params, 2)
|
||||
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)
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
include
|
||||
"seminst.nim"
|
||||
|
||||
include
|
||||
"sigmatch.nim"
|
||||
include "seminst.nim", "sigmatch.nim"
|
||||
|
||||
proc CheckBool(t: PNode) =
|
||||
if (t.Typ == nil) or
|
||||
@@ -132,37 +123,27 @@ proc typeMismatch(n: PNode, formal, actual: PType) =
|
||||
typeToString(actual) & ") " &
|
||||
`%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
|
||||
|
||||
include
|
||||
"semtypes.nim"
|
||||
|
||||
include
|
||||
"semexprs.nim"
|
||||
|
||||
include
|
||||
"semgnrc.nim"
|
||||
|
||||
include
|
||||
"semstmts.nim"
|
||||
include "semtypes.nim", "semexprs.nim", "semgnrc.nim", "semstmts.nim"
|
||||
|
||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||
var
|
||||
prc: PSym
|
||||
it: PNode
|
||||
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")
|
||||
prc = it.sym
|
||||
var prc = it.sym
|
||||
if (prc.kind in {skProc, skMethod, skConverter}) and (prc.magic == mNone):
|
||||
if (prc.ast == nil) or (prc.ast.sons[codePos] == nil):
|
||||
InternalError(prc.info, "no code for " & prc.name.s)
|
||||
addSon(n, prc.ast)
|
||||
c.lastGenericIdx = sonsLen(c.generics)
|
||||
|
||||
proc semExprNoFlags(c: PContext, n: PNode): PNode =
|
||||
result = semExpr(c, n, {})
|
||||
|
||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
var c: PContext
|
||||
c = newContext(module, filename)
|
||||
var c = newContext(module, filename)
|
||||
if (c.p != nil): InternalError(module.info, "sem.myOpen")
|
||||
c.semConstExpr = semConstExpr
|
||||
c.semExpr = semExprNoFlags
|
||||
c.p = newProcCon(module)
|
||||
pushOwner(c.module)
|
||||
openScope(c.tab) # scope for imported symbols
|
||||
@@ -177,20 +158,17 @@ proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
result = c
|
||||
|
||||
proc myOpenCached(module: PSym, filename: string, rd: PRodReader): PPassContext =
|
||||
var c: PContext
|
||||
c = PContext(myOpen(module, filename))
|
||||
var c = PContext(myOpen(module, filename))
|
||||
c.fromCache = true
|
||||
result = c
|
||||
|
||||
proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
var
|
||||
c: PContext
|
||||
a: PNode
|
||||
result = nil
|
||||
c = PContext(context)
|
||||
result = semStmt(c, n) # BUGFIX: process newly generated generics here, not at the end!
|
||||
var c = PContext(context)
|
||||
result = semStmt(c, n)
|
||||
# BUGFIX: process newly generated generics here, not at the end!
|
||||
if sonsLen(c.generics) > 0:
|
||||
a = newNodeI(nkStmtList, n.info)
|
||||
var a = newNodeI(nkStmtList, n.info)
|
||||
addCodeForGenerics(c, a)
|
||||
if sonsLen(a) > 0:
|
||||
# a generic has been added to `a`:
|
||||
@@ -198,8 +176,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
|
||||
result = a
|
||||
|
||||
proc myClose(context: PPassContext, n: PNode): PNode =
|
||||
var c: PContext
|
||||
c = PContext(context)
|
||||
var c = PContext(context)
|
||||
closeScope(c.tab) # close module's scope
|
||||
rawCloseScope(c.tab) # imported symbols; don't check for unused ones!
|
||||
if n == nil:
|
||||
|
||||
@@ -15,7 +15,8 @@ import
|
||||
magicsys, nversion, nimsets, pnimsyn, times, passes, rodread
|
||||
|
||||
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
|
||||
defaultCC*: TCallingConvention
|
||||
dynlib*: PLib
|
||||
@@ -46,15 +47,16 @@ type
|
||||
optionStack*: TLinkedList
|
||||
libs*: TLinkedList # all libs used by this module
|
||||
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
|
||||
filename*: string # the module's filename
|
||||
|
||||
|
||||
var gInstTypes*: TIdTable
|
||||
var gInstTypes*: TIdTable # map PType to PType
|
||||
|
||||
proc newContext*(module: PSym, nimfile: string): PContext
|
||||
# map PType to PType
|
||||
|
||||
proc newProcCon*(owner: PSym): PProcCon
|
||||
proc lastOptionEntry*(c: PContext): POptionEntry
|
||||
proc newOptionEntry*(): POptionEntry
|
||||
@@ -70,15 +72,15 @@ proc illFormedAst*(n: PNode)
|
||||
proc getSon*(n: PNode, indx: int): PNode
|
||||
proc checkSonsLen*(n: PNode, length: int)
|
||||
proc checkMinSonsLen*(n: PNode, length: int)
|
||||
# owner handling:
|
||||
|
||||
# owner handling:
|
||||
proc getCurrOwner*(): PSym
|
||||
proc PushOwner*(owner: PSym)
|
||||
proc PopOwner*()
|
||||
# implementation
|
||||
|
||||
var gOwners: seq[PSym]
|
||||
var gOwners: seq[PSym] = @[]
|
||||
|
||||
gOwners = @ []
|
||||
proc getCurrOwner(): PSym =
|
||||
# owner stack (used for initializing the
|
||||
# owner field of syms)
|
||||
@@ -88,14 +90,10 @@ proc getCurrOwner(): PSym =
|
||||
result = gOwners[high(gOwners)]
|
||||
|
||||
proc PushOwner(owner: PSym) =
|
||||
var length: int
|
||||
length = len(gOwners)
|
||||
setlen(gOwners, length + 1)
|
||||
gOwners[length] = owner
|
||||
add(gOwners, owner)
|
||||
|
||||
proc PopOwner() =
|
||||
var length: int
|
||||
length = len(gOwners)
|
||||
var length = len(gOwners)
|
||||
if (length <= 0): InternalError("popOwner")
|
||||
setlen(gOwners, length - 1)
|
||||
|
||||
@@ -128,8 +126,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
|
||||
IntSetInit(result.includedFiles)
|
||||
|
||||
proc addConverter(c: PContext, conv: PSym) =
|
||||
var L: int
|
||||
L = len(c.converters)
|
||||
var L = len(c.converters)
|
||||
for i in countup(0, L - 1):
|
||||
if c.converters[i].id == conv.id: return
|
||||
setlen(c.converters, L + 1)
|
||||
@@ -162,9 +159,9 @@ proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
|
||||
dest.owner = getCurrOwner()
|
||||
dest.size = - 1
|
||||
|
||||
proc makeRangeType(c: PContext, first, last: biggestInt, info: TLineInfo): PType =
|
||||
var n: PNode
|
||||
n = newNodeI(nkRange, info)
|
||||
proc makeRangeType(c: PContext, first, last: biggestInt,
|
||||
info: TLineInfo): PType =
|
||||
var n = newNodeI(nkRange, info)
|
||||
addSon(n, newIntNode(nkIntLit, first))
|
||||
addSon(n, newIntNode(nkIntLit, last))
|
||||
result = newTypeS(tyRange, c)
|
||||
@@ -187,4 +184,4 @@ proc checkSonsLen(n: PNode, length: int) =
|
||||
proc checkMinSonsLen(n: PNode, length: int) =
|
||||
if (n == nil) or (sonsLen(n) < length): illFormedAst(n)
|
||||
|
||||
initIdTable(gInstTypes)
|
||||
initIdTable(gInstTypes)
|
||||
|
||||
277
rod/semfold.nim
277
rod/semfold.nim
@@ -14,7 +14,7 @@ import
|
||||
strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times,
|
||||
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
|
||||
# expression
|
||||
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 newFloatNodeT*(floatVal: BiggestFloat, 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
|
||||
|
||||
proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode =
|
||||
@@ -46,35 +43,6 @@ proc newStrNodeT(strVal: string, n: PNode): PNode =
|
||||
result.typ = n.typ
|
||||
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 =
|
||||
var
|
||||
n: PNode
|
||||
@@ -93,56 +61,35 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
# b and c may be nil
|
||||
result = nil
|
||||
case m
|
||||
of mOrd:
|
||||
result = newIntNodeT(getOrdValue(a), n)
|
||||
of mChr:
|
||||
result = newIntNodeT(getInt(a), n)
|
||||
of mUnaryMinusI, mUnaryMinusI64:
|
||||
result = newIntNodeT(- getInt(a), n)
|
||||
of mUnaryMinusF64:
|
||||
result = newFloatNodeT(- getFloat(a), n)
|
||||
of mNot:
|
||||
result = newIntNodeT(1 - getInt(a), n)
|
||||
of mCard:
|
||||
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 mOrd: result = newIntNodeT(getOrdValue(a), n)
|
||||
of mChr: result = newIntNodeT(getInt(a), n)
|
||||
of mUnaryMinusI, mUnaryMinusI64: result = newIntNodeT(- getInt(a), n)
|
||||
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n)
|
||||
of mNot: result = newIntNodeT(1 - getInt(a), n)
|
||||
of mCard: 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:
|
||||
result = newFloatNodeT(toFloat(int(getInt(a))), n)
|
||||
of mToInt, mToBiggestInt:
|
||||
result = newIntNodeT(system.toInt(getFloat(a)), n)
|
||||
of mAbsF64:
|
||||
result = newFloatNodeT(abs(getFloat(a)), n)
|
||||
of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n)
|
||||
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n)
|
||||
of mAbsI, mAbsI64:
|
||||
if getInt(a) >= 0: result = a
|
||||
else: result = newIntNodeT(- getInt(a), n)
|
||||
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
|
||||
# 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)
|
||||
of mToU8:
|
||||
result = newIntNodeT(getInt(a) and 0x000000FF, n)
|
||||
of mToU16:
|
||||
result = newIntNodeT(getInt(a) and 0x0000FFFF, n)
|
||||
of mToU32:
|
||||
result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n)
|
||||
of mSucc:
|
||||
result = newIntNodeT(getOrdValue(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 mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n)
|
||||
of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n)
|
||||
of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n)
|
||||
of mSucc: result = newIntNodeT(getOrdValue(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:
|
||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), 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 tyInt64, tyInt: result = newIntNodeT(`shr`(getInt(a), getInt(b)), n)
|
||||
else: InternalError(n.info, "constant folding for shl")
|
||||
of mDivI, mDivI64:
|
||||
result = newIntNodeT(getInt(a) div getInt(b), n)
|
||||
of mModI, mModI64:
|
||||
result = newIntNodeT(getInt(a) mod getInt(b), n)
|
||||
of mAddF64:
|
||||
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 mDivI, mDivI64: result = newIntNodeT(getInt(a) div getInt(b), n)
|
||||
of mModI, mModI64: result = newIntNodeT(getInt(a) mod getInt(b), n)
|
||||
of mAddF64: 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:
|
||||
if getFloat(b) == 0.0:
|
||||
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:
|
||||
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n)
|
||||
else: result = newFloatNodeT(getFloat(a), n)
|
||||
of mIsNil:
|
||||
result = newIntNodeT(ord(a.kind == nkNilLit), n)
|
||||
of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n)
|
||||
of mLtI, mLtI64, mLtB, mLtEnum, mLtCh:
|
||||
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n)
|
||||
of mLeI, mLeI64, mLeB, mLeEnum, mLeCh:
|
||||
result = newIntNodeT(ord(getOrdValue(a) <= getOrdValue(b)), n)
|
||||
of mEqI, mEqI64, mEqB, mEqEnum, mEqCh:
|
||||
result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n) # operators for floats
|
||||
of mLtF64:
|
||||
result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n)
|
||||
of mLeF64:
|
||||
result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n)
|
||||
of mEqF64:
|
||||
result = newIntNodeT(ord(getFloat(a) == getFloat(b)), n) # operators for strings
|
||||
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)
|
||||
result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n)
|
||||
of mLtF64: result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n)
|
||||
of mLeF64: result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n)
|
||||
of mEqF64: result = newIntNodeT(ord(getFloat(a) == getFloat(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:
|
||||
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n)
|
||||
of mLeU, mLeU64:
|
||||
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n)
|
||||
of mBitandI, mBitandI64, mAnd:
|
||||
result = newIntNodeT(getInt(a) and getInt(b), n)
|
||||
of mBitorI, mBitorI64, mOr:
|
||||
result = newIntNodeT(getInt(a) or getInt(b), n)
|
||||
of mBitxorI, mBitxorI64, mXor:
|
||||
result = newIntNodeT(getInt(a) xor getInt(b), n)
|
||||
of mAddU, mAddU64:
|
||||
result = newIntNodeT(`+%`(getInt(a), getInt(b)), n)
|
||||
of mSubU, mSubU64:
|
||||
result = newIntNodeT(`-%`(getInt(a), getInt(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 mBitandI, mBitandI64, mAnd: result = newIntNodeT(getInt(a) and getInt(b), n)
|
||||
of mBitorI, mBitorI64, mOr: result = newIntNodeT(getInt(a) or getInt(b), n)
|
||||
of mBitxorI, mBitxorI64, mXor: result = newIntNodeT(getInt(a) xor getInt(b), n)
|
||||
of mAddU, mAddU64: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n)
|
||||
of mSubU, mSubU64: result = newIntNodeT(`-%`(getInt(a), getInt(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:
|
||||
result = newIntNodeT(Ord(containsSets(a, b) and not equalSets(a, b)), n)
|
||||
of mMulSet:
|
||||
@@ -243,32 +168,24 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
of mSymDiffSet:
|
||||
result = nimsets.symdiffSets(a, b)
|
||||
result.info = n.info
|
||||
of mConStrStr:
|
||||
result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n)
|
||||
of mInSet:
|
||||
result = newIntNodeT(Ord(inSet(a, b)), n)
|
||||
of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n)
|
||||
of mInSet: result = newIntNodeT(Ord(inSet(a, b)), n)
|
||||
of mRepr:
|
||||
# BUGFIX: we cannot eval mRepr here. But this means that it is not
|
||||
# available for interpretation. I don't know how to fix this.
|
||||
#result := newStrNodeT(renderTree(a, {@set}[renderNoComments]), n);
|
||||
of mIntToStr, mInt64ToStr:
|
||||
result = newStrNodeT($(getOrdValue(a)), n)
|
||||
of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n)
|
||||
of mBoolToStr:
|
||||
if getOrdValue(a) == 0: result = newStrNodeT("false", n)
|
||||
else: result = newStrNodeT("true", n)
|
||||
of mCopyStr:
|
||||
result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)) + 0), n)
|
||||
of mCopyStr: result = newStrNodeT(copy(getStr(a), int(getOrdValue(b))), n)
|
||||
of mCopyStrLast:
|
||||
result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)) + 0,
|
||||
int(getOrdValue(c)) + 0), n)
|
||||
of mFloatToStr:
|
||||
result = newStrNodeT($(getFloat(a)), n)
|
||||
of mCStrToStr, mCharToStr:
|
||||
result = newStrNodeT(getStrOrChar(a), n)
|
||||
of mStrToStr:
|
||||
result = a
|
||||
of mEnumToStr:
|
||||
result = newStrNodeT(enumValToString(a), n)
|
||||
result = newStrNodeT(copy(getStr(a), int(getOrdValue(b)),
|
||||
int(getOrdValue(c))), n)
|
||||
of mFloatToStr: result = newStrNodeT($(getFloat(a)), n)
|
||||
of mCStrToStr, mCharToStr: result = newStrNodeT(getStrOrChar(a), n)
|
||||
of mStrToStr: result = a
|
||||
of mEnumToStr: result = newStrNodeT(enumValToString(a), n)
|
||||
of mArrToSeq:
|
||||
result = copyTree(a)
|
||||
result.typ = n.typ
|
||||
@@ -278,15 +195,13 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
else: InternalError(a.info, "evalOp(" & $m & ')')
|
||||
|
||||
proc getConstIfExpr(c: PSym, n: PNode): PNode =
|
||||
var it, e: PNode
|
||||
result = nil
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
it = n.sons[i]
|
||||
var it = n.sons[i]
|
||||
case it.kind
|
||||
of nkElifExpr:
|
||||
e = getConstExpr(c, it.sons[0])
|
||||
if e == nil:
|
||||
return nil
|
||||
var e = getConstExpr(c, it.sons[0])
|
||||
if e == nil: return nil
|
||||
if getOrdValue(e) != 0:
|
||||
if result == nil:
|
||||
result = getConstExpr(c, it.sons[1])
|
||||
@@ -297,10 +212,9 @@ proc getConstIfExpr(c: PSym, n: PNode): PNode =
|
||||
|
||||
proc partialAndExpr(c: PSym, n: PNode): PNode =
|
||||
# partial evaluation
|
||||
var a, b: PNode
|
||||
result = n
|
||||
a = getConstExpr(c, n.sons[1])
|
||||
b = getConstExpr(c, n.sons[2])
|
||||
var a = getConstExpr(c, n.sons[1])
|
||||
var b = getConstExpr(c, n.sons[2])
|
||||
if a != nil:
|
||||
if getInt(a) == 0: result = a
|
||||
elif b != nil: result = b
|
||||
@@ -311,10 +225,9 @@ proc partialAndExpr(c: PSym, n: PNode): PNode =
|
||||
|
||||
proc partialOrExpr(c: PSym, n: PNode): PNode =
|
||||
# partial evaluation
|
||||
var a, b: PNode
|
||||
result = n
|
||||
a = getConstExpr(c, n.sons[1])
|
||||
b = getConstExpr(c, n.sons[2])
|
||||
var a = getConstExpr(c, n.sons[1])
|
||||
var b = getConstExpr(c, n.sons[2])
|
||||
if a != nil:
|
||||
if getInt(a) != 0: result = a
|
||||
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")
|
||||
|
||||
proc getConstExpr(module: PSym, n: PNode): PNode =
|
||||
var
|
||||
s: PSym
|
||||
a, b, c: PNode
|
||||
proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result = nil
|
||||
case n.kind
|
||||
of nkSym:
|
||||
s = n.sym
|
||||
var s = n.sym
|
||||
if s.kind == skEnumField:
|
||||
result = newIntNodeT(s.position, n)
|
||||
elif (s.kind == skConst):
|
||||
case s.magic
|
||||
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in module.flags),
|
||||
n)
|
||||
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
|
||||
of mCompileDate: result = newStrNodeT(times.getDateStr(), n)
|
||||
of mCompileTime: result = newStrNodeT(times.getClockStr(), 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 mInf: result = newFloatNodeT(Inf, n)
|
||||
of mNegInf: result = newFloatNodeT(NegInf, n)
|
||||
else:
|
||||
result = copyTree(s.ast) # BUGFIX
|
||||
else: result = copyTree(s.ast)
|
||||
elif s.kind in {skProc, skMethod}: # BUGFIX
|
||||
result = n
|
||||
of nkCharLit..nkNilLit:
|
||||
result = copyNode(n)
|
||||
of nkIfExpr:
|
||||
result = getConstIfExpr(module, n)
|
||||
result = getConstIfExpr(m, n)
|
||||
of nkCall, nkCommand, nkCallStrLit:
|
||||
if (n.sons[0].kind != nkSym): return
|
||||
s = n.sons[0].sym
|
||||
var s = n.sons[0].sym
|
||||
if (s.kind != skProc): return
|
||||
try:
|
||||
case s.magic
|
||||
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:
|
||||
a = n.sons[1]
|
||||
var a = n.sons[1]
|
||||
if computeSize(a.typ) < 0:
|
||||
liMessage(a.info, errCannotEvalXBecauseIncompletelyDefined, "sizeof")
|
||||
if a.typ.kind in {tyArray, tyObject, tyTuple}:
|
||||
result = nil # XXX: size computation for complex types
|
||||
# is still wrong
|
||||
result = nil
|
||||
# XXX: size computation for complex types is still wrong
|
||||
else:
|
||||
result = newIntNodeT(getSize(a.typ), n)
|
||||
of mLow:
|
||||
@@ -396,13 +304,14 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
|
||||
{tyOpenArray, tySequence, tyString}):
|
||||
result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)), n)
|
||||
else:
|
||||
a = getConstExpr(module, n.sons[1])
|
||||
var a = getConstExpr(m, n.sons[1])
|
||||
var b, c: PNode
|
||||
if a == nil: return
|
||||
if sonsLen(n) > 2:
|
||||
b = getConstExpr(module, n.sons[2])
|
||||
b = getConstExpr(m, n.sons[2])
|
||||
if b == nil: return
|
||||
if sonsLen(n) > 3:
|
||||
c = getConstExpr(module, n.sons[3])
|
||||
c = getConstExpr(m, n.sons[3])
|
||||
if c == nil: return
|
||||
else:
|
||||
b = nil
|
||||
@@ -412,22 +321,21 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
|
||||
except EDivByZero:
|
||||
liMessage(n.info, errConstantDivisionByZero)
|
||||
of nkAddr:
|
||||
a = getConstExpr(module, n.sons[0])
|
||||
var a = getConstExpr(m, n.sons[0])
|
||||
if a != nil:
|
||||
result = n
|
||||
n.sons[0] = a
|
||||
of nkBracket:
|
||||
result = copyTree(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = getConstExpr(module, n.sons[i])
|
||||
if a == nil:
|
||||
return nil
|
||||
var a = getConstExpr(m, n.sons[i])
|
||||
if a == nil: return nil
|
||||
result.sons[i] = a
|
||||
incl(result.flags, nfAllConst)
|
||||
of nkRange:
|
||||
a = getConstExpr(module, n.sons[0])
|
||||
var a = getConstExpr(m, n.sons[0])
|
||||
if a == nil: return
|
||||
b = getConstExpr(module, n.sons[1])
|
||||
var b = getConstExpr(m, n.sons[1])
|
||||
if b == nil: return
|
||||
result = copyNode(n)
|
||||
addSon(result, a)
|
||||
@@ -435,9 +343,8 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
|
||||
of nkCurly:
|
||||
result = copyTree(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = getConstExpr(module, n.sons[i])
|
||||
if a == nil:
|
||||
return nil
|
||||
var a = getConstExpr(m, n.sons[i])
|
||||
if a == nil: return nil
|
||||
result.sons[i] = a
|
||||
incl(result.flags, nfAllConst)
|
||||
of nkPar:
|
||||
@@ -445,19 +352,17 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
|
||||
result = copyTree(n)
|
||||
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = getConstExpr(module, n.sons[i].sons[1])
|
||||
if a == nil:
|
||||
return nil
|
||||
var a = getConstExpr(m, n.sons[i].sons[1])
|
||||
if a == nil: return nil
|
||||
result.sons[i].sons[1] = a
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = getConstExpr(module, n.sons[i])
|
||||
if a == nil:
|
||||
return nil
|
||||
var a = getConstExpr(m, n.sons[i])
|
||||
if a == nil: return nil
|
||||
result.sons[i] = a
|
||||
incl(result.flags, nfAllConst)
|
||||
of nkChckRangeF, nkChckRange64, nkChckRange:
|
||||
a = getConstExpr(module, n.sons[0])
|
||||
var a = getConstExpr(m, n.sons[0])
|
||||
if a == nil: return
|
||||
if leValueConv(n.sons[1], a) and leValueConv(a, n.sons[2]):
|
||||
result = a # a <= x and x <= b
|
||||
@@ -467,12 +372,12 @@ proc getConstExpr(module: PSym, n: PNode): PNode =
|
||||
msgKindToString(errIllegalConvFromXtoY),
|
||||
[typeToString(n.sons[0].typ), typeToString(n.typ)]))
|
||||
of nkStringToCString, nkCStringToString:
|
||||
a = getConstExpr(module, n.sons[0])
|
||||
var a = getConstExpr(m, n.sons[0])
|
||||
if a == nil: return
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast:
|
||||
a = getConstExpr(module, n.sons[1])
|
||||
var a = getConstExpr(m, n.sons[1])
|
||||
if a == nil: return
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt..tyInt64:
|
||||
|
||||
179
rod/transf.nim
179
rod/transf.nim
@@ -118,11 +118,9 @@ proc newAsgnStmt(c: PTransf, le, ri: PNode): PNode =
|
||||
addSon(result, ri)
|
||||
|
||||
proc transformSym(c: PTransf, n: PNode): PNode =
|
||||
var
|
||||
tc: PTransCon
|
||||
b: PNode
|
||||
var b: PNode
|
||||
if (n.kind != nkSym): internalError(n.info, "transformSym")
|
||||
tc = c.transCon
|
||||
var tc = c.transCon
|
||||
if sfBorrow in n.sym.flags:
|
||||
# simply exchange the symbol:
|
||||
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 =
|
||||
# we transform the continue statement into a block statement
|
||||
var
|
||||
counter: int
|
||||
x: PNode
|
||||
labl: PSym
|
||||
result = n
|
||||
for i in countup(0, sonsLen(n) - 1): result.sons[i] = transform(c, n.sons[i])
|
||||
counter = 0
|
||||
labl = newSym(skLabel, nil, getCurrOwner(c))
|
||||
var counter = 0
|
||||
var labl = newSym(skLabel, nil, getCurrOwner(c))
|
||||
labl.name = getIdent(genPrefix & $(labl.id))
|
||||
labl.info = result.info
|
||||
transformContinueAux(c, result, labl, counter)
|
||||
if counter > 0:
|
||||
x = newNodeI(nkBlockStmt, result.info)
|
||||
var x = newNodeI(nkBlockStmt, result.info)
|
||||
addSon(x, newSymNode(labl))
|
||||
addSon(x, result)
|
||||
result = x
|
||||
@@ -189,10 +183,9 @@ proc skipConv(n: PNode): PNode =
|
||||
else: result = n
|
||||
|
||||
proc newTupleAccess(tup: PNode, i: int): PNode =
|
||||
var lit: PNode
|
||||
result = newNodeIT(nkBracketExpr, tup.info, tup.typ.sons[i])
|
||||
addSon(result, copyTree(tup))
|
||||
lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
|
||||
var lit = newNodeIT(nkIntLit, tup.info, getSysType(tyInt))
|
||||
lit.intVal = i
|
||||
addSon(result, lit)
|
||||
|
||||
@@ -203,9 +196,8 @@ proc unpackTuple(c: PTransf, n, father: PNode) =
|
||||
transform(c, newTupleAccess(n, i))))
|
||||
|
||||
proc transformYield(c: PTransf, n: PNode): PNode =
|
||||
var e: PNode
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
e = n.sons[0]
|
||||
var e = n.sons[0]
|
||||
if skipTypes(e.typ, {tyGenericInst}).kind == tyTuple:
|
||||
e = skipConv(e)
|
||||
if e.kind == nkPar:
|
||||
@@ -220,10 +212,6 @@ proc transformYield(c: PTransf, n: PNode): PNode =
|
||||
addSon(result, transform(c, lastSon(c.transCon.forStmt)))
|
||||
|
||||
proc inlineIter(c: PTransf, n: PNode): PNode =
|
||||
var
|
||||
L: int
|
||||
it: PNode
|
||||
newVar: PSym
|
||||
result = n
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
@@ -234,13 +222,14 @@ proc inlineIter(c: PTransf, n: PNode): PNode =
|
||||
of nkVarSection:
|
||||
result = copyTree(n)
|
||||
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 == nkIdentDefs:
|
||||
if (it.sons[0].kind != nkSym): InternalError(it.info, "inlineIter")
|
||||
newVar = copySym(it.sons[0].sym)
|
||||
incl(newVar.flags, sfFromGeneric) # fixes a strange bug for rodgen:
|
||||
#include(it.sons[0].sym.flags, sfFromGeneric);
|
||||
var newVar = copySym(it.sons[0].sym)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
# fixes a strange bug for rodgen:
|
||||
#include(it.sons[0].sym.flags, sfFromGeneric);
|
||||
newVar.owner = getCurrOwner(c)
|
||||
IdNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
|
||||
it.sons[0] = newSymNode(newVar)
|
||||
@@ -248,9 +237,9 @@ proc inlineIter(c: PTransf, n: PNode): PNode =
|
||||
else:
|
||||
if it.kind != nkVarTuple:
|
||||
InternalError(it.info, "inlineIter: not nkVarTuple")
|
||||
L = sonsLen(it)
|
||||
var L = sonsLen(it)
|
||||
for j in countup(0, L - 3):
|
||||
newVar = copySym(it.sons[j].sym)
|
||||
var newVar = copySym(it.sons[j].sym)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
newVar.owner = getCurrOwner(c)
|
||||
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)
|
||||
|
||||
proc addVar(father, v: PNode) =
|
||||
var vpart: PNode
|
||||
vpart = newNodeI(nkIdentDefs, v.info)
|
||||
var vpart = newNodeI(nkIdentDefs, v.info)
|
||||
addSon(vpart, v)
|
||||
addSon(vpart, nil)
|
||||
addSon(vpart, nil)
|
||||
addSon(father, vpart)
|
||||
|
||||
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
|
||||
var m: PNode
|
||||
case n.sons[0].kind
|
||||
of nkObjUpConv, nkObjDownConv, nkPassAsOpenArray, nkChckRange, nkChckRangeF,
|
||||
nkChckRange64:
|
||||
m = n.sons[0].sons[0]
|
||||
var m = n.sons[0].sons[0]
|
||||
if (m.kind == a) or (m.kind == b):
|
||||
# addr ( nkPassAsOpenArray ( deref ( x ) ) ) --> nkPassAsOpenArray(x)
|
||||
n.sons[0].sons[0] = m.sons[0]
|
||||
return transform(c, n.sons[0])
|
||||
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):
|
||||
# addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
|
||||
n.sons[0].sons[1] = m.sons[0]
|
||||
@@ -294,13 +281,10 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
|
||||
result = n
|
||||
|
||||
proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
var
|
||||
source, dest: PType
|
||||
diff: int
|
||||
n.sons[1] = transform(c, n.sons[1])
|
||||
result = n # numeric types need range checks:
|
||||
dest = skipTypes(n.typ, abstractVarRange)
|
||||
source = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
var dest = skipTypes(n.typ, abstractVarRange)
|
||||
var source = skipTypes(n.sons[1].typ, abstractVarRange)
|
||||
case dest.kind
|
||||
of tyInt..tyInt64, tyEnum, tyChar, tyBool:
|
||||
if (firstOrd(dest) <= firstOrd(source)) and
|
||||
@@ -340,7 +324,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
dest = skipTypes(dest, abstractPtrs)
|
||||
source = skipTypes(source, abstractPtrs)
|
||||
if source.kind == tyObject:
|
||||
diff = inheritanceDiff(dest, source)
|
||||
var diff = inheritanceDiff(dest, source)
|
||||
if diff < 0:
|
||||
result = newNodeIT(nkObjUpConv, n.info, n.typ)
|
||||
addSon(result, n.sons[1])
|
||||
@@ -350,7 +334,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
else:
|
||||
result = n.sons[1]
|
||||
of tyObject:
|
||||
diff = inheritanceDiff(dest, source)
|
||||
var diff = inheritanceDiff(dest, source)
|
||||
if diff < 0:
|
||||
result = newNodeIT(nkObjUpConv, n.info, n.typ)
|
||||
addSon(result, n.sons[1])
|
||||
@@ -360,7 +344,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
else:
|
||||
result = n.sons[1]
|
||||
of tyGenericParam, tyOrdinal:
|
||||
result = n.sons[1] # happens sometimes for generated assignments, etc.
|
||||
result = n.sons[1] # happens sometimes for generated assignments, etc.
|
||||
else:
|
||||
nil
|
||||
|
||||
@@ -393,45 +377,42 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto =
|
||||
proc transformFor(c: PTransf, n: PNode): PNode =
|
||||
# generate access statements for the parameters (unless they are constant)
|
||||
# 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")
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
length = sonsLen(n)
|
||||
var length = sonsLen(n)
|
||||
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):
|
||||
addVar(v, copyTree(n.sons[i])) # declare new vars
|
||||
addSon(result, v)
|
||||
newC = newTransCon()
|
||||
call = n.sons[length - 2]
|
||||
var newC = newTransCon()
|
||||
var call = n.sons[length - 2]
|
||||
if (call.kind != nkCall) or (call.sons[0].kind != nkSym):
|
||||
InternalError(call.info, "transformFor")
|
||||
newC.owner = call.sons[0].sym
|
||||
newC.forStmt = n
|
||||
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)
|
||||
for i in countup(1, sonsLen(call) - 1):
|
||||
arg = skipPassAsOpenArray(transform(c, call.sons[i]))
|
||||
formal = skipTypes(newC.owner.typ, abstractInst).n.sons[i].sym #if IdentEq(newc.Owner.name, 'items') then
|
||||
# liMessage(arg.info, warnUser, 'items: ' + nodeKindToStr[arg.kind]);
|
||||
var arg = skipPassAsOpenArray(transform(c, call.sons[i]))
|
||||
var formal = skipTypes(newC.owner.typ, abstractInst).n.sons[i].sym
|
||||
#if IdentEq(newc.Owner.name, 'items') then
|
||||
# liMessage(arg.info, warnUser, 'items: ' + nodeKindToStr[arg.kind]);
|
||||
case putArgInto(arg, formal.typ)
|
||||
of paDirectMapping:
|
||||
IdNodeTablePut(newC.mapping, formal, arg)
|
||||
of paFastAsgn:
|
||||
# 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))
|
||||
addSon(result, newAsgnStmt(c, newSymNode(temp), arg))
|
||||
IdNodeTablePut(newC.mapping, formal, newSymNode(temp))
|
||||
of paVarAsgn:
|
||||
assert(skipTypes(formal.typ, abstractInst).kind == tyVar)
|
||||
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)
|
||||
addSon(result, inlineIter(c, body))
|
||||
popInfoContext()
|
||||
@@ -447,14 +428,11 @@ proc getMagicOp(call: PNode): TMagic =
|
||||
proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
|
||||
container: PNode) =
|
||||
# gather used vars for closure generation
|
||||
var
|
||||
s: PSym
|
||||
found: bool
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkSym:
|
||||
s = n.sym
|
||||
found = false
|
||||
var s = n.sym
|
||||
var found = false
|
||||
case s.kind
|
||||
of skVar: found = not (sfGlobal in s.flags)
|
||||
of skTemp, skForVar, skParam: found = true
|
||||
@@ -476,10 +454,9 @@ proc addFormalParam(routine: PSym, param: PSym) =
|
||||
|
||||
proc indirectAccess(a, b: PSym): PNode =
|
||||
# returns a^ .b as a node
|
||||
var x, y, deref: PNode
|
||||
x = newSymNode(a)
|
||||
y = newSymNode(b)
|
||||
deref = newNodeI(nkDerefExpr, x.info)
|
||||
var x = newSymNode(a)
|
||||
var y = newSymNode(b)
|
||||
var deref = newNodeI(nkDerefExpr, x.info)
|
||||
deref.typ = x.typ.sons[0]
|
||||
addSon(deref, x)
|
||||
result = newNodeI(nkDotExpr, x.info)
|
||||
@@ -488,29 +465,26 @@ proc indirectAccess(a, b: PSym): PNode =
|
||||
result.typ = y.typ
|
||||
|
||||
proc transformLambda(c: PTransf, n: PNode): PNode =
|
||||
var
|
||||
marked: TIntSet
|
||||
closure: PNode
|
||||
s, param: PSym
|
||||
cl, p: PType
|
||||
newC: PTransCon
|
||||
var marked: TIntSet
|
||||
result = n
|
||||
IntSetInit(marked)
|
||||
if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda")
|
||||
s = n.sons[namePos].sym
|
||||
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!):
|
||||
cl = newType(tyObject, s)
|
||||
var s = n.sons[namePos].sym
|
||||
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!):
|
||||
var cl = newType(tyObject, s)
|
||||
cl.n = closure
|
||||
addSon(cl, nil) # no super class
|
||||
p = newType(tyRef, s)
|
||||
var p = newType(tyRef, s)
|
||||
addSon(p, cl)
|
||||
param = newSym(skParam, getIdent(genPrefix & "Cl"), s)
|
||||
var param = newSym(skParam, getIdent(genPrefix & "Cl"), s)
|
||||
param.typ = p
|
||||
addFormalParam(s, param) # all variables that are accessed should be accessed by the new closure
|
||||
# parameter:
|
||||
addFormalParam(s, param)
|
||||
# all variables that are accessed should be accessed by the new closure
|
||||
# parameter:
|
||||
if sonsLen(closure) > 0:
|
||||
newC = newTransCon()
|
||||
var newC = newTransCon()
|
||||
for i in countup(0, sonsLen(closure) - 1):
|
||||
IdNodeTablePut(newC.mapping, 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 =
|
||||
# removes `elif` branches of a case stmt
|
||||
# adds ``else: nil`` if needed for the code generator
|
||||
var
|
||||
length, i: int
|
||||
ifs, elsen: PNode
|
||||
length = sonsLen(n)
|
||||
i = length - 1
|
||||
var length = sonsLen(n)
|
||||
var i = length - 1
|
||||
if n.sons[i].kind == nkElse: dec(i)
|
||||
if n.sons[i].kind == nkElifBranch:
|
||||
while n.sons[i].kind == nkElifBranch: dec(i)
|
||||
if (n.sons[i].kind != nkOfBranch):
|
||||
InternalError(n.sons[i].info, "transformCase")
|
||||
ifs = newNodeI(nkIfStmt, n.sons[i + 1].info)
|
||||
elsen = newNodeI(nkElse, ifs.info)
|
||||
var ifs = newNodeI(nkIfStmt, n.sons[i + 1].info)
|
||||
var elsen = newNodeI(nkElse, ifs.info)
|
||||
for j in countup(i + 1, length - 1): addSon(ifs, n.sons[j])
|
||||
setlen(n.sons, i + 2)
|
||||
addSon(elsen, ifs)
|
||||
@@ -541,7 +512,7 @@ proc transformCase(c: PTransf, n: PNode): PNode =
|
||||
not (skipTypes(n.sons[0].Typ, abstractVarRange).Kind in
|
||||
{tyInt..tyInt64, tyChar, tyEnum}):
|
||||
#MessageOut(renderTree(n));
|
||||
elsen = newNodeI(nkElse, n.info)
|
||||
var elsen = newNodeI(nkElse, n.info)
|
||||
addSon(elsen, newNodeI(nkNilLit, n.info))
|
||||
addSon(n, elsen)
|
||||
result = n
|
||||
@@ -566,20 +537,15 @@ proc getMergeOp(n: PNode): PSym =
|
||||
nil
|
||||
|
||||
proc flattenTreeAux(d, a: PNode, op: PSym) =
|
||||
var op2: PSym
|
||||
op2 = getMergeOp(a)
|
||||
var op2 = getMergeOp(a)
|
||||
if (op2 != nil) and
|
||||
((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)): # a is a
|
||||
# "leaf", so
|
||||
# add
|
||||
# it:
|
||||
((op2.id == op.id) or (op.magic != mNone) and (op2.magic == op.magic)):
|
||||
for i in countup(1, sonsLen(a) - 1): flattenTreeAux(d, a.sons[i], op)
|
||||
else:
|
||||
addSon(d, copyTree(a))
|
||||
|
||||
proc flattenTree(root: PNode): PNode =
|
||||
var op: PSym
|
||||
op = getMergeOp(root)
|
||||
var op = getMergeOp(root)
|
||||
if op != nil:
|
||||
result = copyNode(root)
|
||||
addSon(result, copyTree(root.sons[0]))
|
||||
@@ -588,21 +554,17 @@ proc flattenTree(root: PNode): PNode =
|
||||
result = root
|
||||
|
||||
proc transformCall(c: PTransf, n: PNode): PNode =
|
||||
var
|
||||
j: int
|
||||
m, a: PNode
|
||||
op: PSym
|
||||
result = flattenTree(n)
|
||||
for i in countup(0, sonsLen(result) - 1):
|
||||
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):
|
||||
m = result
|
||||
var m = result
|
||||
result = newNodeIT(nkCall, m.info, m.typ)
|
||||
addSon(result, copyTree(m.sons[0]))
|
||||
j = 1
|
||||
var j = 1
|
||||
while j < sonsLen(m):
|
||||
a = m.sons[j]
|
||||
var a = m.sons[j]
|
||||
inc(j)
|
||||
if isConstExpr(a):
|
||||
while (j < sonsLen(m)) and isConstExpr(m.sons[j]):
|
||||
@@ -616,11 +578,8 @@ proc transformCall(c: PTransf, n: PNode): PNode =
|
||||
result = methodCall(result)
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode =
|
||||
var cnst: PNode
|
||||
result = n
|
||||
if n == nil:
|
||||
return #if ToLinenumber(n.info) = 32 then
|
||||
# MessageOut(RenderTree(n));
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkSym:
|
||||
return transformSym(c, n)
|
||||
@@ -657,16 +616,16 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
of nkCommentStmt, nkTemplateDef:
|
||||
return
|
||||
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:
|
||||
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:
|
||||
result = cnst # do not miss an optimization
|
||||
|
||||
proc processTransf(context: PPassContext, n: PNode): PNode =
|
||||
var c: PTransf
|
||||
c = PTransf(context)
|
||||
var c = PTransf(context)
|
||||
result = transform(c, n)
|
||||
|
||||
proc openTransf(module: PSym, filename: string): PPassContext =
|
||||
@@ -680,4 +639,4 @@ proc transfPass(): TPass =
|
||||
result.open = openTransf
|
||||
result.process = processTransf
|
||||
result.close = processTransf # we need to process generics too!
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import
|
||||
ast, astalgo, scanner, msgs, strutils
|
||||
|
||||
proc getMagic*(op: PNode): TMagic
|
||||
# function getConstExpr(const t: TNode; out res: TNode): Boolean;
|
||||
|
||||
proc isConstExpr*(n: PNode): bool
|
||||
proc flattenTree*(root: PNode, op: TMagic): PNode
|
||||
proc TreeToSym*(t: PNode): PSym
|
||||
@@ -32,12 +32,11 @@ proc hasSon(father, son: PNode): bool =
|
||||
result = false
|
||||
|
||||
proc cyclicTreeAux(n, s: PNode): bool =
|
||||
var m: int
|
||||
if n == nil:
|
||||
return false
|
||||
if hasSon(s, n):
|
||||
return true
|
||||
m = sonsLen(s)
|
||||
var m = sonsLen(s)
|
||||
addSon(s, n)
|
||||
if not (n.kind in {nkEmpty..nkNilLit}):
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
@@ -47,8 +46,7 @@ proc cyclicTreeAux(n, s: PNode): bool =
|
||||
delSon(s, m)
|
||||
|
||||
proc cyclicTree(n: PNode): bool =
|
||||
var s: PNode
|
||||
s = newNodeI(nkEmpty, n.info)
|
||||
var s = newNodeI(nkEmpty, n.info)
|
||||
result = cyclicTreeAux(n, s)
|
||||
|
||||
proc ExprStructuralEquivalent(a, b: PNode): bool =
|
||||
@@ -57,18 +55,14 @@ proc ExprStructuralEquivalent(a, b: PNode): bool =
|
||||
result = true
|
||||
elif (a != nil) and (b != nil) and (a.kind == b.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
|
||||
of nkIdent:
|
||||
result = a.ident.id == b.ident.id
|
||||
of nkCharLit..nkInt64Lit:
|
||||
result = a.intVal == b.intVal
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
result = a.strVal == b.strVal
|
||||
of nkEmpty, nkNilLit, nkType:
|
||||
result = true
|
||||
of nkIdent: result = a.ident.id == b.ident.id
|
||||
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
|
||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||
of nkEmpty, nkNilLit, nkType: result = true
|
||||
else:
|
||||
if sonsLen(a) == sonsLen(b):
|
||||
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:
|
||||
return #if a.info.fileIndex <> b.info.fileIndex then exit;
|
||||
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
|
||||
of nkIdent:
|
||||
result = a.ident.id == b.ident.id
|
||||
of nkCharLit..nkInt64Lit:
|
||||
result = a.intVal == b.intVal
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
result = a.strVal == b.strVal
|
||||
of nkEmpty, nkNilLit, nkType:
|
||||
result = true
|
||||
of nkIdent: result = a.ident.id == b.ident.id
|
||||
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
|
||||
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
|
||||
of nkEmpty, nkNilLit, nkType: result = true
|
||||
else:
|
||||
if sonsLen(a) == sonsLen(b):
|
||||
for i in countup(0, sonsLen(a) - 1):
|
||||
@@ -118,8 +108,7 @@ proc getMagic(op: PNode): TMagic =
|
||||
case op.kind
|
||||
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit:
|
||||
case op.sons[0].Kind
|
||||
of nkSym:
|
||||
result = op.sons[0].sym.magic
|
||||
of nkSym: result = op.sons[0].sym.magic
|
||||
else: result = mNone
|
||||
else: result = mNone
|
||||
|
||||
@@ -146,7 +135,6 @@ proc flattenTree(root: PNode, op: TMagic): PNode =
|
||||
flattenTreeAux(result, root, op)
|
||||
|
||||
proc SwapOperands(op: PNode) =
|
||||
var tmp: PNode
|
||||
tmp = op.sons[1]
|
||||
var tmp = op.sons[1]
|
||||
op.sons[1] = op.sons[2]
|
||||
op.sons[2] = tmp
|
||||
|
||||
Reference in New Issue
Block a user