public Object visit(ArithmeticExpression node) {
            Expression left = node.getLeftExpression();
            Expression right = node.getRightExpression();

            Type ltype = left.getType();
            Type rtype = right.getType();
            if (ltype == null || rtype == null) {
                throw new RuntimeException(
                    "ArithmeticExpression types invalid: " +
                    ltype + ", " + rtype
                );
            }

            setLineNumber(node.getOperator().getSourceInfo());

            int ID = node.getOperator().getID();

            // handle simple scenario of primitive to primitive calculation
            if (ltype.isPrimitive() && rtype.isPrimitive()) {
                if (!ltype.equals(rtype)) {
                    throw new RuntimeException(
                        "ArithmeticExpression types must match as primitives: " +
                        ltype + ", " + rtype
                    );
                }

                byte opcode = Opcode.NOP;
                Class<?> clazz = ltype.getNaturalClass();
                if (clazz == int.class) {
                    switch (ID) {
                    case Token.PLUS:
                        opcode = Opcode.IADD;
                        break;
                    case Token.MINUS:
                        opcode = Opcode.ISUB;
                        break;
                    case Token.MULT:
                        opcode = Opcode.IMUL;
                        break;
                    case Token.DIV:
                        opcode = Opcode.IDIV;
                        break;
                    case Token.MOD:
                        opcode = Opcode.IREM;
                        break;
                    }
                }
                else if (clazz == float.class) {
                    switch (ID) {
                    case Token.PLUS:
                        opcode = Opcode.FADD;
                        break;
                    case Token.MINUS:
                        opcode = Opcode.FSUB;
                        break;
                    case Token.MULT:
                        opcode = Opcode.FMUL;
                        break;
                    case Token.DIV:
                        opcode = Opcode.FDIV;
                        break;
                    case Token.MOD:
                        opcode = Opcode.FREM;
                        break;
                    }
                }
                else if (clazz == long.class) {
                    switch (ID) {
                    case Token.PLUS:
                        opcode = Opcode.LADD;
                        break;
                    case Token.MINUS:
                        opcode = Opcode.LSUB;
                        break;
                    case Token.MULT:
                        opcode = Opcode.LMUL;
                        break;
                    case Token.DIV:
                        opcode = Opcode.LDIV;
                        break;
                    case Token.MOD:
                        opcode = Opcode.LREM;
                        break;
                    }
                }
                else if (clazz == double.class) {
                    switch (ID) {
                    case Token.PLUS:
                        opcode = Opcode.DADD;
                        break;
                    case Token.MINUS:
                        opcode = Opcode.DSUB;
                        break;
                    case Token.MULT:
                        opcode = Opcode.DMUL;
                        break;
                    case Token.DIV:
                        opcode = Opcode.DDIV;
                        break;
                    case Token.MOD:
                        opcode = Opcode.DREM;
                        break;
                    }
                }

                generate(node.getLeftExpression());
                generate(node.getRightExpression());

                mBuilder.math(opcode);
            }

            // otherwise, we must be using some unknown numerical value, so
            // attempt a runtime calculation (Number, etc)
            else {
                int opcode = 0;
                switch (ID) {
                case Token.PLUS:
                    opcode = WrapperTypeConversionUtil.OP_ADD;
                    break;
                case Token.MINUS:
                    opcode = WrapperTypeConversionUtil.OP_SUB;
                    break;
                case Token.MULT:
                    opcode = WrapperTypeConversionUtil.OP_MULT;
                    break;
                case Token.DIV:
                    opcode = WrapperTypeConversionUtil.OP_DIV;
                    break;
                case Token.MOD:
                    opcode = WrapperTypeConversionUtil.OP_MOD;
                    break;
                }

                Class<?> lclass = Number.class, rclass = Number.class;
                if (ltype.isPrimitive()) {
                    lclass = ltype.getNaturalClass();
                }
                else if (rtype.isPrimitive()) {
                    rclass = rtype.getNaturalClass();
                }

                Method method = getMethod(
                    WrapperTypeConversionUtil.class, "math", int.class,
                    lclass, rclass
                );

                mBuilder.loadConstant(opcode);
                generate(node.getLeftExpression());
                generate(node.getRightExpression());

                mBuilder.invoke(method);
            }

            return null;
        }