Function arguments, start of scoping

This commit is contained in:
2025-08-22 13:52:26 +10:00
parent 50d83aa228
commit f7f3972248
2 changed files with 95 additions and 30 deletions

View File

@@ -239,13 +239,18 @@ struct Instruction {
vector<variant<Literal, ValueRef, ListRef, FunctionRef, TypeRef, Direct, Line>> args; vector<variant<Literal, ValueRef, ListRef, FunctionRef, TypeRef, Direct, Line>> args;
}; };
struct FnArg {
Direct ref;
Types type;
};
/* /*
Function struct Function struct
Contains information needed to run a Ground function. Contains information needed to run a Ground function.
*/ */
struct Function { struct Function {
Types returnType; Types returnType;
vector<pair<Direct, Types>> args; vector<FnArg> args;
vector<Instruction> instructions; vector<Instruction> instructions;
}; };
@@ -263,9 +268,9 @@ vector<Literal> fnArgs;
/* /*
localArgStack stack localArgStack stack
Contains the variables in a scope This keeps track of all the local arguments in functions that are being called.
*/ */
stack<vector<Literal>> localArgStack; stack<vector<Direct>> localArgStack;
/* /*
error function error function
@@ -376,6 +381,21 @@ Types getType(string in) {
return Types::Int; return Types::Int;
} }
/*
getLitType function
This function determines the type of a value inside a Literal based on the
holds_alternative() function. Returns a type from the Types enum class.
*/
Types getLitType(Literal in) {
if (holds_alternative<int>(in.val)) return Types::Int;
if (holds_alternative<double>(in.val)) return Types::Double;
if (holds_alternative<bool>(in.val)) return Types::Bool;
if (holds_alternative<string>(in.val)) return Types::String;
if (holds_alternative<char>(in.val)) return Types::Char;
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;
}
bool processingFunction = false; bool processingFunction = false;
string procFnName = ""; string procFnName = "";
@@ -1488,29 +1508,29 @@ Literal exec(vector<Instruction> in) {
error("Second argument of function must be a function reference"); error("Second argument of function must be a function reference");
} }
Types argType; // Parse function arguments (type-direct pairs)
Direct ref; if ((l.args.size() - 2) % 2 != 0) {
bool expectingType = true; error("Function arguments must be in type-direct pairs");
for (int m = 2; m < l.args.size(); m++) {
if (expectingType) {
if (holds_alternative<TypeRef>(l.args[m])) {
argType = get<TypeRef>(l.args[m]).type;
} else {
error("Functions expect a type reference, then a direct reference. Missing a type reference.");
}
} else {
if (holds_alternative<Direct>(l.args[m])) {
ref = get<Direct>(l.args[m]);
} else {
error("Functions expect a type reference, then a direct reference. Missing a direct reference.");
}
newFunction.args.push_back(pair(ref, argType));
}
expectingType = !expectingType;
} }
if (!expectingType) { for (int m = 2; m < l.args.size(); m += 2) {
error("Incomplete function definition, expecting a direct reference after type reference"); FnArg newArg;
// Get type
if (holds_alternative<TypeRef>(l.args[m])) {
newArg.type = get<TypeRef>(l.args[m]).type;
} else {
error("Expected type reference in function argument definition");
}
// Get direct reference
if (m + 1 < l.args.size() && holds_alternative<Direct>(l.args[m + 1])) {
newArg.ref = get<Direct>(l.args[m + 1]);
} else {
error("Expected direct reference after type reference in function argument definition");
}
newFunction.args.push_back(newArg);
} }
functions[fnName] = newFunction; functions[fnName] = newFunction;
@@ -1578,12 +1598,53 @@ Literal exec(vector<Instruction> in) {
error("Second argument of call must be a direct reference"); error("Second argument of call must be a direct reference");
} }
// 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()));
}
localArgStack.push(vector<Direct>());
// Create function arguments with type checking
for (int m = 0; m < functions[ref.fnName].args.size(); m++) {
FnArg arg = functions[ref.fnName].args[m];
// Type checking - now with error reporting
if (arg.type != getLitType(fnArgs[m])) {
error("Function " + ref.fnName + " argument " + to_string(m + 1) +
" type mismatch. Expected type does not match provided argument type.");
}
// Create the variable
variables[arg.ref.varName] = fnArgs[m];
localArgStack.top().push_back(arg.ref);
}
// Call the function
variables[returnRef.varName] = exec(functions[ref.fnName].instructions); variables[returnRef.varName] = exec(functions[ref.fnName].instructions);
// Remove variables that were declared in this scope
for (Direct delref : localArgStack.top()) {
variables.erase(delref.varName);
}
localArgStack.pop();
// Clear function arguments for next call
fnArgs.clear();
} }
break; break;
case Instructions::Use: case Instructions::Use:
cout << "Still to be implemented" << endl;
break; break;
case Instructions::Extern: case Instructions::Extern:
cout << "Still to be implemented" << endl;
break; break;
default: default:
cout << "Still to be implemented" << endl; cout << "Still to be implemented" << endl;

View File

@@ -1,10 +1,14 @@
fun -int !dingle -string &silly fun -int !dingle -string &silly
stdlnout "This is inside the function" stdlnout "This is inside the function"
stdout "The function argument is "
stdlnout $silly
return 10 return 10
endfun endfun
stdlnout "This is outside the function" stdlnout "This is outside the function"
pusharg "heheheha"
call !dingle &var call !dingle &var
stdout "Function returned "
stdlnout $var stdlnout $var