hfguidshfiouhowfonweoinfvodnsbdifbisdb
This commit is contained in:
@@ -913,7 +913,24 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
GroundBytecodeValue* type = HEAP_GET(heap, instruction->args.at[i]);
|
GroundBytecodeValue* type = HEAP_GET(heap, instruction->args.at[i]);
|
||||||
switch (type->type.type) {
|
switch (type->type.type) {
|
||||||
case GroundType_Struct: {
|
case GroundType_Struct: {
|
||||||
// TODO nested structs
|
GroundBytecodeStruct* innerStruct = &type->as.Struct;
|
||||||
|
GroundBytecodeObject nestedObject = {
|
||||||
|
.size = innerStruct->size,
|
||||||
|
.capacity = innerStruct->size,
|
||||||
|
.values = malloc(sizeof(GroundBytecodeValue) * innerStruct->size)
|
||||||
|
};
|
||||||
|
if (nestedObject.values == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return CONTINUE;
|
||||||
|
}
|
||||||
|
for (GroundSize k = 0; k < innerStruct->size; k++) {
|
||||||
|
nestedObject.values[k] = Ground.Copy.BytecodeValue(&innerStruct->values[k]);
|
||||||
|
}
|
||||||
|
gbs->values[offset] = (GroundBytecodeValue) {
|
||||||
|
.as.Object = nestedObject,
|
||||||
|
.type = {GroundType_Object}
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroundType_CoreType: {
|
case GroundType_CoreType: {
|
||||||
@@ -1054,6 +1071,22 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
SETFIELD: {
|
SETFIELD: {
|
||||||
|
// args: [parent_offset, field0_offset, ..., fieldF_offset, value_offset]
|
||||||
|
GroundBytecodeValue* current = HEAP_GET(heap, instruction->args.at[0]);
|
||||||
|
|
||||||
|
for (GroundSize i = 1; i < instruction->args.len - 1; i++) {
|
||||||
|
if (current->type.type != GroundType_Object) {
|
||||||
|
Ground.Log.Error("SETFIELD on non-object value in Ground.Bytecode.Instruction.execute");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return CONTINUE;
|
||||||
|
}
|
||||||
|
current = ¤t->as.Object.values[instruction->args.at[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
GroundBytecodeValue* value = HEAP_GET(heap, instruction->args.at[instruction->args.len - 1]);
|
||||||
|
Ground.Free.BytecodeValue(current);
|
||||||
|
*current = Ground.Copy.BytecodeValue(value);
|
||||||
|
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
USE: {
|
USE: {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
void _GroundFreeArg(GroundArg* in) {
|
void _GroundFreeArg(GroundArg* in) {
|
||||||
if (in->type == GroundArg_Value) {
|
if (in->type == GroundArg_Value) {
|
||||||
Ground.Free.Value(&in->as.value);
|
Ground.Free.Value(&in->as.value);
|
||||||
} else {
|
} else if (in->type != GroundArg_DirectRef && in->type != GroundArg_Label && in->type != GroundArg_LineRef) {
|
||||||
Ground.Free.Identifier(in->as.ref);
|
Ground.Free.Identifier(in->as.ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,15 +106,49 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
|
|
||||||
// Set offset for each struct field
|
// Set offset for each struct field
|
||||||
GroundObjectField *s, *tmp;
|
GroundObjectField *s, *tmp;
|
||||||
GroundSize i = 0;
|
GroundSize fi = 0;
|
||||||
HASH_ITER(hh, gs->fields, s, tmp) {
|
HASH_ITER(hh, gs->fields, s, tmp) {
|
||||||
s->offset = i++;
|
s->offset = fi++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create bytecode instruction
|
||||||
|
GroundBytecodeInstruction newInst = {
|
||||||
|
.type = GroundInstruction_STRUCT,
|
||||||
|
.args = {
|
||||||
|
.at = malloc(sizeof(GroundSize) * inst->args.len),
|
||||||
|
.capacity = inst->args.len,
|
||||||
|
.len = inst->args.len
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newInst.args.at == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.New.Bytecode -> doOffsets");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the struct type variable to a heap offset
|
||||||
|
GroundArg* arg = &inst->args.at[0];
|
||||||
|
GroundVariable* structItem = NULL;
|
||||||
|
HASH_FIND_STR(state->variables, arg->as.ref->string, structItem);
|
||||||
|
if (structItem == NULL) {
|
||||||
|
structItem = malloc(sizeof(GroundVariable));
|
||||||
|
if (structItem == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.New.Bytecode -> doOffsets");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
structItem->value = Ground.New.Value.Int(0);
|
||||||
|
strncpy(structItem->name, arg->as.ref->string, 2047);
|
||||||
|
structItem->_offset = size++;
|
||||||
|
HASH_ADD_STR(state->variables, name, structItem);
|
||||||
|
}
|
||||||
|
newInst.args.at[0] = structItem->_offset;
|
||||||
|
|
||||||
// Now go through and add offsets to everything (skip struct name at index 0)
|
// Now go through and add offsets to everything (skip struct name at index 0)
|
||||||
for (GroundSize j = 1; j < inst->args.len; j++) {
|
for (GroundSize j = 1; j < inst->args.len; j++) {
|
||||||
// struct field name
|
// struct field name
|
||||||
GroundArg* arg = &inst->args.at[j];
|
arg = &inst->args.at[j];
|
||||||
GroundObjectField* field = NULL;
|
GroundObjectField* field = NULL;
|
||||||
HASH_FIND_STR(gs->fields, arg->as.ref->string, field);
|
HASH_FIND_STR(gs->fields, arg->as.ref->string, field);
|
||||||
if (field == NULL) {
|
if (field == NULL) {
|
||||||
@@ -122,20 +156,37 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
Ground.Flags.error = true;
|
Ground.Flags.error = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arg->_offset = field->offset;
|
newInst.args.at[j] = field->offset;
|
||||||
// 2nd arg offset is already set, but what we do next depends on it
|
// 2nd arg is the op code, what we do next depends on it
|
||||||
j++;
|
j++;
|
||||||
// 0 -> none
|
// 0 -> none
|
||||||
// 1 -> init
|
// 1 -> init
|
||||||
// 2 -> set
|
// 2 -> set
|
||||||
// 3 -> attach closure to function
|
// 3 -> attach closure to function
|
||||||
switch (inst->args.at[j]._offset) {
|
GroundSize op = inst->args.at[j]._offset;
|
||||||
|
newInst.args.at[j] = op;
|
||||||
|
switch (op) {
|
||||||
case 0: case 3: break; // these do not require extra values
|
case 0: case 3: break; // these do not require extra values
|
||||||
case 1: // but these do, so we process them
|
case 1: // but these do, so we process them
|
||||||
case 2: { // it's safe to assume that literals will have
|
case 2: {
|
||||||
j++; // been dealt with accordingly
|
j++;
|
||||||
arg = &inst->args.at[j];
|
arg = &inst->args.at[j];
|
||||||
GroundVariable* item = NULL;
|
GroundVariable* item = NULL;
|
||||||
|
|
||||||
|
if (arg->type == GroundArg_Value) {
|
||||||
|
// Literal value: create a constant variable for it
|
||||||
|
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.Copy.Value(&arg->as.value);
|
||||||
|
item->_offset = size++;
|
||||||
|
snprintf(item->name, sizeof(item->name) - 1, "_._.ground_internal_constant_%zu", item->_offset);
|
||||||
|
HASH_ADD_STR(state->variables, name, item);
|
||||||
|
} else {
|
||||||
|
// Variable reference: look it up or create it
|
||||||
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
|
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
|
||||||
|
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
@@ -150,12 +201,16 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
item->_offset = size++;
|
item->_offset = size++;
|
||||||
HASH_ADD_STR(state->variables, name, item);
|
HASH_ADD_STR(state->variables, name, item);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
arg->_offset = item->_offset;
|
newInst.args.at[j] = item->_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gbp->at[i] = newInst;
|
||||||
|
gbp->len++;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case GroundInstruction_GETFIELD: {
|
case GroundInstruction_GETFIELD: {
|
||||||
@@ -274,6 +329,114 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case GroundInstruction_SETFIELD: {
|
case GroundInstruction_SETFIELD: {
|
||||||
|
// setfield $parent -type (&field -type)... &field $value
|
||||||
|
// Bytecode: parent_offset, field0_offset, ..., fieldF_offset, value_offset
|
||||||
|
GroundInstruction* inst = &gp->at[i];
|
||||||
|
GroundSize gbiSize = 2 + ((inst->args.len - 2) / 2);
|
||||||
|
|
||||||
|
GroundBytecodeInstruction newInst = {
|
||||||
|
.type = GroundInstruction_SETFIELD,
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
newInst.args.at[0] = item->_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 value variable
|
||||||
|
GroundArg* valueArg = &inst->args.at[inst->args.len - 1];
|
||||||
|
GroundVariable* valueItem = NULL;
|
||||||
|
HASH_FIND_STR(state->variables, valueArg->as.ref->string, valueItem);
|
||||||
|
if (valueItem == NULL) {
|
||||||
|
valueItem = malloc(sizeof(GroundVariable));
|
||||||
|
if (valueItem == NULL) {
|
||||||
|
Ground.Log.Error("malloc failed in Ground.New.Bytecode -> doOffsets");
|
||||||
|
Ground.Flags.error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
valueItem->value = Ground.New.Value.Int(0);
|
||||||
|
strncpy(valueItem->name, valueArg->as.ref->string, 2047);
|
||||||
|
valueItem->_offset = size++;
|
||||||
|
HASH_ADD_STR(state->variables, name, valueItem);
|
||||||
|
}
|
||||||
|
newInst.args.at[gbiSize - 1] = valueItem->_offset;
|
||||||
|
|
||||||
|
gbp->at[i] = newInst;
|
||||||
|
gbp->len++;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,6 +246,8 @@ static void doStruct(GroundProgram* program, GroundProgram* newProgram, GroundSt
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ground.Program.append(newProgram, output);
|
||||||
|
|
||||||
GroundVariable* variable = malloc(sizeof(GroundVariable));
|
GroundVariable* variable = malloc(sizeof(GroundVariable));
|
||||||
if (variable == NULL) {
|
if (variable == NULL) {
|
||||||
Ground.Log.Error("malloc failed in Ground.Program.Preprocess -> doStruct");
|
Ground.Log.Error("malloc failed in Ground.Program.Preprocess -> doStruct");
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ char* _GroundStringifyBytecodeValue(GroundBytecodeValue* value) {
|
|||||||
}
|
}
|
||||||
case GroundType_Object: {
|
case GroundType_Object: {
|
||||||
Estr str = CREATE_ESTR("<object fields: { ");
|
Estr str = CREATE_ESTR("<object fields: { ");
|
||||||
for (GroundSize i = 0; i < value->as.Struct.size; i++) {
|
for (GroundSize i = 0; i < value->as.Object.size; i++) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
APPEND_ESTR(str, ", ");
|
APPEND_ESTR(str, ", ");
|
||||||
}
|
}
|
||||||
char* field = Ground.Stringify.BytecodeValue(&value->as.Struct.values[i]);
|
char* field = Ground.Stringify.BytecodeValue(&value->as.Object.values[i]);
|
||||||
APPEND_ESTR(str, field);
|
APPEND_ESTR(str, field);
|
||||||
free(field);
|
free(field);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user