This commit is contained in:
2026-06-21 16:39:05 +10:00
parent b2f6883e62
commit c495b7c6fc
13 changed files with 109 additions and 101 deletions

View File

@@ -1,6 +1,33 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <string.h>
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
#define HEAP_SET(heap, idx, val) ((heap)->heap[(idx)] = (val))
static void printValue(GroundValue* val) {
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
}
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) { int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
@@ -20,11 +47,10 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
&&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH &&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH
}; };
// Jump to the spot
goto *jumpTable[instruction->type]; goto *jumpTable[instruction->type];
IF: { IF: {
GroundValue* cond = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* cond = HEAP_GET(heap, instruction->args.at[0]);
if (cond->as.Bool) { if (cond->as.Bool) {
return instruction->args.at[1]; return instruction->args.at[1];
} }
@@ -41,69 +67,19 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
} }
PRINT: { PRINT: {
for (GroundSize i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = Ground.Bytecode.Heap.get(heap, instruction->args.at[i]); printValue(HEAP_GET(heap, instruction->args.at[i]));
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
} }
return -1; return -1;
} }
PRINTLN: { PRINTLN: {
for (GroundSize i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = Ground.Bytecode.Heap.get(heap, instruction->args.at[i]); printValue(HEAP_GET(heap, instruction->args.at[i]));
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
} }
printf("\n"); printf("\n");
return -1; return -1;
} }
SET: { SET: {
Ground.Bytecode.Heap.set(heap, instruction->args.at[0], *Ground.Bytecode.Heap.get(heap, instruction->args.at[1])); HEAP_SET(heap, instruction->args.at[0], *HEAP_GET(heap, instruction->args.at[1]));
return -1; return -1;
} }
GETTYPE: { GETTYPE: {
@@ -136,9 +112,9 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
ADD: { ADD: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]); GroundValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]); GroundValue* right = HEAP_GET(heap, instruction->args.at[1]);
switch (left->type.type) { switch (left->type.type) {
case GroundType_Int: { case GroundType_Int: {
@@ -180,7 +156,8 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
case GroundType_String: { case GroundType_String: {
switch (right->type.type) { switch (right->type.type) {
case GroundType_String: { case GroundType_String: {
char* buf = malloc(sizeof(char) * (left->as.String.len + right->as.String.len + 1)); GroundSize total = left->as.String.len + right->as.String.len;
char* buf = malloc(total + 1);
if (buf == NULL) { if (buf == NULL) {
Ground.Log.Error("malloc failed (instruction ADD{string, string, dirref}) in Ground.Instruction.execute()"); Ground.Log.Error("malloc failed (instruction ADD{string, string, dirref}) in Ground.Instruction.execute()");
Ground.Flags.error = true; Ground.Flags.error = true;
@@ -206,9 +183,9 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
SUBTRACT: { SUBTRACT: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]); GroundValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]); GroundValue* right = HEAP_GET(heap, instruction->args.at[1]);
switch (left->type.type) { switch (left->type.type) {
case GroundType_Int: { case GroundType_Int: {
@@ -256,9 +233,9 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
MULTIPLY: { MULTIPLY: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]); GroundValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]); GroundValue* right = HEAP_GET(heap, instruction->args.at[1]);
switch (left->type.type) { switch (left->type.type) {
case GroundType_Int: { case GroundType_Int: {
@@ -306,9 +283,9 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
DIVIDE: { DIVIDE: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]); GroundValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]); GroundValue* right = HEAP_GET(heap, instruction->args.at[1]);
switch (left->type.type) { switch (left->type.type) {
case GroundType_Int: { case GroundType_Int: {
@@ -356,9 +333,9 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
EQUAL: { EQUAL: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]); GroundValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]); GroundValue* right = HEAP_GET(heap, instruction->args.at[1]);
switch (left->type.type) { switch (left->type.type) {
case GroundType_Int: { case GroundType_Int: {
@@ -413,14 +390,13 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
} }
case GroundType_String: { case GroundType_String: {
if (right->type.type == GroundType_String) { if (right->type.type == GroundType_String) {
*final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr)); *final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr) == 0);
} else { } else {
*final = Ground.New.Value.Bool(false); *final = Ground.New.Value.Bool(false);
} }
break; break;
} }
default: { default: {
// FIXME implement for complex types
*final = Ground.New.Value.Bool(false); *final = Ground.New.Value.Bool(false);
break; break;
} }
@@ -428,9 +404,9 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
INEQUAL: { INEQUAL: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]); GroundValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]); GroundValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]); GroundValue* right = HEAP_GET(heap, instruction->args.at[1]);
switch (left->type.type) { switch (left->type.type) {
case GroundType_Int: { case GroundType_Int: {
@@ -485,14 +461,13 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
} }
case GroundType_String: { case GroundType_String: {
if (right->type.type == GroundType_String) { if (right->type.type == GroundType_String) {
*final = Ground.New.Value.Bool(!strcmp(left->as.String.cstr, right->as.String.cstr)); *final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr) != 0);
} else { } else {
*final = Ground.New.Value.Bool(true); *final = Ground.New.Value.Bool(true);
} }
break; break;
} }
default: { default: {
// FIXME implement for complex types
*final = Ground.New.Value.Bool(false); *final = Ground.New.Value.Bool(false);
break; break;
} }
@@ -500,7 +475,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
return -1; return -1;
} }
NOT: { NOT: {
Ground.Bytecode.Heap.set(heap, instruction->args.at[1], Ground.New.Value.Bool(!Ground.Bytecode.Heap.get(heap, instruction->args.at[0])->as.Bool)); HEAP_SET(heap, instruction->args.at[1], Ground.New.Value.Bool(!HEAP_GET(heap, instruction->args.at[0])->as.Bool));
return -1; return -1;
} }
GREATER: { GREATER: {

View File

@@ -2,14 +2,15 @@
#include <stdint.h> #include <stdint.h>
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) { void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) {
for (GroundSize i = 0; i < program->len; i++) { GroundSize i = 0;
while (i < program->len) {
int64_t status = Ground.Bytecode.Instruction.execute(&program->at[i], heap); int64_t status = Ground.Bytecode.Instruction.execute(&program->at[i], heap);
if (Ground.Flags.error) { if (Ground.Flags.error) {
return; return;
} }
switch (status) { switch (status) {
case -1: break; case -1: i++; break;
case -2: return; case -2: return;
default: i = status; break; default: i = status; break;
} }

View File

@@ -1,5 +1,16 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program) { void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program) {
// TODO: Implement optimisation
for (GroundSize i = 0; i < program->len; i++) {
if (program->at[i].type == GroundInstruction_JUMP) {
GroundSize target = program->at[i].args.at[0];
while (target < program->len && program->at[target].type == GroundInstruction_JUMP) {
target = program->at[target].args.at[0];
}
program->at[i].args.at[0] = target;
}
}
} }

View File

@@ -22,6 +22,13 @@ GroundObject _GroundCopyObject(GroundObject* in) {
strncpy(item->name, s->name, 2047); strncpy(item->name, s->name, 2047);
item->value = malloc(sizeof(GroundValue));
if (item->value == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.Object()");
Ground.Flags.error = true;
return object;
}
*item->value = Ground.Copy.Value(s->value); *item->value = Ground.Copy.Value(s->value);
if (Ground.Flags.error) { if (Ground.Flags.error) {

View File

@@ -33,7 +33,7 @@ GroundState _GroundCopyState(GroundState* in) {
GroundLabel *s, *tmp, *new; GroundLabel *s, *tmp, *new;
HASH_ITER(hh, in->labels, s, tmp) { HASH_ITER(hh, in->labels, s, tmp) {
new = malloc(sizeof(GroundVariable)); new = malloc(sizeof(GroundLabel));
if (new == NULL) { if (new == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.State()"); Ground.Log.Error("malloc failed in Ground.Copy.State()");
Ground.Flags.error = true; Ground.Flags.error = true;
@@ -52,7 +52,7 @@ GroundState _GroundCopyState(GroundState* in) {
GroundCatch *s, *tmp, *new; GroundCatch *s, *tmp, *new;
HASH_ITER(hh, in->catches, s, tmp) { HASH_ITER(hh, in->catches, s, tmp) {
new = malloc(sizeof(GroundVariable)); new = malloc(sizeof(GroundCatch));
if (new == NULL) { if (new == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.State()"); Ground.Log.Error("malloc failed in Ground.Copy.State()");
Ground.Flags.error = true; Ground.Flags.error = true;

View File

@@ -3,7 +3,7 @@
GroundString _GroundCopyString(GroundString* in) { GroundString _GroundCopyString(GroundString* in) {
GroundString string = *in; GroundString string = *in;
string.cstr = malloc(sizeof(char) * in->len); string.cstr = malloc(in->len + 1);
if (string.cstr == NULL) { if (string.cstr == NULL) {
Ground.Flags.error = false; Ground.Flags.error = false;
return string; return string;

View File

@@ -21,6 +21,13 @@ GroundStruct _GroundCopyStruct(GroundStruct* in) {
strncpy(item->name, s->name, 2047); strncpy(item->name, s->name, 2047);
item->value = malloc(sizeof(GroundValue));
if (item->value == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.Struct()");
Ground.Flags.error = true;
return gs;
}
*item->value = Ground.Copy.Value(s->value); *item->value = Ground.Copy.Value(s->value);
if (Ground.Flags.error) { if (Ground.Flags.error) {

View File

@@ -12,14 +12,14 @@ void _GroundFreeState(GroundState* in) {
{ {
GroundCatch *s, *tmp; GroundCatch *s, *tmp;
HASH_ITER(hh, in->catches, s, tmp) { HASH_ITER(hh, in->catches, s, tmp) {
HASH_DEL(in->variables, s); HASH_DEL(in->catches, s);
free(s); free(s);
} }
} }
{ {
GroundLabel *s, *tmp; GroundLabel *s, *tmp;
HASH_ITER(hh, in->labels, s, tmp) { HASH_ITER(hh, in->labels, s, tmp) {
HASH_DEL(in->variables, s); HASH_DEL(in->labels, s);
free(s); free(s);
} }
} }

View File

@@ -4,13 +4,13 @@ void _GroundLogPrintErrors() {
if (Ground.Log.errorCount != 0) { if (Ground.Log.errorCount != 0) {
printf("%zu errors:\n", Ground.Log.errorCount); printf("%zu errors:\n", Ground.Log.errorCount);
for (GroundSize i = 0; i < Ground.Log.errorCount; i++) { for (GroundSize i = 0; i < Ground.Log.errorCount; i++) {
printf(" \e[0;31m%zu: %s\n\e[0m", Ground.Log.errorCount, Ground.Log.errors[i]); printf(" \e[0;31m%zu: %s\n\e[0m", i, Ground.Log.errors[i]);
} }
} }
if (Ground.Log.warningCount != 0) { if (Ground.Log.warningCount != 0) {
printf("%zu warnings:\n", Ground.Log.warningCount); printf("%zu warnings:\n", Ground.Log.warningCount);
for (GroundSize i = 0; i < Ground.Log.warningCount; i++) { for (GroundSize i = 0; i < Ground.Log.warningCount; i++) {
printf(" \e[0;33m%zu: %s\n\e[0m", Ground.Log.warningCount, Ground.Log.warnings[i]); printf(" \e[0;33m%zu: %s\n\e[0m", i, Ground.Log.warnings[i]);
} }
} }
} }

View File

@@ -2,9 +2,9 @@
GroundFunction _GroundNewFunction(GroundState* state) { GroundFunction _GroundNewFunction(GroundState* state) {
GroundFunction function = { GroundFunction function = {
.args.at = malloc(sizeof(char*) * 16), .args.at = malloc(sizeof(GroundFunctionArg) * 16),
.args.count = 0, .args.count = 0,
.args.capacity = 0, .args.capacity = 16,
.closure = malloc(sizeof(GroundState)), .closure = malloc(sizeof(GroundState)),
.isNativeFunction = false, .isNativeFunction = false,

View File

@@ -22,6 +22,13 @@ GroundObject _GroundNewObject(GroundStruct* in) {
strncpy(item->name, s->name, 2047); strncpy(item->name, s->name, 2047);
item->value = malloc(sizeof(GroundValue));
if (item->value == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Object()");
Ground.Flags.error = true;
return object;
}
*item->value = Ground.Copy.Value(s->value); *item->value = Ground.Copy.Value(s->value);
if (Ground.Flags.error) { if (Ground.Flags.error) {

View File

@@ -6,7 +6,7 @@ GroundString _GroundNewString(const char* in) {
GroundString string = { GroundString string = {
.len = len, .len = len,
.cstr = malloc(sizeof(len) + 1) .cstr = malloc(len + 1)
}; };
if (string.cstr == NULL) { if (string.cstr == NULL) {

View File

@@ -30,7 +30,7 @@ Args parseArgs(int argc, char** argv) {
args.action = ARGS_DEBUG; args.action = ARGS_DEBUG;
} else if (strcmp(arg, "-a") == 0 || strcmp(arg, "--assemble") == 0) { } else if (strcmp(arg, "-a") == 0 || strcmp(arg, "--assemble") == 0) {
args.action = ARGS_ASSEMBLE; args.action = ARGS_ASSEMBLE;
if (i + i < argc) { if (i + 1 < argc) {
i++; i++;
args.outputFile = argv[i]; args.outputFile = argv[i];
} }
@@ -50,13 +50,13 @@ Args parseArgs(int argc, char** argv) {
int main(int argc, char** argv) { int main(int argc, char** argv) {
Args args = parseArgs(argc, argv); Args args = parseArgs(argc, argv);
if (args.inputFile == NULL) {
fprintf(stderr, "Please specify a bytecode file\n");
return 1;
}
switch (args.action) { switch (args.action) {
case ARGS_EXECUTE: { case ARGS_EXECUTE: {
if (args.inputFile == NULL) {
fprintf(stderr, "Please specify a bytecode file\n");
return 1;
}
GroundBytecode bc = Ground.Bytecode.load(args.inputFile); GroundBytecode bc = Ground.Bytecode.load(args.inputFile);
if (Ground.Flags.error) { if (Ground.Flags.error) {
fprintf(stderr, "Failed to load bytecode, printing errors...\n"); fprintf(stderr, "Failed to load bytecode, printing errors...\n");