Example #1
0
        /// <summary>
        /// This method binds names with values, but doesn't allow their usage within expressions
        /// that are being bound.
        /// </summary>
        private Bounce ApplyLetSpecialForm(IExpression expressions, Environment env, Cont cont)
        {
            var letSpecialForm = expressions as ScmLetSpecialForm;
            // Split keys and values in separate lists.
            var bindingKeys   = new List <IExpression> ();
            var bindingValues = new List <IExpression> ();

            foreach (var keyValue in letSpecialForm.Bindings)
            {
                bindingValues.Add(keyValue.Value);
                bindingKeys.Add(keyValue.Key);
            }
            // Evaluate values.
            return(() => EvalList(bindingValues, env, evalBindingResults =>
            {
                var bindingResultsAsList = evalBindingResults as List <IExpression>;
                // Create a temporary environment frame that will hold these
                // bindings.
                var environmentFrame = new EnvironmentFrame();
                for (int i = 0; i < bindingKeys.Count; ++i)
                {
                    var bindingName = bindingKeys[i] as ScmSymbol;
                    var bindingValue = bindingResultsAsList[i];
                    environmentFrame.Set(bindingName, bindingValue);
                }
                // Extend the environemnt with these bindings.
                var newEnvironment = (new Environment(env)).Extend(environmentFrame);
                // Evaluate the body in the new environment.
                return EvalList(letSpecialForm.Expressions, newEnvironment, evalResults =>
                {
                    var evalResultsAsList = evalResults as List <IExpression>;
                    return (Bounce)cont(evalResultsAsList.Last());
                });
            }));
        }
Example #2
0
        public Environment()
        {
            // Set up global environment.
            var initialFrame = new EnvironmentFrame();

            // Numeric operations.
            initialFrame.Set(new ScmSymbol("+"), new ScmAddition());
            initialFrame.Set(new ScmSymbol("-"), new ScmSubtraction());
            initialFrame.Set(new ScmSymbol("*"), new ScmMultiplication());
            initialFrame.Set(new ScmSymbol("/"), new ScmDivision());
            initialFrame.Set(new ScmSymbol("zero?"), new ScmZeroPredicateProcedure());
            initialFrame.Set(new ScmSymbol("odd?"), new ScmOddPredicateProcedure());
            initialFrame.Set(new ScmSymbol("even?"), new ScmEvenPredicateProcedure());
            initialFrame.Set(new ScmSymbol("quotient"), new ScmQuotientProcedure());
            initialFrame.Set(new ScmSymbol("remainder"), new ScmRemainderProcedure());
            initialFrame.Set(new ScmSymbol("modulo"), new ScmModuloProcedure());
            initialFrame.Set(new ScmSymbol("abs"), new ScmAbsProcedure());
            initialFrame.Set(new ScmSymbol("min"), new ScmMinProcedure());
            initialFrame.Set(new ScmSymbol("max"), new ScmMaxProcedure());
            initialFrame.Set(new ScmSymbol("number?"), new ScmNumberPredicateProcedure());
            initialFrame.Set(new ScmSymbol("integer?"), new ScmIntegerPredicateProcedure());
            initialFrame.Set(new ScmSymbol("real?"), new ScmRealPredicateProcedure());

            // TODO: exact?, inexact?, positive?, negative?,
            // sin, cos, sqrt etc.

            // True, false and comparison operations.
            initialFrame.Set(new ScmSymbol("#t"), ScmTrueValue.Instance);
            initialFrame.Set(new ScmSymbol("#f"), ScmFalseValue.Instance);
            initialFrame.Set(new ScmSymbol("<"), new ScmLessThan());
            initialFrame.Set(new ScmSymbol(">"), new ScmGreaterThan());
            initialFrame.Set(new ScmSymbol("="), new ScmEqualTo());
            initialFrame.Set(new ScmSymbol("<="), new ScmLessThanOrEqualTo());
            initialFrame.Set(new ScmSymbol(">="), new ScmGreaterThanOrEqualTo());

            // List procedures.
            initialFrame.Set(new ScmSymbol("cons"), new ScmConsProcedure());
            initialFrame.Set(new ScmSymbol("list"), new ScmListProcedure());
            initialFrame.Set(new ScmSymbol("list?"), new ScmListPredicateProcedure());
            initialFrame.Set(new ScmSymbol("null?"), new ScmNullPredicateProcedure());
            initialFrame.Set(new ScmSymbol("length"), new ScmLengthProcedure());
            initialFrame.Set(new ScmSymbol("list-ref"), new ScmListRefProcedure());
            initialFrame.Set(new ScmSymbol("car"), new ScmCarProcedure());
            initialFrame.Set(new ScmSymbol("cdr"), new ScmCdrProcedure());
            initialFrame.Set(new ScmSymbol("set-car!"), new ScmSetCarProcedure());
            initialFrame.Set(new ScmSymbol("set-cdr!"), new ScmSetCdrProcedure());

            // Continuation and evaluation procedures.
            initialFrame.Set(new ScmSymbol("eval"), new ScmEvalProcedure());
            initialFrame.Set(new ScmSymbol("call/cc"), new ScmCallCcProcedure());
            initialFrame.Set(new ScmSymbol("call-with-current-continuation"), new ScmCallCcProcedure());
            Extend(initialFrame);
        }
Example #3
0
        private Bounce ApplyClosureProcedure(ScmCombination combination, Environment env, Cont cont)
        {
            //((lambda (b . a) a) 1)
            var closure           = combination.Procedure as ScmClosure;
            var numberOfArguments = closure.ArgumentList.Count;
            var operands          = new List <IExpression> (combination.Operands);

            if (!closure.Dotted && numberOfArguments != operands.Count)
            {
                throw new EvaluatorException(String.Format("Expecting {0} argument{1}", numberOfArguments, numberOfArguments > 1 ? "s" : ""), combination);
            }
            else if (closure.Dotted)
            {
                var numberOfArgumentsButLast = numberOfArguments - 1;
                if (numberOfArgumentsButLast > operands.Count)
                {
                    throw new EvaluatorException(String.Format("Expecting at least {0} argument{1}", numberOfArgumentsButLast, numberOfArgumentsButLast > 1 ? "s" : ""), combination);
                }
                else if (numberOfArgumentsButLast == operands.Count)
                {
                    operands.Add(ScmEmptyList.Instance);
                }
                else
                {
                    var lastArgument = new ScmPair(operands.TailFrom(numberOfArgumentsButLast));
                    operands = new List <IExpression> (operands.GetRange(0, numberOfArgumentsButLast));
                    operands.Add(lastArgument);
                }
            }

            return(() => EvalList(operands, env, evalResults =>
            {
                var environmentFrame = new EnvironmentFrame();
                var evalResultsAsList = evalResults as List <IExpression>;
                for (int i = 0; i < closure.ArgumentList.Count; ++i)
                {
                    var argumentName = closure.ArgumentList[i];
                    var argumentValue = evalResultsAsList[i];
                    environmentFrame.Set(argumentName, argumentValue);
                }

                var newEnvironment = (new Environment(closure.Env)).Extend(environmentFrame);
                return EvalList(closure.Body.AllButLast(), newEnvironment, bodyEvalResults =>
                {
                    return Eval(closure.Body.Last(), newEnvironment, cont);
                });
            }));
        }
Example #4
0
        /// <summary>
        /// This method binds names with values allowing their usage within expressions
        /// that are being bound.
        /// </summary>
        private Bounce ApplyLetrecSpecialForm(IExpression expression, Environment env, Cont cont)
        {
            // In comments below we refer to bindings as key-value pairs.
            var letRecSpecialForm = expression as ScmLetrecSpecialForm;
            // We are going to use a temporary environmental frame, using which we are
            // going to define dummy values for each identifier first, and then substitute with
            // evaluated ones.
            var environmentFrame = new EnvironmentFrame();
            // A list of names (keys) that we are going to bind.
            var bindingKeys = new List <IExpression> ();
            // A list of corresponding values.
            var bindingValues = new List <IExpression> ();

            // Proccess each pair in the list of bindings, by saving
            // them in corresponding lists and assigning
            // the unassigned value to each of the identifiers.
            foreach (var keyValue in letRecSpecialForm.Bindings)
            {
                bindingValues.Add(keyValue.Value);
                bindingKeys.Add(keyValue.Key);
                environmentFrame.Set((ScmSymbol)keyValue.Key, ScmUnassigned.Instance);
            }
            // Now evaluate each expression (i.e. "value").
            return(() => EvalList(bindingValues, env, evalBindingsResult =>
            {
                var bindingResultsAsList = evalBindingsResult as List <IExpression>;
                // Substitute evaluated results.
                for (int i = 0; i < bindingKeys.Count; ++i)
                {
                    var bindingName = bindingKeys[i] as ScmSymbol;
                    var bindingValue = bindingResultsAsList[i];
                    environmentFrame.Set(bindingName, bindingValue);
                }
                // Extend the environment with this new frame.
                // FIXME: it should "branch" here, and not create a copy of entire environment.
                var newEnvironment = (new Environment(env)).Extend(environmentFrame);
                // And evalute expressions in the environment with those bindings.
                return EvalList(letRecSpecialForm.Expressions, newEnvironment, evalResults =>
                {
                    // FIXME: rewrite this in the same manner as for closure.
                    var evalResultsAsList = evalResults as List <IExpression>;
                    return (Bounce)cont(evalResultsAsList.Last());
                });
            }));
        }
Example #5
0
 /// <summary>
 /// Extends the environment by adding a given frame on top of the stack.
 /// </summary>
 /// <param name="frame"></param>
 /// <returns>This environment.</returns>
 public Environment Extend(EnvironmentFrame frame)
 {
     m_Env.Push(frame);
     return(this);
 }