From 4cd4d9080d60bb7e8638e7ef5a4fd792ecdaebdc Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Wed, 13 Aug 2025 09:40:03 +1000 Subject: [PATCH] Function declarations --- src/main.cpp | 114 +++++++++++++++++++++++++++++++++++++------ tests/functions.grnd | 6 +++ 2 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 tests/functions.grnd diff --git a/src/main.cpp b/src/main.cpp index c8d5e9b..a73f1fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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> args; -}; /* ListRef struct @@ -187,12 +178,6 @@ map lists; */ map labels; -/* - functions map - Contains the positions of functions and types of their values -*/ -map 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> args; }; +/* + Function struct + Contains information needed to run a Ground function. +*/ +struct Function { + Types returnType; + vector> args; + vector instructions; +}; + +/* + functions map + Contains the code of functions and types of their values +*/ +map 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 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(l.args[j])) { @@ -1386,7 +1401,7 @@ void exec(vector 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 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(l.args[0])) { + newFunction.returnType = get(l.args[0]).type; + } else { + error("First argument of function must be a type reference"); + } + + string fnName; + + if (holds_alternative(l.args[1])) { + fnName = get(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(l.args[m])) { + argType = get(l.args[m]).type; + } else { + error("Functions expect a type reference, then a direct reference. Missing a type reference."); + } + } else { + if (holds_alternative(l.args[m])) { + ref = get(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 parser(vector> 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 parser(vector> in) { newFunction.fnName = i.substr(1); newInst.args.push_back(newFunction); } + break; case Types::Line: { Line newLine; diff --git a/tests/functions.grnd b/tests/functions.grnd new file mode 100644 index 0000000..906f18d --- /dev/null +++ b/tests/functions.grnd @@ -0,0 +1,6 @@ +fun -int !dingle -string &silly +stdlnout &silly +return 10 +endfun + +stdlnout "This is outside the function"