view parser_old.rhope @ 42:aabda74c7a88

Fields can now be defined to have naked primitive types
author Mike Pavone <pavone@retrodev.com>
date Tue, 13 Oct 2009 00:07:34 -0400
parents 789a146a48e1
children a24eb366195c
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
}

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 <<[[[[New@Dictionary[]]Set["n","\n"]]Set["r","\r"]]Set["t","\t"]]
}

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 <- New@List[]
	}
	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 Parse Program
{
	Workers
	Imports
	Blueprints
	Errors
}

New@Parse Program[:out]
{
	out <- [[[Build["Parse Program"]
	]Workers <<[New@Dictionary[]]
	]Imports <<[New@Dictionary[]]
	]Blueprints <<[New@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 <<[New@List[]]]Uses Stores <<[New@List[]]]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 <<[New@List[]]]Blocks <<[New@List[]]
}

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]
{
	Print["Add Blocks to Worker"]
	{
	[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 >>]]
	}
}

Add Multi Wire[worker,ref,junk,end index,input num:out]
{
	Print[
		[[[[[[["Wire: "
			]Append[ [ref]Index >> ]
			]Append[","]
			]Append[ [ref]Output Number >>]
			]Append[" to "]
			]Append[end index]
			]Append[","]
			]Append[input num]
		]
	out <- [worker]Add Wire[[ref]Index >>, [ref]Output Number >>, end index, input num]
	{ Print["Wire added"] }
}

Add Param Wire[worker,param,input num,end index,blocks,parse worker,assignments:out]
{
	Print[[[["param type: "
		]Append[Type Of[param]]
		]Append[", dest index:"]
		]Append[end index]]
	{
	param worker, start index, output num <- [param]Add Wires[worker, blocks, parse worker, assignments] {}
	{
		Print[
		[[[[[[["Wire: "
			]Append[start index ]
			]Append[","]
			]Append[output num]
			]Append[" to "]
			]Append[end index]
			]Append[","]
			]Append[input num]
		] {
		out <- [param worker]Add Wire[start index, output num, end index, input num]
		{ Print["wire done, Add Param Wire"] }
		}
	}{}{
		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]
{
	Print[["_Add Block Wire "]Append[Type Of[node]]]
	{
		out <- [node]Add Wires[worker, blocks, parse worker, assignments]
		{ Print[["_Add Block Wire done "]Append[Type Of[node]]] }
	}
}

Add Block Wire[worker,block nodes,output num,parent index,existing blocks,parse worker,assignments:out]
{
	Print["Add Block Wire"]
	{
	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]
	{ Print["done: Add Block Wire"] }
	}
}

Assignments Add Wires[worker,assignment,output num,parse worker,start index:out worker]
{
	Print[["Assignments Add Wires: "]Append[assignment]]
	{
	[[parse worker]Outputs >>]Find[assignment]
	{
		,output index <- [worker]Add Typed Output[assignment, ~, [[parse worker]Output Types >>]Index[~]]
		{
			Print[
				[[[[[[["Wire: "
					]Append[ start index ]
					]Append[","]
					]Append[ output num]
					]Append[" to "]
					]Append[output index]
					]Append[","]
					]Append[ 0 ]
				]
			out worker <- [~]Add Wire[start index, output num, output index, 0]
			{ Print["wire done, Assignments Add Wires 1"] }
		}
	}{
		//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]
				{ Print["wire done, Assignments Add Wires 2"] }
			}
		}{
			Print["Pipe assignment, do nothing"]
			{ 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]
{
	Print["Add Wires@Worker Node"]
	{
	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]
{
	Print["Add Wires Worker or Field"]
	{
	Fold[[["Assignments Add Wires"]Set Input[3, parse worker]]Set Input[4, [node]Index >>], worker, [node]Assignments >>]
	{ 
		Print["Assignments Add Wires done"]
		Fold[[[[["Add Block Wire"]Set Input[3, [node]Index >>]]Set Input[4, blocks]]Set Input[5, parse worker]]Set Input[6, assignments], ~, [node]Blocks >>]
		{ 
			Print["Add Block Wire fold done"]
			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 >>] }}
	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]
		}
	}
	index <- [node]Index >>
	num <- 0
	}
}

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 <<[New@List[]]]Blocks <<[New@List[]]]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]
{
	Print["Add Wires@Field Node"]
	{
	worker,index,num <- Add Wires Worker or Field[node, worker, blocks, parse worker, assignments]
	}
}

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

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[~]] {}
		{
			Print[["Added input, node:"]Append[~]]
			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]
{
	Print["Add Wires@Named Pipe Node"]
	{
	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 >>]
}

Blueprint Global Node
{
	Store
	Name
	Assignments
	Blocks
	Index
}

New@Global Node[store,name:out]
{
	out <- [[[[Build["Global Node"]]Store <<[store]]Name <<[name]]Assignments <<[New@List[]]]Blocks <<[New@List[]]
}

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
}

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

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]
{
	Print["Add Wires@Literal Node"]
	{
	worker,index,num <- Add Wires Literal or Global[node, worker, blocks, parse worker, assignments]
	}
}

Add Wires Literal or Global[node,worker,blocks,parse worker,junk:worker,index,num,unused]
{
	Print["Add Wires Literal or Global"]
	{
	assignments worker <- Fold[[["Assignments Add Wires"]Set Input[3, parse worker]]Set Input[4, [node]Index >>], worker, [node]Assignments >>]
	{ Print["Done fold Assignments Add Wires"] }
	[blocks]Peek
	{
		Print["Add wire"]
		worker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number>>, [node]Index >>, [0]-[1]]
		{ Print["Add wire done"] }
	}{
		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]
}

Filter 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[[[New@List[]]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], New@List[], Filter[Map[body lines, ["Trim"]Set Input[1,"\n\r\t "]], "Filter 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, New@List[]]
		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 <- [[New@List[]]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
}

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]
		}{
			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, New@List[]]
		}{
			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[40]]] }
							}{
								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, New@List[]]
	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, New@List[]]
				}
			}
		}{
			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, New@List[]]
		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] {}
	{
		nextlist <- [paramlist]Append[Trim[~, "\r\n\t "]]
		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"]]
					{
						paramtype,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]]
						paramtype <- Val[before variant]
					}
				}{
					paramtype <- Val[before variant]
				}
			}{
				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 Name[string,params,tree,lines:out]
{
	,whitespace name <- [string]Get Comment DString[[params]Arg Begin >>, params]
	{
		worker name <- Trim[whitespace name, "\n\r\t "]
		Print[["Parsing worker: "]Append[worker name]]
		in out <- [params]In Out Delim >>
		arg end <- [params]Arg End >>
		delims <- [[New@List[]]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]]
			{
				after arglist <- [after]Get Comment DString[arg end, params] {}
				{
					outputs,output types <- Parse Param List[~, (), (), params]
					{ Print["got outputs"] }
					{ Print["got output types"] }
				}
			}{
				after arglist <- Val[after]
				outputs <- ()
				output types <- ()
			}
			inputs,input types <- Parse Param List[arglist, (), (), params]
			{ Print["got inputs"] }
			{ Print["got input types"] }
			
			//inputs <- Map[[arglist]Split[[params]List Delim >>], ["Trim"]Set Input[1,"\n\r\t "]]
			//outputs <- Map[[output string]Split[[params]List Delim >>], ["Trim"]Set Input[1,"\n\r\t "]]

			New@Parse Worker[worker name, inputs, outputs, input types, output types, 0]
			{
				Print["Got parse worker"]
				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, New@List[]]
				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
	}
}

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]
		}{
			out <- Worker Name[trimmed, params, tree, current line]
		}
	}
}

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]]
	out <- [prog]Register Worker[name, "rhope", [[worker]Inputs >>]Length, [[worker]Outputs >>]Length]
}

Add Workers Compile[prog, worker, name:out]
{
	Print[["Add Workers Compile: "]Append[name]]
	{
	trees, nworker, refs <- Add List to Worker[[worker]Trees >>, [NWorker["rhope"]]Uses[[worker]Uses Stores >>], prog, worker, New@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]
{
	Print["Add Wires Helper"]
	{
	out <- [node]Add Wires[worker, New@List[], parse worker, assignments]
	{ Print["Add Wires Helper Done"] }
	}
}

Add Contents[parse worker,name,program:out,key]
{
	Print[["Add Contents: "]Append[name]]
	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, New@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
	{
		Print["Adding workers"]
		prog <- Add Workers[[parse tree]Workers >>, ~, after blueprint]
		{ Print["Add Workers done"] }
	}{
		Print["No workers!"]
	}
	Key Value Map[[parse tree]Workers >>, ["Add Contents"]Set Input[2, prog]]
	{ Print["Done Add Contents"] }
	out <- Val[prog]
}

Tree to Program[parse tree:out]
{
	Print["Tree to Program"]
	out <- _Tree to Program[parse tree, [New@Program[]]Add Builtins]
	{ Print["done"] }
}

Tree to Program Native[parse tree:out]
{
	registered <- Fold["Register Workers Compile", Fold["Add Blueprint Compile", [NProgram[]]Register Builtins, [parse tree]Blueprints >>], [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]
{
	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", New@List[], [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], ~] }
			}
		}{
			Print["Expression"]
			trees <- Worker Body[[line]Append["}"], params, New@List[]]
			{ Print["Parse done"] }
			tree <- [New@Worker Node["Val", [New@List[]]Append[[trees]Index[0]]]]Assignments <<[("__out")]
			{ Print["Constructed new tree"] }
			this stores <- [[tree]Gather Stores[params, New@Dictionary[]]]Keys
			{ Print["Got stores"] }
			next stores <- Fold["_Init Used Store", stores, this stores]
			{
				Print["Initialized stores"]
				pworker <- [[New@Parse Worker["__Eval", New@List[], ("__out"), 0]]Trees <<[[New@List[]]Append[tree]]]Uses Stores <<[this stores]
				{ Print["Constructed parse worker"] }
			}
			[[prog]Find Worker["__Eval"]]Clear
			{ 
				Print["Cleared worker"]
				Add Contents[pworker, "__Eval", prog]
				{ 
					Print["Added Contents"]
					Pretty Print[[[[prog]Find Worker["__Eval"]]Do[New@List[]]]Index[0], ""]
					{ 
						Print["Finished executeion"]
						_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, New@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 >>]
}


Main[args]
{
	Print["start"]
	fname <- [args]Index[1]
	{
		file <- <String@File[~]
		,text <- [file]Get FString[[file]Length]
		params <- New@Parser[]
		Print[["Parsing "]Append[fname]]
		Null[text, params, New@Parse Program[], 0]
		{
			Print["Parsing imports"]
			tree <- Process Imports[~, params]
			{ Print["Compiling"] }
			compiled <- [Tree to Program Native[tree]]Compile Program[C Program[]]
			outfile <- <String@File[ [fname]Append[".c"] ]
			[outfile]Put String[ [compiled]Text ]
			{ Print[["Wrote output to "]Append[ [fname]Append[".c"] ]] }
		}
	}{
		REPL[New@Parser[]]
	}
}