| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- #include "Code.h"
- #include <stdio.h>
- #include <string.h>
- #include "Code.h"
- #include "Constants.h"
- #include "Memory.h"
- void codeInit(Code* c) {
- *c = (Code){};
- bufferInit(&c->code);
- }
- void codeDestroy(Code* c) {
- bufferDestroy(&c->code);
- memoryFree(c->stack);
- *c = (Code){};
- }
- void codeReset(Code* c) {
- bufferReset(&c->code);
- }
- #define POP_VALUE(name) \
- Value name; \
- if(iPopValue(c, &name)) \
- return true
- #define INT_VALUE(value) ((Value){.type = VT_INT32, .data = (value)})
- #define CSTRING_VALUE(value) \
- ((Value){.type = VT_CONSTANT_STRING, .data = (value)})
- #define SET_ERROR(format, ...) \
- snprintf( \
- c->error.text, sizeof(c->error.text), \
- format __VA_OPT__(, ) __VA_ARGS__)
- [[nodiscard]] static bool codeReadI32(Code* c, i32* i) {
- return bufferReadI32(&c->code, i);
- }
- [[nodiscard]] static const char* codeReadConstantString(Code* c) {
- return bufferReadString(&c->code);
- }
- static void codeSetPosition(Code* c, size_t pos) {
- c->code.readIndex = pos;
- }
- static i32 codeGetPosition(Code* c) {
- return (i32)c->code.readIndex;
- }
- static bool iPushValue(Code* c, Value v) {
- while(c->stackIndex >= c->maxStackSize) {
- size_t newSize = c->maxStackSize <= 0 ? 16 : (c->maxStackSize * 5) / 4;
- if(newSize >= MAX_STACK_VALUES) {
- SET_ERROR("Stack overflow");
- return true;
- }
- Value* newValues = memoryAllocate(sizeof(Value) * newSize);
- if(newValues == nullptr) {
- SET_ERROR("Out of memory for stack");
- return true;
- }
- memcpy(newValues, c->stack, sizeof(Value) * c->stackIndex);
- memoryFree(c->stack);
- c->stack = newValues;
- c->maxStackSize = newSize;
- }
- c->stack[c->stackIndex++] = v;
- return false;
- }
- static bool iPopValue(Code* c, Value* v) {
- if(c->stackIndex <= 0) {
- SET_ERROR("Pop on empty stack");
- return true;
- }
- *v = c->stack[--c->stackIndex];
- return false;
- }
- static bool iAdd(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(a.data + b.data));
- }
- static bool iPushConstantString(Code* c) {
- const char* s = codeReadConstantString(c);
- i32 address = (i32)((const u8*)s - c->code.data);
- return iPushValue(c, CSTRING_VALUE(address));
- }
- static bool iPushInt(Code* c) {
- i32 i = 0;
- if(codeReadI32(c, &i)) {
- SET_ERROR("PushInt without value");
- return true;
- }
- return iPushValue(c, INT_VALUE(i));
- }
- static bool iPrint(Code* c) {
- POP_VALUE(a);
- switch(a.type) {
- case VT_INT32: printf("%d", a.data); break;
- case VT_CONSTANT_STRING: printf("%s", c->code.data + a.data); break;
- }
- return false;
- }
- static bool iPrintNewline() {
- putchar('\n');
- return false;
- }
- static bool iJump(Code* c) {
- i32 jumpPos = 0;
- if(codeReadI32(c, &jumpPos)) {
- SET_ERROR("Jump without position");
- return true;
- }
- codeSetPosition(c, (size_t)jumpPos);
- return false;
- }
- static bool iJumpIf(Code* c) {
- POP_VALUE(a);
- i32 jumpPos = 0;
- if(codeReadI32(c, &jumpPos)) {
- SET_ERROR("JumpIf without position");
- return true;
- }
- if(a.data == 0) {
- codeSetPosition(c, (size_t)jumpPos);
- }
- return false;
- }
- static bool iJumpSub(Code* c) {
- i32 jumpPos = 0;
- if(codeReadI32(c, &jumpPos)) {
- SET_ERROR("JumpSub without position");
- return true;
- } else if(iPushValue(c, INT_VALUE(codeGetPosition(c)))) {
- return true;
- }
- codeSetPosition(c, (size_t)jumpPos);
- return false;
- }
- static bool iReturn(Code* c) {
- POP_VALUE(a);
- codeSetPosition(c, (size_t)a.data);
- return false;
- }
- static bool iReadVariable(Code* c) {
- i32 address = 0;
- if(codeReadI32(c, &address)) {
- SET_ERROR("ReadVariable without address");
- return true;
- } else if((size_t)address >= c->stackIndex) {
- SET_ERROR("ReadVariable with invalid address");
- return true;
- }
- return iPushValue(c, c->stack[address]);
- }
- static bool iSetVariable(Code* c) {
- i32 address = 0;
- if(codeReadI32(c, &address)) {
- SET_ERROR("SetVariable without address");
- return true;
- } else if((size_t)address >= c->stackIndex) {
- SET_ERROR("SetVariable with invalid address");
- return true;
- }
- POP_VALUE(a);
- c->stack[address] = a;
- return false;
- }
- static bool iPushStackVariables(Code* c) {
- i32 amount = 0;
- if(codeReadI32(c, &amount)) {
- SET_ERROR("PushStackVariables without amount");
- return true;
- }
- Value v = INT_VALUE(0);
- while(amount > 0) {
- if(iPushValue(c, v)) {
- return true;
- }
- amount--;
- }
- return false;
- }
- static bool execute(Code* c, Instruction command) {
- switch(command) {
- case ADD: return iAdd(c);
- case PUSH_CONSTANT_STRING: return iPushConstantString(c);
- case PUSH_INT64: return iPushInt(c);
- case PRINT: return iPrint(c);
- case PRINT_NEWLINE: return iPrintNewline();
- case JUMP: return iJump(c);
- case JUMP_ON_0: return iJumpIf(c);
- case JUMP_SUB: return iJumpSub(c);
- case RETURN: return iReturn(c);
- case READ_VARIABLE: return iReadVariable(c);
- case SET_VARIABLE: return iSetVariable(c);
- case PUSH_STACK_VARIABLES: return iPushStackVariables(c);
- case STOP: return true;
- }
- return false;
- }
- void codeRun(Code* c) {
- while(true) {
- Instruction i = STOP;
- if(bufferReadU8(&c->code, &i) || execute(c, i)) {
- return;
- }
- }
- }
- bool codeHasRunError(const Code* code) {
- return hasError(&code->error);
- }
- const char* codeGetRunError(const Code* code) {
- return code->error.text;
- }
|