summary refs log tree commit diff stats
path: root/rod/evals.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/evals.nim')
-rwxr-xr-xrod/evals.nim1110
1 files changed, 0 insertions, 1110 deletions
diff --git a/rod/evals.nim b/rod/evals.nim
deleted file mode 100755
index 7d0f9c801..000000000
--- a/rod/evals.nim
+++ /dev/null
@@ -1,1110 +0,0 @@
-#
-#
-#           The Nimrod Compiler
-#        (c) Copyright 2011 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This file implements the evaluator for Nimrod code.
-# The evaluator is very slow, but simple. Since this
-# is used mainly for evaluating macros and some other
-# stuff at compile time, performance is not that
-# important.
-
-import 
-  strutils, magicsys, lists, options, ast, astalgo, trees, treetab, nimsets, 
-  msgs, os, condsyms, idents, rnimsyn, types, passes, semfold
-
-type 
-  PStackFrame* = ref TStackFrame
-  TStackFrame*{.final.} = object 
-    mapping*: TIdNodeTable    # mapping from symbols to nodes
-    prc*: PSym                # current prc; proc that is evaluated
-    call*: PNode
-    next*: PStackFrame        # for stacking
-    params*: TNodeSeq         # parameters passed to the proc
-  
-  TEvalContext* = object of passes.TPassContext
-    module*: PSym
-    tos*: PStackFrame         # top of stack
-    lastException*: PNode
-    optEval*: bool            # evaluation done for optimization purposes
-  
-  PEvalContext* = ref TEvalContext
-
-  TEvalFlag = enum 
-    efNone, efLValue
-  TEvalFlags = set[TEvalFlag]
-
-proc eval*(c: PEvalContext, n: PNode): PNode
-  # eval never returns nil! This simplifies the code a lot and
-  # makes it faster too.
-proc evalConstExpr*(module: PSym, e: PNode): PNode
-
-const
-  evalMaxIterations = 500_000 # max iterations of all loops
-  evalMaxRecDepth = 10_000    # max recursion depth for evaluation
-
-# Much better: use a timeout! -> Wether code compiles depends on the machine
-# the compiler runs on then! Bad idea!
-
-proc newStackFrame*(): PStackFrame = 
-  new(result)
-  initIdNodeTable(result.mapping)
-  result.params = @[]
-
-proc newEvalContext*(module: PSym, filename: string, 
-                     optEval: bool): PEvalContext = 
-  new(result)
-  result.module = module
-  result.optEval = optEval
-
-proc pushStackFrame*(c: PEvalContext, t: PStackFrame) {.inline.} = 
-  t.next = c.tos
-  c.tos = t
-
-proc popStackFrame*(c: PEvalContext) {.inline.} = 
-  if (c.tos == nil): InternalError("popStackFrame")
-  c.tos = c.tos.next
-
-proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
-
-proc stackTraceAux(x: PStackFrame) =
-  if x != nil:
-    stackTraceAux(x.next)
-    var info = if x.call != nil: x.call.info else: UnknownLineInfo()
-    # we now use the same format as in system/except.nim
-    var s = toFilename(info)
-    var line = toLineNumber(info)
-    if line > 0:
-      add(s, '(')
-      add(s, $line)
-      add(s, ')')
-    if x.prc != nil:
-      for k in 1..max(1, 25-s.len): add(s, ' ')
-      add(s, x.prc.name.s)
-    MsgWriteln(s)
-
-proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") = 
-  MsgWriteln("stack trace: (most recent call last)")
-  stackTraceAux(c.tos)
-  Fatal(n.info, msg, arg)
-
-proc isSpecial(n: PNode): bool {.inline.} = 
-  result = (n.kind == nkExceptBranch) 
-  # or (n.kind == nkEmpty)
-  # XXX this does not work yet! Better to compile too much than to compile to
-  # few programs
-
-proc myreset(n: PNode) {.inline.} =
-  when defined(system.reset): reset(n[])
-
-proc evalIf(c: PEvalContext, n: PNode): PNode = 
-  var i = 0
-  var length = sonsLen(n)
-  while (i < length) and (sonsLen(n.sons[i]) >= 2): 
-    result = evalAux(c, n.sons[i].sons[0], {})
-    if isSpecial(result): return 
-    if (result.kind == nkIntLit) and (result.intVal != 0): 
-      return evalAux(c, n.sons[i].sons[1], {})
-    inc(i)
-  if (i < length) and (sonsLen(n.sons[i]) < 2): 
-    result = evalAux(c, n.sons[i].sons[0], {})
-  else: 
-    result = emptyNode
-  
-proc evalCase(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {})
-  if isSpecial(result): return 
-  var res = result
-  result = emptyNode
-  for i in countup(1, sonsLen(n) - 1): 
-    if n.sons[i].kind == nkOfBranch: 
-      for j in countup(0, sonsLen(n.sons[i]) - 2): 
-        if overlap(res, n.sons[i].sons[j]): 
-          return evalAux(c, lastSon(n.sons[i]), {})
-    else: 
-      result = evalAux(c, lastSon(n.sons[i]), {})
-
-var 
-  gWhileCounter: int # Use a counter to prevent endless loops!
-                     # We make this counter global, because otherwise
-                     # nested loops could make the compiler extremely slow.
-  gNestedEvals: int  # count the recursive calls to ``evalAux`` to prevent
-                     # endless recursion
-
-proc evalWhile(c: PEvalContext, n: PNode): PNode = 
-  while true: 
-    result = evalAux(c, n.sons[0], {})
-    if isSpecial(result): return 
-    if getOrdValue(result) == 0: break 
-    result = evalAux(c, n.sons[1], {})
-    case result.kind
-    of nkBreakStmt: 
-      if result.sons[0].kind == nkEmpty: 
-        result = emptyNode    # consume ``break`` token
-      # Bugfix (see tmacro2): but break in any case!
-      break 
-    of nkExceptBranch, nkReturnToken: break 
-    else: nil
-    dec(gWhileCounter)
-    if gWhileCounter <= 0: 
-      stackTrace(c, n, errTooManyIterations)
-      break 
-
-proc evalBlock(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if result.kind == nkBreakStmt: 
-    if result.sons[0] != nil: 
-      assert(result.sons[0].kind == nkSym)
-      if n.sons[0].kind != nkEmpty: 
-        assert(n.sons[0].kind == nkSym)
-        if result.sons[0].sym.id == n.sons[0].sym.id: result = emptyNode
-    else: 
-      result = emptyNode      # consume ``break`` token
-  
-proc evalFinally(c: PEvalContext, n, exc: PNode): PNode = 
-  var finallyNode = lastSon(n)
-  if finallyNode.kind == nkFinally: 
-    result = evalAux(c, finallyNode, {})
-    if result.kind != nkExceptBranch: result = exc
-  else: 
-    result = exc
-  
-proc evalTry(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {})
-  case result.kind
-  of nkBreakStmt, nkReturnToken: 
-    nil
-  of nkExceptBranch: 
-    if sonsLen(result) >= 1: 
-      # creating a nkExceptBranch without sons means that it could not be
-      # evaluated
-      var exc = result
-      var i = 1
-      var length = sonsLen(n)
-      while (i < length) and (n.sons[i].kind == nkExceptBranch): 
-        var blen = sonsLen(n.sons[i])
-        if blen == 1: 
-          # general except section:
-          result = evalAux(c, n.sons[i].sons[0], {})
-          exc = result
-          break 
-        else: 
-          for j in countup(0, blen - 2): 
-            assert(n.sons[i].sons[j].kind == nkType)
-            if exc.typ.id == n.sons[i].sons[j].typ.id: 
-              result = evalAux(c, n.sons[i].sons[blen - 1], {})
-              exc = result
-              break 
-        inc(i)
-      result = evalFinally(c, n, exc)
-  else: result = evalFinally(c, n, emptyNode)
-  
-proc getNullValue(typ: PType, info: TLineInfo): PNode
-proc getNullValueAux(obj: PNode, result: PNode) = 
-  case obj.kind
-  of nkRecList:
-    for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result)
-  of nkRecCase:
-    getNullValueAux(obj.sons[0], result)
-    for i in countup(1, sonsLen(obj) - 1): 
-      getNullValueAux(lastSon(obj.sons[i]), result)
-  of nkSym: 
-    var s = obj.sym
-    var p = newNodeIT(nkExprColonExpr, result.info, s.typ)
-    addSon(p, newSymNode(s, result.info))
-    addSon(p, getNullValue(s.typ, result.info))
-    addSon(result, p)
-  else: InternalError(result.info, "getNullValueAux")
-  
-proc getNullValue(typ: PType, info: TLineInfo): PNode = 
-  var t = skipTypes(typ, abstractRange)
-  result = emptyNode
-  case t.kind
-  of tyBool, tyChar, tyInt..tyInt64: 
-    result = newNodeIT(nkIntLit, info, t)
-  of tyFloat..tyFloat128: 
-    result = newNodeIt(nkFloatLit, info, t)
-  of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr, 
-     tyStmt, tyTypeDesc: 
-    result = newNodeIT(nkNilLit, info, t)
-  of tyObject: 
-    result = newNodeIT(nkPar, info, t)
-    getNullValueAux(t.n, result)
-  of tyArray, tyArrayConstr: 
-    result = newNodeIT(nkBracket, info, t)
-    for i in countup(0, int(lengthOrd(t)) - 1): 
-      addSon(result, getNullValue(elemType(t), info))
-  of tyTuple: 
-    result = newNodeIT(nkPar, info, t)
-    for i in countup(0, sonsLen(t) - 1): 
-      var p = newNodeIT(nkExprColonExpr, info, t.sons[i])
-      var field = if t.n != nil: t.n.sons[i].sym else: newSym(
-        skField, getIdent(":tmp" & $i), t.owner)
-      addSon(p, newSymNode(field, info))
-      addSon(p, getNullValue(t.sons[i], info))
-      addSon(result, p)
-  of tySet:
-    result = newNodeIT(nkCurly, info, t)    
-  else: InternalError("getNullValue")
-  
-proc evalVar(c: PEvalContext, n: PNode): PNode = 
-  for i in countup(0, sonsLen(n) - 1): 
-    var a = n.sons[i]
-    if a.kind == nkCommentStmt: continue 
-    assert(a.kind == nkIdentDefs)
-    assert(a.sons[0].kind == nkSym)
-    var v = a.sons[0].sym
-    if a.sons[2].kind != nkEmpty: 
-      result = evalAux(c, a.sons[2], {})
-      if isSpecial(result): return 
-    else: 
-      result = getNullValue(a.sons[0].typ, a.sons[0].info)
-    IdNodeTablePut(c.tos.mapping, v, result)
-  result = emptyNode
-
-proc evalCall(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {})
-  if isSpecial(result): return 
-  var prc = result
-  # bind the actual params to the local parameter of a new binding
-  var d = newStackFrame()
-  d.call = n
-  if prc.kind == nkSym: 
-    d.prc = prc.sym
-    if not (prc.sym.kind in {skProc, skConverter}): 
-      InternalError(n.info, "evalCall")
-  setlen(d.params, sonsLen(n))
-  for i in countup(1, sonsLen(n) - 1): 
-    result = evalAux(c, n.sons[i], {})
-    if isSpecial(result): return 
-    d.params[i] = result
-  if n.typ != nil: d.params[0] = getNullValue(n.typ, n.info)
-  pushStackFrame(c, d)
-  result = evalAux(c, prc, {})
-  if result.kind == nkExceptBranch: return 
-  if n.typ != nil: result = d.params[0]
-  popStackFrame(c)
-
-proc aliasNeeded(n: PNode, flags: TEvalFlags): bool = 
-  result = efLValue in flags or n.typ == nil or 
-    n.typ.kind in {tyExpr, tyStmt, tyTypeDesc}
-
-proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode = 
-  # We need to return a node to the actual value,
-  # which can be modified.
-  var x = c
-  while x != nil: 
-    if sfResult in sym.flags: 
-      result = x.params[0]
-      if result == nil: result = emptyNode
-      return
-    result = IdNodeTableGet(x.mapping, sym)
-    if result != nil and not aliasNeeded(result, flags): 
-      result = copyTree(result)
-    if result != nil: return 
-    x = x.next
-  result = emptyNode
-
-proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  result = evalAux(c, n.sons[0], flags)
-  if isSpecial(result): return 
-  var x = result
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  var idx = getOrdValue(result)
-  result = emptyNode
-  case x.kind
-  of nkPar: 
-    if (idx >= 0) and (idx < sonsLen(x)): 
-      result = x.sons[int(idx)]
-      if result.kind == nkExprColonExpr: result = result.sons[1]
-    else: stackTrace(c, n, errIndexOutOfBounds)
-    if not aliasNeeded(result, flags): result = copyTree(result)
-  of nkBracket, nkMetaNode: 
-    if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
-    else: stackTrace(c, n, errIndexOutOfBounds)
-    if not aliasNeeded(result, flags): result = copyTree(result)
-  of nkStrLit..nkTripleStrLit: 
-    if efLValue in flags: 
-      InternalError(n.info, "cannot evaluate write access to char")
-    result = newNodeIT(nkCharLit, x.info, getSysType(tyChar))
-    if (idx >= 0) and (idx < len(x.strVal)): 
-      result.intVal = ord(x.strVal[int(idx) + 0])
-    elif idx == len(x.strVal): 
-      nil
-    else: 
-      stackTrace(c, n, errIndexOutOfBounds)
-  else: stackTrace(c, n, errNilAccess)
-  
-proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  # a real field access; proc calls have already been transformed
-  # XXX: field checks!
-  result = evalAux(c, n.sons[0], flags)
-  if isSpecial(result): return 
-  var x = result
-  if x.kind != nkPar: InternalError(n.info, "evalFieldAccess")
-  var field = n.sons[1].sym
-  for i in countup(0, sonsLen(x) - 1): 
-    var it = x.sons[i]
-    if it.kind != nkExprColonExpr: 
-      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 = 
-  result = evalAux(c, n.sons[0], {efLValue})
-  if isSpecial(result): return 
-  var x = result
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  myreset(x)
-  x.kind = result.kind
-  x.typ = result.typ
-  case x.kind
-  of nkCharLit..nkInt64Lit: 
-    x.intVal = result.intVal
-  of nkFloatLit..nkFloat64Lit: 
-    x.floatVal = result.floatVal
-  of nkStrLit..nkTripleStrLit: 
-    x.strVal = result.strVal
-  else: 
-    if not (x.kind in {nkEmpty..nkNilLit}): 
-      discardSons(x)
-      for i in countup(0, sonsLen(result) - 1): addSon(x, result.sons[i])
-  result = emptyNode
-  assert result.kind == nkEmpty
-
-proc evalSwap(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {efLValue})
-  if isSpecial(result): return 
-  var x = result
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  if (x.kind != result.kind): 
-    stackTrace(c, n, errCannotInterpretNodeX, $n.kind)
-  else: 
-    case x.kind
-    of nkCharLit..nkInt64Lit: 
-      var tmpi = x.intVal
-      x.intVal = result.intVal
-      result.intVal = tmpi
-    of nkFloatLit..nkFloat64Lit: 
-      var tmpf = x.floatVal
-      x.floatVal = result.floatVal
-      result.floatVal = tmpf
-    of nkStrLit..nkTripleStrLit: 
-      var tmps = x.strVal
-      x.strVal = result.strVal
-      result.strVal = tmps
-    else: 
-      var tmpn = copyTree(x)
-      discardSons(x)
-      for i in countup(0, sonsLen(result) - 1): addSon(x, result.sons[i])
-      discardSons(result)
-      for i in countup(0, sonsLen(tmpn) - 1): addSon(result, tmpn.sons[i])
-  result = emptyNode
-
-proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  case n.sym.kind
-  of skProc, skConverter, skMacro: result = n.sym.ast.sons[codePos]
-  of skVar, skForVar, skTemp: result = evalVariable(c.tos, n.sym, flags)
-  of skParam: 
-    # XXX what about LValue?
-    result = c.tos.params[n.sym.position + 1]
-  of skConst: result = n.sym.ast
-  else: 
-    stackTrace(c, n, errCannotInterpretNodeX, $n.sym.kind)
-    result = emptyNode
-  if result == nil: stackTrace(c, n, errCannotInterpretNodeX, n.sym.name.s)
-  
-proc evalIncDec(c: PEvalContext, n: PNode, sign: biggestInt): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  case a.kind
-  of nkCharLit..nkInt64Lit: a.intval = a.intVal + sign * getOrdValue(b)
-  else: internalError(n.info, "evalIncDec")
-  result = emptyNode
-
-proc getStrValue(n: PNode): string = 
-  case n.kind
-  of nkStrLit..nkTripleStrLit: result = n.strVal
-  else: 
-    InternalError(n.info, "getStrValue")
-    result = ""
-
-proc evalEcho(c: PEvalContext, n: PNode): PNode = 
-  for i in countup(1, sonsLen(n) - 1): 
-    result = evalAux(c, n.sons[i], {})
-    if isSpecial(result): return 
-    Write(stdout, getStrValue(result))
-  writeln(stdout, "")
-  result = emptyNode
-
-proc evalExit(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  Message(n.info, hintQuitCalled)
-  quit(int(getOrdValue(result)))
-
-proc evalOr(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  if result.kind != nkIntLit: InternalError(n.info, "evalOr")
-  if result.intVal == 0: result = evalAux(c, n.sons[2], {})
-  
-proc evalAnd(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  if result.kind != nkIntLit: InternalError(n.info, "evalAnd")
-  if result.intVal != 0: result = evalAux(c, n.sons[2], {})
-  
-proc evalNoOpt(c: PEvalContext, n: PNode): PNode = 
-  result = newNodeI(nkExceptBranch, n.info) 
-  # creating a nkExceptBranch without sons 
-  # means that it could not be evaluated
-  
-proc evalNew(c: PEvalContext, n: PNode): PNode = 
-  if c.optEval: return evalNoOpt(c, n)
-  # we ignore the finalizer for now and most likely forever :-)
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  var t = skipTypes(n.sons[1].typ, abstractVar)
-  if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty")
-  myreset(a)
-  a.kind = nkRefTy
-  a.info = n.info
-  a.typ = t
-  a.sons = nil
-  addSon(a, getNullValue(t.sons[0], n.info))
-  result = emptyNode
-
-proc evalDeref(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  result = evalAux(c, n.sons[0], {efLValue})
-  if isSpecial(result): return 
-  case result.kind
-  of nkNilLit: stackTrace(c, n, errNilAccess)
-  of nkRefTy: 
-    # XXX efLValue?
-    result = result.sons[0]
-  else: InternalError(n.info, "evalDeref " & $result.kind)
-  
-proc evalAddr(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  result = evalAux(c, n.sons[0], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  var t = newType(tyPtr, c.module)
-  addSon(t, a.typ)
-  result = newNodeIT(nkRefTy, n.info, t)
-  addSon(result, a)
-
-proc evalConv(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return
-  var a = result
-  result = foldConv(n, a)
-  if result == nil: 
-    # foldConv() cannot deal with everything that we want to do here:
-    result = a
-
-proc evalCheckedFieldAccess(c: PEvalContext, n: PNode, 
-                            flags: TEvalFlags): PNode = 
-  result = evalAux(c, n.sons[0], flags)
-
-proc evalUpConv(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  result = evalAux(c, n.sons[0], flags)
-  if isSpecial(result): return 
-  var dest = skipTypes(n.typ, abstractPtrs)
-  var src = skipTypes(result.typ, abstractPtrs)
-  if inheritanceDiff(src, dest) > 0: 
-    stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src))
-  
-proc evalRangeChck(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {})
-  if isSpecial(result): return 
-  var x = result
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  if leValueConv(a, x) and leValueConv(x, b): 
-    result = x                # a <= x and x <= b
-    result.typ = n.typ
-  else: 
-    stackTrace(c, n, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
-        typeToString(n.sons[0].typ), typeToString(n.typ)])
-  
-proc evalConvStrToCStr(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {})
-  if isSpecial(result): return 
-  result.typ = n.typ
-
-proc evalConvCStrToStr(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[0], {})
-  if isSpecial(result): return 
-  result.typ = n.typ
-
-proc evalRaise(c: PEvalContext, n: PNode): PNode = 
-  if n.sons[0].kind != nkEmpty: 
-    result = evalAux(c, n.sons[0], {})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkExceptBranch, n.info, a.typ)
-    addSon(result, a)
-    c.lastException = result
-  elif c.lastException != nil: 
-    result = c.lastException
-  else: 
-    stackTrace(c, n, errExceptionAlreadyHandled)
-    result = newNodeIT(nkExceptBranch, n.info, nil)
-    addSon(result, ast.emptyNode)
-
-proc evalReturn(c: PEvalContext, n: PNode): PNode = 
-  if n.sons[0].kind != nkEmpty: 
-    result = evalAsgn(c, n.sons[0])
-    if isSpecial(result): return 
-  result = newNodeIT(nkReturnToken, n.info, nil)
-
-proc evalProc(c: PEvalContext, n: PNode): PNode = 
-  if n.sons[genericParamsPos].kind == nkEmpty: 
-    if (resultPos < sonsLen(n)) and (n.sons[resultPos].kind != nkEmpty): 
-      var v = n.sons[resultPos].sym
-      result = getNullValue(v.typ, n.info)
-      IdNodeTablePut(c.tos.mapping, v, result)
-      result = evalAux(c, n.sons[codePos], {})
-      if result.kind == nkReturnToken: 
-        result = IdNodeTableGet(c.tos.mapping, v)
-    else:
-      result = evalAux(c, n.sons[codePos], {})
-      if result.kind == nkReturnToken: 
-        result = emptyNode
-  else: 
-    result = emptyNode
-  
-proc evalHigh(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  case skipTypes(n.sons[1].typ, abstractVar).kind
-  of tyOpenArray, tySequence: result = newIntNodeT(sonsLen(result), n)
-  of tyString: result = newIntNodeT(len(result.strVal) - 1, n)
-  else: InternalError(n.info, "evalHigh")
-  
-proc evalIs(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  result = newIntNodeT(ord(inheritanceDiff(result.typ, n.sons[2].typ) >= 0), n)
-
-proc evalSetLengthStr(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  case a.kind
-  of nkStrLit..nkTripleStrLit: 
-    var newLen = int(getOrdValue(b))
-    setlen(a.strVal, newLen)
-  else: InternalError(n.info, "evalSetLengthStr")
-  result = emptyNode
-
-proc evalSetLengthSeq(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  if a.kind != nkBracket: InternalError(n.info, "evalSetLengthSeq")
-  var newLen = int(getOrdValue(b))
-  var oldLen = sonsLen(a)
-  setlen(a.sons, newLen)
-  for i in countup(oldLen, newLen - 1): 
-    a.sons[i] = getNullValue(skipTypes(n.sons[1].typ, abstractVar), n.info)
-  result = emptyNode
-
-proc evalNewSeq(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  var t = skipTypes(n.sons[1].typ, abstractVar)
-  if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty")
-  myreset(a)
-  a.kind = nkBracket
-  a.info = n.info
-  a.typ = t
-  a.sons = nil
-  var L = int(getOrdValue(b))
-  newSeq(a.sons, L)
-  for i in countup(0, L-1): 
-    a.sons[i] = getNullValue(t.sons[0], n.info)
-  result = emptyNode
-
-proc evalAssert(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  if getOrdValue(result) != 0: result = emptyNode
-  else: stackTrace(c, n, errAssertionFailed)
-  
-proc evalIncl(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  if not inSet(a, b): addSon(a, copyTree(b))
-  result = emptyNode
-
-proc evalExcl(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = newNodeIT(nkCurly, n.info, n.sons[1].typ)
-  addSon(b, result)
-  var r = diffSets(a, b)
-  discardSons(a)
-  for i in countup(0, sonsLen(r) - 1): addSon(a, r.sons[i])
-  result = emptyNode
-
-proc evalAppendStrCh(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  case a.kind
-  of nkStrLit..nkTripleStrLit: add(a.strVal, chr(int(getOrdValue(b))))
-  else: InternalError(n.info, "evalAppendStrCh")
-  result = emptyNode
-
-proc evalConStrStr(c: PEvalContext, n: PNode): PNode = 
-  # we cannot use ``evalOp`` for this as we can here have more than 2 arguments
-  var a = newNodeIT(nkStrLit, n.info, n.typ)
-  a.strVal = ""
-  for i in countup(1, sonsLen(n) - 1): 
-    result = evalAux(c, n.sons[i], {})
-    if isSpecial(result): return 
-    a.strVal.add(getStrValue(result))
-  result = a
-
-proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  case a.kind
-  of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrValue(b)
-  else: InternalError(n.info, "evalAppendStrStr")
-  result = emptyNode
-
-proc evalAppendSeqElem(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {efLValue})
-  if isSpecial(result): return 
-  var a = result
-  result = evalAux(c, n.sons[2], {})
-  if isSpecial(result): return 
-  var b = result
-  if a.kind == nkBracket: addSon(a, copyTree(b))
-  else: InternalError(n.info, "evalAppendSeqElem")
-  result = emptyNode
-
-proc evalRepr(c: PEvalContext, n: PNode): PNode = 
-  result = evalAux(c, n.sons[1], {})
-  if isSpecial(result): return 
-  result = newStrNodeT(renderTree(result, {renderNoComments}), n)
-
-proc isEmpty(n: PNode): bool = 
-  result = (n != nil) and (n.kind == nkEmpty)
-
-proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode = 
-  var m = getMagic(n)
-  case m
-  of mNone: result = evalCall(c, n)
-  of mIs: result = evalIs(c, n)
-  of mSizeOf: internalError(n.info, "sizeof() should have been evaluated")
-  of mHigh: result = evalHigh(c, n)
-  of mAssert: result = evalAssert(c, n)
-  of mExit: result = evalExit(c, n)
-  of mNew, mNewFinalize: result = evalNew(c, n)
-  of mNewSeq: result = evalNewSeq(c, n)
-  of mSwap: result = evalSwap(c, n)
-  of mInc: result = evalIncDec(c, n, 1)
-  of ast.mDec: result = evalIncDec(c, n, - 1)
-  of mEcho: result = evalEcho(c, n)
-  of mSetLengthStr: result = evalSetLengthStr(c, n)
-  of mSetLengthSeq: result = evalSetLengthSeq(c, n)
-  of mIncl: result = evalIncl(c, n)
-  of mExcl: result = evalExcl(c, n)
-  of mAnd: result = evalAnd(c, n)
-  of mOr: result = evalOr(c, n)
-  of mAppendStrCh: result = evalAppendStrCh(c, n)
-  of mAppendStrStr: result = evalAppendStrStr(c, n)
-  of mAppendSeqElem: result = evalAppendSeqElem(c, n)
-  of mNLen: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkIntLit, n.info, n.typ)
-    case a.kind
-    of nkEmpty..nkNilLit: nil
-    else: result.intVal = sonsLen(a)
-  of mNChild: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    var k = getOrdValue(result)
-    if not (a.kind in {nkEmpty..nkNilLit}) and (k >= 0) and (k < sonsLen(a)): 
-      result = a.sons[int(k)]
-      if result == nil: result = newNode(nkEmpty)
-    else: 
-      stackTrace(c, n, errIndexOutOfBounds)
-      result = emptyNode
-  of mNSetChild: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    var b = result
-    result = evalAux(c, n.sons[3], {efLValue})
-    if isSpecial(result): return 
-    var k = getOrdValue(b)
-    if (k >= 0) and (k < sonsLen(a)) and not (a.kind in {nkEmpty..nkNilLit}): 
-      a.sons[int(k)] = result
-    else: 
-      stackTrace(c, n, errIndexOutOfBounds)
-    result = emptyNode
-  of mNAdd: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    addSon(a, result)
-    result = emptyNode
-  of mNAddMultiple: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    for i in countup(0, sonsLen(result) - 1): addSon(a, result.sons[i])
-    result = emptyNode
-  of mNDel: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    var b = result
-    result = evalAux(c, n.sons[3], {efLValue})
-    if isSpecial(result): return 
-    for i in countup(0, int(getOrdValue(result)) - 1): 
-      delSon(a, int(getOrdValue(b)))
-    result = emptyNode
-  of mNKind: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkIntLit, n.info, n.typ)
-    result.intVal = ord(a.kind)
-  of mNIntVal: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkIntLit, n.info, n.typ)
-    case a.kind
-    of nkCharLit..nkInt64Lit: result.intVal = a.intVal
-    else: InternalError(n.info, "no int value")
-  of mNFloatVal: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkFloatLit, n.info, n.typ)
-    case a.kind
-    of nkFloatLit..nkFloat64Lit: result.floatVal = a.floatVal
-    else: InternalError(n.info, "no float value")
-  of mNSymbol: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    if result.kind != nkSym: InternalError(n.info, "no symbol")
-  of mNIdent: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    if result.kind != nkIdent: InternalError(n.info, "no symbol")
-  of mNGetType: result = evalAux(c, n.sons[1], {})
-  of mNStrVal: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkStrLit, n.info, n.typ)
-    case a.kind
-    of nkStrLit..nkTripleStrLit: result.strVal = a.strVal
-    else: InternalError(n.info, "no string value")
-  of mNSetIntVal: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {})
-    if isSpecial(result): return 
-    a.intVal = result.intVal  # XXX: exception handling?
-    result = emptyNode
-  of mNSetFloatVal: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {})
-    if isSpecial(result): return 
-    a.floatVal = result.floatVal # XXX: exception handling?
-    result = emptyNode
-  of mNSetSymbol: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    a.sym = result.sym        # XXX: exception handling?
-    result = emptyNode
-  of mNSetIdent: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    a.ident = result.ident    # XXX: exception handling?
-    result = emptyNode
-  of mNSetType: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    a.typ = result.typ        # XXX: exception handling?
-    result = emptyNode
-  of mNSetStrVal: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {})
-    if isSpecial(result): return 
-    a.strVal = result.strVal  # XXX: exception handling?
-    result = emptyNode
-  of mNNewNimNode: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var k = getOrdValue(result)
-    result = evalAux(c, n.sons[2], {efLValue})
-    if result.kind == nkExceptBranch: return 
-    var a = result
-    if k < 0 or k > ord(high(TNodeKind)): 
-      internalError(n.info, "request to create a NimNode with invalid kind")
-    result = newNodeI(TNodeKind(int(k)), 
-      if a.kind == nkNilLit: n.info else: a.info)
-  of mNCopyNimNode: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    result = copyNode(result)
-  of mNCopyNimTree: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    result = copyTree(result)
-  of mStrToIdent: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    if not (result.kind in {nkStrLit..nkTripleStrLit}): 
-      InternalError(n.info, "no string node")
-    var a = result
-    result = newNodeIT(nkIdent, n.info, n.typ)
-    result.ident = getIdent(a.strVal)
-  of mIdentToStr: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    if result.kind != nkIdent: InternalError(n.info, "no ident node")
-    var a = result
-    result = newNodeIT(nkStrLit, n.info, n.typ)
-    result.strVal = a.ident.s
-  of mEqIdent: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {})
-    if isSpecial(result): return 
-    var b = result
-    result = newNodeIT(nkIntLit, n.info, n.typ)
-    if (a.kind == nkIdent) and (b.kind == nkIdent): 
-      if a.ident.id == b.ident.id: result.intVal = 1
-  of mEqNimrodNode: 
-    result = evalAux(c, n.sons[1], {efLValue})
-    if isSpecial(result): return 
-    var a = result
-    result = evalAux(c, n.sons[2], {efLValue})
-    if isSpecial(result): return 
-    var b = result
-    result = newNodeIT(nkIntLit, n.info, n.typ)
-    if (a == b) or
-        (b.kind in {nkNilLit, nkEmpty}) and (a.kind in {nkNilLit, nkEmpty}): 
-      result.intVal = 1
-  of mNHint: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    Message(n.info, hintUser, getStrValue(result))
-    result = emptyNode
-  of mNWarning: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    Message(n.info, warnUser, getStrValue(result))
-    result = emptyNode
-  of mNError: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    stackTrace(c, n, errUser, getStrValue(result))
-    result = emptyNode
-  of mConStrStr: 
-    result = evalConStrStr(c, n)
-  of mRepr: 
-    result = evalRepr(c, n)
-  of mNewString: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    result = newNodeIT(nkStrLit, n.info, n.typ)
-    result.strVal = newString(int(getOrdValue(a)))
-  else: 
-    result = evalAux(c, n.sons[1], {})
-    if isSpecial(result): return 
-    var a = result
-    var b: PNode = nil
-    var cc: PNode = nil
-    if sonsLen(n) > 2: 
-      result = evalAux(c, n.sons[2], {})
-      if isSpecial(result): return 
-      b = result
-      if sonsLen(n) > 3: 
-        result = evalAux(c, n.sons[3], {})
-        if isSpecial(result): return 
-        cc = result
-    if isEmpty(a) or isEmpty(b) or isEmpty(cc): result = emptyNode
-    else: result = evalOp(m, n, a, b, cc)
-  
-proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = 
-  result = emptyNode
-  dec(gNestedEvals)
-  if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
-  case n.kind                 # atoms:
-  of nkEmpty: result = n
-  of nkSym: result = evalSym(c, n, flags)
-  of nkType..nkNilLit: result = copyNode(n) # end of atoms
-  of nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand, nkCallStrLit: 
-    result = evalMagicOrCall(c, n)
-  of nkCurly, nkBracket, nkRange: 
-    # flags need to be passed here for mNAddMultiple :-(
-    # XXX this is not correct in every case!
-    var a = copyNode(n)
-    for i in countup(0, sonsLen(n) - 1): 
-      result = evalAux(c, n.sons[i], flags)
-      if isSpecial(result): return 
-      addSon(a, result)
-    result = a
-  of nkPar: 
-    var a = copyTree(n)
-    for i in countup(0, sonsLen(n) - 1): 
-      result = evalAux(c, n.sons[i].sons[1], flags)
-      if isSpecial(result): return 
-      a.sons[i].sons[1] = result
-    result = a
-  of nkBracketExpr: result = evalArrayAccess(c, n, flags)
-  of nkDotExpr: result = evalFieldAccess(c, n, flags)
-  of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags)
-  of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags)
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n)
-  of nkAsgn, nkFastAsgn: result = evalAsgn(c, n)
-  of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
-  of nkWhileStmt: result = evalWhile(c, n)
-  of nkCaseStmt: result = evalCase(c, n)
-  of nkVarSection: result = evalVar(c, n)
-  of nkTryStmt: result = evalTry(c, n)
-  of nkRaiseStmt: result = evalRaise(c, n)
-  of nkReturnStmt: result = evalReturn(c, n)
-  of nkBreakStmt, nkReturnToken: result = n
-  of nkBlockExpr, nkBlockStmt: result = evalBlock(c, n)
-  of nkDiscardStmt: result = evalAux(c, n.sons[0], {})
-  of nkCheckedFieldExpr: result = evalCheckedFieldAccess(c, n, flags)
-  of nkObjDownConv: result = evalAux(c, n.sons[0], flags)
-  of nkObjUpConv: result = evalUpConv(c, n, flags)
-  of nkChckRangeF, nkChckRange64, nkChckRange: result = evalRangeChck(c, n)
-  of nkStringToCString: result = evalConvStrToCStr(c, n)
-  of nkCStringToString: result = evalConvCStrToStr(c, n)
-  of nkPassAsOpenArray: result = evalAux(c, n.sons[0], flags)
-  of nkStmtListExpr, nkStmtList, nkModule: 
-    for i in countup(0, sonsLen(n) - 1): 
-      result = evalAux(c, n.sons[i], flags)
-      case result.kind
-      of nkExceptBranch, nkReturnToken, nkBreakStmt: break 
-      else: nil
-  of nkProcDef, nkMethodDef, nkMacroDef, nkCommentStmt, nkPragma,
-     nkTypeSection, nkTemplateDef, nkConstSection, nkIteratorDef,
-     nkConverterDef, nkIncludeStmt, nkImportStmt, nkFromStmt: 
-    nil
-  of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, 
-     nkLambda, nkContinueStmt, nkIdent: 
-    stackTrace(c, n, errCannotInterpretNodeX, $n.kind)
-  else: InternalError(n.info, "evalAux: " & $n.kind)
-  if result == nil: 
-    InternalError(n.info, "evalAux: returned nil " & $n.kind)
-  inc(gNestedEvals)
-
-proc eval(c: PEvalContext, n: PNode): PNode = 
-  gWhileCounter = evalMaxIterations
-  gNestedEvals = evalMaxRecDepth
-  result = evalAux(c, n, {})
-  if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1): 
-    stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ))
-  
-proc evalConstExpr(module: PSym, e: PNode): PNode = 
-  var p = newEvalContext(module, "", true)
-  var s = newStackFrame()
-  s.call = e
-  pushStackFrame(p, s)
-  result = eval(p, e)
-  if result != nil and result.kind == nkExceptBranch: result = nil
-  popStackFrame(p)
-
-proc myOpen(module: PSym, filename: string): PPassContext = 
-  var c = newEvalContext(module, filename, false)
-  pushStackFrame(c, newStackFrame())
-  result = c
-
-proc myProcess(c: PPassContext, n: PNode): PNode = 
-  result = eval(PEvalContext(c), n)
-
-proc evalPass*(): TPass = 
-  initPass(result)
-  result.open = myOpen
-  result.close = myProcess
-  result.process = myProcess
-