changeset 100:f51c4c17457c

Broken port of parser to compiler
author Mike Pavone <pavone@retrodev.com>
date Mon, 09 Aug 2010 02:03:57 -0400
parents e09c2d1d6d5b
children f4fc0a98088a
files backendutils.rhope backendutils_c.rhope cbackend.rhope file.rhope kernel.rhope list.rhope parser_old_c.rhope runtime/func.h string.rhope
diffstat 9 files changed, 2014 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/backendutils.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/backendutils.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -1,7 +1,7 @@
 
 Escape Rhope Name NU[name:escaped]
 {
-	escaped <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[name]Replace["_","UN_"]
+	escaped <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[name]Replace["_","UN_"]
 		]Replace["@","AT_"]
 		]Replace[" ","SP_"]
 		]Replace[":","CN_"]
@@ -33,11 +33,19 @@
 		]Replace["&", "AM_"]
 		]Replace["|", "PI_"]
 		]Replace["%", "PC_"]
+		]Replace["`", "BT_"]
+		]Replace["~", "TD_"]
 }
 
-Escape Rhope Name[name:escaped]
+Escape Rhope Name[name:out]
 {
 	escaped <- Escape Rhope Name NU[[name]Replace["_","__"]]
+	[("char","int","short","long","float","double","void","struct")]Find[escaped]
+	{
+		out <- ["ID_"]Append[escaped]
+	}{
+		out <- Val[escaped]
+	}
 }
 
 Blueprint AddRef
--- a/backendutils_c.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/backendutils_c.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -1,11 +1,18 @@
 
-Escape Rhope Name[name:escaped]
+Escape Rhope Name[name:out]
 {
 	escaped <- [name]Replace[
 		("_",  "@",  " ",  ":",  "?",  "+",  "-",  "*",  "/",  "<",  ">",  "(",  ")",  "!",  "=",  "'",  
-			"\"", "\t", ",",  ".",  "\n", "{",  "}",   "[",   "]",   "#",   "\\",  "\r",  ";",   "&",   "|",   "%",   "^"),
+			"\"", "\t", ",",  ".",  "\n", "{",  "}",   "[",   "]",   "#",   "\\",  "\r",  ";",   "&",   "|",   "%",   "^",   "`",   "~"),
 		("UN_","AT_","SP_","CN_","QN_","PL_","MN_","TM_","DV_","LT_","GT_","LP_","RP_","NT_","EQ_","PR_",
-			"DP_","TB_","CM_","PD_","NL_","LC_","RC_", "LS_", "RS_", "HS_", "BS_", "CR_", "SC_", "AM_", "PI_", "PC_", "CT_")]
+			"DP_","TB_","CM_","PD_","NL_","LC_","RC_", "LS_", "RS_", "HS_", "BS_", "CR_", "SC_", "AM_", "PI_", "PC_", "CT_", "BT_", "TD_")]
+			
+	[("char","int","short","long","float","double","void","struct")]Find[=[escaped, ?]]
+	{
+		out <- ["ID_"]Append[escaped]
+	}{
+		out <- Val[escaped]
+	}
 }
 
 Blueprint AddRef
--- a/cbackend.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/cbackend.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -722,18 +722,24 @@
 
 	If[[[func]Last NumParams >>] = [-1]]
 	{
-		freed <- Val[func]
-	}{
-		freed <- [func]Add Raw Line["FreeCall"]
-	}
-	prepped <- [[freed]Add Raw Line[ 
+		prepped <- [[func]Add Raw Line[ 
 			[[[["VCPrepCall("
 				]Append[worker]
 				]Append[", "]
 				]Append[[rargs]Length]
 				]Append[")"] ]
 		]Last NumParams <<[[rargs]Length]
-	
+	}{
+		prepped <- [[func]Add Raw Line[ 
+			[[[[[["VCRePrepCall("
+				]Append[worker]
+				]Append[", "]
+				]Append[[rargs]Length]
+				]Append[", "]
+				]Append[[func]Last NumParams >>]
+				]Append[")"] ]
+		]Last NumParams <<[[rargs]Length]
+	}
 	
 	out <- [[[[Fold[["_Val Function Arg C"]Set Input[3, worker], prepped, rargs]
 	]Add Raw Line[
--- a/file.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/file.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -99,7 +99,7 @@
 			}
 		}
 	}
-	fd <- open[[[[file]Name >>]Flatten]Buffer >>, imode, 438u32]
+	fd <- open[[[[[file]Name >>]Flatten]Buffer >>]Append[0u8], imode, 438u32]
 	error <- If[[fd]=[-1i32]] {}
 	{
 		ofile <- [[[Build[type]	
--- a/kernel.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/kernel.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -310,3 +310,11 @@
 	out <- Fold[_Keys[?], (), container]
 }
 
+Between[num,low,high:yep,nope]
+{
+	,nope <- If[[num]>[low]]
+	{
+		yep,nope <- If[[num]<[high]]
+	}
+}
+
--- a/list.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/list.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -331,3 +331,25 @@
 	{ out <- _Print Seq[list, [list]First] }
 }
 
+
+Peek@List[list:out,empty]
+{
+	[list]Last
+	{
+		out <- [list]Index[~]
+	}{
+		empty <- list
+	}
+}
+
+Peek@List Leaf[list:out,empty]
+{
+	[list]Last
+	{
+		out <- [list]Index[~]
+	}{
+		empty <- list
+	}
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parser_old_c.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -0,0 +1,1607 @@
+Import nworker_c.rhope
+
+//Rather than rewrite the code that uses this
+//let's implement Get DString using Partition
+Get DString[str,delims:after,before,delim,not found]
+{
+	before,delim,after,not found <- [str]Partition[delims] {} {} {}
+	{
+		before <- str
+	}
+}
+
+
+Blueprint Parser
+{
+	Arg Begin
+	Arg End
+	Line Comment
+	Comment Begin
+	Comment End
+	Assign
+	Block Begin
+	Block End
+	Blueprint Type Delim
+	Empty Block
+	Binary Operator
+	String Begin
+	String End
+	String Escape 
+	List Begin
+	List End
+	List Delim
+	In Out Delim
+	Do Worker
+	Index Begin
+	Index End
+	Previous
+	Block Val
+	Set Field
+	Get Field
+	Import
+	Blueprint
+	Global Separator
+	Uses
+	Hex Escape
+	Escape Map
+	Foreign
+}
+
+Parser[:out]
+{
+	out <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Build[Parser()]
+	]Arg Begin << ["["]
+	]Arg End <<["]"]
+	]Line Comment <<["//"]
+	]Comment Begin <<["/*"]
+	]Comment End <<["*/"]
+	]Assign <<["<-"]
+	]Block Begin <<["{"]
+	]Block End <<["}"]
+	]Blueprint Type Delim <<[":"]
+	]Empty Block <<[";"]
+	]Binary Operator <<["`"]
+	]String Begin <<["\""]
+	]String End <<["\""]
+	]String Escape <<["\\"]
+	]List Begin <<["("]
+	]List End <<[")"]
+	]List Delim <<[","]
+	]In Out Delim <<[":"]
+	]Do Worker <<["$"]
+	]Index Begin <<["("]
+	]Index End <<[")"]
+	]Previous <<["@"]
+	]Set Field <<["<<"]
+	]Get Field <<[">>"]
+	]Import <<["Import"]
+	]Blueprint <<["Blueprint"]
+	]Global Separator <<["::"]
+	]Hex Escape <<["x"]
+	]Uses <<["uses"]
+	]Escape Map <<[[[[Dictionary[]]Set["n","\n"]]Set["r","\r"]]Set["t","\t"]]
+	]Foreign <<["Foreign"]
+}
+
+Blueprint Output Reference
+{
+	Index
+	Output Number
+}
+
+Output Reference[index,num:out]
+{
+	out <- [[Build[Output Reference()]]Index <<[index]]Output Number <<[num]
+}
+
+Add Pipe Reference[refs,name,reference:out]
+{
+	reflist <- [refs]Index[name] {}
+	{
+		reflist <- ()
+	}
+	out <- [refs]Set[name, [reflist]Append[reference]]
+}
+
+Assignment Save Reference[refs,assignment,output num,parse worker,index:out]
+{
+	[[parse worker]Outputs >>]Find[=[assignment,?]]
+	{
+		out <- refs
+	}{
+		out <- Add Pipe Reference[refs, assignment, Output Reference[index, output num]]
+	}
+}
+
+Blueprint Foreign Lib
+{
+	Language
+	Name
+}
+
+New Foreign Lib[language, library:out]
+{
+	out <- [[Build[Foreign Lib()]
+	]Language <<[language]
+	]Name <<[library]
+}
+
+Blueprint Parse Program
+{
+	Workers
+	Imports
+	Blueprints
+	Errors
+}
+
+Parse Program[:out]
+{
+	out <- [[[[Build[Parse Program()]
+	]Workers <<[Dictionary[]]
+	]Imports <<[[Dictionary[]]Set["kernel.rhope", Yes]]
+	]Blueprints <<[Dictionary[]]
+	]Errors <<[()]
+}
+
+Blueprint Blueprint Definition
+{
+	Name
+	Fields
+}
+
+New Blueprint Definition[name,fields:out]
+{
+	out <- [[Build[Blueprint Definition()]]Name << [name]]Fields <<[fields]
+}
+
+Blueprint Parse Worker
+{
+	Name
+	Inputs
+	Outputs
+	Line Number
+	Trees
+	Uses Stores
+	Input Types
+	Output Types
+}
+
+Parse Worker[name,inputs,outputs,intypes,outtypes,line:out]
+{
+	out <- [[[[[[[[Build[Parse Worker()]]Name <<[name]]Inputs <<[inputs]]Outputs <<[outputs]]Line Number <<[line]]Trees <<[()]]Uses Stores <<[()]]Input Types <<[intypes]]Output Types <<[outtypes]
+}
+
+Blueprint Worker Node
+{
+	Name
+	Params
+	Assignments
+	Blocks
+	Index
+}
+
+Worker Node[name,params:out]
+{
+	out <- [[[[Build[Worker Node()]]Name <<[name]]Params <<[params]]Assignments <<[()]]Blocks <<[()]
+}
+
+Add List Helper[inlist,worker,program,key,parse worker,refs:out list,out worker,out refs]
+{
+	,nextworker,nextrefs <- [[inlist]Index[key]]Add to Worker[worker, program, parse worker, refs]
+	{ nextlist <- [inlist]Set[key, ~] }
+	[inlist]Next[key]
+	{
+		out list,out worker,out refs <- Add List Helper[nextlist, nextworker, program, ~, parse worker, nextrefs]
+	}{
+		out list <- Val[nextlist]
+		out worker <- Val[nextworker]
+		out refs <- Val[nextrefs]
+	}
+}
+
+Add List to Worker[list,worker,program,parse worker,refs:out list,out worker,out refs]
+{
+	[list]First
+	{
+		out list,out worker,out refs <- Add List Helper[list, worker, program, ~, parse worker, refs]
+	}{
+		out list <- list
+		out worker <- worker
+		out refs <- refs
+	}
+}
+
+_Add Blocks to Worker[blocks,worker,program,parse worker,key,refs:out blocks,out worker,out refs]
+{
+	block, next worker, nextrefs <- Add List to Worker[[blocks]Index[key], worker, program, parse worker, refs]
+	next blocks <- [blocks]Set[key, block]
+	[blocks]Next[key]
+	{
+		out blocks,out worker,out refs <- _Add Blocks to Worker[next blocks, next worker, program, parse worker, ~, nextrefs]
+	}{
+		out blocks <- Val[next blocks]
+		out worker <- Val[next worker]
+		out refs <- Val[nextrefs]
+	}
+}
+
+Add Blocks to Worker[blocks,worker,program,parse worker,refs:out blocks,out worker,out refs]
+{
+	[blocks]First
+	{
+		out blocks, out worker, out refs <- _Add Blocks to Worker[blocks, worker, program, parse worker, ~, refs]
+	}{
+		out blocks <- blocks
+		out worker <- worker
+		out refs <- refs
+	}
+}
+
+Add to Worker@Worker Node[node,worker,program,parse worker,refs:out node,out worker,out refs]
+{
+	[program]Find Worker[[node]Name >>]
+	{
+		after worker <- [worker]Add Worker Call[~] {}
+		{
+			//Print[[[[node]Name >>]Append[" has index "]]Append[~]]
+			assignment refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>]
+			[node]Index <<[~]
+			{ 
+				params list, params worker, params refs <- Add List to Worker[[~]Params >>, after worker, program, parse worker, assignment refs]
+				block list, out worker, out refs <- Add Blocks to Worker[[~]Blocks >>, params worker, program, parse worker, params refs]
+				out node <- [[~]Params <<[params list]]Blocks <<[block list]
+			}
+		}
+	}{
+		Print[["Error: Could not find a worker named "]Append[[node]Name >>]]
+	}
+}
+
+Check Question Mark[params, index:has mark,no mark]
+{
+	param,no mark <-[params]Index[index]
+	{
+		If[[Blueprint Of[param]]=[Named Pipe Node()]]
+		{
+			has mark <-If[[[param]Name >>] = ["?"]] {}
+			{
+				has mark,no mark <- Check Question Mark[params, [index]+[1]]
+			}
+		}{
+			has mark,no mark <- Check Question Mark[params, [index]+[1]]
+		}
+	}
+}
+
+Collect Literal Inputs[literal, params, index, complex inputs:literal out,complex out]
+{
+	param <- [params]Index[index]
+	{
+		If[[Blueprint Of[param]]=[Literal Node()]]
+		{
+			next literal <- [literal]Set Input[index, [param]Value >>]
+			next complex <- Val[complex inputs]
+		}{
+			,doset <- If[[Blueprint Of[param]]=[Named Pipe Node()]]
+			{
+				,doset <- If[[[param]Name >>] = ["?"]]
+				{
+					//Question mark indicates unpopulated input
+					next complex <- Val[complex inputs]
+					next literal <- Val[literal]
+				}
+			}
+
+			Val[doset]
+			{
+				next complex <- [complex inputs]Set[index, param]
+				next literal <- Val[literal]
+			}
+		}
+		literal out, complex out <- Collect Literal Inputs[next literal, params, [index]+[1], next complex]
+	}{
+		literal out <- literal
+		complex out <- complex inputs
+	}
+}
+
+Do Set Input[literal,param,index:out]
+{
+	out <- Worker Node["Set Input", [[[()]Append[literal]]Append[Literal Node[index]]]Append[param]]
+}
+
+Check Worker Literals@Worker Node[node,program:out]
+{
+	new params <- Map[[node]Params >>, Check Worker Literals[?, program]]
+	Check Question Mark[new params, 0]
+	{
+		base literal, complex inputs <- Collect Literal Inputs[Worker Literal[[node]Name >>], new params, 0, ()]
+		new node <- Fold[Do Set Input[?], Literal Node[base literal], complex inputs]
+	}{
+		new node <- [node]Params <<[new params]
+	}
+	out <- [new node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ]
+}
+
+Add Multi Wire[worker,ref,junk,end index,input num:out]
+{
+	out <- [worker]Add Wire[[ref]Index >>, [ref]Output Number >>, end index, input num]
+}
+
+Add Param Wire[worker,param,input num,end index,blocks,parse worker,assignments:out]
+{
+	param worker, start index, output num <- [param]Add Wires[worker, blocks, parse worker, assignments] {}
+	{
+		out <- [param worker]Add Wire[start index, output num, end index, input num]
+	}{}{
+		out <- Fold[Add Multi Wire[?, ?, ?, end index, input num], param worker, ~]
+	}
+}
+
+_Add Block Wire[worker,node,junk,blocks,parse worker,assignments:out]
+{
+	out <- [node]Add Wires[worker, blocks, parse worker, assignments]
+}
+
+Add Block Wire[worker,block nodes,output num,parent index,existing blocks,parse worker,assignments:out]
+{
+	blocks <- [existing blocks]Append[Output Reference[parent index, output num]]
+	out <- Fold[_Add Block Wire[?, ?, ?, blocks, parse worker, assignments], worker, block nodes]
+}
+
+Assignments Add Wires[worker,assignment,output num,parse worker,start index:out worker]
+{
+	[[parse worker]Outputs >>]Find[=[assignment,?]]
+	{
+		,output index <- [worker]Add Typed Output[assignment, ~, [[parse worker]Output Types >>]Index[~]]
+		{
+			out worker <- [~]Add Wire[start index, output num, output index, 0]
+		}
+	}{
+		//Ugly hack alert!
+		If[[assignment]Contains["::"]]
+		{
+			parts <- [assignment]Split["::"]
+			,global index <- [worker]Add Global Set[[parts]Index[0], [parts]Index[1]]
+			{
+				out worker <- [~]Add Wire[start index, output num, global index, 0]
+			}
+		}{
+			out worker <- worker
+		}
+	}
+}
+
+Has Block@Worker Node[junk:out,unused]
+{
+	out <- Yes
+}
+
+_Has Block Params[param list,key:out]
+{
+	param <- [param list]Index[key]
+	out <- [param]Has Block {}
+	{
+		[param list]Next[key]
+		{
+			out <- _Has Block Params[param list, ~]
+		}{
+			out <- No
+		}
+	}
+	
+}
+
+Has Block Params[param list:out]
+{
+	[param list]First
+	{
+		out <- _Has Block Params[param list, ~]
+	}{
+		out <- No
+	}
+}
+
+Add Wires@Worker Node[node,worker,blocks,parse worker,assignments:outworker,index,num,unused]
+{
+	outworker,index,num <- Add Wires Worker or Field[node, worker, blocks, parse worker, assignments]
+}
+
+Add Wires Worker or Field[node,worker,blocks,parse worker,assignments:outworker,index,num,unused]
+{
+	Fold[Assignments Add Wires[?, ?, ?, parse worker, [node]Index >>], worker, [node]Assignments >>]
+	{
+		Fold[Add Block Wire[?, ?, ?, [node]Index >>, blocks, parse worker, assignments], ~, [node]Blocks >>]
+		{ 
+			params worker <- Fold[Add Param Wire[?, ?, ?, [node]Index >>, blocks, parse worker, assignments], ~, [node]Params >>] 
+			{
+				index <- [node]Index >>
+				num <- 0
+			}
+		}
+	}
+	If[Has Block Params[[node]Params >>]]
+	{
+		outworker <- Val[params worker]
+	}{
+		[blocks]Peek
+		{
+			outworker <- [params worker]Add Wire[[~]Index >>, [~]Output Number >>, [node]Index >>, [0]-[1]]
+		}{
+			outworker <- Val[params worker]
+		}
+	}
+}
+
+Blueprint Field Node
+{
+	Name
+	Params
+	Assignments
+	Blocks
+	Index
+	Set?
+}
+
+Has Block@Field Node[junk:has block,unused]
+{
+	has block <- Yes
+}
+
+Field Node[name,params,set:out]
+{
+	out <- [[[[[Build[Field Node()]]Name <<[name]]Assignments <<[()]]Blocks <<[()]]Set? <<[set]]Params <<[params]
+}
+
+Add to Worker@Field Node[node,worker,program,parse worker,refs:out node,out worker,out refs]
+{
+	If[[node]Set? >>]
+	{
+		after worker,index <- [worker]Add Object Set[[node]Name >>]
+	}{
+		after worker,index <- [worker]Add Object Get[[node]Name >>]
+	}
+	Val[index]
+	{
+		assignment refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>]
+		[node]Index <<[~]
+		{ 
+			params list, params worker, params refs <- Add List to Worker[[~]Params >>, after worker, program, parse worker, assignment refs]
+			block list, out worker, out refs <- Add Blocks to Worker[[~]Blocks >>, params worker, program, parse worker, params refs]
+			out node <- [[~]Params <<[params list]]Blocks <<[block list]
+		}
+	}
+}
+
+Add Wires@Field Node[node,worker,blocks,parse worker,assignments:outworker,index,num]
+{
+	outworker,index,num <- Add Wires Worker or Field[node, worker, blocks, parse worker, assignments]
+}
+
+Check Worker Literals@Field Node[node,program:out]
+{
+	new params <- Map[[node]Params >>, Check Worker Literals[?, program]]
+	out <- [[node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ]
+		]Params <<[new params]
+}
+
+Blueprint Named Pipe Node
+{
+	Name
+	Assignments
+	Blocks
+	Index
+}
+
+Has Block@Named Pipe Node[node:has block,no block]
+{
+	If[[[node]Index >>] < [0]]
+	{
+		//~ should really be a parser parameter
+		If[[[node]Name >>] = ["~"]]
+		{
+			has block <- Yes
+		}{
+			no block <- No
+		}
+	}{
+		has block <- Yes
+	}
+}
+
+Named Pipe Node[name:out]
+{
+	out <- [[[Build[Named Pipe Node()]]Name <<[name]]Assignments <<[()]]Blocks <<[()]
+}
+
+Add to Worker@Named Pipe Node[node,worker,program,parse worker,refs:out node,out worker,out refs]
+{
+	[[parse worker]Inputs >>]Find[=[[node]Name >>, ?]]
+	{
+		after add <- [worker]Add Typed Input[[node]Name >>, ~, [[parse worker]Input Types>>]Index[~]] {}
+		{
+			assign refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>]
+			index node <- [node]Index <<[~]
+		}
+	}{
+		after add <- worker
+		index node <- [node]Index <<[[0]-[1]]
+		//TODO: Handle assignments from a named pipe that isn't an input
+		assign refs <- refs
+	}
+	block list, out worker, out refs <- Add Blocks to Worker[[node]Blocks >>, after add, program, parse worker, assign refs]
+	out node <- [index node]Blocks <<[block list]
+}
+
+Add Wires@Named Pipe Node[node,worker,blocks,parse worker,assignments:outworker,index,num,reflist]
+{
+	reflist <- [assignments]Index[[node]Name >>]
+	{ 
+		//TODO: Fix support for a named pipe with a block
+		outworker <- worker 
+	}{
+		If[[[node]Name >>] = ["~"]]
+		{
+			wires worker <- worker
+			[blocks]Peek
+			{
+				my index <- [~]Index >>
+				num <- [~]Output Number >>
+			}{
+				//TODO: Propagate an error rather than printing it out
+				Print["Error, block reference symbol  located outside of a block"]
+			}
+		}{
+			If[[[node]Index >>] < [0]]
+			{
+				Print[[[["Error, reference to named pipe "]Append[[node]Name >>]]Append[" that was never assigned to in worker "]]Append[[parse worker]Name >>]]
+			}{
+				my index <- [node]Index >>
+				num <- 0
+				assignments worker <- Fold[Assignments Add Wires[?, ?, ?, parse worker, [node]Index >>], worker, [node]Assignments >>]
+				[blocks]Peek
+				{
+					wires worker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number >>, [node]Index >>, [0]-[1]]
+				}{
+					wires worker <- Val[assignments worker]
+				}
+			}
+		}
+	}
+	index <- Val[my index]
+	
+	outworker <- Fold[Add Block Wire[?, ?, ?, my index, blocks, parse worker, assignments], wires worker, [node]Blocks >>]
+}
+
+Check Worker Literals@Named Pipe Node[node,program:out]
+{
+	out <- [node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ]
+}
+
+Blueprint Global Node
+{
+	Store
+	Name
+	Assignments
+	Blocks
+	Index
+}
+
+Global Node[store,name:out]
+{
+	out <- [[[[Build[Global Node()]]Store <<[store]]Name <<[name]]Assignments <<[()]]Blocks <<[()]
+}
+
+Add to Worker@Global Node[node,worker,unused,parse worker,refs:out node,out worker,outrefs]
+{
+	out worker <- [worker]Add Global Get[[node]Store >>, [node]Name >>] {}
+	{
+		outrefs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>]
+		out node <- [node]Index <<[~]
+	}
+	outrefs <- refs
+}
+
+Add Wires@Global Node[node,worker,blocks,parse worker,assignments:outworker,index,num,unused]
+{
+	outworker,index,num <- Add Wires Literal or Global[node, worker, blocks, parse worker, assignments]
+}
+
+Has Block@Global Node[junk:out,unused]
+{
+	out <- Yes
+}
+
+Check Worker Literals@Global Node[node,program:out]
+{
+	out <- [node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ]
+}
+
+Blueprint Literal Node
+{
+	Value
+	Assignments
+	Blocks
+	Index
+}
+
+Has Block@Literal Node[junk:out,unused]
+{
+	out <- Yes
+}
+
+Literal Node[value:out]
+{
+	out <- [[[Build[Literal Node()]]Value <<[value]]Assignments <<[()]]Blocks <<[()]
+}
+
+Add to Worker@Literal Node[node,worker,unused,parse worker,refs:out node,out worker,out refs]
+{
+	out worker <- [worker]Add Constant[[node]Value >>] {}
+	{
+		out refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>]
+		out node <- [node]Index <<[~]
+	}
+}
+
+Add Wires@Literal Node[node,worker,blocks,parse worker,assignments:outworker,index,num,unused]
+{
+	outworker,index,num <- Add Wires Literal or Global[node, worker, blocks, parse worker, assignments]
+}
+
+Check Worker Literals@Literal Node[node,program:out]
+{
+	out <- [node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ]
+}
+
+Add Wires Literal or Global[node,worker,blocks,parse worker,junk:outworker,index,num,unused]
+{
+	assignments worker <- Fold[Assignments Add Wires[?, ?, ?, parse worker, [node]Index >>], worker, [node]Assignments >>]
+	[blocks]Peek
+	{
+		outworker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number>>, [node]Index >>, [0]-[1]]
+	}{
+		outworker <- Val[assignments worker]
+	}
+	index <- [node]Index >>
+	num <- 0
+}
+
+Blueprint Block Node
+{
+	Number
+}
+
+Blueprint Parse Error
+{
+	Type
+	Text
+	Line Number
+}
+
+Parse Error[type,text,number:out]
+{
+	out <- [[[Build[Parse Error()]]Type <<[type]]Text <<[text]]Line Number <<[number]
+}
+
+Not Empty[string:out]
+{
+	If[[[string]Length] > [0]]
+	{
+		out <- Yes
+	}{
+		out <- No
+	}
+}
+
+Blueprint Blueprint Field
+{
+	Name
+	Type
+}
+
+New Blueprint Field[name,type:out]
+{
+	out <- [[Build[Blueprint Field()]]Name <<[name]]Type <<[type]
+}
+
+Process Blueprint Field[list,field,params:out]
+{
+	,name <- [field]Get DString[[params]List Begin >>]
+	{
+		type info <- Parse List[~,params,()]
+		type <- [type info]Index[0]
+		{
+			If[[Blueprint Of[~]] = [Named Pipe Node()]]
+			{
+				before variant <- Type Instance[[type]Name >>]
+			}{
+				before variant <-  [type]Params <<[ Map[[type]Params >>, Remove Named Pipe Node[?]] ]
+			}
+			variant <- [type info]Index[1]
+			{
+				,warn <- If[[Blueprint Of[~]] = [Named Pipe Node()]]
+				{
+					fieldtype,warn <- [before variant]Set Variant[[variant]Name >>]
+				}
+				Val[warn]
+				{
+					Print[[[["Warning: Invalid variant for type "]Append[[before variant]Name >>]]Append[" on field "]]Append[name]]
+					fieldtype <- Val[before variant]
+				}
+			}{
+				fieldtype <- Val[before variant]
+			}
+		}{
+			fieldtype <- Type Instance["Any Type"]
+		}
+		out <- [list]Append[New Blueprint Field[name, fieldtype]]
+	} {} {} {
+		out <- [list]Append[New Blueprint Field[name, Type Instance["Any Type"]]]
+	}
+}
+
+Block Comment[string,begin comment,end comment,block count:out]
+{
+	If[[block count] > [0]]
+	{
+		after, before <- [string]Get DString[[[()]Append[begin comment]]Append[end comment]] {} {}
+		{
+			If[[~] = [begin comment]]
+			{
+				out <- Block Comment[after, begin comment, end comment, [block count]+[1]]
+			}{
+				out <- Block Comment[after, begin comment, end comment, [block count]-[1]]
+			}
+		}{
+			//No match
+			out <- ""
+		}
+	}{
+		out <- string
+	}
+}
+
+Line Comment[string:out]
+{
+	[string]Get DString["\n"]
+	{
+		out <- ["\n"]Append[~]
+	} {} {} {
+		out <- ""
+	}
+}
+
+_Get Comment DString[string,delims,line comment,begin comment,end comment,prev before:rest,before,delim,nomatch]
+{
+	after,befored,used delim,nomatch <- [string]Get DString[delims]
+	{
+		If[[used delim] = [line comment]]
+		{
+			after comment <- Line Comment[after]
+		}{
+			If[[used delim] = [begin comment]]
+			{
+				after comment <- Block Comment[after, begin comment, end comment, 1]	
+			}{
+				rest <- Val[after]
+				before <- [prev before]Append[befored]
+				delim <- Val[used delim]
+			}
+		}
+	} {} {} {
+		before <- [prev before]Append[befored]
+	}
+	
+	after comment
+	{
+		rest,more before,delim,nomatch <- _Get Comment DString[~, delims, line comment, begin comment, end comment, prev before]
+		before <- [before]Append[more before]
+	}
+		
+}
+
+As List[val:out]
+{
+	[(List(),List Leaf())]Find[=[Blueprint Of[val], ?]]
+	{
+		out <- val
+	}{
+		out <- [()]Append[val]
+	}
+}
+
+Get Comment DString[string,delims,params:rest,before,delim,not found]
+{
+	line comment <- [params]Line Comment >>
+	begin comment <- [params]Comment Begin >>
+	end comment <- [params]Comment End >>
+	all delims <- [[[delims]As List]Append[begin comment]]Append[line comment]
+	rest, before, delim, not found <- _Get Comment DString[string, delims, line comment, begin comment, end comment, ""]
+}
+
+Comment Left Trim[string,trim chars,params:out]
+{
+	line comment <- [params]Line Comment >>
+	
+	end comment <- [params]Comment End >>
+	trimmed <- Left Trim[string, trim chars]
+	If[[trimmed]Starts With[line comment]]
+	{
+		,after delim <- [trimmed]Slice[[line comment]Length]
+		out <- Comment Left Trim[Line Comment[after delim], trim chars, params]
+	}{
+		begin comment <- [params]Comment Begin >>
+		If[[trimmed]Starts With[begin comment]]
+		{
+			,after delim <- [trimmed]Slice[[line comment]Length]
+			out <- Comment Left Trim[Block Comment[after delim, begin comment, end comment, 1], trim chars, params]
+		}{
+			out <- Val[trimmed]
+		}
+	}
+}
+
+PBlueprint[string,params,tree,lines:out]
+{
+	,whitespace name <- [string]Get Comment DString[[params]Block Begin >>, params]
+	{	
+		,no blueprint <- [whitespace name]Slice[ [[params]Blueprint >>]Length ]
+		name <- Trim[no blueprint, "\r\n\t "]
+		name lines <- 0
+		,body <- [~]Get Comment DString[ [params]Block End >>, params]
+		{
+			body lines <- [body]Split["\n"]
+			more lines <- [[[body lines]Length] - [1]] + [name lines]
+			fields <- Fold[Process Blueprint Field[?, ?, params], (), Filter[Map[body lines, Trim[?,"\n\r\t "]], Not Empty[?]]]
+			new tree <- [tree]Blueprints << [ [[tree]Blueprints >>]Set[name, New Blueprint Definition[name, fields]] ]
+			out <- Null[~, params, new tree, [lines] + [more lines]]
+		} {} {
+			out <- [tree]Errors <<[ [[tree]Errors >>]Append[Parse Error["Error",[["Blueprint is missing an block close symbol \""]Append[[params]Block End >>]]Append["\""], lines]] ]
+		}
+		
+	} {} {
+		out <- [tree]Errors <<[ [[tree]Errors >>]Append[Parse Error["Error",[["Blueprint is missing an block open symbol \""]Append[[params]Block Begin >>]]Append["\""], lines]] ]
+	}
+}
+
+Parse Import[string,params,tree,lines:out]
+{
+	[line]Slice[ [[params]Import >>]Length ] {}
+	{
+		filename <- Trim[~, " \n\r\t"]
+	}
+	
+	new tree <- [tree]Imports <<[[[tree]Imports >>]Set[filename, Yes]]
+	
+	,line <- [string]Get Comment DString["\n", params]
+	{
+		out <- Null[~, params, new tree, [lines] + [1]]
+	} {} {} {
+		out <- Val[new tree]
+	}
+}
+
+Get Expression Blocks[string,params,blocks:outblocks,after]
+{
+	check block <- Comment Left Trim[string, "\n\r\t ", params]
+	If[[check block]Starts With[[params]Block Begin >>]]
+	{
+		,begin block <- [check block]Slice[[[params]Block Begin >>]Length]
+		trees, after block <- Worker Body[begin block, params, ()]
+		outblocks, after <- Get Expression Blocks[after block, params, [blocks]Append[trees]]
+	}{
+		If[[check block]Starts With[[params]Empty Block >>]]
+		{
+			outblocks <- blocks
+			,after <- [check block]Slice[[[params]Empty Block >>]Length]
+		}{
+			outblocks <- blocks
+			after <- Val[check block]
+		}
+	}
+}
+
+Parse Escape[string,params:char,after]
+{
+	code,rest <- [string]Slice[1]
+	If[[code] = [[params]Hex Escape >>]]
+	{
+		hex,after <- [rest]Slice[2]
+		char <- String[[Array[]]Append[Trunc UInt8[Abs UInt[Hex Int32[hex]]]]]
+	}{
+		after <- Val[rest]
+		char <- [[params]Escape Map >>]Index[code] {}
+		{
+			char <- Val[code]
+		}
+	}
+}
+
+Parse String[string,params,current:value,after]
+{
+	delims <- [[()]Append[[params]String End >>]]Append[[params]String Escape >>]
+	afters, before, delim <- [string]Get Comment DString[delims, params]
+	{
+		If[[delim] = [[params]String End >>]]
+		{
+			value <- [current]Append[before]
+			after <- Val[afters]
+		}{
+			char,after escape <- Parse Escape[afters, params]
+			value,after <- Parse String[after escape, params, [[current]Append[before]]Append[char]]
+		}
+	}
+}
+
+Parse List[string,params,list:value,after]
+{
+	trimmed <- Comment Left Trim[string, "\r\n\t ", params]
+	If[[trimmed]Starts With[[params]List End >>]]
+	{
+		value <- list
+		,after <- [trimmed]Slice[[[params]List End >>]Length]
+	}{
+		If[[trimmed]Starts With[[params]List Delim >>]]
+		{
+			,el string <- [trimmed]Slice[[[params]List Delim >>]Length]
+		}{
+			el string <- Val[trimmed]
+		}
+		element,after el <- Named Pipe or Literal[el string, params]
+		value,after <- Parse List[after el, params, [list]Append[[element]Get Value]]
+	}
+}
+
+Get Value@Literal Node[node:out]
+{
+	out <- [node]Value >>
+}
+
+Get Value@Named Pipe Node[node:out]
+{
+	out <- node
+}
+
+Machine Integer[val, size, signed?:out]
+{
+	conv <- [[[[[[[[()
+	]Append[UInt8[?]]
+	]Append[Int8[?]]
+	]Append[UInt16[?]]
+	]Append[Int16[?]]
+	]Append[UInt32[?]]
+	]Append[Int32[?]]
+	]Append[UInt64[?]]
+	]Append[Int64[?]]
+	
+	base idx <- [[(8,16,32,64)]Find[=[size,?]]]*[2]
+	
+	If[signed?]
+	{
+		idx <- [base idx]+[1]
+	}{
+		idx <- Val[base idx]
+	}
+	out <- [[conv]Index[idx]]Call[val]
+}
+
+Parse Number[string,params:value,after]
+{
+	delims <- [[[[(" ","\t","\n","\r")]Append[[params]List Delim >>]]Append[[params]Block Begin >>]]Append[[params]Arg End >>]]Append[[params]List End >>]
+	after delim,valstring <- [string]Get Comment DString[delims, params] {} {}
+	{
+		after <- [~]Append[after delim]
+	}{
+		after <- ""
+	}
+	first two,rest <- [valstring]Slice[2]
+	If[[first two] = ["0x"]]
+	{
+		value <- Hex Int32[rest]
+	}{
+		If[[valstring]Contains["."]]
+		{
+			value <- Real64[valstring]
+		}{
+			size, val, type <- [valstring]Get DString[("i","u")]
+			{
+				value <- Machine Integer[val, Int32[size], [type]=["i"]]
+			} {} {} {
+				value <- Int32[valstring]
+			}
+		}
+	}
+}
+
+Parse Params@Type Instance[literal,params,string:out,after]
+{
+	plist,after <- Parse List[string,params,()]
+	out <- [literal]Params <<[plist]
+}
+
+Named Pipe or Literal[string,params:out,after]
+{
+	name <- Comment Left Trim[string, "\n\r\t ", params]
+	If[[name]Starts With[[params]String Begin >>]]
+	{
+		,string begin <- [name]Slice[[[params]String Begin >>]Length]
+		value,after <- Parse String[string begin, params, ""]
+	}{
+		If[[name]Starts With[[params]List Begin >>]]
+		{
+			,list start <- [name]Slice[[[params]List Begin >>]Length]
+			value,after <- Parse List[list start, params, ()]
+		}{
+			If[[[name]Slice[1]]In["-0123456789"]]
+			{
+				value,after <- Parse Number[name, params]
+			}{
+				delims <- [[[[[[[("\n")]Append[[params]Block Begin >>]]Append[[params]Block End >>]]Append[[params]Empty Block >>]]Append[[params]Arg End >>]]Append[[params]List Delim >>]]Append[[params]List End >>]]Append[[params]List Begin >>]
+				afterdelim,raw before,delim,nodelim <- [name]Get Comment DString[delims, params]
+
+				before <- Trim[raw before, "\r\n\t "]
+				If[[delim] = [[params]List Begin >>]]
+				{
+					value,after <- [Type Instance[before]]Parse Params[params,afterdelim]
+				}{
+					Val[afterdelim]
+					{
+						after <- [delim]Append[~]
+					}
+					Val[nodelim]
+					{
+						after <- ""
+					}
+					If[[before] = ["Yes"]]
+					{
+						yesno <- Yes
+					}{
+						If[[before] = ["No"]]
+						{
+							yesno <- No
+						}{
+							If[[before] = [""]]
+							{
+								Print[[["Found "]Append[delim]]Append[" where a named pipe or literal was expected"]]
+								{ Print[["Near: "]Append[ [afterdelim]Slice[80]]] }
+							}{
+								If[[before]Contains[[params]Global Separator >>]]
+								{
+									parts <- [before]Split[[params]Global Separator >>]
+									out <- Global Node[Right Trim[[parts]Index[0],"\r\n\t "], Trim[[parts]Index[1], "\r\n\t "]]
+								}{
+									out <- Named Pipe Node[Right Trim[before,"\r\n\t "]]
+								}
+							}
+						}
+					}
+					out <- Literal Node[yesno]
+				}
+			}
+		}
+	}
+	out <- Literal Node[value]
+}
+
+Parse Arguments[string,params,arglist:args,after]
+{
+	targs <- Comment Left Trim[string, "\r\n\t ", params]
+	If[[targs]Starts With[[params]List Delim >>]]
+	{
+		[targs]Slice[[[params]List Delim >>]Length] {} 
+		{
+			final args <- Comment Left Trim[~, "\r\n\t ", params]
+		}
+	}{
+		If[[targs]Starts With[[params]Arg End >>]]
+		{
+			args <- arglist
+			,after <- [targs]Slice[[[params]Arg End >>]Length]
+		}{
+			final args <- Val[targs]
+		}
+	}
+	arg, after arg <- Parse Expression[final args, params]
+	args, after <- Parse Arguments[after arg, params, [arglist]Append[arg]]
+}
+
+Worker or Field[name,args,params:out]
+{
+	get field <- [params]Get Field >>
+	If[[name]Ends With[get field]]
+	{
+		field <- Right Trim[[name]Slice[[[name]Length] - [[get field]Length]], "\n\r\t "]
+		out <- Field Node[field, args, No]
+	}{
+		set field <- [params]Set Field >>
+		If[[name]Ends With[set field]]
+		{
+			field <- Right Trim[[name]Slice[[[name]Length] - [[set field]Length]], "\n\r\t "]
+			out <- Field Node[field, args, Yes]
+		}{
+			out <- Worker Node[name, args]
+		}
+	}
+}
+
+Prefix[string,params,name,existing args:expression,after]
+{	
+	//Parse argument list
+	more args,after <- Parse Arguments[string, params, existing args]
+	expression <- Worker or Field[name, more args, params]
+}
+
+Postfix or Infix[string,params:expression,after]
+{
+	args, after args <- Parse Arguments[string, params, ()]
+	delims <- [[[[[("\n")]Append[[params]Arg Begin >>]]Append[[params]Empty Block >>]]Append[[params]Block Begin >>]]Append[[params]Arg End >>]]Append[[params]List Delim >>]
+	aftere,before,delim <- [after args]Get Comment DString[delims, params]
+	{
+		If[[delim] = [[params]Arg Begin >>]]
+		{
+			expression, after <- Prefix[aftere, params, Trim[before,"\r\n\t "], args]
+		}{
+			If[[delim] = [[params]Empty Block >>]]
+			{
+				after <- Val[aftere]
+			}{
+				,after <- [after args]Slice[[before]Length]
+			}
+			expression <- Worker or Field[Trim[before,"\r\n\t "], args, params]
+		}
+	}
+}
+
+Parse Expression[trimmed,params:final expression,after blocks]
+{
+	delims <- [[[[[[[("\n")]Append[[params]Arg Begin >>]]Append[[params]Arg End >>]]Append[[params]Assign >>]]Append["\n"]]Append[[params]Empty Block >>]]Append[[params]Block End >>]]Append[[params]String Begin >>]
+	after, before, delim <- [trimmed]Get Comment DString[delims, params]
+	{
+		//If we find an arg begin token, we have a worker expression
+		If[[delim] = [[params]Arg Begin >>]]
+		{
+			maybe name <- Right Trim[before, "\r\t "]
+			//Prefix expressions will have the worker name before the first arg begin token
+			If[[maybe name] = [""]]
+			{
+				expression, after expression <- Postfix or Infix[after, params]
+			}{
+				If[[maybe name]Contains[[params]List Delim >>]]
+				{
+					after expression <- [after literal]Append[[delim]Append[after]]
+					expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params]
+				}{
+					expression, after expression <- Prefix[after, params, maybe name, ()]
+				}
+			}
+		}{
+			If[[delim] = [[params]Assign >>]]
+			{
+				//Expressions starting with an assignment can be prefix, postfix or infix
+				//or they can be a simple literal or named pipe
+				assignments <- Map[[before]Split[[params]List Delim >>], Trim[?,"\n\r\t "]]
+				,after blocks <- Parse Expression[Comment Left Trim[after, " \n\r\t", params], params]
+				{
+					final expression <- [~]Assignments <<[assignments]
+				}
+			}{
+				//If[[delim] = [[params]String Begin >>]]
+				//{
+				//	If[[Trim[before, "\r\n\t "]] = [""]]
+				//	{
+				//		expression, after expression <- Named Pipe or Literal[[delim]Append[after], params]
+				//	}{
+				//		after expression <- [after literal]Append[[delim]Append[after]]
+				//		expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params]
+				//	}
+				//}{
+				//	after expression <- [after literal]Append[[delim]Append[after]]
+				//	expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params]
+				//}
+				expression, after expression <- Named Pipe or Literal[trimmed, params]
+			}
+		}
+		//Any expression can be followed by one or more blocks mapping the inputs of other expressions
+		//to the outputs of the current one
+		blocks,after blocks <- Get Expression Blocks[after expression, params, ()]
+		final expression <- [expression]Blocks <<[blocks]
+	}
+}
+
+Worker Body[string,params,trees:outtrees,after end]
+{
+	trimmed <- Comment Left Trim[string, "\n\r\t ", params]
+	If[[trimmed]Starts With[[params]Block End >>]]
+	{
+		//We're done with this block, return
+		,after end <- [trimmed]Slice[[[params]Block End >>]Length]
+		outtrees <- trees
+	}{
+		expression, after expression <- Parse Expression[trimmed, params]
+		outtrees,after end <- Worker Body[after expression, params, [trees]Append[expression]]
+	}
+}
+
+Process Modifiers[worker,params,modifiers:out]
+{
+	//Eventually this will need to be more sophisticated to handle more modifiers
+	trimmed <- Comment Left Trim[modifiers, "\n\r\t ", params]
+	If[[trimmed]Starts With[[params]Uses >>]]
+	{
+		,after uses <- [trimmed]Slice[[[params]Uses >>]Length]
+		,stores string <- [after uses]Get Comment DString["\n", params]
+		out <- [worker]Uses Stores <<[Map[[stores string]Split[[params]List Delim >>], Trim[?, "\r\n\t "]]]
+	}{
+		out <- worker
+	}
+}
+
+Remove Named Pipe Node[element:out]
+{
+	If[[Blueprint Of[element]] = [Named Pipe Node()]]
+	{
+		out <- [element]Name >>
+	}{
+		If[[Blueprint Of[element]] = [Type Instance()]]
+		{
+			out <- [element]Params <<[ Map[[element]Params >>, Remove Named Pipe Node[?]] ]
+		}{
+			out <- element
+		}
+	}
+}
+
+Parse Param List[text,paramlist,typelist,params:out params,out types]
+{
+	delims <- [[()]Append[[params]List Begin >>]]Append[[params]List Delim >>]
+	after,param name <-[text]Get DString[delims] {}
+	{
+		tname <- Trim[~, "\r\n\t "]
+		If[[tname] = [""]]
+		{
+			nextlist <- Val[paramlist]
+			next types <- Val[typelist]
+		}{
+			nextlist <- [paramlist]Append[tname]
+			next types <-  [typelist]Append[paramtype]
+		}
+	}{
+		If[[~] = [[params]List Begin >>]]
+		{
+			type info,after type <- Parse List[after,params,()]
+			type <- [type info]Index[0]
+			{
+				If[[Blueprint Of[~]] = [Named Pipe Node()]]
+				{
+					before variant <- Type Instance[[type]Name >>]
+				}{
+					before variant <- <- [type]Params <<[ Map[[type]Params >>, Remove Named Pipe Node[?]] ]
+				}
+				variant <- [type info]Index[1]
+				{
+					,warn <- If[[Blueprint Of[~]] = [Named Pipe Node()]]
+					{
+						before mutable,warn <- [before variant]Set Variant[[variant]Name >>]
+					}
+					Val[warn]
+					{
+						Print[[[["Warning: Invalid variant for type "]Append[[before variant]Name >>]]Append[" on input "]]Append[param name]]
+						before mutable <- Val[before variant]
+					}
+				}{
+					before mutable <- Val[before variant]
+				}
+				[type info]Index[2]
+				{
+					paramtype <- [before mutable]Mutable? <<[ [[~]Name >>] = ["Mutable"] ]
+				}{
+					paramtype <- Val[before mutable]
+				}
+			}{
+				paramtype <- Type Instance["Any Type"]
+			}
+			[after type]Get DString[","]
+			{
+				out params,out types <- Parse Param List[~,nextlist,next types,params]
+			} {} {} {
+				out params <- Val[nextlist]
+				out types <- Val[next types]
+			}
+		}{
+			paramtype <- Type Instance["Any Type"]
+			out params,out types <- Parse Param List[after,nextlist,next types,params]
+		}
+		
+	}{
+		paramtype <- Type Instance["Any Type"]
+		out params <- Val[nextlist]
+		out types <- Val[next types]
+	}
+}
+
+Worker Declaration[string,params:worker,rest,no match]
+{
+	,whitespace name <- [string]Get Comment DString[[params]Arg Begin >>, params]
+	{
+		worker name <- Trim[whitespace name, "\n\r\t "]
+		in out <- [params]In Out Delim >>
+		arg end <- [params]Arg End >>
+		delims <- [[()]Append[in out]]Append[arg end]
+		after <- [~]Get Comment DString[delims, params] {} 
+		{
+			arglist <- Trim[~,"\r\n\t "]
+		}{
+			//check if there is an in/out separator
+			//if it isn't present, everything in the arglist is an input
+			If[[~] = [in out]]
+			{
+				rest <- [after]Get Comment DString[arg end, params] {}
+				{
+					outputs,output types <- Parse Param List[~, (), (), params]
+				}
+			}{
+				rest <- Val[after]
+				outputs <- ()
+				output types <- ()
+			}
+			inputs,input types <- Parse Param List[arglist, (), (), params]
+			worker <- Parse Worker[worker name, inputs, outputs, input types, output types, 0]
+		}
+	}{}{}{
+		no match <- string
+	}
+}
+
+Worker Name[string,params,tree,lines:out]
+{
+	,after arglist <- Worker Declaration[string, params]
+	{
+		worker name <- [~]Name >>
+		body text, modifiers <- [after arglist]Get Comment DString[[params]Block Begin >>, params]
+		modified <- Process Modifiers[~, params, modifiers]
+		expression trees, after body <- Worker Body[body text, params, ()]
+		worker <- [modified]Trees <<[expression trees]
+		new worker dict <- [[tree]Workers >>]Set[worker name, worker]
+		out <- Null[after body, params, [tree]Workers <<[new worker dict], 0]
+	} {} {
+		out <- tree
+	}
+}
+
+Parse Foreign Worker[tree, string, lib, params:out]
+{
+	,rest <- Worker Declaration[string, params]
+	{
+		foreign <- [~]Trees << [lib]
+		next <- [tree]Workers << [[[tree]Workers >>]Set[[foreign]Name >>, foreign]]
+		out <- Parse Foreign Worker[next, rest, lib, params]
+	} {} {
+		out <- tree
+	}
+}
+
+Parse Foreign[string,params,tree,lines:out]
+{	
+	,after foreign <- [string]Slice[[[params]Foreign >>]Length]
+	[after foreign]Get Comment DString[[params]Blueprint Type Delim >>, params]
+	{
+		[~]Get Comment DString[[params]Block Begin >>, params]
+		{
+			rest, body <- [~]Get Comment DString[[params]Block End >>, params]
+		}
+		{ lib <- Trim[~, "\r\n\t "] }
+	}
+	{ language <- Trim[~, "\r\n\t "] }
+	Parse Foreign Worker[tree, body, New Foreign Lib[language, lib], params]
+	{ 
+		out <- Null[rest, params, ~, 0]
+	}
+}
+
+Null[string,params,tree,lines:out]
+{
+	trimmed <- Comment Left Trim[string, " \n\r\t", params]
+	current line <- 0
+	If[[trimmed]Starts With[ [params]Blueprint >> ]]
+	{
+		out <- PBlueprint[trimmed, params, tree, current line]
+	}{
+		If[[trimmed]Starts With[ [params]Import >> ]]
+		{
+			out <- Parse Import[trimmed, params, tree, current line]
+		}{
+			If[[trimmed]Starts With[ [params]Foreign >> ]]
+			{
+				out <- Parse Foreign[trimmed, params, tree, current line]
+			}{
+				If[trimmed]
+				{
+					out <- Worker Name[trimmed, params, tree, current line]
+				}{
+					out <- tree
+				}
+			}
+		}
+	}
+}
+
+Check Worker Literals@Parse Worker[worker,program:out]
+{
+	[(List(),List Leaf())]Find[=[Blueprint Of[[worker]Trees >>], ?]]
+	{
+		out <- [worker]Trees <<[ Map[[worker]Trees >>, Check Worker Literals[?, program]] ]
+	}{
+		out <- worker
+	}
+}
+
+Register Workers Compile[prog, worker, name:out]
+{
+	//Print[["Registering "]Append[name]]
+	If[[ Blueprint Of[[worker]Trees >>] ] = [Foreign Lib()]]
+	{ convention <- Val[[[worker]Trees >>]Language >>] }
+	{ convention <- "rhope" }
+	out <- [prog]Register Worker[name, convention, [[worker]Inputs >>]Length, [[worker]Outputs >>]Length]
+}
+
+Add Workers Compile[prog, worker, name:out]
+{
+	Print[["Transforming "]Append[name]]
+		If[[Blueprint Of[[worker]Trees >>]] = [Foreign Lib()]]
+		{
+			//TODO: Handle foreign func
+			final nworker <- [[[[[NWorker[[[worker]Trees >>]Language >>]
+			]Inputs <<[ [worker]Inputs >> ]
+			]Input Types <<[ [worker]Input Types >> ]
+			]Outputs <<[ [worker]Outputs >> ]
+			]Output Types <<[ [worker]Output Types >> ]
+			]Library <<[ [[worker]Trees >>]Name >> ]
+			
+		}{
+			trees, nworker, refs <- Add List to Worker[[worker]Trees >>, [[NWorker["rhope"]]Uses[[worker]Uses Stores >>]]Outputs <<[ [worker]Outputs >> ], prog, worker, Dictionary[]]
+			{
+				final nworker <- Fold[Add Wires Helper[?, ?, ?, worker, refs], nworker, trees]
+			}
+			
+		}
+		out <- [prog]Bind Worker[name, final nworker]
+}
+
+Add Wires Helper[worker,node,unused,parse worker,assignments:out]
+{
+	out <- [node]Add Wires[worker, (), parse worker, assignments]
+}
+
+Add Blueprint Field[blueprint,field,unused:out]
+{
+	out <- [blueprint]Add Field[[field]Name >>, [field]Type >>]
+}
+
+Add Blueprint Compile[prog,def:out]
+{
+	out <- [prog]Bind Blueprint[[def]Name >>, Fold[Add Blueprint Field[?], NBlueprint[], [def]Fields >>]]
+}
+
+Tree to Program Native[parse tree:out]
+{
+	registered <- Fold[Register Workers Compile[?], [Fold[Add Blueprint Compile[?], NProgram[], [parse tree]Blueprints >>]]Register Builtins, [parse tree]Workers >>]
+	out <- Fold[Add Workers Compile[?], registered, [parse tree]Workers >>]
+	{ Print["Transformed AST to dataflow graph "] }
+}
+
+Needs Imports[needs import,not imported?,name:out]
+{
+	If[not imported?]
+	{
+		out <- [needs import]Append[name]
+	}{
+		out <- needs import
+	}
+}
+
+Do Import[tree,file name,unused,params:out]
+{
+	Print[["Parsing: "]Append[file name]]
+	file <- [File[file name]]Open["r"]
+	text <- String[[file]Read[[file]Length]]
+	after import <- Null[text, params, tree, 0]
+
+	out <- [after import]Imports <<[[[after import]Imports >>]Set[file name, No]]
+}
+
+Process Imports[parse tree,params:out]
+{
+	needs import <- Fold[Needs Imports[?], (), [parse tree]Imports >>]
+	If[[[needs import]Length] > [0]]
+	{
+		import tree <- Fold[Do Import[?, ?, ?, params], parse tree, needs import]
+		out <- Process Imports[import tree, params]
+	}{
+		out <- parse tree
+	}
+}
+
+Until End[text:out]
+{
+	line <- Get Input[]
+	If[[line] = ["End"]]
+	{
+		out <- [text]Append["\n"]
+	}{
+		out <- Until End[[[text]Append["\n"]]Append[line]]
+	}
+}
+
+Add If Store[stores,name,params:out]
+{
+	If[[name]Contains[[params]Global Separator >>]]
+	{
+		parts <- [name]Split[[params]Global Separator >>]
+		out <- [stores]Set[[parts]Index[0], Yes]
+	}{
+		out <- stores
+	}
+}
+
+Param Gather Stores[stores,node,params:out]
+{
+	out <- [node]Gather Stores[params, stores]
+}
+
+Gather Stores@Named Pipe Node[node,params,stores:out]
+{
+	out <- Fold[Add If Store[?, ?, params], stores, [node]Assignments >>]
+}
+
+Gather Stores@Global Node[node,params,stores:out]
+{
+	out <- [stores]Set[[node]Store >>, Yes]
+}
+
+Gather Stores@Worker Node[node,params,stores:out]
+{
+	//TODO: Handle blocks
+	store list <- Fold[Param Gather Stores[?, ?, params], stores, [node]Params >>]
+	out <- Fold[Add If Store[?, ?, params], store list, [node]Assignments >>]
+}
+
+Gather Stores@Field Node[node,params,stores:out]
+{
+	//TODO: Handle blocks
+	store list <- Fold[Param Gather Stores[?, ?, params], stores, [node]Params >>]
+	out <- Fold[Add If Store[?, ?, params], store list, [node]Assignments >>]
+}
+
+Gather Stores@Literal Node[node,params,stores:out]
+{
+	out <- Fold[Add If Store[?, ?, params], stores, [node]Assignments >>]
+}
+
+
+Main[args]
+{
+	fname <- [args]Index[1]
+	{
+		file <- [File[~]]Open["r"]
+		text <- String[[file]Read[[file]Length]]
+		params <- Parser[]
+		Print[["Parsing "]Append[fname]]
+		Null[text, params, Parse Program[], 0]
+		{
+			Print["Parsing imports"]
+			Process Imports[~, params]
+			{
+				tree <- [~]Workers << [ Map[[~]Workers >>, Check Worker Literals[?, ~]] ]
+				{ Print["Compiling"] }
+			}
+			compiled <- [Tree to Program Native[tree]]Compile Program[C Program[]]
+			{ Print["Compiled program to backend"] }
+			outfile <- [File[ [fname]Append[".c"] ]]Truncate
+			[outfile]Write[ [Flatten[[compiled]Text]]Buffer >> ]
+			{ Print[["Wrote output to "]Append[ [fname]Append[".c"] ]] }
+		}
+	}{
+		Print["You must provide a file name to compile"]
+	}
+}
--- a/runtime/func.h	Fri Aug 06 01:42:37 2010 -0400
+++ b/runtime/func.h	Mon Aug 09 02:03:57 2010 -0400
@@ -14,21 +14,21 @@
 
 
 typedef returntype (*rhope_func)(calldata *);
-typedef void (*special_func) (object *);
-
-#ifdef MULTI_SWITCH
-#define DispatchEntry(name) case FUNC_##name: goto f_##name;
-#define ResumeEntry(num,name) case RES_##num##_##name: goto r##num##_##name;
-#define DispatchVar
-#define DISPATCH switch(func) { DispatchEntries }
-#define EndEntry case END: goto DO_END;
-#else
-#define DispatchEntry(name) &&f_##name,
-#define ResumeEntry(num,name) &&r##num##_##name,
-#define DispatchVar void * funcs[] = { DispatchEntries };
-#define DISPATCH goto *funcs[func];
-#define EndEntry &&DO_END
-#endif
+typedef void (*special_func) (object *);
+
+#ifdef MULTI_SWITCH
+#define DispatchEntry(name) case FUNC_##name: goto f_##name;
+#define ResumeEntry(num,name) case RES_##num##_##name: goto r##num##_##name;
+#define DispatchVar
+#define DISPATCH switch(func) { DispatchEntries }
+#define EndEntry case END: goto DO_END;
+#else
+#define DispatchEntry(name) &&f_##name,
+#define ResumeEntry(num,name) &&r##num##_##name,
+#define DispatchVar void * funcs[] = { DispatchEntries };
+#define DISPATCH goto *funcs[func];
+#define EndEntry &&DO_END
+#endif
 
 
 #define MethodName(name,type) f_ ## name ## AT_ ## type
@@ -134,38 +134,48 @@
 
 #define PrepCall(callspace) cdata = alloc_cdata(ct, cdata, callspace);
 
-#define SetParam(num,value) cdata->params[num] = value;
-
-#define VCPrepCall(func,numparams) \
-	cdata = alloc_cdata(ct, cdata, numparams + ((t_Worker *)func)->payload.Count);\
-	vcparam_offset = 0;
-
-#define VCSetParam(func,num,value) \
-	while((num+vcparam_offset) < ((t_Worker *)func)->payload.Size && ((object **)(((t_Worker *)func)+1))[num+vcparam_offset])\
-	{\
-		cdata->params[num+vcparam_offset] = add_ref(((object **)(((t_Worker *)func)+1))[num+vcparam_offset]);\
-		++vcparam_offset;\
-	}\
-	cdata->params[num+vcparam_offset] = value;\
-	last_vcparam = num+vcparam_offset;
-
-#define ValCall(tocall,numparams,resumeto,myname)\
-	last_vcparam++;\
-	while(last_vcparam < ((t_Worker *)tocall)->payload.Size)\
-	{\
-		if (((object **)(((t_Worker *)tocall)+1))[last_vcparam]) \
-			cdata->params[last_vcparam] = add_ref(((object **)(((t_Worker *)tocall)+1))[last_vcparam]);\
-		++last_vcparam;\
-	}\
+#define SetParam(num,value) cdata->params[num] = value;
+
+
+#define VCRePrepCall(func,numparams,lastnumparams) \
+	if(numparams + ((t_Worker *)func)->payload.Count > lastnumparams)\
+	{\
+		temp_cdata = cdata->lastframe;\
+		free_stack(ct, cdata);\
+		cdata = alloc_cdata(ct, temp_cdata, numparams + ((t_Worker *)func)->payload.Count);\
+	}\
+	vcparam_offset = 0;
+
+#define VCPrepCall(func,numparams) \
+	cdata = alloc_cdata(ct, cdata, numparams + ((t_Worker *)func)->payload.Count);\
+	vcparam_offset = 0;
+
+#define VCSetParam(func,num,value) \
+	while((num+vcparam_offset) < ((t_Worker *)func)->payload.Size && ((object **)(((t_Worker *)func)+1))[num+vcparam_offset])\
+	{\
+		cdata->params[num+vcparam_offset] = add_ref(((object **)(((t_Worker *)func)+1))[num+vcparam_offset]);\
+		++vcparam_offset;\
+	}\
+	cdata->params[num+vcparam_offset] = value;\
+	last_vcparam = num+vcparam_offset;
+
+#define ValCall(tocall,numparams,resumeto,myname)\
+	last_vcparam++;\
+	while(last_vcparam < ((t_Worker *)tocall)->payload.Size)\
+	{\
+		if (((object **)(((t_Worker *)tocall)+1))[last_vcparam]) \
+			cdata->params[last_vcparam] = add_ref(((object **)(((t_Worker *)tocall)+1))[last_vcparam]);\
+		++last_vcparam;\
+	}\
 	cdata->func = RES_  ## resumeto ## _ ## myname;\
-	cdata->num_params = numparams + ((t_Worker *)tocall)->payload.Count;\
-	cdata->vars = lv_ ## myname;\
-	func = ((t_Worker *)tocall)->payload.Index;
-
-#define ValCallPostlude(resumeto,myname)\
-r ## resumeto ## _ ## myname:\
+	cdata->num_params = numparams + ((t_Worker *)tocall)->payload.Count;\
+	cdata->vars = lv_ ## myname;\
+	func = ((t_Worker *)tocall)->payload.Index;
+
+#define ValCallPostlude(resumeto,myname)\
+r ## resumeto ## _ ## myname:\
 	my_cdata = cdata->lastframe;\
-	lv_ ## myname = cdata->vars;
+	lv_ ## myname = cdata->vars;
 
 
 #define Call(tocall, numparams, resumeto, myname)\
--- a/string.rhope	Fri Aug 06 01:42:37 2010 -0400
+++ b/string.rhope	Mon Aug 09 02:03:57 2010 -0400
@@ -106,7 +106,7 @@
 	{ out <- String[~] }
 }
 
-_String to Int32[current,index,array:out]
+_String to Int[current,index,array,ten,conv:out]
 {
 	char <- [array]Index[index]
 	{
@@ -118,7 +118,7 @@
 			{
 				out <- Val[current]
 			}{
-				out <- _String to Int32[[[current]*[10i32]]+[Int32[[char]-[48u8]]], [index]+[1], array]
+				out <- _String to Int[[[current]*[ten]]+[[conv]Call[[char]-[48u8]]], [index]+[1], array, ten, conv]
 			}
 		}
 		
@@ -127,6 +127,46 @@
 	}
 }
 
+U8toI8[val:out]
+{
+	out <- Trunc Int8[Int16[val]]
+}
+
+Int8@String[string:out]
+{
+	buf <- [string]Buffer >>
+	[buf]Index[0]
+	{
+		If[[~]=[45u8]]
+		{
+			out <- [0i8]-[_String to Int[0i8, 1, buf, 10i8, U8toI8[?]]]
+		}{
+			out <- _String to Int[0i8, 0, buf, 10i8, U8toI8[?]]
+		}
+	}{
+		out <- 0i8
+	}
+	
+}
+
+
+Int16@String[string:out]
+{
+	buf <- [string]Buffer >>
+	[buf]Index[0]
+	{
+		If[[~]=[45u8]]
+		{
+			out <- [0i16]-[_String to Int[0i16, 1, buf, 10i16, Int16[?]]]
+		}{
+			out <- _String to Int[0i16, 0, buf, 10i16, Int16[?]]
+		}
+	}{
+		out <- 0i16
+	}
+	
+}
+
 Int32@String[string:out]
 {
 	buf <- [string]Buffer >>
@@ -134,9 +174,9 @@
 	{
 		If[[~]=[45u8]]
 		{
-			out <- [0i32]-[_String to Int32[0i32, 1, buf]]
+			out <- [0i32]-[_String to Int[0i32, 1, buf, 10i32, Int32[?]]]
 		}{
-			out <- _String to Int32[0i32, 0, buf]
+			out <- _String to Int[0i32, 0, buf, 10i32, Int32[?]]
 		}
 	}{
 		out <- 0i32
@@ -144,6 +184,103 @@
 	
 }
 
+_Hex Int32[str,cur,idx:out]
+{
+	char <- [str]Byte[idx]
+	{
+		//0-9
+		[char]Between[47u8, 58u8]
+		{
+			adjust <- 48u8
+		}{
+			//A-F
+			[char]Between[64u8, 71u8]
+			{
+				adjust <- 55u8
+			}{
+				//a-f
+				[char]Between[96u8, 103u8]
+				{
+					adjust <- 87u8
+				}{
+					out <- cur
+				}
+			}
+		}
+		Val[adjust]
+		{
+			out <- _Hex Int32[str, [[cur]*[16i32]]+[Int32[[char]-[adjust]]], [idx]+[1]]
+		}
+	}{
+		out <- cur
+	}
+}
+
+Hex Int32[str:out]
+{
+	out <- _Hex Int32[str, 0i32, 0]
+}
+
+Int64@String[string:out]
+{
+	buf <- [string]Buffer >>
+	[buf]Index[0]
+	{
+		If[[~]=[45u8]]
+		{
+			out <- [0i64]-[_String to Int[0i64, 1, buf, 10i64, Int64[?]]]
+		}{
+			out <- _String to Int[0i64, 0, buf, 10i64, Int64[?]]
+		}
+	}{
+		out <- 0i64
+	}
+	
+}
+
+UInt8@String[string:out]
+{
+	out <- _String to Int[0u8, 0, [string]Buffer >>, 10u8, Val[?]]	
+}
+
+
+UInt16@String[string:out]
+{
+	out <- _String to Int[0u16, 0, [string]Buffer >>, 10u16, UInt16[?]]	
+	
+}
+
+UInt32@String[string:out]
+{
+	out <- _String to Int[0u32, 0, [string]Buffer >>, 10u32, UInt32[?]]	
+	
+}
+
+UInt64@String[string:out]
+{
+	out <- _String to Int[0u64, 0, [string]Buffer >>, 10u64, UInt64[?]]	
+}
+
+Int8@String Slice[string:out]
+{
+	out <- Int8[[string]Flatten]
+}
+
+Int8@String Cat[string:out]
+{
+	out <- Int8[[string]Flatten]
+}
+
+Int16@String Slice[string:out]
+{
+	out <- Int16[[string]Flatten]
+}
+
+Int16@String Cat[string:out]
+{
+	out <- Int16[[string]Flatten]
+}
+
 Int32@String Slice[string:out]
 {
 	out <- Int32[[string]Flatten]
@@ -154,6 +291,62 @@
 	out <- Int32[[string]Flatten]
 }
 
+Int64@String Slice[string:out]
+{
+	out <- Int64[[string]Flatten]
+}
+
+Int64@String Cat[string:out]
+{
+	out <- Int64[[string]Flatten]
+}
+
+UInt8@String Slice[string:out]
+{
+	out <- UInt8[[string]Flatten]
+}
+
+UInt8@String Cat[string:out]
+{
+	out <- UInt8[[string]Flatten]
+}
+
+UInt16@String Slice[string:out]
+{
+	out <- UInt16[[string]Flatten]
+}
+
+UInt16@String Cat[string:out]
+{
+	out <- UInt16[[string]Flatten]
+}
+
+UInt32@String Slice[string:out]
+{
+	out <- UInt32[[string]Flatten]
+}
+
+UInt32@String Cat[string:out]
+{
+	out <- UInt32[[string]Flatten]
+}
+
+UInt64@String Slice[string:out]
+{
+	out <- UInt64[[string]Flatten]
+}
+
+UInt64@String Cat[string:out]
+{
+	out <- UInt64[[string]Flatten]
+}
+
+//TODO: Implement me once Real64 support is added
+Real64[string:out]
+{
+	out <- string
+}
+
 Flatten@String[string:out]
 {
 	out <- string
@@ -236,10 +429,21 @@
 
 Slice@String[string,slicepoint:left,right]
 {
-	//TODO: Handle invalid slicepoints
-	sliceoffset <- CPOff to BOff[[string]Buffer >>, 0i32, 0i32, slicepoint]
-	left <- String Slice[string, 0i32, slicepoint, sliceoffset]
-	right <- String Slice[string, sliceoffset, [[string]Length >>]-[slicepoint], [[[string]Buffer >>]Length]-[sliceoffset]]
+	If[[slicepoint]>=[[string]Length]]
+	{
+		left <- string
+		right <- ""
+	}{
+		If[[slicepoint]<=[0]]
+		{
+			left <- ""
+			right <- string
+		}{
+			sliceoffset <- CPOff to BOff[[string]Buffer >>, 0i32, 0i32, slicepoint]
+			left <- String Slice[string, 0i32, slicepoint, sliceoffset]
+			right <- String Slice[string, sliceoffset, [[string]Length >>]-[slicepoint], [[[string]Buffer >>]Length]-[sliceoffset]]
+		}
+	}
 }
 
 Byte@String[string,index:out,invalid]
@@ -373,10 +577,21 @@
 
 Slice@String Slice[string,slicepoint:left,right]
 {
-	//TODO: Handle invalid slicepoints
-	sliceoffset <- CPOff to BOff[[[string]Source >>]Buffer >>, 0i32, [string]Offset >>, slicepoint]
-	left <- String Slice[[string]Source >>, [string]Offset >>, slicepoint, [sliceoffset]-[[string]Offset >>]]
-	right <- String Slice[[string]Source >>, sliceoffset, [[string]Length >>]-[slicepoint], [[string]Byte Length]-[[sliceoffset]-[[string]Offset >>]]]
+	If[[slicepoint]>=[[string]Length]]
+	{
+		left <- string
+		right <- ""
+	}{
+		If[[slicepoint]<=[0]]
+		{
+			left <- ""
+			right <- string
+		}{
+			sliceoffset <- CPOff to BOff[[[string]Source >>]Buffer >>, 0i32, [string]Offset >>, slicepoint]
+			left <- String Slice[[string]Source >>, [string]Offset >>, slicepoint, [sliceoffset]-[[string]Offset >>]]
+			right <- String Slice[[string]Source >>, sliceoffset, [[string]Length >>]-[slicepoint], [[string]Byte Length]-[[sliceoffset]-[[string]Offset >>]]]
+		}
+	}
 }
 
 Blueprint String Cat
@@ -679,3 +894,65 @@
 	{ out <- () }
 }
 
+In[needle,haystack:out]
+{
+	If[haystack]
+	{
+		out <- If[[[haystack]Slice[Length[needle]]]=[needle]] {}
+		{
+			[haystack]Slice[1] {}
+			{ out <- [needle]In[~] }
+		}
+	}{
+		out <- No
+	}
+}
+
+Left Trim[string,trim:trimmed]
+{
+	If[ [[string]Length] > [0] ]
+	{
+		first,rest <- [string]Slice[1]
+		If[ [first]In[trim] ]
+		{
+			trimmed <- Left Trim[rest, trim]
+		}{
+			trimmed <- string
+		}
+	}{
+		trimmed <- string
+	}
+}
+
+Right Trim[string,trim:trimmed]
+{
+	If[ [[string]Length] > [0] ]
+	{
+		rest,last <- [string]Slice[ [[string]Length] - [1]]
+		If[ [last]In[trim] ]
+		{
+			trimmed <- Right Trim[rest, trim]
+		}{
+			trimmed <- string
+		}
+	}{
+		trimmed <- string
+	}
+}
+
+Trim[string,trim:trimmed]
+{
+	left <- Left Trim[string, trim]
+	trimmed <- Right Trim[left, trim]
+}
+
+Contains[haystack,needle:out]
+{
+	[haystack]Partition[needle]
+	{
+		out <- Yes	
+	} {} {} {
+		out <- No
+	}
+}
+