Пример #1
0
        /// <summary>
        /// Evaluates combination.
        /// </summary>
        /// <param name="combination">A combination to evaluate.</param>
        /// <param name="env">Environment in which the given combination will be evaluated.</param>
        /// <param name="cont">Continuation.</param>
        /// <returns>Bounce ir null.</returns>
        private Bounce EvalCombination(ScmCombination combination, Environment env, Cont cont)
        {
            System.Diagnostics.Debug.Assert(combination != null);

            // If this is an empty combination, then signal an error, since there is no
            // procedure to apply.
            if (combination.IsEmpty)
            {
                throw new EvaluatorException(UserMessages.CannotApplyProcedure, combination);
            }
            // Otherwise evaluate the procedure.
            return(() => Eval(combination.Procedure, env, evalResult =>
            {
                // Now check whether the expression that is supposed to evaluate to a
                // procedure has really evaluated to a procedure, and signal an error
                // otherwise.
                var procedure = evalResult as IProcedure;
                if (procedure == null)
                {
                    throw new EvaluatorException(UserMessages.CannotApplyProcedure, combination);
                }
                // Depending on whether we are dealing with a primitive procedure or
                // just a procedure we call different handlers.
                if ((procedure is IPrimitiveProcedure))
                {
                    combination.Expressions[0] = procedure;
                    return ApplyPrimitiveProcedure(combination, env, cont);
                }
                // TODO: this assingment needs fixing.
                combination.Expressions[0] = procedure;
                return ApplyProcedure(combination, env, cont);
            }));
        }
Пример #2
0
        private Bounce ApplyCallCcProcedure(IExpression expression, Environment env, Cont cont)
        {
            var combination = expression as ScmCombination;

            if (!combination.Operands.IsSingle())
            {
                throw new EvaluatorException("Expects 1 argument", expression);
            }

            return(() => Eval(combination.Operands.First(), env, closure =>
            {
                var oneArgumentClosure = closure as ScmClosure;
                if (oneArgumentClosure == null)
                {
                    throw new EvaluatorException("Argument for call/cc must evaluate to a procedure", expression);
                }
                if (!oneArgumentClosure.ArgumentList.IsSingle())
                {
                    throw new EvaluatorException("Call/cc argument must be a procedure of one argument", expression);
                }

                var currentContinuation = new ScmContinuation(cont);
                var closureCall = new ScmCombination(new List <IExpression> {
                    oneArgumentClosure, currentContinuation
                });
                return ApplyClosureProcedure(closureCall, env, cont);
            }));
        }
Пример #3
0
 /// <summary>
 /// This method adds expr to the currExpr, if the latter is not null, and to the program
 /// otherwise.
 /// </summary>
 /// <param name="expr">Expression to add.</param>
 /// <param name="currExpr">Current enclosing expression.</param>
 /// <param name="program">Program.</param>
 private static void AddExpression(IExpression expr, ScmCombination currExpr, List <IExpression> program)
 {
     if (currExpr != null)
     {
         currExpr.Expressions.Add(expr);
         return;
     }
     program.Add(expr);
 }
Пример #4
0
        private Bounce ApplyContinuationProcedure(ScmCombination combination, Environment env, Cont cont)
        {
            var continuation = combination.Procedure as ScmContinuation;

            if (!combination.HasOperands)
            {
                return((Bounce)continuation.Cont(ScmUnassigned.Instance));
            }
            else if (combination.Operands.IsSingle())
            {
                return(() => Eval(combination.Operands.First(), env, returnValue => (Bounce)continuation.Cont(returnValue)));
            }
            throw new EvaluatorException("Continuation expects zero or one argument", combination);
        }
Пример #5
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);
                });
            }));
        }
Пример #6
0
 private Bounce ApplyProcedure(ScmCombination combination, Environment env, Cont cont)
 {
     if (combination.Procedure is ScmEvalProcedure)
     {
         return(() => ApplyEvalProcedure(combination, env, cont));
     }
     else if (combination.Procedure is ScmClosure)
     {
         return(() => ApplyClosureProcedure(combination, env, cont));
     }
     else if (combination.Procedure is ScmContinuation)
     {
         return(() => ApplyContinuationProcedure(combination, env, cont));
     }
     throw new EvaluatorException("Unknown procedure", combination);
 }
Пример #7
0
        private Bounce ApplyEvalProcedure(ScmCombination combination, Environment env, Cont cont)
        {
            if (!combination.Operands.IsSingle())
            {
                throw new EvaluatorException("Expecting 1 argument", combination);
            }
            return(() => Eval(combination.Operands.First(), env, evalResult =>
            {
                var evalResultAsList = evalResult as ScmPair;
                if (evalResultAsList == null)
                {
                    throw new EvaluatorException("Must be a non-empty list", combination);
                }

                var combinationFromImproperList = new ScmCombination(evalResultAsList.GetImproperList());
                return Eval(combinationFromImproperList, env, combinationEvalResult => { return (Bounce)cont(combinationEvalResult); });
            }));
        }
Пример #8
0
 private Bounce ApplyPrimitiveProcedure(ScmCombination combination, Environment env, Cont cont)
 {
     return(() => m_PPHandlers[combination.Procedure.GetType()] (combination, env, cont));
 }
Пример #9
0
 public void AddClause(ScmCombination combination)
 {
     m_Clauses.Add(combination);
 }
Пример #10
0
        /// <summary>
        /// This methods analyses the given tokens and produces a list of combinations
        /// and expressions that can be parsed further for syntax consistency etc.
        /// </summary>
        /// <param name="tokens">A list of tokens.</param>
        /// <returns>A list of combinations and expressions.</returns>
        private static List <IExpression> CombineExpressions(List <Token> tokens)
        {
            CheckParanthesisBalance(tokens);

            var            program            = new List <IExpression> ();
            var            eStack             = new Stack <IExpression> ();
            ScmCombination currentCombination = null;

            for (int i = 0; i < tokens.Count; ++i)
            {
                var token = tokens[i];

                if (token is BeginToken)
                {
                    if (currentCombination != null)
                    {
                        eStack.Push(currentCombination);
                    }
                    currentCombination = new ScmCombination(token);
                }
                else if (token is EndToken)
                {
                    IExpression cExpr = currentCombination as IExpression;
                    currentCombination = cExpr as ScmCombination;
                    if (eStack.Count > 0)
                    {
                        var stackExprOnTop = eStack.Peek() as ScmCombination;
                        stackExprOnTop.Expressions.Add(currentCombination);
                        currentCombination = eStack.Pop() as ScmCombination;
                    }
                    else
                    {
                        program.Add(currentCombination);
                        currentCombination = null;
                    }
                }
                else
                {
                    if (token is SymbolToken)
                    {
                        IExpression scmSymbol = new ScmSymbol(token);
                        AddExpression(scmSymbol, currentCombination, program);
                    }
                    else if (token is NumberToken)
                    {
                        IExpression scmNumber = NumberParser(token as NumberToken);
                        AddExpression(scmNumber, currentCombination, program);
                    }
                    else if (token is StringToken)
                    {
                        IExpression scmString = new ScmString(token);
                        AddExpression(scmString, currentCombination, program);
                    }
                    else if (token is DotToken)
                    {
                        IExpression scmString = new ScmDotModifier(token);
                        AddExpression(scmString, currentCombination, program);
                    }
                    else if (token is QuoteToken || token is QuasiquoteToken || token is UnquoteToken)
                    {
                        IExpression scmQuote = null;
                        if (token is QuoteToken)
                        {
                            scmQuote = new ScmQuoteSpecialForm(null);
                        }
                        else if (token is UnquoteToken)
                        {
                            scmQuote = new ScmUnquoteSpecialForm(null);
                        }
                        else
                        {
                            scmQuote = new ScmQuasiquoteSpecialForm(null);
                        }
                        AddExpression(scmQuote, currentCombination, program);
                    }
                }
            }

            return(QuotationSyntacticSugar(program, false));
        }