bug fixes and getfield implementation beta
This commit is contained in:
@@ -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 = ¤t->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: {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,5 +8,6 @@ void _GroundFreeObject(GroundObject* in) {
|
||||
HASH_DEL(in->fields, s);
|
||||
|
||||
Ground.Free.Value(&s->value);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,5 +8,6 @@ void _GroundFreeStruct(GroundStruct* in) {
|
||||
HASH_DEL(in->fields, s);
|
||||
|
||||
Ground.Free.Value(&s->value);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user