// Copyright (c) 1996-2002 Brian D. Carlstrom

package bdc.scheme.compiler;

import bdc.scheme.Pair;
import bdc.scheme.Scheme;
import bdc.scheme.Stack;
import bdc.scheme.exception.ArgumentTypeException;
import bdc.scheme.expression.Procedure1;

/**
    Or2If converts reduces derived Or syntax into another form.
*/
public class Or2If extends Procedure1
{
    public Object apply1 (Stack stack) throws ArgumentTypeException
    {
        Object o1 = stack.array[stack.inUse-1];
        Object e = Scheme.pair(o1, this).cdr;

            // (or)
        if (e == Scheme.Null) {
            return Boolean.FALSE;
        }

            // (or foo)
        Pair clauses = Scheme.pair(e, this);
        if (clauses.cdr == Scheme.Null) {
            return clauses.car;
        }

            // (or foo ...)

        Pair if_ =
            new Pair(Compiler.If,
                     new Pair(Compiler.X,
                              new Pair(Compiler.X,
                                       new Pair(new Pair(Compiler.Thunk,
                                                         Scheme.Null),
                                                Scheme.Null))));
        Pair lambda =
            new Pair(Compiler.Lambda,
                     new Pair(Scheme.Null,
                              new Pair(new Pair(Compiler.Or,
                                                clauses.cdr),
                                       Scheme.Null)));
        Pair let =
            new Pair(Compiler.Let,
                     new Pair(new Pair(new Pair(Compiler.X,
                                                new Pair(clauses.car,
                                                         Scheme.Null)),
                                       new Pair(new Pair(Compiler.Thunk,
                                                         new Pair(lambda,
                                                                  Scheme.Null)),
                                                Scheme.Null)),
                              new Pair(if_,
                                       Scheme.Null)));
        return let;
    }
}
