bugfix: macro evaluation; added colors.extractRGB

This commit is contained in:
Andreas Rumpf 2010-03-04 23:42:19 +01:00
commit f45a2f23b0
8 changed files with 190 additions and 154 deletions

View file

@ -196,9 +196,23 @@ Cryptography and Hashing
This module implements the MD5 checksum algorithm. This module implements the MD5 checksum algorithm.
Multimedia support
------------------
* `colors <colors.html>`_
This module implements color handling for Nimrod. It is used by
the ``graphics`` module.
Impure libraries Impure libraries
================ ================
* `graphics <graphics>`_
This module implements graphical output for Nimrod; the current
implementation uses SDL but the interface is meant to support multiple
backends some day.
* `dialogs <dialogs.html>`_ * `dialogs <dialogs.html>`_
This module implements portable dialogs for Nimrod; the implementation This module implements portable dialogs for Nimrod; the implementation
builds on the GTK interface. On Windows, native dialogs are shown if builds on the GTK interface. On Windows, native dialogs are shown if

View file

@ -150,7 +150,7 @@ proc drawLine*(sur: PSurface, p1, p2: TPoint, color: TColor) =
setPix(video, pitch, x0, y0, color) setPix(video, pitch, x0, y0, color)
proc drawHorLine*(sur: PSurface, x, y, w: Natural, Color: TColor) = proc drawHorLine*(sur: PSurface, x, y, w: Natural, Color: TColor) =
## draws a horizontal line from (x,y) to (x+w-1, h). ## draws a horizontal line from (x,y) to (x+w-1, y).
var video = cast[PPixels](sur.s.pixels) var video = cast[PPixels](sur.s.pixels)
var pitch = sur.s.pitch div ColSize var pitch = sur.s.pitch div ColSize
for i in 0 .. w-1: setPix(video, pitch, x + i, y, color) for i in 0 .. w-1: setPix(video, pitch, x + i, y, color)

View file

@ -6,8 +6,8 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## This module implements graphical output for Nimrod; the current ## This module implements color handling for Nimrod. It is used by
## implementation uses Cairo under the surface. ## the ``graphics`` module.
import strutils import strutils
@ -53,6 +53,12 @@ proc `-`*(a, b: TColor): TColor =
## component cannot overflow (255 is used as a maximum). ## component cannot overflow (255 is used as a maximum).
colorOp(satMinus) colorOp(satMinus)
proc extractRGB*(a: TColor): tuple[r, g, b: range[0..255]] =
## extracts the red/green/blue components of the color `a`.
result.r = a.int shr 16 and 0xff
result.g = a.int shr 8 and 0xff
result.b = a.int and 0xff
template mix*(a, b: TColor, fn: expr): expr = template mix*(a, b: TColor, fn: expr): expr =
## uses `fn` to mix the colors `a` and `b`. `fn` is invoked for each component ## uses `fn` to mix the colors `a` and `b`. `fn` is invoked for each component
## R, G, and B. This is a template because `fn` should be inlined and the ## R, G, and B. This is a template because `fn` should be inlined and the

View file

@ -172,6 +172,8 @@ when not defined(ECMAScript):
proc randomize() = srand(gettime(nil)) proc randomize() = srand(gettime(nil))
proc random(max: int): int = return int(rand()) mod max proc random(max: int): int = return int(rand()) mod max
proc trunc*(x: float): float {.importc: "trunc", nodecl.}
else: else:
proc mathrandom(): float {.importc: "Math.random", nodecl.} proc mathrandom(): float {.importc: "Math.random", nodecl.}
proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.} proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.}

View file

@ -162,15 +162,11 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
## produces the same output. ## produces the same output.
var last = 0 var last = 0
assert(not ('\0' in seps)) assert(not ('\0' in seps))
#echo "cam here 1", s
while last < len(s): while last < len(s):
while s[last] in seps: inc(last) while s[last] in seps: inc(last)
var first = last var first = last
#echo "A first: ", first, " last: ", last
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX! while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
#echo "B first: ", first, " last: ", last
if first <= last-1: if first <= last-1:
echo copy(s, first, last-1)
yield copy(s, first, last-1) yield copy(s, first, last-1)
iterator split*(s: string, sep: char): string = iterator split*(s: string, sep: char): string =

View file

@ -34,6 +34,11 @@ type
PEvalContext* = ref TEvalContext PEvalContext* = ref TEvalContext
TEvalFlag = enum
efNone, efLValue
TEvalFlags = set[TEvalFlag]
proc newStackFrame*(): PStackFrame proc newStackFrame*(): PStackFrame
proc pushStackFrame*(c: PEvalContext, t: PStackFrame) proc pushStackFrame*(c: PEvalContext, t: PStackFrame)
proc popStackFrame*(c: PEvalContext) proc popStackFrame*(c: PEvalContext)
@ -70,7 +75,7 @@ proc popStackFrame(c: PEvalContext) =
if (c.tos == nil): InternalError("popStackFrame") if (c.tos == nil): InternalError("popStackFrame")
c.tos = c.tos.next c.tos = c.tos.next
proc evalAux(c: PEvalContext, n: PNode): PNode proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
proc stackTraceAux(x: PStackFrame) = proc stackTraceAux(x: PStackFrame) =
if x != nil: if x != nil:
@ -93,18 +98,18 @@ 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]) result = evalAux(c, n.sons[i].sons[0], {})
if isSpecial(result): return 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):
result = evalAux(c, n.sons[i].sons[0]) result = evalAux(c, n.sons[i].sons[0], {})
else: else:
result = emptyNode result = emptyNode
proc evalCase(c: PEvalContext, n: PNode): PNode = proc evalCase(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {})
if isSpecial(result): return if isSpecial(result): return
var res = result var res = result
result = emptyNode result = emptyNode
@ -112,9 +117,9 @@ proc evalCase(c: PEvalContext, n: PNode): PNode =
if n.sons[i].kind == nkOfBranch: if n.sons[i].kind == nkOfBranch:
for j in countup(0, sonsLen(n.sons[i]) - 2): for j in countup(0, sonsLen(n.sons[i]) - 2):
if overlap(res, n.sons[i].sons[j]): if overlap(res, n.sons[i].sons[j]):
return evalAux(c, lastSon(n.sons[i])) return evalAux(c, lastSon(n.sons[i]), {})
else: else:
result = evalAux(c, lastSon(n.sons[i])) result = evalAux(c, lastSon(n.sons[i]), {})
var var
gWhileCounter: int # Use a counter to prevent endless loops! gWhileCounter: int # Use a counter to prevent endless loops!
@ -125,10 +130,10 @@ 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]) result = evalAux(c, n.sons[0], {})
if isSpecial(result): return 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
of nkBreakStmt: of nkBreakStmt:
if result.sons[0] == nil: if result.sons[0] == nil:
@ -144,7 +149,7 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
break break
proc evalBlock(c: PEvalContext, n: PNode): PNode = proc evalBlock(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if result.kind == nkBreakStmt: if result.kind == nkBreakStmt:
if result.sons[0] != nil: if result.sons[0] != nil:
assert(result.sons[0].kind == nkSym) assert(result.sons[0].kind == nkSym)
@ -157,13 +162,13 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
proc evalFinally(c: PEvalContext, n, exc: PNode): PNode = proc evalFinally(c: PEvalContext, n, exc: PNode): PNode =
var finallyNode = lastSon(n) var finallyNode = lastSon(n)
if finallyNode.kind == nkFinally: if finallyNode.kind == nkFinally:
result = evalAux(c, finallyNode) result = evalAux(c, finallyNode, {})
if result.kind != nkExceptBranch: result = exc if result.kind != nkExceptBranch: result = exc
else: else:
result = exc result = exc
proc evalTry(c: PEvalContext, n: PNode): PNode = proc evalTry(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {})
case result.kind case result.kind
of nkBreakStmt, nkReturnToken: of nkBreakStmt, nkReturnToken:
nil nil
@ -178,14 +183,14 @@ proc evalTry(c: PEvalContext, n: PNode): PNode =
var blen = sonsLen(n.sons[i]) var blen = sonsLen(n.sons[i])
if blen == 1: if blen == 1:
# general except section: # general except section:
result = evalAux(c, n.sons[i].sons[0]) result = evalAux(c, n.sons[i].sons[0], {})
exc = result exc = result
break break
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: if exc.typ.id == n.sons[i].sons[j].typ.id:
result = evalAux(c, n.sons[i].sons[blen - 1]) result = evalAux(c, n.sons[i].sons[blen - 1], {})
exc = result exc = result
break break
inc(i) inc(i)
@ -224,7 +229,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
assert(a.sons[0].kind == nkSym) assert(a.sons[0].kind == nkSym)
var v = a.sons[0].sym var v = a.sons[0].sym
if a.sons[2] != nil: if a.sons[2] != nil:
result = evalAux(c, a.sons[2]) result = evalAux(c, a.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
else: else:
result = getNullValue(a.sons[0].typ, a.sons[0].info) result = getNullValue(a.sons[0].typ, a.sons[0].info)
@ -232,7 +237,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalCall(c: PEvalContext, n: PNode): PNode = proc evalCall(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {})
if isSpecial(result): return if isSpecial(result): return
var prc = result var prc = result
# bind the actual params to the local parameter of a new binding # bind the actual params to the local parameter of a new binding
@ -244,17 +249,17 @@ proc evalCall(c: PEvalContext, n: PNode): PNode =
InternalError(n.info, "evalCall") InternalError(n.info, "evalCall")
setlen(d.params, sonsLen(n)) setlen(d.params, sonsLen(n))
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
result = evalAux(c, n.sons[i]) result = evalAux(c, n.sons[i], {})
if isSpecial(result): return if isSpecial(result): return
d.params[i] = result d.params[i] = result
if n.typ != nil: d.params[0] = getNullValue(n.typ, n.info) if n.typ != nil: d.params[0] = getNullValue(n.typ, n.info)
pushStackFrame(c, d) pushStackFrame(c, d)
result = evalAux(c, prc) result = evalAux(c, prc, {})
if result.kind == nkExceptBranch: return if result.kind == nkExceptBranch: return
if n.typ != nil: result = d.params[0] if n.typ != nil: result = d.params[0]
popStackFrame(c) popStackFrame(c)
proc evalVariable(c: PStackFrame, sym: PSym): PNode = proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode =
# We need to return a node to the actual value, # We need to return a node to the actual value,
# which can be modified. # which can be modified.
var x = c var x = c
@ -264,15 +269,16 @@ proc evalVariable(c: PStackFrame, sym: PSym): PNode =
if result == nil: result = emptyNode if result == nil: result = emptyNode
return return
result = IdNodeTableGet(x.mapping, sym) result = IdNodeTableGet(x.mapping, sym)
if efLValue notin flags: result = copyTree(result)
if result != nil: return if result != nil: return
x = x.next x = x.next
result = emptyNode result = emptyNode
proc evalArrayAccess(c: PEvalContext, n: PNode): PNode = proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], flags)
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var idx = getOrdValue(result) var idx = getOrdValue(result)
result = emptyNode result = emptyNode
@ -280,7 +286,10 @@ proc evalArrayAccess(c: PEvalContext, n: PNode): PNode =
of nkBracket, nkPar, nkMetaNode: of nkBracket, nkPar, nkMetaNode:
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)] if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
else: stackTrace(c, n, errIndexOutOfBounds) else: stackTrace(c, n, errIndexOutOfBounds)
if efLValue notin flags: result = copyTree(result)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if efLValue in flags:
InternalError(n.info, "cannot evaluate write access to char")
result = newNodeIT(nkCharLit, x.info, getSysType(tyChar)) result = newNodeIT(nkCharLit, x.info, getSysType(tyChar))
if (idx >= 0) and (idx < len(x.strVal)): if (idx >= 0) and (idx < len(x.strVal)):
result.intVal = ord(x.strVal[int(idx) + 0]) result.intVal = ord(x.strVal[int(idx) + 0])
@ -290,11 +299,11 @@ proc evalArrayAccess(c: PEvalContext, n: PNode): PNode =
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n, errIndexOutOfBounds)
else: stackTrace(c, n, errNilAccess) else: stackTrace(c, n, errNilAccess)
proc evalFieldAccess(c: PEvalContext, n: PNode): PNode = proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
# a real field access; proc calls have already been # a real field access; proc calls have already been
# transformed # transformed
# XXX: field checks! # XXX: field checks!
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], flags)
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
if x.kind != nkPar: InternalError(n.info, "evalFieldAccess") if x.kind != nkPar: InternalError(n.info, "evalFieldAccess")
@ -303,15 +312,17 @@ proc evalFieldAccess(c: PEvalContext, n: PNode): PNode =
if x.sons[i].kind != nkExprColonExpr: if x.sons[i].kind != nkExprColonExpr:
InternalError(n.info, "evalFieldAccess") InternalError(n.info, "evalFieldAccess")
if x.sons[i].sons[0].sym.name.id == field.id: if x.sons[i].sons[0].sym.name.id == field.id:
return x.sons[i].sons[1] result = x.sons[i].sons[1]
if efLValue in flags: result = copyTree(result)
return
stackTrace(c, n, errFieldXNotFound, field.name.s) stackTrace(c, n, errFieldXNotFound, field.name.s)
result = emptyNode result = emptyNode
proc evalAsgn(c: PEvalContext, n: PNode): PNode = proc evalAsgn(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
x.kind = result.kind x.kind = result.kind
x.typ = result.typ x.typ = result.typ
@ -329,10 +340,10 @@ proc evalAsgn(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalSwap(c: PEvalContext, n: PNode): PNode = proc evalSwap(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
if (x.kind != result.kind): if (x.kind != result.kind):
stackTrace(c, n, errCannotInterpretNodeX, $n.kind) stackTrace(c, n, errCannotInterpretNodeX, $n.kind)
@ -358,11 +369,13 @@ proc evalSwap(c: PEvalContext, n: PNode): PNode =
for i in countup(0, sonsLen(tmpn) - 1): addSon(result, tmpn.sons[i]) for i in countup(0, sonsLen(tmpn) - 1): addSon(result, tmpn.sons[i])
result = emptyNode result = emptyNode
proc evalSym(c: PEvalContext, n: PNode): PNode = proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
case n.sym.kind case n.sym.kind
of skProc, skConverter, skMacro: result = n.sym.ast.sons[codePos] of skProc, skConverter, skMacro: result = n.sym.ast.sons[codePos]
of skVar, skForVar, skTemp: result = evalVariable(c.tos, n.sym) of skVar, skForVar, skTemp: result = evalVariable(c.tos, n.sym, flags)
of skParam: result = c.tos.params[n.sym.position + 1] of skParam:
# XXX what about LValue?
result = c.tos.params[n.sym.position + 1]
of skConst: result = n.sym.ast of skConst: result = n.sym.ast
else: else:
stackTrace(c, n, errCannotInterpretNodeX, $n.sym.kind) stackTrace(c, n, errCannotInterpretNodeX, $n.sym.kind)
@ -370,10 +383,10 @@ proc evalSym(c: PEvalContext, n: PNode): PNode =
if result == nil: stackTrace(c, n, errCannotInterpretNodeX, n.sym.name.s) if result == nil: stackTrace(c, n, errCannotInterpretNodeX, n.sym.name.s)
proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode = proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
case a.kind case a.kind
@ -390,29 +403,29 @@ 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]) result = evalAux(c, n.sons[i], {})
if isSpecial(result): return 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 =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
liMessage(n.info, hintQuitCalled) liMessage(n.info, hintQuitCalled)
quit(int(getOrdValue(result))) quit(int(getOrdValue(result)))
proc evalOr(c: PEvalContext, n: PNode): PNode = proc evalOr(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
if result.kind != nkIntLit: InternalError(n.info, "evalOr") if result.kind != nkIntLit: InternalError(n.info, "evalOr")
if result.intVal == 0: result = evalAux(c, n.sons[2]) if 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]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
if result.kind != nkIntLit: InternalError(n.info, "evalAnd") if result.kind != nkIntLit: InternalError(n.info, "evalAnd")
if result.intVal != 0: result = evalAux(c, n.sons[2]) if result.intVal != 0: result = evalAux(c, n.sons[2], {})
proc evalNoOpt(c: PEvalContext, n: PNode): PNode = proc evalNoOpt(c: PEvalContext, n: PNode): PNode =
result = newNodeI(nkExceptBranch, n.info) result = newNodeI(nkExceptBranch, n.info)
@ -426,16 +439,18 @@ proc evalNew(c: PEvalContext, n: PNode): PNode =
result = newNodeIT(nkRefTy, n.info, t) result = newNodeIT(nkRefTy, n.info, t)
addSon(result, getNullValue(t.sons[0], n.info)) addSon(result, getNullValue(t.sons[0], n.info))
proc evalDeref(c: PEvalContext, n: PNode): PNode = proc evalDeref(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {efLValue})
if isSpecial(result): return if isSpecial(result): return
case result.kind case result.kind
of nkNilLit: stackTrace(c, n, errNilAccess) of nkNilLit: stackTrace(c, n, errNilAccess)
of nkRefTy: result = result.sons[0] of nkRefTy:
# XXX efLValue?
result = result.sons[0]
else: InternalError(n.info, "evalDeref " & $result.kind) else: InternalError(n.info, "evalDeref " & $result.kind)
proc evalAddr(c: PEvalContext, n: PNode): PNode = proc evalAddr(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
var t = newType(tyPtr, c.module) var t = newType(tyPtr, c.module)
@ -445,14 +460,15 @@ proc evalAddr(c: PEvalContext, n: PNode): PNode =
proc evalConv(c: PEvalContext, n: PNode): PNode = proc evalConv(c: PEvalContext, n: PNode): PNode =
# hm, I cannot think of any conversions that need to be handled here... # hm, I cannot think of any conversions that need to be handled here...
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
result.typ = n.typ result.typ = n.typ
proc evalCheckedFieldAccess(c: PEvalContext, n: PNode): PNode = proc evalCheckedFieldAccess(c: PEvalContext, n: PNode,
result = evalAux(c, n.sons[0]) flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0], flags)
proc evalUpConv(c: PEvalContext, n: PNode): PNode = proc evalUpConv(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], flags)
if isSpecial(result): return if isSpecial(result): return
var dest = skipTypes(n.typ, abstractPtrs) var dest = skipTypes(n.typ, abstractPtrs)
var src = skipTypes(result.typ, abstractPtrs) var src = skipTypes(result.typ, abstractPtrs)
@ -460,13 +476,13 @@ proc evalUpConv(c: PEvalContext, n: PNode): PNode =
stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src)) stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src))
proc evalRangeChck(c: PEvalContext, n: PNode): PNode = proc evalRangeChck(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {})
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return 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):
@ -477,18 +493,18 @@ proc evalRangeChck(c: PEvalContext, n: PNode): PNode =
typeToString(n.sons[0].typ), typeToString(n.typ)])) 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], {})
if isSpecial(result): return if isSpecial(result): return
result.typ = n.typ result.typ = n.typ
proc evalConvCStrToStr(c: PEvalContext, n: PNode): PNode = proc evalConvCStrToStr(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {})
if isSpecial(result): return if isSpecial(result): return
result.typ = n.typ result.typ = n.typ
proc evalRaise(c: PEvalContext, n: PNode): PNode = proc evalRaise(c: PEvalContext, n: PNode): PNode =
if n.sons[0] != nil: if n.sons[0] != nil:
result = evalAux(c, n.sons[0]) result = evalAux(c, n.sons[0], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkExceptBranch, n.info, a.typ) result = newNodeIT(nkExceptBranch, n.info, a.typ)
@ -513,18 +529,18 @@ proc evalProc(c: PEvalContext, n: PNode): PNode =
var v = n.sons[resultPos].sym var v = n.sons[resultPos].sym
result = getNullValue(v.typ, n.info) result = getNullValue(v.typ, n.info)
IdNodeTablePut(c.tos.mapping, v, result) IdNodeTablePut(c.tos.mapping, v, result)
result = evalAux(c, n.sons[codePos]) result = evalAux(c, n.sons[codePos], {})
if result.kind == nkReturnToken: if result.kind == nkReturnToken:
result = IdNodeTableGet(c.tos.mapping, v) result = IdNodeTableGet(c.tos.mapping, v)
else: else:
result = evalAux(c, n.sons[codePos]) result = evalAux(c, n.sons[codePos], {})
if result.kind == nkReturnToken: if result.kind == nkReturnToken:
result = emptyNode result = emptyNode
else: else:
result = emptyNode result = emptyNode
proc evalHigh(c: PEvalContext, n: PNode): PNode = proc evalHigh(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
case skipTypes(n.sons[1].typ, abstractVar).kind case skipTypes(n.sons[1].typ, abstractVar).kind
of tyOpenArray, tySequence: result = newIntNodeT(sonsLen(result), n) of tyOpenArray, tySequence: result = newIntNodeT(sonsLen(result), n)
@ -532,15 +548,15 @@ proc evalHigh(c: PEvalContext, n: PNode): PNode =
else: InternalError(n.info, "evalHigh") else: InternalError(n.info, "evalHigh")
proc evalIs(c: PEvalContext, n: PNode): PNode = proc evalIs(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
result = newIntNodeT(ord(inheritanceDiff(result.typ, n.sons[2].typ) >= 0), n) result = newIntNodeT(ord(inheritanceDiff(result.typ, n.sons[2].typ) >= 0), n)
proc evalSetLengthStr(c: PEvalContext, n: PNode): PNode = proc evalSetLengthStr(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
case a.kind case a.kind
@ -551,10 +567,10 @@ proc evalSetLengthStr(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalSetLengthSeq(c: PEvalContext, n: PNode): PNode = proc evalSetLengthSeq(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
if a.kind != nkBracket: InternalError(n.info, "evalSetLengthSeq") if a.kind != nkBracket: InternalError(n.info, "evalSetLengthSeq")
@ -566,10 +582,10 @@ proc evalSetLengthSeq(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalNewSeq(c: PEvalContext, n: PNode): PNode = proc evalNewSeq(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
var t = skipTypes(n.sons[1].typ, abstractVar) var t = skipTypes(n.sons[1].typ, abstractVar)
@ -582,26 +598,26 @@ proc evalNewSeq(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalAssert(c: PEvalContext, n: PNode): PNode = proc evalAssert(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 getOrdValue(result) != 0: result = emptyNode if getOrdValue(result) != 0: result = emptyNode
else: stackTrace(c, n, errAssertionFailed) else: stackTrace(c, n, errAssertionFailed)
proc evalIncl(c: PEvalContext, n: PNode): PNode = proc evalIncl(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
if not inSet(a, b): addSon(a, copyTree(b)) if not inSet(a, b): addSon(a, copyTree(b))
result = emptyNode result = emptyNode
proc evalExcl(c: PEvalContext, n: PNode): PNode = proc evalExcl(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = newNodeIT(nkCurly, n.info, n.sons[1].typ) var b = newNodeIT(nkCurly, n.info, n.sons[1].typ)
addSon(b, result) addSon(b, result)
@ -611,10 +627,10 @@ proc evalExcl(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalAppendStrCh(c: PEvalContext, n: PNode): PNode = proc evalAppendStrCh(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
case a.kind case a.kind
@ -624,20 +640,20 @@ proc evalAppendStrCh(c: PEvalContext, n: PNode): PNode =
proc evalConStrStr(c: PEvalContext, n: PNode): PNode = proc evalConStrStr(c: PEvalContext, n: PNode): PNode =
# we cannot use ``evalOp`` for this as we can here have more than 2 arguments # we cannot use ``evalOp`` for this as we can here have more than 2 arguments
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
for i in countup(2, sonsLen(n) - 1): for i in countup(2, sonsLen(n) - 1):
result = evalAux(c, n.sons[i]) result = evalAux(c, n.sons[i], {})
if isSpecial(result): return if isSpecial(result): return
a.strVal = getStrValue(a) & getStrValue(result) a.strVal = getStrValue(a) & getStrValue(result)
result = a result = a
proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode = proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
case a.kind case a.kind
@ -646,10 +662,10 @@ proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode = proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode =
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
if a.kind == nkBracket: addSon(a, copyTree(b)) if a.kind == nkBracket: addSon(a, copyTree(b))
@ -657,7 +673,7 @@ proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode =
result = emptyNode result = emptyNode
proc evalRepr(c: PEvalContext, n: PNode): PNode = proc evalRepr(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
result = newStrNodeT(renderTree(result, {renderNoComments}), n) result = newStrNodeT(renderTree(result, {renderNoComments}), n)
@ -689,7 +705,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of mAppendStrStr: result = evalAppendStrStr(c, n) of mAppendStrStr: result = evalAppendStrStr(c, n)
of mAppendSeqElem: result = evalAppendSeqElem(c, n) of mAppendSeqElem: result = evalAppendSeqElem(c, n)
of mNLen: of mNLen:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkIntLit, n.info, n.typ) result = newNodeIT(nkIntLit, n.info, n.typ)
@ -698,10 +714,10 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
nil nil
else: result.intVal = sonsLen(a) else: result.intVal = sonsLen(a)
of mNChild: of mNChild:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var k = getOrdValue(result) var k = getOrdValue(result)
if not (a.kind in {nkEmpty..nkNilLit}) and (k >= 0) and (k < sonsLen(a)): if not (a.kind in {nkEmpty..nkNilLit}) and (k >= 0) and (k < sonsLen(a)):
@ -711,13 +727,13 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n, errIndexOutOfBounds)
result = emptyNode result = emptyNode
of mNSetChild: of mNSetChild:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
result = evalAux(c, n.sons[3]) result = evalAux(c, n.sons[3], {})
if isSpecial(result): return if isSpecial(result): return
var k = getOrdValue(b) var k = getOrdValue(b)
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}):
@ -727,41 +743,41 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
stackTrace(c, n, errIndexOutOfBounds) stackTrace(c, n, errIndexOutOfBounds)
result = emptyNode result = emptyNode
of mNAdd: of mNAdd:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
addSon(a, result) addSon(a, result)
result = emptyNode result = emptyNode
of mNAddMultiple: of mNAddMultiple:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i]) for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i])
result = emptyNode result = emptyNode
of mNDel: of mNDel:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
result = evalAux(c, n.sons[3]) result = evalAux(c, n.sons[3], {})
if isSpecial(result): return if isSpecial(result): return
for i in countup(0, int(getOrdValue(result)) - 1): for i in countup(0, int(getOrdValue(result)) - 1):
delSon(a, int(getOrdValue(b))) delSon(a, int(getOrdValue(b)))
result = emptyNode result = emptyNode
of mNKind: of mNKind:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkIntLit, n.info, n.typ) result = newNodeIT(nkIntLit, n.info, n.typ)
result.intVal = ord(a.kind) result.intVal = ord(a.kind)
of mNIntVal: of mNIntVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkIntLit, n.info, n.typ) result = newNodeIT(nkIntLit, n.info, n.typ)
@ -769,7 +785,7 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of nkCharLit..nkInt64Lit: result.intVal = a.intVal of nkCharLit..nkInt64Lit: result.intVal = a.intVal
else: InternalError(n.info, "no int value") else: InternalError(n.info, "no int value")
of mNFloatVal: of mNFloatVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkFloatLit, n.info, n.typ) result = newNodeIT(nkFloatLit, n.info, n.typ)
@ -777,16 +793,16 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of nkFloatLit..nkFloat64Lit: result.floatVal = a.floatVal of nkFloatLit..nkFloat64Lit: result.floatVal = a.floatVal
else: InternalError(n.info, "no float value") else: InternalError(n.info, "no float value")
of mNSymbol: of mNSymbol:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
if result.kind != nkSym: InternalError(n.info, "no symbol") if result.kind != nkSym: InternalError(n.info, "no 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: InternalError(n.info, "no symbol") if result.kind != nkIdent: InternalError(n.info, "no symbol")
of mNGetType: result = evalAux(c, n.sons[1]) of mNGetType: result = evalAux(c, n.sons[1], {})
of mNStrVal: of mNStrVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkStrLit, n.info, n.typ) result = newNodeIT(nkStrLit, n.info, n.typ)
@ -794,58 +810,58 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of nkStrLit..nkTripleStrLit: result.strVal = a.strVal of nkStrLit..nkTripleStrLit: result.strVal = a.strVal
else: InternalError(n.info, "no string value") else: InternalError(n.info, "no string value")
of mNSetIntVal: of mNSetIntVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
a.intVal = result.intVal # XXX: exception handling? a.intVal = result.intVal # XXX: exception handling?
result = emptyNode result = emptyNode
of mNSetFloatVal: of mNSetFloatVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
a.floatVal = result.floatVal # XXX: exception handling? a.floatVal = result.floatVal # XXX: exception handling?
result = emptyNode result = emptyNode
of mNSetSymbol: of mNSetSymbol:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
a.sym = result.sym # XXX: exception handling? a.sym = result.sym # XXX: exception handling?
result = emptyNode result = emptyNode
of mNSetIdent: of mNSetIdent:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
a.ident = result.ident # XXX: exception handling? a.ident = result.ident # XXX: exception handling?
result = emptyNode result = emptyNode
of mNSetType: of mNSetType:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
a.typ = result.typ # XXX: exception handling? a.typ = result.typ # XXX: exception handling?
result = emptyNode result = emptyNode
of mNSetStrVal: of mNSetStrVal:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {efLValue})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
a.strVal = result.strVal # XXX: exception handling? a.strVal = result.strVal # XXX: exception handling?
result = emptyNode result = emptyNode
of mNNewNimNode: of mNNewNimNode:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var k = getOrdValue(result) var k = getOrdValue(result)
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if result.kind == nkExceptBranch: return if result.kind == nkExceptBranch: return
var a = result var a = result
if (k < 0) or (k > ord(high(TNodeKind))): if (k < 0) or (k > ord(high(TNodeKind))):
@ -853,15 +869,15 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = newNodeI(TNodeKind(int(k)), result = newNodeI(TNodeKind(int(k)),
if a.kind == nkNilLit: n.info else: a.info) if a.kind == nkNilLit: n.info else: a.info)
of mNCopyNimNode: of mNCopyNimNode:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
result = copyNode(result) result = copyNode(result)
of mNCopyNimTree: of mNCopyNimTree:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
result = copyTree(result) result = copyTree(result)
of mStrToIdent: of mStrToIdent:
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}):
InternalError(n.info, "no string node") InternalError(n.info, "no string node")
@ -869,27 +885,27 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
result = newNodeIT(nkIdent, n.info, n.typ) result = newNodeIT(nkIdent, n.info, n.typ)
result.ident = getIdent(a.strVal) result.ident = getIdent(a.strVal)
of mIdentToStr: of mIdentToStr:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
if result.kind != nkIdent: InternalError(n.info, "no ident node") if result.kind != nkIdent: InternalError(n.info, "no ident node")
var a = result var a = result
result = newNodeIT(nkStrLit, n.info, n.typ) result = newNodeIT(nkStrLit, n.info, n.typ)
result.strVal = a.ident.s result.strVal = a.ident.s
of mEqIdent: of mEqIdent:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
result = newNodeIT(nkIntLit, n.info, n.typ) result = newNodeIT(nkIntLit, n.info, n.typ)
if (a.kind == nkIdent) and (b.kind == nkIdent): if (a.kind == nkIdent) and (b.kind == nkIdent):
if a.ident.id == b.ident.id: result.intVal = 1 if a.ident.id == b.ident.id: result.intVal = 1
of mEqNimrodNode: of mEqNimrodNode:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
result = newNodeIT(nkIntLit, n.info, n.typ) result = newNodeIT(nkIntLit, n.info, n.typ)
@ -897,17 +913,17 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
(b.kind in {nkNilLit, nkEmpty}) and (a.kind in {nkNilLit, nkEmpty}): (b.kind in {nkNilLit, nkEmpty}) and (a.kind in {nkNilLit, nkEmpty}):
result.intVal = 1 result.intVal = 1
of mNHint: of mNHint:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
liMessage(n.info, hintUser, getStrValue(result)) liMessage(n.info, hintUser, getStrValue(result))
result = emptyNode result = emptyNode
of mNWarning: of mNWarning:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
liMessage(n.info, warnUser, getStrValue(result)) liMessage(n.info, warnUser, getStrValue(result))
result = emptyNode result = emptyNode
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, errUser, getStrValue(result))
result = emptyNode result = emptyNode
@ -916,35 +932,35 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
of mRepr: of mRepr:
result = evalRepr(c, n) result = evalRepr(c, n)
of mNewString: of mNewString:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
result = newNodeIT(nkStrLit, n.info, n.typ) result = newNodeIT(nkStrLit, n.info, n.typ)
result.strVal = newString(int(getOrdValue(a))) result.strVal = newString(int(getOrdValue(a)))
else: else:
result = evalAux(c, n.sons[1]) result = evalAux(c, n.sons[1], {})
if isSpecial(result): return if isSpecial(result): return
var a = result var a = result
var b: PNode = nil var b: PNode = nil
var cc: PNode = nil var cc: PNode = nil
if sonsLen(n) > 2: if sonsLen(n) > 2:
result = evalAux(c, n.sons[2]) result = evalAux(c, n.sons[2], {})
if isSpecial(result): return if isSpecial(result): return
b = result b = result
if sonsLen(n) > 3: if sonsLen(n) > 3:
result = evalAux(c, n.sons[3]) result = evalAux(c, n.sons[3], {})
if isSpecial(result): return if isSpecial(result): return
cc = result cc = result
if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode
else: result = evalOp(m, n, a, b, cc) else: result = evalOp(m, n, a, b, cc)
proc evalAux(c: PEvalContext, n: PNode): 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, errTooManyIterations)
case n.kind # atoms: case n.kind # atoms:
of nkEmpty: result = n of nkEmpty: result = n
of nkSym: result = evalSym(c, n) of nkSym: result = evalSym(c, n, flags)
of nkType..pred(nkNilLit): result = copyNode(n) of nkType..pred(nkNilLit): result = copyNode(n)
of nkNilLit: result = n # end of atoms of nkNilLit: result = n # end of atoms
of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit: of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit:
@ -952,21 +968,21 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
of nkCurly, nkBracket, nkRange: of nkCurly, nkBracket, nkRange:
var a = copyNode(n) var a = copyNode(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = evalAux(c, n.sons[i]) result = evalAux(c, n.sons[i], {})
if isSpecial(result): return if isSpecial(result): return
addSon(a, result) addSon(a, result)
result = a result = a
of nkPar: of nkPar:
var a = copyTree(n) var a = copyTree(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = evalAux(c, n.sons[i].sons[1]) result = evalAux(c, n.sons[i].sons[1], {})
if isSpecial(result): return if isSpecial(result): return
a.sons[i].sons[1] = result a.sons[i].sons[1] = result
result = a result = a
of nkBracketExpr: result = evalArrayAccess(c, n) of nkBracketExpr: result = evalArrayAccess(c, n, flags)
of nkDotExpr: result = evalFieldAccess(c, n) of nkDotExpr: result = evalFieldAccess(c, n, flags)
of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n) of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags)
of nkAddr, nkHiddenAddr: result = evalAddr(c, n) of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n) of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
of nkAsgn, nkFastAsgn: result = evalAsgn(c, n) of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n) of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
@ -978,17 +994,17 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
of nkReturnStmt: result = evalReturn(c, n) of nkReturnStmt: result = evalReturn(c, n)
of nkBreakStmt, nkReturnToken: result = n of nkBreakStmt, nkReturnToken: result = n
of nkBlockExpr, nkBlockStmt: result = evalBlock(c, n) of nkBlockExpr, nkBlockStmt: result = evalBlock(c, n)
of nkDiscardStmt: result = evalAux(c, n.sons[0]) of nkDiscardStmt: result = evalAux(c, n.sons[0], {})
of nkCheckedFieldExpr: result = evalCheckedFieldAccess(c, n) of nkCheckedFieldExpr: result = evalCheckedFieldAccess(c, n, flags)
of nkObjDownConv: result = evalAux(c, n.sons[0]) of nkObjDownConv: result = evalAux(c, n.sons[0], flags)
of nkObjUpConv: result = evalUpConv(c, n) of nkObjUpConv: result = evalUpConv(c, n, flags)
of nkChckRangeF, nkChckRange64, nkChckRange: result = evalRangeChck(c, n) of nkChckRangeF, nkChckRange64, nkChckRange: result = evalRangeChck(c, n)
of nkStringToCString: result = evalConvStrToCStr(c, n) of nkStringToCString: result = evalConvStrToCStr(c, n)
of nkCStringToString: result = evalConvCStrToStr(c, n) of nkCStringToString: result = evalConvCStrToStr(c, n)
of nkPassAsOpenArray: result = evalAux(c, n.sons[0]) of nkPassAsOpenArray: result = evalAux(c, n.sons[0], flags)
of nkStmtListExpr, nkStmtList, nkModule: of nkStmtListExpr, nkStmtList, nkModule:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = evalAux(c, n.sons[i]) result = evalAux(c, n.sons[i], flags)
case result.kind case result.kind
of nkExceptBranch, nkReturnToken, nkBreakStmt: break of nkExceptBranch, nkReturnToken, nkBreakStmt: break
else: nil else: nil
@ -1007,7 +1023,7 @@ proc evalAux(c: PEvalContext, n: PNode): PNode =
proc eval(c: PEvalContext, n: PNode): PNode = proc eval(c: PEvalContext, n: PNode): PNode =
gWhileCounter = evalMaxIterations gWhileCounter = evalMaxIterations
gNestedEvals = evalMaxRecDepth gNestedEvals = evalMaxRecDepth
result = evalAux(c, n) result = evalAux(c, n, {})
if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1): if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1):
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ))

View file

@ -47,9 +47,11 @@ Additions
- Added ``xmlparser`` module. - Added ``xmlparser`` module.
- Added ``htmlparser`` module. - Added ``htmlparser`` module.
- Added ``re`` module. - Added ``re`` module.
- Added ``graphics`` module.
- Added ``colors`` module.
- Many wrappers now do not contain redundant name prefixes (like ``GTK_``, - Many wrappers now do not contain redundant name prefixes (like ``GTK_``,
``lua``). The new wrappers are available in ``lib/newwrap``. Change ``lua``). The old wrappers are still available in ``lib/oldwrappers``.
your configuration file to use these. Change your configuration file to use these.
- Triple quoted strings allow for ``"`` in more contexts. - Triple quoted strings allow for ``"`` in more contexts.
- ``""`` within raw string literals stands for a single quotation mark. - ``""`` within raw string literals stands for a single quotation mark.
- More extensive subscript operator overloading. See - More extensive subscript operator overloading. See

View file

@ -31,7 +31,7 @@ srcdoc: "pure/streams;pure/terminal;pure/cgi;impure/web;pure/unicode"
srcdoc: "impure/zipfiles;pure/xmlgen;pure/macros;pure/parseutils;pure/browsers" srcdoc: "impure/zipfiles;pure/xmlgen;pure/macros;pure/parseutils;pure/browsers"
srcdoc: "impure/db_postgres;impure/db_mysql;pure/httpserver;pure/httpclient" srcdoc: "impure/db_postgres;impure/db_mysql;pure/httpserver;pure/httpclient"
srcdoc: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser" srcdoc: "pure/ropes;pure/unidecode/unidecode;pure/xmldom;pure/xmldomparser"
srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree" srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors;impure/graphics"
webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup" webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
webdoc: "wrappers/sqlite3;wrappers/python;wrappers/tcl" webdoc: "wrappers/sqlite3;wrappers/python;wrappers/tcl"