view parser_old_c.rhope @ 173:e769b2e0facc

Syntactic sugar for calling a value
author Mike Pavone <pavone@retrodev.com>
date Tue, 17 May 2011 23:17:42 -0700
parents 7bbdc034e347
children
line wrap: on
line source

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
	Index Begin
	Index End
	Previous
	Block Val
	Set Field
	Get Field
	Import
	Blueprint
	Global Separator
	Uses
	Hex Escape
	Escape Map
	Foreign
	Globals
}

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 <<[":"]
	]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"]
	]Globals <<["Globals"]
}

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 Global Store
{
	Name
	Vars
}

Global Store[name:out]
{
	out <- [[Build[Global Store()]]Name <<[name]]Vars <<[Dictionary[]]
}

Blueprint Parse Program
{
	Workers
	Imports
	Blueprints
	Global Stores
	Errors
}

Parse Program[:out]
{
	out <- [[[[[Build[Parse Program()]
	]Workers <<[Dictionary[]]
	]Imports <<[Dictionary[]]
	]Blueprints <<[Dictionary[]]
	]Global Stores <<[Dictionary[]]
	]Errors <<[()]
}

Add Global Store@Parse Program[tree,store:out]
{
	out <- [tree]Global Stores <<[ [[tree]Global Stores >>]Set[[store]Name >>, store] ]
}

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
	Assigned
}

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]]Assigned <<[Dictionary[]]
}

Blueprint Worker Node
{
	Name
	Params
	Assignments
	Blocks
	Index
}

Worker Node[name,params:out]
{
	out <- [[[[Build[Worker Node()]]Name <<[name]]Params <<[params]]Assignments <<[()]]Blocks <<[()]
}

_Get Assigned Pipes[pipe dict,node:out]
{
	out <- [node]Get Assigned Pipes[pipe dict]
}

Get Assigned Pipes[node,pipe dict:out]
{
	Fold[Set[?,?,Yes], pipe dict, [node]Assignments >>]
	{ out <- Fold[Fold[_Get Assigned Pipes[?], ?], ~, [node]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]
			}
		}
	}{
		make call <- [[parse worker]Assigned >>]Index[[node]Name >>] {}
		{
			make call <- [[parse worker]Inputs >>]Find[=[?,[node]Name >>]] {}
			{
				Print[["Error: Could not find a worker named "]Append[[node]Name >>]]
			}
		}
		Val[make call]
		{
			new params <- Fold[Append[?], [()]Append[Named Pipe Node[[node]Name >>]], [node]Params >>]
			out node, out worker, out refs <- [[[node]Params <<[new params]]Name <<["Call"]]Add to Worker[worker, program, parse worker, refs]
		}
	}
}

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] {} {} {}
				{ delim <- "" }

				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]
	}
}

Parse Global Vars[string,params,store:out]
{
	trimmed <- Left Trim[string, "\r\n\t "]
	If[trimmed]
	{
		,,after <- [trimmed]Partition[[params]Assign >>]
		{
			varname <- Right Trim[~, "\r\n\t "]
		} {} {
			valstring <- [~]Partition["\n"] {} {} 
			{
				out <- Parse Global Vars[~,params,next store]
			}{
				valstring <- Val[after]
				out <- Val[next store]
			}
			Val[valstring]
			{
				Print[["Parsing initial value: "]Append[valstring]]
				value <- [Named Pipe or Literal[Trim[~, "\r\n\t "], params]]Value >>
				next store <- [store]Vars <<[ [[store]Vars >>]Set[varname, value] ]
			}
		}{
			Print[["Expected assignment operator in global var block, found "]Append[trimmed]]
		}
	}{
		out <- store
	}
}

Parse Globals[string,params,tree,lines:out]
{
	,after globals <- [string]Slice[[[params]Globals >>]Length]
	[after globals]Partition[[params]Block Begin >>]
	{
		store <- Global Store[Trim[~, "\r\n\t "]]
	} {} {
		
		[~]Partition[[params]Block End >>]
		{
			next tree <- [tree]Add Global Store[Parse Global Vars[~, params, store]]
		} {} {
			out <- Null[~,params,next tree,lines]
		}{
			Print["Error: Globals declaration missing block close symbol"]
			out <- tree
		}
	} {
		Print["Error: Globals declaration without block"]
		out <- tree
	}
}


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]Starts With[[params]Globals >>]]
				{
					out <- Parse Globals[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 >> ]
			
		}{
			assigned <- Fold[_Get Assigned Pipes[?], Dictionary[], [worker]Trees >>]
			trees, nworker, refs <- Add List to Worker[[worker]Trees >>, [[NWorker["rhope"]]Uses[[worker]Uses Stores >>]]Outputs <<[ [worker]Outputs >> ], prog, [worker]Assigned <<[assigned], 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,number types:out]
{
	registered <- Fold[Register Workers Compile[?], [Fold[Add Blueprint Compile[?], [[NProgram[]]Numtypes <<[number types]]Global Stores <<[[parse tree]Global Stores >>], [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 >>]
}