bug fixes and getfield implementation beta

This commit is contained in:
2026-07-13 11:49:59 +10:00
parent 6929f055de
commit f2fbeb3a68
11 changed files with 371 additions and 23 deletions

View File

@@ -713,6 +713,9 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
return CONTINUE;
}
} else {
for (GroundSize i = 0; i < function->closure->len; i++) {
Ground.Free.BytecodeValue(&function->closure->heap[i]);
}
free(function->closure->heap);
}
@@ -724,11 +727,6 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
Ground.Flags.error = true;
return CONTINUE;
} else {
// forget all values in previous closure
for (GroundSize i = 0; i < function->closure->len; i++) {
Ground.Free.BytecodeValue(&function->closure->heap[i]);
}
}
for (GroundSize i = 0; i < heap->len; i++) {
@@ -961,6 +959,9 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
return CONTINUE;
}
} else {
for (GroundSize i = 0; i < function->closure->len; i++) {
Ground.Free.BytecodeValue(&function->closure->heap[i]);
}
free(function->closure->heap);
}
@@ -972,11 +973,6 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
Ground.Flags.error = true;
return CONTINUE;
} else {
// forget all values in previous closure
for (GroundSize i = 0; i < function->closure->len; i++) {
Ground.Free.BytecodeValue(&function->closure->heap[i]);
}
}
for (GroundSize i = 0; i < heap->len; i++) {
@@ -1039,6 +1035,17 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
return CONTINUE;
}
GETFIELD: {
// args: [parent_offset, field0_offset, ..., fieldF_offset, output_offset]
GroundBytecodeValue* current = HEAP_GET(heap, instruction->args.at[0]);
for (GroundSize i = 1; i < instruction->args.len - 1; i++) {
current = &current->as.Object.values[instruction->args.at[i]];
}
GroundBytecodeValue* output = HEAP_GET(heap, instruction->args.at[instruction->args.len - 1]);
Ground.Free.BytecodeValue(output);
*output = Ground.Copy.BytecodeValue(current);
return CONTINUE;
}
SETFIELD: {

View File

@@ -1,4 +1,5 @@
#include "../../include/ground.h"
#include <string.h>
GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
GroundBytecodeValue newValue = *value;
@@ -7,6 +8,7 @@ GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
case GroundType_Double:
case GroundType_Bool:
case GroundType_Char:
case GroundType_CoreType:
break;
case GroundType_String: {
@@ -14,7 +16,161 @@ GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
break;
}
// TODO: Implement copying for everything else
case GroundType_Object: {
GroundBytecodeObject* src = &value->as.Object;
GroundBytecodeObject dst = {
.size = src->size,
.capacity = src->capacity,
};
if (src->capacity > 0) {
dst.values = malloc(sizeof(GroundBytecodeValue) * src->capacity);
if (dst.values == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
for (GroundSize i = 0; i < src->size; i++) {
dst.values[i] = Ground.Copy.BytecodeValue(&src->values[i]);
}
}
newValue.as.Object = dst;
break;
}
case GroundType_Struct: {
GroundBytecodeStruct* src = &value->as.Struct;
GroundBytecodeStruct dst = {
.size = src->size,
.capacity = src->capacity,
};
if (src->capacity > 0) {
dst.values = malloc(sizeof(GroundBytecodeValue) * src->capacity);
if (dst.values == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
for (GroundSize i = 0; i < src->size; i++) {
dst.values[i] = Ground.Copy.BytecodeValue(&src->values[i]);
}
}
newValue.as.Struct = dst;
break;
}
case GroundType_List: {
GroundBytecodeList* src = &value->as.List;
GroundBytecodeList dst = {
.count = src->count,
.capacity = src->capacity,
};
if (src->capacity > 0) {
dst.at = malloc(sizeof(GroundBytecodeValue) * src->capacity);
if (dst.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
for (GroundSize i = 0; i < src->count; i++) {
dst.at[i] = Ground.Copy.BytecodeValue(&src->at[i]);
}
}
newValue.as.List = dst;
break;
}
case GroundType_Function: {
GroundBytecodeFunction* src = &value->as.Function;
GroundBytecodeFunction dst = *src;
if (src->args.at != NULL && src->args.count > 0) {
dst.args.at = malloc(sizeof(GroundFunctionArg) * src->args.count);
if (dst.args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
memcpy(dst.args.at, src->args.at, sizeof(GroundFunctionArg) * src->args.count);
} else {
dst.args.at = NULL;
}
if (!src->isNativeFunction && src->program.ground != NULL) {
dst.program.ground = malloc(sizeof(GroundBytecodeProgram));
if (dst.program.ground == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
free(dst.args.at);
break;
}
*dst.program.ground = *src->program.ground;
if (src->program.ground->at != NULL && src->program.ground->len > 0) {
dst.program.ground->at = malloc(sizeof(GroundBytecodeInstruction) * src->program.ground->len);
if (dst.program.ground->at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
free(dst.program.ground);
free(dst.args.at);
break;
}
for (GroundSize i = 0; i < src->program.ground->len; i++) {
dst.program.ground->at[i] = src->program.ground->at[i];
if (src->program.ground->at[i].args.at != NULL && src->program.ground->at[i].args.len > 0) {
dst.program.ground->at[i].args.at = malloc(sizeof(GroundSize) * src->program.ground->at[i].args.len);
if (dst.program.ground->at[i].args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
memcpy(dst.program.ground->at[i].args.at, src->program.ground->at[i].args.at, sizeof(GroundSize) * src->program.ground->at[i].args.len);
}
}
}
}
if (src->closure != NULL) {
dst.closure = malloc(sizeof(GroundBytecodeHeap));
if (dst.closure == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
dst.closure->capacity = src->closure->capacity;
dst.closure->len = src->closure->len;
if (src->closure->heap != NULL && src->closure->len > 0) {
dst.closure->heap = malloc(sizeof(GroundBytecodeValue) * src->closure->capacity);
if (dst.closure->heap == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
free(dst.closure);
break;
}
for (GroundSize i = 0; i < src->closure->len; i++) {
if (src->closure->heap[i].type.type == GroundType_Function) {
dst.closure->heap[i] = src->closure->heap[i];
} else {
dst.closure->heap[i] = Ground.Copy.BytecodeValue(&src->closure->heap[i]);
}
}
} else {
dst.closure->heap = NULL;
}
}
if (src->isNativeFunction && src->returnType != NULL) {
dst.returnType = malloc(sizeof(GroundType));
if (dst.returnType == NULL) {
Ground.Log.Error("malloc failed in Ground.Copy.BytecodeValue");
Ground.Flags.error = true;
break;
}
*dst.returnType = *src->returnType;
}
newValue.as.Function = dst;
break;
}
default: break;
}

View File

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

View File

@@ -2,27 +2,56 @@
void _GroundFreeBytecodeValue(GroundBytecodeValue* in) {
// TODO: Implement all this
switch (in->type.type) {
case GroundType_String: {
Ground.Free.String(&in->as.String);
break;
}
case GroundType_List: {
// Ground.Free.List(&in->as.List);
for (GroundSize i = 0; i < in->as.List.count; i++) {
Ground.Free.BytecodeValue(&in->as.List.at[i]);
}
free(in->as.List.at);
break;
}
case GroundType_Function: {
// Ground.Free.Function(&in->as.Function);
GroundBytecodeFunction* fn = &in->as.Function;
if (fn->closure != NULL) {
for (GroundSize i = 0; i < fn->closure->len; i++) {
if (fn->closure->heap[i].type.type != GroundType_Function) {
Ground.Free.BytecodeValue(&fn->closure->heap[i]);
}
}
free(fn->closure->heap);
free(fn->closure);
}
free(fn->args.at);
if (!fn->isNativeFunction && fn->program.ground != NULL) {
for (GroundSize i = 0; i < fn->program.ground->len; i++) {
free(fn->program.ground->at[i].args.at);
}
free(fn->program.ground->at);
free(fn->program.ground);
}
if (fn->isNativeFunction && fn->returnType != NULL) {
free(fn->returnType);
}
break;
}
case GroundType_Struct: {
// Ground.Free.Struct(&in->as.Struct);
GroundBytecodeStruct* gbs = &in->as.Struct;
for (GroundSize i = 0; i < gbs->size; i++) {
Ground.Free.BytecodeValue(&gbs->values[i]);
}
free(gbs->values);
break;
}
case GroundType_Object: {
// Ground.Free.Object(&in->as.Object);
GroundBytecodeObject* gbo = &in->as.Object;
for (GroundSize i = 0; i < gbo->size; i++) {
Ground.Free.BytecodeValue(&gbo->values[i]);
}
free(gbo->values);
break;
}

View File

@@ -8,5 +8,6 @@ void _GroundFreeObject(GroundObject* in) {
HASH_DEL(in->fields, s);
Ground.Free.Value(&s->value);
free(s);
}
}

View File

@@ -8,5 +8,6 @@ void _GroundFreeStruct(GroundStruct* in) {
HASH_DEL(in->fields, s);
Ground.Free.Value(&s->value);
free(s);
}
}

View File

@@ -1,4 +1,5 @@
#include "../../include/ground.h"
#include <uthash.h>
static inline void doLabels(GroundProgram* program, GroundState* state) {
@@ -158,6 +159,117 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
continue;
}
case GroundInstruction_GETFIELD: {
// getfield $parent -type (&field -type)... &field &output
// The last field does not need a type annotation.
// Bytecode: parent_offset, field0_offset, ..., fieldF_offset, output_offset
GroundInstruction* inst = &gp->at[i];
GroundSize gbiSize = 2 + ((inst->args.len - 2) / 2);
GroundBytecodeInstruction newInst = {
.type = GroundInstruction_GETFIELD,
.args = {
.at = malloc(sizeof(GroundSize) * gbiSize),
.capacity = gbiSize,
.len = gbiSize
}
};
if (newInst.args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
// Resolve the parent variable to a heap offset
GroundArg* arg = &inst->args.at[0];
GroundVariable* item = NULL;
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
if (item == NULL) {
item = malloc(sizeof(GroundVariable));
if (item == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
item->value = Ground.New.Value.Int(0);
strncpy(item->name, arg->as.ref->string, 2047);
item->_offset = size++;
HASH_ADD_STR(state->variables, name, item);
}
arg->_offset = item->_offset;
newInst.args.at[0] = arg->_offset;
// Get the type of the parent (type annotation is at args[1])
GroundVariable* var = NULL;
HASH_FIND_STR(state->variables, inst->args.at[1].as.ref->string, var);
if (var == NULL) {
Ground.Log.Error("unknown struct name in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
if (var->value.type.type != GroundType_Struct) {
Ground.Log.Error("known name is not a struct in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
GroundStruct* currentType = &var->value.as.Struct;
// Resolve each field's offset within its containing struct
for (GroundSize j = 0; j < gbiSize - 2; j++) {
GroundArg* arg = &inst->args.at[2 + (j * 2)];
GroundObjectField* field;
HASH_FIND_STR(currentType->fields, arg->as.ref->string, field);
if (field == NULL) {
Ground.Log.Error("unknown field in struct in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
newInst.args.at[1 + j] = field->offset;
// Resolve the type for the next field (not needed for the last field)
if (j < gbiSize - 3) {
GroundVariable* typeVar = NULL;
HASH_FIND_STR(state->variables, inst->args.at[3 + j * 2].as.ref->string, typeVar);
if (typeVar == NULL) {
Ground.Log.Error("unknown struct type for field in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
if (typeVar->value.type.type != GroundType_Struct) {
Ground.Log.Error("field type is not a struct in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
currentType = &typeVar->value.as.Struct;
}
}
// Resolve the output variable
GroundArg* outputArg = &inst->args.at[inst->args.len - 1];
GroundVariable* outputItem = NULL;
HASH_FIND_STR(state->variables, outputArg->as.ref->string, outputItem);
if (outputItem == NULL) {
outputItem = malloc(sizeof(GroundVariable));
if (outputItem == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Bytecode -> doOffsets");
Ground.Flags.error = true;
return 0;
}
outputItem->value = Ground.New.Value.Int(0);
strncpy(outputItem->name, outputArg->as.ref->string, 2047);
outputItem->_offset = size++;
HASH_ADD_STR(state->variables, name, outputItem);
}
outputArg->_offset = outputItem->_offset;
newInst.args.at[gbiSize - 1] = outputArg->_offset;
gbp->at[i] = newInst;
gbp->len++;
continue;
}

View File

@@ -1,5 +1,6 @@
#include "../../include/ground.h"
#include <uthash.h>
#include <string.h>
static inline GroundBytecodeFunction doFunction(GroundFunction* function) {
GroundBytecodeFunction bf = {
@@ -47,6 +48,9 @@ static inline GroundBytecodeFunction doFunction(GroundFunction* function) {
// Now convert the program to bytecode
GroundBytecode bytecode = Ground.New.Bytecode(function->program.ground, &state);
*bf.program.ground = bytecode.program;
for (GroundSize i = 0; i < bytecode.heap.len; i++) {
Ground.Free.BytecodeValue(&bytecode.heap.heap[i]);
}
free(bytecode.heap.heap);
return bf;
@@ -65,10 +69,12 @@ static inline GroundBytecodeStruct doStruct(GroundStruct* gs) {
if (gbs.size >= gbs.capacity) {
GroundBytecodeValue* tmp = malloc(sizeof(GroundBytecodeValue) * gbs.capacity * 2);
if (tmp == NULL) {
Ground.Log.Error("malloc failedd in Ground.New.BytecodeValue -> doStruct");
Ground.Log.Error("malloc failed in Ground.New.BytecodeValue -> doStruct");
Ground.Flags.error = true;
return gbs;
}
memcpy(tmp, gbs.values, sizeof(GroundBytecodeValue) * gbs.size);
free(gbs.values);
gbs.values = tmp;
gbs.capacity *= 2;
}
@@ -92,10 +98,12 @@ static inline GroundBytecodeObject doObject(GroundObject* go) {
if (gbo.size >= gbo.capacity) {
GroundBytecodeValue* tmp = malloc(sizeof(GroundBytecodeValue) * gbo.capacity * 2);
if (tmp == NULL) {
Ground.Log.Error("malloc failedd in Ground.New.BytecodeValue -> doStruct");
Ground.Log.Error("malloc failed in Ground.New.BytecodeValue -> doObject");
Ground.Flags.error = true;
return gbo;
}
memcpy(tmp, gbo.values, sizeof(GroundBytecodeValue) * gbo.size);
free(gbo.values);
gbo.values = tmp;
gbo.capacity *= 2;
}

View File

@@ -231,9 +231,10 @@ static void doStruct(GroundProgram* program, GroundProgram* newProgram, GroundSt
}
case GroundInstruction_ENDSTRUCT: {
parsing = false;
break;
}
default: {
Ground.Log.Error("invalid instruction inside struct in ");
Ground.Log.Error("invalid instruction inside struct in Ground.Program.Preprocess -> doStruct");
}
}