/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.ir.transform.expression; import gw.internal.gosu.ir.transform.AbstractElementTransformer; import gw.internal.gosu.parser.expressions.NewExpression; import gw.internal.gosu.parser.expressions.MapInitializerExpression; import gw.internal.gosu.ir.transform.ExpressionTransformer; import gw.internal.gosu.ir.transform.TopLevelTransformationContext; import gw.internal.gosu.ir.transform.util.IRTypeResolver; import gw.lang.ir.IRStatement; import gw.lang.ir.IRExpression; import gw.lang.parser.IExpression; import gw.lang.parser.IParsedElement; import gw.lang.reflect.IType; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.java.IJavaClassInfo; import gw.lang.reflect.java.JavaTypes; import java.util.AbstractMap; import java.util.Map; import java.util.List; import java.util.ArrayList; /** */ public class MapInitializerExpressionTransformer extends AbstractElementTransformer<MapInitializerExpression> { public static List<IRStatement> compile( TopLevelTransformationContext cc, MapInitializerExpression expr, IRExpression root ) { MapInitializerExpressionTransformer gen = new MapInitializerExpressionTransformer( cc, expr ); return gen.compile( root ); } private MapInitializerExpressionTransformer( TopLevelTransformationContext cc, MapInitializerExpression expr ) { super( cc, expr ); } private List<IRStatement> compile( IRExpression root ) { Class mapType = getMapType(); List<IExpression> keys = getParsedElement().getKeys(); List<IExpression> values = getParsedElement().getValues(); List<IRStatement> statements = new ArrayList<IRStatement>(); for( int i = 0; i < keys.size(); i++ ) { IExpression keyExpr = keys.get( i ); IRExpression irKeyExpr = ExpressionTransformer.compile( keyExpr, _cc() ); IExpression valueExpr = values.get( i ); IRExpression irValueExpr = ExpressionTransformer.compile( valueExpr, _cc() ); IRExpression putCall = callMethod( mapType, "put", new Class[]{Object.class, Object.class}, root, exprList( irKeyExpr, irValueExpr ) ); statements.add( buildMethodCall( putCall ) ); } return statements; } /** * Try to get a more specific class instead of using the Map interface * i.e., invokevirtual is significantly faster then invokeinterface. */ private Class getMapType() { Class mapType = Map.class; IParsedElement parent = getParsedElement().getParent(); if( parent instanceof NewExpression ) { IType newType = ((NewExpression)parent).getType(); IJavaClassInfo classInfo = IRTypeResolver.getJavaBackedClass(newType); Class javaBackedClass = classInfo != null ? classInfo.getBackingClass() : null; if( classInfo != null && javaBackedClass != null ) { mapType = javaBackedClass; } else if( JavaTypes.getJreType(AbstractMap.class).isAssignableFrom( newType ) ) { mapType = AbstractMap.class; } } return mapType; } }