Function declarations

This commit is contained in:
2025-08-13 09:40:03 +10:00
parent 52eadaa9c3
commit 4cd4d9080d
2 changed files with 104 additions and 16 deletions

View File

@@ -144,15 +144,6 @@ struct TypeRef {
struct FunctionRef {
string fnName;
};
/*
Function struct
Contains information needed to run a Ground function.
*/
struct Function {
int startPos;
Types returnType;
vector<pair<Direct, Types>> args;
};
/*
ListRef struct
@@ -187,12 +178,6 @@ map<string, List> lists;
*/
map<string, int> labels;
/*
functions map
Contains the positions of functions and types of their values
*/
map<string, Function> functions;
/*
ValueRef struct
If the program being executed makes a value reference, it is stored in a ValueRef
@@ -253,6 +238,22 @@ struct Instruction {
vector<variant<Literal, ValueRef, ListRef, FunctionRef, TypeRef, Direct, Line>> args;
};
/*
Function struct
Contains information needed to run a Ground function.
*/
struct Function {
Types returnType;
vector<pair<Direct, Types>> args;
vector<Instruction> instructions;
};
/*
functions map
Contains the code of functions and types of their values
*/
map<string, Function> functions;
/*
error function
Takes a string (which is a debug message) and prints it to the console, letting the
@@ -368,9 +369,23 @@ Types getType(string in) {
function below) and acts upon their properties. This is the main interpreter
function for the program.
*/
bool processingFunction = false;
string procFnName = "";
void exec(vector<Instruction> in) {
for (int i = 0; i < in.size(); i++) {
Instruction l = in[i];
if (processingFunction) {
if (l.inst == Instructions::Endfun) {
processingFunction = false;
procFnName = "";
continue;
} else {
functions[procFnName].instructions.push_back(l);
continue;
}
}
// Pre process value references and labels
for (int j = 0; j < l.args.size(); j++) {
if (holds_alternative<ValueRef>(l.args[j])) {
@@ -1386,7 +1401,7 @@ void exec(vector<Instruction> in) {
}
break;
/*
end instructoin
end instruction
Ends execution of the code, eith the status code provided.
*/
case Instructions::End:
@@ -1403,14 +1418,78 @@ void exec(vector<Instruction> in) {
error("First argument of end must be an int value");
}
break;
/*
fun instruction
Allows functions to be defined.
*/
case Instructions::Fun:
if (l.args.size() < 3) {
error("Could not find all arguments required for Fun inbuilt");
}
{
Function newFunction;
if (holds_alternative<TypeRef>(l.args[0])) {
newFunction.returnType = get<TypeRef>(l.args[0]).type;
} else {
error("First argument of function must be a type reference");
}
string fnName;
if (holds_alternative<FunctionRef>(l.args[1])) {
fnName = get<FunctionRef>(l.args[1]).fnName;
} else {
error("Second argument of function must be a function reference");
}
Types argType;
Direct ref;
bool expectingType = true;
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) {
error("Incomplete function definition, expecting a direct reference after type reference");
}
functions[fnName] = newFunction;
processingFunction = true;
procFnName = fnName;
}
break;
/*
return instruction
Exits a function.
*/
case Instructions::Return:
break;
/*
endfun instruction
This should not be reached during normal execution.
*/
case Instructions::Endfun:
error("No function is being defined. Cannot end function declaration here");
break;
case Instructions::Pusharg:
break;
case Instructions::Local:
break;
case Instructions::Call:
break;
case Instructions::Use:
@@ -1580,6 +1659,8 @@ vector<Instruction> parser(vector<vector<string>> in) {
else if (type == "double") newType.type = Types::Double;
else if (type == "int") newType.type = Types::Int;
else if (type == "bool") newType.type = Types::Bool;
else error("Ground could not find type. This is an error with the interpreter, not your code. This line of code should never be reached.");
newInst.args.push_back(newType);
}
break;
case Types::Function:
@@ -1588,6 +1669,7 @@ vector<Instruction> parser(vector<vector<string>> in) {
newFunction.fnName = i.substr(1);
newInst.args.push_back(newFunction);
}
break;
case Types::Line:
{
Line newLine;

6
tests/functions.grnd Normal file
View File

@@ -0,0 +1,6 @@
fun -int !dingle -string &silly
stdlnout &silly
return 10
endfun
stdlnout "This is outside the function"