refactorings for the eval engine; bugfix: clean templates as accessors

This commit is contained in:
Araq 2013-07-19 22:22:20 +02:00
commit bfbdb1f028
10 changed files with 235 additions and 239 deletions

View file

@ -211,7 +211,7 @@ type
nkClosure, # (prc, env)-pair (internally used for code gen) nkClosure, # (prc, env)-pair (internally used for code gen)
nkGotoState, # used for the state machine (for iterators) nkGotoState, # used for the state machine (for iterators)
nkState, # give a label to a code section (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] TNodeKinds* = set[TNodeKind]
type type
@ -534,7 +534,6 @@ type
when defined(useNodeIds): when defined(useNodeIds):
id*: int id*: int
typ*: PType typ*: PType
comment*: string
info*: TLineInfo info*: TLineInfo
flags*: TNodeFlags flags*: TNodeFlags
case Kind*: TNodeKind case Kind*: TNodeKind
@ -550,6 +549,7 @@ type
ident*: PIdent ident*: PIdent
else: else:
sons*: TNodeSeq sons*: TNodeSeq
comment*: string
TSymSeq* = seq[PSym] TSymSeq* = seq[PSym]
TStrTable* = object # a table[PIdent] of PSym TStrTable* = object # a table[PIdent] of PSym
@ -667,7 +667,7 @@ type
# for modules, an unique index corresponding # for modules, an unique index corresponding
# to the module's fileIdx # to the module's fileIdx
# for variables a slot index for the evaluator # for variables a slot index for the evaluator
# for routines a superop-ID
offset*: int # offset of record field offset*: int # offset of record field
loc*: TLoc loc*: TLoc
annex*: PLib # additional fields (seldom used, so we use a annex*: PLib # additional fields (seldom used, so we use a
@ -778,10 +778,10 @@ const
genericParamsPos* = 2 genericParamsPos* = 2
paramsPos* = 3 paramsPos* = 3
pragmasPos* = 4 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! bodyPos* = 6 # position of body; use rodread.getBody() instead!
resultPos* = 7 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, nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
nkCommand, nkCallStrLit, nkHiddenCallConv} nkCommand, nkCallStrLit, nkHiddenCallConv}

View file

@ -59,6 +59,7 @@ proc InitDefines*() =
DefineSymbol("nimmixin") DefineSymbol("nimmixin")
DefineSymbol("nimeffects") DefineSymbol("nimeffects")
DefineSymbol("nimbabel") DefineSymbol("nimbabel")
DefineSymbol("nimsuperops")
# add platform specific symbols: # add platform specific symbols:
case targetCPU case targetCPU

View file

@ -110,13 +110,18 @@ proc stackTraceAux(x: PStackFrame) =
add(s, x.prc.name.s) add(s, x.prc.name.s)
MsgWriteln(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)") MsgWriteln("stack trace: (most recent call last)")
stackTraceAux(c.tos) stackTraceAux(c.tos)
LocalError(n.info, msg, arg) LocalError(info, msg, arg)
proc isSpecial(n: PNode): bool {.inline.} = template isSpecial(n: PNode): bool = n.kind == nkExceptBranch
result = 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) = proc myreset(n: PNode) =
when defined(system.reset): when defined(system.reset):
@ -128,9 +133,8 @@ proc evalIf(c: PEvalContext, n: PNode): PNode =
var i = 0 var i = 0
var length = sonsLen(n) var length = sonsLen(n)
while (i < length) and (sonsLen(n.sons[i]) >= 2): while (i < length) and (sonsLen(n.sons[i]) >= 2):
result = evalAux(c, n.sons[i].sons[0], {}) evalX(n.sons[i].sons[0], {})
if isSpecial(result): return if result.kind == nkIntLit and result.intVal != 0:
if (result.kind == nkIntLit) and (result.intVal != 0):
return evalAux(c, n.sons[i].sons[1], {}) return evalAux(c, n.sons[i].sons[1], {})
inc(i) inc(i)
if (i < length) and (sonsLen(n.sons[i]) < 2): if (i < length) and (sonsLen(n.sons[i]) < 2):
@ -139,8 +143,7 @@ proc evalIf(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalCase(c: PEvalContext, n: PNode): PNode = proc evalCase(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0], {}) evalX(n.sons[0], {})
if isSpecial(result): return
var res = result var res = result
result = emptyNode result = emptyNode
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
@ -160,8 +163,7 @@ var
proc evalWhile(c: PEvalContext, n: PNode): PNode = proc evalWhile(c: PEvalContext, n: PNode): PNode =
while true: while true:
result = evalAux(c, n.sons[0], {}) evalX(n.sons[0], {})
if isSpecial(result): return
if getOrdValue(result) == 0: break if getOrdValue(result) == 0: break
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
case result.kind case result.kind
@ -177,7 +179,7 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
if allowInfiniteLoops in c.features: if allowInfiniteLoops in c.features:
gWhileCounter = 0 gWhileCounter = 0
else: else:
stackTrace(c, n, errTooManyIterations) stackTrace(c, n.info, errTooManyIterations)
break break
proc evalBlock(c: PEvalContext, n: PNode): PNode = proc evalBlock(c: PEvalContext, n: PNode): PNode =
@ -222,7 +224,9 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
else: else:
for j in countup(0, blen - 2): for j in countup(0, blen - 2):
assert(n.sons[i].sons[j].kind == nkType) 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], {}) result = evalAux(c, n.sons[i].sons[blen - 1], {})
exc = result exc = result
break break
@ -290,14 +294,17 @@ proc evalVarValue(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n, {}) result = evalAux(c, n, {})
if result.kind in {nkType..nkNilLit}: result = result.copyNode 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) = proc setSlot(c: PStackFrame, sym: PSym, val: PNode) =
assert sym.owner == c.prc assert sym.owner == c.prc
var idx = sym.position let idx = allocSlot(c, sym)
if idx == 0:
idx = c.slots.len
if idx == 0: idx = 1
sym.position = idx
setLen(c.slots, max(idx+1, c.slots.len))
c.slots[idx] = val c.slots[idx] = val
proc setVar(c: PEvalContext, v: PSym, n: PNode) = proc setVar(c: PEvalContext, v: PSym, n: PNode) =
@ -313,7 +320,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
result = evalVarValue(c, a.lastSon) result = evalVarValue(c, a.lastSon)
if result.kind in {nkType..nkNilLit}: if result.kind in {nkType..nkNilLit}:
result = result.copyNode result = result.copyNode
if isSpecial(result): return bailout()
if result.kind != nkPar: if result.kind != nkPar:
return raiseCannotEval(c, n.info) return raiseCannotEval(c, n.info)
for i in 0 .. a.len-3: for i in 0 .. a.len-3:
@ -322,7 +329,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
else: else:
if a.sons[2].kind != nkEmpty: if a.sons[2].kind != nkEmpty:
result = evalVarValue(c, a.sons[2]) result = evalVarValue(c, a.sons[2])
if isSpecial(result): return bailout()
else: else:
result = getNullValue(a.sons[0].typ, a.sons[0].info) result = getNullValue(a.sons[0].typ, a.sons[0].info)
if a.sons[0].kind == nkSym: if a.sons[0].kind == nkSym:
@ -331,8 +338,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
else: else:
# assign to a.sons[0]: # assign to a.sons[0]:
var x = result var x = result
result = evalAux(c, a.sons[0], {}) evalX(a.sons[0], {})
if isSpecial(result): return
myreset(x) myreset(x)
x.kind = result.kind x.kind = result.kind
x.typ = result.typ x.typ = result.typ
@ -392,6 +398,9 @@ proc evalGlobalVar(c: PEvalContext, s: PSym, flags: TEvalFlags): PNode =
else: else:
result = raiseCannotEval(nil, s.info) result = raiseCannotEval(nil, s.info)
proc optBody(c: PEvalContext, s: PSym): PNode =
result = s.getBody
proc evalCall(c: PEvalContext, n: PNode): PNode = proc evalCall(c: PEvalContext, n: PNode): PNode =
var d = newStackFrame() var d = newStackFrame()
d.call = n d.call = n
@ -400,8 +409,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
setlen(d.slots, sonsLen(n) + ord(isClosure)) setlen(d.slots, sonsLen(n) + ord(isClosure))
if isClosure: if isClosure:
#debug prc #debug prc
result = evalAux(c, prc.sons[1], {efLValue}) evalX(prc.sons[1], {efLValue})
if isSpecial(result): return
d.slots[sonsLen(n)] = result d.slots[sonsLen(n)] = result
result = evalAux(c, prc.sons[0], {}) result = evalAux(c, prc.sons[0], {})
else: else:
@ -418,8 +426,7 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
InternalError(n.info, "evalCall") InternalError(n.info, "evalCall")
return return
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
result = evalAux(c, n.sons[i], {}) evalX(n.sons[i], {})
if isSpecial(result): return
d.slots[i] = result d.slots[i] = result
if n.typ != nil: d.slots[0] = getNullValue(n.typ, n.info) if n.typ != nil: d.slots[0] = getNullValue(n.typ, n.info)
@ -432,17 +439,14 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
return callForeignFunction(newCall) return callForeignFunction(newCall)
pushStackFrame(c, d) pushStackFrame(c, d)
result = evalAux(c, prc.sym.getBody, {}) evalX(optBody(c, prc.sym), {})
if result.kind == nkExceptBranch: return
if n.typ != nil: result = d.slots[0] if n.typ != nil: result = d.slots[0]
popStackFrame(c) popStackFrame(c)
proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0], flags) evalX(n.sons[0], flags)
if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return
var idx = getOrdValue(result) var idx = getOrdValue(result)
result = emptyNode result = emptyNode
case x.kind case x.kind
@ -452,13 +456,13 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
if result.kind == nkExprColonExpr: result = result.sons[1] if result.kind == nkExprColonExpr: result = result.sons[1]
if not aliasNeeded(result, flags): result = copyTree(result) if not aliasNeeded(result, flags): result = copyTree(result)
else: else:
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n.info, errIndexOutOfBounds)
of nkBracket, nkMetaNode: of nkBracket, nkMetaNode:
if (idx >= 0) and (idx < sonsLen(x)): if (idx >= 0) and (idx < sonsLen(x)):
result = x.sons[int(idx)] result = x.sons[int(idx)]
if not aliasNeeded(result, flags): result = copyTree(result) if not aliasNeeded(result, flags): result = copyTree(result)
else: else:
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n.info, errIndexOutOfBounds)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if efLValue in flags: return raiseCannotEval(c, n.info) if efLValue in flags: return raiseCannotEval(c, n.info)
result = newNodeIT(nkCharLit, x.info, getSysType(tyChar)) 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): elif idx == len(x.strVal):
nil nil
else: else:
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n.info, errIndexOutOfBounds)
else: stackTrace(c, n, errNilAccess) else: stackTrace(c, n.info, errNilAccess)
proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
# a real field access; proc calls have already been transformed # a real field access; proc calls have already been transformed
# XXX: field checks! # XXX: field checks!
result = evalAux(c, n.sons[0], flags) evalX(n.sons[0], flags)
if isSpecial(result): return
var x = result var x = result
if x.kind != nkPar: return raiseCannotEval(c, n.info) if x.kind != nkPar: return raiseCannotEval(c, n.info)
# this is performance critical: # this is performance critical:
@ -482,48 +485,26 @@ proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = x.sons[field.position] result = x.sons[field.position]
if result.kind == nkExprColonExpr: result = result.sons[1] if result.kind == nkExprColonExpr: result = result.sons[1]
if not aliasNeeded(result, flags): result = copyTree(result) 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] var a = n.sons[0]
if a.kind == nkBracketExpr and a.sons[0].typ.kind in {tyString, tyCString}: if a.kind == nkBracketExpr and a.sons[0].typ.kind in {tyString, tyCString}:
result = evalAux(c, a.sons[0], {efLValue}) evalX(a.sons[0], {efLValue})
if isSpecial(result): return
var x = result var x = result
result = evalAux(c, a.sons[1], {}) evalX(a.sons[1], {})
if isSpecial(result): return
var idx = getOrdValue(result) var idx = getOrdValue(result)
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return if result.kind notin {nkIntLit, nkCharLit}: return c.raiseCannotEval(n.info)
if result.kind != nkCharLit: return raiseCannotEval(c, 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)) x.strVal[int(idx)] = chr(int(result.intVal))
else: else:
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n.info, errIndexOutOfBounds)
else: else:
result = evalAux(c, n.sons[0], {efLValue}) evalX(n.sons[0], {efLValue})
if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return
myreset(x) myreset(x)
x.kind = result.kind x.kind = result.kind
x.typ = result.typ x.typ = result.typ
@ -541,13 +522,11 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode =
assert result.kind == nkEmpty assert result.kind == nkEmpty
proc evalSwap(c: PEvalContext, n: PNode): PNode = proc evalSwap(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0], {efLValue}) evalX(n.sons[0], {efLValue})
if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1], {efLValue}) evalX(n.sons[1], {efLValue})
if isSpecial(result): return
if x.kind != result.kind: if x.kind != result.kind:
stackTrace(c, n, errCannotInterpretNodeX, $n.kind) stackTrace(c, n.info, errCannotInterpretNodeX, $n.kind)
else: else:
case x.kind case x.kind
of nkCharLit..nkInt64Lit: swap(x.intVal, result.intVal) 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) result = raiseCannotEval(c, n.info)
proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode = proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode =
result = evalAux(c, n.sons[1], {efLValue}) evalX(n.sons[1], {efLValue})
if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2], {}) evalX(n.sons[2], {})
if isSpecial(result): return
var b = result var b = result
case a.kind case a.kind
of nkCharLit..nkInt64Lit: a.intval = a.intVal + sign * getOrdValue(b) 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 = proc evalEcho(c: PEvalContext, n: PNode): PNode =
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
result = evalAux(c, n.sons[i], {}) evalX(n.sons[i], {})
if isSpecial(result): return
Write(stdout, getStrValue(result)) Write(stdout, getStrValue(result))
writeln(stdout, "") writeln(stdout, "")
result = emptyNode result = emptyNode
proc evalExit(c: PEvalContext, n: PNode): PNode = proc evalExit(c: PEvalContext, n: PNode): PNode =
if c.mode in {emRepl, emStatic}: if c.mode in {emRepl, emStatic}:
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return
Message(n.info, hintQuitCalled) Message(n.info, hintQuitCalled)
quit(int(getOrdValue(result))) quit(int(getOrdValue(result)))
else: else:
result = raiseCannotEval(c, n.info) result = raiseCannotEval(c, n.info)
proc evalOr(c: PEvalContext, n: PNode): PNode = proc evalOr(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return if result.intVal == 0: result = evalAux(c, n.sons[2], {})
if result.kind != nkIntLit: InternalError(n.info, "evalOr")
elif result.intVal == 0: result = evalAux(c, n.sons[2], {})
proc evalAnd(c: PEvalContext, n: PNode): PNode = proc evalAnd(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return if result.intVal != 0: result = evalAux(c, n.sons[2], {})
if result.kind != nkIntLit: InternalError(n.info, "evalAnd")
elif result.intVal != 0: result = evalAux(c, n.sons[2], {})
proc evalNew(c: PEvalContext, n: PNode): PNode = proc evalNew(c: PEvalContext, n: PNode): PNode =
#if c.mode == emOptimize: return raiseCannotEval(c, n.info) #if c.mode == emOptimize: return raiseCannotEval(c, n.info)
# we ignore the finalizer for now and most likely forever :-) # we ignore the finalizer for now and most likely forever :-)
result = evalAux(c, n.sons[1], {efLValue}) evalX(n.sons[1], {efLValue})
if isSpecial(result): return
var a = result var a = result
var t = skipTypes(n.sons[1].typ, abstractVar) var t = skipTypes(n.sons[1].typ, abstractVar)
if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty") if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty")
myreset(a) myreset(a)
a.kind = nkRefTy let u = getNullValue(t.sons[0], n.info)
a.info = n.info a.kind = u.kind
a.typ = t a.typ = t
a.sons = nil shallowCopy(a.sons, u.sons)
addSon(a, getNullValue(t.sons[0], n.info))
result = emptyNode 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 = proc evalDeref(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0], {efLValue}) evalX(n.sons[0], {efLValue})
if isSpecial(result): return
case result.kind case result.kind
of nkNilLit: stackTrace(c, n, errNilAccess) of nkNilLit: stackTrace(c, n.info, errNilAccess)
of nkRefTy: of nkRefTy:
# XXX efLValue? # XXX efLValue?
result = result.sons[0] result = result.sons[0]
else: 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 = proc evalAddr(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0], {efLValue}) evalX(n.sons[0], {efLValue})
if isSpecial(result): return
var a = result var a = result
var t = newType(tyPtr, c.module) var t = newType(tyPtr, c.module)
addSonSkipIntLit(t, a.typ) addSonSkipIntLit(t, a.typ)
@ -703,24 +678,22 @@ proc evalUpConv(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
var dest = skipTypes(n.typ, abstractPtrs) var dest = skipTypes(n.typ, abstractPtrs)
var src = skipTypes(result.typ, abstractPtrs) var src = skipTypes(result.typ, abstractPtrs)
if inheritanceDiff(src, dest) > 0: if inheritanceDiff(src, dest) > 0:
stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src)) stackTrace(c, n.info, errInvalidConversionFromTypeX, typeToString(src))
proc evalRangeChck(c: PEvalContext, n: PNode): PNode = proc evalRangeChck(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0], {}) evalX(n.sons[0], {})
if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1], {}) evalX(n.sons[1], {})
if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2], {}) evalX(n.sons[2], {})
if isSpecial(result): return
var b = result var b = result
if leValueConv(a, x) and leValueConv(x, b): if leValueConv(a, x) and leValueConv(x, b):
result = x # a <= x and x <= b result = x # a <= x and x <= b
result.typ = n.typ result.typ = n.typ
else: else:
stackTrace(c, n, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [ stackTrace(c, n.info, errGenerated,
typeToString(n.sons[0].typ), typeToString(n.typ)]) msgKindToString(errIllegalConvFromXtoY) % [
typeToString(n.sons[0].typ), typeToString(n.typ)])
proc evalConvStrToCStr(c: PEvalContext, n: PNode): PNode = proc evalConvStrToCStr(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0], {}) result = evalAux(c, n.sons[0], {})
@ -744,7 +717,7 @@ proc evalRaise(c: PEvalContext, n: PNode): PNode =
elif c.lastException != nil: elif c.lastException != nil:
result = c.lastException result = c.lastException
else: else:
stackTrace(c, n, errExceptionAlreadyHandled) stackTrace(c, n.info, errExceptionAlreadyHandled)
result = newNodeIT(nkExceptBranch, n.info, nil) result = newNodeIT(nkExceptBranch, n.info, nil)
addSon(result, ast.emptyNode) addSon(result, ast.emptyNode)
else: else:
@ -1100,7 +1073,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = a.sons[int(k)] result = a.sons[int(k)]
if result == nil: result = newNode(nkEmpty) if result == nil: result = newNode(nkEmpty)
else: else:
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n.info, errIndexOutOfBounds)
result = emptyNode result = emptyNode
of mNSetChild: of mNSetChild:
result = evalAux(c, n.sons[1], {efLValue}) 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}): if (k >= 0) and (k < sonsLen(a)) and not (a.kind in {nkEmpty..nkNilLit}):
a.sons[int(k)] = result a.sons[int(k)] = result
else: else:
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n.info, errIndexOutOfBounds)
result = emptyNode result = emptyNode
of mNAdd: of mNAdd:
result = evalAux(c, n.sons[1], {efLValue}) 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) result = newNodeIT(nkIntLit, n.info, n.typ)
case a.kind case a.kind
of nkCharLit..nkInt64Lit: result.intVal = a.intVal of nkCharLit..nkInt64Lit: result.intVal = a.intVal
else: stackTrace(c, n, errFieldXNotFound, "intVal") else: stackTrace(c, n.info, errFieldXNotFound, "intVal")
of mNFloatVal: of mNFloatVal:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
@ -1166,15 +1139,15 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = newNodeIT(nkFloatLit, n.info, n.typ) result = newNodeIT(nkFloatLit, n.info, n.typ)
case a.kind case a.kind
of nkFloatLit..nkFloat64Lit: result.floatVal = a.floatVal of nkFloatLit..nkFloat64Lit: result.floatVal = a.floatVal
else: stackTrace(c, n, errFieldXNotFound, "floatVal") else: stackTrace(c, n.info, errFieldXNotFound, "floatVal")
of mNSymbol: of mNSymbol:
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return 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: of mNIdent:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return 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: of mNGetType:
var ast = evalAux(c, n.sons[1], {}) var ast = evalAux(c, n.sons[1], {})
InternalAssert c.getType != nil InternalAssert c.getType != nil
@ -1186,7 +1159,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = newNodeIT(nkStrLit, n.info, n.typ) result = newNodeIT(nkStrLit, n.info, n.typ)
case a.kind case a.kind
of nkStrLit..nkTripleStrLit: result.strVal = a.strVal of nkStrLit..nkTripleStrLit: result.strVal = a.strVal
else: stackTrace(c, n, errFieldXNotFound, "strVal") else: stackTrace(c, n.info, errFieldXNotFound, "strVal")
of mNSetIntVal: of mNSetIntVal:
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
@ -1197,7 +1170,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result.kind in {nkCharLit..nkInt64Lit}: result.kind in {nkCharLit..nkInt64Lit}:
a.intVal = result.intVal a.intVal = result.intVal
else: else:
stackTrace(c, n, errFieldXNotFound, "intVal") stackTrace(c, n.info, errFieldXNotFound, "intVal")
result = emptyNode result = emptyNode
of mNSetFloatVal: of mNSetFloatVal:
result = evalAux(c, n.sons[1], {efLValue}) result = evalAux(c, n.sons[1], {efLValue})
@ -1209,7 +1182,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result.kind in {nkFloatLit..nkFloat64Lit}: result.kind in {nkFloatLit..nkFloat64Lit}:
a.floatVal = result.floatVal a.floatVal = result.floatVal
else: else:
stackTrace(c, n, errFieldXNotFound, "floatVal") stackTrace(c, n.info, errFieldXNotFound, "floatVal")
result = emptyNode result = emptyNode
of mNSetSymbol: of mNSetSymbol:
result = evalAux(c, n.sons[1], {efLValue}) 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: if a.kind == nkSym and result.kind == nkSym:
a.sym = result.sym a.sym = result.sym
else: else:
stackTrace(c, n, errFieldXNotFound, "symbol") stackTrace(c, n.info, errFieldXNotFound, "symbol")
result = emptyNode result = emptyNode
of mNSetIdent: of mNSetIdent:
result = evalAux(c, n.sons[1], {efLValue}) 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: if a.kind == nkIdent and result.kind == nkIdent:
a.ident = result.ident a.ident = result.ident
else: else:
stackTrace(c, n, errFieldXNotFound, "ident") stackTrace(c, n.info, errFieldXNotFound, "ident")
result = emptyNode result = emptyNode
of mNSetType: of mNSetType:
result = evalAux(c, n.sons[1], {efLValue}) 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 if a.kind in {nkStrLit..nkTripleStrLit} and
result.kind in {nkStrLit..nkTripleStrLit}: result.kind in {nkStrLit..nkTripleStrLit}:
a.strVal = result.strVal a.strVal = result.strVal
else: stackTrace(c, n, errFieldXNotFound, "strVal") else: stackTrace(c, n.info, errFieldXNotFound, "strVal")
result = emptyNode result = emptyNode
of mNNewNimNode: of mNNewNimNode:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
@ -1280,7 +1253,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
if not (result.kind in {nkStrLit..nkTripleStrLit}): if not (result.kind in {nkStrLit..nkTripleStrLit}):
stackTrace(c, n, errFieldXNotFound, "strVal") stackTrace(c, n.info, errFieldXNotFound, "strVal")
return return
var a = result var a = result
result = newNodeIT(nkIdent, n.info, n.typ) result = newNodeIT(nkIdent, n.info, n.typ)
@ -1333,7 +1306,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of mNError: of mNError:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
stackTrace(c, n, errUser, getStrValue(result)) stackTrace(c, n.info, errUser, getStrValue(result))
result = emptyNode result = emptyNode
of mConStrStr: of mConStrStr:
result = evalConStrStr(c, n) result = evalConStrStr(c, n)
@ -1353,7 +1326,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result.strVal = newString(0) result.strVal = newString(0)
of mNCallSite: of mNCallSite:
if c.callsite != nil: result = c.callsite if c.callsite != nil: result = c.callsite
else: stackTrace(c, n, errFieldXNotFound, "callsite") else: stackTrace(c, n.info, errFieldXNotFound, "callsite")
else: else:
result = evalAux(c, n.sons[1], {}) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
@ -1374,7 +1347,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = emptyNode result = emptyNode
dec(gNestedEvals) dec(gNestedEvals)
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations) if gNestedEvals <= 0: stackTrace(c, n.info, errTooManyIterations)
case n.kind case n.kind
of nkSym: result = evalSym(c, n, flags) of nkSym: result = evalSym(c, n, flags)
of nkType..nkNilLit: of nkType..nkNilLit:
@ -1473,6 +1446,7 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = n result = n
else: InternalError(n.info, "evalAux: " & $n.kind) else: InternalError(n.info, "evalAux: " & $n.kind)
if result == nil: if result == nil:
debug n
InternalError(n.info, "evalAux: returned nil " & $n.kind) InternalError(n.info, "evalAux: returned nil " & $n.kind)
inc(gNestedEvals) inc(gNestedEvals)
@ -1489,9 +1463,9 @@ proc eval*(c: PEvalContext, n: PNode): PNode =
result = tryEval(c, n) result = tryEval(c, n)
if result.kind == nkExceptBranch: if result.kind == nkExceptBranch:
if sonsLen(result) >= 1: if sonsLen(result) >= 1:
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) stackTrace(c, n.info, errUnhandledExceptionX, typeToString(result.typ))
else: else:
stackTrace(c, result, errCannotInterpretNodeX, renderTree(n)) stackTrace(c, result.info, errCannotInterpretNodeX, renderTree(n))
proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode = proc evalConstExprAux(module, prc: PSym, e: PNode, mode: TEvalMode): PNode =
var p = newEvalContext(module, mode) var p = newEvalContext(module, mode)
@ -1531,7 +1505,7 @@ proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
# setup parameters: # setup parameters:
for i in 1 .. < L: s.slots[i] = setupMacroParam(n.sons[i]) for i in 1 .. < L: s.slots[i] = setupMacroParam(n.sons[i])
pushStackFrame(c, s) pushStackFrame(c, s)
discard eval(c, sym.getBody) discard eval(c, optBody(c, sym))
result = s.slots[0] result = s.slots[0]
popStackFrame(c) popStackFrame(c)
if cyclicTree(result): GlobalError(n.info, errCyclicTree) if cyclicTree(result): GlobalError(n.info, errCyclicTree)

View file

@ -491,20 +491,13 @@ proc factImplies(fact, prop: PNode): TImplication =
else: discard else: discard
case prop.sons[0].sym.magic case prop.sons[0].sym.magic
of mNot: of mNot: result = ~fact.factImplies(prop.sons[1])
result = ~fact.factImplies(prop.sons[1]) of mIsNil: result = impliesIsNil(fact, prop)
of mIsNil: of someEq: result = impliesEq(fact, prop)
result = impliesIsNil(fact, prop) of someLe: result = impliesLe(fact, prop.sons[1], prop.sons[2])
of someEq: of someLt: result = impliesLt(fact, prop.sons[1], prop.sons[2])
result = impliesEq(fact, prop) of mInSet: result = impliesIn(fact, prop.sons[2], prop.sons[1])
of someLe: else: internalError(prop.info, "invalid proposition")
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 = proc doesImply*(facts: TModel, prop: PNode): TImplication =
assert prop.kind in nkCallKinds assert prop.kind in nkCallKinds

View file

@ -118,8 +118,7 @@ proc mapType(typ: PType): TJSTypeKind =
of tyPointer: of tyPointer:
# treat a tyPointer like a typed pointer to an array of bytes # treat a tyPointer like a typed pointer to an array of bytes
result = etyInt result = etyInt
of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyIter, of tyRange, tyDistinct, tyOrdinal, tyConst, tyMutable, tyIter, tyProxy:
tyProxy:
result = mapType(t.sons[0]) result = mapType(t.sons[0])
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
of tyBool: result = etyBool of tyBool: result = etyBool
@ -826,17 +825,18 @@ proc genSwap(p: PProc, n: PNode) =
gen(p, n.sons[1], a) gen(p, n.sons[1], a)
gen(p, n.sons[2], b) gen(p, n.sons[2], b)
inc(p.unique) inc(p.unique)
let tmp = ropef("Tmp$1", [toRope(p.unique)]) var tmp = ropef("Tmp$1", [toRope(p.unique)])
case mapType(skipTypes(n.sons[1].typ, abstractVar)) if mapType(skipTypes(n.sons[1].typ, abstractVar)) == etyBaseIndex:
of etyBaseIndex:
inc(p.unique) inc(p.unique)
let tmp2 = ropef("Tmp$1", [toRope(p.unique)]) let tmp2 = ropef("Tmp$1", [toRope(p.unique)])
if a.typ != etyBaseIndex or b.typ != etyBaseIndex: if a.typ != etyBaseIndex or b.typ != etyBaseIndex:
internalError(n.info, "genSwap") 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;$n" |
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1", [tmp2, a.res, b.res]) "local $1 = $2; $2 = $3; $3 = $1;$n", [
else: tmp, a.address, b.address])
appf(p.body, "var $1 = $2; $2 = $3; $3 = $1", [tmp, a.res, b.res]) 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 = proc getFieldPosition(f: PNode): int =
case f.kind 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.locals)
app(p.g.code, p.body) 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 = proc myClose(b: PPassContext, n: PNode): PNode =
if passes.skipCodegen(n): return n if passes.skipCodegen(n): return n
result = myProcess(b, n) result = myProcess(b, n)
var m = BModule(b) var m = BModule(b)
if sfMainModule in m.module.flags: if sfMainModule in m.module.flags:
for prc in globals.forwarded: let code = wholeCode(m)
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)
var outfile = changeFileExt(completeCFilePath(m.module.filename), "js") var outfile = changeFileExt(completeCFilePath(m.module.filename), "js")
discard writeRopeIfNotEqual(con(genHeader(), code), outfile) discard writeRopeIfNotEqual(con(genHeader(), code), outfile)

View file

@ -341,6 +341,18 @@ proc CommandInteractive =
incl(m.flags, sfMainModule) incl(m.flags, sfMainModule)
processModule(m, LLStreamOpenStdIn(), nil) 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] const evalPasses = [verbosePass, semPass, evalPass]
proc evalNim(nodes: PNode, module: PSym) = proc evalNim(nodes: PNode, module: PSym) =

View file

@ -24,7 +24,7 @@ const
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGenSym, wInject, wRaises, wTags} wGenSym, wInject, wRaises, wTags, wOperator}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas methodPragmas* = procPragmas
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty} templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty}
@ -34,7 +34,7 @@ const
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect, iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises, wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises,
wTags} wTags, wOperator}
exprPragmas* = {wLine} exprPragmas* = {wLine}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, 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) if sym == nil: invalidPragma(it)
of wLine: PragmaLine(c, it) of wLine: PragmaLine(c, it)
of wRaises, wTags: pragmaRaisesOrTags(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: invalidPragma(it) else: invalidPragma(it)
else: processNote(c, it) else: processNote(c, it)

View file

@ -620,7 +620,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
{skProc, skMethod, skConverter, skMacro, skTemplate}) {skProc, skMethod, skConverter, skMacro, skTemplate})
if result != nil: if result != nil:
if result.sons[0].kind != nkSym: if result.sons[0].kind != nkSym:
InternalError("semDirectCallAnalyseEffects") InternalError("semOverloadedCallAnalyseEffects")
return return
let callee = result.sons[0].sym let callee = result.sons[0].sym
case callee.kind case callee.kind
@ -632,10 +632,6 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
if {sfImportc, sfSideEffect} * callee.flags != {}: if {sfImportc, sfSideEffect} * callee.flags != {}:
incl(c.p.owner.flags, sfSideEffect) 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 semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = nil result = nil
@ -707,12 +703,28 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
LocalError(n.info, errExprXCannotBeCalled, LocalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))
return errorNode(c, n) return errorNode(c, n)
#result = afterCallActions(c, result, nOrig, flags)
fixAbstractType(c, result) fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result) analyseIfAddressTakenInCall(c, result)
if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone: if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags) result = magicsAfterOverloadResolution(c, result, flags)
result = evalAtCompileTime(c, result) 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 = proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# this seems to be a hotspot in the compiler! # this seems to be a hotspot in the compiler!
let nOrig = n.copyTree let nOrig = n.copyTree
@ -723,18 +735,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if result == nil: if result == nil:
NotFoundError(c, n) NotFoundError(c, n)
return errorNode(c, n) return errorNode(c, n)
let callee = result.sons[0].sym result = afterCallActions(c, result, nOrig, flags)
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)
proc buildStringify(c: PContext, arg: PNode): PNode = proc buildStringify(c: PContext, arg: PNode): PNode =
if arg.typ != nil and if arg.typ != nil and
@ -928,30 +929,33 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = n result = n
markUsed(n, f) 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 = proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# this is difficult, because the '.' is used in many different contexts # this is difficult, because the '.' is used in many different contexts
# in Nimrod. We first allow types in the semantic checking. # in Nimrod. We first allow types in the semantic checking.
result = builtinFieldAccess(c, n, flags) result = builtinFieldAccess(c, n, flags)
if result == nil: if result == nil:
if isSymChoice(n.sons[1]): result = dotTransformation(c, n)
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 buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode = proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
result = newNodeI(nkCall, n.info) result = newNodeI(nkCall, n.info)
@ -1030,14 +1034,12 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
let aOrig = nOrig[0] let aOrig = nOrig[0]
result = newNode(nkCall, n.info, sons = @[setterId, a[0], semExpr(c, n[1])]) 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]]) 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: if result != nil:
fixAbstractType(c, result) result = afterCallActions(c, result, nOrig, {})
analyseIfAddressTakenInCall(c, result) #fixAbstractType(c, result)
else: #analyseIfAddressTakenInCall(c, result)
if not ContainsOrIncl(c.UnknownIdents, id.id):
LocalError(n.Info, errUndeclaredFieldX, id.s)
result = errorNode(c, n)
proc takeImplicitAddr(c: PContext, n: PNode): PNode = proc takeImplicitAddr(c: PContext, n: PNode): PNode =
case n.kind case n.kind
@ -1072,7 +1074,14 @@ proc semAsgn(c: PContext, n: PNode): PNode =
let nOrig = n.copyTree let nOrig = n.copyTree
a = builtinFieldAccess(c, a, {efLValue}) a = builtinFieldAccess(c, a, {efLValue})
if a == nil: 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: of nkBracketExpr:
# a[i] = x # a[i] = x
# --> `[]=`(a, i, x) # --> `[]=`(a, i, x)

View file

@ -101,7 +101,7 @@ proc normalize*(s: string): string {.noSideEffect, procvar,
if j != s.len: setLen(result, j) if j != s.len: setLen(result, j)
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect, 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: ## Compares two strings in a case insensitive manner. Returns:
## ##
## | 0 iff a == b ## | 0 iff a == b
@ -119,7 +119,7 @@ proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
# thus we compile without checks here # thus we compile without checks here
proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect, 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 ## Compares two strings normalized (i.e. case and
## underscores do not matter). Returns: ## underscores do not matter). Returns:
## ##
@ -141,7 +141,7 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
{.pop.} {.pop.}
proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, 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. ## Strips whitespace from `s` and returns the resulting string.
## If `leading` is true, leading whitespace is stripped. ## If `leading` is true, leading whitespace is stripped.
## If `trailing` is true, trailing 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 return -1
proc find*(s, sub: string, start: int = 0): int {.noSideEffect, 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 ## Searches for `sub` in `s` starting at position `start`. Searching is
## case-sensitive. If `sub` is not in `s`, -1 is returned. ## case-sensitive. If `sub` is not in `s`, -1 is returned.
var a {.noinit.}: TSkipTable var a {.noinit.}: TSkipTable
@ -723,7 +723,7 @@ proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} =
return find(s, chars) >= 0 return find(s, chars) >= 0
proc replace*(s, sub: string, by = ""): string {.noSideEffect, proc replace*(s, sub: string, by = ""): string {.noSideEffect,
rtl, extern: "nsuReplaceStr".} = rtl, extern: "nsuReplaceStr", operator: 1.} =
## Replaces `sub` in `s` by the string `by`. ## Replaces `sub` in `s` by the string `by`.
var a {.noinit.}: TSkipTable var a {.noinit.}: TSkipTable
result = "" result = ""
@ -1023,7 +1023,7 @@ type
ffScientific ## use scientific notation (using ``e`` character) ffScientific ## use scientific notation (using ``e`` character)
proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
precision = 16): string {.noSideEffect, precision = 16): string {.noSideEffect, operator: 2,
rtl, extern: "nsu$1".} = rtl, extern: "nsu$1".} =
## converts a floating point value `f` to a string. ## converts a floating point value `f` to a string.
## ##
@ -1054,7 +1054,7 @@ proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault,
result = $buf result = $buf
proc formatFloat*(f: float, format: TFloatFormat = ffDefault, proc formatFloat*(f: float, format: TFloatFormat = ffDefault,
precision = 16): string {.noSideEffect, precision = 16): string {.noSideEffect, operator: 2,
rtl, extern: "nsu$1".} = rtl, extern: "nsu$1".} =
## converts a floating point value `f` to a string. ## converts a floating point value `f` to a string.
## ##

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2013 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -42,3 +42,5 @@ else:
{.pragma: inl, inline.} {.pragma: inl, inline.}
{.pragma: compilerRtl, compilerproc.} {.pragma: compilerRtl, compilerproc.}
when not defined(nimsuperops):
{.pragma: operator.}