/// <summary>
 /// Initializes a new instance of the EvaluateTimeBase class.
 /// </summary>
 /// <param name="expr">The expression to evaluate.</param>
 /// <param name="count">The number of times to evaluate.</param>
 /// <param name="env">The evaluation environment</param>
 /// <param name="caller">The caller.  Return to this when done.</param>
 protected EvaluateTimeBase(SchemeObject expr, int count, Environment env, Evaluator caller)
     : base(InitialStep, expr, env, caller)
 {
     this.counter = count;
     this.startMem = GC.GetTotalMemory(true);
     this.stopwatch = Stopwatch.StartNew();
 }
 /// <summary>
 /// Initializes a new instance of the SynchronousClrProcedure class.
 /// </summary>
 /// <param name="targetClassName">The class of the object to invoke.</param>
 /// <param name="methodName">The method to invoke.</param>
 /// <param name="instanceClass">The type of the instance argument.  Null if static or constructor.</param>
 /// <param name="argClasses">The types of each argument.</param>
 /// <param name="caller">The calling evaluator.</param>
 private SynchronousClrProcedure(string targetClassName, string methodName, Type instanceClass, Type[] argClasses, Evaluator caller)
     : base(targetClassName, 
         methodName, 
         GetMethodInfo(targetClassName, methodName, argClasses, caller), 
         instanceClass,
         argClasses, 
         argClasses.Length)
 {
 }
 /// <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>
        /// Call the parallel evaluator.
        /// </summary>
        /// <param name="expr">The expressions 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 parallel evaluator.</returns>
        internal static Evaluator Call(SchemeObject expr, Environment env, Evaluator caller)
        {
            if (expr is EmptyList)
            {
                caller = caller.Caller;
                caller.ReturnedExpr = EmptyList.Instance;
                return caller;
            }

            return new EvaluateParallel(expr, env, caller);
        }
 /// <summary>
 /// Initializes a new instance of the AsynchronousClrProcedure class.
 /// </summary>
 /// <param name="targetClassName">The class name of the CLR function.</param>
 /// <param name="methodName">The method name of the CLR function.</param>
 /// <param name="instanceClass">The type of the instance argument.  Null if static or constructor.</param>
 /// <param name="argClasses">The types of all method arguments.</param>
 /// <param name="caller">The calling evaluator.</param>
 internal AsynchronousClrProcedure(string targetClassName, string methodName, Type instanceClass, Type[] argClasses, Evaluator caller)
     : base(targetClassName, 
         methodName, 
         GetMethodInfo(targetClassName, "Begin" + methodName, argClasses, caller), 
         instanceClass,
         argClasses, 
         argClasses.Length - 1)
 {
     var endClasses = new[] { typeof(IAsyncResult) };
     this.endMethodInfo = GetMethodInfo(targetClassName, "End" + methodName, endClasses, caller);
 }
        /// <summary>
        /// Closes the output port and returns the evaluation result.
        /// </summary>
        /// <param name="s">This evaluator.</param>
        /// <returns>The evaluation result.</returns>
        private static Evaluator CloseStep(Evaluator s)
        {
            var step = (EvaluateCallWithOutputFile)s;
            if (step.port != null)
            {
                step.port.Close();
            }

            Evaluator caller = step.Caller;
            caller.ReturnedExpr = s.ReturnedExpr;
            return caller;
        }
        /// <summary>
        /// Back here after expression evaluation.  
        /// Increment and test the counter.
        /// If not done, loop back.
        /// Otherwise, calculate elapsed time and mem use.
        /// </summary>
        /// <param name="s">This evaluator.</param>
        /// <returns>Continue, or else give the timer results.</returns>
        protected static Evaluator CompleteStep(Evaluator s)
        {
            var step = (EvaluateTimeBase)s;
            step.i++;
            if (step.i < step.counter)
            {
                s.Pc = EvaluateStep;
                return s;
            }

            step.stopwatch.Stop();
            long time = step.stopwatch.ElapsedMilliseconds;
            long mem = GC.GetTotalMemory(false) - step.startMem;
            Evaluator caller = step.Caller;
            caller.ReturnedExpr =
                MakeList(
                    s.ReturnedExpr,
                    MakeList((Number)time,  (Symbol)"msec"),
                    MakeList((Number)mem, (Symbol)"bytes"));
            return caller;
        }
Exemple #8
0
        /// <summary>
        /// Initializes a new instance of the Interpreter class.
        /// Create an interpreter and install the primitives into the global environment.
        /// Then read a list of files.
        /// </summary>
        /// <param name="loadStandardMacros">Load standard macros and other primitives.</param>
        /// <param name="primEnvironment">Environment containing the primitives (can be null).</param>
        /// <param name="files">The files to read.</param>
        /// <param name="reader">The input reader.</param>
        /// <param name="writer">The output writer.</param>
        private Interpreter(
            bool loadStandardMacros, 
            PrimitiveEnvironment primEnvironment, 
            IEnumerable<string> files, 
            TextReader reader, 
            TextWriter writer)
        {
            this.Trace = false;
            this.Count = false;
            this.Transcript = new TranscriptLogger(this);
            this.CurrentInputPort = InputPort.New(reader ?? Console.In, this);
            this.CurrentOutputPort = OutputPort.New(writer ?? Console.Out, this);
            this.PrimEnvironment = primEnvironment ?? new PrimitiveEnvironment();

            this.CurrentCounters = new Counter();
            this.GlobalEnvironment = new Environment(this, this.PrimEnvironment);
            this.halted = new HaltedEvaluator(this.GlobalEnvironment);
            var echo = (writer != null) ? this.CurrentOutputPort : null;
            try
            {
                if (loadStandardMacros)
                {
                    this.Load(SchemePrimitives.Code);
                }

                if (files != null)
                {
                    foreach (string file in files)
                    {
                        this.LoadFile((Symbol)file, echo);
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorHandlers.PrintException(ex);
            }
        }
 /// <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>
 /// Start by setting up timers and counter.
 /// </summary>
 /// <param name="s">This evaluator.</param>
 /// <returns>Continue to next step.</returns>
 private static Evaluator InitialStep(Evaluator s)
 {
     var step = (EvaluateTimeBase)s;
     step.i = 0;
     s.Pc = EvaluateStep;
     return s;
 }
        /// <summary>
        /// Comes back here after evaluation completes synchronously or is suspended.
        /// If evaluation is suspended, then EvaluateExpressionWithCatch will catch and return undefined.
        /// Loop back and evaluate another expression.
        /// Continue looping until all evaluations return an actual result.
        /// Accumulate the results and return when everything finishes.
        /// </summary>
        /// <param name="s">This evaluator.</param>
        /// <returns>Immediately steps back.</returns>
        private static Evaluator LoopStep(Evaluator s)
        {
            var step = (EvaluateParallel)s;
            lock (step.lockObj)
            {
                step.FetchReturnValue();
                switch (step.ReturnFlag)
                {
                    case ReturnType.CaughtSuspended:
                        // caught an asynchronous suspension -- go on to the next expr
                        step.forked++;
                        break;
                    case ReturnType.AsynchronousReturn:
                        // return after suspension
                        // Record return result and either end the thread or
                        //  return from the whole thing.
                        step.accum = Cons(step.ReturnedExpr, step.accum);
                        step.joined++;
                        if (step.joined < step.forked || !(s.Expr is EmptyList))
                        {
                            return new FinalEvaluator(Undefined.Instance);
                        }

                        Evaluator caller = step.Caller;
                        caller.ReturnedExpr = step.accum;
                        return caller;

                    case ReturnType.SynchronousReturn:
                        // synchronous return
                        step.accum = Cons(step.ReturnedExpr, step.accum);
                        break;
                }

                s.Expr = Rest(s.Expr);
                if (s.Expr is EmptyList)
                {
                    // finished with expressions -- either suspend (if there is more pending) or
                    //   return from the whole thing
                    if (step.joined < step.forked)
                    {
                        s.Pc = LoopStep;
                        return new SuspendedEvaluator(s.ReturnedExpr, s).NextStep();
                    }

                    Evaluator caller = step.Caller;
                    caller.ReturnedExpr = step.accum;
                    return caller;
                }

                s.Pc = LoopStep;
                return EvaluateExpressionWithCatch.Call(First(s.Expr), s.Env, s);
            }
        }
 /// <summary>
 /// Create an evaluator with output file.
 /// </summary>
 /// <param name="args">A pair, containing a filename and a proc to evaluate.</param>
 /// <param name="caller">The caller.  Return to this when done.</param>
 /// <returns>The created evaluator.</returns>
 internal static Evaluator Call(SchemeObject args, Evaluator caller)
 {
     OutputPort port = OpenOutputFile(First(args), caller.Interp);
     return new EvaluateCallWithOutputFile(args, caller.Env, caller, port);
 }
 /// <summary>
 /// Open the output file and apply the proc.
 /// </summary>
 /// <param name="s">This evaluator.</param>
 /// <returns>The next step in the application, or if the result is ready, 
 /// continues to the next step.</returns>
 private static Evaluator InitialStep(Evaluator s)
 {
     var step = (EvaluateCallWithOutputFile)s;
     var proc = Second(s.Expr);
     s.Pc = CloseStep;
     return ((Procedure)proc).Apply(MakeList(step.port), null, s, s);
 }
Exemple #14
0
 /// <summary>
 /// Initializes a new instance of the Continuation class.
 /// The evaluator and its chain of evaluators back to the beginning have to be cloned because they
 ///   hold information about the progress of the evaluation.  When the evaluation proceeds
 ///   these evaluators might be altered, damaging the ability to continue, which is what makes the
 ///   clone necessary.
 /// </summary>
 /// <param name="eval">The continuation to return to when applied.</param>
 /// <returns>A new continuation.</returns>
 public static Continuation New(Evaluator eval)
 {
     return new Continuation(eval);
 }
 /// <summary>
 /// Take a list of CLR method arguments and turn them into an array, suitable for
 ///   calling the method.
 /// Add the extra async arguments for the Begin call.
 /// Check to make sure the number and types of the arguments in the list match 
 ///    what is expected.
 /// </summary>
 /// <param name="args">A list of the method arguments.</param>
 /// <param name="state">State, passed on to completion function.</param>
 /// <param name="caller">The calling evaluator.</param>
 /// <returns>An array of arguments for the method call.</returns>
 private object[] ToArgListBegin(SchemeObject args, object state, Evaluator caller)
 {
     object[] additionalArgs = { (AsyncCallback)this.CompletionMethod, state };
     return this.ToArgList(args, additionalArgs, "AsynchronousClrProcedure", caller);
 }
Exemple #16
0
        /// <summary>
        /// Take a list of CLR method arguments and turn them into a list, suitable for
        ///   calling the method.
        /// Check to make sure the number and types of the arguments in the list match 
        ///    what is expected.
        /// </summary>
        /// <param name="args">A list of the method arguments.</param>
        /// <param name="additionalArgs">A list of the additional args, not supplied by the caller. 
        /// These are part of the asynchronous calling pattern.</param>
        /// <param name="evaluatorName">The evaluator name, for the error message.</param>
        /// <param name="caller">The calling evaluator.</param>
        /// <returns>An array of arguments for the method call.</returns>
        protected object[] ToArgList(SchemeObject args, object[] additionalArgs, string evaluatorName, Evaluator caller)
        {
            // This has been checked once already, in Procedure.CheckArgCount, but that included
            //  an instance argument.  Check again to protect the rest of this method.
            int additionalN = additionalArgs != null ? additionalArgs.Length : 0;
            int numArgs = ListLength(args) + additionalN;
            int expectedArgs = this.ArgClasses.Length;
            if (numArgs != expectedArgs)
            {
                this.ArgCountError(numArgs, expectedArgs, args, evaluatorName, caller);
            }

            var array = new object[numArgs];

            int a = 0;
            while (args is Pair)
            {
                array[a] = ClrObject.ToClrObject(First(args), this.ArgClasses[a]);
                a++;
                args = Rest(args);
            }

            for (int i = 0; i < additionalN; i++)
            {
                Debug.Assert(additionalArgs != null, "ClrProcedure: additionalArgs != null");
                array[a++] = additionalArgs[i];
            }

            return array;
        }
Exemple #17
0
        /// <summary>
        /// Look up the method info.
        /// </summary>
        /// <param name="className">The class name of the class to get method info about</param>
        /// <param name="theMethodName">The method name</param>
        /// <param name="argClassList">The argument types.</param>
        /// <param name="caller">The calling evaluator.</param>
        /// <returns>The method info for the method.</returns>
        protected static MethodInfo GetMethodInfo(
            string className, 
            string theMethodName, 
            Type[] argClassList, 
            Evaluator caller)
        {
            // TODO use caller to get line number
            caller.FindLineNumberInCallStack();
            try
            {
                Type cls = className.ToClass();
                if (cls == null)
                {
                    ErrorHandlers.ClrError(string.Format("Can't find class: {0} at line {1}", className, caller.FindLineNumberInCallStack()));
                    return null;
                }

                MethodInfo info = cls.GetMethod(theMethodName, argClassList);
                if (info == null)
                {
                    ErrorHandlers.ClrError(string.Format("Can't find method: {0}:{1} at line {2}", className, theMethodName, caller.FindLineNumberInCallStack()));
                    return null;
                }

                return info;
            }
            catch (TypeLoadException)
            {
                ErrorHandlers.ClrError(string.Format("Bad class, can't load: {0} at line {1}", className, caller.FindLineNumberInCallStack()));
                return null;
            }
        }
 /// <summary>
 /// Execute the constructor.
 /// Match all arguments supplied up to the constructor's types.
 /// </summary>
 /// <param name="args">Arguments to pass to the constructor.</param>
 /// <param name="env">The environment of the evaluation.</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.</param>
 /// <returns>The next evaluator to excute.</returns>
 internal override Evaluator Apply(SchemeObject args, Environment env, Evaluator returnTo, Evaluator caller)
 {
     #if Check
     this.CheckArgCount(ListLength(args), args, "ClrConstructor", caller);
     #endif
     Assembly assembly = this.classType.Assembly;
     object[] argArray = this.ToArgList(args, null, "ClrConstructor", caller);
     object res = assembly.CreateInstance(this.classType.FullName, false, BindingFlags.Default, null, argArray, null, null);
     returnTo.ReturnedExpr = ClrObject.New(res);
     return returnTo;
 }
 /// <summary>
 /// Initial step: evaluate the first expression.
 /// Instead of calling normal EvaluateExpression, call a variant that catches suspended
 ///   execution and halts the evaluation.
 /// </summary>
 /// <param name="s">This evaluator.</param>
 /// <returns>The next evaluator.</returns>
 private static Evaluator InitialStep(Evaluator s)
 {
     s.Pc = LoopStep;
     return EvaluateExpressionWithCatch.Call(First(s.Expr), s.Env, s);
 }
        /// <summary>
        /// Apply the method to the given arguments.
        /// If the method is static, all arguments are passed to the method.
        /// Otherwise, the first argument is the class instance, and the rest are passed 
        ///    to the method.
        /// </summary>
        /// <param name="args">Arguments to pass to the method.</param>
        /// <param name="env">The environment of the application.</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.</param>
        /// <returns>The next evaluator to excute.</returns>
        internal override Evaluator Apply(SchemeObject args, Environment env, Evaluator returnTo, Evaluator caller)
        {
            SchemeObject target = null;
            if (!this.MethodInfo.IsStatic)
            {
                target = First(args);
                args = Rest(args);
            }

            #if Check
            this.CheckArgCount(ListLength(args), args, "SynchronousClrProcedure", caller);
            #endif

            var actualTarget = ClrObject.ToClrObject(target, this.InstanceClass);
            var argList = this.ToArgList(args, null, "SynchronousClrProcedure", caller);
            object res = this.MethodInfo.Invoke(actualTarget, argList);
            res = res ?? Undefined.Instance;
            returnTo.ReturnedExpr = ClrObject.FromClrObject(res);
            return returnTo;
        }
 /// <summary>
 /// Exit the whole process.
 /// </summary>
 /// <param name="args">If given, the process exit code.</param>
 /// <param name="caller">The calling evaluator (not used).</param>
 /// <returns>Does not return.</returns>
 private static SchemeObject Exit(SchemeObject args, Evaluator caller)
 {
     System.Environment.Exit(List.First(args) is EmptyList ? 0 : Number.AsInt(List.First(args)));
     return Undefined.Instance;
 }
 /// <summary>
 /// Subclass must provide an implementation.
 /// This evaluates the expression, in a way that is appropriate
 ///   to the function (eval or apply).
 /// </summary>
 /// <param name="s">This evaluator.</param>
 /// <returns>The next step.</returns>
 protected static Evaluator EvaluateStep(Evaluator s)
 {
     return ((EvaluateTimeBase)s).EvaluateStep();
 }
Exemple #23
0
 /// <summary>
 /// Initializes a new instance of the Continuation class.
 /// The evaluator and its chain of evaluators back to the beginning have to be cloned because they
 ///   hold information about the progress of the evaluation.  When the evaluation proceeds
 ///   these evaluators might be altered, damaging the ability to continue, which is what makes the
 ///   clone necessary.
 /// </summary>
 /// <param name="eval">The continuation to return to when applied.</param>
 private Continuation(Evaluator eval)
     : base(null, new ArgsInfo(1, 1, false))
 {
     this.savedEvaluator = eval.CloneChain();
 }
        /// <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>
        /// Start evaluation by testing the various forms.
        /// The special forms have their own evaluators.
        /// Otherwise, evaluate the first argument (the proc) in preparation for a call.
        /// </summary>
        /// <param name="s">This evaluator.</param>
        /// <returns>The next thing to do.</returns>
        private static Evaluator InitialStep(Evaluator s)
        {
            var step = (EvaluateExpression)s;

            // If we get here, it wasn't one of the special forms.
            // So we need to evaluate the first item (the function) in preparation for
            //    doing a procedure call.
            //// <r4rs section="4.1.3">(<operator> <operand1> ...)</r4rs>
            s.Pc = ApplyProcStep;
            return Call(step.fn, s.Env, s);
        }
        /// <summary>
        /// Apply the method to the given arguments.
        /// If the method is static, all arguments are passed to the method.
        /// Otherwise, the first argument is the class instance, and the rest are passed 
        ///    to the method.
        /// </summary>
        /// <param name="args">Arguments to pass to the method.</param>
        /// <param name="env">The environment of the application.</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.</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, "AsynchronousClrProcedure", caller);
            #endif
            SchemeObject target = null;
            if (!this.MethodInfo.IsStatic)
            {
                target = First(args);
                args = Rest(args);
            }

            var actualTarget = ClrObject.ToClrObject(target, this.InstanceClass);
            var argArray = this.ToArgListBegin(args, new Tuple<object, Evaluator>(actualTarget, returnTo), caller);
            var res = this.MethodInfo.Invoke(actualTarget, argArray) as IAsyncResult;

            // res is not converted because it is IAsyncResult -- convert in completion method
            return new SuspendedEvaluator(ClrObject.New(res), returnTo).NextStep();
        }
 /// <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;
 }
Exemple #28
0
 /// <summary>
 /// Perform steps until evaluation is complete or suspended.
 /// Calling "a subroutine" does not recursively call EvalSteps.
 /// A "call" is handled by creating a new evaluator and passing a step within it as the nextStep.
 /// A "return" is handled by return a step in the "caller" as the next step.
 /// </summary>
 /// <param name="evaluator">The evaluator to execute first.</param>
 /// <returns>The evaluation result, or suspended evaluator.</returns>
 internal SchemeObject EvalSteps(Evaluator evaluator)
 {
     while (true)
     {
         // Get the PC from the evaluator and call the action it points to, passing it the evaluator instance.
         evaluator = evaluator.Pc(evaluator);
         if (evaluator.Finished)
         {
             return evaluator.ReturnedExpr;
         }
     }
 }
 /// <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>
 /// Initializes a new instance of the EvaluateParallel class.
 /// </summary>
 /// <param name="expr">The expressions to evaluate.</param>
 /// <param name="env">The evaluation environment</param>
 /// <param name="caller">The caller.  Return to this when done.</param>
 private EvaluateParallel(SchemeObject expr, Environment env, Evaluator caller)
     : base(InitialStep, expr, env, caller)
 {
     this.forked = this.joined = 0;
     this.accum = EmptyList.Instance;
 }