package vitry.prelude; import java.math.BigInteger; import vitry.runtime.BigRational; import vitry.runtime.StandardFunction; import vitry.runtime.Symbol; import vitry.runtime.VitryRuntime; import vitry.runtime.error.InvocationError; import vitry.runtime.error.TypeError; abstract class MathPrimitive extends StandardFunction.Binary { public final Object apply(Object x, Object y) throws InvocationError { if (x instanceof Symbol) { if (y instanceof Symbol) return withBool((Symbol) x, (Symbol) y); x = boolToInt((Symbol) x); } if (x instanceof BigInteger) { if (y instanceof Symbol) return withInt((BigInteger) x, boolToInt((Symbol) y)); if (y instanceof BigInteger) return withInt((BigInteger) x, (BigInteger) y); x = intToRat((BigInteger) x); } if (x instanceof BigRational) { if (y instanceof Symbol) return withRat((BigRational) x, intToRat(boolToInt((Symbol) y))); if (y instanceof BigInteger) return withRat((BigRational) x, intToRat((BigInteger) y)); if (y instanceof BigRational) return withRat((BigRational) x, (BigRational) y); } if (x instanceof Float) { if (y instanceof Float) return withFloat((Float) x, (Float) y); x = floatToDouble((Float) x); } if (x instanceof Double) { if (y instanceof Float) return withDouble((Double) x, (Double) y); if (y instanceof Double) return withDouble((Double) x, (Double) y); } throw new TypeError("Can not apply " + this + " to " + x + " and " + y); } abstract Object withBool(Symbol x, Symbol y); // abstract BigInteger withNat(BigInteger x, BigInteger y); abstract Object withInt(BigInteger x, BigInteger y); abstract Object withRat(BigRational x, BigRational y); abstract Object withFloat(float x, float y); abstract Object withDouble(double x, double y); static final BigInteger boolToInt(Symbol x) { if (VitryRuntime.toPrimBool(x)) return BigInteger.ONE; else return BigInteger.ZERO; } static final BigInteger natToInt(BigInteger x) { return x; } static final BigRational intToRat(BigInteger x) { return BigRational.valueOf(x); } static final BigInteger ratToInt(BigRational x) { if (x.isInteger()) return x.bigIntegerValue(); else throw new TypeError("Could not convert rat to nat"); } static final Double floatToDouble(Float x) { return Double.valueOf(x); } }