refactor to facilitate solstice stuff

This commit is contained in:
2026-04-20 19:05:10 +10:00
parent fca9dd63a0
commit 80ee95b918
2 changed files with 130 additions and 147 deletions

View File

@@ -25,7 +25,7 @@ char* getFileContents(const char* filename) {
file = calloc(1, lSize + 1);
if (!file) {
fclose(fp);
fputs("memory allocation fail when reading file", stderr);
fprintf(stderr, "memory allocation fail when reading file %s\n", filename);
exit(1);
}

View File

@@ -373,11 +373,59 @@ GroundFunction* parseFunction(GroundProgram* in, size_t errorOffset) {
return function;
}
GroundValue resolveInstructionVariables(GroundInstruction* in, GroundScope* scope) {
for (size_t i = 0; i < in->args.length; i++) {
if (in->args.args[i].type == VALREF) {
GroundVariable* variable = findVariable(*scope->variables, in->args.args[i].value.refName);
if (variable) {
// If there is a duplicator, call it (except when returning and getting fields)
if (variable->value.type == CUSTOM && in->type != RETURN && in->type != GETFIELD) {
GroundObject* obj = variable->value.data.customVal;
GroundObjectField* duplicator = findField(*obj, "duplicator");
if (duplicator != NULL) {
if (duplicator->value.type != FUNCTION) {
runtimeError(ARG_TYPE_MISMATCH, "duplicator is not a function", in, currentInstruction);
}
GroundInstruction gi = createGroundInstruction(CALLMETHOD);
addArgToInstruction(&gi, createRefGroundArg(DIRREF, in->args.args[i].value.refName));
addArgToInstruction(&gi, createRefGroundArg(FNREF, "duplicator"));
addArgToInstruction(&gi, createValueGroundArg(variable->value));
addArgToInstruction(&gi, createRefGroundArg(DIRREF, "__ground_tmp_duplicate"));
GroundValue gv = interpretGroundInstruction(gi, scope);
if (gv.type == ERROR) {
return gv;
}
GroundVariable* tmp = findVariable(*scope->variables, "__ground_tmp_duplicate");
if (tmp == NULL) {
runtimeError(FIXME, "Couldn't find temporary variable (this should never happen)", in, currentInstruction);
}
in->args.args[i].value.value = copyGroundValue(&tmp->value);
in->args.args[i].type = VALUE;
deleteVariable(scope->variables, tmp);
continue;
}
}
free(in->args.args[i].value.refName);
in->args.args[i].value.value = copyGroundValue(&variable->value);
in->args.args[i].type = VALUE;
} else {
runtimeError(UNKNOWN_VARIABLE, NULL, in, currentInstruction);
}
}
}
return createNoneGroundValue();
}
GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffset) {
GroundStruct gstruct = createStruct();
for (size_t i = 0; i < in->size; i++) {
switch (in->instructions[i].type) {
case SET: {
GroundValue resolved = resolveInstructionVariables(&in->instructions[i], scope);
if (resolved.type == ERROR) {
throwError(&resolved.data.errorVal);
}
if (in->instructions[i].args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", &in->instructions[i], i + errorOffset);
}
@@ -520,7 +568,6 @@ GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffs
}
return gstruct;
}
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
GroundLabel* labels = NULL;
GroundVariable* variables = NULL;
@@ -537,51 +584,11 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
}
scope.isMainScope = isMainScopeGlobal;
isMainScopeGlobal = false;
// Preprocess all labels, structs and functions
// Preprocess all labels
for (size_t i = 0; i < in->size; i++) {
if (in->instructions[i].type == CREATELABEL) {
addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i);
}
if (in->instructions[i].type == STRUCT) {
if (in->instructions[i].args.length < 1) {
runtimeError(TOO_FEW_ARGS, "Expecting 1 arg", &in->instructions[i], i);
}
if (in->instructions[i].args.length > 1) {
runtimeError(TOO_MANY_ARGS, "Expecting 1 arg", &in->instructions[i], i);
}
if (in->instructions[i].args.args[0].type != TYPEREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expected arg 1 to be a typeref", &in->instructions[i], i);
}
char* name = malloc(strlen(in->instructions[i].args.args[0].value.refName) + 1);
strcpy(name, in->instructions[i].args.args[0].value.refName);
i++;
size_t counter = 1;
GroundProgram gp = createGroundProgram();
size_t errorOffset = i;
while (counter > 0) {
if (i >= in->size) {
runtimeError(PREMATURE_EOF, "Reached end of scope before struct definition ended", &in->instructions[i - 1], i - 1);
}
if (in->instructions[i].type == STRUCT) {
counter++;
}
if (in->instructions[i].type == ENDSTRUCT) {
counter--;
}
addInstructionToProgram(&gp, in->instructions[i]);
i++;
}
i--;
GroundValue gv = {
.type = STRUCTVAL,
.data.structVal = malloc(sizeof(GroundStruct))
};
*gv.data.structVal = parseStruct(&gp, &scope, errorOffset);
addVariable(scope.variables, name, gv);
}
}
for (size_t i = 0; i < in->size; i++) {
if (in->instructions[i].type == FUN) {
@@ -621,37 +628,47 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
addVariable(scope.variables, name, gv);
}
/*
if (in->instructions[i].type == FUN) {
int count = 1;
while (count > 0) {
i++;
if (i >= in->size) {
return createNoneGroundValue();
}
if (in->instructions[i].type == FUN) {
count++;
}
if (in->instructions[i].type == ENDFUN) {
count--;
}
}
}
*/
if (in->instructions[i].type == STRUCT) {
int count = 1;
while (count > 0) {
if (in->instructions[i].args.length < 1) {
runtimeError(TOO_FEW_ARGS, "Expecting 1 arg", &in->instructions[i], i);
}
if (in->instructions[i].args.length > 1) {
runtimeError(TOO_MANY_ARGS, "Expecting 1 arg", &in->instructions[i], i);
}
if (in->instructions[i].args.args[0].type != TYPEREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expected arg 1 to be a typeref", &in->instructions[i], i);
}
char* name = malloc(strlen(in->instructions[i].args.args[0].value.refName) + 1);
strcpy(name, in->instructions[i].args.args[0].value.refName);
i++;
size_t counter = 1;
GroundProgram gp = createGroundProgram();
size_t errorOffset = i;
while (counter > 0) {
if (i >= in->size) {
return createNoneGroundValue();
runtimeError(PREMATURE_EOF, "Reached end of scope before struct definition ended", &in->instructions[i - 1], i - 1);
}
if (in->instructions[i].type == STRUCT) {
count++;
counter++;
}
if (in->instructions[i].type == ENDSTRUCT) {
count--;
counter--;
}
GroundInstruction structInstruction = copyGroundInstruction(&in->instructions[i]);
addInstructionToProgram(&gp, structInstruction);
i++;
}
i--;
GroundValue gv = {
.type = STRUCTVAL,
.data.structVal = malloc(sizeof(GroundStruct))
};
*gv.data.structVal = parseStruct(&gp, &scope, errorOffset);
addVariable(scope.variables, name, gv);
}
if (in->instructions[i].type == PAUSE || instructionsToPause == 0) {
printf("Paused execution\n");
@@ -784,46 +801,12 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
GroundInstruction copied_inst = copyGroundInstruction(&inst);
GroundInstruction* in = &copied_inst;
// Insert variables prefixed with $
for (size_t i = 0; i < in->args.length; i++) {
if (in->args.args[i].type == VALREF) {
GroundVariable* variable = findVariable(*scope->variables, in->args.args[i].value.refName);
if (variable) {
// If there is a duplicator, call it (except when returning and getting fields)
if (variable->value.type == CUSTOM && in->type != RETURN && in->type != GETFIELD) {
GroundObject* obj = variable->value.data.customVal;
GroundObjectField* duplicator = findField(*obj, "duplicator");
if (duplicator != NULL) {
if (duplicator->value.type != FUNCTION) {
runtimeError(ARG_TYPE_MISMATCH, "duplicator is not a function", in, currentInstruction);
}
GroundInstruction gi = createGroundInstruction(CALLMETHOD);
addArgToInstruction(&gi, createRefGroundArg(DIRREF, in->args.args[i].value.refName));
addArgToInstruction(&gi, createRefGroundArg(FNREF, "duplicator"));
addArgToInstruction(&gi, createValueGroundArg(variable->value));
addArgToInstruction(&gi, createRefGroundArg(DIRREF, "__ground_tmp_duplicate"));
GroundValue gv = interpretGroundInstruction(gi, scope);
if (gv.type == ERROR) {
return gv;
}
GroundVariable* tmp = findVariable(*scope->variables, "__ground_tmp_duplicate");
if (tmp == NULL) {
runtimeError(FIXME, "Couldn't find temporary variable (this should never happen)", in, currentInstruction);
}
in->args.args[i].value.value = copyGroundValue(&tmp->value);
in->args.args[i].type = VALUE;
deleteVariable(scope->variables, tmp);
continue;
}
}
free(in->args.args[i].value.refName); // Free the strdup'd refName
in->args.args[i].value.value = copyGroundValue(&variable->value);
in->args.args[i].type = VALUE;
} else {
runtimeError(UNKNOWN_VARIABLE, NULL, in, currentInstruction);
}
}
GroundValue resolved = resolveInstructionVariables(in, scope);
if (resolved.type == ERROR) {
freeGroundInstruction(in);
return resolved;
}
switch (in->type) {
// We can safely ignore these instructions, as they have been preprocessed
case FUN: