aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <hallo@tomsmeding.nl>2014-04-24 22:14:39 +0200
committertomsmeding <hallo@tomsmeding.nl>2014-04-24 22:14:39 +0200
commitc275a149eec2f8641dbce4cdf114ab0dca5216ff (patch)
tree3b94e96913f1bb1bc72979f82a8677f6e1e34f85
Initial commit
Already did some programming though…
-rw-r--r--factorial.trt9
-rw-r--r--io.trt11
-rw-r--r--newlojban.trt6
-rw-r--r--primes.trt29
-rw-r--r--pshpll.trt38
-rwxr-xr-xtreetree.js384
-rw-r--r--treetree.md212
7 files changed, 689 insertions, 0 deletions
diff --git a/factorial.trt b/factorial.trt
new file mode 100644
index 0000000..f2e628b
--- /dev/null
+++ b/factorial.trt
@@ -0,0 +1,9 @@
+"Factorial for num:" OUT
+INP FLT
+#loop
+ DUP
+ 1 DIF
+DUP 1 GRT @loop IFJ
+SWP
+PI_
+STR OUT \ No newline at end of file
diff --git a/io.trt b/io.trt
new file mode 100644
index 0000000..1986ff3
--- /dev/null
+++ b/io.trt
@@ -0,0 +1,11 @@
+inp out
+"io.trt" ifi
+inp out "
+" out
+"io.out.txt" ofi
+inp out "
+" out
+ius
+inp out
+ous
+inp out \ No newline at end of file
diff --git a/newlojban.trt b/newlojban.trt
new file mode 100644
index 0000000..f319e57
--- /dev/null
+++ b/newlojban.trt
@@ -0,0 +1,6 @@
+RND RND RND RND RND
+SWP
+26 MOD
+97 SUM
+"" SUM
+SIG OUT \ No newline at end of file
diff --git a/primes.trt b/primes.trt
new file mode 100644
index 0000000..84a0f55
--- /dev/null
+++ b/primes.trt
@@ -0,0 +1,29 @@
+"Up to which number do you want a list of primes?" OUT
+INP INT
+"Here you go:" OUT
+2 2
+"2" OUT
+#MAIN
+1 SUM
+DUP
+2 PLL
+DUP
+3 PSH
+MOD
+PI_
+NOT
+@NOPRIME IFJ
+DUP
+2 PSH
+1 GRB
+1 PLL
+DUP
+STR
+OUT
+#NOPRIME
+DUP
+3 PLL
+DUP
+4 PSH
+SML
+@MAIN IFJ \ No newline at end of file
diff --git a/pshpll.trt b/pshpll.trt
new file mode 100644
index 0000000..5418c15
--- /dev/null
+++ b/pshpll.trt
@@ -0,0 +1,38 @@
+2 pll
+
+{
+[3,
+ [2,
+ [1,false,false],
+ ["a",
+ false,
+ ["b",false,false]]],
+ ["b",
+ ["xx",false,false],
+ false]]
+
+
+3--"b"
+| |
+| "xx"
+|
+2--"a"--"b"
+|
+|
+|
+1
+
+---------->
+1
+|
+|
+|
+3--"b"
+| |
+| "xx"
+|
+2--"a"--"b"
+
+
+[1,[3,[2,false,["a",false,["b",false,false]]],["b",["xx",false,false],false]],false]
+} \ No newline at end of file
diff --git a/treetree.js b/treetree.js
new file mode 100755
index 0000000..1c0e0ff
--- /dev/null
+++ b/treetree.js
@@ -0,0 +1,384 @@
+#!/usr/bin/env node
+
+var fs=require("fs"),util=require("util"),kbd=require("kbd");
+
+var flags={"debug":false},TRpreload=undefined;
+
+if(process.argv.length<3){
+ console.log("Please supply a treetree source file on the command line.");
+ console.log("\t-d Debug stuff.");
+ console.log("\t-s Preload stack in internal JSON array format in next parameter.");
+ process.exit(1);
+} else {
+ var i,j,skipArg=false;
+ for(i=2;i<process.argv.length-1;i++){
+ if(skipArg){
+ skipArg=false;
+ continue;
+ }
+ if(process.argv[i][0]!="-"){
+ console.log("Invalid argument '"+process.argv[i]+"'!");
+ process.exit(1);
+ }
+ for(j=1;j<process.argv[i].length;j++){
+ switch(process.argv[i][j]){
+ case "d":flags.debug=true;break;
+ case "s":TRpreload=JSON.parse(process.argv[i+1]);skipArg=true;break;
+ default:
+ console.log("Invalid flag '-"+process.argv[i][j]+"'!");
+ process.exit(1);
+ }
+ }
+ }
+}
+
+function TTerror(msg){
+ TTerror.super_.apply(this,arguments);
+ this.message=msg.toString();
+}
+util.inherits(TTerror,Error);
+
+function objcpy(obj){return JSON.parse(JSON.stringify(obj));}
+
+var cmd_list=["INP","OUT","IFI","OFI","IUS","OUS","ICH","OCH","PSH","PLL","SWP","POP","DUP","GRB","REL","INT","FLT","STR","NAN","LEN","SPL","SUM","DIF","PRO","QUO","POW","ROO","LOG","MOD","SIG","PI_","OR_","AND","XOR","INV","NOT","EQU","NEQ","SML","GRT","TAU","E__","RND","JMP","EXJ","IFJ","STP","STK"];
+
+//returns [command term,index after end of command]
+function extractCmd(code,startat){
+ var i;
+ while((code[startat]==" "||code[startat]=="\t"||code[startat]=="\n")&&startat<code.length)startat++;
+ if(startat==code.length)return false;
+ if(code[startat]=='"'||code[startat]=="'"||code[startat]=="{"){
+ var term;
+ term="";
+ for(i=startat+1;i<code.length;i++){
+ if(code[i]==code[startat]||(code[startat]=="{"&&code[i]=="}"))break;
+ term+=code[i];
+ }
+ if(code[startat]=="'"||code[startat]=="{")return extractCmd(code,i+1); //'this is a comment,' {and this too.}
+ return [["str",term],i+1];
+ } else if(code[startat].match(/[0-9]|-|\./)){
+ var neg,dot;
+ i=startat;
+ neg=code[startat]=="-";
+ i+=neg;
+ dot=false;
+ for(;i<code.length;i++){
+ if(code[i]=="."){
+ if(!dot)dot=true;
+ else break;
+ }
+ if(!code[i].match(/[0-9]/))break;
+ }
+ return [[dot?"flt":"int",parseFloat(code.slice(startat,i))],i];
+ } else if(code[startat]=="#"){
+ var term;
+ for(i=startat+1;i<code.length;i++)
+ if(code[i]==" "||code[i]=="\t"||code[i]=="\n")break;
+ return [["lbl",code.slice(startat+1,i)],i];
+ } else if(code[startat]=="@"){
+ var term;
+ for(i=startat+1;i<code.length;i++)
+ if(code[i]==" "||code[i]=="\t"||code[i]=="\n")break;
+ return [["ref",code.slice(startat+1,i)],i];
+ } else {
+ var term;
+ if(code.length-startat<3)throw new Error("Invalid command '"+code.slice(startat)+"' at end of code with less than 3 characters!");
+ term=code.slice(startat,startat+3).toUpperCase();
+ if(cmd_list.indexOf(term)!=-1)return [["cmd",term],startat+3];
+ else throw new Error("Unrecognised command '"+term+"'!");
+ }
+}
+
+var runCmds_state={"in":undefined,"out":undefined,"interm":"\n","outterm":"\n","stdinbuf":""};
+//Pass command array and the current tree. The tree is edited in-place.
+function runCmds(cmds,TR){
+ var cmdidx;
+ for(cmdidx=0;cmdidx<cmds.length;cmdidx++){
+ if(cmds[cmdidx][0]=="str"||cmds[cmdidx][0]=="int"||cmds[cmdidx][0]=="flt")TR=[cmds[cmdidx][1],TR,false];
+ else if(cmds[cmdidx][0]=="ref")TR=[labels[cmds[cmdidx][1]],TR,false]; //yes, a label reference is just the position integer.
+ else if(cmds[cmdidx][0]=="cmd"){
+ switch(cmds[cmdidx][1]){
+ case "INP":
+ if(runCmds_state["in"]==undefined){
+ var idx,str;
+ str=kbd.getLineSync()+"\n";
+ idx=str.indexOf(runCmds_state["interm"]);
+ while(idx==-1){
+ runCmds_state["stdinbuf"]+=str;
+ str=kbd.getLineSync()+"\n";
+ idx=str.indexOf(runCmds_state["interm"]);
+ }
+ idx=runCmds_state["stdinbuf"].length+idx;
+ runCmds_state["stdinbuf"]+=str;
+ TR=[runCmds_state["stdinbuf"].slice(0,idx),TR,false];
+ runCmds_state["stdinbuf"]=runCmds_state["stdinbuf"].slice(idx+1,runCmds_state["stdinbuf"].length);
+ } else {
+ var buf,str,c;
+ buf=new Buffer(1);
+ str="";
+ do{
+ fs.readSync(runCmds_state["in"],buf,0,1,null);
+ c=String.fromCharCode(buf[0])
+ str+=c;
+ }while(c!=runCmds_state["interm"]);
+ TR=[str.slice(0,-1),TR,false];
+ }
+ break;
+ case "OUT":
+ var f,stdout,printPrimaryChildTree;
+ if(runCmds_state["out"]==undefined)stdout=true;
+ else stdout=false;
+ printPrimaryChildTree=function(e){
+ while(e!=false){
+ if(typeof e[0]!="string")throw new TTerror("Value to be printed, "+e[0].toString()+", is not a string!");
+ if(stdout)process.stdout.write(e[0]);
+ else fs.writeSync(runCmds_state["out"],new Buffer(e[0]),0,e[0].length,null);
+ if(e[2]!==false)printPrimaryChildTree(e[2]);
+ e=e[1];
+ }
+ }
+ if(TR===false)throw new TTerror("Tree is empty while processing OUT!");
+ if(typeof TR[0]!="string")throw new TTerror("Value to be printed, "+TR[0].toString()+", is not a string!");
+ if(stdout)process.stdout.write(TR[0]+runCmds_state["outterm"]);
+ else fs.writeSync(runCmds_state["out"],new Buffer(TR[0]+runCmds_state["outterm"]),0,TR[0].length+1,null);
+ printPrimaryChildTree(TR[2]);
+ TR=TR[1];
+ break;
+ case "IFI":
+ var fname;
+ if(typeof TR[0]!="string")throw new TTerror("File name (in IFI) is not a string (namely "+TR[0].toString()+")!");
+ if(TR[2]!=false)throw new TTerror("Cannot open multiple files (in IFI), but the root node ('"+TR[0]+"') has secondary children!");
+ fname=TR[0];
+ TR=[1,TR[1],false]; //"return" 1
+ try{
+ runCmds_state["in"]=fs.openSync(fname,"r");
+ } catch(err){
+ TR[0]=0; //"return" 0
+ }
+ break;
+ case "OFI":
+ var fname;
+ if(typeof TR[0]!="string")throw new TTerror("File name (in OFI) is not a string (namely "+TR[0].toString()+")!");
+ if(TR[2]!=false)throw new TTerror("Cannot open multiple files (in OFI), but the root node ('"+TR[0]+"') has secondary children!");
+ fname=TR[0];
+ TR=[1,TR[1],false]; //"return" 1
+ try{
+ runCmds_state["out"]=fs.openSync(fname,"w");
+ } catch(err){
+ TR[0]=0; //"return" 0
+ }
+ break;
+ case "IUS":
+ if(runCmds_state["in"]!=undefined){
+ fs.closeSync(runCmds_state["in"]);
+ runCmds_state["in"]=undefined;
+ }
+ break;
+ case "OUS":
+ if(runCmds_state["out"]!=undefined){
+ fs.closeSync(runCmds_state["out"]);
+ runCmds_state["out"]=undefined;
+ }
+ break;
+ case "ICH":
+ if(TR[2]!=false)throw new TTerror("Cannot open multiple files (in ICH), but the root node ('"+TR[0]+"') has secondary children!");
+ if(typeof TR[0]!="string")throw new TTerror("String expected (in ICH), got '"+TR[0].toString()+"'!");
+ if(TR[0].length!=1)throw new TTerror("String is not one character while processing ICH!");
+ runCmds_state["interm"]=TR[0];
+ TR=TR[1];
+ break;
+ case "OCH":
+ if(TR[2]!=false)throw new TTerror("Cannot open multiple files (in OCH), but the root node ('"+TR[0]+"') has secondary children!");
+ if(typeof TR[0]!="string")throw new TTerror("String expected (in OCH), got '"+TR[0].toString()+"'!");
+ if(TR[0].length!=1)throw new TTerror("String is not one character while processing OCH!");
+ runCmds_state["outterm"]=TR[0];
+ TR=TR[1];
+ break;
+ case "PSH":case "PLL":
+ var n;
+ if(TR[2]!=false)throw new TTerror("Cannot operate multiple times (in "+cmds[cmdidx][1]+"), but the root node ('"+TR[0]+"') has secondary children!");
+ if(typeof TR[0]!="number"||TR[0]%1!=0)throw new TTerror("Integer expected (in "+cmds[cmdidx][1]+"), got '"+TR[0].toString()+"'!");
+ n=TR[0];
+ TR=TR[1];
+ if(cmds[cmdidx][1]=="PLL")n=-n;
+ if(n>0){ //PSH
+ var next_part,next_part_parent,moved_node,i;
+ next_part_parent=TR;
+ for(i=0;i<n;i++){
+ next_part_parent=next_part_parent[1];
+ if(next_part_parent==false)throw new TTerror("Trying to PSH beyond end of tree (in "+cmds[cmdidx][1]+")!");
+ }
+ next_part=objcpy(next_part_parent[1]);
+ moved_node=[TR[0],next_part,objcpy(TR[2])];
+ TR=TR[1];
+ next_part_parent[1]=moved_node;
+ } else if(n<-1){ //PLL; if n==1 then it pulls the root node onto the root node. Which is useless.
+ n=-n;
+ var moved_node_parent,i;
+ moved_node_parent=TR;
+ for(i=0;i<n-1;i++){
+ moved_node_parent=moved_node_parent[1];
+ if(moved_node_parent==false)throw new TTerror("Trying to PLL beyond end of tree (in "+cmds[cmdidx][1]+")!");
+ }
+ moved_node=moved_node_parent[1];
+ if(moved_node==false)throw new TTerror("Trying to PLL just beyond end of tree (in "+cmds[cmdidx][1]+")!");
+ moved_node_parent[1]=objcpy(moved_node[1]);
+ moved_node=[moved_node[0],TR,moved_node[2]];
+ TR=objcpy(moved_node); //Sorry, garbage colector.
+ }
+ break;
+ case "SWP":
+ var temp;
+ temp=objcpy(TR[1]);
+ TR[1]=objcpy(TR[2]);
+ TR[2]=temp;
+ break;
+ case "POP":break;
+ case "DUP":break;
+ case "GRB":break;
+ case "REL":break;
+ case "INT":break;
+ case "FLT":break;
+ case "STR":break;
+ case "NAN":break;
+ case "LEN":break;
+ case "SPL":break;
+ case "SUM":break;
+ case "DIF":break;
+ case "PRO":break;
+ case "QUO":break;
+ case "POW":break;
+ case "ROO":break;
+ case "LOG":break;
+ case "MOD":break;
+ case "SIG":break;
+ case "PI_":break;
+ case "OR_":break;
+ case "AND":break;
+ case "XOR":break;
+ case "INV":break;
+ case "NOT":break;
+ case "EQU":break;
+ case "NEQ":break;
+ case "SML":break;
+ case "GRT":break;
+ case "TAU":break;
+ case "E__":break;
+ case "RND":break;
+ case "JMP":break;
+ case "EXJ":break;
+ case "IFJ":break;
+ case "STP":
+ process.exit();
+ break;
+ case "STK":
+ var str;
+ str=util.inspect(TR,{"depth":null});
+ if(runCmds_state["out"]==undefined)process.stdout.write(str);
+ else fs.writeSync(runCmds_state["out"],new Buffer(str),0,str.length,null);
+ break;
+ default:
+ throw new Error("Internal error: Unrecognised command in internal command array! Please report the command '"+cmds[cmdidx][1]+"'!");
+ }
+ } else throw new Error("Internal error: Invalid command type! Please report the type '"+cmds[cmdidx][0]+"'!");
+ if(flags.debug){
+ process.stdout.write("\x1B[36m");
+ console.log("%j",TR);
+ process.stdout.write("\x1B[0m");
+ }
+ }
+}
+
+//Edits `labels` in-place.
+function parseLabels(cmds,labels){
+ var i;
+ for(i=0;i<cmds.length;i++){
+ if(cmds[i][0]=="lbl"){
+ labels[cmds[i][1]]=i;
+ cmds.splice(i,1);
+ i--;
+ }
+ }
+}
+
+/*
+`TR` stores the main tree in treetree. `false` indicates non-existance. It
+contains a root node with a primary child and a secondary child. Every node is
+represented by an array with three items, the first containing the contents of
+the node, the second containing the primary child (which is also an array like
+this node) and the third containing the second child. An absent child is of
+course indicated with the literal value `false`.
+For example, the following program:
+1 2 3 SWP 4
+makes the tree (*'s indicating absence of children, / is a primary child, --
+is a secondary child):
+ 4 *
+ /
+ 3--2 *
+ * /
+ 1 *
+ *
+and is represented in `TR` like:
+[4,
+ [3,
+ false,
+ [2,
+ [1,false,false],
+ false
+ ]
+ ],
+ false
+]
+
+Commands, in `cmds`, are each an array with two items, the first being the type
+and the second being the value. The types are:
+"str", "flt", "int", "lbl", "ref" and "cmd".
+"str" contains a literal string, "flt" a literal floating-point and "int" a
+literal integer. "lbl" and "ref" contain the names of the labels and "irf"
+contains the integer mapping of the label after the first pass. "cmd" indicates
+a string with the specific command.
+
+The first pass over the code removes all the "lbl" commands and adds those
+labels to `labels`. The second pass interprets the code.
+*/
+
+var fname,infile,offset,code,cmds,TR,labels;
+
+fname=process.argv[process.argv.length-1];
+try{
+ infile=fs.openSync(fname,"r");
+ fs.closeSync(infile);
+}catch(e){
+ console.log("Could not open file '"+fname+"'!");
+ process.exit(1);
+}
+code=fs.readFileSync(fname,{"encoding":"utf8"});
+cmds=[]; //command list in array form
+offset=0;
+while(true){
+ offset=extractCmd(code,offset);
+ if(offset===false)break;
+ cmds.push(offset[0]);
+ offset=offset[1];
+}
+
+if(TRpreload)TR=TRpreload;
+else TR=false; //The Big TRee starts non-existant. Yeah. Well, it is true, sort-of.
+labels=[]; //label index
+parseLabels(cmds,labels);
+if(flags.debug){
+ process.stdout.write("\x1B[36m");
+ process.stdout.write("Commands: ");
+ console.log(cmds);
+ process.stdout.write("Labels: ");
+ console.log(labels);
+ process.stdout.write("\x1B[0m");
+}
+try{
+ runCmds(cmds,TR);
+} catch(err) {
+ if(err instanceof TTerror){
+ console.log("\x1B[31;1mTreetree error:\x1B[0m \x1B[31m"+err.message+"\x1B[0m");
+ process.exit(1);
+ } else throw err;
+}
diff --git a/treetree.md b/treetree.md
new file mode 100644
index 0000000..28e62ff
--- /dev/null
+++ b/treetree.md
@@ -0,0 +1,212 @@
+## Input and Output operations
+
+- INP
+ _Input_
+ **put 1 str**
+ Get a string from the active in-stream (cin is default), terminated by the set in-stream termination character (newline is default)
+- OUT
+ _Output_
+ **pop 1 str**
+ Put a string in the active out-stream (cout is default), terminated by the set out-stream termination character (newline is default)
+- IFI
+ _Input File_
+ **pop 1 str**
+ **put 1 int**
+ Get a filename, open that file for reading and set the active in-stream to that file. Returns a boolean value with true for succes and false for any error that has occured while trying to open the file.
+- OFI
+ _Output File_
+ **pop 1 str**
+ **put 1 int**
+ Get a filename, open that file for writing and set the active out-stream to that file. Returns a boolean value with true for succes and false for any error that has occured while trying to open the file.
+- IUS
+ _Input User_
+ Set the active in-stream to cin and if required close the file previously set as the active in-stream.
+- OUS
+ _Output User_
+ Set the active out-stream to cout and if required close the file previously set as the active out-stream.
+- ICH
+ _Input Character_
+ **pop 1 str**
+ Change the in-stream termination character (newline is default).
+- OCH
+ _Output Character_
+ ** pop 1 str **
+ Change the out-stream termination character (newline is default).
+
+## Tree operations
+
+- PSH
+ _Push_
+ **pop 1 int**
+ Take the root node and its secondary children and put it between the n-th and (n+1)-th primary child of the root node. Negative numbers invoke a PLL with that number's absolute value.
+- PLL
+ _Pull_
+ **pop 1 int**
+ Take the n-th node and its secondary children and make it the root node, with the previous root node as its primary child. Negative numbers invoke a PSH with that number's absolute value.
+- SWP
+ _Swap_
+ Swap the root node's primary and secondary child.
+- POP
+ _Pop_
+ Remove the root node and its secondary children from the tree, making the previous root node's primary child the root node.
+- DUP
+ _Duplicate_
+ Copy the root node and its secondary children and make it the root node, making the previous root node the new root node's primary child.
+- GRB
+ _Grab_
+ **pop 1 int**
+ Take n generations of primary children of the root node with all of their secondary children and insert them between the root node and the root node's secondary child.
+- REL
+ _Release_
+ **pop 1 int**
+ Take n-1 generations of primary children of the root node's secondary child and the root node's secondary child itself with all of their secondary children and insert them between the root node and and the root node's primary child.
+
+## Datatypes
+
+- INT
+ _Integer_
+ **pop 1 datatype**
+ **put 1 int**
+ Convert datatype to integer. When impossible, the NaN type is put instead of an integer.
+- FLT
+ _Floating point_
+ **pop 1 datatype**
+ **put 1 flt**
+ Convert datatype to floating point. When impossible, the NaN type is put instead of a floating point.
+- STR
+ _String_
+ **pop 1 datatype**
+ **put 1 str**
+ Convert datatype to string. This always succeeds.
+- NAN
+ _Not a Number_
+ **put 1 nan**
+ Put a Not a Number type.
+- LEN
+ _Length_
+ **pop 1 str**
+ **put 1 int**
+ Put the number of characters in the string. If the datatype is not a string, NaN is put instead of an integer.
+- SPL
+ _Split_
+ **pop 1 int**
+ **put 1 str**
+ Split the string in two between the the n-th character from the beginning of the string for positive numbers and between the (length+n)-th character for negative values of n. For all values for n that are out of string bounds throw an error.
+
+## Math, Arithmetic and Bitwise operators
+
+All operations are applied on the root node and optionaly its primary child as first and second parameter. One of these parameters is allowed to have secondary children, on which the operation is also executed. This allows for a large number of operations in a small number of commands.
+
+All math and arithmetic functions work for the integer and floating point type. The operation will return a floating point, when one of the parameters is a floating point. Otherwise it will return an integer.
+
+Bitwise operators require integers, although the SUM and PRO operations work on strings as well.
+
+Operations on illegal types will throw an error, and math errors will result in the NaN type. (ex. 1/0 -> NaN)
+
+- SUM
+ _Sum_
+ 1. The sum of two numbers.
+ 2. Concatenation of two strings.
+- DIF
+ _Difference_
+ The difference between two numbers
+- PRO
+ _Product_
+ 1. The product of two numbers
+ 2. A number of times a string concatenated to itself.
+- QUO
+ _Quotient_
+ The quotient of two numbers
+- POW
+ _Power_
+ The first parameter raised to the second parameter's power.
+- ROO
+ _Root_
+ The first parameter's root of the first parameter's degree.
+- LOG
+ _Logarithm_
+ The second parameter's log of the first parameter.
+- MOD
+ _Modulo_
+ The remainder of a division of the first and second parameter.
+- SIG
+ _Sigma/Summation_
+ The sum of the root node and all its secondary children.
+- PI\_
+ _Pi/Product_
+ The product of the root node and all its secondary children.
+- OR\_
+ _Bitwise Or_
+ The bitwise or of two integers.
+- AND
+ _Bitwise And_
+ The bitwise and of two integers.
+- XOR
+ _Bitwise Xor_
+ The bitwise xor of two integers.
+- INV
+ _Bitwise Invert_
+ The bitwise inversion of an integer.
+- NOT
+ _Not_
+ A boolean not of an integer. (equal to n<1)
+- EQU
+ _Equal_
+ Compare to datatypes and put true when they are equal and otherwise put false.
+- NEQ
+ _Not Equal_
+ Compare to datatypes and put true when they are not equal and otherwise put false.
+- SML
+ _Smaller than_
+ Compare to datatypes and put true when the first is smaller than the second and otherwise put false.
+- GRT
+ _Greater than_
+ Compare to datatypes and put true when the first is greater than the second and otherwise put false.
+
+## Constants and Generated Variables
+
+- TAU
+ _Tau_
+ **put 1 flt**
+ Put the ratio of a circle's circumference to its radius, equal to 2&pi;.
+- E__
+ _e_
+ **put 1 flt**
+ Put Euler's number.
+- RND
+ _Random_
+ **put 1 int**
+ Put a random integer.
+
+## Loops and Conditions
+
+- JMP
+ _Jump_
+ **pop 1 int**
+ Let the n-th command be the next one.
+- EXJ
+ _Extended Jump_
+ **pop 1 int**
+ **put 1 int**
+ Let the n-th command be the next and put back an integer with the position of the command after this EXJ.
+Useful for functions.
+- IFJ
+ _If Jump_
+ **pop 1 int**
+ If the second parameter is true, jump to the first parameters position.
+- STP
+ _Stop_
+ Terminate the program
+
+## Debug functions
+
+- STK
+ _Stack_
+ Output the stack without popping anything.
+
+## Literals
+
+Integers and floating points are written down as one normally would, accepting an 'e' for an exponent, a minus sign in front for negative and a dot ('.') as the decimal separator. Strings are enclosed in "double quotes" and comments in 'single quotes' or, more preferably, in {braces}.
+Special characters in strings can be written down as they are, with the sole exception of the double quote ("), which cannot be put in a string literal.
+
+Bare literals in the code get pushed into the tree such that the old root node becomes the first child of the newly pushed thing, and thus the newly pushed thing becomes the new root node. \ No newline at end of file