# # # The Nimrod Compiler # (c) Copyright 2012 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, renderer, types, passes, semfold, transf, parser, ropes, rodread, idgen, osproc, streams 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 TEvalMode* = enum ## reason for evaluation emRepl, ## evaluate because in REPL mode emConst, ## evaluate for 'const' according to spec emOptimize, ## evaluate for optimization purposes (same as ## emConst?) emStatic ## evaluate for enforced compile time eval ## ('static' context) TEvalContext* = object of passes.TPassContext module*: PSym tos*: PStackFrame # top of stack lastException*: PNode mode*: TEvalMode globals*: TIdNodeTable # state of global vars PEvalContext* = ref TEvalContext TEvalFlag = enum efNone, efLValue TEvalFlags = set[TEvalFlag] const evalMaxIterations = 500_000 # max iterations of all loops evalMaxRecDepth = 10_000 # max recursion depth for evaluation # other idea: 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, mode: TEvalMode): PEvalContext = new(result) result.module = module result.mode = mode initIdNodeTable(result.globals) 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 evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode = result = newNodeI(nkExceptBranch, info) # creating a nkExceptBranch without sons # means that it could not be evaluated 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: PEv
import os
proc findNodeJs*(): string =
result = findExe("nodejs")
if result == "":
result = findExe("node")
if result == "":
result = findExe("iojs")