package me.tomassetti.turin.compiler; import me.tomassetti.bytecode_generation.MathOperationBS; import me.tomassetti.bytecode_generation.RelationalOperationBS; import me.tomassetti.jvm.JvmTypeCategory; import me.tomassetti.turin.parser.ast.expressions.MathOperation; import me.tomassetti.turin.parser.ast.expressions.RelationalOperation; import org.objectweb.asm.Opcodes; public final class BytecodeUtils { private BytecodeUtils() { // prevent instantiation } public static RelationalOperationBS createRelationOperation(RelationalOperation.Operator operator) { int jumpOpcode; switch (operator) { case EQUAL: jumpOpcode = Opcodes.IF_ICMPNE; break; case DIFFERENT: jumpOpcode = Opcodes.IF_ICMPEQ; break; case LESS: jumpOpcode = Opcodes.IF_ICMPGE; break; case LESSEQ: jumpOpcode = Opcodes.IF_ICMPGT; break; case MORE: jumpOpcode = Opcodes.IF_ICMPLE; break; case MOREEQ: jumpOpcode = Opcodes.IF_ICMPLT; break; default: throw new UnsupportedOperationException(operator.name()); } return new RelationalOperationBS(jumpOpcode); } public static MathOperationBS createMathOperation(JvmTypeCategory operandsType, MathOperation.Operator operator) { int opcode; switch (operator) { case MULTIPLICATION: switch (operandsType) { case INT: opcode = Opcodes.IMUL; break; case LONG: opcode = Opcodes.LMUL; break; case FLOAT: opcode = Opcodes.FMUL; break; case DOUBLE: opcode = Opcodes.DMUL; break; default: throw new UnsupportedOperationException(operator + " " +operandsType.name()); } break; case SUM: switch (operandsType) { case INT: opcode = Opcodes.IADD; break; case LONG: opcode = Opcodes.LADD; break; case FLOAT: opcode = Opcodes.FADD; break; case DOUBLE: opcode = Opcodes.DADD; break; default: throw new UnsupportedOperationException(operator + " " +operandsType.name()); } break; case SUBTRACTION: switch (operandsType) { case INT: opcode = Opcodes.ISUB; break; case LONG: opcode = Opcodes.LSUB; break; case FLOAT: opcode = Opcodes.FSUB; break; case DOUBLE: opcode = Opcodes.DSUB; break; default: throw new UnsupportedOperationException(operator + " " +operandsType.name()); } break; case DIVISION: switch (operandsType) { case INT: opcode = Opcodes.IDIV; break; case LONG: opcode = Opcodes.LDIV; break; case FLOAT: opcode = Opcodes.FDIV; break; case DOUBLE: opcode = Opcodes.DDIV; break; default: throw new UnsupportedOperationException(operator + " " +operandsType.name()); } break; default: throw new UnsupportedOperationException(operator.name()); } return new MathOperationBS(opcode); } }