/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.ir.transform.expression; import gw.lang.parser.MemberAccessKind; import gw.internal.gosu.parser.Symbol; import gw.internal.gosu.parser.BeanAccess; import gw.internal.gosu.parser.expressions.Identifier; import gw.internal.gosu.parser.expressions.MemberAccess; import gw.internal.gosu.parser.expressions.MemberExpansionAccess; import gw.internal.gosu.ir.transform.ExpressionTransformer; import gw.internal.gosu.ir.transform.TopLevelTransformationContext; import gw.lang.ir.IRExpression; import gw.lang.parser.StandardSymbolTable; import gw.lang.parser.exceptions.ParseException; import gw.lang.reflect.IType; import gw.lang.reflect.IPropertyInfo; import gw.lang.reflect.java.IJavaType; import gw.lang.reflect.java.JavaTypes; import gw.lang.reflect.java.JavaTypes; /** */ public class MemberExpansionAccessTransformer extends AbstractMemberExpansionTransformer<MemberAccess> { public static IRExpression compile( TopLevelTransformationContext cc, MemberExpansionAccess expr ) { MemberExpansionAccessTransformer compiler = new MemberExpansionAccessTransformer( cc, expr ); return compiler.compile(); } private MemberExpansionAccessTransformer( TopLevelTransformationContext cc, MemberExpansionAccess expr ) { super( cc, expr ); } @Override protected IRExpression createIterationExpr(IType rootComponentType, String irIdentifierSym, IType identifierType, IType compType) { // Make MemberAccessExpr for *temp_mae_X.<property> MemberAccess ma; if( rootComponentType.isArray() || JavaTypes.COLLECTION().isAssignableFrom( rootComponentType ) ) { // The MemberExpansionAccess just chains together, so the return type of the nested one is the same as the // return type of the outer one ma = new MemberExpansionAccess(); ma.setType( _expr().getType() ); ma.setMemberAccessKind( MemberAccessKind.EXPANSION ); // expansion implies null-safety on root } else { ma = new MemberAccess(); // We need to set the type of the MemberAccess to exactly the type of the property in question ma.setType( getPropertyOrMethodType(rootComponentType, compType) ); ma.setMemberAccessKind( MemberAccessKind.NULL_SAFE ); // expansion implies null-safety on elements } Identifier id = new Identifier(); id.setType( rootComponentType ); StandardSymbolTable symTable = new StandardSymbolTable(); Symbol identifierSym = new Symbol( irIdentifierSym, identifierType, symTable); id.setSymbol( identifierSym, symTable ); ma.setRootExpression( id ); ma.setMemberName( _expr().getMemberName() ); return ExpressionTransformer.compile( ma, _cc() ); } @Override protected IType getPropertyOrMethodType(IType rootComponentType, IType compType) { return getProperty( rootComponentType ).getFeatureType(); } private IPropertyInfo getProperty(IType rootComponentType) { try { return BeanAccess.getPropertyInfoDirectly(rootComponentType, _expr().getMemberName()); } catch (ParseException e) { throw new RuntimeException(e); } } }