// Copyright (c) 1996-2002 Brian D. Carlstrom

package bdc.scheme.expression;

import bdc.scheme.Environment;
import bdc.scheme.Scheme;
import bdc.scheme.SchemeException;
import bdc.scheme.Stack;
import bdc.scheme.Writer;
import bdc.scheme.compiler.CompileTimeEnvironment;
import bdc.util.Fmt;

public class LocalAssignment extends Expression
{
    LocalAddress localAddress;
    Expression   expression;

    public LocalAssignment (LocalAddress localAddress,
                            Expression   expression)
    {
        this.localAddress = localAddress;
        this.expression   = expression;
    }

    public Object eval (Environment environment, Stack stack)
      throws SchemeException
    {
        try {
            Object object = expression.eval(environment, stack);
            stack.array[stack.frame+localAddress.index] = object;
            return Scheme.Unspecified;
        }
        catch (SchemeException se) {
            backTrace(se);
            return Scheme.NotReached;
        }
    }

    /**
        Fixup

        If the LocalAddress changes to a LexicalAddress,
        we need to change ourselves to a LexicalAssignment
    */
    public Expression fixupVariables (CompileTimeEnvironment environment)
    {
        expression = expression.fixupVariables(environment);

        Expression address = localAddress.fixupVariables(environment);
        if (address instanceof LexicalAddress) {
            LexicalAddress lexicalAddress = (LexicalAddress)address;
            return new LexicalAssignment(lexicalAddress, expression);
        }
        else {
            localAddress = (LocalAddress)address;
            return this;
        }
    }

    public String toString ()
    {
        return
            Fmt.S("(set! %s %s)",
                  localAddress.variable.name,
                  Writer.write(expression));
    }
}
