/*
* 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.CollectionInitializerExpression;
import gw.internal.gosu.parser.expressions.NewExpression;
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.IRExpression;
import gw.lang.ir.IRStatement;
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.Collection;
import java.util.AbstractCollection;
import java.util.List;
import java.util.ArrayList;
/**
*/
public class CollectionInitializerExpressionTransformer extends AbstractElementTransformer<CollectionInitializerExpression>
{
public static List<IRStatement> compile( TopLevelTransformationContext cc, CollectionInitializerExpression expr, IRExpression root )
{
CollectionInitializerExpressionTransformer gen = new CollectionInitializerExpressionTransformer( cc, expr );
return gen.compile( root );
}
private CollectionInitializerExpressionTransformer( TopLevelTransformationContext cc, CollectionInitializerExpression expr )
{
super( cc, expr );
}
private List<IRStatement> compile( IRExpression root )
{
List<IRStatement> statements = new ArrayList<IRStatement>();
Class collectionType = getCollectionType();
for( IExpression e : getParsedElement().getValues() )
{
IRExpression value = ExpressionTransformer.compile( e, _cc() );
statements.add( buildMethodCall( callMethod( collectionType, "add", new Class[]{Object.class}, root, exprList( value ) ) ));
}
return statements;
}
/**
* Try to get a more specific class instead of using the Collection interface
* i.e., invokevirtual is significantly faster then invokeinterface.
*/
private Class getCollectionType()
{
Class collectionType = Collection.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 )
{
collectionType = javaBackedClass;
}
else if( JavaTypes.getJreType(AbstractCollection.class).isAssignableFrom( newType ) )
{
collectionType = AbstractCollection.class;
}
}
return collectionType;
}
}