forked from ground/ground
Function calling in structs
This commit is contained in:
80
src/main.cpp
80
src/main.cpp
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user