List of usage examples for org.objectweb.asm.commons GeneratorAdapter arrayLoad
public void arrayLoad(final Type type)
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding array value. The logic is similar to the one in * {@link #encodeCollection}, with collection size replaced with array length. * * @param mg//from w ww . j a v a 2 s. c om * @param componentType * @param componentSchema * @param value * @param encoder * @param schemaLocal * @param seenRefs */ private void encodeArray(GeneratorAdapter mg, TypeToken<?> componentType, Schema componentSchema, int value, int encoder, int schemaLocal, int seenRefs) { // Encode and store the array length locally mg.loadArg(value); mg.arrayLength(); int length = mg.newLocal(Type.INT_TYPE); mg.storeLocal(length); mg.loadArg(encoder); mg.loadLocal(length); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); // Store the component schema mg.loadArg(schemaLocal); mg.invokeVirtual(Type.getType(Schema.class), getMethod(Schema.class, "getComponentSchema")); int componentSchemaLocal = mg.newLocal(Type.getType(Schema.class)); mg.storeLocal(componentSchemaLocal); // for (int idx = 0; idx < array.length; idx++) mg.push(0); int idx = mg.newLocal(Type.INT_TYPE); mg.storeLocal(idx); Label beginFor = mg.mark(); Label endFor = mg.newLabel(); mg.loadLocal(idx); mg.loadLocal(length); mg.ifICmp(GeneratorAdapter.GE, endFor); // Call encode method to encode array[idx] mg.loadThis(); mg.loadArg(value); mg.loadLocal(idx); TypeToken<?> callTypeToken = getCallTypeToken(componentType, componentSchema); mg.arrayLoad(Type.getType(callTypeToken.getRawType())); mg.loadArg(encoder); mg.loadLocal(componentSchemaLocal); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(componentType, componentSchema)); mg.iinc(idx, 1); mg.goTo(beginFor); mg.mark(endFor); // if length > 0, write out 0 at the end of array. Label zeroLength = mg.newLabel(); mg.loadLocal(length); mg.ifZCmp(GeneratorAdapter.LE, zeroLength); encodeInt(mg, 0, encoder); mg.mark(zeroLength); }
From source file:com.alibaba.hotswap.processor.constructor.ConstructorVisitor.java
License:Open Source License
private void storeArgs(GeneratorAdapter adapter, MethodVisitor hotswapInit, MethodMeta methodMeta) { Type[] argTypes = Type.getArgumentTypes(methodMeta.desc); if (argTypes.length == 0) { return;//from w w w. j av a 2 s.com } adapter.loadArg(2);// Object[] int nextIndex = 4; for (int i = 0; i < argTypes.length; i++) { adapter.dup(); adapter.push(i); adapter.arrayLoad(Type.getType(Object.class));// Object[i] adapter.unbox(argTypes[i]); hotswapInit.visitVarInsn(argTypes[i].getOpcode(Opcodes.ISTORE), nextIndex); nextIndex += argTypes[i].getSize(); } adapter.pop(); }
From source file:com.android.build.gradle.internal.incremental.ByteCodeUtils.java
License:Apache License
/** * Given an array with values at the top of the stack, the values are unboxed and stored * on the given variables. The array is popped from the stack. *//*ww w. j a va 2s . com*/ static void restoreVariables(@NonNull GeneratorAdapter mv, @NonNull List<LocalVariable> variables) { for (int i = 0; i < variables.size(); i++) { LocalVariable variable = variables.get(i); // Duplicates the array on the stack; mv.dup(); // Sets up the index mv.push(i); // Gets the Object value mv.arrayLoad(Type.getType(Object.class)); // Unboxes to the type of the local variable mv.unbox(variable.type); // Restores the local variable mv.visitVarInsn(variable.type.getOpcode(Opcodes.ISTORE), variable.var); } // Pops the array from the stack. mv.pop(); }
From source file:com.android.build.gradle.internal.incremental.ConstructorArgsRedirection.java
License:Apache License
@Override protected void restore(GeneratorAdapter mv, List<Type> args) { // At this point, init$args has been called and the result Object is on the stack. // The value of that Object is Object[] with exactly n + 1 elements. // The first element is a string with the qualified name of the constructor to call. // The remaining elements are the constructtor arguments. // Create a new local that holds the result of init$args call. mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;"); int constructorArgs = mv.newLocal(Type.getType("[Ljava/lang/Object;")); mv.storeLocal(constructorArgs);// w ww.j a v a 2 s . c o m // Reinstate local values mv.loadLocal(locals); int stackIndex = 0; for (int arrayIndex = 0; arrayIndex < args.size(); arrayIndex++) { Type arg = args.get(arrayIndex); // Do not restore "this" if (arrayIndex > 0) { // duplicates the array mv.dup(); // index in the array of objects to restore the boxed parameter. mv.push(arrayIndex); // get it from the array mv.arrayLoad(Type.getType(Object.class)); // unbox the argument ByteCodeUtils.unbox(mv, arg); // restore the argument mv.visitVarInsn(arg.getOpcode(Opcodes.ISTORE), stackIndex); } // stack index must progress according to the parameter type we just processed. stackIndex += arg.getSize(); } // pops the array mv.pop(); // Push a null for the marker parameter. mv.loadLocal(constructorArgs); mv.visitInsn(Opcodes.ACONST_NULL); // Invoke the constructor mv.visitMethodInsn(Opcodes.INVOKESPECIAL, thisClassName, "<init>", DISPATCHING_THIS_SIGNATURE, false); mv.goTo(end.getLabel()); }
From source file:com.android.build.gradle.internal.incremental.ConstructorRedirection.java
License:Apache License
@Override protected void doRedirect(GeneratorAdapter mv, int change) { mv.loadLocal(change);/*from ww w .j ava 2 s . c o m*/ mv.push("init$args." + constructor.args.desc); Type arrayType = Type.getType("[Ljava/lang/Object;"); // init$args args (including this) + locals mv.push(types.size() + 1); mv.newArray(Type.getType(Object.class)); int array = mv.newLocal(arrayType); mv.dup(); mv.storeLocal(array); // "this" is not ready yet, use null instead. mv.dup(); mv.push(0); mv.visitInsn(Opcodes.ACONST_NULL); mv.arrayStore(Type.getType(Object.class)); // Set the arguments in positions 1..(n-1); ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value // Add the locals array at the last position. mv.dup(); // The index of the last position of the array. mv.push(types.size()); // Create the array with all the local variables declared up to this point. ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis)); mv.arrayStore(Type.getType(Object.class)); mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE, Method.getMethod("Object access$dispatch(String, Object[])")); mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;"); //// At this point, init$args has been called and the result Object is on the stack. //// The value of that Object is Object[] with exactly n + 2 elements. //// The first element is the resulting local variables //// The second element is a string with the qualified name of the constructor to call. //// The remaining elements are the constructor arguments. // Keep a reference to the new locals array mv.dup(); mv.push(0); mv.arrayLoad(Type.getType("[Ljava/lang/Object;")); mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;"); mv.storeLocal(array); // Call super constructor // Put this behind the returned array mv.visitVarInsn(Opcodes.ALOAD, 0); mv.swap(); // Push a null for the marker parameter. mv.visitInsn(Opcodes.ACONST_NULL); // Invoke the constructor mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, "<init>", DISPATCHING_THIS_SIGNATURE, false); // Dispatch to init$body mv.loadLocal(change); mv.push("init$body." + constructor.body.desc); mv.loadLocal(array); // Now "this" can be set mv.dup(); mv.push(0); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.arrayStore(Type.getType(Object.class)); mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE, Method.getMethod("Object access$dispatch(String, Object[])")); mv.pop(); }
From source file:com.android.build.gradle.internal2.incremental.ConstructorRedirection.java
License:Apache License
@Override protected void doRedirect(GeneratorAdapter mv, int change) { mv.loadLocal(change);//from w w w . ja v a2 s . co m mv.push("init$args." + constructor.args.desc); Type arrayType = Type.getType("[Ljava/lang/Object;"); // init$args args (including this) + locals mv.push(types.size() + 1); mv.newArray(Type.getType(Object.class)); int array = mv.newLocal(arrayType); mv.dup(); mv.storeLocal(array); // "this" is not ready yet, use null instead. mv.dup(); mv.push(0); mv.visitInsn(Opcodes.ACONST_NULL); mv.arrayStore(Type.getType(Object.class)); // Set the arguments in positions 1..(n-1); ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value // Add the locals array at the last position. mv.dup(); // The index of the last position of the array. mv.push(types.size()); // Create the array with all the local variables declared up to this point. ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis)); mv.arrayStore(Type.getType(Object.class)); mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE, Method.getMethod("Object access$dispatch(String, Object[])")); mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;"); //// At this point, init$args has been called and the result Object is on the stack. //// The value of that Object is Object[] with exactly n + 2 elements. //// The first element is the resulting local variables //// The second element is a string with the qualified name of the constructor to call. //// The remaining elements are the constructor arguments. // Keep a reference to the new locals array mv.dup(); mv.push(0); mv.arrayLoad(Type.getType("[Ljava/lang/Object;")); mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;"); mv.storeLocal(array); // Call super constructor // Put this behind the returned array mv.visitVarInsn(Opcodes.ALOAD, 0); mv.swap(); // Push a null for the marker parameter. mv.visitInsn(Opcodes.ACONST_NULL); // Invoke the constructor mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, ByteCodeUtils.CONSTRUCTOR, DISPATCHING_THIS_SIGNATURE, false); // { // // FIXME: Opcodes.INVOKESPECIAL??????this?,????? // mv.visitVarInsn(Opcodes.ALOAD, 0); // // List<LocalVariable> variables = ByteCodeUtils.toLocalVariables(types); // for (int i = 1; i < variables.size(); i++) { // LocalVariable variable = variables.get(i); // // Duplicates the array on the stack; // mv.loadLocal(array); // // Sets up the index // mv.push(i + 1); // // Gets the Object value // mv.arrayLoad(Type.getType(Object.class)); // mv.unbox(variable.type); // } // mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, ByteCodeUtils.CONSTRUCTOR, constructor.originConstructor.desc, false); // } // Dispatch to init$body mv.loadLocal(change); mv.push("init$body." + constructor.body.desc); mv.loadLocal(array); // Now "this" can be set mv.dup(); mv.push(0); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.arrayStore(Type.getType(Object.class)); mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE, Method.getMethod("Object access$dispatch(String, Object[])")); mv.pop(); }
From source file:com.changingbits.Builder.java
License:Apache License
private void buildCounterAsm(GeneratorAdapter gen, Node node, boolean sawOutputs) { sawOutputs |= node.outputs != null;//from ww w .ja v a 2 s. c om if (node.left != null) { assert node.left.end + 1 == node.right.start; // Recurse on either left or right Label labelLeft = new Label(); Label labelEnd = new Label(); gen.loadArg(0); gen.push(node.left.end); gen.ifCmp(Type.LONG_TYPE, GeneratorAdapter.LE, labelLeft); buildCounterAsm(gen, node.right, sawOutputs); gen.goTo(labelEnd); gen.visitLabel(labelLeft); buildCounterAsm(gen, node.left, sawOutputs); gen.visitLabel(labelEnd); } else if (sawOutputs) { // leaf: elementaryCounts[node.leafIndex]++ gen.loadThis(); gen.getField(BASE_LONG_RANGE_COUNTER_TYPE, "elementaryCounts", INT_ARRAY_TYPE); gen.push(node.leafIndex); gen.dup2(); gen.arrayLoad(Type.INT_TYPE); gen.push(1); gen.visitInsn(Opcodes.IADD); gen.arrayStore(Type.INT_TYPE); } }
From source file:com.google.code.nanorm.internal.introspect.asm.MapperBuilder.java
License:Apache License
/** * Generate mapper method.//w ww . j a va 2 s . co m * * @param owner self type * @param cw class writer * @param config method configuration */ private static void visitMethod(Type owner, ClassWriter cw, MethodConfig config) { java.lang.reflect.Method ifaceMethod = config.getMethod(); Type returnType = Type.getType(ifaceMethod.getReturnType()); Type[] args = new Type[ifaceMethod.getParameterTypes().length]; for (int i = 0; i < args.length; ++i) { args[i] = Type.getType(ifaceMethod.getParameterTypes()[i]); } Method method = new Method(ifaceMethod.getName(), returnType, args); GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, null, null, cw); // Factory mg.loadThis(); mg.getField(owner, "delegate", QUERY_DELEGATE_TYPE); // Statement config mg.loadThis(); mg.getField(owner, "configs", STATEMENT_CONFIGS_ARR_TYPE); mg.push(config.getIndex()); mg.arrayLoad(Type.getType(StatementConfig.class)); // Arguments mg.loadArgArray(); mg.invokeInterface(QUERY_DELEGATE_TYPE, QUERY_METHOD); mg.unbox(returnType); mg.returnValue(); mg.endMethod(); // Copy the annotations copyAnnotations(ifaceMethod, null, mg); }
From source file:io.datakernel.codegen.ExpressionArrayGet.java
License:Apache License
@Override public Type load(Context ctx) { Type type = Type.getType(array.type(ctx).getDescriptor().substring(1)); GeneratorAdapter g = ctx.getGeneratorAdapter(); array.load(ctx);//from www. j a va 2s. co m nom.load(ctx); g.arrayLoad(type); return type; }
From source file:org.apache.lucene.expressions.js.JavascriptCompiler.java
License:Apache License
/** * Sends the bytecode of class file to {@link ClassWriter}. *//* w w w .j a va2 s .c om*/ private void generateClass(final ParseTree parseTree, final ClassWriter classWriter, final Map<String, Integer> externalsMap) throws ParseException { classWriter.visit(CLASSFILE_VERSION, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL, COMPILED_EXPRESSION_INTERNAL, null, EXPRESSION_TYPE.getInternalName(), null); final String clippedSourceText = (sourceText.length() <= MAX_SOURCE_LENGTH) ? sourceText : (sourceText.substring(0, MAX_SOURCE_LENGTH - 3) + "..."); classWriter.visitSource(clippedSourceText, null); final GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC, EXPRESSION_CTOR, null, null, classWriter); constructor.loadThis(); constructor.loadArgs(); constructor.invokeConstructor(EXPRESSION_TYPE, EXPRESSION_CTOR); constructor.returnValue(); constructor.endMethod(); final GeneratorAdapter gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC, EVALUATE_METHOD, null, null, classWriter); // to completely hide the ANTLR visitor we use an anonymous impl: new JavascriptBaseVisitor<Void>() { private final Deque<Type> typeStack = new ArrayDeque<>(); @Override public Void visitCompile(JavascriptParser.CompileContext ctx) { typeStack.push(Type.DOUBLE_TYPE); visit(ctx.expression()); typeStack.pop(); return null; } @Override public Void visitPrecedence(JavascriptParser.PrecedenceContext ctx) { visit(ctx.expression()); return null; } @Override public Void visitNumeric(JavascriptParser.NumericContext ctx) { if (ctx.HEX() != null) { pushLong(Long.parseLong(ctx.HEX().getText().substring(2), 16)); } else if (ctx.OCTAL() != null) { pushLong(Long.parseLong(ctx.OCTAL().getText().substring(1), 8)); } else if (ctx.DECIMAL() != null) { gen.push(Double.parseDouble(ctx.DECIMAL().getText())); gen.cast(Type.DOUBLE_TYPE, typeStack.peek()); } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } return null; } @Override public Void visitExternal(JavascriptParser.ExternalContext ctx) { String text = ctx.VARIABLE().getText(); int arguments = ctx.expression().size(); boolean parens = ctx.LP() != null && ctx.RP() != null; Method method = parens ? functions.get(text) : null; try { if (method != null) { int arity = method.getParameterTypes().length; if (arguments != arity) { throw new ParseException("Invalid expression '" + sourceText + "': Expected (" + arity + ") arguments for function call (" + text + "), but found (" + arguments + ").", ctx.start.getStartIndex()); } typeStack.push(Type.DOUBLE_TYPE); for (int argument = 0; argument < arguments; ++argument) { visit(ctx.expression(argument)); } typeStack.pop(); gen.invokeStatic(Type.getType(method.getDeclaringClass()), org.objectweb.asm.commons.Method.getMethod(method)); gen.cast(Type.DOUBLE_TYPE, typeStack.peek()); } else if (!parens || arguments == 0 && text.contains(".")) { int index; text = normalizeQuotes(ctx.getText()); if (externalsMap.containsKey(text)) { index = externalsMap.get(text); } else { index = externalsMap.size(); externalsMap.put(text, index); } gen.loadArg(0); gen.push(index); gen.arrayLoad(FUNCTION_VALUES_TYPE); gen.invokeVirtual(FUNCTION_VALUES_TYPE, DOUBLE_VAL_METHOD); gen.cast(Type.DOUBLE_TYPE, typeStack.peek()); } else { throw new ParseException("Invalid expression '" + sourceText + "': Unrecognized function call (" + text + ").", ctx.start.getStartIndex()); } return null; } catch (ParseException e) { // The API doesn't allow checked exceptions here, so propagate up the stack. This is unwrapped // in getAntlrParseTree. throw new RuntimeException(e); } } @Override public Void visitUnary(JavascriptParser.UnaryContext ctx) { if (ctx.BOOLNOT() != null) { Label labelNotTrue = new Label(); Label labelNotReturn = new Label(); typeStack.push(Type.INT_TYPE); visit(ctx.expression()); typeStack.pop(); gen.visitJumpInsn(Opcodes.IFEQ, labelNotTrue); pushBoolean(false); gen.goTo(labelNotReturn); gen.visitLabel(labelNotTrue); pushBoolean(true); gen.visitLabel(labelNotReturn); } else if (ctx.BWNOT() != null) { typeStack.push(Type.LONG_TYPE); visit(ctx.expression()); typeStack.pop(); gen.push(-1L); gen.visitInsn(Opcodes.LXOR); gen.cast(Type.LONG_TYPE, typeStack.peek()); } else if (ctx.ADD() != null) { visit(ctx.expression()); } else if (ctx.SUB() != null) { typeStack.push(Type.DOUBLE_TYPE); visit(ctx.expression()); typeStack.pop(); gen.visitInsn(Opcodes.DNEG); gen.cast(Type.DOUBLE_TYPE, typeStack.peek()); } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } return null; } @Override public Void visitMuldiv(JavascriptParser.MuldivContext ctx) { int opcode; if (ctx.MUL() != null) { opcode = Opcodes.DMUL; } else if (ctx.DIV() != null) { opcode = Opcodes.DDIV; } else if (ctx.REM() != null) { opcode = Opcodes.DREM; } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } pushArith(opcode, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitAddsub(JavascriptParser.AddsubContext ctx) { int opcode; if (ctx.ADD() != null) { opcode = Opcodes.DADD; } else if (ctx.SUB() != null) { opcode = Opcodes.DSUB; } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } pushArith(opcode, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBwshift(JavascriptParser.BwshiftContext ctx) { int opcode; if (ctx.LSH() != null) { opcode = Opcodes.LSHL; } else if (ctx.RSH() != null) { opcode = Opcodes.LSHR; } else if (ctx.USH() != null) { opcode = Opcodes.LUSHR; } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } pushShift(opcode, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBoolcomp(JavascriptParser.BoolcompContext ctx) { int opcode; if (ctx.LT() != null) { opcode = GeneratorAdapter.LT; } else if (ctx.LTE() != null) { opcode = GeneratorAdapter.LE; } else if (ctx.GT() != null) { opcode = GeneratorAdapter.GT; } else if (ctx.GTE() != null) { opcode = GeneratorAdapter.GE; } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } pushCond(opcode, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBooleqne(JavascriptParser.BooleqneContext ctx) { int opcode; if (ctx.EQ() != null) { opcode = GeneratorAdapter.EQ; } else if (ctx.NE() != null) { opcode = GeneratorAdapter.NE; } else { throw new IllegalStateException("Unknown operation specified: " + ctx.getText()); } pushCond(opcode, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBwand(JavascriptParser.BwandContext ctx) { pushBitwise(Opcodes.LAND, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBwxor(JavascriptParser.BwxorContext ctx) { pushBitwise(Opcodes.LXOR, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBwor(JavascriptParser.BworContext ctx) { pushBitwise(Opcodes.LOR, ctx.expression(0), ctx.expression(1)); return null; } @Override public Void visitBooland(JavascriptParser.BoolandContext ctx) { Label andFalse = new Label(); Label andEnd = new Label(); typeStack.push(Type.INT_TYPE); visit(ctx.expression(0)); gen.visitJumpInsn(Opcodes.IFEQ, andFalse); visit(ctx.expression(1)); gen.visitJumpInsn(Opcodes.IFEQ, andFalse); typeStack.pop(); pushBoolean(true); gen.goTo(andEnd); gen.visitLabel(andFalse); pushBoolean(false); gen.visitLabel(andEnd); return null; } @Override public Void visitBoolor(JavascriptParser.BoolorContext ctx) { Label orTrue = new Label(); Label orEnd = new Label(); typeStack.push(Type.INT_TYPE); visit(ctx.expression(0)); gen.visitJumpInsn(Opcodes.IFNE, orTrue); visit(ctx.expression(1)); gen.visitJumpInsn(Opcodes.IFNE, orTrue); typeStack.pop(); pushBoolean(false); gen.goTo(orEnd); gen.visitLabel(orTrue); pushBoolean(true); gen.visitLabel(orEnd); return null; } @Override public Void visitConditional(JavascriptParser.ConditionalContext ctx) { Label condFalse = new Label(); Label condEnd = new Label(); typeStack.push(Type.INT_TYPE); visit(ctx.expression(0)); typeStack.pop(); gen.visitJumpInsn(Opcodes.IFEQ, condFalse); visit(ctx.expression(1)); gen.goTo(condEnd); gen.visitLabel(condFalse); visit(ctx.expression(2)); gen.visitLabel(condEnd); return null; } private void pushArith(int operator, ExpressionContext left, ExpressionContext right) { pushBinaryOp(operator, left, right, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE); } private void pushShift(int operator, ExpressionContext left, ExpressionContext right) { pushBinaryOp(operator, left, right, Type.LONG_TYPE, Type.INT_TYPE, Type.LONG_TYPE); } private void pushBitwise(int operator, ExpressionContext left, ExpressionContext right) { pushBinaryOp(operator, left, right, Type.LONG_TYPE, Type.LONG_TYPE, Type.LONG_TYPE); } private void pushBinaryOp(int operator, ExpressionContext left, ExpressionContext right, Type leftType, Type rightType, Type returnType) { typeStack.push(leftType); visit(left); typeStack.pop(); typeStack.push(rightType); visit(right); typeStack.pop(); gen.visitInsn(operator); gen.cast(returnType, typeStack.peek()); } private void pushCond(int operator, ExpressionContext left, ExpressionContext right) { Label labelTrue = new Label(); Label labelReturn = new Label(); typeStack.push(Type.DOUBLE_TYPE); visit(left); visit(right); typeStack.pop(); gen.ifCmp(Type.DOUBLE_TYPE, operator, labelTrue); pushBoolean(false); gen.goTo(labelReturn); gen.visitLabel(labelTrue); pushBoolean(true); gen.visitLabel(labelReturn); } private void pushBoolean(boolean truth) { switch (typeStack.peek().getSort()) { case Type.INT: gen.push(truth); break; case Type.LONG: gen.push(truth ? 1L : 0L); break; case Type.DOUBLE: gen.push(truth ? 1. : 0.); break; default: throw new IllegalStateException("Invalid expected type: " + typeStack.peek()); } } private void pushLong(long i) { switch (typeStack.peek().getSort()) { case Type.INT: gen.push((int) i); break; case Type.LONG: gen.push(i); break; case Type.DOUBLE: gen.push((double) i); break; default: throw new IllegalStateException("Invalid expected type: " + typeStack.peek()); } } }.visit(parseTree); gen.returnValue(); gen.endMethod(); classWriter.visitEnd(); }