public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args) { ScheminList conditions = (ScheminList) args; ScheminList builtIf = new ScheminList(); builtIf.UnQuote(); ScheminList firstCondition = (ScheminList) conditions.Car(); if ((firstCondition.Car() as ScheminAtom) != null) { ScheminAtom atom = (ScheminAtom) firstCondition.Car(); if (atom.Name == "else") { ScheminList elseClause = firstCondition.Cdr(); elseClause.Cons(new ScheminPrimitive("begin")); return elseClause; } } builtIf.Append(new ScheminPrimitive("if")); builtIf.Append(firstCondition.Car()); ScheminList beginExpression = firstCondition.Cdr(); beginExpression.Cons(new ScheminPrimitive("begin")); builtIf.Append(beginExpression); if (conditions.Cdr().Length > 0) { ScheminList nextConditions = conditions.Cdr(); nextConditions.Cons(new ScheminPrimitive("cond")); builtIf.Append(nextConditions); } return builtIf; }
public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args) { IScheminType function = args.Car(); ScheminList argList = args.Cdr(); ScheminList toApply = (ScheminList) args.Cdr().Last(); ScheminList list = new ScheminList(); list.UnQuote(); foreach (IScheminType type in toApply) { list.Append(type); } foreach (IScheminType type in argList) { if (type != toApply) list.Cons(type); } list.Cons(function); return list; }
private ScheminList CombineStackFrame(ScheminList before, ScheminList after, IScheminType result) { ScheminList complete = new ScheminList(); complete.UnQuote(); if (before != null && !before.Empty) { complete.Append(before.Head); var restBefore = before.Rest; while (restBefore != null) { complete.Append(restBefore.Head); restBefore = restBefore.Rest; } } if (result != null) { complete.Append(result); } if (after != null && !after.Empty) { complete.Append(after.Head); var restAfter = after.Rest; while (restAfter != null) { complete.Append(restAfter.Head); restAfter = restAfter.Rest; } } return complete; }
public IScheminType EvaluateList(ScheminList list) { StackFrame start = new StackFrame(); start.WaitingOn = list; start.CurrentEnv = this.GlobalEnv; Stack.Clear(); Stack.Push(start); StackStart: while (Stack.Count > 0) { StackFrame current = Stack.Pop(); Environment CurrentEnv = current.CurrentEnv; ScheminList before = current.Before; ScheminList after = current.After; IScheminType WaitingOn = current.WaitingOn; if ((WaitingOn as ScheminList) == null || WaitingOn.Quoted() == true || IsEmptyList(WaitingOn)) { StackFrame next = new StackFrame(); if (before == null && after == null) { if ((WaitingOn as ScheminAtom) != null && !WaitingOn.Quoted()) { WaitingOn = EvalAtom(WaitingOn, CurrentEnv); } if (Stack.Count < 1) { return WaitingOn; } StackFrame previous = Stack.Pop(); if (previous.Before == null && previous.After == null) { next.WaitingOn = WaitingOn; } else { next.WaitingOn = CombineStackFrame(previous.Before, previous.After, WaitingOn); } // Use the previous environment in this case as well if (Stack.Count > 0) { next.CurrentEnv = Stack.Peek().CurrentEnv; } else { next.CurrentEnv = previous.CurrentEnv; } Stack.Push(next); continue; } // We need to use the PREVIOUS environment here, so peek it.. otherwise we're re-using the same environment for the previous context. StackFrame peeked = Stack.Peek(); next.WaitingOn = CombineStackFrame(before, after, WaitingOn); next.CurrentEnv = peeked.CurrentEnv; Stack.Push(next); continue; } StackFrame completeFrame = new StackFrame(); ScheminPrimitive currentPrimitive = null; ScheminList rest = (ScheminList) WaitingOn; ScheminList pendingBefore = new ScheminList(); pendingBefore.UnQuote(); if ((rest.Car() as ScheminPrimitive) != null) { if (rest.Car().Quoted() == false) { currentPrimitive = (ScheminPrimitive) rest.Car(); } } int currentArg = 0; while (!rest.Empty) { IScheminType type = rest.Car(); if (currentPrimitive != null) { if (!EvaluateNextArg(currentPrimitive, currentArg, ((ScheminList) WaitingOn).Cdr())) { pendingBefore.Append(type); rest = rest.Cdr(); currentArg++; continue; } } if ((type as ScheminAtom) != null) { if (type.Quoted()) { pendingBefore.Append(type); } else { IScheminType atomResult = EvalAtom(type, CurrentEnv); if ((atomResult as ScheminRewriter) != null) { // if we get a quoted rewriter here, we're going to apply it :( pendingBefore.Append(atomResult); QuoteAll(rest.Cdr()); } else { pendingBefore.Append(atomResult); } } } else if ((type as ScheminList) != null) { ScheminList tempList = (ScheminList) type; if (tempList.Quoted() || tempList.Empty) { pendingBefore.Append(type); rest = rest.Cdr(); currentArg++; continue; } StackFrame next = new StackFrame(); next.WaitingOn = type; next.After = rest.Cdr(); next.Before = pendingBefore; next.CurrentEnv = CurrentEnv; Stack.Push(current); Stack.Push(next); goto StackStart; } else { pendingBefore.Append(type); } rest = rest.Cdr(); currentArg++; } IScheminType functionPosition = pendingBefore.Car(); ScheminList functionArgs = pendingBefore.Cdr(); if ((functionPosition as ScheminPrimitive) != null) { ScheminPrimitive prim = (ScheminPrimitive) functionPosition; completeFrame.Before = before; completeFrame.After = after; // Need to pass push the previous frame back on so we can get access to the current continuation via the evaluator's Stack field. // also adding the primitive's name to the exception if it gets thrown. try { Stack.Push(current); completeFrame.WaitingOn = prim.Evaluate(functionArgs, CurrentEnv, this); Stack.Pop(); } catch (BadArgumentsException ba) { Token sourceToken = prim.SourceToken; string line = String.Empty; if (sourceToken != null) { line = " line: " + sourceToken.LineNumber.ToString() + " col: " + sourceToken.ColNumber.ToString(); } throw new BadArgumentsException(prim.ToString() + " " + ba.Message + line); } completeFrame.CurrentEnv = CurrentEnv; Stack.Push(completeFrame); continue; } else if ((functionPosition as ScheminLambda) != null) { ScheminLambda lam = (ScheminLambda) functionPosition; completeFrame.Before = before; completeFrame.After = after; Environment args = lam.MakeEnvironment(functionArgs, this); completeFrame.WaitingOn = lam.Definition; completeFrame.CurrentEnv = args; Stack.Push(completeFrame); continue; } else if ((functionPosition as ScheminContinuation) != null) { ScheminContinuation con = (ScheminContinuation) functionPosition; this.Stack = new Stack<StackFrame>(con.PreviousStack); this.Stack.Peek().WaitingOn = functionArgs.Car(); continue; } else if ((functionPosition as ScheminRewriter) != null) { ScheminRewriter rewriter = (ScheminRewriter) functionPosition; QuoteAll(functionArgs); IScheminType result = rewriter.Rewrite(functionArgs); completeFrame.Before = before; completeFrame.After = after; completeFrame.WaitingOn = result; completeFrame.CurrentEnv = CurrentEnv; this.Stack.Push(completeFrame); continue; } else { throw new InvalidOperationException("Non-function in function position: " + functionPosition.ToString()); } } throw new InvalidOperationException("Control escaped list evaluator..."); }
public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args) { bool isNamed = false; if ((args.Car() as ScheminAtom) != null) { isNamed = true; } ScheminList bindings; ScheminList expression; if (!isNamed) { expression = args.Cdr(); bindings = (ScheminList) args.Car(); } else { expression = args.Cdr().Cdr(); bindings = (ScheminList) args.Cdr().Car(); } ScheminList letArgs = new ScheminList(); ScheminList argExps = new ScheminList(); letArgs.UnQuote(); argExps.UnQuote(); foreach (ScheminList bindingPair in bindings) { letArgs.Append(bindingPair.Car()); argExps.Append(bindingPair.Cdr().Car()); } ScheminList lambdaDef = new ScheminList(letArgs); lambdaDef.UnQuote(); foreach (IScheminType type in expression) { lambdaDef.Append(type); } Environment closure = env; if (isNamed) { closure = new Environment(); closure.parent = env; } ScheminLambda lam = new ScheminLambda(lambdaDef, closure); if (isNamed) { ScheminAtom name = (ScheminAtom) args.Car(); closure.AddBinding(name, lam); } ScheminList toEvaluate = new ScheminList(lam); toEvaluate.UnQuote(); foreach (IScheminType arg in argExps) { toEvaluate.Append(arg); } return toEvaluate; }
public override IScheminType Execute(Environment env, Evaluator eval, ScheminList args) { bool deffun = false; if ((args.Car() as ScheminList) != null) { deffun = true; } if (!deffun) { ScheminAtom symbol = (ScheminAtom) args.Car(); IScheminType definition = args.Cdr().Car(); if (env.bindings.ContainsKey(symbol.Name)) { env.RemoveBinding(symbol); env.AddBinding(symbol, definition); } else { env.AddBinding(symbol, definition); } return new ScheminList(false); } else { ScheminList arguments = (ScheminList) args.Car(); ScheminList expression = args.Cdr(); ScheminAtom name = (ScheminAtom) arguments.Car(); ScheminList argSymbols = arguments.Cdr(); ScheminList lamArgs = new ScheminList(argSymbols, expression); lamArgs.UnQuote(); ScheminLambda lam = new ScheminLambda(lamArgs, env); if (env.bindings.ContainsKey(name.Name)) { env.RemoveBinding(name); env.AddBinding(name, lam); } else { env.AddBinding(name, lam); } return new ScheminList(false); } }