bug fixes and getfield implementation beta
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user