/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.ir.transform.statement; import gw.config.CommonServices; import gw.internal.gosu.parser.TypeLoaderAccess; import gw.internal.gosu.parser.expressions.ArrayAccess; import gw.internal.gosu.parser.statements.ArrayAssignmentStatement; import gw.internal.gosu.ir.transform.ExpressionTransformer; import gw.internal.gosu.ir.transform.TopLevelTransformationContext; import gw.lang.ir.IRStatement; import gw.lang.ir.IRExpression; import gw.lang.ir.IRSymbol; import gw.lang.ir.statement.IRStatementList; import gw.lang.parser.EvaluationException; import gw.lang.reflect.IType; import gw.lang.reflect.java.IJavaType; import gw.lang.reflect.java.JavaTypes; import gw.lang.reflect.java.JavaTypes; import java.util.List; /** */ public class ArrayAssignmentStatementTransformer extends AbstractStatementTransformer<ArrayAssignmentStatement> { public static IRStatement compile( TopLevelTransformationContext cc, ArrayAssignmentStatement stmt ) { ArrayAssignmentStatementTransformer gen = new ArrayAssignmentStatementTransformer( cc, stmt ); return gen.compile(); } private ArrayAssignmentStatementTransformer( TopLevelTransformationContext cc, ArrayAssignmentStatement stmt ) { super( cc, stmt ); } @Override protected IRStatement compile_impl() { ArrayAccess arrayAccess = _stmt().getArrayAccessExpression(); IRExpression originalRoot = ExpressionTransformer.compile( arrayAccess.getRootExpression(), _cc() ); IRSymbol tempRoot = null; IRExpression root; boolean needsAutoinsert = needsAutoinsert( arrayAccess ); if( needsAutoinsert) { tempRoot = _cc().makeAndIndexTempSymbol( originalRoot.getType() ); root = identifier( tempRoot ); } else { root = originalRoot; } IRExpression originalIndex = ExpressionTransformer.compile( arrayAccess.getMemberExpression(), _cc() ); IRSymbol tempIndex = null; IRExpression index; if( needsAutoinsert ) { tempIndex = _cc().makeAndIndexTempSymbol( originalIndex.getType() ); index = identifier( tempIndex ); } else { index = originalIndex; } IRExpression value = ExpressionTransformer.compile( _stmt().getExpression(), _cc() ); IType rootType = arrayAccess.getRootExpression().getType(); if( rootType.isArray() && isBytecodeType( rootType ) ) { // Normal array access return buildArrayStore(root, index, value, getDescriptor( rootType.getComponentType() )); } else { if( needsAutoinsert ) { return new IRStatementList( false, buildAssignment( tempRoot, originalRoot ), buildAssignment( tempIndex, originalIndex ), buildMethodCall( callStaticMethod( ArrayAssignmentStatementTransformer.class, "setOrAddElement", new Class[]{Object.class, int.class, Object.class}, exprList( root, index, value ) ) ) ); } else { return buildMethodCall( callStaticMethod( ArrayAssignmentStatementTransformer.class, "setArrayElement", new Class[]{Object.class, int.class, Object.class}, exprList( root, index, value ) ) ); } } } private static boolean needsAutoinsert( ArrayAccess arrayAccess ) { if (ArrayAccess.needsAutoinsert( arrayAccess ) ) { return true; } else if ( arrayAccess.getRootExpression() instanceof ArrayAccess ) { return ArrayAccess.needsAutoinsert((ArrayAccess) arrayAccess.getRootExpression()); } else { return false; } } public static void setArrayElement( Object obj, int iIndex, Object value ) { if( obj instanceof List ) { //noinspection unchecked ((List)obj).set( iIndex, value ); return; } IType classObj = TypeLoaderAccess.instance().getIntrinsicTypeFromObject( obj ); if( classObj.isArray() ) { value = CommonServices.getCoercionManager().convertValue( value, classObj.getComponentType() ); classObj.setArrayComponent( obj, iIndex, value ); return; } if( obj instanceof StringBuffer ) { ((StringBuffer)obj).setCharAt( iIndex, ((Character)CommonServices.getCoercionManager().convertValue( value, JavaTypes.CHARACTER() )).charValue() ); } throw new EvaluationException( "The type, " + classObj.getName() + ", is not coercible to an indexed-writable array." ); } public static void setOrAddElement( Object obj, int iIndex, Object value ) { List l = (List)obj; if( l.size() == iIndex ) { l.add( value ); } else { l.set( iIndex, value ); } } }