/// <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); })); }
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); })); }
/// <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); }
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); }
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); }); })); }
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); }
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); }); })); }
private Bounce ApplyPrimitiveProcedure(ScmCombination combination, Environment env, Cont cont) { return(() => m_PPHandlers[combination.Procedure.GetType()] (combination, env, cont)); }
public void AddClause(ScmCombination combination) { m_Clauses.Add(combination); }
/// <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)); }