/******************************************************************************* * Copyright (c) 2009-2013 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI * * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl * * Paul Klint - Paul.Klint@cwi.nl - CWI * * Arnold Lankamp - Arnold.Lankamp@cwi.nl *******************************************************************************/ package org.rascalmpl.interpreter.result; import static org.rascalmpl.interpreter.result.IntegerResult.makeStepRangeFromToWithSecond; import static org.rascalmpl.interpreter.result.ResultFactory.bool; import static org.rascalmpl.interpreter.result.ResultFactory.makeResult; import org.rascalmpl.interpreter.IEvaluatorContext; import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory; import org.rascalmpl.value.IBool; import org.rascalmpl.value.INumber; import org.rascalmpl.value.IReal; import org.rascalmpl.value.IValue; import org.rascalmpl.value.type.Type; import org.rascalmpl.values.ValueFactoryFactory; public class RealResult extends ElementResult<IReal> { public RealResult(IReal real, IEvaluatorContext ctx) { this(real.getType(), real, ctx); } public RealResult(Type type, IReal real, IEvaluatorContext ctx) { super(type, real, ctx); } @Override public <U extends IValue, V extends IValue> Result<U> add(Result<V> result) { return result.addReal(this); } @Override public <U extends IValue, V extends IValue> Result<U> multiply(Result<V> result) { return result.multiplyReal(this); } @Override public <U extends IValue, V extends IValue> Result<U> divide(Result<V> result) { return result.divideReal(this); } @Override public <U extends IValue, V extends IValue> Result<U> makeRange(Result<V> that) { return that.makeRangeFromReal(this); } @Override public <U extends IValue, V extends IValue, W extends IValue> Result<U> makeStepRange(Result<V> to, Result<W> step) { return to.makeStepRangeFromReal(this, step); } @Override public <U extends IValue, V extends IValue> Result<U> subtract(Result<V> result) { return result.subtractReal(this); } @Override public <V extends IValue> Result<IBool> equals(Result<V> that) { return that.equalToReal(this); } @Override public <V extends IValue> Result<IBool> nonEquals(Result<V> that) { return that.nonEqualToReal(this); } @Override public <V extends IValue> LessThanOrEqualResult lessThanOrEqual(Result<V> result) { return result.lessThanOrEqualReal(this); } @Override public <V extends IValue> Result<IBool> greaterThan(Result<V> that) { return that.greaterThanReal(this); } @Override public <V extends IValue> Result<IBool> greaterThanOrEqual(Result<V> that) { return that.greaterThanOrEqualReal(this); } @Override public <V extends IValue> Result<IBool> lessThan(Result<V> that) { return that.lessThanReal(this); } /// real impls start here @Override public <U extends IValue> Result<U> negative() { return makeResult(type, getValue().negate(), ctx); } @Override protected <U extends IValue> Result<U> addInteger(IntegerResult n) { return n.widenToReal().add(this); } @Override protected <U extends IValue> Result<U> subtractInteger(IntegerResult n) { // Note reversed args: we need n - this return n.widenToReal().subtract(this); } @Override protected <U extends IValue> Result<U> multiplyInteger(IntegerResult n) { return n.widenToReal().multiply(this); } @Override protected <U extends IValue> Result<U> divideInteger(IntegerResult n) { try { // Note reversed args: we need n / this return n.widenToReal().divide(this); } catch (ArithmeticException ae) { throw RuntimeExceptionFactory.arithmeticException(ae.getMessage(), this.ctx.getCurrentAST(), null); } } @Override protected <U extends IValue> Result<U> addRational(RationalResult n) { return n.widenToReal().add(this); } @Override protected <U extends IValue> Result<U> subtractRational(RationalResult n) { // Note reversed args: we need n - this return n.widenToReal().subtract(this); } @Override protected <U extends IValue> Result<U> multiplyRational(RationalResult n) { return n.widenToReal().multiply(this); } @Override protected <U extends IValue> Result<U> divideRational(RationalResult n) { try { // Note reversed args: we need n / this return n.widenToReal().divide(this); } catch (ArithmeticException ae) { throw RuntimeExceptionFactory.arithmeticException(ae.getMessage(), this.ctx.getCurrentAST(), null); } } @Override protected <U extends IValue> Result<U> addReal(ElementResult<IReal> n) { return makeResult(type, getValue().add(n.getValue()), ctx); } @Override protected <U extends IValue> Result<U> subtractReal(ElementResult<IReal> n) { // note the reverse subtraction. return makeResult(type, n.getValue().subtract(getValue()), ctx); } @Override protected <U extends IValue> Result<U> multiplyReal(ElementResult<IReal> n) { return makeResult(type, getValue().multiply(n.getValue()), ctx); } @Override protected <U extends IValue> Result<U> divideReal(ElementResult<IReal> n) { try { // note the reverse division int prec = ValueFactoryFactory.getValueFactory().getPrecision(); return makeResult(type, n.getValue().divide(getValue(), prec), ctx); } catch (ArithmeticException ae) { throw RuntimeExceptionFactory.arithmeticException(ae.getMessage(), this.ctx.getCurrentAST(), null); } } @Override protected Result<IBool> equalToReal(RealResult that) { return bool(that.getValue().equal(getValue()).getValue(), ctx); } @Override protected Result<IBool> equalToValue(ValueResult that) { return equalityBoolean(that); } @Override protected Result<IBool> equalToRational(RationalResult that) { return bool(that.getValue().equal(getValue()).getValue(), ctx); } @Override protected Result<IBool> nonEqualToReal(RealResult that) { return bool(!that.getValue().equal(getValue()).getValue(), ctx); } @Override protected LessThanOrEqualResult lessThanOrEqualReal(ElementResult<IReal> that) { // note reversed args: we need that <= this return new LessThanOrEqualResult(that.getValue().less(getValue()).getValue(), that.getValue().equal(getValue()).getValue(), ctx); } @Override protected Result<IBool> equalToInteger(IntegerResult that) { return that.widenToReal().equals(this); } @Override protected Result<IBool> nonEqualToInteger(IntegerResult that) { return that.widenToReal().nonEquals(this); } @Override protected Result<IBool> lessThanInteger(IntegerResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().less(getValue()), ctx); } @Override protected Result<IBool> lessThanNumber(NumberResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().less(getValue()), ctx); } @Override protected Result<IBool> lessThanReal(RealResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().less(getValue()), ctx); } @Override protected LessThanOrEqualResult lessThanOrEqualInteger(IntegerResult that) { return new LessThanOrEqualResult(that.getValue().less(getValue()).getValue(), that.getValue().equal(getValue()).getValue(), ctx); } @Override protected Result<IBool> greaterThanInteger(IntegerResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().greater(getValue()), ctx); } @Override protected Result<IBool> greaterThanOrEqualInteger(IntegerResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().greaterEqual(getValue()), ctx); } @Override protected Result<IBool> greaterThanNumber(NumberResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().greater(getValue()), ctx); } @Override protected Result<IBool> greaterThanOrEqualReal(ElementResult<IReal> that) { return makeResult(getTypeFactory().boolType(), that.getValue().greaterEqual(getValue()), ctx); } @Override protected Result<IBool> greaterThanOrEqualNumber(NumberResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().greaterEqual(getValue()), ctx); } @Override protected Result<IBool> greaterThanReal(ElementResult<IReal> that) { return makeResult(getTypeFactory().boolType(), that.getValue().greater(getValue()), ctx); } protected Result<IBool> lessThanRational(RationalResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().less(getValue()), ctx); } @Override protected LessThanOrEqualResult lessThanOrEqualRational(RationalResult that) { return new LessThanOrEqualResult(that.getValue().less(getValue()).getValue(), that.getValue().equal(getValue()).getValue(), ctx); } @Override protected Result<IBool> greaterThanRational(RationalResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().greater(getValue()), ctx); } @Override protected Result<IBool> greaterThanOrEqualRational(RationalResult that) { return makeResult(getTypeFactory().boolType(), that.getValue().greaterEqual(getValue()), ctx); } @Override protected <U extends IValue> Result<U> addNumber(NumberResult n) { return makeResult(type, getValue().add(n.getValue()), ctx); } @Override protected <U extends IValue> Result<U> subtractNumber(NumberResult n) { // note the reverse subtraction. return makeResult(type, n.getValue().subtract(getValue()), ctx); } @Override protected <U extends IValue> Result<U> multiplyNumber(NumberResult n) { return makeResult(type, getValue().multiply(n.getValue()), ctx); } @Override protected <U extends IValue> Result<U> divideNumber(NumberResult n) { try { // note the reverse division return makeResult(type, n.getValue().divide(getValue(), 60 /* PRECISION */), ctx); // TODO } catch (ArithmeticException ae) { throw RuntimeExceptionFactory.arithmeticException(ae.getMessage(), this.ctx.getCurrentAST(), null); } } @Override protected Result<IBool> equalToNumber(NumberResult that) { return bool(that.getValue().equal(getValue()).getValue(), ctx); } @Override protected Result<IBool> nonEqualToNumber(NumberResult that) { return bool(!that.getValue().equal(getValue()).getValue(), ctx); } @Override protected LessThanOrEqualResult lessThanOrEqualNumber(NumberResult that) { return new LessThanOrEqualResult(that.getValue().less(getValue()).getValue(), that.getValue().equal(getValue()).getValue(), ctx); } @Override protected <U extends IValue> Result<U> makeRangeFromInteger(IntegerResult from) { return makeRangeWithDefaultStep(toReal(from)); } @Override protected <U extends IValue, V extends IValue> Result<U> makeStepRangeFromInteger(IntegerResult from, Result<V> second) { return makeStepRangeFromToWithSecond(toReal(from), this, second, getValueFactory(), getTypeFactory(), ctx); } @Override protected <U extends IValue> Result<U> makeRangeFromReal(ElementResult<IReal> from) { return makeRangeWithDefaultStep(from); } @Override protected <U extends IValue, V extends IValue> Result<U> makeStepRangeFromReal(ElementResult<IReal> from, Result<V> second) { return makeStepRangeFromToWithSecond(from, this, second, getValueFactory(), getTypeFactory(), ctx); } @Override protected <U extends IValue> Result<U> makeRangeFromNumber(NumberResult from) { return makeRangeWithDefaultStep(from); } private <U extends IValue, V extends INumber> Result<U> makeRangeWithDefaultStep(Result<V> from) { if (from.getValue().less(getValue()).getValue()) { return makeStepRangeFromToWithSecond(from, this, makeResult(getTypeFactory().realType().lub(from.getType()), from.getValue().add(getValueFactory().real(1.0)), ctx), getValueFactory(), getTypeFactory(), ctx); } return makeStepRangeFromToWithSecond(from, this, makeResult(getTypeFactory().realType().lub(from.getType()), from.getValue().subtract(getValueFactory().real(1.0)), ctx), getValueFactory(), getTypeFactory(), ctx); } }