public static List<object> PairToList(Pair l) { List<object> r = new List<object>(); while (l != null) { r.Add(l.Car); l = (Pair)l.Cdr; } return r; }
public static Pair ListToPair(List<object> l) { Pair r = null; for (int i = l.Count - 1; i >= 0; --i) { r = new Pair() { Car = l[i], Cdr = r }; } return r; }
private ByteCodeInterpreter() { Utils.QueryPerformanceCounter(out mTimerStart); Utils.QueryPerformanceFrequency(out mTimerFreq); Dictionary<string, object> builtinVars = new Dictionary<string, object>() { {"true", true}, {"false", false}, {"else", true}, {"null", null}, }; Dictionary<string, HostProcedure> builtinProcedures = new Dictionary<string, HostProcedure>() { {"not", (stack, ret) => stack[ret]=!(bool)stack[ret+1]}, {"identity", (stack, ret) => stack[ret]=stack[ret+1]}, {"sqr", (stack, ret) => {var a = (INumber)stack[ret+1]; stack[ret]=a.Mul(a);} }, {"+", (stack, ret) => stack[ret]=((INumber)stack[ret+1]).Add((INumber)stack[ret+2])}, {"-", (stack, ret) => stack[ret]=((INumber)stack[ret+1]).Sub((INumber)stack[ret+2])}, {"*", (stack, ret) => stack[ret]=((INumber)stack[ret+1]).Mul((INumber)stack[ret+2])}, {"/", (stack, ret) => stack[ret]=((INumber)stack[ret+1]).Div((INumber)stack[ret+2])}, {"quotient", (stack, ret) => stack[ret]=((INumber)stack[ret+1]).Div((INumber)stack[ret+2]).CastToInteger()}, {"remainder", (stack, ret) => stack[ret]=((INumber)stack[ret+1]).Mod((INumber)stack[ret+2])}, {"=", (stack, ret) => stack[ret]=stack[ret+1].Equals(stack[ret+2])}, {"<", (stack, ret) => stack[ret]=(stack[ret+1] as IComparable).CompareTo(stack[ret+2]) < 0}, {"<=", (stack, ret) => stack[ret]=(stack[ret+1] as IComparable).CompareTo(stack[ret+2]) <= 0}, {">", (stack, ret) => stack[ret]=(stack[ret+1] as IComparable).CompareTo(stack[ret+2]) > 0}, {">=", (stack, ret) => stack[ret]=(stack[ret+1] as IComparable).CompareTo(stack[ret+2]) >= 0}, {"eq?", (stack, ret) => stack[ret]=object.ReferenceEquals(stack[ret+1], stack[ret+2])}, {"cons", (stack, ret) => stack[ret]=new Pair() { Car = stack[ret+1], Cdr = stack[ret+2] }}, {"car", (stack, ret) => stack[ret]=((Pair)stack[ret+1]).Car}, {"cdr", (stack, ret) => stack[ret]=((Pair)stack[ret+1]).Cdr}, {"drop", (stack, ret) => { Pair l = (Pair)stack[ret+1]; int n = ((NumberInteger)stack[ret+2]).value; for (; n > 0; --n) { l = (Pair)l.Cdr; } stack[ret] = l; }}, {"length", (stack, ret) => { int n = 0; for (Pair l = (Pair)stack[ret+1]; l != null; ++n, l = (Pair)l.Cdr) ; stack[ret] = Number.Create(n); }}, {"append", (stack, ret) => { var l = ListProcess.PairToList((Pair)stack[ret+1]); l.InsertRange(l.Count, ListProcess.PairToList((Pair)stack[ret+2])); stack[ret] = ListProcess.ListToPair(l); }}, {"empty?", (stack, ret) => stack[ret]=stack[ret+1] == null}, {"pretty-print", (stack, ret) => { ListProcess.PrintPairExp(stack[ret+1]); stack[ret] = null; }}, {"display", (stack, ret) => { ListProcess.PrintListExp(ListProcess.PairExpToListExp(stack[ret+1])); stack[ret] = null; }}, {"current-inexact-milliseconds", (stack, ret) => { long now; Utils.QueryPerformanceCounter(out now); stack[ret] = Number.Create((decimal)(now - mTimerStart) * 1000 / mTimerFreq); }}, {"exit", (stack, ret) => { Environment.Exit(0); stack[ret] = null; }}, {"random", (stack, ret) => stack[ret] = Number.Create(mRandom.Next(((NumberInteger)stack[ret+1]).value))}, {"eval", (stack, ret) => stack[ret] = Interpret(ListProcess.PairExpToListExp(stack[ret+1]))}, }; GlobalEnv.Instance().ReserveVariables(builtinVars.Count + builtinProcedures.Count); foreach (KeyValuePair<string, object> kv in builtinVars) { GlobalEnv.Instance().variables[SymbolTable.DefineOrGetGlobalSymbol(kv.Key).index] = kv.Value; } foreach (KeyValuePair<string, HostProcedure> kv in builtinProcedures) { GlobalEnv.Instance().variables[SymbolTable.DefineOrGetGlobalSymbol(kv.Key).index] = kv.Value; } }