<$BlogRSDUrl$>

Thursday, February 05, 2004

So how might I implement the stack-based evaluation? Well...

Representation and implementation

So assume for now that we'll stick with the existing hierarchy:
        SExpression
            Symbol
            Number
            SList
            Function
to represent scheme s-expressions in memory. Assume also that we have a way of building these up from a string representation.
Let's follow along as the different types of S-Expressions get evaluated.
Inside the REPL we have something like this:
        SExpression expression = parser.getNextExpression();
        SExpression result = virtualMachine.getReturnValue(expression);
        System.out.println(result.toString);
getReturnValue() is
            expressionStack.push(expression); 
            evaluate();
            return returnValueStack.pop();
evaluate() is
        while(expressionStack.isNotEmpty())
            expressionStack.pop().evaluate(this); 
So that handles the general stuff, in specific:
Example:
-> 123

this is parsed into a Number.
        Number.evaluate(VirtualMachine)
           virtualMachine.returnValueStack.push(this); 
Example:
-> +

this is parsed into a Symbol.
        Symbol.evaluate(VirtualMachine)
            SExpression value = virtualMachine.lookup(this);
            if value == null
                throw EvaluationException("Unbound variable: ${name}");
            virtualMachine.returnValueStack.push(value);

        virtualMachine.lookup(Symbol)
            for each environment in environmentStack from top to bottom
                SExpression value = environment.lookup(symbol);
                if value is not null,
                    return it
            if we haven't found anything return null.

        environment.lookup(Symbol)
            return bindings.get(symbol)
Example:
-> '+
this is parsed into a SList: (quote +)
that is, an SList which contains the Symbol 'quote', followed by the symbol '+'.
        SList.evaluate(VirtualMachine)
            SExpression first = this.first();
            SExpression rest  = this.rest();  // guaranteed to be a list
            if first is null,
                throw new EvaluationException("missing or extra expression");
            virtualMachine.expressionStack.push(new ApplyFunction());
            virtualMachine.expressionStack.push(first);
            virtualMachine.returnValueStack.push(rest);

        ApplyFunction.evaluate(VirtualMachine)
            SExpression function  = virtualMachine.returnValueStack.pop();
            SExpression arguments = virtualMachine.returnValueStack.pop();
            if function is not an Function then
                throw new EvaluationException("wrong type to apply");
            if arguments is not a SList then
                throw new RuntimeException("stack outta wack.");
            ((Function)function).setup(virtualMachine, (SList)arguments)

        QuoteFunction.setup(VirtualMachine, SList arguments)
            if arguments.size() != 1 then
                throw new EvaluationException("missing or extra expression");
            virtualMachine.expressionStack.push(this);
            virtualMachine.returnValueStack.push(arguments.index(0));
            
        QuoteFunction.evaluate(VirtualMachine)
            SExpression result = virtualMachine.returnValueStack.pop();
            if result is null then
                throw new RuntimeException("stack outta wack");
            virtualMachine.returnValueStack.push(result);
Example:
-> (+ 2 3)
       AdditionFunction.setup(VirtualMachine, SList arguments);
            if arguments.size() is not 2 then 
                throw new EvaluationException("wrong number of arguments to
                ${name}: ${arguments}")
            virtualMachine.expressionStack.push(this); 
            virtualMachine.expressionStack.push(arguments.index(1)); 
            virtualMachine.expressionStack.push(arguments.index(0)); 

        AdditionFunction.evaluate(VirtualMachine)
            SExpression operand1 = virtualMachine.returnValueStack.pop(); 
            SExpression operand2 = virtualMachine.returnValueStack.pop(); 
            if operand1 or operand2 are not Numbers then
                throw new EvaluationException("wrong argument type for
                ${name}");
            // i'm leaving out the type casting in the next step
            Number result = new Number(operand1.value() + operand2.value());
            virtualMachine.returnValueStack.push(result);

0 Comments:

This page is powered by Blogger. Isn't yours?