Not a recursive lambda evaluator that magically optimizes tail recursion

I think that when inserting my main method GetTermValueplus a class StackFrameand a few helper methods ( Returnand Replace) there should be all I need for it to be concise, but first a few notes about the code:

An ILambdaValuerepresents the value, which is mainly the result of an evaluation ILambdaTerm, which is the analyzed lambda member.

A class AbstractionValueis ILambdaFunction(which in turn is ILambdaValue) that contains IAbstractionTerm(which is ILambdaTerm), which is called AbstractionTerm, which contains the parsing of the paragraph, and IScope<ILambdaValue>is called Scope, which represents the environment in which the abstraction value was created.

An IScopeis just a dictionary with string keys. InnerScopeis one IScopethat models lambda substitution by taking the parent region and dictionary and overwriting the parent region with the values ​​in the dictionary.

public class StackFrame
{
    public ILambdaTerm Term;
    public IScope<ILambdaValue> Scope;
    public List<ILambdaValue> Results = new List<ILambdaValue>();

    public StackFrame() { }

    public StackFrame(ILambdaTerm term, IScope<ILambdaValue> scope)
    {
        Term = term;
        Scope = scope;
    }
}

private static void Return(Stack<StackFrame> stack, ILambdaValue result)
{
    stack.Pop();
    stack.Peek().Results.Add(result);
}

private static void Replace(Stack<StackFrame> stack, StackFrame stackFrame)
{
    stack.Pop();
    stack.Push(stackFrame);
}

public static ILambdaValue GetTermValue(ILambdaTerm _term, IScope<ILambdaValue> _scope)
{
    Stack<StackFrame> stack = new Stack<StackFrame>();

    stack.Push(new StackFrame());
    stack.Push(new StackFrame(_term, _scope));

    while (stack.Count > 1)
    {
        var stackFrame = stack.Peek();

        switch (stackFrame.Term.TermKind)
        {
            case LambdaTermType.String:
                Return(stack, new StringValue(((ILiteralTerm<string>)stackFrame.Term).Value));
                break;
            case LambdaTermType.Number:
                Return(stack, new NumberValue(((ILiteralTerm<double>)stackFrame.Term).Value));
                break;
            case LambdaTermType.Boolean:
                Return(stack, new BooleanValue(((ILiteralTerm<bool>)stackFrame.Term).Value));
                break;
            case LambdaTermType.Variable:
                Return(stack, stackFrame.Scope[((IVariableTerm)stackFrame.Term).Name]);
                break;
            case LambdaTermType.Application:
                {
                    var application = (IApplicationTerm)stackFrame.Term;

                    if (stackFrame.Results.Count == 0)
                    {
                        stack.Push(new StackFrame(application.Function, stackFrame.Scope));
                    }
                    else if (stackFrame.Results.Count <= application.Arguments.Length)
                    {
                        stack.Push(new StackFrame(application.Arguments[stackFrame.Results.Count - 1], stackFrame.Scope));
                    }
                    else
                    {
                        var function = (ILambdaFunction)stackFrame.Results[0];
                        var argList = stackFrame.Results.Skip(1).ToList();

                        if (function is AbstractionValue) // If the function is a lambda-defined abstraction (see next `case`):
                        {
                            var abstraction = (AbstractionValue)function;
                            var substitutions = abstraction.AbstractionTerm.Parameters.Select((Param, Index) => new { Param, Index }).ToDictionary(ai => ai.Param.Name, ai => argList[ai.Index]);
                            InnerScope<ILambdaValue> innerScope = new InnerScope<ILambdaValue>(abstraction.Scope, substitutions);
                            Replace(stack, new StackFrame(abstraction.AbstractionTerm.Body, innerScope));
                        }
                        else // If the function is a built-in function so there no abstraction:
                        {
                            Return(stack, function.ApplyTo(argList));
                        }
                    }
                }
                break;
            case LambdaTermType.Abstraction:
                Return(stack, new AbstractionValue((IAbstractionTerm)stackFrame.Term, stackFrame.Scope));
                break;
            default:
                throw new NotImplementedException();
        }
    }

    return stack.Peek().Results[0];
}

, , "" . ( , , , - , let overflow = \x.(overflow x) ( )) , , - , , . 100%, , , , . ( ) , , , ( "" ), , , .

, , - Replace if (function is AbstractionValue). -, , . ( , - , ).

, , ? , "" , ?

+4

All Articles