/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.ir.transform.expression;
import gw.lang.reflect.interval.BigDecimalInterval;
import gw.lang.reflect.interval.BigIntegerInterval;
import gw.lang.reflect.interval.DateInterval;
import gw.lang.reflect.interval.ISequenceable;
import gw.lang.reflect.interval.IntegerInterval;
import gw.lang.reflect.interval.LongInterval;
import gw.internal.gosu.ir.transform.ExpressionTransformer;
import gw.internal.gosu.ir.transform.TopLevelTransformationContext;
import gw.internal.gosu.parser.expressions.IntervalExpression;
import gw.lang.ir.IRExpression;
import gw.lang.reflect.interval.ComparableInterval;
import gw.lang.reflect.IRelativeTypeInfo;
import gw.lang.reflect.IType;
import gw.lang.reflect.interval.SequenceableInterval;
import gw.lang.reflect.java.JavaTypes;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*/
public class IntervalExpressionTransformer extends AbstractExpressionTransformer<IntervalExpression>
{
public static IRExpression compile( TopLevelTransformationContext cc, IntervalExpression expr )
{
IntervalExpressionTransformer gen = new IntervalExpressionTransformer( cc, expr );
return gen.compile();
}
private IntervalExpressionTransformer( TopLevelTransformationContext cc, IntervalExpression expr )
{
super( cc, expr );
}
protected IRExpression compile_impl()
{
IType type = _expr().getType();
if( type == JavaTypes.INTEGER_INTERVAL() )
{
return makeIntegerInterval();
}
else if( type == JavaTypes.LONG_INTERVAL() )
{
return makeLongInterval();
}
else if( type == JavaTypes.BIG_INTEGER_INTERVAL() )
{
return makeBigIntegerInterval();
}
else if( type == JavaTypes.BIG_DECIMAL_INTERVAL() )
{
return makeBigDecimalInterval();
}
else if( type == JavaTypes.DATE_INTERVAL() )
{
return makeDateInterval();
}
else if( type.getGenericType() == JavaTypes.SEQUENCEABLE_INTERVAL() )
{
return makeSequenceableInterval();
}
if( type.getGenericType() == JavaTypes.COMPARABLE_INTERVAL() )
{
return makeComparableInterval();
}
throw new IllegalStateException( "Unknown interval type: " + type.getName() );
}
private IRExpression makeIntegerInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( boxValue( _expr().getLHS().getType(), ExpressionTransformer.compile( _expr().getLHS(), _cc() ) ) );
args.add( boxValue( _expr().getRHS().getType(), ExpressionTransformer.compile( _expr().getRHS(), _cc() ) ) );
args.add( boxValue( JavaTypes.pINT(), pushConstant( 1 ) ) );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeIntegerInterval",
new Class[]{Object.class, Object.class, Integer.class, boolean.class, boolean.class},
args );
}
private IRExpression makeLongInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( boxValue( _expr().getLHS().getType(), ExpressionTransformer.compile( _expr().getLHS(), _cc() ) ) );
args.add( boxValue( _expr().getRHS().getType(), ExpressionTransformer.compile( _expr().getRHS(), _cc() ) ) );
args.add( boxValue( JavaTypes.pLONG(), pushConstant( 1L ) ) );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeLongInterval",
new Class[]{Long.class, Long.class, Long.class, boolean.class, boolean.class},
args );
}
private IRExpression makeBigIntegerInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( ExpressionTransformer.compile( _expr().getLHS(), _cc() ) );
args.add( ExpressionTransformer.compile( _expr().getRHS(), _cc() ) );
args.add( getStaticField( JavaTypes.BIG_INTEGER(), "ONE", getDescriptor( JavaTypes.BIG_INTEGER() ), IRelativeTypeInfo.Accessibility.PUBLIC ) );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeBigIntegerInterval",
new Class[]{BigInteger.class, BigInteger.class, BigInteger.class, boolean.class, boolean.class},
args );
}
private IRExpression makeBigDecimalInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( ExpressionTransformer.compile( _expr().getLHS(), _cc() ) );
args.add( ExpressionTransformer.compile( _expr().getRHS(), _cc() ) );
args.add( getStaticField( JavaTypes.BIG_DECIMAL(), "ONE", getDescriptor( JavaTypes.BIG_DECIMAL() ), IRelativeTypeInfo.Accessibility.PUBLIC ) );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeBigDecimalInterval",
new Class[]{Number.class, Number.class, BigDecimal.class, boolean.class, boolean.class},
args );
}
private IRExpression makeDateInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( ExpressionTransformer.compile( _expr().getLHS(), _cc() ) );
args.add( ExpressionTransformer.compile( _expr().getRHS(), _cc() ) );
args.add( pushNull() );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeDateInterval",
new Class[]{Date.class, Date.class, Integer.class, boolean.class, boolean.class},
args );
}
private IRExpression makeSequenceableInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( ExpressionTransformer.compile( _expr().getLHS(), _cc() ) );
args.add( ExpressionTransformer.compile( _expr().getRHS(), _cc() ) );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeSequenceableInterval",
new Class[]{ISequenceable.class, ISequenceable.class, boolean.class, boolean.class},
args );
}
private IRExpression makeComparableInterval()
{
List<IRExpression> args = new ArrayList<IRExpression>();
args.add( ExpressionTransformer.compile( _expr().getLHS(), _cc() ) );
args.add( ExpressionTransformer.compile( _expr().getRHS(), _cc() ) );
args.add( pushConstant( _expr().isLeftClosed() ) );
args.add( pushConstant( _expr().isRightClosed() ) );
return callStaticMethod( IntervalExpressionTransformer.class, "_makeComparableInterval",
new Class[]{Comparable.class, Comparable.class, boolean.class, boolean.class},
args );
}
@SuppressWarnings({"UnusedDeclaration"})
public static IntegerInterval _makeIntegerInterval( Object lhs, Object rhs, Integer step, boolean bLeftClosed, boolean bRightClosed )
{
if( lhs instanceof Character )
{
lhs = Integer.valueOf( (Character)lhs );
}
if( rhs instanceof Character )
{
rhs = Integer.valueOf( (Character)rhs );
}
int iLhs = ((Number)lhs).intValue();
int iRhs = ((Number)rhs).intValue();
if( iRhs < iLhs )
{
return new IntegerInterval( iRhs, iLhs, step, bLeftClosed, bRightClosed, true );
}
return new IntegerInterval( iLhs, iRhs, step, bLeftClosed, bRightClosed, false );
}
@SuppressWarnings({"UnusedDeclaration"})
public static LongInterval _makeLongInterval( Long lhs, Long rhs, Long step, boolean bLeftClosed, boolean bRightClosed )
{
if( rhs.longValue() < lhs.longValue() )
{
return new LongInterval( rhs, lhs, step, bLeftClosed, bRightClosed, true );
}
return new LongInterval( lhs, rhs, step, bLeftClosed, bRightClosed, false );
}
@SuppressWarnings({"UnusedDeclaration"})
public static BigIntegerInterval _makeBigIntegerInterval( BigInteger lhs, BigInteger rhs, BigInteger step, boolean bLeftClosed, boolean bRightClosed )
{
if( rhs.compareTo( lhs ) < 0 )
{
return new BigIntegerInterval( rhs, lhs, step, bLeftClosed, bRightClosed, true );
}
return new BigIntegerInterval( lhs, rhs, step, bLeftClosed, bRightClosed, false );
}
@SuppressWarnings({"UnusedDeclaration"})
public static BigDecimalInterval _makeBigDecimalInterval( Number lhs, Number rhs, BigDecimal step, boolean bLeftClosed, boolean bRightClosed )
{
BigDecimal biglhs = lhs instanceof BigDecimal ? (BigDecimal)lhs : new BigDecimal( lhs.toString() );
BigDecimal bigrhs = rhs instanceof BigDecimal ? (BigDecimal)rhs : new BigDecimal( rhs.doubleValue() == Double.POSITIVE_INFINITY ? "1E+1000" : rhs.toString() );
if( bigrhs.compareTo( biglhs ) < 0 )
{
return new BigDecimalInterval( bigrhs, biglhs, step, bLeftClosed, bRightClosed, true );
}
return new BigDecimalInterval( biglhs, bigrhs, step, bLeftClosed, bRightClosed, false );
}
@SuppressWarnings({"UnusedDeclaration"})
public static SequenceableInterval _makeSequenceableInterval( ISequenceable lhs, ISequenceable rhs, boolean bLeftClosed, boolean bRightClosed )
{
if( ((Comparable)rhs).compareTo( lhs ) < 0 )
{
return new SequenceableInterval( rhs, lhs, null, null, bLeftClosed, bRightClosed, true );
}
return new SequenceableInterval( lhs, rhs, null, null, bLeftClosed, bRightClosed, false );
}
@SuppressWarnings({"UnusedDeclaration"})
public static ComparableInterval _makeComparableInterval( Comparable lhs, Comparable rhs, boolean bLeftClosed, boolean bRightClosed )
{
if( rhs.compareTo( lhs ) < 0 )
{
return new ComparableInterval( rhs, lhs, bLeftClosed, bRightClosed, true );
}
return new ComparableInterval( lhs, rhs, bLeftClosed, bRightClosed, false );
}
@SuppressWarnings({"UnusedDeclaration"})
public static DateInterval _makeDateInterval( Date lhs, Date rhs, Integer step, boolean bLeftClosed, boolean bRightClosed )
{
if( step == null )
{
step = 1;
}
if( rhs.compareTo( lhs ) < 0 )
{
return new DateInterval( rhs, lhs, step, null, bLeftClosed, bRightClosed, true );
}
return new DateInterval( lhs, rhs, step, null, bLeftClosed, bRightClosed, false );
}
}