forked from ground/ground
Function declarations
This commit is contained in:
114
src/main.cpp
114
src/main.cpp
@@ -144,15 +144,6 @@ struct TypeRef {
|
|||||||
struct FunctionRef {
|
struct FunctionRef {
|
||||||
string fnName;
|
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
|
ListRef struct
|
||||||
@@ -187,12 +178,6 @@ map<string, List> lists;
|
|||||||
*/
|
*/
|
||||||
map<string, int> labels;
|
map<string, int> labels;
|
||||||
|
|
||||||
/*
|
|
||||||
functions map
|
|
||||||
Contains the positions of functions and types of their values
|
|
||||||
*/
|
|
||||||
map<string, Function> functions;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ValueRef struct
|
ValueRef struct
|
||||||
If the program being executed makes a value reference, it is stored in a ValueRef
|
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;
|
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
|
error function
|
||||||
Takes a string (which is a debug message) and prints it to the console, letting the
|
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 below) and acts upon their properties. This is the main interpreter
|
||||||
function for the program.
|
function for the program.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
bool processingFunction = false;
|
||||||
|
string procFnName = "";
|
||||||
|
|
||||||
void exec(vector<Instruction> in) {
|
void exec(vector<Instruction> in) {
|
||||||
for (int i = 0; i < in.size(); i++) {
|
for (int i = 0; i < in.size(); i++) {
|
||||||
Instruction l = in[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
|
// Pre process value references and labels
|
||||||
for (int j = 0; j < l.args.size(); j++) {
|
for (int j = 0; j < l.args.size(); j++) {
|
||||||
if (holds_alternative<ValueRef>(l.args[j])) {
|
if (holds_alternative<ValueRef>(l.args[j])) {
|
||||||
@@ -1386,7 +1401,7 @@ void exec(vector<Instruction> in) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
end instructoin
|
end instruction
|
||||||
Ends execution of the code, eith the status code provided.
|
Ends execution of the code, eith the status code provided.
|
||||||
*/
|
*/
|
||||||
case Instructions::End:
|
case Instructions::End:
|
||||||
@@ -1403,14 +1418,78 @@ void exec(vector<Instruction> in) {
|
|||||||
error("First argument of end must be an int value");
|
error("First argument of end must be an int value");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
/*
|
||||||
|
fun instruction
|
||||||
|
Allows functions to be defined.
|
||||||
|
*/
|
||||||
case Instructions::Fun:
|
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;
|
break;
|
||||||
|
/*
|
||||||
|
return instruction
|
||||||
|
Exits a function.
|
||||||
|
*/
|
||||||
case Instructions::Return:
|
case Instructions::Return:
|
||||||
break;
|
break;
|
||||||
|
/*
|
||||||
|
endfun instruction
|
||||||
|
This should not be reached during normal execution.
|
||||||
|
*/
|
||||||
case Instructions::Endfun:
|
case Instructions::Endfun:
|
||||||
|
error("No function is being defined. Cannot end function declaration here");
|
||||||
break;
|
break;
|
||||||
case Instructions::Pusharg:
|
case Instructions::Pusharg:
|
||||||
break;
|
break;
|
||||||
|
case Instructions::Local:
|
||||||
|
break;
|
||||||
case Instructions::Call:
|
case Instructions::Call:
|
||||||
break;
|
break;
|
||||||
case Instructions::Use:
|
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 == "double") newType.type = Types::Double;
|
||||||
else if (type == "int") newType.type = Types::Int;
|
else if (type == "int") newType.type = Types::Int;
|
||||||
else if (type == "bool") newType.type = Types::Bool;
|
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;
|
break;
|
||||||
case Types::Function:
|
case Types::Function:
|
||||||
@@ -1588,6 +1669,7 @@ vector<Instruction> parser(vector<vector<string>> in) {
|
|||||||
newFunction.fnName = i.substr(1);
|
newFunction.fnName = i.substr(1);
|
||||||
newInst.args.push_back(newFunction);
|
newInst.args.push_back(newFunction);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case Types::Line:
|
case Types::Line:
|
||||||
{
|
{
|
||||||
Line newLine;
|
Line newLine;
|
||||||
|
6
tests/functions.grnd
Normal file
6
tests/functions.grnd
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
fun -int !dingle -string &silly
|
||||||
|
stdlnout &silly
|
||||||
|
return 10
|
||||||
|
endfun
|
||||||
|
|
||||||
|
stdlnout "This is outside the function"
|
Reference in New Issue
Block a user