IntegerConstant.java

package org.sterling.runtime.expression;

import static java.lang.String.valueOf;
import static org.sterling.runtime.expression.BooleanConstant.FALSE;
import static org.sterling.runtime.expression.BooleanConstant.TRUE;
import static org.sterling.runtime.expression.ExpressionConversions.convertInteger;
import static org.sterling.runtime.expression.ExpressionConversions.convertSymbol;
import static org.sterling.runtime.expression.ExpressionFactory.constant;
import static org.sterling.util.StringUtil.stringify;

import java.util.Objects;
import org.sterling.SterlingException;

public class IntegerConstant extends Expression {

    private final int value;

    public IntegerConstant(int value) {
        this.value = value;
    }

    @Override
    public Expression access(Expression member) throws SterlingException {
        switch (convertSymbol(member).getValue()) {
            case "+": return new AddClosure(value);
            case "-": return new SubtractClosure(value);
            case "*": return new MultiplyClosure(value);
            case "/": return new DivideClosure(value);
            case "%": return new ModuloClosure(value);
            case "<<": return new LeftShiftClosure(value);
            case ">>": return new SignedRightShiftClosure(value);
            case ">>>": return new RightShiftClosure(value);
            case "&": return new BitwiseAndClosure(value);
            case "|": return new BitwiseOrClosure(value);
            case "^": return new BitwiseXorClosure(value);
            case "<": return new LessThanClosure(value);
            case "<=": return new LessThanEqualsClosure(value);
            case "positive": return new IntegerConstant(Math.abs(value));
            case "negative": return new IntegerConstant(-value);
            case "toBoolean": return toBoolean();
            case "toInteger": return this;
            case "toString": return constant(valueOf(value));
            case "toDouble": return new DoubleConstant(Integer.valueOf(value).doubleValue());
            default: return super.access(member);
        }
    }

    @Override
    public boolean equals(Object o) {
        return o == this || o instanceof IntegerConstant && value == ((IntegerConstant) o).value;
    }

    @Override
    public int hashCode() {
        return Objects.hash(value);
    }

    @Override
    public String toString() {
        return stringify(this, value);
    }

    private BooleanConstant toBoolean() {
        return value == 1 ? TRUE : FALSE;
    }

    private static abstract class IntegerClosure extends Expression {

        private final int value;

        public IntegerClosure(int value) {
            this.value = value;
        }

        @Override
        public Expression apply(Expression argument) throws SterlingException {
            return new IntegerConstant(operate(value, convertInteger(argument).value));
        }

        @Override
        public String toString() {
            return stringify(this, value);
        }

        protected abstract int operate(int leftValue, int rightValue);
    }

    private static final class AddClosure extends IntegerClosure {

        public AddClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue + rightValue;
        }
    }

    private static final class SubtractClosure extends IntegerClosure {

        public SubtractClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue - rightValue;
        }
    }

    private static final class MultiplyClosure extends IntegerClosure {

        public MultiplyClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue * rightValue;
        }
    }

    private static final class DivideClosure extends IntegerClosure {

        public DivideClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue / rightValue;
        }
    }

    private static final class ModuloClosure extends IntegerClosure {

        public ModuloClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue % rightValue;
        }
    }

    private static final class LeftShiftClosure extends IntegerClosure {

        public LeftShiftClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue << rightValue;
        }
    }

    private static final class RightShiftClosure extends IntegerClosure {

        public RightShiftClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue >>> rightValue;
        }
    }

    private static final class SignedRightShiftClosure extends IntegerClosure {

        public SignedRightShiftClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue >> rightValue;
        }
    }

    private static final class BitwiseAndClosure extends IntegerClosure {

        public BitwiseAndClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue & rightValue;
        }
    }

    private static final class BitwiseOrClosure extends IntegerClosure {

        public BitwiseOrClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue | rightValue;
        }
    }

    private static final class BitwiseXorClosure extends IntegerClosure {

        public BitwiseXorClosure(int value) {
            super(value);
        }

        @Override
        protected int operate(int leftValue, int rightValue) {
            return leftValue ^ rightValue;
        }
    }

    private static final class LessThanClosure extends Expression {

        private final int value;

        public LessThanClosure(int value) {
            this.value = value;
        }

        @Override
        public Expression apply(Expression argument) throws SterlingException {
            return value < convertInteger(argument).value ? TRUE : FALSE;
        }
    }

    private static class LessThanEqualsClosure extends Expression {

        private final int value;

        public LessThanEqualsClosure(int value) {
            this.value = value;
        }

        @Override
        public Expression apply(Expression argument) throws SterlingException {
            return value <= convertInteger(argument).value ? TRUE : FALSE;
        }
    }
}