forked from ground/ground
Start work on lists
This commit is contained in:
189
src/main.cpp
189
src/main.cpp
@@ -49,7 +49,12 @@ using namespace std;
|
||||
function, interpreter function, Instruction struct
|
||||
*/
|
||||
enum class Instructions {
|
||||
Jump, Stdout, Stdin, Stdlnout, Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, If, End, Set, Empty
|
||||
Jump, If,
|
||||
Stdout, Stdin, Stdlnout,
|
||||
Add, Subtract, Multiply, Divide,
|
||||
Equal, Inequal, Greater, Lesser,
|
||||
End, Set, Empty,
|
||||
Setlist, Getlistat, Setlistat, Getlistsize
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -67,7 +72,7 @@ enum class Instructions {
|
||||
See also parser function
|
||||
*/
|
||||
enum class Types {
|
||||
Int, Double, String, Char, Bool, Value, Direct, Line
|
||||
Int, Double, String, Char, Bool, Value, Direct, Line, ListRef
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -86,12 +91,61 @@ struct Literal {
|
||||
variant<int, double, bool, string, char> val;
|
||||
};
|
||||
|
||||
/*
|
||||
List struct
|
||||
Contains literal values inside a vector. For example, if the following
|
||||
program was written:
|
||||
setlist #myNums 3 5 9 13
|
||||
The List struct which would be created and stored should look like this:
|
||||
{
|
||||
val = {
|
||||
Literal {
|
||||
val = 3
|
||||
},
|
||||
Literal {
|
||||
val = 5
|
||||
},
|
||||
Literal {
|
||||
val = 9
|
||||
},
|
||||
Literal {
|
||||
val = 13
|
||||
},
|
||||
}
|
||||
}
|
||||
All elements in the list must be of the same type. See also Literal struct.
|
||||
*/
|
||||
struct List {
|
||||
vector<Literal> val;
|
||||
};
|
||||
|
||||
/*
|
||||
ListRef struct
|
||||
Contains the name of a list referenced by the program. For example, if the
|
||||
following program was written:
|
||||
setlist #myNums 3 5 9 13
|
||||
The ListRef struct should look like this:
|
||||
{
|
||||
listName = "myNums";
|
||||
}
|
||||
*/
|
||||
struct ListRef {
|
||||
string listName;
|
||||
};
|
||||
|
||||
/*
|
||||
variables map
|
||||
Contains all variables made while running the program. See also Literal struct.
|
||||
*/
|
||||
map<string, Literal> variables;
|
||||
|
||||
|
||||
/*
|
||||
lists map
|
||||
Contains all lists made while running the program. See also List struct.
|
||||
*/
|
||||
map<string, List> lists;
|
||||
|
||||
/*
|
||||
ValueRef struct
|
||||
If the program being executed makes a value reference, it is stored in a ValueRef
|
||||
@@ -161,7 +215,7 @@ struct Line {
|
||||
*/
|
||||
struct Instruction {
|
||||
Instructions inst = Instructions::Empty;
|
||||
vector<variant<Literal, ValueRef, Direct, Line>> args;
|
||||
vector<variant<Literal, ValueRef, ListRef, Direct, Line>> args;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -224,7 +278,12 @@ bool isDirect(string in) {
|
||||
}
|
||||
|
||||
bool isLine(string in) {
|
||||
if (in.size() >= 1 && in[0] == '%' && isInt(in.substr(1))) return true;
|
||||
if (in.size() >= 1 && in[0] == '%') return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool isListRef(string in) {
|
||||
if (in.size() >= 1 && in[0] == '*') return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
@@ -242,6 +301,7 @@ Types getType(string in) {
|
||||
if (isValue(in)) return Types::Value;
|
||||
if (isDirect(in)) return Types::Direct;
|
||||
if (isLine(in)) return Types::Line;
|
||||
if (isListRef(in)) return Types::ListRef;
|
||||
error("Could not determine type of \"" + in + "\"");
|
||||
return Types::Int;
|
||||
}
|
||||
@@ -368,6 +428,114 @@ void exec(vector<Instruction> in) {
|
||||
variables[varName] = varContents;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
setlist instruction
|
||||
This instruction takes a potentially infinite amount of arguments and
|
||||
saves them to a list (vector) with name listName.
|
||||
*/
|
||||
case Instructions::Setlist:
|
||||
if (l.args.size() < 2) {
|
||||
error("Could not find all arguments required for Setlist inbuilt");
|
||||
}
|
||||
{
|
||||
string listName;
|
||||
List listContents;
|
||||
|
||||
if (holds_alternative<ListRef>(l.args[0])) {
|
||||
listName = get<ListRef>(l.args[0]).listName;
|
||||
} else {
|
||||
error("First argument of setlist must be a list reference");
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
for (variant<Literal, ValueRef, ListRef, Direct, Line> k : l.args) {
|
||||
if (holds_alternative<Literal>(k)) {
|
||||
listContents.val.push_back(get<Literal>(k));
|
||||
} else {
|
||||
if (!first) error("All arguments after first in setlist must be values");
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
lists[listName] = listContents;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
getlistat instruction
|
||||
This instruction gets a list item from a list and an index and saves the
|
||||
value to a variable.
|
||||
*/
|
||||
case Instructions::Getlistat:
|
||||
if (l.args.size() < 3) {
|
||||
error("Could not find all arguments required for Getlistat inbuilt");
|
||||
}
|
||||
{
|
||||
ListRef listref;
|
||||
int ref;
|
||||
Direct var;
|
||||
|
||||
if (holds_alternative<ListRef>(l.args[0])) {
|
||||
listref = get<ListRef>(l.args[0]);
|
||||
} else {
|
||||
error("First argument of getlistat must be a list reference");
|
||||
}
|
||||
|
||||
if (holds_alternative<Literal>(l.args[1])) {
|
||||
if (holds_alternative<int>(get<Literal>(l.args[1]).val)) {
|
||||
ref = get<int>(get<Literal>(l.args[1]).val);
|
||||
} else {
|
||||
error("Second argument of getlistat must be an integer literal");
|
||||
}
|
||||
} else {
|
||||
error("Second argument of getlistat must be an integer literal");
|
||||
}
|
||||
|
||||
if (holds_alternative<Direct>(l.args[2])) {
|
||||
var = get<Direct>(l.args[2]);
|
||||
} else {
|
||||
error("Third argument of getlistat must be a direct reference");
|
||||
}
|
||||
|
||||
if (lists.find(listref.listName) != lists.end()) {
|
||||
if (lists[listref.listName].val.size() > ref) {
|
||||
variables[var.varName] = lists[listref.listName].val[ref];
|
||||
} else {
|
||||
error("Index " + to_string(ref) + " out of range of list " + listref.listName);
|
||||
}
|
||||
} else {
|
||||
error("Unknown list: " + listref.listName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instructions::Getlistsize:
|
||||
if (l.args.size() < 2) {
|
||||
error("Could not find all arguments required for Getlistsize inbuilt");
|
||||
}
|
||||
{
|
||||
ListRef ref;
|
||||
Direct var;
|
||||
|
||||
if (holds_alternative<ListRef>(l.args[0])) {
|
||||
ref = get<ListRef>(l.args[0]);
|
||||
} else {
|
||||
error("First argument of getlistsize must be a list reference");
|
||||
}
|
||||
|
||||
if (holds_alternative<Direct>(l.args[1])) {
|
||||
var = get<Direct>(l.args[1]);
|
||||
} else {
|
||||
error("Second argument of getlistsize must be a direct reference");
|
||||
}
|
||||
|
||||
Literal newLit;
|
||||
if (lists.find(ref.listName) != lists.end()) {
|
||||
newLit.val = int(lists[ref.listName].val.size());
|
||||
variables[var.varName] = newLit;
|
||||
} else {
|
||||
error("Couldn't find the list " + ref.listName);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
/*
|
||||
stdin instruction
|
||||
This instruction takes input from the standard character input via
|
||||
@@ -375,7 +543,7 @@ void exec(vector<Instruction> in) {
|
||||
*/
|
||||
case Instructions::Stdin:
|
||||
if (l.args.size() < 1) {
|
||||
error("Could not find all arguments require for Stdin inbuilt");
|
||||
error("Could not find all arguments required for Stdin inbuilt");
|
||||
}
|
||||
if (holds_alternative<Direct>(l.args[0])) {
|
||||
string userIn;
|
||||
@@ -980,6 +1148,10 @@ vector<Instruction> parser(vector<vector<string>> in) {
|
||||
else if (i == "inequal") newInst.inst = Instructions::Inequal;
|
||||
else if (i == "end") newInst.inst = Instructions::End;
|
||||
else if (i == "set") newInst.inst = Instructions::Set;
|
||||
else if (i == "setlist") newInst.inst = Instructions::Setlist;
|
||||
else if (i == "setlistat") newInst.inst = Instructions::Setlistat;
|
||||
else if (i == "getlistat") newInst.inst = Instructions::Getlistat;
|
||||
else if (i == "getlistsize") newInst.inst = Instructions::Getlistsize;
|
||||
else error("Unexpected token: " + i);
|
||||
} else {
|
||||
Types type = getType(i);
|
||||
@@ -1005,6 +1177,13 @@ vector<Instruction> parser(vector<vector<string>> in) {
|
||||
newInst.args.push_back(newLine);
|
||||
}
|
||||
break;
|
||||
case Types::ListRef:
|
||||
{
|
||||
ListRef newLR;
|
||||
newLR.listName = i.substr(1);
|
||||
newInst.args.push_back(newLR);
|
||||
}
|
||||
break;
|
||||
case Types::String:
|
||||
{
|
||||
Literal newLiteral;
|
||||
|
Reference in New Issue
Block a user