view parser.vistxt @ 164:429afd920a23

Allow sending and receiving arrays of arbitrary objects rather than just UInt8s
author Mike Pavone <pavone@retrodev.com>
date Mon, 10 Jan 2011 00:25:35 -0500
parents 6202b866d72c
children
line wrap: on
line source

Import extendlib.vistxt



Company 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
:|

New@Parser(0,1)
|:
	out(0) <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[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"]]
:|

Company Output Reference
|:
	Index
	Output Number
:|

New@Output Reference(2,1)
|:
	out(0) <- [[Build["Output Reference"]]Index <<[index(0)]]Output Number <<[num(1)]
:|

Add Pipe Reference(3,1)
|:
	reflist <- [refs(0)]Index[name(1)] |::|
	|:
		reflist <- List[]
	:|
	out(0) <- [refs(0)]Set[name(1), [reflist]Append[reference(2)]]
:|

Assignment Save Reference(5,1)
|:
	[[parse worker(3)]Outputs >>]Find[assignment(1)]
	|:
		out(0) <- refs(0)
	:||:
		out(0) <- Add Pipe Reference[refs(0), assignment(1), New@Output Reference[index(4), output num(2)]]
	:|
:|

Company Parse Program
|:
	Workers
	Imports
	Blueprints
	Errors
:|

New@Parse Program(0,1)
|:
	out(0) <- [[[Build["Parse Program"]
	]Workers <<[Dictionary[]]
	]Imports <<[Dictionary[]]
	]Blueprints <<[Dictionary[]]
:|

Company Blueprint Definition
|:
	Name
	Fields
:|

New@Blueprint Definition(2,1)
|:
	out(0) <- [[Build["Blueprint Definition"]]Name << [name(0)]]Fields <<[fields(1)]
:|

Company Parse Worker
|:
	Name
	Inputs
	Outputs
	Line Number
	Trees
	Uses Stores
:|

New@Parse Worker(4,1)
|:
	out(0) <- [[[[[[Build["Parse Worker"]]Name <<[name(0)]]Inputs <<[inputs(1)]]Outputs <<[outputs(2)]]Line Number <<[line(3)]]Trees <<[List[]]]Uses Stores <<[List[]]
:|

Company Worker Node
|:
	Name
	Params
	Assignments
	Blocks
	Index
:|

New@Worker Node(2,1)
|:
	out(0) <- [[[[Build["Worker Node"]]Name <<[name(0)]]Params <<[params(1)]]Assignments <<[List[]]]Blocks <<[List[]]
:|

Add List Helper(6,3)
|:
	,nextworker,nextrefs <- [[list(0)]Index[key(3)]]Add to Worker[worker(1), program(2), parse worker(4), refs(5)]
	|: nextlist <- [list(0)]Set[key(3), ~] :|
	[list(0)]Next[key(3)]
	|:
		list(0),worker(1),refs(2) <- Add List Helper[nextlist, nextworker, program(2), ~, parse worker(4), nextrefs]
	:||:
		list(0) <- Val[nextlist]
		worker(1) <- Val[nextworker]
		refs(2) <- Val[nextrefs]
	:|
:|

Add List to Worker(5,3)
|:
	[list(0)]First
	|:
		list(0),worker(1),refs(2) <- Add List Helper[list(0), worker(1), program(2), ~, parse worker(3), refs(4)]
	:||:
		list(0) <- list(0)
		worker(1) <- worker(1)
		refs(2) <- refs(4)
	:|
:|

_Add Blocks to Worker(6,3)
|:
	block, next worker, nextrefs <- Add List to Worker[[blocks(0)]Index[key(4)], worker(1), program(2), parse worker(3), refs(5)]
	next blocks <- [blocks(0)]Set[key(4), block]
	[blocks(0)]Next[key(4)]
	|:
		blocks(0),worker(1),refs(2) <- _Add Blocks to Worker[next blocks, next worker, program(2), parseworker(3), ~, nextrefs]
	:||:
		blocks(0) <- Val[next blocks]
		worker(1) <- Val[next worker]
		refs(2) <- Val[nextrefs]
	:|
:|

Add Blocks to Worker(5,3)
|:
	[blocks(0)]First
	|:
		blocks(0), worker(1), refs(2) <- _Add Blocks to Worker[blocks(0), worker(1), program(2), parse worker(3), ~, refs(4)]
	:||:
		blocks(0) <- blocks(0)
		worker(1) <- worker(1)
		refs(2) <- refs(4)
	:|
:|

Add to Worker@Worker Node(5,3)
|:
	[program(2)]Find Worker[[node(0)]Name >>]
	|:
		after worker <- [worker(1)]Add Worker Call[~] |::|
		|:
			assignment refs <- Fold[[["Assignment Save Reference"]Set Input[3, parse worker(3)]]Set Input[4, ~], refs(4), [node(0)]Assignments >>]
			[node(0)]Index <<[~]
			|: 
				params list, params worker, params refs <- Add List to Worker[[~]Params >>, after worker, program(2), parse worker(3), assignment refs]
				block list, worker(1), refs(2) <- Add Blocks to Worker[[~]Blocks >>, params worker, program(2), parse worker(3), params refs]
				node(0) <- [[~]Params <<[params list]]Blocks <<[block list]
			:|
		:|
	:||:
		Print[[[["Error: Could not find a worker named "]Append[[node(0)]Name >>]]Append[" in worker "]]Append[ [parse worker(3)]Name >> ]]
	:|
:|

Add Multi Wire(5,1)
|:
	out(0) <- [worker(0)]Add Wire[[ref(1)]Index >>, [ref(1)]Output Number >>, end index(3), input num(4)]
:|

Add Param Wire(7,1)
|:
	param worker, start index, output num <- [param(1)]Add Wires[worker(0), blocks(4), parse worker(5), assignments(6)] |::|
	|:
		out(0) <- [param worker]Add Wire[start index, output num, end index(3), input num(2)]
	:||::||:
		out(0) <- Fold[[["Add Multi Wire"]Set Input[3, end index(3)]]Set Input[4, input num(2)], param worker, ~]
	:|
:|

_Add Block Wire(6,1)
|:
	out(0) <- [node(1)]Add Wires[worker(0), blocks(3), parse worker(4), assignments(5)]
:|

Add Block Wire(7,1)
|:
	blocks <- [existing blocks(4)]Append[New@Output Reference[parent index(3), output num(2)]]
	out(0) <- Fold[[[["_Add Block Wire"]Set Input[3, blocks]]Set Input[4, parse worker(5)]]Set Input[5, assignments(6)], worker(0), block nodes(1)]
	//out(0) <- [param(1)]Add Wires[worker(0), blocks]
:|

Assignments Add Wires(5,1)
|:
	[[parse worker(3)]Outputs >>]Find[assignment(1)]
	|:
		,output index <- [worker(0)]Add Output[assignment(1), ~]
		|:
			worker(0) <- [~]Add Wire[start index(4), output num(2), output index, 0]
		:|
	:||:
		//Ugly hack alert!
		If[[asignment(1)]Contains["::"]]
		|:
			parts <- [assignment(1)]Split["::"]
			,global index <- [worker(0)]Add Global Set[[parts]Index[0], [parts]Index[1]]
			|:
				worker(0) <- [~]Add Wire[start index(4), output num(2), global index, 0]
			:|
		:||:
			worker(0) <- worker(0)
		:|
	:|
:|

Has Block@Worker Node(1,2)
|:
	out(0) <- Yes
:|

_Has Block Params(2,1)
|:
	param <- [param list(0)]Index[key(1)]
	out(0) <- [param]Has Block |::|
	|:
		[param list(0)]Next[key(1)]
		|:
			out(0) <- _Has Block Params[param list(0), ~]
		:||:
			out(0) <- No
		:|
	:|
	
:|

Has Block Params(1,1)
|:
	[param list(0)]First
	|:
		out(0) <- _Has Block Params[param list(0), ~]
	:||:
		out(0) <- No
	:|
:|

Add Wires@Worker Node(5,4)
|:
	worker(0),index(1),num(2) <- Add Wires Worker or Field[node(0), worker(1), blocks(2), parse worker(3), assignments(4)]
:|

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

Company Field Node
|:
	Name
	Params
	Assignments
	Blocks
	Index
	Set?
:|

Has Block@Field Node(1,2)
|:
	has block(0) <- Yes
:|

New@Field Node(3,1)
|:
	out(0) <- [[[[[Build["Field Node"]]Name <<[name(0)]]Assignments <<[List[]]]Blocks <<[List[]]]Set? <<[set(2)]]Params <<[params(1)]
:|

Add to Worker@Field Node(5,3)
|:
	If[[node(0)]Set? >>]
	|:
		after worker,index <- [worker(1)]Add Object Set[[node(0)]Name >>]
	:||:
		after worker,index <- [worker(1)]Add Object Get[[node(0)]Name >>]
	:|
	index
	|:
		assignment refs <- Fold[[["Assignment Save Reference"]Set Input[3, parse worker(3)]]Set Input[4, ~], refs(4), [node(0)]Assignments >>]
		[node(0)]Index <<[~]
		|: 
			params list, params worker, params refs <- Add List to Worker[[~]Params >>, after worker, program(2), parse worker(3), assignment refs]
			block list, worker(1), refs(2) <- Add Blocks to Worker[[~]Blocks >>, params worker, program(2), parse worker(3), params refs]
			node(0) <- [[~]Params <<[params list]]Blocks <<[block list]
		:|
	:|
:|

Add Wires@Field Node(5,4)
|:
	worker(0),index(1),num(2) <- Add Wires Worker or Field[node(0), worker(1), blocks(2), parse worker(3), assignments(4)]
:|

Company Named Pipe Node
|:
	Name
	Assignments
	Blocks
	Index
:|

Has Block@Named Pipe Node(1,2)
|:
	If[[[node(0)]Index >>] < [0]]
	|:
		//~ should really be a parser parameter
		If[[[node(0)]Name >>] = ["~"]]
		|:
			has block(0) <- Yes
		:||:
			no block(1) <- No
		:|
	:||:
		has block(0) <- Yes
	:|
:|

New@Named Pipe Node(1,1)
|:
	out(0) <- [[[Build["Named Pipe Node"]]Name <<[name(0)]]Assignments <<[List[]]]Blocks <<[List[]]
:|

Add to Worker@Named Pipe Node(5,3)
|:
	[[parse worker(3)]Inputs >>]Find[[node(0)]Name >>]
	|:
		after add <- [worker(1)]Add Input[[node(0)]Name >>, ~] |::|
		|:
			assign refs <- Fold[[["Assignment Save Reference"]Set Input[3, parse worker(3)]]Set Input[4, ~], refs(4), [node(0)]Assignments >>]
			index node <- [node(0)]Index <<[~]
		:|
	:||:
		after add <- worker(1)
		index node <- [node(0)]Index <<[[0]-[1]]
		//TODO: Handle assignments from a named pipe that isn't an input
		assign refs <- refs(4)
	:|
	block list, worker(1), refs(2) <- Add Blocks to Worker[[node(0)]Blocks >>, after add, program(2), parse worker(3), assign refs]
	node(0) <- [index node]Blocks <<[block list]
:|

Add Wires@Named Pipe Node(5,4)
|:
	reflist(3) <- [assignments(4)]Index[[node(0)]Name >>]
	|: 
		//TODO: Fix support for a named pipe with a block
		worker(0) <- worker (1)
	:||:
		If[[[node(0)]Name >>] = ["~"]]
		|:
			wires worker <- worker(1)
			[blocks(2)]Peek
			|:
				my index <- [~]Index >>
				num(2) <- [~]Output Number >>
			:||:
				//TODO: Propagate an error rather than printing it out
				Print["Error, block reference symbol (~) located outside of a block"]
			:|
		:||:
			If[[[node(0)]Index >>] < [0]]
			|:
				Print[[[["Error, reference to named pipe "]Append[[node(0)]Name >>]]Append[" that was never assigned to in worker "]]Append[[parse worker(3)]Name >>]]
			:||:
				my index <- [node(0)]Index >>
				num(2) <- 0
				assignments worker <- Fold[[["Assignments Add Wires"]Set Input[3, parse worker(3)]]Set Input[4, [node(0)]Index >>], worker(1), [node(0)]Assignments >>]
				[blocks(2)]Peek
				|:
					wires worker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number >>, [node(0)]Index >>, [0]-[1]]
				:||:
					wires worker <- Val[assignments worker]
				:|
			:|
		:|
	:|
	index(1) <- my index
	
	worker(0) <- Fold[[[[["Add Block Wire"]Set Input[3, my index]]Set Input[4, blocks(2)]]Set Input[5, parse worker(3)]]Set Input[6, assignments(4)], wires worker, [node(0)]Blocks >>]
:|

Company Global Node
|:
	Store
	Name
	Assignments
	Blocks
	Index
:|

New@Global Node(2,1)
|:
	out(0) <- [[[[Build["Global Node"]]Store <<[store(0)]]Name <<[name(1)]]Assignments <<[List[]]]Blocks <<[List[]]
:|

Add to Worker@Global Node(5,3)
|:
	out worker(1) <- [worker(1)]Add Global Get[[node(0)]Store >>, [node(0)]Name >>] |::|
	|:
		refs(2) <- Fold[[["Assignment Save Reference"]Set Input[3, parse worker(3)]]Set Input[4, ~], refs(4), [node(0)]Assignments >>]
		out node(0) <- [node(0)]Index <<[~]
	:|
	refs(2) <- refs(4)
:|

Add Wires@Global Node(5,4)
|:
	worker(0),index(1),num(2) <- Add Wires Literal or Global[node(0), worker(1), blocks(2), parse worker(3), assignments(4)]
:|

Has Block@Global Node(1,2)
|:
	out(0) <- Yes
:|

Company Literal Node
|:
	Value
	Assignments
	Blocks
	Index
:|

Has Block@Literal Node(1,2)
|:
	out(0) <- Yes
:|

New@Literal Node(1,1)
|:
	out(0) <- [[[Build["Literal Node"]]Value <<[value(0)]]Assignments <<[List[]]]Blocks <<[List[]]
:|

Add to Worker@Literal Node(5,3)
|:
	out worker(1) <- [worker(1)]Add Constant[[node(0)]Value >>] |::|
	|:
		refs(2) <- Fold[[["Assignment Save Reference"]Set Input[3, parse worker(3)]]Set Input[4, ~], refs(4), [node(0)]Assignments >>]
		out node(0) <- [node(0)]Index <<[~]
	:|
:|

Add Wires@Literal Node(5,4)
|:
	worker(0),index(1),num(2) <- Add Wires Literal or Global[node(0), worker(1), blocks(2), parse worker(3), assignments(4)]
:|

Add Wires Literal or Global(5,4)
|:
	assignments worker <- Fold[[["Assignments Add Wires"]Set Input[3, parse worker(3)]]Set Input[4, [node(0)]Index >>], worker(1), [node(0)]Assignments >>]
	[blocks(2)]Peek
	|:
		worker(0) <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number>>, [node(0)]Index >>, [0]-[1]]
	:||:
		worker(0) <- Val[assignments worker]
	:|
	index(1) <- [node(0)]Index >>
	num(2) <- 0
:|

Company Block Node
|:
	Number
:|

Company Parse Error
|:
	Type
	Text
	Line Number
:|

New@Parse Error(3,1)
|:
	out(0) <- [[[Build["Parse Error"]]Type <<[type(0)]]Text <<[text(1)]]Line Number <<[number(2)]
:|

Filter Empty(1,1)
|:
	If[[[string(0)]Length] > [0]]
	|:
		out(0) <- Yes
	:||:
		out(0) <- No
	:|
:|

Company Blueprint Field
|:
	Name
	Type
:|

New@Blueprint Field(2,1)
|:
	out(0) <- [[Build["Blueprint Field"]]Name <<[name(0)]]Type <<[type(1)]
:|

Process Blueprint Field(3,1)
|:
	parts <- [field(1)]Split[delim(2)]
	If[[[parts]Length] > [1]]
	|:
		out(0) <- [list(0)]Append[New@Blueprint Field[[parts]Index[1], [parts]Index[0]]]
	:||:
		out(0) <- [list(0)]Append[New@Blueprint Field[[parts]Index[0], "Any Type"]]
	:|
:|

Block Comment(4,1)
|:
	If[[block count(3)] > [0]]
	|:
		after, before <- [string(0)]Get DString[[[List[]]Append[begin comment(1)]]Append[end comment(2)]] |::| |::|
		|:
			If[[~] = [begin comment(1)]]
			|:
				out(0) <- Block Comment[after, begin comment(1), end comment(2), [block count(3)]+[1]]
			:||:
				out(0) <- Block Comment[after, begin comment(1), end comment(2), [block count(3)]-[1]]
			:|
		:||:
			//No match
			out(0) <- ""
		:|
	:||:
		out(0) <- string(0)
	:|
:|

Line Comment(1,1)
|:
	[string(0)]Get DString["\n"]
	|:
		out(0) <- ["\n"]Append[~]
	:| |::| |::| |:
		out(0) <- ""
	:|
:|

_Get Comment DString(6,4)
|:
	after,before,delim,nomatch(3) <- [string(0)]Get DString[delims(1)]
	|:
		If[[delim] = [line comment(2)]]
		|:
			after comment <- Line Comment[after]
		:||:
			If[[delim] = [begin comment(3)]]
			|:
				after comment <- Block Comment[after, begin comment(3), end comment(4), 1]	
			:||:
				rest(0) <- Val[after]
				before(1) <- [prev before(5)]Append[before]
				delim(2) <- Val[delim]
			:|
		:|
	:| |::| |::| |:
		before(1) <- [prev before(5)]Append[before]
	:|
	
	after comment
	|:
		rest(0),more before,delim(2),nomatch(3) <- _Get Comment DString[~, delims(1), line comment(2), begin comment(3), end comment(4), prev before(5)]
		before(1) <- [before]Append[more before]
	:|
		
:|

Get Comment DString(3,4)
|:
	line comment <- [params(2)]Line Comment >>
	begin comment <- [params(2)]Comment Begin >>
	end comment <- [params(2)]Comment End >>
	all delims <- [[[delims(1)]As List]Append[begin comment]]Append[line comment]
	rest(0), before(1), delim(2), not found(3) <- _Get Comment DString[string(0), delims(1), line comment, begin comment, end comment, ""]
:|

Comment Left Trim(3,1)
|:
	line comment <- [params(2)]Line Comment >>
	
	end comment <- [params(2)]Comment End >>
	trimmed <- Left Trim[string(0), trim chars(1)]
	If[[trimmed]Starts With[line comment]]
	|:
		,after delim <- [trimmed]Slice[[line comment]Length]
		out(0) <- Comment Left Trim[Line Comment[after delim], trim chars(1), params(2)]
	:||:
		begin comment <- [params(2)]Comment Begin >>
		If[[trimmed]Starts With[begin comment]]
		|:
			,after delim <- [trimmed]Slice[[line comment]Length]
			out(0) <- Comment Left Trim[Block Comment[after delim, begin comment, end comment, 1], trim chars(1), params(2)]
		:||:
			out(0) <- Val[trimmed]
		:|
	:|
:|

PBlueprint(4,1)
|:
	,whitespace name <- [string(0)]Get Comment DString[[params(1)]Block Begin >>, params(1)]
	|:	
		,no blueprint <- [whitespace name]Slice[ [[params(1)]Blueprint >>]Length ]
		name <- Trim[no blueprint, "\r\n\t "]
		name lines <- 0//[Count Substring[left, "\n"]] + [Count Substring[right, "\n"]]
		,body <- [~]Get Comment DString[ [params(1)]Block End >>, params(1)]
		|:
			body lines <- [body]Split["\n"]
			more lines <- [[[body lines]Length] - [1]] + [name lines]
			fields <- Fold[["Process Blueprint Field"]Set Input[2, [params(1)]Blueprint Type Delim >>], List[], Filter[Map[body lines, ["Trim"]Set Input[1,"\n\r\t "]], "Filter Empty"]]
			new tree <- [tree(2)]Blueprints << [ [[tree(2)]Blueprints >>]Set[name, New@Blueprint Definition[name, fields]] ]
			out(0) <- Null[~, params(1), new tree, [lines(3)] + [more lines]]
		:| |::| |:
			out(0) <- [tree(2)]Errors <<[ [[tree(2)]Errors >>]Append[New@Parse Error["Error",[["Blueprint is missing an block close symbol \""]Append[[params(1)]Block End >>]]Append["\""], lines(3)]] ]
		:|
		
	:| |::| |:
		out(0) <- [tree(2)]Errors <<[ [[tree(2)]Errors >>]Append[New@Parse Error["Error",[["Blueprint is missing an block open symbol \""]Append[[params(1)]Block Begin >>]]Append["\""], lines(3)]] ]
	:|
:|

Parse Import(4,1)
|:
	[line]Slice[ [[params(1)]Import >>]Length ] |::|
	|:
		filename <- Trim[~, " \n\r\t"]
	:|
	new tree <- [tree(2)]Imports <<[ [[tree(2)]Imports >>]Set[filename, Yes] ]
	,line <- [string(0)]Get Comment DString["\n", params(1)]
	|:
		out(0) <- Null[~, params(1), new tree, [lines(3)] + [1]]
	:| |::| |:
		out(0) <- Val[new tree]
	:|
:|

Get Expression Blocks(3,2)
|:
	check block <- Comment Left Trim[string(0), "\n\r\t ", params(1)]
	If[[check block]Starts With[[params(1)]Block Begin >>]]
	|:
		,begin block <- [check block]Slice[[[params(1)]Block Begin >>]Length]
		trees, after block <- Worker Body[begin block, params(1), List[]]
		blocks(0), after(1) <- Get Expression Blocks[after block, params(1), [blocks(2)]Append[trees]]
	:||:
		If[[check block]Starts With[[params(1)]Empty Block >>]]
		|:
			blocks(0) <- blocks(2)
			,after(1) <- [check block]Slice[[[params(1)]Empty Block >>]Length]
		:||:
			blocks(0) <- blocks(2)
			after(1) <- Val[check block]
		:|
	:|
:|

Parse Escape(2,2)
|:
	code,rest <- [string(0)]Slice[1]
	If[[code] = [[params(1)]Hex Escape >>]]
	|:
		hex,after(1) <- [rest]Slice[2]
		char(0) <- [""]Put Byte[From Hex@Whole Number[hex]]
	:||:
		after(1) <- Val[rest]
		char(0) <- [[params(1)]Escape Map >>]Index[code] |::|
		|:
			char(0) <- Val[code]
		:|
	:|
:|

Parse String(3,2)
|:
	delims <- [[List[]]Append[[params(1)]String End >>]]Append[[params(1)]String Escape >>]
	after, before, delim <- [string(0)]Get Comment DString[delims, params(1)]
	|:
		If[[delim] = [[params(1)]String End >>]]
		|:
			value(0) <- [current(2)]Append[before]
			after(1) <- Val[after]
		:||:
			char,after escape <- Parse Escape[after, params(1)]
			value(0),after(1) <- Parse String[after escape, params(1), [[current(2)]Append[before]]Append[char]]
		:|
	:|
:|

Parse List(3,2)
|:
	trimmed <- Comment Left Trim[string(0), "\r\n\t ", params(1)]
	If[[trimmed]Starts With[[params(1)]List End >>]]
	|:
		value(0) <- list(2)
		,after(1) <- [trimmed]Slice[[[params(1)]List End >>]Length]
	:||:
		If[[trimmed]Starts With[[params(1)]List Delim >>]]
		|:
			,el string <- [trimmed]Slice[[[params(1)]List Delim >>]Length]
		:||:
			el string <- Val[trimmed]
		:|
		element,after el <- Named Pipe or Literal[el string, params(1)]
		value(0),after(1) <- Parse List[after el, params(1), [list(2)]Append[[element]Get Value]]
	:|
:|

Get Value@Literal Node(1,1)
|:
	out(0) <- [node(0)]Value >>
:|

Get Value@Named Pipe Node(1,1)
|:
	out(0) <- node(0)
:|

Parse Number(2,2)
|:
	delims <- [[[[{" ","\t","\n","\r"}]Append[[params(1)]List Delim >>]]Append[[params(1)]Block Begin >>]]Append[[params(1)]Arg End >>]]Append[[params(1)]List End >>]
	after delim,valstring <- [string(0)]Get Comment DString[delims, params(1)] |::| |::|
	|:
		after(1) <- [~]Append[after delim]
	:||:
		after(1) <- ""
	:|
	first two,rest <- [valstring]Slice[2]
	If[[first two] = ["0x"]]
	|:
		value(0) <- From Hex@Whole Number[rest]
	:||:
		If[[valstring]Contains["."]]
		|:
			value(0) <- <String@Real Number[valstring]
		:||:
			value(0) <- <String@Whole Number[valstring]
		:|
	:|
:|

Named Pipe or Literal(2,2)
|:
	name <- Comment Left Trim[string(0), "\n\r\t ", params(1)]
	If[[name]Starts With[[params(1)]String Begin >>]]
	|:
		,string begin <- [name]Slice[[[params(1)]String Begin >>]Length]
		value,after(1) <- Parse String[string begin, params(1), ""]
	:||:
		If[[name]Starts With[[params(1)]List Begin >>]]
		|:
			,list start <- [name]Slice[[[params(1)]List Begin >>]Length]
			value,after(1) <- Parse List[list start, params(1), List[]]
		:||:
			If[[[name]Slice[1]]In["-0123456789"]]
			|:
				value,after(1) <- Parse Number[name, params(1)]
			:||:
				delims <- [[[[[[{"\n"}]Append[[params(1)]Block Begin >>]]Append[[params(1)]Block End >>]]Append[[params(1)]Empty Block >>]]Append[[params(1)]Arg End >>]]Append[[params(1)]List Delim >>]]Append[[params(1)]List End >>]
				afterdelim,raw before,delim <- [name]Get Comment DString[delims, params(1)]
				|:
					after(1) <- [delim]Append[~]
				:| |::| |::| |: 
					after(1) <- ""
				:|
				before <- Trim[raw before, "\r\n\t "]
				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[40]]] :|
						:||:
							If[[before]Contains[[params(1)]Global Separator >>]]
							|:
								parts <- [before]Split[[params(1)]Global Separator >>]
								out(0) <- New@Global Node[Right Trim[[parts]Index[0],"\r\n\t "], Trim[[parts]Index[1], "\r\n\t "]]
							:||:
								out(0) <- New@Named Pipe Node[Right Trim[before,"\r\n\t "]]
							:|
						:|
					:|
				:|
				out(0) <- New@Literal Node[yesno]
			:|
		:|
	:|
	out(0) <- New@Literal Node[value]
:|

Parse Arguments(3,2)
|:
	args <- Comment Left Trim[string(0), "\r\n\t ", params(1)]
	If[[args]Starts With[[params(1)]List Delim >>]]
	|:
		[args]Slice[[[params(1)]List Delim >>]Length] |::| 
		|:
			final args <- Comment Left Trim[~, "\r\n\t ", params(1)]
		:|
	:||:
		If[[args]Starts With[[params(1)]Arg End >>]]
		|:
			args(0) <- arglist(2)
			,after(1) <- [args]Slice[[[params(1)]Arg End >>]Length]
		:||:
			final args <- Val[args]
		:|
	:|
	arg, after arg <- Parse Expression[final args, params(1)]
	args(0), after(1) <- Parse Arguments[after arg, params(1), [arglist(2)]Append[arg]]
:|

Worker or Field(3,1)
|:
	get field <- [params(2)]Get Field >>
	If[[name(0)]Ends With[get field]]
	|:
		field <- Right Trim[[name(0)]Slice[[[name(0)]Length] - [[get field]Length]], "\n\r\t "]
		out(0) <- New@Field Node[field, args(1), No]
	:||:
		set field <- [params(2)]Set Field >>
		If[[name(0)]Ends With[set field]]
		|:
			field <- Right Trim[[name(0)]Slice[[[name(0)]Length] - [[set field]Length]], "\n\r\t "]
			out(0) <- New@Field Node[field, args(1), Yes]
		:||:
			out(0) <- New@Worker Node[name(0), args(1)]
		:|
	:|
:|

Prefix(4,2)
|:	
	//Parse argument list
	more args,after(1) <- Parse Arguments[string(0), params(1), existing args(3)]
	expression(0) <- Worker or Field[name(2), more args, params(1)]
:|

Postfix or Infix(2,2)
|:
	args, after args <- Parse Arguments[string(0), params(1), List[]]
	delims <- [[[[[{"\n"}]Append[[params(1)]Arg Begin >>]]Append[[params(1)]Empty Block >>]]Append[[params(1)]Block Begin >>]]Append[[params(1)]Arg End >>]]Append[[params(1)]List Delim >>]
	after,before,delim <- [after args]Get Comment DString[delims, params(1)]
	|:
		If[[delim] = [[params(1)]Arg Begin >>]]
		|:
			expression(0), after(1) <- Prefix[after, params(1), Trim[before,"\r\n\t "], args]
		:||:
			If[[delim] = [[params(1)]Empty Block >>]]
			|:
				after expression(1) <- Val[after]
			:||:
				,after expression(1) <- [after args]Slice[[before]Length]
			:|
			expression(0) <- Worker or Field[Trim[before,"\r\n\t "], args, params(1)]
		:|
	:|
:|

Parse Expression(2,2)
|:
	delims <- [[[[[[[{"\n"}]Append[[params(1)]Arg Begin >>]]Append[[params(1)]Arg End >>]]Append[[params(1)]Assign >>]]Append["\n"]]Append[[params(1)]Empty Block >>]]Append[[params(1)]Block End >>]]Append[[params(1)]String Begin >>]
	after, before, delim <- [trimmed(0)]Get Comment DString[delims, params(1)]
	|:
		//If we find an arg begin token, we have a worker expression
		If[[delim] = [[params(1)]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(1)]
			:||:
				If[[maybe name]Contains[[params(1)]List Delim >>]]
				|:
					after expression <- [after literal]Append[[delim]Append[after]]
					expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params(1)]
				:||:
					expression, after expression <- Prefix[after, params(1), maybe name, List[]]
				:|
			:|
		:||:
			If[[delim] = [[params(1)]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(1)]List Delim >>], ["Trim"]Set Input[1,"\n\r\t "]]
				,after blocks(1) <- Parse Expression[Comment Left Trim[after, " \n\r\t", params(1)], params(1)]
				|:
					final expression(0) <- [~]Assignments <<[assignments]
				:|
			:||:
				//If[[delim] = [[params(1)]String Begin >>]]
				//|:
				//	If[[Trim[before, "\r\n\t "]] = [""]]
				//	|:
				//		expression, after expression <- Named Pipe or Literal[[delim]Append[after], params(1)]
				//	:||:
				//		after expression <- [after literal]Append[[delim]Append[after]]
				//		expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params(1)]
				//	:|
				//:||:
				//	after expression <- [after literal]Append[[delim]Append[after]]
				//	expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params(1)]
				//:|
				expression, after expression <- Named Pipe or Literal[trimmed(0), params(1)]
			:|
		:|
		//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(1) <- Get Expression Blocks[after expression, params(1), List[]]
		final expression(0) <- [expression]Blocks <<[blocks]
	:|
:|

Worker Body(3,2)
|:
	trimmed <- Comment Left Trim[string(0), "\n\r\t ", params(1)]
	If[[trimmed]Starts With[[params(1)]Block End >>]]
	|:
		//We're done with this block, return
		,after end(1) <- [trimmed]Slice[[[params(1)]Block End >>]Length]
		trees(0) <- trees(2)
	:||:
		expression, after expression <- Parse Expression[trimmed, params(1)]
		trees(0),after end(1) <- Worker Body[after expression, params(1), [trees(2)]Append[expression]]
	:|
:|

Process Modifiers(3,1)
|:
	//Eventually this will need to be more sophisticated to handle more modifiers
	trimmed <- Comment Left Trim[modifiers(2), "\n\r\t ", params(1)]
	If[[trimmed]Starts With[[params(1)]Uses >>]]
	|:
		,after uses <- [trimmed]Slice[[[params(1)]Uses >>]Length]
		,stores string <- [after uses]Get Comment DString["\n", params(1)]
		out(0) <- [worker(0)]Uses Stores <<[Map[[stores string]Split[[params(1)]List Delim >>], ["Trim"]Set Input[1, "\r\n\t "]]]
	:||:
		out(0) <- worker(0)
	:|
:|

Worker Name(4,1)
|:
	,whitespace name <- [string(0)]Get Comment DString[[params(1)]Arg Begin >>, params(1)]
	|:
		worker name <- Trim[whitespace name, "\n\r\t "]
		in out <- [params(1)]In Out Delim >>
		arg end <- [params(1)]Arg End >>
		delims <- [[List[]]Append[in out]]Append[arg end]
		after <- [~]Get Comment DString[delims, params(1)] |::| 
		|:
			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]]
			|:
				after arglist <- [after]Get Comment DString[arg end, params(1)] |::|
				|:
					output string <- Trim[~,"\n\r\t "]
				:|
			:||:
				after arglist <- Val[after]
				output string <- ""
			:|
			inputs <- Map[[arglist]Split[[params(1)]List Delim >>], ["Trim"]Set Input[1,"\n\r\t "]]
			outputs <- Map[[output string]Split[[params(1)]List Delim >>], ["Trim"]Set Input[1,"\n\r\t "]]

			New@Parse Worker[worker name, inputs, outputs, 0]
			|:
				body text, modifiers <- [after arglist]Get Comment DString[[params(1)]Block Begin >>, params(1)]
				modified <- Process Modifiers[~, params(1), modifiers]
				expression trees, after body <- Worker Body[body text, params(1), List[]]
				worker <- [modified]Trees <<[expression trees]
				new worker dict <- [[tree(2)]Workers >>]Set[worker name, worker]
				out(0) <- Null[after body, params(1), [tree(2)]Workers <<[new worker dict], 0]
			:|
		:|
	:||::||::||:
		out(0) <- tree(2)
	:|
:|

Null(4,1)
|:
	trimmed <- Comment Left Trim[string(0), " \n\r\t", params(1)]
	current line <- 0//[lines(3)] + [Count Substring[whitespace, "\n"]]
	If[[trimmed]Starts With[ [params(1)]Blueprint >> ]]
	|:
		out(0) <- PBlueprint[trimmed, params(1), tree(2), current line]
	:||:
		If[[trimmed]Starts With[ [params(1)]Import >> ]]
		|:
			out(0) <- Parse Import[trimmed, params(1), tree(2), current line]
		:||:
			out(0) <- Worker Name[trimmed, params(1), tree(2), current line]
		:|
	:|
:|

Add Workers(3,1)
|:
	prog,worker <- [program(2)]New Worker[name(1)]
	[worker]Set IO Counts[ [[[worker(0)]Index[name(1)]]Inputs >>]Length, [[[worker(0)]Index[name(1)]]Outputs >>]Length]
	[workers(0)]Next[name(1)]
	|:
		out(0) <- Add Workers[workers(0), ~, prog]
	:||:
		out(0) <- Val[prog]
	:|
:|

Add Wires Helper(5,1)
|:
	worker(0) <- [node(1)]Add Wires[worker(0), List[], parse worker(3), assignments(4)]
:|

Add Contents(3,2)
|:
	worker <- [[program(2)]Find Worker[name(1)]]Uses[[parse worker(0)]Uses Stores >>]
	trees, contents worker, refs <- Add List to Worker[[parse worker(0)]Trees >>, worker, program(2), parse worker(0), Dictionary[]]
	Fold[[["Add Wires Helper"]Set Input[3, parse worker(0)]]Set Input[4, refs], contents worker, trees]
	out(0) <- [parse worker(0)]Trees <<[trees]
	key(1) <- name(1)
:|

Add Blueprint Field(3,1)
|:
	out(0) <- [blueprint(0)]Add Field[[field(1)]Name >>, [field(1)]Type >>]
:|

Add Blueprint(2,1)
|:
	out(0) <- [prog(0)]New Blueprint[[def(1)]Name >>] |::|
	|:	
		Fold["Add Blueprint Field", ~, [def(1)]Fields >>]
	:|
:|

_Tree to Program(2,1)
|:
	after blueprint <- Fold["Add Blueprint", program(1), [parse tree(0)]Blueprints >>]
	[[parse tree(0)]Workers >>]First
	|:
		prog <- Add Workers[[parse tree(0)]Workers >>, ~, after blueprint]
	:|
	Key Value Map[[parse tree(0)]Workers >>, ["Add Contents"]Set Input[2, prog]]
	out(0) <- prog
:|

Tree to Program(1,1)
|:
	out(0) <- _Tree to Program[parse tree(0), [Program[]]Add Builtins]
:|

Needs Imports(3,1)
|:
	If[not imported?(1)]
	|:
		out(0) <- [needs import(0)]Append[name(2)]
	:||:
		out(0) <- needs import(0)
	:|
:|

Do Import(4,1)
|:
	file <- <String@File[file name(1)]
	,text <- [file]Get FString[[file]Length]
	after import <- Null[text, params(3), tree(0), 0]
	out(0) <- [after import]Imports <<[ [[after import]Imports >>]Set[file name(1), No] ]
:|

Process Imports(2,1)
|:
	needs import <- Fold["Needs Imports", List[], [parse tree(0)]Imports >>]
	If[[[needs import]Length] > [0]]
	|:
		import tree <- Fold[["Do Import"]Set Input[3, params(1)], parse tree(0), needs import]
		out(0) <- Process Imports[import tree, params(1)]
	:||:
		out(0) <- parse tree(0)
	:|
:|

_Init Used Store(2,1)
|:
	[dict(0)]Index[store name(1)]
	|:
		out(0) <- dict(0)
	:||:
		Init Store[store name(1)]
		out(0) <- [dict(0)]Set[store name(1), Yes]
	:|
:|

_Init Used Stores(2,1)
|:
	out(0) <- Fold["_Init Used Store", dict(0), [worker(1)]Uses Stores >>]
:|

Init Used Stores(1,1)
|:
	out(0) <- Fold["_Init Used Stores", existing stores(1), [parse tree(0)]Workers >>]
:|

Until End(1,1)
|:
	line <- Get Input[]
	If[[line] = ["End"]]
	|:
		out(0) <- [text(0)]Append["\n"]
	:||:
		out(0) <- Until End[[[text(0)]Append["\n"]]Append[line]]
	:|
:|

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

REPL(1,0)
|:
	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(0), New@Parse Program[], 0]]
	_REPL[params(0), prog, Dictionary[]]
:|

Add If Store(3,1)
|:
	If[[name(1)]Contains[[params(2)]Global Separator >>]]
	|:
		parts <- [name(1)]Split[[params(2)]Global Separator >>]
		out(0) <- [stores(0)]Set[[parts]Index[0], Yes]
	:||:
		out(0) <- stores(0)
	:|
:|

Param Gather Stores(3,1)
|:
	out(0) <- [node(1)]Gather Stores[params(2), stores(0)]
:|

Gather Stores@Named Pipe Node(3,1)
|:
	out(0) <- Fold[["Add If Store"]Set Input[2, params(1)], stores(2), [node(0)]Assignments >>]
:|

Gather Stores@Global Node(3,1)
|:
	out(0) <- [stores(2)]Set[[node(0)]Store >>, Yes]
:|

Gather Stores@Worker Node(3,1)
|:
	//TODO: Handle blocks
	store list <- Fold[["Param Gather Stores"]Set Input[2, params(1)], stores(2), [node(0)]Params >>]
	out(0) <- Fold[["Add If Store"]Set Input[2, params(1)], store list, [node(0)]Assignments >>]
:|

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

Gather Stores@Literal Node(3,1)
|:
	out(0) <- Fold[["Add If Store"]Set Input[2, params(1)], stores(2), [node(0)]Assignments >>]
:|


Main(1,0)
|:
	
	[args(0)]Index[1]
	|:
		file <- <String@File[~]
		,text <- [file]Get FString[[file]Length]
		params <- New@Parser[]
		Null[text, params, New@Parse Program[], 0]
		|:
			tree <- Process Imports[~, params]
			Init Used Stores[tree, Dictionary[]]
			|: [Tree to Program[tree]]Run[[args(0)]Tail[1]] :|
		:|
	:||:
		REPL[New@Parser[]]
	:|
:|