bug fixes and getfield implementation beta
This commit is contained in:
19
README.md
19
README.md
@@ -53,3 +53,22 @@ Under the hood, Ground uses a bytecode format to store things.
|
|||||||
`extern` no longer loads a dynamic library from /usr/lib/ground, it is now used to detail a system shared library to open.
|
`extern` no longer loads a dynamic library from /usr/lib/ground, it is now used to detail a system shared library to open.
|
||||||
|
|
||||||
Format: `extern "libName" "symbolName" !functionName -returnType -argType...`
|
Format: `extern "libName" "symbolName" !functionName -returnType -argType...`
|
||||||
|
|
||||||
|
### `getfield`, `setfield`, `callmethod`
|
||||||
|
|
||||||
|
Due to the new bytecode format, these instructions go from this format
|
||||||
|
|
||||||
|
```
|
||||||
|
getfield $parent &fields... &output
|
||||||
|
setfield &parent &fields... $input
|
||||||
|
callmethod &parent &fields... !functionName $args... &output
|
||||||
|
```
|
||||||
|
|
||||||
|
to this format:
|
||||||
|
```
|
||||||
|
getfield $parent -type (&field -type)... &output
|
||||||
|
setfield &parent -type (&field -type)... $input
|
||||||
|
callmethod &parent -type (&field -type)... !functionName $args... &output
|
||||||
|
```
|
||||||
|
|
||||||
|
so offsets for instructions can be computed before runtime.
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @file ground.h
|
||||||
|
* @brief Defines the interface for the GroundVM.
|
||||||
|
*
|
||||||
|
* This header has two main sections: the types, and the interface. The types are the layout of the data that the GroundVM uses, whereas the interface declares all the functions which GroundVM provides for interfacing with Ground programs. The interface resides entirely in the struct _Ground, which has pointers to implementation functions.
|
||||||
|
*
|
||||||
|
* @author Maxwell Jeffress
|
||||||
|
* @date 2026-07-12
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef GROUND_H
|
#ifndef GROUND_H
|
||||||
#define GROUND_H
|
#define GROUND_H
|
||||||
|
|
||||||
@@ -394,10 +404,14 @@ struct _Ground {
|
|||||||
bool error;
|
bool error;
|
||||||
} Flags;
|
} Flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Functions to create new instances of Ground-specific types. Use Ground.Free to free when no longer needed.
|
||||||
|
*/
|
||||||
struct {
|
struct {
|
||||||
|
|
||||||
// Creates a new value of the specified type.
|
/**
|
||||||
// Returns a GroundValue
|
* @brief Creates a new GroundValue, which wraps the underlying value for the VM. Copies the input value.
|
||||||
|
*/
|
||||||
struct {
|
struct {
|
||||||
GroundValue (*Int) (GroundInt in);
|
GroundValue (*Int) (GroundInt in);
|
||||||
GroundValue (*Double) (GroundDouble in);
|
GroundValue (*Double) (GroundDouble in);
|
||||||
|
|||||||
@@ -713,6 +713,9 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
for (GroundSize i = 0; i < function->closure->len; i++) {
|
||||||
|
Ground.Free.BytecodeValue(&function->closure->heap[i]);
|
||||||
|
}
|
||||||
free(function->closure->heap);
|
free(function->closure->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,11 +727,6 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
|
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
|
||||||
Ground.Flags.error = true;
|
Ground.Flags.error = true;
|
||||||
return CONTINUE;
|
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++) {
|
for (GroundSize i = 0; i < heap->len; i++) {
|
||||||
@@ -961,6 +959,9 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
for (GroundSize i = 0; i < function->closure->len; i++) {
|
||||||
|
Ground.Free.BytecodeValue(&function->closure->heap[i]);
|
||||||
|
}
|
||||||
free(function->closure->heap);
|
free(function->closure->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -972,11 +973,6 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
|
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
|
||||||
Ground.Flags.error = true;
|
Ground.Flags.error = true;
|
||||||
return CONTINUE;
|
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++) {
|
for (GroundSize i = 0; i < heap->len; i++) {
|
||||||
@@ -1039,6 +1035,17 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
GETFIELD: {
|
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;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
SETFIELD: {
|
SETFIELD: {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "../../include/ground.h"
|
#include "../../include/ground.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
|
GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
|
||||||
GroundBytecodeValue newValue = *value;
|
GroundBytecodeValue newValue = *value;
|
||||||
@@ -7,6 +8,7 @@ GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
|
|||||||
case GroundType_Double:
|
case GroundType_Double:
|
||||||
case GroundType_Bool:
|
case GroundType_Bool:
|
||||||
case GroundType_Char:
|
case GroundType_Char:
|
||||||
|
case GroundType_CoreType:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GroundType_String: {
|
case GroundType_String: {
|
||||||
@@ -14,7 +16,161 @@ GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
|
|||||||
break;
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ GroundString _GroundCopyString(GroundString* in) {
|
|||||||
|
|
||||||
string.cstr = malloc(in->len + 1);
|
string.cstr = malloc(in->len + 1);
|
||||||
if (string.cstr == NULL) {
|
if (string.cstr == NULL) {
|
||||||
Ground.Flags.error = false;
|
Ground.Flags.error = true;
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,27 +2,56 @@
|
|||||||
|
|
||||||
void _GroundFreeBytecodeValue(GroundBytecodeValue* in) {
|
void _GroundFreeBytecodeValue(GroundBytecodeValue* in) {
|
||||||
|
|
||||||
// TODO: Implement all this
|
|
||||||
|
|
||||||
switch (in->type.type) {
|
switch (in->type.type) {
|
||||||
case GroundType_String: {
|
case GroundType_String: {
|
||||||
Ground.Free.String(&in->as.String);
|
Ground.Free.String(&in->as.String);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroundType_List: {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GroundType_Function: {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GroundType_Struct: {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case GroundType_Object: {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ void _GroundFreeObject(GroundObject* in) {
|
|||||||
HASH_DEL(in->fields, s);
|
HASH_DEL(in->fields, s);
|
||||||
|
|
||||||
Ground.Free.Value(&s->value);
|
Ground.Free.Value(&s->value);
|
||||||
|
free(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ void _GroundFreeStruct(GroundStruct* in) {
|
|||||||
HASH_DEL(in->fields, s);
|
HASH_DEL(in->fields, s);
|
||||||
|
|
||||||
Ground.Free.Value(&s->value);
|
Ground.Free.Value(&s->value);
|
||||||
|
free(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "../../include/ground.h"
|
#include "../../include/ground.h"
|
||||||
|
#include <uthash.h>
|
||||||
|
|
||||||
static inline void doLabels(GroundProgram* program, GroundState* state) {
|
static inline void doLabels(GroundProgram* program, GroundState* state) {
|
||||||
|
|
||||||
@@ -158,6 +159,117 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case GroundInstruction_GETFIELD: {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "../../include/ground.h"
|
#include "../../include/ground.h"
|
||||||
#include <uthash.h>
|
#include <uthash.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static inline GroundBytecodeFunction doFunction(GroundFunction* function) {
|
static inline GroundBytecodeFunction doFunction(GroundFunction* function) {
|
||||||
GroundBytecodeFunction bf = {
|
GroundBytecodeFunction bf = {
|
||||||
@@ -47,6 +48,9 @@ static inline GroundBytecodeFunction doFunction(GroundFunction* function) {
|
|||||||
// Now convert the program to bytecode
|
// Now convert the program to bytecode
|
||||||
GroundBytecode bytecode = Ground.New.Bytecode(function->program.ground, &state);
|
GroundBytecode bytecode = Ground.New.Bytecode(function->program.ground, &state);
|
||||||
*bf.program.ground = bytecode.program;
|
*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);
|
free(bytecode.heap.heap);
|
||||||
|
|
||||||
return bf;
|
return bf;
|
||||||
@@ -65,10 +69,12 @@ static inline GroundBytecodeStruct doStruct(GroundStruct* gs) {
|
|||||||
if (gbs.size >= gbs.capacity) {
|
if (gbs.size >= gbs.capacity) {
|
||||||
GroundBytecodeValue* tmp = malloc(sizeof(GroundBytecodeValue) * gbs.capacity * 2);
|
GroundBytecodeValue* tmp = malloc(sizeof(GroundBytecodeValue) * gbs.capacity * 2);
|
||||||
if (tmp == NULL) {
|
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;
|
Ground.Flags.error = true;
|
||||||
return gbs;
|
return gbs;
|
||||||
}
|
}
|
||||||
|
memcpy(tmp, gbs.values, sizeof(GroundBytecodeValue) * gbs.size);
|
||||||
|
free(gbs.values);
|
||||||
gbs.values = tmp;
|
gbs.values = tmp;
|
||||||
gbs.capacity *= 2;
|
gbs.capacity *= 2;
|
||||||
}
|
}
|
||||||
@@ -92,10 +98,12 @@ static inline GroundBytecodeObject doObject(GroundObject* go) {
|
|||||||
if (gbo.size >= gbo.capacity) {
|
if (gbo.size >= gbo.capacity) {
|
||||||
GroundBytecodeValue* tmp = malloc(sizeof(GroundBytecodeValue) * gbo.capacity * 2);
|
GroundBytecodeValue* tmp = malloc(sizeof(GroundBytecodeValue) * gbo.capacity * 2);
|
||||||
if (tmp == NULL) {
|
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;
|
Ground.Flags.error = true;
|
||||||
return gbo;
|
return gbo;
|
||||||
}
|
}
|
||||||
|
memcpy(tmp, gbo.values, sizeof(GroundBytecodeValue) * gbo.size);
|
||||||
|
free(gbo.values);
|
||||||
gbo.values = tmp;
|
gbo.values = tmp;
|
||||||
gbo.capacity *= 2;
|
gbo.capacity *= 2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,9 +231,10 @@ static void doStruct(GroundProgram* program, GroundProgram* newProgram, GroundSt
|
|||||||
}
|
}
|
||||||
case GroundInstruction_ENDSTRUCT: {
|
case GroundInstruction_ENDSTRUCT: {
|
||||||
parsing = false;
|
parsing = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
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