This commit is contained in:
2026-06-20 19:45:52 +10:00
parent b4e481ed9c
commit f97cec4567
17 changed files with 92 additions and 51 deletions

View File

@@ -14,3 +14,7 @@ meson install -C builddir
``` ```
You may need to run `ldconfig` or reboot to update your ld cache. You may need to run `ldconfig` or reboot to update your ld cache.
## Bytecode Format
Under the hood, Ground uses a bytecode format to store things.

View File

@@ -20,6 +20,10 @@ typedef struct GroundInstruction GroundInstruction;
typedef struct GroundProgram GroundProgram; typedef struct GroundProgram GroundProgram;
typedef struct GroundState GroundState; typedef struct GroundState GroundState;
typedef struct GroundBytecodeProgram GroundBytecodeProgram;
typedef struct GroundBytecodeInstruction GroundBytecodeInstruction;
typedef struct GroundBytecodeHeap GroundBytecodeHeap;
// --- Literal types --- // --- Literal types ---
typedef int64_t GroundInt; typedef int64_t GroundInt;
@@ -48,23 +52,25 @@ typedef struct GroundVariable GroundVariable;
typedef struct GroundLabel GroundLabel; typedef struct GroundLabel GroundLabel;
typedef struct GroundCatch GroundCatch; typedef struct GroundCatch GroundCatch;
typedef uint64_t GroundSize;
// --- Complex types definitions --- // --- Complex types definitions ---
struct GroundString { struct GroundString {
char* cstr; char* cstr;
size_t len; GroundSize len;
}; };
struct GroundList { struct GroundList {
size_t capacity; GroundSize capacity;
size_t count; GroundSize count;
GroundValue* at; GroundValue* at;
}; };
struct GroundFunction { struct GroundFunction {
struct { struct {
size_t capacity; GroundSize capacity;
size_t count; GroundSize count;
GroundFunctionArg* at; GroundFunctionArg* at;
} args; } args;
@@ -77,7 +83,7 @@ struct GroundFunction {
GroundState* closure; GroundState* closure;
size_t _requiredSize; GroundSize _requiredSize;
}; };
struct GroundStruct { struct GroundStruct {
@@ -149,7 +155,7 @@ struct GroundArg {
GroundValue value; GroundValue value;
} as; } as;
size_t _offset; GroundSize _offset;
}; };
enum GroundInstructionType { enum GroundInstructionType {
@@ -209,15 +215,15 @@ enum GroundInstructionType {
struct GroundInstruction { struct GroundInstruction {
enum GroundInstructionType type; enum GroundInstructionType type;
struct { struct {
size_t len; GroundSize len;
size_t capacity; GroundSize capacity;
GroundArg* at; GroundArg* at;
} args; } args;
}; };
struct GroundProgram { struct GroundProgram {
size_t len; GroundSize len;
size_t capacity; GroundSize capacity;
GroundInstruction* at; GroundInstruction* at;
}; };
@@ -226,12 +232,12 @@ struct GroundVariable {
GroundValue value; GroundValue value;
UT_hash_handle hh; UT_hash_handle hh;
size_t _offset; GroundSize _offset;
}; };
struct GroundLabel { struct GroundLabel {
char name[2048]; char name[2048];
size_t lineNum; GroundSize lineNum;
UT_hash_handle hh; UT_hash_handle hh;
}; };
@@ -246,14 +252,36 @@ struct GroundState {
GroundLabel* labels; GroundLabel* labels;
GroundCatch* catches; GroundCatch* catches;
size_t _size; GroundSize _size;
}; };
struct GroundIdentifier { struct GroundIdentifier {
char* string; char* string;
size_t referenceCount; GroundSize referenceCount;
}; };
struct GroundBytecodeProgram {
GroundBytecodeInstruction* at;
GroundSize capacity;
GroundSize len;
};
struct GroundBytecodeInstruction {
GroundInstruction instruction;
struct {
GroundSize* at;
GroundSize capacity;
GroundSize len;
} args;
};
struct GroundBytecodeHeap {
GroundValue* heap;
GroundSize capacity;
GroundSize count;
};
// //
// INTERFACE // INTERFACE
// //
@@ -299,7 +327,7 @@ struct _Ground {
GroundObject (*Object) (GroundStruct* in); GroundObject (*Object) (GroundStruct* in);
GroundError (*Error) (GroundValue* in); GroundError (*Error) (GroundValue* in);
GroundFunction (*NativeFunction) (void* function, size_t argc, ...); GroundFunction (*NativeFunction) (void* function, GroundSize argc, ...);
GroundInstruction (*Instruction) (enum GroundInstructionType type); GroundInstruction (*Instruction) (enum GroundInstructionType type);
GroundProgram (*Program) (); GroundProgram (*Program) ();
@@ -368,7 +396,7 @@ struct _Ground {
struct { struct {
GroundValue* (*findVariable) (GroundState* state, const char* id); GroundValue* (*findVariable) (GroundState* state, const char* id);
size_t* (*findLabel) (GroundState* state, const char* id); GroundSize* (*findLabel) (GroundState* state, const char* id);
GroundCatch* (*findCatch) (GroundState* state, const char* id); GroundCatch* (*findCatch) (GroundState* state, const char* id);
} State; } State;
@@ -384,10 +412,19 @@ struct _Ground {
void (*printErrors)(); void (*printErrors)();
char* errors[4096]; char* errors[4096];
size_t errorCount; GroundSize errorCount;
char* warnings[4096]; char* warnings[4096];
size_t warningCount; GroundSize warningCount;
} Log; } Log;
struct {
struct {
void (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
void (*optimise) (GroundBytecodeProgram* program);
} Program;
struct {} Instruction;
struct {} Heap;
} Bytecode;
}; };
extern struct _Ground Ground; extern struct _Ground Ground;

View File

@@ -31,7 +31,7 @@ GroundFunction _GroundCopyFunction(GroundFunction* in) {
Ground.Flags.error = true; Ground.Flags.error = true;
return newFunction; return newFunction;
} }
for (size_t i = 0; i < in->args.count; i++) { for (GroundSize i = 0; i < in->args.count; i++) {
if (newFunction.args.at == NULL) { if (newFunction.args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.Function()"); Ground.Log.Error("malloc failed in Ground.Copy.Function()");
Ground.Flags.error = true; Ground.Flags.error = true;

View File

@@ -12,7 +12,7 @@ GroundInstruction _GroundCopyInstruction(GroundInstruction* in) {
return instruction; return instruction;
} }
for (size_t i = 0; i < in->args.len; i++) { for (GroundSize i = 0; i < in->args.len; i++) {
instruction.args.at[i] = Ground.Copy.Arg(&in->args.at[i]); instruction.args.at[i] = Ground.Copy.Arg(&in->args.at[i]);
} }

View File

@@ -9,7 +9,7 @@ GroundList _GroundCopyList(GroundList* in) {
return list; return list;
} }
for (size_t i = 0; i < in->count; i++) { for (GroundSize i = 0; i < in->count; i++) {
list.at[i] = Ground.Copy.Value(&in->at[i]); list.at[i] = Ground.Copy.Value(&in->at[i]);
} }

View File

@@ -9,7 +9,7 @@ GroundProgram _GroundCopyProgram(GroundProgram* in) {
return program; return program;
} }
for (size_t i = 0; i < in->len; i++) { for (GroundSize i = 0; i < in->len; i++) {
program.at[i] = Ground.Copy.Instruction(&in->at[i]); program.at[i] = Ground.Copy.Instruction(&in->at[i]);
} }

View File

@@ -5,7 +5,7 @@ void _GroundFreeFunction(GroundFunction* in) {
Ground.Free.Program(in->program.ground); Ground.Free.Program(in->program.ground);
free(in->program.ground); free(in->program.ground);
for (size_t i = 0; i < in->args.count; i++) { for (GroundSize i = 0; i < in->args.count; i++) {
free(in->args.at[i].as.id); free(in->args.at[i].as.id);
} }
} }

View File

@@ -1,7 +1,7 @@
#include "../../include/ground.h" #include "../../include/ground.h"
void _GroundFreeInstruction(GroundInstruction* in) { void _GroundFreeInstruction(GroundInstruction* in) {
for (size_t i = 0; i < in->args.len; i++) { for (GroundSize i = 0; i < in->args.len; i++) {
Ground.Free.Arg(&in->args.at[i]); Ground.Free.Arg(&in->args.at[i]);
} }
free(in->args.at); free(in->args.at);

View File

@@ -1,7 +1,7 @@
#include "../../include/ground.h" #include "../../include/ground.h"
void _GroundFreeProgram(GroundProgram* in) { void _GroundFreeProgram(GroundProgram* in) {
for (size_t i = 0; i < in->len; i++) { for (GroundSize i = 0; i < in->len; i++) {
Ground.Free.Instruction(&in->at[i]); Ground.Free.Instruction(&in->at[i]);
} }
free(in->at); free(in->at);

View File

@@ -29,9 +29,9 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h
}; };
// Preprocess any ValueRefs // Preprocess any ValueRefs
for (size_t i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
if (instruction->args.at[i].type == GroundArg_ValueRef) { if (instruction->args.at[i].type == GroundArg_ValueRef) {
size_t offset = instruction->args.at[i]._offset; GroundSize offset = instruction->args.at[i]._offset;
instruction->args.at[i] = Ground.New.Arg.Value(heap[offset]); instruction->args.at[i] = Ground.New.Arg.Value(heap[offset]);
} }
} }
@@ -62,7 +62,7 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h
return -1; return -1;
} }
PRINT: { PRINT: {
for (size_t i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = &instruction->args.at[i].as.value; GroundValue* val = &instruction->args.at[i].as.value;
switch (val->type.type) { switch (val->type.type) {
case GroundType_Int: case GroundType_Int:
@@ -93,7 +93,7 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h
return -1; return -1;
} }
PRINTLN: { PRINTLN: {
for (size_t i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = &instruction->args.at[i].as.value; GroundValue* val = &instruction->args.at[i].as.value;
switch (val->type.type) { switch (val->type.type) {
case GroundType_Int: case GroundType_Int:
@@ -125,7 +125,7 @@ int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* h
return -1; return -1;
} }
SET: { SET: {
size_t offset = instruction->args.at[0]._offset; GroundSize offset = instruction->args.at[0]._offset;
heap[offset] = instruction->args.at[1].as.value; heap[offset] = instruction->args.at[1].as.value;
return -1; return -1;
} }

View File

@@ -6,7 +6,7 @@
static inline void doLabels(GroundProgram* program, GroundState* state) { static inline void doLabels(GroundProgram* program, GroundState* state) {
for (size_t i = 0; i < program->len; i++) { for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction* instruction = &program->at[i]; GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_CREATELABEL) { if (instruction->type == GroundInstruction_CREATELABEL) {
if (instruction->args.len > 0) { if (instruction->args.len > 0) {
@@ -30,11 +30,11 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
} }
} }
for (size_t i = 0; i < program->len; i++) { for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction* instruction = &program->at[i]; GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_JUMP) { if (instruction->type == GroundInstruction_JUMP) {
GroundArg* arg = &instruction->args.at[0]; GroundArg* arg = &instruction->args.at[0];
size_t* line = Ground.State.findLabel(state, arg->as.ref->string); GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) { if (line == NULL) {
char buf[2048]; char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i); snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
@@ -47,7 +47,7 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
} else if (instruction->type == GroundInstruction_IF) { } else if (instruction->type == GroundInstruction_IF) {
GroundArg* arg = &instruction->args.at[1]; GroundArg* arg = &instruction->args.at[1];
size_t* line = Ground.State.findLabel(state, arg->as.ref->string); GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) { if (line == NULL) {
char buf[2048]; char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i); snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
@@ -60,7 +60,7 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
} else if (instruction->type == GroundInstruction_CATCH) { } else if (instruction->type == GroundInstruction_CATCH) {
GroundArg* arg = &instruction->args.at[1]; GroundArg* arg = &instruction->args.at[1];
size_t* line = Ground.State.findLabel(state, arg->as.ref->string); GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) { if (line == NULL) {
char buf[2048]; char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i); snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
@@ -79,10 +79,10 @@ static inline void doLabels(GroundProgram* program, GroundState* state) {
/* /*
* Assigns an offset to each variable referenced. * Assigns an offset to each variable referenced.
*/ */
static inline size_t doOffsets(GroundProgram* program, GroundState* state) { static inline GroundSize doOffsets(GroundProgram* program, GroundState* state) {
size_t size = 0; GroundSize size = 0;
for (size_t i = 0; i < program->len; i++) { for (GroundSize i = 0; i < program->len; i++) {
for (size_t j = 0; j < program->at[i].args.len; j++) { for (GroundSize j = 0; j < program->at[i].args.len; j++) {
GroundArg* arg = &program->at[i].args.at[j]; GroundArg* arg = &program->at[i].args.at[j];
if ( if (
@@ -120,12 +120,12 @@ void _GroundInternalRun(GroundProgram* program, GroundState* state) {
doLabels(program, state); doLabels(program, state);
if (Ground.Flags.error) return; if (Ground.Flags.error) return;
size_t size = doOffsets(program, state); GroundSize size = doOffsets(program, state);
if (Ground.Flags.error) return; if (Ground.Flags.error) return;
GroundValue* heap = malloc(sizeof(GroundValue) * size); GroundValue* heap = malloc(sizeof(GroundValue) * size);
for (size_t i = 0; i < program->len; i++) { for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction instruction = Ground.Copy.Instruction(&program->at[i]); GroundInstruction instruction = Ground.Copy.Instruction(&program->at[i]);
int64_t status = Ground.Instruction.execute(&instruction, heap); int64_t status = Ground.Instruction.execute(&instruction, heap);
switch (status) { switch (status) {

View File

@@ -3,13 +3,13 @@
void _GroundLogPrintErrors() { 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 (size_t 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", Ground.Log.errorCount, 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 (size_t 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", Ground.Log.warningCount, Ground.Log.warnings[i]);
} }
} }

View File

@@ -1,6 +1,6 @@
#include "../../include/ground.h" #include "../../include/ground.h"
GroundList _GroundNewList(size_t len, GroundValue* contents) { GroundList _GroundNewList(GroundSize len, GroundValue* contents) {
GroundList list = { GroundList list = {
.capacity = 16, .capacity = 16,
.count = 0, .count = 0,

View File

@@ -2,7 +2,7 @@
#include <ffi.h> #include <ffi.h>
#include <stdarg.h> #include <stdarg.h>
GroundFunction _GroundNewNativeFunction(void* function, size_t argc, ...) { GroundFunction _GroundNewNativeFunction(void* function, GroundSize argc, ...) {
GroundState state = {NULL, NULL, NULL}; GroundState state = {NULL, NULL, NULL};
GroundFunction gf = Ground.New.Function(&state); GroundFunction gf = Ground.New.Function(&state);
@@ -13,7 +13,7 @@ GroundFunction _GroundNewNativeFunction(void* function, size_t argc, ...) {
va_list args; va_list args;
va_start(args, argc); va_start(args, argc);
for (size_t i = 0; i < argc; i++) { for (GroundSize i = 0; i < argc; i++) {
GroundType type = va_arg(args, GroundType); GroundType type = va_arg(args, GroundType);
if (type.type == GroundType_Struct) { if (type.type == GroundType_Struct) {
Ground.Log.Error("Cannot pass struct to native function in Ground.New.NativeFunction()"); Ground.Log.Error("Cannot pass struct to native function in Ground.New.NativeFunction()");

View File

@@ -2,7 +2,7 @@
GroundString _GroundNewString(const char* in) { GroundString _GroundNewString(const char* in) {
size_t len = strlen(in); GroundSize len = strlen(in);
GroundString string = { GroundString string = {
.len = len, .len = len,

View File

@@ -1,6 +1,6 @@
#include "../../include/ground.h" #include "../../include/ground.h"
size_t* _GroundStateFindLabel(GroundState* state, char* id) { GroundSize* _GroundStateFindLabel(GroundState* state, char* id) {
GroundLabel* item = NULL; GroundLabel* item = NULL;
HASH_FIND_STR(state->labels, id, item); HASH_FIND_STR(state->labels, id, item);

View File

@@ -21,7 +21,7 @@ GroundArg _GroundNewArgTypeRef(GroundIdentifier* ref);
GroundList _GroundNewList(); GroundList _GroundNewList();
GroundString _GroundNewString(const char* in); GroundString _GroundNewString(const char* in);
GroundFunction _GroundNewFunction(GroundState* state); GroundFunction _GroundNewFunction(GroundState* state);
GroundFunction _GroundNewNativeFunction(void* function, size_t argc, ...); GroundFunction _GroundNewNativeFunction(void* function, GroundSize argc, ...);
GroundStruct _GroundNewStruct(); GroundStruct _GroundNewStruct();
GroundObject _GroundNewObject(GroundStruct* in); GroundObject _GroundNewObject(GroundStruct* in);
GroundError _GroundNewError(GroundValue* in); GroundError _GroundNewError(GroundValue* in);
@@ -81,7 +81,7 @@ void _GroundStructAddField(GroundStruct* gs, const char* id, GroundValue value);
GroundValue* _GroundStateFindVariable(GroundState* state, const char* id); GroundValue* _GroundStateFindVariable(GroundState* state, const char* id);
size_t* _GroundStateFindLabel(GroundState* state, const char* id); GroundSize* _GroundStateFindLabel(GroundState* state, const char* id);
GroundCatch* _GroundStateFindCatch(GroundState* state, const char* id); GroundCatch* _GroundStateFindCatch(GroundState* state, const char* id);