// 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.scheme.exception.ArgumentTypeException;
import bdc.scheme.exception.PrimitiveException;
import bdc.util.Fmt;

public class Application1 extends Expression
{
    Expression operator;
    Expression o1;

    public Application1 (Expression operator,
                         Expression o1)
    {
        this.operator = operator;
        this.o1       = o1;
    }

    public Object eval (Environment environment, Stack stack)
      throws SchemeException
    {
        stack.addElement(o1.eval(environment, stack));
        Object expression = operator.eval(environment, stack);
        if (!(expression instanceof Procedure)) {
            throw new ArgumentTypeException(this,
                                            "Procedure",
                                            expression);
        }

        try {
            return ((Procedure)expression).apply1(stack);
        }
        catch (SchemeException se) {
            backTrace(se);
            return Scheme.NotReached;
        }
        catch (RuntimeException re) {
            throw new PrimitiveException(re);
        }
        finally {
            stack.inUse -= 1;
        }
    }

    /**
        Fixup sub-expressions and return
    */
    public Expression fixupVariables (CompileTimeEnvironment environment)
    {
        operator = operator.fixupVariables(environment);
        o1       = o1.fixupVariables(environment);
        return this;
    }

    public String toString ()
    {
        return Fmt.S("(%s %s)",
                     Writer.write(operator),
                     Writer.write(o1));
    }
}
