package org.dynjs.parser.ast; import org.dynjs.parser.CodeVisitor; import org.dynjs.runtime.ExecutionContext; import org.dynjs.runtime.Types; import org.dynjs.runtime.builtins.types.BuiltinNumber; public class MultiplicativeExpression extends AbstractBinaryExpression { public MultiplicativeExpression(Expression lhs, Expression rhs, String op) { super(lhs, rhs, op); } @Override public Object accept(Object context, CodeVisitor visitor, boolean strict) { return visitor.visit( context, this, strict ); } @Override public Object interpret(ExecutionContext context, boolean debug) { Number lval = Types.toNumber(context, getValue(this.lhsGet, context, getLhs().interpret( context, debug) ) ); Number rval = Types.toNumber(context, getValue(this.rhsGet, context, getRhs().interpret(context, debug)) ); if (Double.isNaN(lval.doubleValue()) || Double.isNaN(rval.doubleValue())) { return(Double.NaN); } if (lval instanceof Double || rval instanceof Double) { switch (getOp()) { case "*": return(lval.doubleValue() * rval.doubleValue()); case "/": // Divide-by-zero if (NumericHelper.isZero(rval)) { if (NumericHelper.isZero(lval)) { return(Double.NaN); } else if (NumericHelper.isSameSign(lval, rval)) { return(Double.POSITIVE_INFINITY); } else { return(Double.NEGATIVE_INFINITY); } // Zero-divided-by-something } else if (NumericHelper.isZero(lval)) { if (NumericHelper.isSameSign(lval, rval)) { return(0L); } else { return(-0.0); } } // Regular math double primaryValue = lval.doubleValue() / rval.doubleValue(); if (NumericHelper.isRepresentableByLong(primaryValue)) { return((long) primaryValue); } else { return(primaryValue); } case "%": if (rval.doubleValue() == 0.0) { return(Double.NaN); } return(BuiltinNumber.modulo(lval, rval)); } } else { switch (getOp()) { case "*": return(lval.longValue() * rval.longValue()); case "/": if (rval.longValue() == 0L) { if (lval.longValue() == 0L) { return(Double.NaN); } else if (NumericHelper.isSameSign(lval, rval)) { return(Double.POSITIVE_INFINITY); } else { return(Double.NEGATIVE_INFINITY); } } if (lval.longValue() == 0) { if (Double.compare(rval.doubleValue(), 0.0) > 0) { return(0L); } else { return(-0.0); } } double primaryResult = lval.doubleValue() / rval.longValue(); if (primaryResult == (long) primaryResult) { return((long) primaryResult); } else { return(primaryResult); } case "%": if (rval.longValue() == 0L) { return(Double.NaN); } return(BuiltinNumber.modulo(lval, rval)); } } return null; // not reached } }