| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- #include "Code.h"
- #include <stdio.h>
- #include <string.h>
- #include "Code.h"
- #include "Constants.h"
- #include "Memory.h"
- #include "SystemFunctions.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 CSTRING_VALUE(value) \
- ((Value){.type = VT_CONSTANT_STRING, .data = (value)})
- #define SET_ERROR(format, ...) \
- snprintf( \
- c->error.text, sizeof(c->error.text), "%zu | " format, \
- c->code.readIndex __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 iPop(Code* c) {
- POP_VALUE(a);
- return false;
- }
- static bool iAdd(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data + a.data));
- }
- static bool iSub(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data - a.data));
- }
- static bool iMul(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data * a.data));
- }
- static bool iDiv(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data / a.data));
- }
- static bool iAnd(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data && a.data));
- }
- static bool iOr(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data || a.data));
- }
- static bool iNot(Code* c) {
- POP_VALUE(a);
- return iPushValue(c, INT_VALUE(!a.data));
- }
- static bool iEqual(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data == a.data));
- }
- static bool iNotEqual(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data != a.data));
- }
- static bool iGreater(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data > a.data));
- }
- static bool iSmaller(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data < a.data));
- }
- static bool iGreaterOrEqual(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data >= a.data));
- }
- static bool iSmallerOrEqual(Code* c) {
- POP_VALUE(a);
- POP_VALUE(b);
- return iPushValue(c, INT_VALUE(b.data <= a.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 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;
- i32 offset = 0;
- if(codeReadI32(c, &jumpPos)) {
- SET_ERROR("JumpSub without position");
- return true;
- } else if(codeReadI32(c, &offset)) {
- SET_ERROR("JumpSub without offset");
- return true;
- }
- i32 returnIndex = (i32)c->stackIndex - (offset + 1);
- if(returnIndex < 1 && returnIndex >= (i32)c->maxStackSize) {
- SET_ERROR("JumpSub with invalid return index");
- return true;
- }
- c->stack[returnIndex].data = codeGetPosition(c);
- c->stack[returnIndex - 1].data = c->localVariableIndex;
- c->localVariableIndex = returnIndex;
- codeSetPosition(c, (size_t)jumpPos);
- return false;
- }
- static bool iReturn(Code* c) {
- i32 popAmount = 0;
- if(codeReadI32(c, &popAmount)) {
- SET_ERROR("Return without pop amount");
- return true;
- }
- c->stackIndex -= (size_t)popAmount;
- POP_VALUE(returnAddress);
- POP_VALUE(variableIndex);
- codeSetPosition(c, (size_t)returnAddress.data);
- c->localVariableIndex = variableIndex.data;
- return false;
- }
- static bool iReturnValue(Code* c) {
- POP_VALUE(value);
- if(iReturn(c)) {
- return true;
- }
- return iPushValue(c, value);
- }
- static i32 iConvertAddress(Code* c, i32 address) {
- if(address >= 0) {
- return address;
- }
- return c->localVariableIndex - address;
- }
- static bool iReadVariable(Code* c) {
- i32 address = 0;
- if(codeReadI32(c, &address)) {
- SET_ERROR("ReadVariable without address");
- return true;
- }
- address = iConvertAddress(c, address);
- if((size_t)address >= c->stackIndex) {
- SET_ERROR(
- "ReadVariable with invalid address %d %zu", address, c->stackIndex);
- 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;
- }
- address = iConvertAddress(c, address);
- 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 iCallSystem(Code* c) {
- i32 amountIndex = 0;
- if(codeReadI32(c, &amountIndex)) {
- SET_ERROR("CallSystem without argument amount");
- return true;
- }
- i32 amount = amountIndex & 0xFF;
- i32 index = amountIndex >> 8;
- if(amount < 0 || amount > (i32)MAX_SYSTEM_FUNCTION_ARGUMENTS) {
- SET_ERROR("CallSystem with invalid amount");
- return true;
- }
- Value values[MAX_SYSTEM_FUNCTION_ARGUMENTS];
- for(i32 i = amount - 1; i >= 0; i--) {
- if(iPopValue(c, values + i)) {
- return true;
- }
- }
- SystemFunction f = getSystemFunction(index);
- if(f == nullptr) {
- SET_ERROR("Invalid system function index");
- return true;
- }
- Value r = {};
- if(f(c, &r, values, amount)) {
- return true;
- }
- return iPushValue(c, r);
- }
- static bool execute(Code* c, Instruction command) {
- switch(command) {
- case ADD: return iAdd(c);
- case SUB: return iSub(c);
- case MUL: return iMul(c);
- case DIV: return iDiv(c);
- case PUSH_CONSTANT_STRING: return iPushConstantString(c);
- case PUSH_INT32: return iPushInt(c);
- case POP: return iPop(c);
- case JUMP: return iJump(c);
- case JUMP_ON_0: return iJumpIf(c);
- case JUMP_SUB: return iJumpSub(c);
- case RETURN_VALUE: return iReturnValue(c);
- case READ_VARIABLE: return iReadVariable(c);
- case SET_VARIABLE: return iSetVariable(c);
- case PUSH_STACK_VARIABLES: return iPushStackVariables(c);
- case AND: return iAnd(c);
- case OR: return iOr(c);
- case NOT: return iNot(c);
- case EQUAL: return iEqual(c);
- case NOT_EQUAL: return iNotEqual(c);
- case GREATER: return iGreater(c);
- case SMALLER: return iSmaller(c);
- case GREATER_OR_EQUAL: return iGreaterOrEqual(c);
- case SMALLER_OR_EQUAL: return iSmallerOrEqual(c);
- case CALL_SYSTEM: return iCallSystem(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;
- }
- #define DUMP(name) \
- case name: fprintf(stderr, #name "\n"); break
- #define DUMP_INT(name) \
- case name: { \
- i32 v = 0; \
- (void)codeReadI32(&c, &v); \
- fprintf(stderr, #name " %d\n", v); \
- break; \
- } break
- #define DUMP_INT2(name) \
- case name: { \
- i32 v[2] = {}; \
- (void)codeReadI32(&c, v); \
- (void)codeReadI32(&c, v + 1); \
- fprintf(stderr, #name " %d %d\n", v[0], v[1]); \
- break; \
- } break
- void codeDump(const Code* code) {
- Code c = *code;
- while(true) {
- size_t start = c.code.readIndex;
- Instruction i = STOP;
- if(bufferReadU8(&c.code, &i)) {
- return;
- }
- fprintf(stderr, "%4zu | ", start);
- switch(i) {
- DUMP(ADD);
- DUMP(SUB);
- DUMP(MUL);
- DUMP(DIV);
- DUMP_INT(PUSH_INT32);
- DUMP(POP);
- DUMP_INT(JUMP);
- DUMP_INT(JUMP_ON_0);
- DUMP_INT2(JUMP_SUB);
- DUMP_INT(RETURN_VALUE);
- DUMP_INT(READ_VARIABLE);
- DUMP_INT(SET_VARIABLE);
- DUMP_INT(PUSH_STACK_VARIABLES);
- DUMP(AND);
- DUMP(OR);
- DUMP(NOT);
- DUMP(EQUAL);
- DUMP(NOT_EQUAL);
- DUMP(GREATER);
- DUMP(SMALLER);
- DUMP(GREATER_OR_EQUAL);
- DUMP(SMALLER_OR_EQUAL);
- DUMP_INT(CALL_SYSTEM);
- DUMP(STOP);
- case PUSH_CONSTANT_STRING:
- fprintf(
- stderr, "PUSH_CONSTANT_STRING %s\n",
- codeReadConstantString(&c));
- break;
- }
- }
- }
|