Compare commits
	
		
			9 Commits
		
	
	
		
			0.0.1
			...
			3a8600b481
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3a8600b481 | |||
| c39967a72f | |||
| 163f85b896 | |||
| 09033cd432 | |||
| 566d3aa0fb | |||
| f8397e85d4 | |||
| 3f2482d7ea | |||
| 2e388c6e68 | |||
| f43f79b869 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1 +1,2 @@
 | 
				
			|||||||
ground
 | 
					ground
 | 
				
			||||||
 | 
					Bobfile
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								Bobfile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Bobfile
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
compiler "g++";
 | 
					compiler "g++";
 | 
				
			||||||
binary "ground";
 | 
					binary "ground";
 | 
				
			||||||
source "src/main.cpp";
 | 
					source "src/main.cpp";
 | 
				
			||||||
flag "O3";
 | 
					flag "Ofast";
 | 
				
			||||||
compile;
 | 
					compile;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* **Simple syntax:** Ground doesn't have very many features, and that's intentional. It makes Ground easy to learn, and keeps it speedy.
 | 
					* **Simple syntax:** Ground doesn't have very many features, and that's intentional. It makes Ground easy to learn, and keeps it speedy.
 | 
				
			||||||
* **Super speed:** Ground code is faster than Python and JavaScript, and nearly as fast as C++ and Rust, while still being interpreted. (Tested using tests/to1000.grnd)
 | 
					* **Super speed:** Ground code is faster than Python and JavaScript, and nearly as fast as C++ and Rust, while still being interpreted. (Tested using tests/to1000.grnd)
 | 
				
			||||||
* **Tiny interpreter:** Ground contains 761 lines of code (and 233 lines of comments) at the time of writing, and compiles in seconds.
 | 
					* **Tiny interpreter:** Ground contains 1154 lines of code (and 320 lines of comments) at the time of writing, and compiles in seconds.
 | 
				
			||||||
* **Portable:** Ground's code only uses features from the C++ standard library, using features from C++17 and prior.
 | 
					* **Portable:** Ground's code only uses features from the C++ standard library, using features from C++17 and prior.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## How do I get started?
 | 
					## How do I get started?
 | 
				
			||||||
@@ -16,7 +16,7 @@ Ground is an interpreter which processes and interprets Ground instructions. It
 | 
				
			|||||||
Clone the repo and compile with your favourite C++ compiler:
 | 
					Clone the repo and compile with your favourite C++ compiler:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
  g++ src/main.cpp -std=C++17 -O3 -o ground
 | 
					  g++ src/main.cpp -std=c++17 -O3 -o ground
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(You can omit the -std flag on systems which default to the latest standard, and the -O3 flag if you're fine with a slightly slower interpreter.)
 | 
					(You can omit the -std flag on systems which default to the latest standard, and the -O3 flag if you're fine with a slightly slower interpreter.)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										148
									
								
								docs/syntax.md
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								docs/syntax.md
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
## Ground Syntax Guide
 | 
					## Ground Syntax Guide
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### General syntax
 | 
					## General syntax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Ground uses simple instructions and arguments to run code.
 | 
					Ground uses simple instructions and arguments to run code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,12 +32,32 @@ Reference a line (a line reference) with a percent symbol before a line number:
 | 
				
			|||||||
  jump %10
 | 
					  jump %10
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Keywords
 | 
					Alternatively, set a label:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					  @myLabel   # The '@' symbol denotes setting 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note: In most of these functions, if a direct reference is used, the value outputted by that function will be avaliable at that variable. Any existing value inside that variable will be overwritten.
 | 
					Note: In most of these functions, if a direct reference is used, the value outputted by that function will be avaliable at that variable. Any existing value inside that variable will be overwritten.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Control Flow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### if
 | 
					#### if
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Make a decision based on a boolean. If the boolean is true, jumps to the line referenced.
 | 
					Make a decision based on a boolean. If the boolean is true, jumps to the line referenced.
 | 
				
			||||||
@@ -54,7 +74,9 @@ 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`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### I/O
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### stdin
 | 
					#### stdin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,12 +96,60 @@ Allows output to the console, appending a new line at the end.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Usage: `stdlnout $value`
 | 
					Usage: `stdlnout $value`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Variables and Lists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### set
 | 
					#### set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Allows you to set a variable to a value.
 | 
					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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### listappend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Appends an item to a list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `listappend *list $var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### String Operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### getstrsize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gets the size of a string and puts it in the variable provided.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `getstrsize $stringvalue &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### getstrcharat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Gets a character at a certain position in a string and saves it to a variable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `getstrcharat $stringvalue $intvalue &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Maths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 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.
 | 
				
			||||||
@@ -104,6 +174,8 @@ Divides two numbers. Numbers mean an integer or a double. Outputs to a direct re
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Usage: `divide $value $value &var`
 | 
					Usage: `divide $value $value &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Comparisons
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### equal
 | 
					#### equal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Checks if two values are equal. Outputs a boolean to a direct reference.
 | 
					Checks if two values are equal. Outputs a boolean to a direct reference.
 | 
				
			||||||
@@ -127,3 +199,73 @@ Usage: `greater $value $value &var`
 | 
				
			|||||||
Checks if the left value is lesser than the right value. Outputs a boolean to a direct reference.
 | 
					Checks if the left value is lesser than the right value. Outputs a boolean to a direct reference.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Usage: `lesser $value $value &var`
 | 
					Usage: `lesser $value $value &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Type Conversions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### stoi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Converts a string to an integer. Throws an error if the string cannot be turned into an integer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `stoi $stringvalue &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### stod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Converts a string to a double. Throws an error if the string cannot be turned into a double.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `stod $stringvalue &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### tostring
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Converts any type to a string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `tostring $value &var`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Functions and function specific features (ALL WORK IN PROGRESS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some symbols specific to this category:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `!function`: A function reference
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `-type`: A type reference. Can be one of the following: "-string", "-char", "-int", "-double", "-bool"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### fun 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Defines a function. All code between `fun` and `endfun` will be included in the function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `fun !functionname -type &var -type &var -type &var   # and so on...`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### endfun
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ends a function definition. When a function reaches the end the argument list will be cleared.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `endfun`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### pusharg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Adds a value to the argument list which will be passed to the function when it is called.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `pusharg $value`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### call
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Calls a function, with all the arguments in the argument list. The return value will be put in the specified variable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `call !function &var
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Interacting with Libraries (ALL WORK IN PROGRESS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Attempts to import another Ground program. Gets inserted wherever the use statement is. Any code (including code outside function declarations) will be executed. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: Ground will check the directory where the program is stored when trying to find imported programs. If that fails, it will check the directory set in the $GROUND_PATH environment variable set by your system. The '.grnd' extension is appended automatically.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `use $stringvalue`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### extern
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Attempts to import a shared object library written for Ground. All functions in the external library will be usable with `call`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note: Ground will check the directory where the program is stored when trying to find external programs. If that fails, it will check the directory set in the $GROUND_PATH environment variable set by your system. The '.so', '.dll', etc  extension is appended automatically.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usage: `extern $stringvalue`
 | 
				
			||||||
							
								
								
									
										546
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										546
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -20,8 +20,8 @@
 | 
				
			|||||||
    With the licence out of the way, let's begin!
 | 
					    With the licence out of the way, let's begin!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ground is a programming language which takes some inspiration from
 | 
					    Ground is a programming language which takes some inspiration from
 | 
				
			||||||
    Assembly in it's design, but has higher level features (more types,
 | 
					    Assembly in its design, but has higher level features (more types,
 | 
				
			||||||
    simpler IO, easier variables, etc) which make it easy to use.
 | 
					    simpler IO, easier variables, etc) which makes it easy to use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ground works even better if you write a programming language that
 | 
					    Ground works even better if you write a programming language that
 | 
				
			||||||
    compiles to Ground code. Ground is designed to have a similar
 | 
					    compiles to Ground code. Ground is designed to have a similar
 | 
				
			||||||
@@ -49,7 +49,15 @@ 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, Listappend, Listprepend,
 | 
				
			||||||
 | 
					    Getstrcharat, Getstrsize,
 | 
				
			||||||
 | 
					    Stoi, Stod, Tostring,
 | 
				
			||||||
 | 
					    Fun, Endfun, Pusharg, Call
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -67,7 +75,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, Label
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -86,12 +94,67 @@ 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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					    labels map
 | 
				
			||||||
 | 
					    Contains all labels made in the program, for ease of jumping around the code.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					map<string, int> labels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
    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
 | 
				
			||||||
@@ -132,6 +195,8 @@ struct Direct {
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
struct Line {
 | 
					struct Line {
 | 
				
			||||||
    int lineNum;
 | 
					    int lineNum;
 | 
				
			||||||
 | 
					    bool isLabel = false;
 | 
				
			||||||
 | 
					    string label;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -161,7 +226,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;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -182,6 +247,7 @@ void error(string in, int exitc = 1) {
 | 
				
			|||||||
bool isInt(string in) {
 | 
					bool isInt(string in) {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        stoi(in);
 | 
					        stoi(in);
 | 
				
			||||||
 | 
					        if (stod(in) != stoi(in)) return false;
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    } catch (...) {
 | 
					    } catch (...) {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
@@ -223,7 +289,17 @@ 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 isLabel(string in) {
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -241,6 +317,8 @@ 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 (isLabel(in)) return Types::Label;
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -254,7 +332,7 @@ Types getType(string in) {
 | 
				
			|||||||
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];
 | 
				
			||||||
        // Pre process value references
 | 
					        // 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])) {
 | 
				
			||||||
                if (variables.find(get<ValueRef>(l.args[j]).varName) != variables.end()) {
 | 
					                if (variables.find(get<ValueRef>(l.args[j]).varName) != variables.end()) {
 | 
				
			||||||
@@ -262,6 +340,17 @@ void exec(vector<Instruction> in) {
 | 
				
			|||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    error("Could not find variable " + get<ValueRef>(l.args[j]).varName);
 | 
					                    error("Could not find variable " + get<ValueRef>(l.args[j]).varName);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            } else if (holds_alternative<Line>(l.args[j])) {
 | 
				
			||||||
 | 
					                Line ln = get<Line>(l.args[j]);
 | 
				
			||||||
 | 
					                if (ln.isLabel) {
 | 
				
			||||||
 | 
					                    if (labels.find(ln.label) != labels.end()) {
 | 
				
			||||||
 | 
					                        Line newLine;
 | 
				
			||||||
 | 
					                        newLine.lineNum = labels[ln.label];
 | 
				
			||||||
 | 
					                        l.args[j] = newLine;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Could not find label " + ln.label);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        switch (l.inst) {
 | 
					        switch (l.inst) {
 | 
				
			||||||
@@ -367,6 +456,399 @@ 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;
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                getstrcharat instruction
 | 
				
			||||||
 | 
					                This instruction gets a character from a string at an index and saves it
 | 
				
			||||||
 | 
					                to a variable.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Getstrcharat:
 | 
				
			||||||
 | 
					                if (l.args.size() < 3) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Getstrcharat inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    string instr;
 | 
				
			||||||
 | 
					                    int ref;
 | 
				
			||||||
 | 
					                    Direct var;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[0])) {
 | 
				
			||||||
 | 
					                        if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
 | 
				
			||||||
 | 
					                            instr = get<string>(get<Literal>(l.args[0]).val);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            error("First argument of getlistat must be a string literal");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("First argument of getlistat must be a string literal");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    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 (instr.size() > ref) {
 | 
				
			||||||
 | 
					                        Literal newLit;
 | 
				
			||||||
 | 
					                        newLit.val = instr[ref];
 | 
				
			||||||
 | 
					                        variables[var.varName] = newLit;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Index " + to_string(ref) + " out of range of string " + instr);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                setlistat instruction
 | 
				
			||||||
 | 
					                This instruction sets an item in a list to be a certain value.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Setlistat:
 | 
				
			||||||
 | 
					                if (l.args.size() < 3) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Setlistat inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ListRef listref;
 | 
				
			||||||
 | 
					                    int ref;
 | 
				
			||||||
 | 
					                    Literal value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<ListRef>(l.args[0])) {
 | 
				
			||||||
 | 
					                        listref = get<ListRef>(l.args[0]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("First argument of setlistat 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 setlistat must be an integer literal");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Second argument of setlistat must be an integer literal");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[2])) {
 | 
				
			||||||
 | 
					                        value = get<Literal>(l.args[2]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Third argument of setlistat must be a direct reference");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (lists.find(listref.listName) != lists.end()) {
 | 
				
			||||||
 | 
					                        if (lists[listref.listName].val.size() > ref) {
 | 
				
			||||||
 | 
					                            lists[listref.listName].val[ref] = value;
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            error("Index " + to_string(ref) + " out of range of list " + listref.listName);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Unknown list: " + listref.listName);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                listappend instruction
 | 
				
			||||||
 | 
					                This instruction appends an item to a list.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Listappend:
 | 
				
			||||||
 | 
					                if (l.args.size() < 2) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Listappend inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ListRef listref;
 | 
				
			||||||
 | 
					                    Literal value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<ListRef>(l.args[0])) {
 | 
				
			||||||
 | 
					                        listref = get<ListRef>(l.args[0]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Second argument of listappend must be a list reference");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[1])) {
 | 
				
			||||||
 | 
					                        value = get<Literal>(l.args[1]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Second argument of listappend must be a direct reference");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (lists.find(listref.listName) != lists.end()) {
 | 
				
			||||||
 | 
					                        lists[listref.listName].val.push_back(value);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Unknown list: " + listref.listName);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                getlistsize instruction
 | 
				
			||||||
 | 
					                This instruction saves the size of a list in a variable.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            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;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                getstrsize instruction
 | 
				
			||||||
 | 
					                This instruction saves the size of a string in a variable.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Getstrsize:
 | 
				
			||||||
 | 
					                if (l.args.size() < 2) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Getstrsize inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    string ref;
 | 
				
			||||||
 | 
					                    Direct var;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[0])) {
 | 
				
			||||||
 | 
					                        if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
 | 
				
			||||||
 | 
					                            ref = get<string>(get<Literal>(l.args[0]).val);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            error("First argument of getlistsize must be a string value");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("First argument of getlistsize must be a string value");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    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;
 | 
				
			||||||
 | 
					                    newLit.val = int(ref.size());
 | 
				
			||||||
 | 
					                    variables[var.varName] = newLit;
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                stoi instruction
 | 
				
			||||||
 | 
					                This function converts a string to an int, and saves it in a variable.
 | 
				
			||||||
 | 
					                If the string cannot be turned into an integer, there is an error.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Stoi:
 | 
				
			||||||
 | 
					                if (l.args.size() < 2) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Stoi inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    string toConv;
 | 
				
			||||||
 | 
					                    Direct ref;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[0])) {
 | 
				
			||||||
 | 
					                        if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
 | 
				
			||||||
 | 
					                            toConv = get<string>(get<Literal>(l.args[0]).val);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            error("First argument of stoi must be a string literal");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("First argument of stoi must be a string literal");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<Direct>(l.args[1])) {
 | 
				
			||||||
 | 
					                        ref = get<Direct>(l.args[1]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Second argument of stoi must be a direct reference");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (isInt(toConv)) {
 | 
				
			||||||
 | 
					                        Literal newLit;
 | 
				
			||||||
 | 
					                        newLit.val = stoi(toConv);
 | 
				
			||||||
 | 
					                        variables[ref.varName] = newLit;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Cannot convert the value " + toConv + " to an int");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                stod instruction
 | 
				
			||||||
 | 
					                This function converts a string to a decimal, and saves it in a variable.
 | 
				
			||||||
 | 
					                If the string cannot be turned into a decimal, there is an error.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Stod:
 | 
				
			||||||
 | 
					                if (l.args.size() < 2) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Stod inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    string toConv;
 | 
				
			||||||
 | 
					                    Direct ref;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[0])) {
 | 
				
			||||||
 | 
					                        if (holds_alternative<string>(get<Literal>(l.args[0]).val)) {
 | 
				
			||||||
 | 
					                            toConv = get<string>(get<Literal>(l.args[0]).val);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            error("First argument of stod must be a string literal");
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("First argument of stod must be a string literal");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<Direct>(l.args[1])) {
 | 
				
			||||||
 | 
					                        ref = get<Direct>(l.args[1]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Second argument of stod must be a direct reference");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (isDouble(toConv) || isInt(toConv)) {
 | 
				
			||||||
 | 
					                        Literal newLit;
 | 
				
			||||||
 | 
					                        newLit.val = stod(toConv);
 | 
				
			||||||
 | 
					                        variables[ref.varName] = newLit;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Cannot convert the value " + toConv + " to a decimal");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					                tostring instruction
 | 
				
			||||||
 | 
					                This function converts any type to a string, and saves it in a variable.
 | 
				
			||||||
 | 
					            */
 | 
				
			||||||
 | 
					            case Instructions::Tostring:
 | 
				
			||||||
 | 
					                if (l.args.size() < 2) {
 | 
				
			||||||
 | 
					                    error("Could not find all arguments required for Tostring inbuilt");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Literal toConv;
 | 
				
			||||||
 | 
					                    Direct ref;
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                    if (holds_alternative<Literal>(l.args[0])) {
 | 
				
			||||||
 | 
					                        toConv = get<Literal>(l.args[0]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("First argument of tostring must be a literal");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (holds_alternative<Direct>(l.args[1])) {
 | 
				
			||||||
 | 
					                        ref = get<Direct>(l.args[1]);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        error("Second argument of tostring must be a direct reference");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Literal newLit;
 | 
				
			||||||
 | 
					                    if (holds_alternative<int>(toConv.val)) {
 | 
				
			||||||
 | 
					                        newLit.val = to_string(get<int>(toConv.val));
 | 
				
			||||||
 | 
					                    } else if (holds_alternative<double>(toConv.val)) {
 | 
				
			||||||
 | 
					                        newLit.val = to_string(get<double>(toConv.val));
 | 
				
			||||||
 | 
					                    } else if (holds_alternative<string>(toConv.val)) {
 | 
				
			||||||
 | 
					                        newLit.val = get<string>(toConv.val);
 | 
				
			||||||
 | 
					                    } else if (holds_alternative<char>(toConv.val)) {
 | 
				
			||||||
 | 
					                        newLit.val = string().append(&get<char>(toConv.val));
 | 
				
			||||||
 | 
					                    } else if (holds_alternative<bool>(toConv.val)) {
 | 
				
			||||||
 | 
					                        if (get<bool>(toConv.val)) {
 | 
				
			||||||
 | 
					                            newLit.val = "true";
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            newLit.val = "false";
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    variables[ref.varName] = newLit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                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
 | 
				
			||||||
@@ -374,7 +856,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;
 | 
				
			||||||
@@ -430,6 +912,12 @@ void exec(vector<Instruction> in) {
 | 
				
			|||||||
                        final.val = get<double>(left.val) + double(get<int>(right.val));
 | 
					                        final.val = get<double>(left.val) + double(get<int>(right.val));
 | 
				
			||||||
                    } else if (holds_alternative<string>(left.val) && holds_alternative<string>(right.val)) {
 | 
					                    } else if (holds_alternative<string>(left.val) && holds_alternative<string>(right.val)) {
 | 
				
			||||||
                        final.val = get<string>(left.val) + get<string>(right.val);
 | 
					                        final.val = get<string>(left.val) + get<string>(right.val);
 | 
				
			||||||
 | 
					                    } else if (holds_alternative<string>(left.val) && holds_alternative<char>(right.val)) {
 | 
				
			||||||
 | 
					                        final.val = get<string>(left.val).append(&get<char>(right.val));
 | 
				
			||||||
 | 
					                    } else if (holds_alternative<char>(left.val) && holds_alternative<string>(right.val)) {
 | 
				
			||||||
 | 
					                        final.val = string().append(&get<char>(left.val)) + get<string>(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));
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        error("Cannot add those two values");
 | 
					                        error("Cannot add those two values");
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -955,16 +1443,25 @@ 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 = 1;
 | 
				
			||||||
    for (vector<string> lineTokens : in) {
 | 
					    for (vector<string> lineTokens : in) {
 | 
				
			||||||
        if (lineTokens.empty()) continue;
 | 
					        lineNum ++;
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        Instruction newInst;
 | 
					        Instruction newInst;
 | 
				
			||||||
 | 
					        if (lineTokens.empty()) {
 | 
				
			||||||
 | 
					            out.push_back(newInst);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        bool firstInst = true;
 | 
					        bool firstInst = true;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        for (string i : lineTokens) {
 | 
					        for (string i : lineTokens) {
 | 
				
			||||||
            if (firstInst) {
 | 
					            if (firstInst) {
 | 
				
			||||||
                firstInst = false;
 | 
					                firstInst = false;
 | 
				
			||||||
                if (i == "stdin") newInst.inst = Instructions::Stdin;
 | 
					                if (isLabel(i)) {
 | 
				
			||||||
 | 
					                    labels[i.substr(1)] = lineNum;
 | 
				
			||||||
 | 
					                    out.push_back(newInst);
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                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 == "jump") newInst.inst = Instructions::Jump;
 | 
					                else if (i == "jump") newInst.inst = Instructions::Jump;
 | 
				
			||||||
@@ -979,6 +1476,16 @@ 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 if (i == "listappend") newInst.inst = Instructions::Listappend;
 | 
				
			||||||
 | 
					                else if (i == "getstrsize") newInst.inst = Instructions::Getstrsize;
 | 
				
			||||||
 | 
					                else if (i == "getstrcharat") newInst.inst = Instructions::Getstrcharat;
 | 
				
			||||||
 | 
					                else if (i == "stoi") newInst.inst = Instructions::Stoi;
 | 
				
			||||||
 | 
					                else if (i == "stod") newInst.inst = Instructions::Stod;
 | 
				
			||||||
 | 
					                else if (i == "tostring") newInst.inst = Instructions::Tostring;
 | 
				
			||||||
                else error("Unexpected token: " + i);
 | 
					                else error("Unexpected token: " + i);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                Types type = getType(i);
 | 
					                Types type = getType(i);
 | 
				
			||||||
@@ -997,13 +1504,28 @@ vector<Instruction> parser(vector<vector<string>> in) {
 | 
				
			|||||||
                            newInst.args.push_back(newDirect);
 | 
					                            newInst.args.push_back(newDirect);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					                    case Types::Label:
 | 
				
			||||||
 | 
					                        error("Label should be defined as first token");
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
                    case Types::Line:
 | 
					                    case Types::Line:
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            Line newLine;
 | 
					                            Line newLine;
 | 
				
			||||||
                            newLine.lineNum = stoi(i.substr(1));
 | 
					                            if (isInt(i.substr(1))) newLine.lineNum = stoi(i.substr(1));
 | 
				
			||||||
 | 
					                            else {
 | 
				
			||||||
 | 
					                                newLine.isLabel = true;
 | 
				
			||||||
 | 
					                                newLine.label = i.substr(1);
 | 
				
			||||||
 | 
					                                newLine.lineNum = 0;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                            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;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										89
									
								
								tests/everything.grnd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								tests/everything.grnd
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					# I/O
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stdlnout "Hello there!"
 | 
				
			||||||
 | 
					stdout "What is your name? "
 | 
				
			||||||
 | 
					stdin &name
 | 
				
			||||||
 | 
					add "Hello, " $name &out
 | 
				
			||||||
 | 
					stdlnout $out 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Types
 | 
				
			||||||
 | 
					stdlnout "dingus"
 | 
				
			||||||
 | 
					stdlnout 7
 | 
				
			||||||
 | 
					stdlnout 3.14159
 | 
				
			||||||
 | 
					stdlnout true
 | 
				
			||||||
 | 
					stdlnout 'e'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Variables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set &testVar "This is a test"
 | 
				
			||||||
 | 
					stdlnout $testVar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Lists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					setlist *testList "Item 1" "Another Item" "Item the Third"
 | 
				
			||||||
 | 
					getlistat *testList 2 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					setlistat *testList 1 "I changed this item"
 | 
				
			||||||
 | 
					getlistat *testList 1 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					listappend *testList "I appended this item"
 | 
				
			||||||
 | 
					getlistat *testList 3 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					getlistsize *testList &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# String Operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set &testStr "dingus"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					getstrsize $testStr &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					getstrcharat $testStr 3 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Maths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add 1 1 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subtract 10 5 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					multiply 15 15 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					divide 36 4 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Comparisons
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					equal 5 5 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inequal 5 5 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					greater 10 5 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lesser 10 5 &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Control flow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set &counter 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@myLabel
 | 
				
			||||||
 | 
					add $counter 1 &counter
 | 
				
			||||||
 | 
					stdlnout $counter
 | 
				
			||||||
 | 
					inequal $counter 10 &case
 | 
				
			||||||
 | 
					if $case %myLabel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# That's it!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stdlnout "Everything ran! Check the output to see if it is what is expected."
 | 
				
			||||||
 | 
					end 0
 | 
				
			||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
 | 
					@begin
 | 
				
			||||||
stdout "Do you like cheese? "
 | 
					stdout "Do you like cheese? "
 | 
				
			||||||
stdin &userin
 | 
					stdin &userin
 | 
				
			||||||
equal $userin "yes" &condition
 | 
					equal $userin "yes" &condition
 | 
				
			||||||
if $condition %7
 | 
					if $condition %end
 | 
				
			||||||
stdlnout "That is sad"
 | 
					stdlnout "That is sad"
 | 
				
			||||||
jump %1
 | 
					jump %begin
 | 
				
			||||||
 | 
					@end
 | 
				
			||||||
stdlnout "Awesome! I do too!"
 | 
					stdlnout "Awesome! I do too!"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								tests/lists.grnd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/lists.grnd
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# A cool list
 | 
				
			||||||
 | 
					setlist *favWords "hello" "there" "general" "kenobi"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set &count 0
 | 
				
			||||||
 | 
					set &passedThrough true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@jmpbck
 | 
				
			||||||
 | 
					getlistat *favWords $count &tmp
 | 
				
			||||||
 | 
					stdlnout $tmp
 | 
				
			||||||
 | 
					add $count 1 &count
 | 
				
			||||||
 | 
					getlistsize *favWords &tmp2
 | 
				
			||||||
 | 
					inequal $count $tmp2 &tmp3
 | 
				
			||||||
 | 
					if $tmp3 %jmpbck
 | 
				
			||||||
							
								
								
									
										10
									
								
								tests/typeconvs.grnd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/typeconvs.grnd
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					stod "3.14" &out
 | 
				
			||||||
 | 
					stdlnout $out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stoi "732" &out
 | 
				
			||||||
 | 
					add 1 $out &out
 | 
				
			||||||
 | 
					stdlnout $out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tostring 3.14 &out
 | 
				
			||||||
 | 
					add $out " is a number of sorts" &out
 | 
				
			||||||
 | 
					stdlnout $out
 | 
				
			||||||
		Reference in New Issue
	
	Block a user