hfguidshfiouhowfonweoinfvodnsbdifbisdb

This commit is contained in:
2026-07-13 16:47:41 +10:00
parent 7619b897e0
commit 05eddd9a0e
5 changed files with 215 additions and 17 deletions

View File

@@ -106,15 +106,49 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
// Set offset for each struct field
GroundObjectField *s, *tmp;
GroundSize i = 0;
GroundSize fi = 0;
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)
for (GroundSize j = 1; j < inst->args.len; j++) {
// struct field name
GroundArg* arg = &inst->args.at[j];
arg = &inst->args.at[j];
GroundObjectField* field = NULL;
HASH_FIND_STR(gs->fields, arg->as.ref->string, field);
if (field == NULL) {
@@ -122,40 +156,61 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
Ground.Flags.error = true;
return 0;
}
arg->_offset = field->offset;
// 2nd arg offset is already set, but what we do next depends on it
newInst.args.at[j] = field->offset;
// 2nd arg is the op code, what we do next depends on it
j++;
// 0 -> none
// 1 -> init
// 2 -> set
// 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 1: // but these do, so we process them
case 2: { // it's safe to assume that literals will have
j++; // been dealt with accordingly
case 2: {
j++;
arg = &inst->args.at[j];
GroundVariable* item = NULL;
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
if (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.New.Value.Int(0);
strncpy(item->name, arg->as.ref->string, 2047);
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);
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[j] = item->_offset;
}
}
}
gbp->at[i] = newInst;
gbp->len++;
continue;
}
case GroundInstruction_GETFIELD: {
@@ -274,6 +329,114 @@ static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, Ground
continue;
}
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;
}