/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.expressions;
import gw.internal.gosu.parser.Expression;
import gw.internal.gosu.parser.TypeLord;
import gw.lang.parser.GosuParserTypes;
import gw.lang.parser.ICoercer;
import gw.lang.parser.Keyword;
import gw.lang.parser.coercers.MetaTypeToClassCoercer;
import gw.lang.parser.expressions.ITypeAsExpression;
import gw.lang.reflect.IType;
import gw.config.CommonServices;
import gw.lang.reflect.java.IJavaType;
import gw.lang.reflect.java.JavaTypes;
import java.util.Date;
/**
* Represents a typeas expression in the Gosu grammar:
* <pre>
* <i>typeas-expression</i>
* <conditional-or-expression> <b>typeas</b> <type-literal>
* </pre>
* <p/>
*
* @see gw.lang.parser.IGosuParser
*/
public class TypeAsExpression extends Expression implements ITypeAsExpression
{
protected Expression _lhs;
private ICoercer _coercer;
/**
* Base constructor sets type to BooleanType.
*/
public TypeAsExpression()
{
}
/**
* @return The expression for the left-hand-side operand.
*/
public Expression getLHS()
{
return _lhs;
}
/**
* @param e The expression for the left-hand-side operand.
*/
public void setLHS( Expression e )
{
_lhs = e;
}
public boolean isCompileTimeConstant()
{
// Coercions tend not to be compile-time constants, only support them on primitive types, which involve only casting not object construction
return (_coercer == null || getLHS() != null &&
((getLHS().getType().isPrimitive() && getType().isPrimitive()) ||
_coercer instanceof MetaTypeToClassCoercer)) &&
getLHS().isCompileTimeConstant();
}
/**
* Perform a type cast.
*/
public Object evaluate()
{
if( !isCompileTimeConstant() )
{
return super.evaluate();
}
Object value = getLHS().evaluate();
IType argType = getType();
if( value instanceof IType && argType instanceof IJavaType && JavaTypes.CLASS() == TypeLord.getPureGenericType( argType ) )
{
// Don't force class loading during compilation
return value;
}
//============================================================================
// Special Types
// TODO cgross: remove these special cases (came from ParsedElement#convertValue)
// and allow the coercion manager to handle these cases
//============================================================================
if( argType == GosuParserTypes.NUMBER_TYPE() )
{
return CommonServices.getCoercionManager().makeDoubleFrom( value );
}
else if( argType == GosuParserTypes.STRING_TYPE() )
{
return CommonServices.getCoercionManager().makeStringFrom( value );
}
else if( argType == GosuParserTypes.DATETIME_TYPE() )
{
Date date = CommonServices.getCoercionManager().makeDateFrom( value );
if ( date != null ) {
return date;
}
}
//============================================================================
// This is really all we should be doing
//============================================================================
if( _coercer != null && (value != null || _coercer.handlesNull()) )
{
return _coercer.coerceValue( argType, value );
}
return value;
}
public void setCoercer( ICoercer coercer )
{
_coercer = coercer;
}
public ICoercer getCoercer()
{
return _coercer;
}
//------------------------------------------------------------------------------
@Override
public String toString()
{
return getLHS().toString()
+ " " + Keyword.KW_as + " "
+ getType().getName();
}
}