/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.ir.transform.expression; import gw.internal.gosu.ir.nodes.IRTypeFactory; import gw.internal.gosu.ir.nodes.JavaClassIRType; import gw.internal.gosu.ir.transform.ExpressionTransformer; import gw.internal.gosu.ir.transform.TopLevelTransformationContext; import gw.internal.gosu.parser.expressions.FeatureLiteral; import gw.internal.gosu.parser.expressions.TypeLiteral; import gw.lang.ir.IRExpression; import gw.lang.ir.expression.IRNewExpression; import gw.lang.parser.IExpression; import gw.lang.reflect.IType; import gw.lang.reflect.features.BoundComplexPropertyChainReference; import gw.lang.reflect.features.BoundMethodReference; import gw.lang.reflect.features.BoundPropertyReference; import gw.lang.reflect.features.BoundSimplePropertyChainReference; import gw.lang.reflect.features.ComplexPropertyChainReference; import gw.lang.reflect.features.ConstructorReference; import gw.lang.reflect.features.FeatureReference; import gw.lang.reflect.features.MethodChainReference; import gw.lang.reflect.features.MethodReference; import gw.lang.reflect.features.PropertyReference; import gw.lang.reflect.features.SimplePropertyChainReference; import java.util.ArrayList; import java.util.List; public class FeatureLiteralTransformer extends AbstractExpressionTransformer<FeatureLiteral> { public static IRExpression compile( TopLevelTransformationContext cc, FeatureLiteral expr ) { FeatureLiteralTransformer compiler = new FeatureLiteralTransformer( cc, expr ); return compiler.compile(); } private FeatureLiteralTransformer( TopLevelTransformationContext cc, FeatureLiteral expr ) { super( cc, expr ); } protected IRExpression compile_impl() { if( _expr().isPropertyLiteral() ) { IExpression root = _expr().getRoot(); if( root instanceof TypeLiteral ) { return buildNewExpression( PropertyReference.class, new Class[]{IType.class, String.class}, exprList( pushType( _expr().getRootType() ), stringLiteral( _expr().getPropertyName() ) ) ); } else if( root instanceof FeatureLiteral ) { IRNewExpression expression = (IRNewExpression)ExpressionTransformer.compile( root, _cc() ); if( JavaClassIRType.get( SimplePropertyChainReference.class ).isAssignableFrom( IRTypeFactory.get( _expr().getType() ) ) ) { return buildNewExpression( SimplePropertyChainReference.class, new Class[]{IType.class, FeatureReference.class, String.class}, exprList( pushType( _expr().getRootType() ), expression, stringLiteral( _expr().getPropertyName() ) ) ); } else if( JavaClassIRType.get( BoundSimplePropertyChainReference.class ).isAssignableFrom( IRTypeFactory.get( _expr().getType() ) ) ) { return buildNewExpression( BoundSimplePropertyChainReference.class, new Class[]{IType.class, FeatureReference.class, String.class}, exprList( pushType( _expr().getRootType() ), expression, stringLiteral( _expr().getPropertyName() ) ) ); } else if( JavaClassIRType.get( BoundComplexPropertyChainReference.class ).isAssignableFrom( IRTypeFactory.get( _expr().getType() ) ) ) { return buildNewExpression( BoundComplexPropertyChainReference.class, new Class[]{IType.class, FeatureReference.class, String.class}, exprList( pushType( _expr().getRootType() ), expression, stringLiteral( _expr().getPropertyName() ) ) ); } else { return buildNewExpression( ComplexPropertyChainReference.class, new Class[]{IType.class, FeatureReference.class, String.class}, exprList( pushType( _expr().getRootType() ), expression, stringLiteral( _expr().getPropertyName() ) ) ); } } else { return buildNewExpression( BoundPropertyReference.class, new Class[]{IType.class, Object.class, String.class}, exprList( pushType( _expr().getRootType() ), ExpressionTransformer.compile( root, _cc() ), stringLiteral( _expr().getPropertyName() ) ) ); } } else if( _expr().isMethodLiteral() ) { IExpression root = _expr().getRoot(); if( root instanceof TypeLiteral ) { return buildNewExpression( MethodReference.class, new Class[]{IType.class, String.class, IType[].class, Object[].class}, exprList( pushType( _expr().getRootType() ), stringLiteral( _expr().getMethodName() ), pushArrayOfTypes( _expr().getParameterTypes() ), getBoundValues()) ); } else if( root instanceof FeatureLiteral ) { IRNewExpression expression = (IRNewExpression) ExpressionTransformer.compile(root, _cc()); return buildNewExpression( MethodChainReference.class, new Class[]{IType.class, FeatureReference.class, String.class, IType[].class, Object[].class}, exprList( pushType( _expr().getRootType() ), expression, stringLiteral( _expr().getMethodName() ), pushArrayOfTypes( _expr().getParameterTypes() ), getBoundValues() ) ); } else { return buildNewExpression( BoundMethodReference.class, new Class[]{IType.class, Object.class, String.class, IType[].class, Object[].class}, exprList( pushType( _expr().getRootType() ), ExpressionTransformer.compile( root, _cc() ), stringLiteral( _expr().getMethodName() ), pushArrayOfTypes( _expr().getParameterTypes() ), getBoundValues() ) ); } } else if( _expr().isConstructorLiteral() ) { return buildNewExpression( ConstructorReference.class, new Class[]{IType.class, IType[].class, Object[].class}, exprList( pushType( _expr().getRootType() ), pushArrayOfTypes( _expr().getParameterTypes() ), getBoundValues() ) ); } else { throw new IllegalStateException( "Unable to convert reference of type " + _expr().toString() ); } } private IRExpression getBoundValues() { List<IExpression> args = _expr().getBoundArgs(); IRExpression boundArgs; if( args == null ) { boundArgs = pushNull(); } else { ArrayList<IRExpression> values = new ArrayList<IRExpression>(); for( IExpression arg : args ) { values.add( ExpressionTransformer.compile( arg, _cc() ) ); } boundArgs = collectArgsIntoObjArray( values ); } return boundArgs; } }