public Object eval(Env env) { Object f = fexpr.eval(env); Object[] args = new Object[argexprs.Length]; for (Int32 i = 0; i < args.Length; i++) args[i] = argexprs[i].eval(env); Boolean doTrace = fsym != null && interpreter.traceList.Contains(fsym); try { if (doTrace) { interpreter.trace(fsym.name, args); Trace.Indent(); Object ret = Util.InvokeObject(f, args); Trace.Unindent(); return ret; } else return Util.InvokeObject(f, args); } catch (Exception ex) { if (fsym != null && !fsym.name.Equals("throw")) { throw BacktraceException.push(ex, new BacktraceFrame(loc, fsym, args) , interpreter); } else { throw ex; } } }
internal Closure(Cons args, Env env, Interpreter interpreter, Loc loc) { this.interpreter = interpreter; this.loc = loc; ArgSpecs specs = analyzeArgSpec((Cons)args.first, env, loc); //create an env expanded by params in which to analyze body Env env2 = new Env(specs.parameters, null, env); this.argSpecs = specs; this.body = interpreter.analyze(new Cons(interpreter.BLOCK, args.rest), env2, loc); this.env = env; }
internal ApplyExpression(Cons args, Env env, Interpreter interpreter, Loc loc) { this.loc = loc; this.interpreter = interpreter; fexpr = interpreter.analyze(args.first, env, loc); if (fexpr is IVar) { fsym = ((IVar)fexpr).getSymbol(); } Int32 len = Cons.Length(args.rest); argexprs = new IExpression[len]; args = args.rest; for (Int32 i = 0; i < argexprs.Length; i++, args = args.rest) { argexprs[i] = interpreter.analyze(args.first, env, loc); } }
public Interpreter() { globalenv = new Env(null, null, null); reader = new Reader(this); symbolTable = new SymbolTable(); Assembly[] asm = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly a in asm) { addTypesFrom(a); } internBuiltins(); Primitives.internAll(this); LASTVAL.setGlobalValue(null); NEXTLASTVAL.setGlobalValue(null); THIRDLASTVAL.setGlobalValue(null); //these primitives are here, rather than in Primitives, because their implementation //requires calls to gfs bound to symbols Intern("intern", new Function(internf)); Intern("eval", new Function(evalf)); Intern("load", new Function(loadf)); Intern("map->list", new Function(map_to_list)); Intern("apply", new Function(apply)); Intern("<", new Function(lt)); Intern("<=", new Function(lteq)); Intern(">", new Function(gt)); Intern(">=", new Function(gteq)); Intern("==", new Function(eqeq)); Intern("!=", new Function(noteq)); strgf = (GenericFunction)intern("str").getGlobalValue(); get_enum_gf = (GenericFunction)intern("get-enum").getGlobalValue(); compare_gf = (BinOp)intern("compare").getGlobalValue(); Intern("interpreter", this); }
public Object eval(Env env) { try { Object retval = val.eval(env); var.setval(retval, env); return retval; } catch (BacktraceException bex) { throw bex; } catch (Exception ex) { throw BacktraceException.push(ex, new BacktraceFrame(loc, "set", null), interpreter); } }
internal SetExpression(Cons args, Env env, Interpreter interpreter, Loc loc) { this.loc = loc; this.interpreter = interpreter; Int32 len = Cons.Length(args); if (len != 2) throw new Exception("Wrong number of args for set"); var = (IVar)interpreter.analyze(args.first, env, loc); val = interpreter.analyze(Cons.Second(args), env, loc); }
//parse out params from spec (which may contain &optional, &key, &rest, initforms etc internal ArgSpecs analyzeArgSpec(Cons arglist, Env env, Loc loc) { //count the params int nParams = 0; Cons a = arglist; while (a != null) { Object p = a.first; if (p != interpreter.AMPOPT && p != interpreter.AMPKEY && p != interpreter.AMPREST) ++nParams; a = a.rest; } ArgSpecs ret = new ArgSpecs(env); ret.parameters = new Parameter[nParams]; Parameter.Spec state = Parameter.Spec.REQ; int param = 0; a = arglist; while (a != null) { Object p = a.first; switch (state) { case Parameter.Spec.REQ: if (p == interpreter.AMPOPT) state = Parameter.Spec.OPT; else if (p == interpreter.AMPKEY) state = Parameter.Spec.KEY; else if (p == interpreter.AMPREST) state = Parameter.Spec.REST; else { if (p is Symbol) { ret.parameters[param++] = new Parameter((Symbol)p, Parameter.Spec.REQ, null); ++ret.numReq; } else if (p is Cons) { ret.parameters[param] = new Parameter((Symbol)((Cons)p).first, Parameter.Spec.REQ, null); ret.parameters[param].typeSpec = interpreter.eval(Cons.Second((Cons)p), env); ++param; ++ret.numReq; } } break; case Parameter.Spec.OPT: if (p == interpreter.AMPOPT) throw new Exception("&optional can appear only once in arg list"); else if (p == interpreter.AMPKEY) state = Parameter.Spec.KEY; else if (p == interpreter.AMPREST) state = Parameter.Spec.REST; else { if (p is Symbol) { ret.parameters[param++] = new Parameter((Symbol)p, Parameter.Spec.OPT, null); ++ret.numOpt; } else if (p is Cons) { ret.parameters[param++] = new Parameter((Symbol)((Cons)p).first, Parameter.Spec.OPT, interpreter.analyze(Cons.Second((Cons)p), env, loc)); ++ret.numOpt; } else throw new Exception("&optional parameters must be symbols or (symbol init-form)"); } break; case Parameter.Spec.KEY: if (p == interpreter.AMPOPT) throw new Exception("&optional must appear before &key in arg list"); else if (p == interpreter.AMPKEY) throw new Exception("&key can appear only once in arg list"); else if (p == interpreter.AMPREST) state = Parameter.Spec.REST; else { if (p is Symbol) { ret.parameters[param] = new Parameter((Symbol)p, Parameter.Spec.KEY, null); ret.parameters[param].key = interpreter.intern(":" + ((Symbol)p).name); ++param; ++ret.numKey; } else if (p is Cons) { ret.parameters[param] = new Parameter((Symbol)((Cons)p).first, Parameter.Spec.KEY, interpreter.analyze(Cons.Second((Cons)p), env, loc)); ret.parameters[param].key = interpreter.intern(":" + ((Symbol)((Cons)p).first).name); ++param; ++ret.numKey; } else throw new Exception("&key parameters must be symbols or (symbol init-form)"); } break; case Parameter.Spec.REST: if (p == interpreter.AMPOPT) throw new Exception("&optional must appear before &rest in arg list"); else if (p == interpreter.AMPKEY) throw new Exception("&key must appear before &rest in arg list"); else if (p == interpreter.AMPREST) throw new Exception("&rest can appear only once in arg list"); else { if (!(p is Symbol)) throw new Exception("&rest parameter must be a symbol"); else { if (ret.numRest > 0) //already got a rest param throw new Exception("Only one &rest arg can be specified"); ret.parameters[param++] = new Parameter((Symbol)p, Parameter.Spec.REST, null); ++ret.numRest; } } break; } a = a.rest; } return ret; }
internal IExpression analyze(Object expr, Env env, Loc enclosingLoc) { Symbol symbol = expr as Symbol; if (symbol != null) { if (symbol.isDynamic) return new DynamicVar(symbol); Object var = env.lookup(symbol); if (var is LocalVariable) return new LocalVar((LocalVariable)var); else return new GlobalVar((Symbol)var); } if (!(expr is Cons)) //must be literal return new QuoteExpr(expr); Cons exprs = (Cons)expr; Loc loc = (Loc)reader.locTable[expr]; if (loc != null) reader.locTable.Remove(expr); else loc = enclosingLoc; Object f = exprs.first; Cons args = exprs.rest; //see if it's a macro Symbol s = f as Symbol; if (s != null && s.isDefined() && s.getGlobalValue() is Macro) { Macro m = (Macro)s.getGlobalValue(); Object[] argarray = Cons.ToVector(args); Object mexprs = null; try { mexprs = m.Invoke(argarray); } catch (Exception ex) { BacktraceFrame frame = new BacktraceFrame(loc, s, args); throw BacktraceException.push(ex, frame, this); } try { return analyze(mexprs, env, loc); } catch (Exception ex) { BacktraceFrame frame = new BacktraceFrame(loc, "when expanding ", exprs); throw BacktraceException.push(ex, frame, this); } } Int32 numargs = Cons.Length(args); if (f == DLET) return new DynamicLet(args, env, this, loc); else if (f == FN) return new Closure(args, env, this, loc); else if (f == MACRO) return new Macro(args, env, this, loc); else if (f == WHILE) return new WhileExpression(args, env, this, loc); else if (f == BLOCK) { if (numargs == 0) return new QuoteExpr(null); //remove block from block of one else if (numargs == 1) return analyze(args.first, env, loc); else return new BlockExpression(args, env, this, loc); } else if (f == OR) { if (numargs == 0) return new QuoteExpr(null); else return new OrExpression(args, env, this, loc); } else if (f == IF) return new IfExpression(args, env, this, loc); else if (f == QUOTE) return new QuoteExpr(args.first); else if (f == SET) return new SetExpression(args, env, this, loc); else //presume funcall return new ApplyExpression(exprs, env, this, loc); }
internal DynamicLet(Cons args, Env env, Interpreter interpreter, Loc loc) { this.loc = loc; this.interpreter = interpreter; Cons bindlist = (Cons)args.first; Int32 blen = Cons.Length(bindlist); if ((blen % 2) != 0) //odd { throw new Exception("Odd number of args in dynamic-let binding list"); } binds = new BindPair[blen / 2]; for (int i = 0; i < binds.Length; i++) { binds[i].dvar = (DynamicVar)interpreter.analyze(bindlist.first, env, loc); bindlist = bindlist.rest; binds[i].expr = interpreter.analyze(bindlist.first, env, loc); bindlist = bindlist.rest; } this.body = interpreter.analyze(new Cons(interpreter.BLOCK, args.rest), env, loc); }
public Object eval(Env env) { try { while (Util.isTrue(test.eval(env))) { body.eval(env); } return null; } catch (BacktraceException bex) { throw bex; } catch (Exception ex) { throw BacktraceException.push(ex, new BacktraceFrame(loc, "set", null), interpreter); } }
public Object eval(Env env) { try { if (Util.isTrue(test.eval(env))) return brtrue.eval(env); return brfalse.eval(env); } catch (BacktraceException bex) { throw bex; } catch (Exception ex) { throw BacktraceException.push(ex, new BacktraceFrame(loc, "if", null), interpreter); } }
internal IfExpression(Cons args, Env env, Interpreter interpreter, Loc loc) { this.loc = loc; this.interpreter = interpreter; Int32 len = Cons.Length(args); if (len < 2 || len > 3) throw new Exception("Wrong number of args for if"); test = interpreter.analyze(args.first, env, loc); brtrue = interpreter.analyze(Cons.Second(args), env, loc); if (len == 3) brfalse = interpreter.analyze(Cons.Third(args), env, loc); else brfalse = new QuoteExpr(null); }
public void setval(Object val, Env env) { sym.setGlobalValue(val); }
public Object eval(Env env) { return sym.getGlobalValue(); }
public void setval(Object val, Env env) { DynamicEnv d = DynamicEnv.find(sym); if (d != null) d.val = val; sym.setGlobalValue(val); }
public Object eval(Env env) { DynamicEnv d = DynamicEnv.find(sym); if (d != null) return d.val; return sym.getGlobalValue(); }
public Object eval(Env env) { DynamicEnv olddenv = DynamicEnv.current(); try { for (int i = 0; i < binds.Length; i++) { DynamicEnv.extend(binds[i].dvar.sym, binds[i].expr.eval(env)); } return body.eval(env); } catch (BacktraceException bex) { throw bex; } catch (Exception ex) { throw BacktraceException.push(ex, new BacktraceFrame(loc, "set", null), interpreter); } finally { DynamicEnv.restore(olddenv); } }
internal WhileExpression(Cons args, Env env, Interpreter interpreter, Loc loc) { this.loc = loc; this.interpreter = interpreter; this.test = interpreter.analyze(args.first, env, loc); this.body = interpreter.analyze(new Cons(interpreter.BLOCK, args.rest), env, loc); }
internal Env(Parameter[] vars, Object[] vals, Env parent) { this.vars = vars; this.vals = vals; this.parent = parent; }
internal ArgSpecs copy(Env env) { ArgSpecs a = (ArgSpecs)MemberwiseClone(); a.env = env; return a; }
public Object eval(Env env) { return env.getValue(var); }
public Object eval(Env env) { try { for (Int32 i = 0; i < exprs.Length - 1; i++) exprs[i].eval(env); return exprs[exprs.Length - 1].eval(env); } catch (BacktraceException bex) { throw bex; } catch (Exception ex) { throw BacktraceException.push(ex, new BacktraceFrame(loc, "set", null), interpreter); } }
internal ArgSpecs(Env env) { this.env = env; }
public void setval(Object val, Env env) { env.setValue(var, val); }
internal IExpression analyze(Object expr, Env env) { return analyze(expr, env, null); }
internal OrExpression(Cons args, Env env, Interpreter interpreter, Loc loc) { this.loc = loc; this.interpreter = interpreter; exprs = new IExpression[Cons.Length(args)]; for (Int32 i = 0; i < exprs.Length; i++, args = args.rest) { exprs[i] = interpreter.analyze(args.first, env, loc); } }
internal Object eval(Object x, Env env) { IExpression analyzedCode = analyze(x, env); return analyzedCode.eval(env); //Object analyzedCode = analyze(x,env); //return execute(analyzedCode, env); }
public Object eval(Env env) { try { for (Int32 i = 0; i < exprs.Length - 1; i++) { Object result = exprs[i].eval(env); if (Util.isTrue(result)) return result; } return exprs[exprs.Length - 1].eval(env); } catch (BacktraceException bex) { throw bex; } catch (Exception ex) { throw BacktraceException.push(ex, new BacktraceFrame(loc, "set", null), interpreter); } }
internal Macro(Cons args, Env env, Interpreter interpreter, Loc loc) : base(args, env, interpreter, loc) { }
public Object eval(Env env) { return val; }