/// <summary> /// Execute the continuation. /// Transfers execution to the evaluator saved when the continuation was created. /// The environment in effect at that time is also restored. /// Again, the chain of steps back to the beginning need to be clones so that this application /// does not alter the evaluation, making it impossible to return back to the continuation. /// </summary> /// <param name="args">The value to return.</param> /// <param name="env"></param> /// <param name="returnTo">The evaluator to return to. This can be different from caller if this is the last step in evaluation</param> /// <param name="caller">The calling evaluator. Not used, since control is transferred away.</param> /// <returns>The next evaluator to execute.</returns> internal override Evaluator Apply(SchemeObject args, Environment env, Evaluator returnTo, Evaluator caller) { #if Check this.CheckArgCount(ListLength(args), args, "Continuation", caller); #endif Evaluator nextStep = this.savedEvaluator.CloneChain(); nextStep.ReturnedExpr = First(args); nextStep.ReturnedEnv = this.savedEvaluator.Env; return nextStep; }
/// <summary> /// Initializes a new instance of the Environment class. /// This is used to create the global environment. /// When we refer to "parent" we mean the enclosing lexical environment. /// </summary> /// <param name="interp">The interpreter.</param> /// <param name="lexicalParent">The lexical parent environment.</param> public Environment(Interpreter interp, Environment lexicalParent) { this.interp = interp; this.lexicalParent = lexicalParent; this.symbolTable = new SymbolTable(0); if (interp != nullInterp) { interp.IncrementCounter(this.GetType().Name + ":ctor"); } }
/// <summary> /// Initializes a new instance of the EvaluateCallWithOutputFile class. /// </summary> /// <param name="args">A pair, containing a filename and a proc to evaluate.</param> /// <param name="env">The evaluation environment</param> /// <param name="caller">The caller. Return to this when done.</param> /// <param name="port">The output port.</param> private EvaluateCallWithOutputFile(SchemeObject args, Environment env, Evaluator caller, OutputPort port) : base(InitialStep, args, env, caller) { this.port = port; }
/// <summary> /// Initializes a new instance of the Environment class. /// Start out with a set of variable bindings and a lexical parent environment. /// The initial variable bindings are the formal parameters and the corresponding argument values. /// </summary> /// <param name="formals">A list of variable names.</param> /// <param name="vals">The values for these variables.</param> /// <param name="lexicalParent">The lexical parent environment.</param> public Environment(SchemeObject formals, SchemeObject vals, Environment lexicalParent) { this.interp = lexicalParent.Interp; this.lexicalParent = lexicalParent; this.symbolTable = new SymbolTable(formals, vals); }
/// <summary> /// Initializes a new instance of the Environment class. /// Creates a new empty environment. /// </summary> /// <param name="lexicalParent">The lexically enclosing environment.</param> /// <returns>The new environment.</returns> public Environment(Environment lexicalParent) : this(lexicalParent.Interp, lexicalParent) { }
/// <summary> /// Initializes a new instance of the EvaluateExpression class. /// At this point, fn is something that evaluates to a proc. /// It might be a symbol that, when looked up, resolves to a primitive or to a /// proc of some kind, like a lambda. /// It is not a symbol like "and" where there are special argument-evaluation rules, so /// the first task is to evaluate all the arguments. /// </summary> /// <param name="fn">The function to evaluate (the expression in the first position).</param> /// <param name="args">The function args to evaluate (the rest of the expressions in the list).</param> /// <param name="env">The evaluation environment</param> /// <param name="caller">The caller. Return to this when done.</param> private EvaluateExpression(SchemeObject fn, SchemeObject args, Environment env, Evaluator caller) : base(InitialStep, args, env, caller) { this.fn = fn; if (fn is Symbol) { // If the fun is a symbol, we can avoid the first step. this.Pc = ApplyProcStep; Call(fn, env, this); } else if (fn is Procedure) { // Or if the fun is already a procedure, skip the first step. this.Pc = ApplyProcStep; this.ReturnedExpr = fn; } }
/// <summary> /// Increment the variable. /// The intention is that this should be atomic. /// Used by increment! primitive. /// </summary> /// <param name="expr">The symbol whose value is incremented.</param> /// <param name="env">The environment.</param> /// <param name="caller">Return to this caller.</param> /// <returns>The next step to execute.</returns> private static Evaluator Increment(SchemeObject expr, Environment env, Evaluator caller) { SchemeObject lhs = First(expr); if (!(lhs is Symbol)) { ErrorHandlers.SemanticError(string.Format(@"Increment: first argument must be a symbol. Got: ""{0}""", lhs), null); } caller.ReturnedExpr = env.Increment(lhs); return caller; }
/// <summary> /// Evaluate a quote expression. /// </summary> /// <param name="args">The args to quote.</param> /// <param name="env">The environment (unused).</param> /// <param name="caller">The caller.</param> /// <returns>The quoted expression.</returns> private static Evaluator EvalQuote(SchemeObject args, Environment env, Evaluator caller) { caller.ReturnedExpr = First(args); return caller; }
/// <summary> /// Test the fun to apply to see if it is a special procedure. /// The special procedures do not evaluate their arguments. /// These must be implemented as primitives. /// </summary> /// <param name="args">The args to apply.</param> /// <param name="env">The environment in which to do the application.</param> /// <param name="caller">The caller to return to.</param> /// <param name="fun">The procedure to apply.</param> /// <returns>An evaluator.</returns> private static Evaluator ApplySpecial(SchemeObject args, Environment env, Evaluator caller, Procedure fun) { if (!fun.EvaluateArgs) { return fun.Apply(args, env, caller, caller); } return null; }
/// <summary> /// First check for a form that does not need to create an evaluator. If it is one of these, /// just return the answer. Otherwise create an EvaluateExpression to handle it. /// This version uses a supplied environment. This is used with a lambda /// to evaluate in the lambda's environment rather than in the current one. /// </summary> /// <param name="expr">The expression to evaluate.</param> /// <param name="env">The environment to evaluate in.</param> /// <param name="caller">The caller. Return to this when done.</param> /// <returns>The evaluator.</returns> internal static Evaluator Call(SchemeObject expr, Environment env, Evaluator caller) { // If we don't need to do any steps, then // do not create an evaluator -- just return the value directly. // // First look for a symbol. if (expr is Symbol) { var symbol = (Symbol)expr; caller.LineNumber = symbol.LineNumber; // Evaluate a symbol by looking it up in the environment. // It should correspond to a variable name, for which there // is a corresponding value. Debug.Assert(env != null, "EvaluateExpression:Call env is null"); caller.ReturnedExpr = env.Lookup(symbol); return caller; } // Look for all other non-pair forms. if (!(expr is Pair)) { // If we are evaluating something that is not a pair, // it must be a constant. // Return the integer, real, boolean, or vector. caller.ReturnedExpr = expr; return caller; } // Break apart and evaluate the fn and args // Handle special forms that do not need an evaluator instance. var obj = expr; var fn = First(obj); var args = Rest(obj); if (fn is Symbol) { var funSymbol = (Symbol)fn; caller.LineNumber = funSymbol.LineNumber; SpecialAction action = funSymbol.SpecialForm; if (action != null) { return action(args, env, caller); } if (specialActions.TryGetValue(funSymbol.ToString(), out action)) { funSymbol.SpecialForm = action; return action(args, env, caller); } // If fn is still a symbol, then it needs its arguments evaluated // and so it needs an instance of EvaluateExpression to manage that. } // Actually create an evaluator to do the operation. return new EvaluateExpression(fn, args, env, caller); }
/// <summary> /// Initializes a new instance of the Evaluator class. /// This class is not instantiated itself, but only derived classes. /// </summary> /// <param name="initialPc">The initial pc value.</param> /// <param name="args">The expression to evaluate.</param> /// <param name="env">The evaluator environment.</param> /// <param name="caller">The caller evaluator.</param> protected internal Evaluator(Stepper initialPc, SchemeObject args, Environment env, Evaluator caller) { this.expr = args; this.env = env; this.caller = caller; this.pc = initialPc; this.lineNumber = 0; this.returnedExpr = Undefined.Instance; this.returnFlag = ReturnType.SynchronousReturn; this.finished = false; this.caught = 0; #if Diagnostics this.IncrementCounter(this.GetType().Name + ":ctor"); #endif }