Function calling in structs

This commit is contained in:
2025-09-20 20:23:57 +10:00
parent 93eec33e60
commit d7b0c4d818
2 changed files with 77 additions and 26 deletions

View File

@@ -507,8 +507,7 @@ Types getLitType(Literal in) {
if (holds_alternative<string>(in.val)) return Types::String;
if (holds_alternative<char>(in.val)) return Types::Char;
if (holds_alternative<List>(in.val)) return Types::List;
error("Literal for some reason has a weird type. This is not an issue with your program, but an issue with the Ground interpreter.");
return Types::Int;
return Types::Other;
}
/*
@@ -2221,24 +2220,61 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
break;
}
// Check if function exists
if (functions.find(ref.fnName) == functions.end()) {
error("Function " + ref.fnName + " not found");
}
// Check argument count
if (fnArgs.size() != functions[ref.fnName].args.size()) {
error("Function " + ref.fnName + " expects " +
to_string(functions[ref.fnName].args.size()) +
" arguments, got " + to_string(fnArgs.size()));
}
// Create backup of variables to be restored
map<string, Literal> scopeBackup = variables;
Function fnToExec;
bool inStruct = false;
Struct structVal;
string structName;
// Check if function exists
if (functions.find(ref.fnName) == functions.end()) {
if (isReferencingStruct(ref.fnName)) {
string fnInStruct;
size_t dotPos = ref.fnName.find('.');
if (dotPos != string::npos) {
structName = ref.fnName.substr(0, dotPos);
fnInStruct = ref.fnName.substr(dotPos + 1);
if (variables.find(structName) != variables.end()) {
if (holds_alternative<Struct>(variables[structName].val)) {
structVal = get<Struct>(variables[structName].val);
if (structVal.functions.find(fnInStruct) != structVal.functions.end()) {
fnToExec = structVal.functions[fnInStruct];
inStruct = true;
} else {
error("Could not find function '" + fnInStruct + "' in struct '" + structName + "'");
}
for (auto &[key, value] : structVal.values) {
variables[key] = value;
}
} else {
error("Variable '" + structName + "' is not a struct");
}
} else {
error("Could not find struct '" + structName + "'");
}
} else {
error("Invalid struct member access syntax");
}
} else {
error("Function " + ref.fnName + " not found");
}
} else {
fnToExec = functions[ref.fnName];
}
// Check argument count
if (fnArgs.size() != fnToExec.args.size()) {
error("Function " + ref.fnName + " expects " +
to_string(fnToExec.args.size()) +
" arguments, got " + to_string(fnArgs.size()));
}
// Create function arguments with type checking
for (int m = 0; m < functions[ref.fnName].args.size(); m++) {
FnArg arg = functions[ref.fnName].args[m];
for (int m = 0; m < fnToExec.args.size(); m++) {
FnArg arg = fnToExec.args[m];
// Type checking - now with error reporting
if (arg.type != getLitType(fnArgs[m])) {
@@ -2257,12 +2293,22 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
preProcessLabels(functions[ref.fnName].instructions);
// Call the function
Literal retVal = exec(functions[ref.fnName].instructions, true);
Literal retVal = exec(fnToExec.instructions, true);
// If we were executing a function in a struct, add back values
if (inStruct) {
for (auto &[key, value] : structVal.values) {
structVal.values[key] = variables[key];
}
}
// Restore scope
variables = scopeBackup;
labelStack.pop();
// Add back the struct values
variables[structName].val = structVal;
// Now, assign the return value in the current scope.
if (expectList) {
setVal(returnRef, retVal);

View File

@@ -2,23 +2,28 @@ struct -point
init &xpos -int
init &ypos -int
fun -void !init -int &x -int &y
fun -int !init -int &x -int &y
set &xpos $x
set &ypos $y
return
return 0
endfun
fun -string !toString
# do stuff
return "placeholder"
endfun
fun -int !dingle
return 23
tostring $xpos &xposstr
tostring $ypos &yposstr
add "x: " $xposstr &str
add $str ", y: " &str
add $str $yposstr &str
return $str
endfun
endstruct
init &myPoint -point
set &myPoint.xpos 20
pusharg 30 15
!myPoint.init &out
println $myPoint.xpos
!myPoint.toString &out
println $out