forked from ground/ground
Start work on lists
This commit is contained in:
1
Bobfile
1
Bobfile
@@ -1,5 +1,4 @@
|
|||||||
compiler "g++";
|
compiler "g++";
|
||||||
binary "ground";
|
binary "ground";
|
||||||
source "src/main.cpp";
|
source "src/main.cpp";
|
||||||
flag "O3";
|
|
||||||
compile;
|
compile;
|
||||||
|
@@ -32,6 +32,18 @@ Reference a line (a line reference) with a percent symbol before a line number:
|
|||||||
jump %10
|
jump %10
|
||||||
```
|
```
|
||||||
|
|
||||||
|
(WORK IN PROGRESS) Alternatively, set a label and jump to that (setting labels will be discussed below):
|
||||||
|
|
||||||
|
```
|
||||||
|
jump %myLabel
|
||||||
|
```
|
||||||
|
|
||||||
|
Reference a list (a list reference) with an asterisk:
|
||||||
|
|
||||||
|
```
|
||||||
|
setlist *myList $value1 $value2 # and so on
|
||||||
|
```
|
||||||
|
|
||||||
### Keywords
|
### Keywords
|
||||||
|
|
||||||
Note: &var can be replaced with any direct reference. $value can be replaced with a literal value or a value reference. %1 can be replaced with a line reference.
|
Note: &var can be replaced with any direct reference. $value can be replaced with a literal value or a value reference. %1 can be replaced with a line reference.
|
||||||
@@ -54,7 +66,7 @@ Usage: `jump %1`
|
|||||||
|
|
||||||
Ends the program. Requires an integer for a status code.
|
Ends the program. Requires an integer for a status code.
|
||||||
|
|
||||||
Usage: `end $value`
|
Usage: `end $intvalue`
|
||||||
|
|
||||||
#### stdin
|
#### stdin
|
||||||
|
|
||||||
@@ -80,6 +92,30 @@ Allows you to set a variable to a value.
|
|||||||
|
|
||||||
Usage: `set &var $value`
|
Usage: `set &var $value`
|
||||||
|
|
||||||
|
#### setlist
|
||||||
|
|
||||||
|
Allows you to initialize a list.
|
||||||
|
|
||||||
|
Usage: `setlist *list $value1 $value2 $value3...`
|
||||||
|
|
||||||
|
#### setlistat (WORK IN PROGRESS)
|
||||||
|
|
||||||
|
Sets a list item at an index. The item at the index must already exist. Lists are index 0.
|
||||||
|
|
||||||
|
Usage: `setlistat *list $intvalue $value`
|
||||||
|
|
||||||
|
#### getlistat
|
||||||
|
|
||||||
|
Gets a list item at an index, and puts it in the variable provided. The item at the index must already exist. Lists are index 0.
|
||||||
|
|
||||||
|
Usage: `getlistat *list $intvalue &var`
|
||||||
|
|
||||||
|
#### getlistsize
|
||||||
|
|
||||||
|
Gets the size of a list and puts it in the variable provided.
|
||||||
|
|
||||||
|
Usage: `getlistsize *list &var`
|
||||||
|
|
||||||
#### add
|
#### add
|
||||||
|
|
||||||
Adds two numbers. Numbers mean an integer or a double. Outputs to a direct reference.
|
Adds two numbers. Numbers mean an integer or a double. Outputs to a direct reference.
|
||||||
|
189
src/main.cpp
189
src/main.cpp
@@ -49,7 +49,12 @@ using namespace std;
|
|||||||
function, interpreter function, Instruction struct
|
function, interpreter function, Instruction struct
|
||||||
*/
|
*/
|
||||||
enum class Instructions {
|
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
|
See also parser function
|
||||||
*/
|
*/
|
||||||
enum class Types {
|
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;
|
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
|
variables map
|
||||||
Contains all variables made while running the program. See also Literal struct.
|
Contains all variables made while running the program. See also Literal struct.
|
||||||
*/
|
*/
|
||||||
map<string, Literal> variables;
|
map<string, Literal> variables;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
lists map
|
||||||
|
Contains all lists made while running the program. See also List struct.
|
||||||
|
*/
|
||||||
|
map<string, List> lists;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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
|
||||||
@@ -161,7 +215,7 @@ struct Line {
|
|||||||
*/
|
*/
|
||||||
struct Instruction {
|
struct Instruction {
|
||||||
Instructions inst = Instructions::Empty;
|
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) {
|
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;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +301,7 @@ Types getType(string in) {
|
|||||||
if (isValue(in)) return Types::Value;
|
if (isValue(in)) return Types::Value;
|
||||||
if (isDirect(in)) return Types::Direct;
|
if (isDirect(in)) return Types::Direct;
|
||||||
if (isLine(in)) return Types::Line;
|
if (isLine(in)) return Types::Line;
|
||||||
|
if (isListRef(in)) return Types::ListRef;
|
||||||
error("Could not determine type of \"" + in + "\"");
|
error("Could not determine type of \"" + in + "\"");
|
||||||
return Types::Int;
|
return Types::Int;
|
||||||
}
|
}
|
||||||
@@ -368,6 +428,114 @@ void exec(vector<Instruction> in) {
|
|||||||
variables[varName] = varContents;
|
variables[varName] = varContents;
|
||||||
}
|
}
|
||||||
break;
|
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
|
stdin instruction
|
||||||
This instruction takes input from the standard character input via
|
This instruction takes input from the standard character input via
|
||||||
@@ -375,7 +543,7 @@ void exec(vector<Instruction> in) {
|
|||||||
*/
|
*/
|
||||||
case Instructions::Stdin:
|
case Instructions::Stdin:
|
||||||
if (l.args.size() < 1) {
|
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])) {
|
if (holds_alternative<Direct>(l.args[0])) {
|
||||||
string userIn;
|
string userIn;
|
||||||
@@ -980,6 +1148,10 @@ vector<Instruction> parser(vector<vector<string>> in) {
|
|||||||
else if (i == "inequal") newInst.inst = Instructions::Inequal;
|
else if (i == "inequal") newInst.inst = Instructions::Inequal;
|
||||||
else if (i == "end") newInst.inst = Instructions::End;
|
else if (i == "end") newInst.inst = Instructions::End;
|
||||||
else if (i == "set") newInst.inst = Instructions::Set;
|
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 error("Unexpected token: " + i);
|
||||||
} else {
|
} else {
|
||||||
Types type = getType(i);
|
Types type = getType(i);
|
||||||
@@ -1005,6 +1177,13 @@ vector<Instruction> parser(vector<vector<string>> in) {
|
|||||||
newInst.args.push_back(newLine);
|
newInst.args.push_back(newLine);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Types::ListRef:
|
||||||
|
{
|
||||||
|
ListRef newLR;
|
||||||
|
newLR.listName = i.substr(1);
|
||||||
|
newInst.args.push_back(newLR);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Types::String:
|
case Types::String:
|
||||||
{
|
{
|
||||||
Literal newLiteral;
|
Literal newLiteral;
|
||||||
|
9
tests/lists.grnd
Normal file
9
tests/lists.grnd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
setlist *favNums "hello" "there" "general" "kenobi"
|
||||||
|
set &count 0
|
||||||
|
getlistat *favNums $count &tmp
|
||||||
|
stdlnout $tmp
|
||||||
|
add $count 1 &count
|
||||||
|
getlistsize *favNums &tmp2
|
||||||
|
inequal $count $tmp2 &tmp3
|
||||||
|
if $tmp3 %3
|
||||||
|
stdlnout "finished!"
|
Reference in New Issue
Block a user