mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 18:32:11 +00:00
refactorings for the eval engine; bugfix: clean templates as accessors
This commit is contained in:
@@ -211,7 +211,7 @@ type
|
||||
nkClosure, # (prc, env)-pair (internally used for code gen)
|
||||
nkGotoState, # used for the state machine (for iterators)
|
||||
nkState, # give a label to a code section (for iterators)
|
||||
nkBreakState # special break statement for easier code generation
|
||||
nkBreakState, # special break statement for easier code generation
|
||||
TNodeKinds* = set[TNodeKind]
|
||||
|
||||
type
|
||||
@@ -534,7 +534,6 @@ type
|
||||
when defined(useNodeIds):
|
||||
id*: int
|
||||
typ*: PType
|
||||
comment*: string
|
||||
info*: TLineInfo
|
||||
flags*: TNodeFlags
|
||||
case Kind*: TNodeKind
|
||||
@@ -548,8 +547,9 @@ type
|
||||
sym*: PSym
|
||||
of nkIdent:
|
||||
ident*: PIdent
|
||||
else:
|
||||
else:
|
||||
sons*: TNodeSeq
|
||||
comment*: string
|
||||
|
||||
TSymSeq* = seq[PSym]
|
||||
TStrTable* = object # a table[PIdent] of PSym
|
||||
@@ -667,7 +667,7 @@ type
|
||||
# for modules, an unique index corresponding
|
||||
# to the module's fileIdx
|
||||
# for variables a slot index for the evaluator
|
||||
|
||||
# for routines a superop-ID
|
||||
offset*: int # offset of record field
|
||||
loc*: TLoc
|
||||
annex*: PLib # additional fields (seldom used, so we use a
|
||||
@@ -778,10 +778,10 @@ const
|
||||
genericParamsPos* = 2
|
||||
paramsPos* = 3
|
||||
pragmasPos* = 4
|
||||
exceptionPos* = 5 # will be used for exception tracking
|
||||
optimizedCodePos* = 5 # will be used for exception tracking
|
||||
bodyPos* = 6 # position of body; use rodread.getBody() instead!
|
||||
resultPos* = 7
|
||||
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
|
||||
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 7!
|
||||
|
||||
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
||||
nkCommand, nkCallStrLit, nkHiddenCallConv}
|
||||
|
||||
@@ -59,6 +59,7 @@ proc InitDefines*() =
|
||||
DefineSymbol("nimmixin")
|
||||
DefineSymbol("nimeffects")
|
||||
DefineSymbol("nimbabel")
|
||||
DefineSymbol("nimsuperops")
|
||||
|
||||
# add platform specific symbols:
|
||||
case targetCPU
|
||||
|
||||
@@ -110,13 +110,18 @@ proc stackTraceAux(x: PStackFrame) =
|
||||
add(s, x.prc.name.s)
|
||||
MsgWriteln(s)
|
||||
|
||||
proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") =
|
||||
proc stackTrace(c: PEvalContext, info: TLineInfo, msg: TMsgKind, arg = "") =
|
||||
MsgWriteln("stack trace: (most recent call last)")
|
||||
stackTraceAux(c.tos)
|
||||
LocalError(n.info, msg, arg)
|
||||
LocalError(info, msg, arg)
|
||||
|
||||
proc isSpecial(n: PNode): bool {.inline.} =
|
||||
result = n.kind == nkExceptBranch
|
||||
template isSpecial(n: PNode): bool = n.kind == nkExceptBranch
|
||||
template bailout() {.dirty.} =
|
||||
if isSpecial(result): return
|
||||
|
||||
template evalX(n, flags) {.dirty.} =
|
||||
result = evalAux(c, n, flags)
|
||||
bailout()
|
||||
|
||||
proc myreset(n: PNode) =
|
||||
when defined(system.reset):
|
||||
@@ -128,19 +133,17 @@ proc evalIf(c: PEvalContext, n: PNode): PNode =
|
||||
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
|
||||
if (result.kind == nkIntLit) and (result.intVal != 0):
|
||||
evalX(n.sons[i].sons[0], {})
|
||||
if result.kind == nkIntLit and result.intVal != 0:
|
||||
return evalAux(c, n.sons[i].sons[1], {})
|
||||
inc(i)
|
||||
if (i < length) and (sonsLen(n.sons[i]) < 2):
|
||||
if (i < length) and (sonsLen(n.sons[i]) < 2):
|
||||
result = evalAux(c, n.sons[i].sons[0], {})
|
||||
else:
|
||||
else:
|
||||
result = emptyNode
|
||||
|
||||
proc evalCase(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[0], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], {})
|
||||
var res = result
|
||||
result = emptyNode
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
@@ -160,9 +163,8 @@ var
|
||||
|
||||
proc evalWhile(c: PEvalContext, n: PNode): PNode =
|
||||
while true:
|
||||
result = evalAux(c, n.sons[0], {})
|
||||
if isSpecial(result): return
|
||||
if getOrdValue(result) == 0: break
|
||||
evalX(n.sons[0], {})
|
||||
if getOrdValue(result) == 0: break
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
case result.kind
|
||||
of nkBreakStmt:
|
||||
@@ -177,7 +179,7 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
|
||||
if allowInfiniteLoops in c.features:
|
||||
gWhileCounter = 0
|
||||
else:
|
||||
stackTrace(c, n, errTooManyIterations)
|
||||
stackTrace(c, n.info, errTooManyIterations)
|
||||
break
|
||||
|
||||
proc evalBlock(c: PEvalContext, n: PNode): PNode =
|
||||
@@ -222,7 +224,9 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
|
||||
else:
|
||||
for j in countup(0, blen - 2):
|
||||
assert(n.sons[i].sons[j].kind == nkType)
|
||||
if exc.typ.id == n.sons[i].sons[j].typ.id:
|
||||
let a = exc.typ.skipTypes(abstractPtrs)
|
||||
let b = n.sons[i].sons[j].typ.skipTypes(abstractPtrs)
|
||||
if a == b:
|
||||
result = evalAux(c, n.sons[i].sons[blen - 1], {})
|
||||
exc = result
|
||||
break
|
||||
@@ -239,7 +243,7 @@ proc getNullValueAux(obj: PNode, result: PNode) =
|
||||
getNullValueAux(obj.sons[0], result)
|
||||
for i in countup(1, sonsLen(obj) - 1):
|
||||
getNullValueAux(lastSon(obj.sons[i]), result)
|
||||
of nkSym:
|
||||
of nkSym:
|
||||
var s = obj.sym
|
||||
var p = newNodeIT(nkExprColonExpr, result.info, s.typ)
|
||||
addSon(p, newSymNode(s, result.info))
|
||||
@@ -290,14 +294,17 @@ proc evalVarValue(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n, {})
|
||||
if result.kind in {nkType..nkNilLit}: result = result.copyNode
|
||||
|
||||
proc allocSlot(c: PStackFrame; sym: PSym): int =
|
||||
result = sym.position + ord(sym.kind == skParam)
|
||||
if result == 0 and sym.kind != skResult:
|
||||
result = c.slots.len
|
||||
if result == 0: result = 1
|
||||
sym.position = result
|
||||
setLen(c.slots, max(result+1, c.slots.len))
|
||||
|
||||
proc setSlot(c: PStackFrame, sym: PSym, val: PNode) =
|
||||
assert sym.owner == c.prc
|
||||
var idx = sym.position
|
||||
if idx == 0:
|
||||
idx = c.slots.len
|
||||
if idx == 0: idx = 1
|
||||
sym.position = idx
|
||||
setLen(c.slots, max(idx+1, c.slots.len))
|
||||
let idx = allocSlot(c, sym)
|
||||
c.slots[idx] = val
|
||||
|
||||
proc setVar(c: PEvalContext, v: PSym, n: PNode) =
|
||||
@@ -313,7 +320,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalVarValue(c, a.lastSon)
|
||||
if result.kind in {nkType..nkNilLit}:
|
||||
result = result.copyNode
|
||||
if isSpecial(result): return
|
||||
bailout()
|
||||
if result.kind != nkPar:
|
||||
return raiseCannotEval(c, n.info)
|
||||
for i in 0 .. a.len-3:
|
||||
@@ -322,7 +329,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||
else:
|
||||
if a.sons[2].kind != nkEmpty:
|
||||
result = evalVarValue(c, a.sons[2])
|
||||
if isSpecial(result): return
|
||||
bailout()
|
||||
else:
|
||||
result = getNullValue(a.sons[0].typ, a.sons[0].info)
|
||||
if a.sons[0].kind == nkSym:
|
||||
@@ -331,8 +338,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
|
||||
else:
|
||||
# assign to a.sons[0]:
|
||||
var x = result
|
||||
result = evalAux(c, a.sons[0], {})
|
||||
if isSpecial(result): return
|
||||
evalX(a.sons[0], {})
|
||||
myreset(x)
|
||||
x.kind = result.kind
|
||||
x.typ = result.typ
|
||||
@@ -392,6 +398,9 @@ proc evalGlobalVar(c: PEvalContext, s: PSym, flags: TEvalFlags): PNode =
|
||||
else:
|
||||
result = raiseCannotEval(nil, s.info)
|
||||
|
||||
proc optBody(c: PEvalContext, s: PSym): PNode =
|
||||
result = s.getBody
|
||||
|
||||
proc evalCall(c: PEvalContext, n: PNode): PNode =
|
||||
var d = newStackFrame()
|
||||
d.call = n
|
||||
@@ -400,8 +409,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
|
||||
setlen(d.slots, sonsLen(n) + ord(isClosure))
|
||||
if isClosure:
|
||||
#debug prc
|
||||
result = evalAux(c, prc.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(prc.sons[1], {efLValue})
|
||||
d.slots[sonsLen(n)] = result
|
||||
result = evalAux(c, prc.sons[0], {})
|
||||
else:
|
||||
@@ -418,8 +426,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
|
||||
InternalError(n.info, "evalCall")
|
||||
return
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
result = evalAux(c, n.sons[i], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[i], {})
|
||||
d.slots[i] = result
|
||||
if n.typ != nil: d.slots[0] = getNullValue(n.typ, n.info)
|
||||
|
||||
@@ -432,33 +439,30 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
|
||||
return callForeignFunction(newCall)
|
||||
|
||||
pushStackFrame(c, d)
|
||||
result = evalAux(c, prc.sym.getBody, {})
|
||||
if result.kind == nkExceptBranch: return
|
||||
evalX(optBody(c, prc.sym), {})
|
||||
if n.typ != nil: result = d.slots[0]
|
||||
popStackFrame(c)
|
||||
|
||||
proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = evalAux(c, n.sons[0], flags)
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], flags)
|
||||
var x = result
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {})
|
||||
var idx = getOrdValue(result)
|
||||
result = emptyNode
|
||||
case x.kind
|
||||
of nkPar:
|
||||
of nkPar:
|
||||
if (idx >= 0) and (idx < sonsLen(x)):
|
||||
result = x.sons[int(idx)]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
stackTrace(c, n.info, errIndexOutOfBounds)
|
||||
of nkBracket, nkMetaNode:
|
||||
if (idx >= 0) and (idx < sonsLen(x)):
|
||||
result = x.sons[int(idx)]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
stackTrace(c, n.info, errIndexOutOfBounds)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if efLValue in flags: return raiseCannotEval(c, n.info)
|
||||
result = newNodeIT(nkCharLit, x.info, getSysType(tyChar))
|
||||
@@ -467,14 +471,13 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
elif idx == len(x.strVal):
|
||||
nil
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
else: stackTrace(c, n, errNilAccess)
|
||||
stackTrace(c, n.info, errIndexOutOfBounds)
|
||||
else: stackTrace(c, n.info, errNilAccess)
|
||||
|
||||
proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
# a real field access; proc calls have already been transformed
|
||||
# XXX: field checks!
|
||||
result = evalAux(c, n.sons[0], flags)
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], flags)
|
||||
var x = result
|
||||
if x.kind != nkPar: return raiseCannotEval(c, n.info)
|
||||
# this is performance critical:
|
||||
@@ -482,48 +485,26 @@ proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = x.sons[field.position]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
when false:
|
||||
var field = n.sons[1].sym
|
||||
for i in countup(0, sonsLen(x) - 1):
|
||||
var it = x.sons[i]
|
||||
if it.kind != nkExprColonExpr:
|
||||
# lookup per index:
|
||||
result = x.sons[field.position]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
return
|
||||
#InternalError(it.info, "evalFieldAccess")
|
||||
if it.sons[0].sym.name.id == field.name.id:
|
||||
result = x.sons[i].sons[1]
|
||||
if not aliasNeeded(result, flags): result = copyTree(result)
|
||||
return
|
||||
stackTrace(c, n, errFieldXNotFound, field.name.s)
|
||||
result = emptyNode
|
||||
|
||||
proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
||||
proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
||||
var a = n.sons[0]
|
||||
if a.kind == nkBracketExpr and a.sons[0].typ.kind in {tyString, tyCString}:
|
||||
result = evalAux(c, a.sons[0], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(a.sons[0], {efLValue})
|
||||
var x = result
|
||||
result = evalAux(c, a.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
evalX(a.sons[1], {})
|
||||
var idx = getOrdValue(result)
|
||||
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkCharLit: return raiseCannotEval(c, n.info)
|
||||
evalX(n.sons[1], {})
|
||||
if result.kind notin {nkIntLit, nkCharLit}: return c.raiseCannotEval(n.info)
|
||||
|
||||
if (idx >= 0) and (idx < len(x.strVal)):
|
||||
if idx >= 0 and idx < len(x.strVal):
|
||||
x.strVal[int(idx)] = chr(int(result.intVal))
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
else:
|
||||
stackTrace(c, n.info, errIndexOutOfBounds)
|
||||
else:
|
||||
result = evalAux(c, n.sons[0], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], {efLValue})
|
||||
var x = result
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {})
|
||||
myreset(x)
|
||||
x.kind = result.kind
|
||||
x.typ = result.typ
|
||||
@@ -541,13 +522,11 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode =
|
||||
assert result.kind == nkEmpty
|
||||
|
||||
proc evalSwap(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[0], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], {efLValue})
|
||||
var x = result
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {efLValue})
|
||||
if x.kind != result.kind:
|
||||
stackTrace(c, n, errCannotInterpretNodeX, $n.kind)
|
||||
stackTrace(c, n.info, errCannotInterpretNodeX, $n.kind)
|
||||
else:
|
||||
case x.kind
|
||||
of nkCharLit..nkInt64Lit: swap(x.intVal, result.intVal)
|
||||
@@ -587,11 +566,9 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = raiseCannotEval(c, n.info)
|
||||
|
||||
proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode =
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {efLValue})
|
||||
var a = result
|
||||
result = evalAux(c, n.sons[2], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[2], {})
|
||||
var b = result
|
||||
case a.kind
|
||||
of nkCharLit..nkInt64Lit: a.intval = a.intVal + sign * getOrdValue(b)
|
||||
@@ -607,64 +584,62 @@ proc getStrValue(n: PNode): string =
|
||||
|
||||
proc evalEcho(c: PEvalContext, n: PNode): PNode =
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
result = evalAux(c, n.sons[i], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[i], {})
|
||||
Write(stdout, getStrValue(result))
|
||||
writeln(stdout, "")
|
||||
result = emptyNode
|
||||
|
||||
proc evalExit(c: PEvalContext, n: PNode): PNode =
|
||||
if c.mode in {emRepl, emStatic}:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {})
|
||||
Message(n.info, hintQuitCalled)
|
||||
quit(int(getOrdValue(result)))
|
||||
else:
|
||||
result = raiseCannotEval(c, n.info)
|
||||
|
||||
proc evalOr(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkIntLit: InternalError(n.info, "evalOr")
|
||||
elif result.intVal == 0: result = evalAux(c, n.sons[2], {})
|
||||
evalX(n.sons[1], {})
|
||||
if result.intVal == 0: result = evalAux(c, n.sons[2], {})
|
||||
|
||||
proc evalAnd(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkIntLit: InternalError(n.info, "evalAnd")
|
||||
elif result.intVal != 0: result = evalAux(c, n.sons[2], {})
|
||||
evalX(n.sons[1], {})
|
||||
if result.intVal != 0: result = evalAux(c, n.sons[2], {})
|
||||
|
||||
proc evalNew(c: PEvalContext, n: PNode): PNode =
|
||||
#if c.mode == emOptimize: return raiseCannotEval(c, n.info)
|
||||
|
||||
# we ignore the finalizer for now and most likely forever :-)
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {efLValue})
|
||||
var a = result
|
||||
var t = skipTypes(n.sons[1].typ, abstractVar)
|
||||
if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty")
|
||||
myreset(a)
|
||||
a.kind = nkRefTy
|
||||
a.info = n.info
|
||||
let u = getNullValue(t.sons[0], n.info)
|
||||
a.kind = u.kind
|
||||
a.typ = t
|
||||
a.sons = nil
|
||||
addSon(a, getNullValue(t.sons[0], n.info))
|
||||
shallowCopy(a.sons, u.sons)
|
||||
result = emptyNode
|
||||
when false:
|
||||
a.kind = nkRefTy
|
||||
a.info = n.info
|
||||
a.typ = t
|
||||
a.sons = nil
|
||||
addSon(a, getNullValue(t.sons[0], n.info))
|
||||
result = emptyNode
|
||||
|
||||
proc evalDeref(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = evalAux(c, n.sons[0], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], {efLValue})
|
||||
case result.kind
|
||||
of nkNilLit: stackTrace(c, n, errNilAccess)
|
||||
of nkNilLit: stackTrace(c, n.info, errNilAccess)
|
||||
of nkRefTy:
|
||||
# XXX efLValue?
|
||||
result = result.sons[0]
|
||||
else:
|
||||
result = raiseCannotEval(c, n.info)
|
||||
if skipTypes(n.sons[0].typ, abstractInst).kind != tyRef:
|
||||
result = raiseCannotEval(c, n.info)
|
||||
|
||||
proc evalAddr(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = evalAux(c, n.sons[0], {efLValue})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], {efLValue})
|
||||
var a = result
|
||||
var t = newType(tyPtr, c.module)
|
||||
addSonSkipIntLit(t, a.typ)
|
||||
@@ -703,24 +678,22 @@ proc evalUpConv(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
var dest = skipTypes(n.typ, abstractPtrs)
|
||||
var src = skipTypes(result.typ, abstractPtrs)
|
||||
if inheritanceDiff(src, dest) > 0:
|
||||
stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src))
|
||||
stackTrace(c, n.info, errInvalidConversionFromTypeX, typeToString(src))
|
||||
|
||||
proc evalRangeChck(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[0], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[0], {})
|
||||
var x = result
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[1], {})
|
||||
var a = result
|
||||
result = evalAux(c, n.sons[2], {})
|
||||
if isSpecial(result): return
|
||||
evalX(n.sons[2], {})
|
||||
var b = result
|
||||
if leValueConv(a, x) and leValueConv(x, b):
|
||||
result = x # a <= x and x <= b
|
||||
result.typ = n.typ
|
||||
else:
|
||||
stackTrace(c, n, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
|
||||
typeToString(n.sons[0].typ), typeToString(n.typ)])
|
||||
stackTrace(c, n.info, errGenerated,
|
||||
msgKindToString(errIllegalConvFromXtoY) % [
|
||||
typeToString(n.sons[0].typ), typeToString(n.typ)])
|
||||
|
||||
proc evalConvStrToCStr(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[0], {})
|
||||
@@ -744,7 +717,7 @@ proc evalRaise(c: PEvalContext, n: PNode): PNode =
|
||||
elif c.lastException != nil:
|
||||
result = c.lastException
|
||||
else:
|
||||
stackTrace(c, n, errExceptionAlreadyHandled)
|
||||
stackTrace(c, n.info, errExceptionAlreadyHandled)
|
||||
result = newNodeIT(nkExceptBranch, n.info, nil)
|
||||
addSon(result, ast.emptyNode)
|
||||
else:
|
||||
@@ -1089,7 +1062,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
case a.kind
|
||||
of nkEmpty..nkNilLit: nil
|
||||
else: result.intVal = sonsLen(a)
|
||||
of mNChild:
|
||||
of mNChild:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
var a = result
|
||||
@@ -1100,7 +1073,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result = a.sons[int(k)]
|
||||
if result == nil: result = newNode(nkEmpty)
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
stackTrace(c, n.info, errIndexOutOfBounds)
|
||||
result = emptyNode
|
||||
of mNSetChild:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
@@ -1115,7 +1088,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
if (k >= 0) and (k < sonsLen(a)) and not (a.kind in {nkEmpty..nkNilLit}):
|
||||
a.sons[int(k)] = result
|
||||
else:
|
||||
stackTrace(c, n, errIndexOutOfBounds)
|
||||
stackTrace(c, n.info, errIndexOutOfBounds)
|
||||
result = emptyNode
|
||||
of mNAdd:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
@@ -1158,7 +1131,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkIntLit, n.info, n.typ)
|
||||
case a.kind
|
||||
of nkCharLit..nkInt64Lit: result.intVal = a.intVal
|
||||
else: stackTrace(c, n, errFieldXNotFound, "intVal")
|
||||
else: stackTrace(c, n.info, errFieldXNotFound, "intVal")
|
||||
of mNFloatVal:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
@@ -1166,15 +1139,15 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkFloatLit, n.info, n.typ)
|
||||
case a.kind
|
||||
of nkFloatLit..nkFloat64Lit: result.floatVal = a.floatVal
|
||||
else: stackTrace(c, n, errFieldXNotFound, "floatVal")
|
||||
else: stackTrace(c, n.info, errFieldXNotFound, "floatVal")
|
||||
of mNSymbol:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkSym: stackTrace(c, n, errFieldXNotFound, "symbol")
|
||||
if result.kind != nkSym: stackTrace(c, n.info, errFieldXNotFound, "symbol")
|
||||
of mNIdent:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkIdent: stackTrace(c, n, errFieldXNotFound, "ident")
|
||||
if result.kind != nkIdent: stackTrace(c, n.info, errFieldXNotFound, "ident")
|
||||
of mNGetType:
|
||||
var ast = evalAux(c, n.sons[1], {})
|
||||
InternalAssert c.getType != nil
|
||||
@@ -1186,7 +1159,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||
case a.kind
|
||||
of nkStrLit..nkTripleStrLit: result.strVal = a.strVal
|
||||
else: stackTrace(c, n, errFieldXNotFound, "strVal")
|
||||
else: stackTrace(c, n.info, errFieldXNotFound, "strVal")
|
||||
of mNSetIntVal:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
@@ -1197,7 +1170,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result.kind in {nkCharLit..nkInt64Lit}:
|
||||
a.intVal = result.intVal
|
||||
else:
|
||||
stackTrace(c, n, errFieldXNotFound, "intVal")
|
||||
stackTrace(c, n.info, errFieldXNotFound, "intVal")
|
||||
result = emptyNode
|
||||
of mNSetFloatVal:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
@@ -1209,7 +1182,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result.kind in {nkFloatLit..nkFloat64Lit}:
|
||||
a.floatVal = result.floatVal
|
||||
else:
|
||||
stackTrace(c, n, errFieldXNotFound, "floatVal")
|
||||
stackTrace(c, n.info, errFieldXNotFound, "floatVal")
|
||||
result = emptyNode
|
||||
of mNSetSymbol:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
@@ -1220,7 +1193,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
if a.kind == nkSym and result.kind == nkSym:
|
||||
a.sym = result.sym
|
||||
else:
|
||||
stackTrace(c, n, errFieldXNotFound, "symbol")
|
||||
stackTrace(c, n.info, errFieldXNotFound, "symbol")
|
||||
result = emptyNode
|
||||
of mNSetIdent:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
@@ -1231,7 +1204,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
if a.kind == nkIdent and result.kind == nkIdent:
|
||||
a.ident = result.ident
|
||||
else:
|
||||
stackTrace(c, n, errFieldXNotFound, "ident")
|
||||
stackTrace(c, n.info, errFieldXNotFound, "ident")
|
||||
result = emptyNode
|
||||
of mNSetType:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
@@ -1252,7 +1225,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
if a.kind in {nkStrLit..nkTripleStrLit} and
|
||||
result.kind in {nkStrLit..nkTripleStrLit}:
|
||||
a.strVal = result.strVal
|
||||
else: stackTrace(c, n, errFieldXNotFound, "strVal")
|
||||
else: stackTrace(c, n.info, errFieldXNotFound, "strVal")
|
||||
result = emptyNode
|
||||
of mNNewNimNode:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
@@ -1280,7 +1253,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
if not (result.kind in {nkStrLit..nkTripleStrLit}):
|
||||
stackTrace(c, n, errFieldXNotFound, "strVal")
|
||||
stackTrace(c, n.info, errFieldXNotFound, "strVal")
|
||||
return
|
||||
var a = result
|
||||
result = newNodeIT(nkIdent, n.info, n.typ)
|
||||
@@ -1333,7 +1306,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
of mNError:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
stackTrace(c, n, errUser, getStrValue(result))
|
||||
stackTrace(c, n.info, errUser, getStrValue(result))
|
||||
result = emptyNode
|
||||
of mConStrStr:
|
||||
result = evalConStrStr(c, n)
|
||||
@@ -1353,7 +1326,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
result.strVal = newString(0)
|
||||
of mNCallSite:
|
||||
if c.callsite != nil: result = c.callsite
|
||||
else: stackTrace(c, n, errFieldXNotFound, "callsite")
|
||||
else: stackTrace(c, n.info, errFieldXNotFound, "callsite")
|
||||
else:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
@@ -1371,10 +1344,10 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode
|
||||
else: result = evalOp(m, n, a, b, cc)
|
||||
|
||||
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = emptyNode
|
||||
dec(gNestedEvals)
|
||||
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
|
||||
if gNestedEvals <= 0: stackTrace(c, n.info, errTooManyIterations)
|
||||
case n.kind
|
||||
of nkSym: result = evalSym(c, n, flags)
|
||||
of nkType..nkNilLit:
|
||||
@@ -1473,6 +1446,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
||||
result = n
|
||||
else: InternalError(n.info, "evalAux: " & $n.kind)
|
||||
if result == nil:
|
||||
debug n
|
||||
InternalError(n.info, "evalAux: returned nil " & $n.kind)
|
||||
inc(gNestedEvals)
|
||||
|
||||
@@ -1489,9 +1463,9 @@ proc eval*(c: PEvalContext, n: PNode): PNode =
|
||||
result = tryEval(c, n)
|
||||
if result.kind == nkExceptBranch:
|
||||
if sonsLen(result) >= 1:
|
||||
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ))
|
||||
stackTrace(c, n.info, errUnhandledExceptionX, typeToString(result.typ))
|
||||
else:
|
||||
stackTrace(c, result, errCannotInterpretNodeX, renderTree(n))
|
||||
stackTrace(c, result.info, errCannotInterpretNodeX, renderTree(n))
|
||||
|
||||
proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode =
|
||||
var p = newEvalContext(module, mode)
|
||||
@@ -1531,7 +1505,7 @@ proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# setup parameters:
|
||||
for i in 1 .. < L: s.slots[i] = setupMacroParam(n.sons[i])
|
||||
pushStackFrame(c, s)
|
||||
discard eval(c, sym.getBody)
|
||||
discard eval(c, optBody(c, sym))
|
||||
result = s.slots[0]
|
||||
popStackFrame(c)
|
||||
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer
|
||||
|
||||
const
|
||||
someEq = {mEqI, mEqI64, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
||||
someEq = {mEqI, mEqI64, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
||||
mEqUntracedRef, mEqStr, mEqSet, mEqCString}
|
||||
|
||||
# set excluded here as the semantics are vastly different:
|
||||
someLe = {mLeI, mLeI64, mLeF64, mLeU, mLeU64, mLeEnum,
|
||||
someLe = {mLeI, mLeI64, mLeF64, mLeU, mLeU64, mLeEnum,
|
||||
mLeCh, mLeB, mLePtr, mLeStr}
|
||||
someLt = {mLtI, mLtI64, mLtF64, mLtU, mLtU64, mLtEnum,
|
||||
mLtCh, mLtB, mLtPtr, mLtStr}
|
||||
@@ -491,20 +491,13 @@ proc factImplies(fact, prop: PNode): TImplication =
|
||||
else: discard
|
||||
|
||||
case prop.sons[0].sym.magic
|
||||
of mNot:
|
||||
result = ~fact.factImplies(prop.sons[1])
|
||||
of mIsNil:
|
||||
result = impliesIsNil(fact, prop)
|
||||
of someEq:
|
||||
result = impliesEq(fact, prop)
|
||||
of someLe:
|
||||
result = impliesLe(fact, prop.sons[1], prop.sons[2])
|
||||
of someLt:
|
||||
result = impliesLt(fact, prop.sons[1], prop.sons[2])
|
||||
of mInSet:
|
||||
result = impliesIn(fact, prop.sons[2], prop.sons[1])
|
||||
else:
|
||||
internalError(prop.info, "invalid proposition")
|
||||
of mNot: result = ~fact.factImplies(prop.sons[1])
|
||||
of mIsNil: result = impliesIsNil(fact, prop)
|
||||
of someEq: result = impliesEq(fact, prop)
|
||||
of someLe: result = impliesLe(fact, prop.sons[1], prop.sons[2])
|
||||
of someLt: result = impliesLt(fact, prop.sons[1], prop.sons[2])
|
||||
of mInSet: result = impliesIn(fact, prop.sons[2], prop.sons[1])
|
||||
else: internalError(prop.info, "invalid proposition")
|
||||
|
||||
proc doesImply*(facts: TModel, prop: PNode): TImplication =
|
||||
assert prop.kind in nkCallKinds
|
||||
|
||||
@@ -118,8 +118,7 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||
of tyPointer:
|
||||
# treat a tyPointer like a typed pointer to an array of bytes
|
||||
result = etyInt
|
||||
of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyIter,
|
||||
tyProxy:
|
||||
of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyIter, tyProxy:
|
||||
result = mapType(t.sons[0])
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
|
||||
of tyBool: result = etyBool
|
||||
@@ -826,17 +825,18 @@ proc genSwap(p: PProc, n: PNode) =
|
||||
gen(p, n.sons[1], a)
|
||||
gen(p, n.sons[2], b)
|
||||
inc(p.unique)
|
||||
let tmp = ropef("Tmp$1", [toRope(p.unique)])
|
||||
case mapType(skipTypes(n.sons[1].typ, abstractVar))
|
||||
of etyBaseIndex:
|
||||
var tmp = ropef("Tmp$1", [toRope(p.unique)])
|
||||
if mapType(skipTypes(n.sons[1].typ, abstractVar)) == etyBaseIndex:
|
||||
inc(p.unique)
|
||||
let tmp2 = ropef("Tmp$1", [toRope(p.unique)])
|
||||
if a.typ != etyBaseIndex or b.typ != etyBaseIndex:
|
||||
internalError(n.info, "genSwap")
|
||||
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1;$n", [tmp, a.address, b.address])
|
||||
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1", [tmp2, a.res, b.res])
|
||||
else:
|
||||
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res])
|
||||
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1;$n" |
|
||||
"local $1 = $2; $2 = $3; $3 = $1;$n", [
|
||||
tmp, a.address, b.address])
|
||||
tmp = tmp2
|
||||
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1" |
|
||||
"local $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res])
|
||||
|
||||
proc getFieldPosition(f: PNode): int =
|
||||
case f.kind
|
||||
@@ -1664,25 +1664,27 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
app(p.g.code, p.locals)
|
||||
app(p.g.code, p.body)
|
||||
|
||||
proc wholeCode*(m: BModule): PRope =
|
||||
for prc in globals.forwarded:
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
var p = newProc(globals, m, nil, m.module.options)
|
||||
app(p.g.code, genProc(p, prc))
|
||||
|
||||
var disp = generateMethodDispatchers()
|
||||
for i in 0..sonsLen(disp)-1:
|
||||
let prc = disp.sons[i].sym
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
var p = newProc(globals, m, nil, m.module.options)
|
||||
app(p.g.code, genProc(p, prc))
|
||||
|
||||
result = con(globals.typeInfo, globals.code)
|
||||
|
||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||
if passes.skipCodegen(n): return n
|
||||
result = myProcess(b, n)
|
||||
var m = BModule(b)
|
||||
if sfMainModule in m.module.flags:
|
||||
for prc in globals.forwarded:
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
var p = newProc(globals, m, nil, m.module.options)
|
||||
app(p.g.code, genProc(p, prc))
|
||||
|
||||
var disp = generateMethodDispatchers()
|
||||
for i in 0..sonsLen(disp)-1:
|
||||
let prc = disp.sons[i].sym
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
var p = newProc(globals, m, nil, m.module.options)
|
||||
app(p.g.code, genProc(p, prc))
|
||||
|
||||
# write the file:
|
||||
var code = con(globals.typeInfo, globals.code)
|
||||
let code = wholeCode(m)
|
||||
var outfile = changeFileExt(completeCFilePath(m.module.filename), "js")
|
||||
discard writeRopeIfNotEqual(con(genHeader(), code), outfile)
|
||||
|
||||
|
||||
@@ -341,6 +341,18 @@ proc CommandInteractive =
|
||||
incl(m.flags, sfMainModule)
|
||||
processModule(m, LLStreamOpenStdIn(), nil)
|
||||
|
||||
proc execute*(program: string) =
|
||||
passes.gIncludeFile = includeModule
|
||||
passes.gImportModule = importModule
|
||||
initDefines()
|
||||
LoadConfigs(DefaultConfig)
|
||||
InteractivePasses()
|
||||
appendStr(searchPaths, options.libpath)
|
||||
compileSystemModule()
|
||||
var m = makeStdinModule()
|
||||
incl(m.flags, sfMainModule)
|
||||
processModule(m, LLStreamOpen(program), nil)
|
||||
|
||||
const evalPasses = [verbosePass, semPass, evalPass]
|
||||
|
||||
proc evalNim(nodes: PNode, module: PSym) =
|
||||
|
||||
@@ -24,7 +24,7 @@ const
|
||||
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||
wGenSym, wInject, wRaises, wTags}
|
||||
wGenSym, wInject, wRaises, wTags, wOperator}
|
||||
converterPragmas* = procPragmas
|
||||
methodPragmas* = procPragmas
|
||||
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty}
|
||||
@@ -34,7 +34,7 @@ const
|
||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises,
|
||||
wTags}
|
||||
wTags, wOperator}
|
||||
exprPragmas* = {wLine}
|
||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
||||
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||
@@ -717,6 +717,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
if sym == nil: invalidPragma(it)
|
||||
of wLine: PragmaLine(c, it)
|
||||
of wRaises, wTags: pragmaRaisesOrTags(c, it)
|
||||
of wOperator:
|
||||
if sym == nil: invalidPragma(it)
|
||||
else: sym.position = expectIntLit(c, it)
|
||||
else: invalidPragma(it)
|
||||
else: invalidPragma(it)
|
||||
else: processNote(c, it)
|
||||
|
||||
@@ -620,7 +620,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
{skProc, skMethod, skConverter, skMacro, skTemplate})
|
||||
if result != nil:
|
||||
if result.sons[0].kind != nkSym:
|
||||
InternalError("semDirectCallAnalyseEffects")
|
||||
InternalError("semOverloadedCallAnalyseEffects")
|
||||
return
|
||||
let callee = result.sons[0].sym
|
||||
case callee.kind
|
||||
@@ -632,10 +632,6 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
if {sfImportc, sfSideEffect} * callee.flags != {}:
|
||||
incl(c.p.owner.flags, sfSideEffect)
|
||||
|
||||
proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = nil
|
||||
@@ -707,12 +703,28 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
LocalError(n.info, errExprXCannotBeCalled,
|
||||
renderTree(n, {renderNoComments}))
|
||||
return errorNode(c, n)
|
||||
#result = afterCallActions(c, result, nOrig, flags)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
result = evalAtCompileTime(c, result)
|
||||
|
||||
proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
let callee = result.sons[0].sym
|
||||
case callee.kind
|
||||
of skMacro: result = semMacroExpr(c, result, orig, callee)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee)
|
||||
else:
|
||||
semFinishOperands(c, result)
|
||||
activate(c, result)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
if callee.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
result = evalAtCompileTime(c, result)
|
||||
|
||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# this seems to be a hotspot in the compiler!
|
||||
let nOrig = n.copyTree
|
||||
@@ -723,18 +735,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if result == nil:
|
||||
NotFoundError(c, n)
|
||||
return errorNode(c, n)
|
||||
let callee = result.sons[0].sym
|
||||
case callee.kind
|
||||
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
||||
of skTemplate: result = semTemplateExpr(c, result, callee)
|
||||
else:
|
||||
semFinishOperands(c, n)
|
||||
activate(c, n)
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
if callee.magic != mNone:
|
||||
result = magicsAfterOverloadResolution(c, result, flags)
|
||||
result = evalAtCompileTime(c, result)
|
||||
result = afterCallActions(c, result, nOrig, flags)
|
||||
|
||||
proc buildStringify(c: PContext, arg: PNode): PNode =
|
||||
if arg.typ != nil and
|
||||
@@ -928,30 +929,33 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
markUsed(n, f)
|
||||
|
||||
proc dotTransformation(c: PContext, n: PNode): PNode =
|
||||
if isSymChoice(n.sons[1]):
|
||||
result = newNodeI(nkDotCall, n.info)
|
||||
addSon(result, n.sons[1])
|
||||
addSon(result, copyTree(n[0]))
|
||||
else:
|
||||
var i = considerAcc(n.sons[1])
|
||||
var f = searchInScopes(c, i)
|
||||
# if f != nil and f.kind == skStub: loadStub(f)
|
||||
# ``loadStub`` is not correct here as we don't care for ``f`` really
|
||||
if f != nil:
|
||||
# BUGFIX: do not check for (f.kind in {skProc, skMethod, skIterator}) here
|
||||
# This special node kind is to merge with the call handler in `semExpr`.
|
||||
result = newNodeI(nkDotCall, n.info)
|
||||
addSon(result, newIdentNode(i, n[1].info))
|
||||
addSon(result, copyTree(n[0]))
|
||||
else:
|
||||
if not ContainsOrIncl(c.UnknownIdents, i.id):
|
||||
LocalError(n.Info, errUndeclaredFieldX, i.s)
|
||||
result = errorNode(c, n)
|
||||
|
||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# this is difficult, because the '.' is used in many different contexts
|
||||
# in Nimrod. We first allow types in the semantic checking.
|
||||
result = builtinFieldAccess(c, n, flags)
|
||||
if result == nil:
|
||||
if isSymChoice(n.sons[1]):
|
||||
result = newNodeI(nkDotCall, n.info)
|
||||
addSon(result, n.sons[1])
|
||||
addSon(result, copyTree(n[0]))
|
||||
else:
|
||||
var i = considerAcc(n.sons[1])
|
||||
var f = searchInScopes(c, i)
|
||||
# if f != nil and f.kind == skStub: loadStub(f)
|
||||
# ``loadStub`` is not correct here as we don't care for ``f`` really
|
||||
if f != nil:
|
||||
# BUGFIX: do not check for (f.kind in {skProc, skMethod, skIterator}) here
|
||||
# This special node kind is to merge with the call handler in `semExpr`.
|
||||
result = newNodeI(nkDotCall, n.info)
|
||||
addSon(result, newIdentNode(i, n[1].info))
|
||||
addSon(result, copyTree(n[0]))
|
||||
else:
|
||||
if not ContainsOrIncl(c.UnknownIdents, i.id):
|
||||
LocalError(n.Info, errUndeclaredFieldX, i.s)
|
||||
result = errorNode(c, n)
|
||||
result = dotTransformation(c, n)
|
||||
|
||||
proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
|
||||
result = newNodeI(nkCall, n.info)
|
||||
@@ -1030,14 +1034,12 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
|
||||
let aOrig = nOrig[0]
|
||||
result = newNode(nkCall, n.info, sons = @[setterId, a[0], semExpr(c, n[1])])
|
||||
let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
|
||||
result = semDirectCallAnalyseEffects(c, result, orig, {})
|
||||
result = semOverloadedCallAnalyseEffects(c, result, orig, {})
|
||||
|
||||
if result != nil:
|
||||
fixAbstractType(c, result)
|
||||
analyseIfAddressTakenInCall(c, result)
|
||||
else:
|
||||
if not ContainsOrIncl(c.UnknownIdents, id.id):
|
||||
LocalError(n.Info, errUndeclaredFieldX, id.s)
|
||||
result = errorNode(c, n)
|
||||
result = afterCallActions(c, result, nOrig, {})
|
||||
#fixAbstractType(c, result)
|
||||
#analyseIfAddressTakenInCall(c, result)
|
||||
|
||||
proc takeImplicitAddr(c: PContext, n: PNode): PNode =
|
||||
case n.kind
|
||||
@@ -1072,7 +1074,14 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
let nOrig = n.copyTree
|
||||
a = builtinFieldAccess(c, a, {efLValue})
|
||||
if a == nil:
|
||||
return propertyWriteAccess(c, n, nOrig, n[0])
|
||||
a = propertyWriteAccess(c, n, nOrig, n[0])
|
||||
if a != nil: return a
|
||||
# we try without the '='; proc that return 'var' or macros are still
|
||||
# possible:
|
||||
a = dotTransformation(c, n[0])
|
||||
if a.kind == nkDotCall:
|
||||
a.kind = nkCall
|
||||
a = semExprWithType(c, a, {efLValue})
|
||||
of nkBracketExpr:
|
||||
# a[i] = x
|
||||
# --> `[]=`(a, i, x)
|
||||
|
||||
@@ -101,7 +101,7 @@ proc normalize*(s: string): string {.noSideEffect, procvar,
|
||||
if j != s.len: setLen(result, j)
|
||||
|
||||
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
|
||||
rtl, extern: "nsuCmpIgnoreCase", procvar.} =
|
||||
rtl, extern: "nsuCmpIgnoreCase", procvar, operator: 4.} =
|
||||
## Compares two strings in a case insensitive manner. Returns:
|
||||
##
|
||||
## | 0 iff a == b
|
||||
@@ -119,7 +119,7 @@ proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
|
||||
# thus we compile without checks here
|
||||
|
||||
proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
|
||||
rtl, extern: "nsuCmpIgnoreStyle", procvar.} =
|
||||
rtl, extern: "nsuCmpIgnoreStyle", procvar, operator: 3.} =
|
||||
## Compares two strings normalized (i.e. case and
|
||||
## underscores do not matter). Returns:
|
||||
##
|
||||
@@ -141,7 +141,7 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
|
||||
{.pop.}
|
||||
|
||||
proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
|
||||
rtl, extern: "nsuStrip".} =
|
||||
rtl, extern: "nsuStrip", operator: 5.} =
|
||||
## Strips whitespace from `s` and returns the resulting string.
|
||||
## If `leading` is true, leading whitespace is stripped.
|
||||
## If `trailing` is true, trailing whitespace is stripped.
|
||||
@@ -665,7 +665,7 @@ proc findAux(s, sub: string, start: int, a: TSkipTable): int =
|
||||
return -1
|
||||
|
||||
proc find*(s, sub: string, start: int = 0): int {.noSideEffect,
|
||||
rtl, extern: "nsuFindStr".} =
|
||||
rtl, extern: "nsuFindStr", operator: 6.} =
|
||||
## Searches for `sub` in `s` starting at position `start`. Searching is
|
||||
## case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||
var a {.noinit.}: TSkipTable
|
||||
@@ -723,7 +723,7 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} =
|
||||
return find(s, chars) >= 0
|
||||
|
||||
proc replace*(s, sub: string, by = ""): string {.noSideEffect,
|
||||
rtl, extern: "nsuReplaceStr".} =
|
||||
rtl, extern: "nsuReplaceStr", operator: 1.} =
|
||||
## Replaces `sub` in `s` by the string `by`.
|
||||
var a {.noinit.}: TSkipTable
|
||||
result = ""
|
||||
@@ -1023,7 +1023,7 @@ type
|
||||
ffScientific ## use scientific notation (using ``e`` character)
|
||||
|
||||
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||
precision = 16): string {.noSideEffect,
|
||||
precision = 16): string {.noSideEffect, operator: 2,
|
||||
rtl, extern: "nsu$1".} =
|
||||
## converts a floating point value `f` to a string.
|
||||
##
|
||||
@@ -1054,7 +1054,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
|
||||
result = $buf
|
||||
|
||||
proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
|
||||
precision = 16): string {.noSideEffect,
|
||||
precision = 16): string {.noSideEffect, operator: 2,
|
||||
rtl, extern: "nsu$1".} =
|
||||
## converts a floating point value `f` to a string.
|
||||
##
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -42,3 +42,5 @@ else:
|
||||
{.pragma: inl, inline.}
|
||||
{.pragma: compilerRtl, compilerproc.}
|
||||
|
||||
when not defined(nimsuperops):
|
||||
{.pragma: operator.}
|
||||
|
||||
Reference in New Issue
Block a user