// 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 Until extends Expression
{
    Expression   test;
    Expression[] body;

    public Until (Expression test,
                  Begin      body)
    {
        this.test = test;
        this.body = body.expressions;
    }

    public Object eval (Environment environment, Stack stack)
      throws SchemeException
    {
        try {
            while (test.eval(environment, stack) == Boolean.FALSE) {
                int i = 0;
                try {
                    for (; i < body.length; i++)
                        body[i].eval(environment, stack);
                }
                catch (SchemeException se) {
                    Expression.backTrace(body[i], se);
                    return Scheme.NotReached;
                }
            }
            return Scheme.Unspecified;
        }
        catch (SchemeException se) {
            backTrace(se);
            return Scheme.NotReached;
        }
    }

    /**
        Fixup sub-expressions and return
    */
    public Expression fixupVariables (CompileTimeEnvironment environment)
    {
        test = test.fixupVariables(environment);
        Begin.fixupVariables(body, environment);
        return this;
    }

    public String toString ()
    {
        return
            Fmt.S("(until %s %s)",
                  Writer.write(test),
                  Begin.backtrace(body));
    }
}
