From 3e9ce0dfc0a5b96729bb44db5beaca9eb3deaa0e Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 21 Jan 2026 15:54:18 +1100 Subject: [PATCH 1/5] Expose compiler in groundvm.h --- include/groundvm.h | 1 + src/interface.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/include/groundvm.h b/include/groundvm.h index 58bb07a..c35c5a5 100644 --- a/include/groundvm.h +++ b/include/groundvm.h @@ -170,6 +170,7 @@ GroundProgram groundCreateProgram(); void groundAddInstructionToProgram(GroundProgram* program, GroundInstruction instruction); GroundValue groundRunProgram(GroundProgram* program); void groundPrintProgram(GroundProgram* program); +char* groundCompileProgram(GroundProgram* program); GroundInstruction groundCreateInstruction(GroundInstType type); void groundAddValueToInstruction(GroundInstruction* inst, GroundValue value); diff --git a/src/interface.c b/src/interface.c index 2f41515..511cb43 100644 --- a/src/interface.c +++ b/src/interface.c @@ -1,5 +1,6 @@ #include "parser.h" #include "interpreter.h" +#include "compiler.h" #include "types.h" #include @@ -123,3 +124,7 @@ void groundAddValueToScope(GroundScope* gs, const char* name, GroundValue value) void groundAddFieldToStruct(GroundStruct* gstruct, char* name, GroundValue field) { addFieldToStruct(gstruct, name, field); } + +char* groundCompileProgram(GroundProgram* program) { + return compileGroundProgram(program); +} From a3ca9791335b65b70eecf41122cf1e5d8eb5abe0 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 21 Jan 2026 16:02:13 +1100 Subject: [PATCH 2/5] Add not to compiler --- README.md | 1 + src/compiler.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/README.md b/README.md index 9240c35..acfb242 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ Supported instructions so far: * inequal * greater * lesser +* not * jump * if * @ (label creation) diff --git a/src/compiler.c b/src/compiler.c index 716aed9..b2c2dcb 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -221,6 +221,33 @@ char* compileGroundProgram(GroundProgram* program) { break; } + case NOT: { + 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 != VALUE && gi.args.args[0].type != VALREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Int (for now) for arg 1", &gi, i); + } + if (gi.args.args[1].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef", &gi, i); + } + + char* varName = gi.args.args[1].value.refName; + + APPEND_ESTR(start, " ; not\n"); + APPEND_ESTR(start, " mov rax, "); + APPEND_ESTR(start, processValueString(gi.args.args[0])); + APPEND_ESTR(start, "\n"); + APPEND_ESTR(start, " xor rax, 1\n"); + APPEND_ESTR(start, " mov ["); + APPEND_ESTR(start, varName); + APPEND_ESTR(start, "], rax\n"); + + break; + } case ADD: { if (gi.args.length < 3) { runtimeError(TOO_FEW_ARGS, "Expecting 2 args for add instruction", &gi, i); From b289448f56ed2ce2d48808d27f8fbbd2cf9f059d Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 21 Jan 2026 18:41:24 +1100 Subject: [PATCH 3/5] Add struct field access --- README.md | 2 +- src/interpreter.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ src/parser.c | 2 ++ src/types.h | 2 +- tests/struct.grnd | 17 ++++++++++++ 5 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 tests/struct.grnd diff --git a/README.md b/README.md index acfb242..96dd87f 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ build - [x] Return values (type checked) - [x] Arguments for functions - [x] Jumping within functions - - [ ] Custom data structures + - [x] Custom data structures - [ ] Working with external libraries ## Debugger diff --git a/src/interpreter.c b/src/interpreter.c index 0dbb3ca..dc4956e 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -2028,6 +2028,77 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop break; } + /* + * OBJECTS + * Allows manipulation of Ground objects. + */ + // getfield $obj &field &result + case GETFIELD: { + if (in->args.length < 3) { + runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.length > 3) { + runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.args[0].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Object for arg 1", in, currentInstruction); + } + if (in->args.args[0].value.value.type != CUSTOM) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting an Object for arg 1", in, currentInstruction); + } + if (in->args.args[1].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); + } + if (in->args.args[2].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction); + } + + GroundObjectField* field = findField(*in->args.args[0].value.value.data.customVal, in->args.args[1].value.refName); + if (field == NULL) { + runtimeError(UNKNOWN_VARIABLE, "Struct does not contain that field", in, currentInstruction); + } + addVariable(scope->variables, in->args.args[2].value.refName, field->value); + + break; + } + // setfield &obj &field $value + case SETFIELD: { + if (in->args.length < 3) { + runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.length > 3) { + runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction); + } + if (in->args.args[0].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef to an Object for arg 1", in, currentInstruction); + } + if (in->args.args[1].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); + } + if (in->args.args[2].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 3", in, currentInstruction); + } + + GroundVariable* var = findVariable(*scope->variables, in->args.args[0].value.refName); + if (var == NULL) { + runtimeError(UNKNOWN_VARIABLE, "Could not find that object", in, currentInstruction); + } + if (var->value.type != CUSTOM) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef to an Object for arg 1", in, currentInstruction); + } + + GroundObjectField* field = findField(*var->value.data.customVal, in->args.args[1].value.refName); + if (field == NULL) { + runtimeError(UNKNOWN_VARIABLE, "Struct does not contain that field", in, currentInstruction); + } + if (field->value.type != in->args.args[2].value.value.type) { + runtimeError(ARG_TYPE_MISMATCH, "Field type and provided type do not match", in, currentInstruction); + } + + field->value = copyGroundValue(&in->args.args[2].value.value); + break; + } + case DROP: { if (in->args.length < 1) { runtimeError(TOO_FEW_ARGS, "Expecting 1 arg", in, currentInstruction); diff --git a/src/parser.c b/src/parser.c index 57a3395..59a2b29 100644 --- a/src/parser.c +++ b/src/parser.c @@ -168,6 +168,8 @@ static GroundInstType getInstructionType(const char* inst) { if (strcmp(inst, "struct") == 0) return STRUCT; if (strcmp(inst, "endstruct") == 0) return ENDSTRUCT; if (strcmp(inst, "init") == 0) return INIT; + if (strcmp(inst, "getfield") == 0) return GETFIELD; + if (strcmp(inst, "setfield") == 0) return SETFIELD; if (strcmp(inst, "use") == 0) return USE; if (strcmp(inst, "extern") == 0) return EXTERN; if (strcmp(inst, "drop") == 0) return DROP; diff --git a/src/types.h b/src/types.h index 5085cd5..600322c 100644 --- a/src/types.h +++ b/src/types.h @@ -9,7 +9,7 @@ #include "include/uthash.h" typedef enum GroundInstType { - IF, JUMP, END, INPUT, PRINT, PRINTLN, SET, GETTYPE, EXISTS, SETLIST, SETLISTAT, GETLISTAT, GETLISTSIZE, LISTAPPEND, GETSTRSIZE, GETSTRCHARAT, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, NOT, GREATER, LESSER, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD + IF, JUMP, END, INPUT, PRINT, PRINTLN, SET, GETTYPE, EXISTS, SETLIST, SETLISTAT, GETLISTAT, GETLISTSIZE, LISTAPPEND, GETSTRSIZE, GETSTRCHARAT, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, NOT, GREATER, LESSER, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD } GroundInstType; typedef enum GroundValueType { diff --git a/tests/struct.grnd b/tests/struct.grnd new file mode 100644 index 0000000..852b4e7 --- /dev/null +++ b/tests/struct.grnd @@ -0,0 +1,17 @@ +struct -point + + init &x -int + init &y -int + +endstruct + +init &mypoint -point + +setfield &mypoint &x 53 +setfield &mypoint &y 32 + +getfield $mypoint &x &value +println $value + +getfield $mypoint &y &value +println $value From 228d2ac76298ebe6e1cdaf59da7230b15b31fec9 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 21 Jan 2026 18:59:24 +1100 Subject: [PATCH 4/5] I forgot the header again lmao --- include/groundvm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/groundvm.h b/include/groundvm.h index c35c5a5..601e496 100644 --- a/include/groundvm.h +++ b/include/groundvm.h @@ -14,7 +14,7 @@ #include typedef enum GroundInstType { - IF, JUMP, END, INPUT, PRINT, PRINTLN, SET, GETTYPE, EXISTS, SETLIST, SETLISTAT, GETLISTAT, GETLISTSIZE, LISTAPPEND, GETSTRSIZE, GETSTRCHARAT, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, NOT, GREATER, LESSER, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD + IF, JUMP, END, INPUT, PRINT, PRINTLN, SET, GETTYPE, EXISTS, SETLIST, SETLISTAT, GETLISTAT, GETLISTSIZE, LISTAPPEND, GETSTRSIZE, GETSTRCHARAT, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, NOT, GREATER, LESSER, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD } GroundInstType; typedef enum GroundValueType { From c382ecd867204b68cf053ede6980cd64852cb8d6 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Thu, 22 Jan 2026 10:50:48 +1100 Subject: [PATCH 5/5] Fix the header again --- include/groundvm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/groundvm.h b/include/groundvm.h index 601e496..7fbad50 100644 --- a/include/groundvm.h +++ b/include/groundvm.h @@ -58,6 +58,7 @@ typedef struct GroundError { */ typedef struct GroundValue { GroundValueType type; + struct GroundStruct* customType; union { int64_t intVal; double doubleVal;