view parser_old.rhope @ 138:1411de6050e1

First stab at transaction data structures, needs work
author Mike Pavone <pavone@retrodev.com>
date Tue, 16 Nov 2010 21:53:18 -0500
parents 04148770c229
children
line wrap: on
line source

Import nworker.rhope

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
}

New@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
}

New@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, New@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
}

New@Parse Program[:out]
{
	out <- [[[Build["Parse Program"]
	]Workers <<[Dictionary[]]
	]Imports <<[[Dictionary[]]Set["kernel.rhope", Yes]]
	]Blueprints <<[Dictionary[]]
}

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
}

New@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
}

New@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"]Set Input[3, parse worker]]Set Input[4, ~], 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[[Type 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[[Type Of[param]]=["Literal Node"]]
		{
			next literal <- [literal]Set Input[index, [param]Value >>]
			next complex <- Val[complex inputs]
		}{
			,doset <- If[[Type 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 <- New@Worker Node["Set Input", [[[()]Append[literal]]Append[New@Literal Node[index]]]Append[param]]
}

Check Worker Literals@Worker Node[node,program:out]
{
	new params <- Map[[node]Params >>, ["Check Worker Literals"]Set Input[1, 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", New@Literal Node[base literal], complex inputs]
	}{
		new node <- [node]Params <<[new params]
	}
	out <- [new node]Blocks <<[ Map[[node]Blocks >>, ["Map"]Set Input[1, ["Check Worker Literals"]Set Input[1, 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"]Set Input[3, end index]]Set Input[4, 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[New@Output Reference[parent index, output num]]
	out <- Fold[[[["_Add Block Wire"]Set Input[3, blocks]]Set Input[4, parse worker]]Set Input[5, 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:worker,index,num,unused]
{
	worker,index,num <- Add Wires Worker or Field[node, worker, blocks, parse worker, assignments]
}

Add Wires Worker or Field[node,worker,blocks,parse worker,assignments:worker,index,num,unused]
{
	Fold[[["Assignments Add Wires"]Set Input[3, parse worker]]Set Input[4, [node]Index >>], worker, [node]Assignments >>]
	{
		Fold[[[[["Add Block Wire"]Set Input[3, [node]Index >>]]Set Input[4, blocks]]Set Input[5, parse worker]]Set Input[6, assignments], ~, [node]Blocks >>]
		{ 
			params worker <- Fold[[[[["Add Param Wire"]Set Input[3, [node]Index >>]]Set Input[4, blocks]]Set Input[5, parse worker]]Set Input[6, assignments], ~, [node]Params >>] 
			{
				index <- [node]Index >>
				num <- 0
			}
		}
	}
	If[Has Block Params[[node]Params >>]]
	{
		worker <- Val[params worker]
	}{
		[blocks]Peek
		{
			worker <- [params worker]Add Wire[[~]Index >>, [~]Output Number >>, [node]Index >>, [0]-[1]]
		}{
			worker <- Val[params worker]
		}
	}
}

Blueprint Field Node
{
	Name
	Params
	Assignments
	Blocks
	Index
	Set?
}

Has Block@Field Node[junk:has block,unused]
{
	has block <- Yes
}

New@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"]Set Input[3, parse worker]]Set Input[4, ~], 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:worker,index,num]
{
	worker,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"]Set Input[1, program]]
	out <- [[node]Blocks <<[ Map[[node]Blocks >>, ["Map"]Set Input[1, ["Check Worker Literals"]Set Input[1, 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
	}
}

New@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"]Set Input[3, parse worker]]Set Input[4, ~], 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:worker,index,num,reflist]
{
	reflist <- [assignments]Index[[node]Name >>]
	{ 
		//TODO: Fix support for a named pipe with a block
		worker <- 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"]Set Input[3, parse worker]]Set Input[4, [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]
	
	worker <- Fold[[[[["Add Block Wire"]Set Input[3, my index]]Set Input[4, blocks]]Set Input[5, parse worker]]Set Input[6, assignments], wires worker, [node]Blocks >>]
}

Check Worker Literals@Named Pipe Node[node,program:out]
{
	out <- [node]Blocks <<[ Map[[node]Blocks >>, ["Map"]Set Input[1, ["Check Worker Literals"]Set Input[1, program]]] ]
}

Blueprint Global Node
{
	Store
	Name
	Assignments
	Blocks
	Index
}

New@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,refs]
{
	out worker <- [worker]Add Global Get[[node]Store >>, [node]Name >>] {}
	{
		refs <- Fold[[["Assignment Save Reference"]Set Input[3, parse worker]]Set Input[4, ~], refs, [node]Assignments >>]
		out node <- [node]Index <<[~]
	}
	refs <- refs
}

Add Wires@Global Node[node,worker,blocks,parse worker,assignments:worker,index,num,unused]
{
	worker,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"]Set Input[1, ["Check Worker Literals"]Set Input[1, program]]] ]
}

Blueprint Literal Node
{
	Value
	Assignments
	Blocks
	Index
}

Has Block@Literal Node[junk:out,unused]
{
	out <- Yes
}

New@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"]Set Input[3, parse worker]]Set Input[4, ~], refs, [node]Assignments >>]
		out node <- [node]Index <<[~]
	}
}

Add Wires@Literal Node[node,worker,blocks,parse worker,assignments:worker,index,num,unused]
{
	worker,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"]Set Input[1, ["Check Worker Literals"]Set Input[1, program]]] ]
}

Add Wires Literal or Global[node,worker,blocks,parse worker,junk:worker,index,num,unused]
{
	assignments worker <- Fold[[["Assignments Add Wires"]Set Input[3, parse worker]]Set Input[4, [node]Index >>], worker, [node]Assignments >>]
	[blocks]Peek
	{
		worker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number>>, [node]Index >>, [0]-[1]]
	}{
		worker <- Val[assignments worker]
	}
	index <- [node]Index >>
	num <- 0
}

Blueprint Block Node
{
	Number
}

Blueprint Parse Error
{
	Type
	Text
	Line Number
}

New@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[[Type 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[[Type 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]
	}
		
}

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"]Set Input[2, params], (), Filter[Map[body lines, ["Trim"]Set Input[1,"\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[New@Parse Error["Error",[["Blueprint is missing an block close symbol \""]Append[[params]Block End >>]]Append["\""], lines]] ]
		}
		
	} {} {
		out <- [tree]Errors <<[ [[tree]Errors >>]Append[New@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:blocks,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, ()]
		blocks, after <- Get Expression Blocks[after block, params, [blocks]Append[trees]]
	}{
		If[[check block]Starts With[[params]Empty Block >>]]
		{
			blocks <- blocks
			,after <- [check block]Slice[[[params]Empty Block >>]Length]
		}{
			blocks <- 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 <- [""]Put Byte[From Hex@Whole Number[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
}

Blueprint Machine Integer
{
	Value
	Size
	Signed?
}

Machine Integer[value,size,signed?:out]
{
	out <- [[[Build["Machine Integer"]]Value <<[value]]Size <<[size]]Signed? <<[signed?]
}

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 <- From Hex@Whole Number[rest]
	}{
		If[[valstring]Contains["."]]
		{
			value <- <String@Real Number[valstring]
		}{
			size, val, type <- [valstring]Get DString[("i","u")]
			{
				value <- Machine Integer[<String@Whole Number[val], <String@Whole Number[size], [type]=["i"]]
			} {} {} {
				value <- <String@Whole Number[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 <- New@Global Node[Right Trim[[parts]Index[0],"\r\n\t "], Trim[[parts]Index[1], "\r\n\t "]]
								}{
									out <- New@Named Pipe Node[Right Trim[before,"\r\n\t "]]
								}
							}
						}
					}
					out <- New@Literal Node[yesno]
				}
			}
		}
	}
	out <- New@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 <- New@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 <- New@Field Node[field, args, Yes]
		}{
			out <- New@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"]Set Input[1,"\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:trees,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]
		trees <- trees
	}{
		expression, after expression <- Parse Expression[trimmed, params]
		trees,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"]Set Input[1, "\r\n\t "]]]
	}{
		out <- worker
	}
}

Remove Named Pipe Node[element:out]
{
	If[[Type Of[element]] = ["Named Pipe Node"]]
	{
		out <- [element]Name >>
	}{
		If[[Type 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[[Type 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[[Type 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 <- New@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]
	{
		Print[worker name]
		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]
			}{
				out <- Worker Name[trimmed, params, tree, current line]
			}
		}
	}
}

Check Worker Literals@Parse Worker[worker,program:out]
{
	If[[Type Of[[worker]Trees >>]] = ["List"]]
	{
		out <- [worker]Trees <<[ Map[[worker]Trees >>, ["Check Worker Literals"]Set Input[1, program]] ]
	}{
		out <- worker
	}
}

Add Workers[workers,name,program:out]
{
	prog,worker <- [program]New Worker[name]
	[worker]Set IO Counts[ [[[workers]Index[name]]Inputs >>]Length, [[[workers]Index[name]]Outputs >>]Length]
	[workers]Next[name]
	{
		out <- Add Workers[workers, ~, prog]
	}{
		out <- Val[prog]
	}
}

Register Workers Compile[prog, worker, name:out]
{
	//Print[["Registering "]Append[name]]
	If[[ Type 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[[Type 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"]Set Input[3, worker]]Set Input[4, 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 Contents[parse worker,name,program:out,key]
{
	worker <- [[program]Find Worker[name]]Uses[[parse worker]Uses Stores >>]
	trees, contents worker, refs <- Add List to Worker[[parse worker]Trees >>, worker, program, parse worker, Dictionary[]]
	Fold[[["Add Wires Helper"]Set Input[3, parse worker]]Set Input[4, refs], contents worker, trees]
	out <- [parse worker]Trees <<[trees]
	key <- name
}

Add Blueprint Field[blueprint,field,unused:out]
{
	out <- [blueprint]Add Field[[field]Name >>, [field]Type >>]
}

Add Blueprint[prog,def:out]
{
	out <- [prog]New Blueprint[[def]Name >>] {}
	{	
		Fold["Add Blueprint Field", ~, [def]Fields >>]
	}
}

Add Blueprint Compile[prog,def:out]
{
	out <- [prog]Bind Blueprint[[def]Name >>, Fold["Add Blueprint Field", NBlueprint[], [def]Fields >>]]
}

_Tree to Program[parse tree,program:out]
{
	after blueprint <- Fold["Add Blueprint", program, [parse tree]Blueprints >>]
	[[parse tree]Workers >>]First
	{
		prog <- Add Workers[[parse tree]Workers >>, ~, after blueprint]
	}{
		Print["No workers!"]
	}
	Key Value Map[[parse tree]Workers >>, ["Add Contents"]Set Input[2, prog]]
	out <- Val[prog]
}

Tree to Program[parse tree:out]
{
	out <- _Tree to Program[parse tree, [Program[]]Add Builtins]
}

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 <- <String@File[file name]
	,text <- [file]Get FString[[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"]Set Input[3, params], parse tree, needs import]
		out <- Process Imports[import tree, params]
	}{
		out <- parse tree
	}
}

_Init Used Store[dict,store name:out]
{
	[dict]Index[store name]
	{
		out <- dict
	}{
		Init Store[store name]
		out <- [dict]Set[store name, Yes]
	}
}

_Init Used Stores[dict,worker:out]
{
	out <- Fold["_Init Used Store", dict, [worker]Uses Stores >>]
}

Init Used Stores[parse tree,existing stores:out]
{
	out <- Fold["_Init Used Stores", existing stores, [parse tree]Workers >>]
}

Until End[text:out]
{
	line <- Get Input[]
	If[[line] = ["End"]]
	{
		out <- [text]Append["\n"]
	}{
		out <- Until End[[[text]Append["\n"]]Append[line]]
	}
}

_REPL[params,prog,stores]
{
	line <- Get Input[]
	If[[line] = ["Begin"]]
	{
		text <- Until End[""]
		Null[text, params, New@Parse Program[], 0]
		{
			define tree <- Process Imports[~, params]
			Init Used Stores[define tree, stores]
			{ _REPL[params, _Tree to Program[define tree, prog], ~] }
		}
	}{
		If[[line]Starts With[[params]Import >>]]
		{
			Parse Import[[line]Append["\n"], params, New@Parse Program[], 0]
			{
				import tree <- Process Imports[~, params]
				Init Used Stores[import tree, stores]
				{ _REPL[params, _Tree to Program[import tree, prog], ~] }
			}
		}{
			trees <- Worker Body[[line]Append["}"], params, ()]
			tree <- [New@Worker Node["Val", [()]Append[[trees]Index[0]]]]Assignments <<[("__out")]
			this stores <- [[tree]Gather Stores[params, Dictionary[]]]Keys
			next stores <- Fold["_Init Used Store", stores, this stores]
			{
				pworker <- [[New@Parse Worker["__Eval", (), ("__out"), 0]]Trees <<[[()]Append[tree]]]Uses Stores <<[this stores]
			}
			[[prog]Find Worker["__Eval"]]Clear
			{ 
				Add Contents[pworker, "__Eval", prog]
				{ 
						_REPL[params, prog, next stores] } }
		}
	}
}

REPL[params]
{
	Print["Rhope Alpha 2\nCopyright 2008 by Michael Pavone\nEntering interactive mode\n"]
	prog <- Tree to Program[Null["Val[in:out]\n{\n out <- in\n}\n__Eval[:__out]\n{\n}\n", params, New@Parse Program[], 0]]
	_REPL[params, prog, Dictionary[]]
}

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"]Set Input[2, 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"]Set Input[2, params], stores, [node]Params >>]
	out <- Fold[["Add If Store"]Set Input[2, params], store list, [node]Assignments >>]
}

Gather Stores@Field Node[node,params,stores:out]
{
	//TODO: Handle blocks
	store list <- Fold[["Param Gather Stores"]Set Input[2, params], stores, [node]Params >>]
	out <- Fold[["Add If Store"]Set Input[2, params], store list, [node]Assignments >>]
}

Gather Stores@Literal Node[node,params,stores:out]
{
	out <- Fold[["Add If Store"]Set Input[2, params], stores, [node]Assignments >>]
}