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); file = calloc(1, lSize + 1);
if (!file) { if (!file) {
fclose(fp); fclose(fp);
fputs("memory allocation fail when reading file", stderr); fprintf(stderr, "memory allocation fail when reading file %s\n", filename);
exit(1); exit(1);
} }

View File

@@ -373,11 +373,59 @@ GroundFunction* parseFunction(GroundProgram* in, size_t errorOffset) {
return function; 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 parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffset) {
GroundStruct gstruct = createStruct(); GroundStruct gstruct = createStruct();
for (size_t i = 0; i < in->size; i++) { for (size_t i = 0; i < in->size; i++) {
switch (in->instructions[i].type) { switch (in->instructions[i].type) {
case SET: { case SET: {
GroundValue resolved = resolveInstructionVariables(&in->instructions[i], scope);
if (resolved.type == ERROR) {
throwError(&resolved.data.errorVal);
}
if (in->instructions[i].args.length < 2) { if (in->instructions[i].args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", &in->instructions[i], i + errorOffset); 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; return gstruct;
} }
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) { GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
GroundLabel* labels = NULL; GroundLabel* labels = NULL;
GroundVariable* variables = NULL; GroundVariable* variables = NULL;
@@ -537,51 +584,11 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
} }
scope.isMainScope = isMainScopeGlobal; scope.isMainScope = isMainScopeGlobal;
isMainScopeGlobal = false; isMainScopeGlobal = false;
// Preprocess all labels, structs and functions // Preprocess all labels
for (size_t i = 0; i < in->size; i++) { for (size_t i = 0; i < in->size; i++) {
if (in->instructions[i].type == CREATELABEL) { if (in->instructions[i].type == CREATELABEL) {
addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i); 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++) { for (size_t i = 0; i < in->size; i++) {
if (in->instructions[i].type == FUN) { if (in->instructions[i].type == FUN) {
@@ -621,37 +628,47 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
addVariable(scope.variables, name, gv); 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) { if (in->instructions[i].type == STRUCT) {
int count = 1; if (in->instructions[i].args.length < 1) {
while (count > 0) { 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++; i++;
size_t counter = 1;
GroundProgram gp = createGroundProgram();
size_t errorOffset = i;
while (counter > 0) {
if (i >= in->size) { 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) { if (in->instructions[i].type == STRUCT) {
count++; counter++;
} }
if (in->instructions[i].type == ENDSTRUCT) { 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) { if (in->instructions[i].type == PAUSE || instructionsToPause == 0) {
printf("Paused execution\n"); printf("Paused execution\n");
@@ -784,46 +801,12 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
GroundInstruction copied_inst = copyGroundInstruction(&inst); GroundInstruction copied_inst = copyGroundInstruction(&inst);
GroundInstruction* in = &copied_inst; GroundInstruction* in = &copied_inst;
// Insert variables prefixed with $ GroundValue resolved = resolveInstructionVariables(in, scope);
for (size_t i = 0; i < in->args.length; i++) { if (resolved.type == ERROR) {
if (in->args.args[i].type == VALREF) { freeGroundInstruction(in);
GroundVariable* variable = findVariable(*scope->variables, in->args.args[i].value.refName); return resolved;
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);
}
}
} }
switch (in->type) { switch (in->type) {
// We can safely ignore these instructions, as they have been preprocessed // We can safely ignore these instructions, as they have been preprocessed
case FUN: case FUN: