/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.ir.compiler.bytecode.expression; import gw.internal.gosu.ir.compiler.bytecode.AbstractBytecodeCompiler; import gw.internal.gosu.ir.compiler.bytecode.IRBytecodeContext; import gw.internal.gosu.ir.compiler.bytecode.IRBytecodeCompiler; import gw.lang.ir.expression.IRTernaryExpression; import gw.lang.ir.expression.IREqualityExpression; import gw.lang.ir.expression.IRNullLiteral; import gw.lang.ir.IRExpression; import gw.internal.ext.org.objectweb.asm.MethodVisitor; import gw.internal.ext.org.objectweb.asm.Label; import gw.internal.ext.org.objectweb.asm.Opcodes; public class IRTernaryExpressionCompiler extends AbstractBytecodeCompiler { public static void compile( IRTernaryExpression expression, IRBytecodeContext context ) { // TODO - Gosu Perf - We could make this more efficient by inspecting the conditional expression for common // patterns like equality expressions or other comparisons MethodVisitor mv = context.getMv(); Label trueLabel = new Label(); if ( isComparisonToNull( expression.getTest() ) ) { IRBytecodeCompiler.compileIRExpression( getNonNullEqualityOperand( expression.getTest() ), context ); mv.visitJumpInsn( getNullOpCode( expression.getTest() ), trueLabel ); // i.e. jump to trueLabel if the expression is equal to null } else { IRBytecodeCompiler.compileIRExpression( expression.getTest(), context ); mv.visitJumpInsn( Opcodes.IFNE, trueLabel ); // i.e. jump to trueLabel if the expression returned true and thus left a non-zero value on the stack } IRBytecodeCompiler.compileIRExpression( expression.getFalseValue(), context ); Label falseLabel = new Label(); mv.visitJumpInsn( Opcodes.GOTO, falseLabel ); mv.visitLabel( trueLabel ); IRBytecodeCompiler.compileIRExpression( expression.getTrueValue(), context ); mv.visitLabel( falseLabel ); } private static int getNullOpCode( IRExpression test ) { IREqualityExpression equalityExpression = (IREqualityExpression) test; if( equalityExpression.isEquals() ) { return Opcodes.IFNULL; } else { return Opcodes.IFNONNULL; } } private static boolean isComparisonToNull(IRExpression testExpression) { if (testExpression instanceof IREqualityExpression) { IREqualityExpression equalityExpression = (IREqualityExpression) testExpression; if (equalityExpression.getLhs() instanceof IRNullLiteral || equalityExpression.getRhs() instanceof IRNullLiteral) { return true; } } return false; } private static IRExpression getNonNullEqualityOperand( IRExpression testExpression ) { IREqualityExpression equalityExpression = (IREqualityExpression) testExpression; if (equalityExpression.getLhs() instanceof IRNullLiteral) { return equalityExpression.getRhs(); } else { return equalityExpression.getLhs(); } } }