code cleanup and division by zero error handling

This commit is contained in:
SpookyDervish
2025-12-20 19:42:00 +11:00
parent 3752c6abcc
commit 03ea7bd418
5 changed files with 49 additions and 60 deletions

View File

@@ -27,6 +27,10 @@ char* exceptionAsCString(VMBL_Exception exception)
case EXCEPTION_INVALID_INSTRUCTION_ACCESS: case EXCEPTION_INVALID_INSTRUCTION_ACCESS:
return "EXCEPTION_INVALID_INSTRUCTION_ACCESS"; return "EXCEPTION_INVALID_INSTRUCTION_ACCESS";
break; break;
case EXCEPTION_DIVIDE_BY_ZERO:
return "EXCEPTION_DIVIDE_BY_ZERO";
break;
default: default:
return "EXCEPTION_UNKOWN"; return "EXCEPTION_UNKOWN";

View File

@@ -7,7 +7,8 @@ typedef enum {
EXCEPTION_STACK_UNDERFLOW, EXCEPTION_STACK_UNDERFLOW,
EXCEPTION_INVALID_OPCODE, EXCEPTION_INVALID_OPCODE,
EXCEPTION_INVALID_OPPERAND, EXCEPTION_INVALID_OPPERAND,
EXCEPTION_INVALID_INSTRUCTION_ACCESS EXCEPTION_INVALID_INSTRUCTION_ACCESS,
EXCEPTION_DIVIDE_BY_ZERO
} VMBL_ExceptionType; } VMBL_ExceptionType;
typedef struct typedef struct

View File

@@ -6,14 +6,13 @@ VMBL_Instruction program[] = {
MAKE_INST_PUSH(123), MAKE_INST_PUSH(123),
MAKE_INST_PUSH(0), MAKE_INST_PUSH(0),
MAKE_INST_DIV, MAKE_INST_DIV,
}; };
int main() { int main() {
VMBL_State vmblState = {}; VMBL_State vmblState = {};
//VMBL_LoadExecutable(&vmblState, program, sizeof(program)); VMBL_LoadExecutable(&vmblState, program, sizeof(program));
//VMBL_SaveExecutable("fib.vmbl", program, sizeof(program));
VMBL_LoadExecutableFromFile(&vmblState, "fib.vmbl");
VMBL_StartVM(&vmblState); VMBL_StartVM(&vmblState);
return 0; return 0;

View File

@@ -3,6 +3,19 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.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) { VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction) {
switch (instruction.type) switch (instruction.type)
{ {
@@ -15,36 +28,20 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
break; break;
case INSTRUCTION_ADD: case INSTRUCTION_ADD:
if (vmblState->stackSize < 2) { MATH_OP(vmblState, +);
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
}
vmblState->stack[vmblState->stackSize - 2] += vmblState->stack[vmblState->stackSize - 1];
vmblState->stackSize--;
break; break;
case INSTRUCTION_SUB: case INSTRUCTION_SUB:
if (vmblState->stackSize < 2) { MATH_OP(vmblState, -);
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
}
vmblState->stack[vmblState->stackSize - 2] -= vmblState->stack[vmblState->stackSize - 1];
vmblState->stackSize--;
break; break;
case INSTRUCTION_MUL: case INSTRUCTION_MUL:
if (vmblState->stackSize < 2) { MATH_OP(vmblState, *);
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
}
vmblState->stack[vmblState->stackSize - 2] *= vmblState->stack[vmblState->stackSize - 1];
vmblState->stackSize--;
break; break;
case INSTRUCTION_DIV: case INSTRUCTION_DIV:
if (vmblState->stackSize < 2) { if (instruction.opperands[0] == 0) {
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; return (VMBL_Exception){ EXCEPTION_DIVIDE_BY_ZERO };
} }
vmblState->stack[vmblState->stackSize - 2] /= vmblState->stack[vmblState->stackSize - 1]; MATH_OP(vmblState, /);
vmblState->stackSize--;
break; break;
case INSTRUCTION_DUPLICATE: case INSTRUCTION_DUPLICATE:
@@ -75,22 +72,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
break; break;
case INSTRUCTION_EQUAL: case INSTRUCTION_EQUAL:
if (instruction.opperands[0] < 0 || instruction.opperands[1] < 0) { MATH_OP(vmblState, ==);
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];
break; break;
case INSTRUCTION_JUMP_CONDITIONAL: case INSTRUCTION_JUMP_CONDITIONAL:
@@ -103,7 +85,7 @@ VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction i
} }
break; break;
case INSTRUCTION_POP: case INSTRUCTION_DROP:
if (vmblState->stackSize <= 0) { if (vmblState->stackSize <= 0) {
return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW }; return (VMBL_Exception){ EXCEPTION_STACK_UNDERFLOW };
} }
@@ -145,12 +127,12 @@ void VMBL_StartVM(VMBL_State *vmblState) {
VMBL_Instruction instruction = vmblState->program[vmblState->ip++]; 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); VMBL_Exception exception = VBML_ExecuteInstruction(vmblState, instruction);
if (exception.type != EXCEPTION_NONE) { if (exception.type != EXCEPTION_NONE) {
//VMBL_Dump(*vmblState, exception); VMBL_Dump(*vmblState, exception);
return; return;
} }
@@ -220,6 +202,15 @@ char *instructionTypeToCStr(InstructionType type) {
case INSTRUCTION_ADD: case INSTRUCTION_ADD:
return "ADD "; return "ADD ";
break; break;
case INSTRUCTION_SUB:
return "SUB ";
break;
case INSTRUCTION_MUL:
return "MUL ";
break;
case INSTRUCTION_DIV:
return "DIV ";
break;
case INSTRUCTION_DUPLICATE: case INSTRUCTION_DUPLICATE:
return "DUP "; return "DUP ";
@@ -237,10 +228,6 @@ char *instructionTypeToCStr(InstructionType type) {
return "EQ "; return "EQ ";
break; break;
case INSTRUCTION_EQUAL_TOP:
return "EQT ";
break;
case INSTRUCTION_JUMP_CONDITIONAL: case INSTRUCTION_JUMP_CONDITIONAL:
return "JC "; return "JC ";
break; break;

View File

@@ -21,7 +21,7 @@ typedef enum
INSTRUCTION_MUL, INSTRUCTION_MUL,
INSTRUCTION_DIV, INSTRUCTION_DIV,
INSTRUCTION_DUPLICATE, INSTRUCTION_DUPLICATE,
INSTRUCTION_POP, INSTRUCTION_DROP,
// instruction pointer operations // instruction pointer operations
INSTRUCTION_HALT, INSTRUCTION_HALT,
@@ -30,17 +30,11 @@ typedef enum
// conditional operations // conditional operations
INSTRUCTION_NOT_EQUAL, INSTRUCTION_NOT_EQUAL,
INSTRUCTION_NOT_EQUAL_TOP,
INSTRUCTION_EQUAL, INSTRUCTION_EQUAL,
INSTRUCTION_EQUAL_TOP,
INSTRUCTION_LESS_THAN, INSTRUCTION_LESS_THAN,
INSTRUCTION_LESS_THAN_TOP,
INSTRUCTION_LESS_THAN_EQUAL, INSTRUCTION_LESS_THAN_EQUAL,
INSTRUCTION_LESS_THAN_EQUAL_TOP,
INSTRUCTION_GREATER_THAN, INSTRUCTION_GREATER_THAN,
INSTRUCTION_GREATER_THAN_TOP,
INSTRUCTION_GREATER_THAN_EQUAL, INSTRUCTION_GREATER_THAN_EQUAL,
INSTRUCTION_GREATER_THAN_EQUAL_TOP,
} InstructionType; } InstructionType;
typedef struct typedef struct
@@ -62,7 +56,7 @@ typedef struct
} VMBL_State; } VMBL_State;
#define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperands[0] = (value) } #define MAKE_INST_PUSH(value) (VMBL_Instruction) { .type = INSTRUCTION_PUSH, .opperands[0] = (value) }
#define MAKE_INST_POP (VMBL_Instruction) { .type = INSTRUCTION_POP } #define MAKE_INST_DROP (VMBL_Instruction) { .type = INSTRUCTION_POP }
#define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD } #define MAKE_INST_ADD (VMBL_Instruction) { .type = INSTRUCTION_ADD }
#define MAKE_INST_SUB (VMBL_Instruction) { .type = INSTRUCTION_SUB } #define MAKE_INST_SUB (VMBL_Instruction) { .type = INSTRUCTION_SUB }
#define MAKE_INST_MUL (VMBL_Instruction) { .type = INSTRUCTION_MUL } #define MAKE_INST_MUL (VMBL_Instruction) { .type = INSTRUCTION_MUL }
@@ -70,8 +64,12 @@ typedef struct
#define MAKE_INST_DUP(value) (VMBL_Instruction) { .type = INSTRUCTION_DUPLICATE, .opperands[0] = (value) } #define MAKE_INST_DUP(value) (VMBL_Instruction) { .type = INSTRUCTION_DUPLICATE, .opperands[0] = (value) }
#define MAKE_INST_JMP(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP, .opperands[0] = (value) } #define MAKE_INST_JMP(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP, .opperands[0] = (value) }
#define MAKE_INST_HALT (VMBL_Instruction) { .type = INSTRUCTION_HALT } #define MAKE_INST_HALT (VMBL_Instruction) { .type = INSTRUCTION_HALT }
#define MAKE_INST_EQUAL(stack1, stack2) (VMBL_Instruction) { .type = INSTRUCTION_EQUAL, .opperands[0] = (stack1), .opperands[1] = (stack2) } #define MAKE_INST_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_EQUAL }
#define MAKE_INST_EQUAL_TOP (VMBL_Instruction) { .type = INSTRUCTION_EQUAL_TOP } #define MAKE_INST_NOT_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_NOT_EQUAL }
#define MAKE_INST_LESS (VMBL_Instruction) { .type = INSTRUCTION_LESS_THAN }
#define MAKE_INST_LESS_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_LESS_THAN_EQUAL }
#define MAKE_INST_GREATER (VMBL_Instruction) { .type = INSTRUCTION_GREATER_THAN }
#define MAKE_INST_GREATER_EQUAL (VMBL_Instruction) { .type = INSTRUCTION_GREATER_THAN_EQUAL }
#define MAKE_INST_JUMP_CONDITIONAL(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP_CONDITIONAL, .opperands[0] = (value) } #define MAKE_INST_JUMP_CONDITIONAL(value) (VMBL_Instruction) { .type = INSTRUCTION_JUMP_CONDITIONAL, .opperands[0] = (value) }
VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction); VMBL_Exception VBML_ExecuteInstruction(VMBL_State *vmblState, VMBL_Instruction instruction);