/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.expressions;
import gw.internal.gosu.parser.CapturedSymbol;
import gw.internal.gosu.parser.DynamicPropertySymbol;
import gw.internal.gosu.parser.DynamicSymbol;
import gw.internal.gosu.parser.Expression;
import gw.internal.gosu.parser.IGosuClassInternal;
import gw.internal.gosu.parser.Symbol;
import gw.internal.gosu.parser.ScopedDynamicSymbol;
import gw.internal.gosu.parser.java.classinfo.CompileTimeExpressionParser;
import gw.internal.gosu.parser.statements.VarStatement;
import gw.lang.parser.IParsedElement;
import gw.lang.parser.ISymbol;
import gw.lang.parser.ISymbolTable;
import gw.lang.parser.expressions.IIdentifierExpression;
import gw.lang.reflect.IFunctionType;
import gw.lang.reflect.IPropertyInfo;
import gw.lang.reflect.IPropertyInfoDelegate;
import gw.lang.reflect.IType;
import gw.lang.reflect.java.ICompileTimeConstantValue;
import java.lang.reflect.Method;
/**
* Gosu identifier expression.
*/
public class Identifier extends Expression implements IIdentifierExpression
{
private ISymbol _symbol;
public Identifier()
{
}
public ISymbol getSymbol()
{
return _symbol;
}
public void setSymbol( ISymbol symbol, ISymbolTable symTable )
{
// Make a copy of the symbol without the value so that the parsed expression
// doesn't hold onto pointers it shouldn't
_symbol = symbol.getLightWeightReference();
if( _symbol.hasDynamicSymbolTable() )
{
_symbol.setDynamicSymbolTable( symTable );
}
}
@Override
public boolean isCompileTimeConstant()
{
//## todo: reverting change 537145 to see if this is what is crushing suites in TH (causing OutOfMemoryError with permgen)
ISymbol symbol = getSymbol();
return (!(symbol instanceof DynamicSymbol) &&
!(symbol instanceof DynamicPropertySymbol) &&
!symbol.isLocal()) ||
isStaticFinalInitializedCompileTimeConstant();
//
// return symbol.isStatic() && symbol.isFinal();
}
public boolean isStaticFinalInitializedCompileTimeConstant()
{
ISymbol symbol = getSymbol();
if ( symbol instanceof DynamicSymbol && symbol.isStatic() && symbol.isFinal() )
{
IGosuClassInternal gsClass = (IGosuClassInternal)symbol.getGosuClass();
if ( !gsClass.isValid() )
{
return false;
}
VarStatement varStmt = gsClass.getStaticField( symbol.getName() );
if( varStmt != null && varStmt.getAsExpression() != null )
{
return varStmt.getAsExpression().isCompileTimeConstant();
}
}
return false;
}
public Object evaluate()
{
ISymbol symbol = getSymbol();
if( isCompileTimeConstant() && symbol instanceof DynamicSymbol )
{
IGosuClassInternal gsClass = (IGosuClassInternal)symbol.getGosuClass();
gsClass.isValid();
VarStatement varStmt = gsClass.getStaticField( symbol.getName() );
if( varStmt != null )
{
return varStmt.getAsExpression().evaluate();
}
throw new IllegalStateException( "Should have found field for: " + symbol.getName() );
}
IType type = symbol.getType();
Object value = symbol.getValue();
if( type instanceof IFunctionType )
{
// If this symbol simply wraps another symbol, return the wrapped symbol
if( value instanceof Symbol )
{
return value;
}
// If this symbol is a root invokable symbol, return the symbol itself, rather than the value
if( value instanceof Method || value instanceof IParsedElement )
{
return symbol;
}
}
if( symbol instanceof DynamicPropertySymbol )
{
DynamicPropertySymbol dps = (DynamicPropertySymbol)symbol;
IPropertyInfo pi = dps.getPropertyInfo();
while( pi instanceof IPropertyInfoDelegate )
{
pi = ((IPropertyInfoDelegate)pi).getSource();
}
return ((ICompileTimeConstantValue)pi).doCompileTimeEvaluation();
}
if( symbol instanceof CompileTimeExpressionParser.CompileTimeFieldSymbol )
{
return ((ICompileTimeConstantValue)symbol).doCompileTimeEvaluation();
}
return value;
}
@Override
public String toString()
{
return getSymbol().getName();
}
public boolean isLocalVariable() {
ISymbol symbol = getSymbol();
while (symbol instanceof CapturedSymbol) {
symbol = ((CapturedSymbol)symbol).getReferredSymbol();
}
return !(symbol instanceof ScopedDynamicSymbol) &&
!(symbol instanceof DynamicSymbol) &&
!(symbol instanceof CapturedSymbol) &&
symbol.getIndex() >= 0;
}
}