5 Commits

6 changed files with 213 additions and 98 deletions

View File

@@ -15,7 +15,7 @@ def isnumber(num):
allstr = "" allstr = ""
color = "" color = ""
keywords = ["if", "jump", "end", "stdin", "stdout", "stdlnout", "set", "gettype", "exists", "setlist", "setlistat", "getlistat", "getlistsize", "listappend", "getstrsize", "getstrcharat", "add", "subtract", "multiply", "divide", "equal", "inequal", "not", "greater", "lesser", "stoi", "stod", "tostring", "fun", "return", "endfun", "pusharg", "call", "use", "extern"] keywords = ["if", "jump", "end", "stdin", "stdout", "stdlnout", "set", "gettype", "exists", "setlist", "setlistat", "getlistat", "getlistsize", "listappend", "getstrsize", "getstrcharat", "add", "subtract", "multiply", "divide", "equal", "inequal", "not", "greater", "lesser", "stoi", "stod", "tostring", "fun", "return", "endfun", "pusharg", "call", "use", "extern", "error"]
for line in thefile: for line in thefile:
allstr += line + " <br> " allstr += line + " <br> "

View File

@@ -13,7 +13,7 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/* /*
@@ -78,7 +78,7 @@ enum class Instructions {
Getstrcharat, Getstrsize, Getstrcharat, Getstrsize,
Stoi, Stod, Tostring, Stoi, Stod, Tostring,
Fun, Return, Endfun, Pusharg, Call, Local, Fun, Return, Endfun, Pusharg, Call, Local,
Use, Extern Use, Extern, Error, Catch, Try, Exception
}; };
/* /*
@@ -123,7 +123,7 @@ struct Literal;
val = 13 val = 13
}, },
} }
} }
All elements in the list must be of the same type. See also Literal struct. All elements in the list must be of the same type. See also Literal struct.
*/ */
struct List { struct List {
@@ -280,7 +280,7 @@ struct Function {
// C-compatible enum and types for developing libraries for Ground in C // C-compatible enum and types for developing libraries for Ground in C
typedef enum { typedef enum {
GROUND_INT, GROUND_INT,
GROUND_DOUBLE, GROUND_DOUBLE,
GROUND_BOOL, GROUND_BOOL,
GROUND_STRING, GROUND_STRING,
GROUND_CHAR GROUND_CHAR
@@ -305,7 +305,7 @@ map<string, Function> functions;
/* /*
fnArgs vector fnArgs vector
Containst the arguments to be passed to a function Containst the arguments to be passed to a function
*/ */
vector<Literal> fnArgs; vector<Literal> fnArgs;
@@ -367,10 +367,10 @@ Literal groundValueToLiteral(const GroundValue& gv) {
/* /*
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
user know what went wrong with the program. user know what went wrong with the program.
*/ */
void error(string in, int exitc = 1) { void error(string in, string errCode = "syntaxError", int exitc = 1) {
cout << "\033[31mError: \033[39m" << in << endl; cout << "\033[31m" + errCode + ": \033[39m" << in << endl;
exit(exitc); exit(exitc);
} }
@@ -441,7 +441,7 @@ bool isListRef(string in) {
bool isType(string in) { bool isType(string in) {
if (in.size() >= 1 && in[0] == '-') { if (in.size() >= 1 && in[0] == '-') {
string type = in.substr(1); string type = in.substr(1);
if (type == "string" || type == "char" || type == "bool" || type == "double" || type == "int" || type == "list") return true; if (type == "string" || type == "char" || type == "bool" || type == "double" || type == "int" || type == "list") return true;
else return false; else return false;
} else return false; } else return false;
} }
@@ -484,6 +484,7 @@ Types getLitType(Literal in) {
if (holds_alternative<bool>(in.val)) return Types::Bool; if (holds_alternative<bool>(in.val)) return Types::Bool;
if (holds_alternative<string>(in.val)) return Types::String; if (holds_alternative<string>(in.val)) return Types::String;
if (holds_alternative<char>(in.val)) return Types::Char; 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."); 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::Int;
} }
@@ -594,7 +595,42 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
cout << get<char>(get<Literal>(l.args[0]).val); cout << get<char>(get<Literal>(l.args[0]).val);
} }
else { else {
error("Couldn't print that"); error("Couldn't print that", "printError");
}
} else if (holds_alternative<ListRef>(l.args[0])) {
if (variables.find(get<ListRef>(l.args[0]).listName) != variables.end()) {
List list = get<List>(variables[get<ListRef>(l.args[0]).listName].val);
cout << "[";
for (int l = 0; l < list.val.size(); l++) {
if (holds_alternative<string>(list.val[l].val)) {
cout << '"' << get<string>(list.val[l].val) << '"';
}
else if (holds_alternative<int>(list.val[l].val)) {
cout << get<int>(list.val[l].val);
}
else if (holds_alternative<double>(list.val[l].val)) {
cout << get<double>(list.val[l].val);
}
else if (holds_alternative<bool>(list.val[l].val)) {
if (get<bool>(list.val[l].val) == true) {
cout << "true";
} else {
cout << "false";
}
}
else if (holds_alternative<char>(list.val[l].val)) {
cout << '\'' << get<char>(list.val[l].val) << '\'';
}
else {
error("Couldn't print that", "printError");
}
if (l != list.val.size() - 1) {
cout << ", ";
}
}
cout << "]";
} else {
error("Couldn't find list named " + get<ListRef>(l.args[0]).listName);
} }
} else { } else {
error("Argument of stdlnout must be a value (literal or a value reference)"); error("Argument of stdlnout must be a value (literal or a value reference)");
@@ -630,12 +666,78 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
cout << get<char>(get<Literal>(l.args[0]).val) << endl; cout << get<char>(get<Literal>(l.args[0]).val) << endl;
} }
else { else {
error("Couldn't print that"); error("Couldn't print that", "printError");
}
} else if (holds_alternative<ListRef>(l.args[0])) {
if (variables.find(get<ListRef>(l.args[0]).listName) != variables.end()) {
List list = get<List>(variables[get<ListRef>(l.args[0]).listName].val);
cout << "[";
for (int l = 0; l < list.val.size(); l++) {
if (holds_alternative<string>(list.val[l].val)) {
cout << '"' << get<string>(list.val[l].val) << '"';
}
else if (holds_alternative<int>(list.val[l].val)) {
cout << get<int>(list.val[l].val);
}
else if (holds_alternative<double>(list.val[l].val)) {
cout << get<double>(list.val[l].val);
}
else if (holds_alternative<bool>(list.val[l].val)) {
if (get<bool>(list.val[l].val) == true) {
cout << "true";
} else {
cout << "false";
}
}
else if (holds_alternative<char>(list.val[l].val)) {
cout << '\'' << get<char>(list.val[l].val) << '\'';
}
else {
error("Couldn't print that", "printError");
}
if (l != list.val.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
} else {
error("Couldn't find list named " + get<ListRef>(l.args[0]).listName);
} }
} else { } else {
error("Argument of stdlnout must be a value (literal or a value reference)"); error("Argument of stdlnout must be a value (literal or a value reference) or a list reference");
} }
break; break;
/*
error instruction
This instruction outputs a custom error message.
*/
case Instructions::Error:
if (l.args.size() < 2) {
error("Could not find arguments for Error inbuilt");
}
if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<string>(get<Literal>(l.args[0]).val) && holds_alternative<string>(get<Literal>(l.args[1]).val)) {
error(get<string>(get<Literal>(l.args[0]).val), get<string>(get<Literal>(l.args[1]).val));
} else {
error("Argument of error must be a string");
}
} else {
error("Argument of error must be a string");
}
break;
/*
catch instruction
This instruction ensures that errors in programs are caught and dealt with appropriately.
*/
case Instructions::Catch:
if (l.args.size() < 2) {
error("Could not find all arguments for Catch inbuilt");
}
if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
}
}
/* /*
set instruction set instruction
This instruction sets a variable to a provided value. This instruction sets a variable to a provided value.
@@ -659,7 +761,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else { } else {
error("Second argument of set must be a value (literal or value reference)"); error("Second argument of set must be a value (literal or value reference)");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = varContents; variables[varRef.varName] = varContents;
} }
@@ -718,7 +820,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
if (holds_alternative<Literal>(l.args[1])) { if (holds_alternative<Literal>(l.args[1])) {
if (holds_alternative<int>(get<Literal>(l.args[1]).val)) { if (holds_alternative<int>(get<Literal>(l.args[1]).val)) {
ref = get<int>(get<Literal>(l.args[1]).val); ref = get<int>(get<Literal>(l.args[1]).val);
} else { } else {
error("Second argument of getlistat must be an integer literal"); error("Second argument of getlistat must be an integer literal");
} }
} else { } else {
@@ -737,7 +839,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
bool existed = variables.count(var.varName) > 0; bool existed = variables.count(var.varName) > 0;
variables[var.varName] = get<List>(variables[listref.listName].val).val[ref]; variables[var.varName] = get<List>(variables[listref.listName].val).val[ref];
} else { } else {
error("Index " + to_string(ref) + " out of range of list " + listref.listName); error("Index " + to_string(ref) + " out of range of list " + listref.listName, "rangeError");
} }
} else { } else {
error("Found a normal variable in place of a list"); error("Found a normal variable in place of a list");
@@ -774,7 +876,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
if (holds_alternative<Literal>(l.args[1])) { if (holds_alternative<Literal>(l.args[1])) {
if (holds_alternative<int>(get<Literal>(l.args[1]).val)) { if (holds_alternative<int>(get<Literal>(l.args[1]).val)) {
ref = get<int>(get<Literal>(l.args[1]).val); ref = get<int>(get<Literal>(l.args[1]).val);
} else { } else {
error("Second argument of getstrcharat must be an integer literal"); error("Second argument of getstrcharat must be an integer literal");
} }
} else { } else {
@@ -793,7 +895,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
bool existed = variables.count(var.varName) > 0; bool existed = variables.count(var.varName) > 0;
variables[var.varName] = newLit; variables[var.varName] = newLit;
} else { } else {
error("Index " + to_string(ref) + " out of range of string " + instr); error("Index " + to_string(ref) + " out of range of string " + instr, "rangeError");
} }
} }
break; break;
@@ -819,7 +921,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
if (holds_alternative<Literal>(l.args[1])) { if (holds_alternative<Literal>(l.args[1])) {
if (holds_alternative<int>(get<Literal>(l.args[1]).val)) { if (holds_alternative<int>(get<Literal>(l.args[1]).val)) {
ref = get<int>(get<Literal>(l.args[1]).val); ref = get<int>(get<Literal>(l.args[1]).val);
} else { } else {
error("Second argument of setlistat must be an integer literal"); error("Second argument of setlistat must be an integer literal");
} }
} else { } else {
@@ -838,7 +940,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
tmpList.val[ref] = value; tmpList.val[ref] = value;
variables[listref.listName].val = tmpList; variables[listref.listName].val = tmpList;
} else { } else {
error("Index " + to_string(ref) + " out of range of list " + listref.listName); error("Index " + to_string(ref) + " out of range of list " + listref.listName, "rangeError");
} }
} }
} else { } else {
@@ -893,7 +995,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
{ {
ListRef ref; ListRef ref;
Direct var; Direct var;
if (holds_alternative<ListRef>(l.args[0])) { if (holds_alternative<ListRef>(l.args[0])) {
ref = get<ListRef>(l.args[0]); ref = get<ListRef>(l.args[0]);
} else { } else {
@@ -914,7 +1016,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else { } else {
error("Couldn't find the list " + ref.listName); error("Couldn't find the list " + ref.listName);
} }
break; break;
} }
/* /*
@@ -928,7 +1030,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
{ {
string ref; string ref;
Direct var; Direct var;
if (holds_alternative<Literal>(l.args[0])) { if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<string>(get<Literal>(l.args[0]).val)) { if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
ref = get<string>(get<Literal>(l.args[0]).val); ref = get<string>(get<Literal>(l.args[0]).val);
@@ -949,7 +1051,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
newLit.val = int(ref.size()); newLit.val = int(ref.size());
bool existed = variables.count(var.varName) > 0; bool existed = variables.count(var.varName) > 0;
variables[var.varName] = newLit; variables[var.varName] = newLit;
break; break;
} }
/* /*
@@ -964,7 +1066,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
{ {
string toConv; string toConv;
Direct ref; Direct ref;
if (holds_alternative<Literal>(l.args[0])) { if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<string>(get<Literal>(l.args[0]).val)) { if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
toConv = get<string>(get<Literal>(l.args[0]).val); toConv = get<string>(get<Literal>(l.args[0]).val);
@@ -987,7 +1089,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
bool existed = variables.count(ref.varName) > 0; bool existed = variables.count(ref.varName) > 0;
variables[ref.varName] = newLit; variables[ref.varName] = newLit;
} else { } else {
error("Cannot convert the value " + toConv + " to an int"); error("Cannot convert the value " + toConv + " to an int", "conversionError");
} }
} }
break; break;
@@ -1003,7 +1105,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
{ {
string toConv; string toConv;
Direct ref; Direct ref;
if (holds_alternative<Literal>(l.args[0])) { if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<string>(get<Literal>(l.args[0]).val)) { if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
toConv = get<string>(get<Literal>(l.args[0]).val); toConv = get<string>(get<Literal>(l.args[0]).val);
@@ -1026,7 +1128,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
bool existed = variables.count(ref.varName) > 0; bool existed = variables.count(ref.varName) > 0;
variables[ref.varName] = newLit; variables[ref.varName] = newLit;
} else { } else {
error("Cannot convert the value " + toConv + " to a decimal"); error("Cannot convert the value " + toConv + " to a decimal", "conversionError");
} }
} }
break; break;
@@ -1041,7 +1143,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
{ {
Literal toConv; Literal toConv;
Direct ref; Direct ref;
if (holds_alternative<Literal>(l.args[0])) { if (holds_alternative<Literal>(l.args[0])) {
toConv = get<Literal>(l.args[0]); toConv = get<Literal>(l.args[0]);
} else { } else {
@@ -1069,7 +1171,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else { } else {
newLit.val = "false"; newLit.val = "false";
} }
} }
bool existed = variables.count(ref.varName) > 0; bool existed = variables.count(ref.varName) > 0;
variables[ref.varName] = newLit; variables[ref.varName] = newLit;
@@ -1148,9 +1250,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<char>(left.val) && holds_alternative<char>(right.val)) { } else if (holds_alternative<char>(left.val) && holds_alternative<char>(right.val)) {
final.val = string().append(&get<char>(left.val)).append(&get<char>(right.val)); final.val = string().append(&get<char>(left.val)).append(&get<char>(right.val));
} else { } else {
error("Cannot add those two values"); error("Cannot add those two values", "mathError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1198,9 +1300,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<double>(left.val) && holds_alternative<int>(right.val)) { } else if (holds_alternative<double>(left.val) && holds_alternative<int>(right.val)) {
final.val = get<double>(left.val) - double(get<int>(right.val)); final.val = get<double>(left.val) - double(get<int>(right.val));
} else { } else {
error("Cannot subtract those two values"); error("Cannot subtract those two values", "mathError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1248,9 +1350,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<double>(left.val) && holds_alternative<int>(right.val)) { } else if (holds_alternative<double>(left.val) && holds_alternative<int>(right.val)) {
final.val = get<double>(left.val) * double(get<int>(right.val)); final.val = get<double>(left.val) * double(get<int>(right.val));
} else { } else {
error("Cannot multiply those two values"); error("Cannot multiply those two values", "mathError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1291,12 +1393,12 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
// Ensure we aren't dividing by zero // Ensure we aren't dividing by zero
if (holds_alternative<int>(right.val)) { if (holds_alternative<int>(right.val)) {
if (get<int>(right.val) == 0) { if (get<int>(right.val) == 0) {
error("Division by zero is not allowed"); error("Division by zero is not allowed", "divisionByZeroError");
} }
} }
if (holds_alternative<double>(right.val)) { if (holds_alternative<double>(right.val)) {
if (get<double>(right.val) == 0) { if (get<double>(right.val) == 0) {
error("Division by zero is not allowed"); error("Division by zero is not allowed", "divisionByZeroError");
} }
} }
@@ -1310,9 +1412,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<double>(left.val) && holds_alternative<int>(right.val)) { } else if (holds_alternative<double>(left.val) && holds_alternative<int>(right.val)) {
final.val = get<double>(left.val) / double(get<int>(right.val)); final.val = get<double>(left.val) / double(get<int>(right.val));
} else { } else {
error("Cannot divide those two values"); error("Cannot divide those two values", "mathError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1366,9 +1468,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) { } else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) {
final.val = get<bool>(left.val) == get<bool>(right.val); final.val = get<bool>(left.val) == get<bool>(right.val);
} else { } else {
error("Cannot equal those two values"); error("Cannot equal those two values", "comparisonError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1422,9 +1524,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) { } else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) {
final.val = get<bool>(left.val) != get<bool>(right.val); final.val = get<bool>(left.val) != get<bool>(right.val);
} else { } else {
error("Cannot inequal those two values"); error("Cannot inequal those two values", "comparisonError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1441,7 +1543,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
Literal boolean; Literal boolean;
Direct varRef; Direct varRef;
if (holds_alternative<Literal>(l.args[0])) { if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<bool>(get<Literal>(l.args[0]).val)) { if (holds_alternative<bool>(get<Literal>(l.args[0]).val)) {
boolean.val = !(get<bool>(get<Literal>(l.args[0]).val)); boolean.val = !(get<bool>(get<Literal>(l.args[0]).val));
@@ -1511,9 +1613,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) { } else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) {
final.val = get<bool>(left.val) > get<bool>(right.val); final.val = get<bool>(left.val) > get<bool>(right.val);
} else { } else {
error("Cannot greater those two values"); error("Cannot greater those two values", "comparisonError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1567,9 +1669,9 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) { } else if (holds_alternative<bool>(left.val) && holds_alternative<bool>(right.val)) {
final.val = get<bool>(left.val) < get<bool>(right.val); final.val = get<bool>(left.val) < get<bool>(right.val);
} else { } else {
error("Cannot lesser those two values"); error("Cannot lesser those two values", "comparisonError");
} }
bool existed = variables.count(varRef.varName) > 0; bool existed = variables.count(varRef.varName) > 0;
variables[varRef.varName] = final; variables[varRef.varName] = final;
} }
@@ -1674,10 +1776,10 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
variables[ref.varName].val = "char"; variables[ref.varName].val = "char";
break; break;
default: default:
error("Could not get type?? This should never be reached. Please report this issue"); error("Could not get type?? This should never be reached. Please report this issue", "undefinedError");
break; break;
} }
} }
break; break;
@@ -1729,7 +1831,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} }
{ {
Function newFunction; Function newFunction;
if (holds_alternative<TypeRef>(l.args[0])) { if (holds_alternative<TypeRef>(l.args[0])) {
newFunction.returnType = get<TypeRef>(l.args[0]).type; newFunction.returnType = get<TypeRef>(l.args[0]).type;
} else { } else {
@@ -1737,7 +1839,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} }
string fnName; string fnName;
if (holds_alternative<FunctionRef>(l.args[1])) { if (holds_alternative<FunctionRef>(l.args[1])) {
fnName = get<FunctionRef>(l.args[1]).fnName; fnName = get<FunctionRef>(l.args[1]).fnName;
} else { } else {
@@ -1755,24 +1857,24 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
for (int m = 2; m < l.args.size(); m += 2) { for (int m = 2; m < l.args.size(); m += 2) {
FnArg newArg; FnArg newArg;
// Get type // Get type
if (holds_alternative<TypeRef>(l.args[m])) { if (holds_alternative<TypeRef>(l.args[m])) {
newArg.type = get<TypeRef>(l.args[m]).type; newArg.type = get<TypeRef>(l.args[m]).type;
} else { } else {
error("Expected type reference in function argument definition"); error("Expected type reference in function argument definition");
} }
// Get direct reference // Get direct reference
if (m + 1 < l.args.size() && holds_alternative<Direct>(l.args[m + 1])) { if (m + 1 < l.args.size() && holds_alternative<Direct>(l.args[m + 1])) {
newArg.ref = get<Direct>(l.args[m + 1]); newArg.ref = get<Direct>(l.args[m + 1]);
} else { } else {
error("Expected direct reference after type reference in function argument definition"); error("Expected direct reference after type reference in function argument definition");
} }
newFunction.args.push_back(newArg); newFunction.args.push_back(newArg);
} }
functions[fnName] = newFunction; functions[fnName] = newFunction;
processingFunction = true; processingFunction = true;
procFnName = fnName; procFnName = fnName;
@@ -1796,7 +1898,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
break; break;
/* /*
endfun instruction endfun instruction
This should not be reached during normal execution. 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"); error("No function is being defined. Cannot end function declaration here");
@@ -1826,12 +1928,12 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
if (l.args.size() < 2) { if (l.args.size() < 2) {
error("Could not find all arguments required for Call inbuilt"); error("Could not find all arguments required for Call inbuilt");
} }
FunctionRef ref; FunctionRef ref;
string returnRef; string returnRef;
bool expectList = true; bool expectList = true;
if (holds_alternative<FunctionRef>(l.args[0])) { if (holds_alternative<FunctionRef>(l.args[0])) {
ref = get<FunctionRef>(l.args[0]); ref = get<FunctionRef>(l.args[0]);
} else { } else {
@@ -1852,19 +1954,19 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
// Call external function // Call external function
typedef GroundValue (*ExtFunc)(GroundValue*, int); typedef GroundValue (*ExtFunc)(GroundValue*, int);
ExtFunc extFunc = (ExtFunc)externalFunctions[ref.fnName]; ExtFunc extFunc = (ExtFunc)externalFunctions[ref.fnName];
// Convert arguments // Convert arguments
vector<GroundValue> gvArgs; vector<GroundValue> gvArgs;
for (const Literal& arg : fnArgs) { for (const Literal& arg : fnArgs) {
gvArgs.push_back(literalToGroundValue(arg)); gvArgs.push_back(literalToGroundValue(arg));
} }
// Call function // Call function
GroundValue result = extFunc(gvArgs.data(), gvArgs.size()); GroundValue result = extFunc(gvArgs.data(), gvArgs.size());
// Convert result back // Convert result back
Literal resultLit = groundValueToLiteral(result); Literal resultLit = groundValueToLiteral(result);
// Clear arguments and store result // Clear arguments and store result
fnArgs.clear(); fnArgs.clear();
variables[returnRef] = resultLit; variables[returnRef] = resultLit;
@@ -1879,8 +1981,8 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
// Check argument count // Check argument count
if (fnArgs.size() != functions[ref.fnName].args.size()) { if (fnArgs.size() != functions[ref.fnName].args.size()) {
error("Function " + ref.fnName + " expects " + error("Function " + ref.fnName + " expects " +
to_string(functions[ref.fnName].args.size()) + to_string(functions[ref.fnName].args.size()) +
" arguments, got " + to_string(fnArgs.size())); " arguments, got " + to_string(fnArgs.size()));
} }
@@ -1890,17 +1992,17 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
// Create function arguments with type checking // Create function arguments with type checking
for (int m = 0; m < functions[ref.fnName].args.size(); m++) { for (int m = 0; m < functions[ref.fnName].args.size(); m++) {
FnArg arg = functions[ref.fnName].args[m]; FnArg arg = functions[ref.fnName].args[m];
// Type checking - now with error reporting // Type checking - now with error reporting
if (arg.type != getLitType(fnArgs[m])) { if (arg.type != getLitType(fnArgs[m])) {
error("Function " + ref.fnName + " argument " + to_string(m + 1) + error("Function " + ref.fnName + " argument " + to_string(m + 1) +
" type mismatch. Expected type does not match provided argument type."); " type mismatch. Expected type does not match provided argument type.", "typeError");
} }
// Create the variable // Create the variable
variables[arg.ref.varName] = fnArgs[m]; variables[arg.ref.varName] = fnArgs[m];
} }
// Clear function arguments for next call // Clear function arguments for next call
fnArgs.clear(); fnArgs.clear();
@@ -1932,7 +2034,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
} }
{ {
string useName; string useName;
if (holds_alternative<Literal>(l.args[0])) { if (holds_alternative<Literal>(l.args[0])) {
if (holds_alternative<string>(get<Literal>(l.args[0]).val)) { if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
useName = get<string>(get<Literal>(l.args[0]).val) + ".grnd"; useName = get<string>(get<Literal>(l.args[0]).val) + ".grnd";
@@ -1957,11 +2059,11 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
string groundLibsDir = getenv("GROUND_LIBS"); string groundLibsDir = getenv("GROUND_LIBS");
if (filesystem::exists(useName)) { if (filesystem::exists(useName)) {
// no need to do anything here
} else if (groundLibsDir != "" && filesystem::exists(groundLibsDir + useName)) { } else if (groundLibsDir != "" && filesystem::exists(groundLibsDir + useName + ".grnd")) {
useName = groundLibsDir + useName; useName = groundLibsDir + useName + ".grnd";
} else { } else {
error("Could not find external Ground library in $GROUND_LIBS or current directory."); error("Could not find external Ground library in $GROUND_LIBS (currently set to " + groundLibsDir +") or current directory.", "libraryError");
} }
ifstream file(useName); ifstream file(useName);
@@ -2018,7 +2120,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
// Check multiple locations for the library // Check multiple locations for the library
string libPath; string libPath;
bool found = false; bool found = false;
// Check GROUND_LIBS directory // Check GROUND_LIBS directory
const char* groundLibsDir = getenv("GROUND_LIBS"); const char* groundLibsDir = getenv("GROUND_LIBS");
if (groundLibsDir) { if (groundLibsDir) {
@@ -2033,16 +2135,16 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
found = true; found = true;
} }
} }
if (!found) { if (!found) {
error("Could not find external library: " + fullLibName + error("Could not find external library: " + fullLibName +
" (searched current directory and GROUND_LIBS)"); " (searched current directory and GROUND_LIBS)", "libraryError");
} }
// Try to open the library // Try to open the library
void* handle = DLOPEN(libPath.c_str()); void* handle = DLOPEN(libPath.c_str());
if (!handle) { if (!handle) {
error("Failed to load library " + libPath + ": " + string(DLERROR())); error("Failed to load library " + libPath + ": " + string(DLERROR()), "libraryError");
} }
// Store handle for cleanup later // Store handle for cleanup later
@@ -2056,7 +2158,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
GetFunctionFunc getFunction = (GetFunctionFunc)DLSYM(handle, "ground_get_function"); GetFunctionFunc getFunction = (GetFunctionFunc)DLSYM(handle, "ground_get_function");
if (!getFunctions || !getFunction) { if (!getFunctions || !getFunction) {
error("Library " + libName + " is not Ground-compatible (missing required functions: ground_get_functions or ground_get_function)"); error("Library " + libName + " is not Ground-compatible (missing required functions: ground_get_functions or ground_get_function)", "libraryError");
} }
// Optional initialization // Optional initialization
@@ -2071,7 +2173,7 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
if (!functionNames) { if (!functionNames) {
error("Library " + libName + " returned null function list"); error("Library " + libName + " returned null function list");
} }
int functionCount = 0; int functionCount = 0;
for (int i = 0; functionNames[i] != nullptr; i++) { for (int i = 0; functionNames[i] != nullptr; i++) {
void* funcPtr = getFunction(functionNames[i]); void* funcPtr = getFunction(functionNames[i]);
@@ -2079,12 +2181,12 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
externalFunctions[libName + ":" + string(functionNames[i])] = funcPtr; externalFunctions[libName + ":" + string(functionNames[i])] = funcPtr;
functionCount++; functionCount++;
} else { } else {
error("Failed to get function pointer for: " + string(functionNames[i])); error("Failed to get function pointer for: " + string(functionNames[i]), "libraryError");
} }
} }
if (functionCount == 0) { if (functionCount == 0) {
error("No functions were loaded from library: " + libName); error("No functions were loaded from library: " + libName, "libraryError");
} }
} }
break; break;
@@ -2142,7 +2244,7 @@ vector<vector<string>> lexer(string in) {
bool procString = false; bool procString = false;
bool procChar = false; bool procChar = false;
bool isComment = false; bool isComment = false;
for (char i : in) { for (char i : in) {
switch (i) { switch (i) {
case '"': case '"':
@@ -2212,7 +2314,7 @@ vector<vector<string>> lexer(string in) {
vector<Instruction> parser(vector<vector<string>> in) { vector<Instruction> parser(vector<vector<string>> in) {
vector<Instruction> out; vector<Instruction> out;
int lineNum = 0; int lineNum = 0;
for (vector<string> lineTokens : in) { for (vector<string> lineTokens : in) {
lineNum ++; lineNum ++;
Instruction newInst; Instruction newInst;
@@ -2221,7 +2323,7 @@ vector<Instruction> parser(vector<vector<string>> in) {
continue; continue;
}; };
bool firstInst = true; bool firstInst = true;
for (string i : lineTokens) { for (string i : lineTokens) {
if (firstInst) { if (firstInst) {
firstInst = false; firstInst = false;
@@ -2229,9 +2331,19 @@ vector<Instruction> parser(vector<vector<string>> in) {
newInst.isLabel = true; newInst.isLabel = true;
newInst.label.id = i.substr(1); newInst.label.id = i.substr(1);
} }
else if (isFunction(i)){
newInst.inst = Instructions::Call;
FunctionRef newFnRef;
newFnRef.fnName = i.substr(1);
newInst.args.push_back(newFnRef);
}
else if (i == "stdin") newInst.inst = Instructions::Stdin; else if (i == "stdin") newInst.inst = Instructions::Stdin;
else if (i == "stdout") newInst.inst = Instructions::Stdout; else if (i == "stdout") newInst.inst = Instructions::Stdout;
else if (i == "stdlnout") newInst.inst = Instructions::Stdlnout; else if (i == "stdlnout") newInst.inst = Instructions::Stdlnout;
else if (i == "error") newInst.inst = Instructions::Error;
else if (i == "try") newInst.inst = Instructions::Try;
else if (i == "catch") newInst.inst = Instructions::Catch;
else if (i == "exception") newInst.inst = Instructions::Exception;
else if (i == "jump") newInst.inst = Instructions::Jump; else if (i == "jump") newInst.inst = Instructions::Jump;
else if (i == "if") newInst.inst = Instructions::If; else if (i == "if") newInst.inst = Instructions::If;
else if (i == "add") newInst.inst = Instructions::Add; else if (i == "add") newInst.inst = Instructions::Add;
@@ -2295,7 +2407,7 @@ vector<Instruction> parser(vector<vector<string>> in) {
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 if (type == "list") newType.type = Types::List; else if (type == "list") newType.type = Types::List;
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."); 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.", "undefinedError");
newInst.args.push_back(newType); newInst.args.push_back(newType);
} }
break; break;
@@ -2303,7 +2415,7 @@ vector<Instruction> parser(vector<vector<string>> in) {
{ {
FunctionRef newFunction; FunctionRef newFunction;
newFunction.fnName = i.substr(1); newFunction.fnName = i.substr(1);
newInst.args.push_back(newFunction); newInst.args.push_back(newFunction);
} }
break; break;
case Types::Line: case Types::Line:
@@ -2366,10 +2478,10 @@ vector<Instruction> parser(vector<vector<string>> in) {
} }
break; break;
default: default:
error("This type should not be obtained in normal execution"); error("This type should not be obtained in normal execution", "undefinedError");
break; break;
} }
} }
} }
out.push_back(newInst); out.push_back(newInst);
} }
@@ -2396,7 +2508,7 @@ int main(int argc, char** argv) {
argsList.val.push_back(lit); argsList.val.push_back(lit);
} }
variables["args"].val = argsList; variables["args"].val = argsList;
ifstream file(argv[1]); ifstream file(argv[1]);
string lns; string lns;
string in; string in;

1
tests/error.grnd Normal file
View File

@@ -0,0 +1 @@
error "Hello, world!" "sillyError"

View File

@@ -14,7 +14,7 @@ fun -bool !jumpy
return true return true
endfun endfun
call !jumpy &tmp !jumpy &tmp
stdlnout "I called a function" stdlnout "I called a function"

View File

@@ -1,5 +1,6 @@
# A cool list # A cool list
setlist *favWords "hello" "there" "general" "kenobi" setlist *favWords "hello" "there" "general" "kenobi"
stdlnout *favWords
set &count 0 set &count 0
set &passedThrough true set &passedThrough true

View File

@@ -1,5 +1,6 @@
set &var 0 set &var 0
@jump
add 1 $var &var add 1 $var &var
stdlnout $var stdlnout $var
greater 1000 $var &cond greater 10000 $var &cond
if $cond %2 if $cond %jump