From 31577fcc624f10ff4b25b14015a3eeac16c21849 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 21 Jan 2026 13:25:13 +1100 Subject: [PATCH] Add set to compiler --- src/compiler.c | 134 ++++++++++++++++++++++++++++++++++++++++--------- src/compiler.h | 13 +++++ 2 files changed, 124 insertions(+), 23 deletions(-) diff --git a/src/compiler.c b/src/compiler.c index 10f5fdb..d0bc121 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -3,20 +3,126 @@ #include "types.h" #include "include/estr.h" #include +#include + +VariableTable createVariableTable() { + VariableTable vt; + vt.capacity = 16; + vt.count = 0; + vt.vars = malloc(sizeof(VariableInfo) * vt.capacity); + return vt; +} + +void addVtVariable(VariableTable* vt, const char* name) { + // check if it already exists + for (size_t i = 0; i < vt->count; i++) { + if (strcmp(vt->vars[i].name, name) == 0) { + return; + } + } + + // increase capacity + if (vt->count >= vt->capacity) { + vt->capacity *= 2; + vt->vars = realloc(vt->vars, sizeof(VariableInfo) * vt->capacity); + } + + // add the variable + strcpy(vt->vars[vt->count].name, name); + vt->vars[vt->count].offset = vt->count * 8; + vt->count++; +} + +int getVariablePos(VariableTable* vt, const char* name) { + for (size_t i = 0; i < vt->count; i++) { + if (strcmp(vt->vars[i].name, name) == 0) { + return vt->vars[i].offset; + } + } + return -1; +} + +char* processValueString(GroundArg arg) { + if (arg.type == VALREF) { + char* buf = malloc(sizeof(char) * 260); + snprintf(buf, sizeof(char) * 260, "[%s]", arg.value.refName); + return buf; + } + if (arg.type == VALUE) { + if (arg.value.value.type != INT) { + printf("Only int is supported right now"); + exit(1); + } + char* buf = malloc(sizeof(char) * 64); + snprintf(buf, sizeof(char) * 260, "%" PRId64, arg.value.value.data.intVal); + return buf; + } + return NULL; +} char* compileGroundProgram(GroundProgram* program) { Estr start = CREATE_ESTR("global _start\nsection .text\n_start:\n"); - Estr data = CREATE_ESTR("section .rodata\n"); + Estr data = CREATE_ESTR("section .bss\n"); + + VariableTable varTable = createVariableTable(); + + // Allocate a spot for all direct references + for (size_t i = 0; i < program->size; i++) { + GroundInstruction gi = program->instructions[i]; + for (size_t j = 0; j < gi.args.length; j++) { + if (gi.args.args[j].type == DIRREF) { + addVtVariable(&varTable, gi.args.args[j].value.refName); + } + } + } // Create data section for (size_t i = 0; i < program->size; i++) { - + if (strcmp(varTable.vars[i].name, "") == 0) { + continue; + } + APPEND_ESTR(data, " "); + APPEND_ESTR(data, varTable.vars[i].name); + APPEND_ESTR(data, " resq 1\n"); } // Generate assembly for (size_t i = 0; i < program->size; i++) { GroundInstruction gi = program->instructions[i]; switch (gi.type) { + case SET: { + if (gi.args.length < 2) { + runtimeError(TOO_FEW_ARGS, "Expecting 2 args", &gi, i); + } + if (gi.args.length > 2) { + runtimeError(TOO_MANY_ARGS, "Expecting 2 args", &gi, i); + } + if (gi.args.args[0].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 1", &gi, i); + } + if (gi.args.args[1].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 2", &gi, i); + } + + char* varName= gi.args.args[0].value.refName; + GroundValue val = gi.args.args[1].value.value; + + if (val.type != INT) { + runtimeError(ARG_TYPE_MISMATCH, "For now only ints are supported", &gi, i); + } + + char valueStr[32]; + snprintf(valueStr, sizeof(valueStr), "%" PRId64, val.data.intVal); + APPEND_ESTR(start, " ; set\n") + APPEND_ESTR(start, " mov rax, "); + APPEND_ESTR(start, valueStr); + APPEND_ESTR(start, "\n"); + APPEND_ESTR(start, " mov ["); + APPEND_ESTR(start, varName); + APPEND_ESTR(start, "], rax\n"); + + break; + } case END: { if (gi.args.length < 1) { runtimeError(TOO_FEW_ARGS, "Expecting 1 arg for end instruction", &gi, i); @@ -24,29 +130,10 @@ char* compileGroundProgram(GroundProgram* program) { if (gi.args.length > 1) { runtimeError(TOO_MANY_ARGS, "Expecting 1 arg for end instruction", &gi, i); } - if (gi.args.args[0].type != VALUE) { - runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int for end instruction", &gi, i); - } - if (gi.args.args[0].value.value.type != INT) { - runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int for end instruction", &gi, i); - } - - int64_t bigretint = gi.args.args[0].value.value.data.intVal; - int retint; - if (bigretint > 255) { - retint = 255; - } - else if (bigretint < 0) { - retint = 0; - } - else { - retint = bigretint; - } - char retstr[8]; - snprintf(retstr, sizeof(retstr), "%d", retint); + APPEND_ESTR(start, " ; end\n"); APPEND_ESTR(start, " mov rax, 60\n"); APPEND_ESTR(start, " mov rdi, "); - APPEND_ESTR(start, retstr); + APPEND_ESTR(start, processValueString(gi.args.args[0])); APPEND_ESTR(start, "\n"); APPEND_ESTR(start, " syscall\n"); break; @@ -60,6 +147,7 @@ char* compileGroundProgram(GroundProgram* program) { Estr complete = CREATE_ESTR(""); APPEND_ESTR(complete, start.str); + APPEND_ESTR(complete, " ; End of program\n mov rax, 60\n mov rdi, 0\n syscall\n"); APPEND_ESTR(complete, data.str) return complete.str; diff --git a/src/compiler.h b/src/compiler.h index ffda11e..4e5e37f 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -3,3 +3,16 @@ char* compileGroundProgram(GroundProgram* program); [[noreturn]] void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine); + +typedef struct VariableInfo { + char name[256]; + int offset; +} VariableInfo; + +typedef struct VariableTable { + VariableInfo* vars; + size_t count; + size_t capacity; +} VariableTable; + +