code cleanup and division by zero error handling
This commit is contained in:
@@ -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";
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
79
src/vmbl.c
79
src/vmbl.c
@@ -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;
|
||||||
|
|||||||
18
src/vmbl.h
18
src/vmbl.h
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user