code cleanup and division by zero error handling
This commit is contained in:
79
src/vmbl.c
79
src/vmbl.c
@@ -3,6 +3,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define MATH_OP(vmblState, operation) \
|
||||
do { \
|
||||
if ((vmblState)->stackSize < 2) { \
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; \
|
||||
} \
|
||||
(vmblState)->stack[(vmblState)->stackSize - 2] = (vmblState)->stack[(vmblState)->stackSize - 2] operation (vmblState)->stack[(vmblState)->stackSize - 1]; \
|
||||
(vmblState)->stackSize--; \
|
||||
(vmblState)->ip++; \
|
||||
} while (0);
|
||||
|
||||
|
||||
|
||||
VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction) {
|
||||
switch (instruction.type)
|
||||
{
|
||||
@@ -15,36 +28,20 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
|
||||
break;
|
||||
|
||||
case INSTRUCTION_ADD:
|
||||
if (vmblState->stackSize < 2) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||
}
|
||||
|
||||
vmblState->stack[vmblState->stackSize - 2] += vmblState->stack[vmblState->stackSize - 1];
|
||||
vmblState->stackSize--;
|
||||
MATH_OP(vmblState, +);
|
||||
break;
|
||||
case INSTRUCTION_SUB:
|
||||
if (vmblState->stackSize < 2) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||
}
|
||||
|
||||
vmblState->stack[vmblState->stackSize - 2] -= vmblState->stack[vmblState->stackSize - 1];
|
||||
vmblState->stackSize--;
|
||||
MATH_OP(vmblState, -);
|
||||
break;
|
||||
case INSTRUCTION_MUL:
|
||||
if (vmblState->stackSize < 2) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||
}
|
||||
|
||||
vmblState->stack[vmblState->stackSize - 2] *= vmblState->stack[vmblState->stackSize - 1];
|
||||
vmblState->stackSize--;
|
||||
MATH_OP(vmblState, *);
|
||||
break;
|
||||
case INSTRUCTION_DIV:
|
||||
if (vmblState->stackSize < 2) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||
}
|
||||
if (instruction.opperands[0] == 0) {
|
||||
return (VMBL_Exception){ EXCEPTION_DIVIDE_BY_ZERO };
|
||||
}
|
||||
|
||||
vmblState->stack[vmblState->stackSize - 2] /= vmblState->stack[vmblState->stackSize - 1];
|
||||
vmblState->stackSize--;
|
||||
MATH_OP(vmblState, /);
|
||||
break;
|
||||
|
||||
case INSTRUCTION_DUPLICATE:
|
||||
@@ -75,22 +72,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
|
||||
break;
|
||||
|
||||
case INSTRUCTION_EQUAL:
|
||||
if (instruction.opperands[0] < 0 || instruction.opperands[1] < 0) {
|
||||
return (VMBL_Exception) { EXCEPTION_INVALID_OPPERAND };
|
||||
}
|
||||
if (vmblState->stackSize >= VMBL_STACK_SIZE || instruction.opperands[0] > VMBL_STACK_SIZE || instruction.opperands[1] > VMBL_STACK_SIZE) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW };
|
||||
}
|
||||
|
||||
vmblState->stack[vmblState->stackSize] = vmblState->stack[vmblState->stackSize-instruction.opperands[0]] == vmblState->stack[vmblState->stackSize-instruction.opperands[1]];
|
||||
break;
|
||||
|
||||
case INSTRUCTION_EQUAL_TOP:
|
||||
if (vmblState->stackSize >= VMBL_STACK_SIZE) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_OVERFLOW };
|
||||
}
|
||||
|
||||
vmblState->stack[vmblState->stackSize++] = vmblState->stack[vmblState->stackSize-1] == vmblState->stack[vmblState->stackSize-2];
|
||||
MATH_OP(vmblState, ==);
|
||||
break;
|
||||
|
||||
case INSTRUCTION_JUMP_CONDITIONAL:
|
||||
@@ -103,7 +85,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
|
||||
}
|
||||
break;
|
||||
|
||||
case INSTRUCTION_POP:
|
||||
case INSTRUCTION_DROP:
|
||||
if (vmblState->stackSize <= 0) {
|
||||
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
|
||||
}
|
||||
@@ -145,12 +127,12 @@ void VMBL_StartVM(VMBL_State *vmblState) {
|
||||
|
||||
|
||||
VMBL_Instruction instruction = vmblState->program[vmblState->ip++];
|
||||
//printf("%s 0x%lx, 0x%lx, 0x%lx\n", instructionTypeToCStr(instruction.type), instruction.opperands[0], instruction.opperands[1], instruction.opperands[2]);
|
||||
printf("%s 0x%lx, 0x%lx, 0x%lx\n", instructionTypeToCStr(instruction.type), instruction.opperands[0], instruction.opperands[1], instruction.opperands[2]);
|
||||
|
||||
VMBL_Exception exception = VBML_ExecuteInstruction(vmblState, instruction);
|
||||
|
||||
if (exception.type != EXCEPTION_NONE) {
|
||||
//VMBL_Dump(*vmblState, exception);
|
||||
VMBL_Dump(*vmblState, exception);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,6 +202,15 @@ char *instructionTypeToCStr(InstructionType type) {
|
||||
case INSTRUCTION_ADD:
|
||||
return "ADD ";
|
||||
break;
|
||||
case INSTRUCTION_SUB:
|
||||
return "SUB ";
|
||||
break;
|
||||
case INSTRUCTION_MUL:
|
||||
return "MUL ";
|
||||
break;
|
||||
case INSTRUCTION_DIV:
|
||||
return "DIV ";
|
||||
break;
|
||||
|
||||
case INSTRUCTION_DUPLICATE:
|
||||
return "DUP ";
|
||||
@@ -237,10 +228,6 @@ char *instructionTypeToCStr(InstructionType type) {
|
||||
return "EQ ";
|
||||
break;
|
||||
|
||||
case INSTRUCTION_EQUAL_TOP:
|
||||
return "EQT ";
|
||||
break;
|
||||
|
||||
case INSTRUCTION_JUMP_CONDITIONAL:
|
||||
return "JC ";
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user