view nworker.rhope @ 43:709df3e82bb4

Added methods to support type inference
author Mike Pavone <pavone@retrodev.com>
date Thu, 15 Oct 2009 21:32:43 -0400
parents aabda74c7a88
children a7c79ac22efc
line wrap: on
line source

Import extendlib.rhope
Import cbackend.rhope


Blueprint Condition Set
{
	Variables
	Subsets
	Condition Type
}

AndSet[:out]
{
	out <- [[[Build["Condition Set"]]Variables <<[New@Dictionary[]]]Subsets <<[New@Dictionary[]]]Condition Type <<["And"]
}

OrSet[:out]
{
	out <- [[[Build["Condition Set"]]Variables <<[New@Dictionary[]]]Subsets <<[New@Dictionary[]]]Condition Type <<["Or"]
}

To String@Condition Set[set:out]
{
	out <- [[[[[set]Condition Type >>
	]Append["Set:\n\tVariables:\n\t\t"]
	]Append[ Join[Keys[[set]Variables >>], "\n\t\t"] ]
	]Append["\n\tSubsets:\n\t\t"]
	]Append[ Join[Keys[[set]Subsets >>], "\n\t\t"] ]
}

Add Condition@Condition Set[set,cond:out]
{
	If[[Type Of[cond]] = ["Condition Set"]]
	{
		out <- [set]Subsets <<[ [[set]Subsets>>]Set[[cond]To String, cond] ]
	}{
		out <- [set]Variables <<[ [[set]Variables >>]Set[cond, Yes] ]
	}
}

=@Condition Set[set1,set2:out]
{
	,out <- If[[[set1]Condition Type >>] = [[set2]Condition Type >>]]
	{
		,out <- If[[[set1]Variables >>] = [[set2]Variables >>]]
		{
			out,out <- If[[[set1]Subsets >>] = [[set2]Subsets >>]]
		}
	}
}

_For Backend Var[current,junk,variable,type:out]
{
	out <- [[<String@Worker[[type]Append["Cond"]]]Do[ [[()]Append[current]]Append[variable] ]]Index[0]
}

_For Backend Subset[current,subset,type:out]
{
	Print["Calling For Backend on subset"]
	{
	[subset]For Backend
	{
		Print["Got output from for backend"]
		out <- [[<String@Worker[[type]Append["Cond"]]]Do[ [[()]Append[current]]Append[~] ]]Index[0]
		{ Print["done _For Backend Subset with condition"] }
	}{
		Print["none output from for backend"]
		out <- current
	}
	}
}

Empty?@Condition Set[set:not empty,empty]
{
	[[set]Variables >>]First
	{
		not empty <- Yes
	}{
		,empty <- [[set]Subsets >>]First Non-empty Set
		{
			not empty <- Yes
		}
	}
}

_First Non-empty Set[setlist,index:out,none]
{
	current <- [setlist]Index[index]
	[[current]Variables >>]First
	{
		out <- index
	}{
		,trynext <- [[current]Subsets >>]First Non-empty Set
		{
			out <- index
		}
	}
	Val[trynext]
	{
		,none <- [setlist]Next[index]
		{
			out,none <- _First Non-empty Set[setlist, ~]
		}
	}
}

First Non-empty Set[setlist:index,none]
{
	,none <- [setlist]First
	{
		index,none <- _First Non-empty Set[setlist,~]
	}
}

For Backend@Condition Set[set:out,none]
{
	Print["For Backend"]
	firstvar <- [[set]Variables >>]First
	{
		Print["At least one var"]
		[[set]Variables >>]Next[~]
		{
			Print["at least two vars"]
			vars <- _Fold[[set]Variables >>, ~, firstvar, ["_For Backend Var"]Set Input[3, [set]Condition Type >>]]
		}{
			Print["just one var"]
			vars <- Val[firstvar]
		}
		out <- Fold[["_For Backend Subset"]Set Input[2, [set]Condition Type >>], vars, [set]Subsets >>]
		{ Print["done For Backend, with vars"] }
	}{
		Print["no vars"]
		[[set]Subsets >>]First Non-empty Set
		{
			Print[["At least one non-empty subset: "]Append[~]]
			firstsub <- [[[set]Subsets >>]Index[~]]For Backend
			[[set]Subsets >>]Next[~]
			{
				Print["at least two subsets"]
				out <- _Fold[[set]Subsets >>, ~, firstsub, ["_For Backend Subset"]Set Input[2, [set]Condition Type >>]]
				{ Print["done with subsets, but no vars"] }
			}{
				out <- Val[firstsub]
				{ Pretty Print[~, "1s:\t"] }
			}
		}{
			Print["done with none"]
			none <- Yes
		}
	}
}

Set@Range[range,index,val:out]
{
	out <- [[()]Concatenate[range]
	]Set[index,val]
}

List of Lists[num:out]
{
	out <- Fold[["Append"]Set Input[1, ()],(), Range[0,num]]
}

Blueprint Worker Ref
{
	Name
	Convention
	Inputs
	Outputs
}

Worker Ref[name,convention,inputs,outputs:out]
{
	out <- [[[[Build["Worker Ref"]]Name <<[name]]Convention <<[convention]]Inputs <<[inputs]]Outputs <<[outputs]
}

Blueprint Node Ref
{
	Index
	IO Num
}

Node Ref[index,ionum:out]
{
	out <- [[Build["Node Ref"]]Index <<[index]]IO Num <<[ionum]
}

=@Node Ref[left,right:out]
{
	,out <- If[[[left]Index >>] = [[right]Index >>]]
	{
		out <- [[left]IO Num>>] = [[right]IO Num >>]
	}
}

Blueprint NWorker Node
{
	Type
	Data
	Inputs
	Outputs
	Wires From
	Wires To
	Conditions
}

Wire To@NWorker Node[node,from,output,pre input:out]
{
	input <- [pre input]+[1]
	out <- [node]Wires To <<[
		[[node]Wires To >>]Set[input,
			[[[node]Wires To >>]Index[input]
			]Append[Node Ref[from,output]]
		]
	]
}

Wire From@NWorker Node[node,to,input,output:out]
{
	out <- [node]Wires From <<[
		[[node]Wires From >>]Set[output,
			[[[node]Wires From >>]Index[output]
			]Append[Node Ref[to,input]]
		]
	]
}

_Dependency[dlist,ref:out]
{
	[dlist]Find[ref]
	{
		out <- dlist
	}{
		out <- [dlist]Append[ref]
	}
}

Dependencies@NWorker Node[node:out]
{
	out <- Fold[["Fold"]Set Input[0, "_Dependency"], (), [node]Wires To >>]
}


NWorker Node[type,data,inputs,outputs:out]
{
	out <- [[[[[[[Build["NWorker Node"]
		]Type <<[type]
		]Data <<[data]
		]Inputs <<[inputs]
		]Outputs <<[outputs]
		]Wires From <<[List of Lists[outputs]]
		]Wires To <<[List of Lists[[inputs]+[1]]]
		]Conditions <<[AndSet[]]
}

Blueprint NWorker
{
	Convention
	Nodes
	Inputs
	Input Types
	Outputs
	Output Types
	Uses
	NodeResults
	Free Temps
}

NWorker[convention:out]
{
	out <- [[[[[[Build["NWorker"]]Convention <<[convention]]Nodes <<[()]]Inputs <<[()]]Outputs <<[()]]Input Types <<[()]]Output Types <<[()]
}

Add Node@NWorker[worker,type,data,inputs,outputs:out,node index]
{
	out <- [worker]Nodes <<[[[worker]Nodes >>]Append[NWorker Node[type,data,inputs,outputs]]]
	node index <- [[worker]Nodes >>]Length
}

Add Worker Call@NWorker[worker,tocall:out,node index]
{
	out, node index <- [worker]Add Node["call",tocall,[tocall]Inputs >>,[tocall]Outputs >>]
}

Add Constant@NWorker[worker,constant:out,node index]
{
	out, node index <- [worker]Add Node["const",constant,0,1]
}

Add Input@NWorker[worker,name,number:out,node index]
{
	out,node index <- [worker]Add Typed Input[name,number,Type Instance["Any Type"]]
}

Add Typed Input@NWorker[worker,name,number,type:out,node index]
{
	,node index <- [worker]Add Node["input",number,0,1]
	{ 
		out <- [[~]Inputs <<[[[~]Inputs >>]Set[number,name]]
		]Input Types <<[[[~]Input Types >>]Set[number,type]]
	}
}

Add Output@NWorker[worker,name,number:out,node index]
{
	out,node index <- [worker]Add Typed Output[name,number,Type Instance["Any Type"]]
}

Add Typed Output@NWorker[worker,name,number,type:out,node index]
{
	,node index <- [worker]Add Node["output",number,1,0]
	{ 
		out <- [[~]Outputs <<[[[~]Outputs >>]Set[number,name]]
		]Output Types <<[[[~]Output Types >>]Set[number,type]]
	}
}

Add Object Get@NWorker[worker,fieldname:out,node index]
{
	out, node index <- [worker]Add Node["getfield",fieldname,1,1]
}

Add Object Set@NWorker[worker,fieldname:out,node index]
{
	out, node index <- [worker]Add Node["setfield",fieldname,2,1]
}

Add Wire@NWorker[worker,from,output,to,input:out]
{
	Print[[[[[[[[["Add Wire@NWorker["]Append[from]]Append[","]]Append[output]]Append[","]]Append[to]]Append[","]]Append[input]]Append["]"]]
	{
	fromw <- [[[worker]Nodes >>]Index[from]]Wire From[to,input,output]
	{ Print["fromw"] }
	tow <- [[[worker]Nodes >>]Index[to]]Wire To[from,output,input]
	{ Print["tow"] }
	nodes <- [[[worker]Nodes >>]Set[from, fromw]]Set[to, tow]
	{ Print["nodes"] }
	out <- [worker]Nodes <<[nodes]
	{ Print["Add Wire@NWorker done"] }
	}
}

Uses@NWorker[worker,uses:out]
{
	out <- [worker]Uses <<[uses]
}

_No Dependencies[list,node,index:out]
{
	[[node]Wires To>>]Index[1]
	{
		out <- Val[list]
	}{
		[[[node]Wires To>>]Index[0]]First
		{
			out <- Val[list]
		}{
			out <- [list]Append[index]
		}
	}
}

No Dependencies@NWorker[worker:out]
{
	out <- Fold["_No Dependencies", (), [worker]Nodes >>]
}

_Collect Dests[candidates,wire:out]
{
	out <- [candidates]Set[[wire]Index >>, Yes]
}

Collect Dests@NWorker[worker,candidates,node index:out]
{
	out <- Fold[["Fold"]Set Input[0, "_Collect Dests"], candidates, [[[worker]Nodes >>]Index[node index]]Wires From >>]
}

Check Dependency@NWorker[worker,nodes,wires,wire index:met?]
{
	ref <- [wires]Index[wire index]
	[nodes]Find[[ref]Index >>]
	{
		[wires]Next[wire index]
		{
			met? <- [worker]Check Dependency[nodes,wires,~]
		}{
			met? <- Yes
		}
	}{
		met? <- No
	}
}
_Check Dependencies@NWorker[worker,nodes,inputs,input index:met?]
{
	wires <- [inputs]Index[input index]
	[wires]First
	{
		current met? <- [worker]Check Dependency[nodes, wires, ~]
	}{
		current met? <- Yes
	}
	If[current met?]
	{
		[inputs]Next[input index]
		{
			met? <- [worker]_Check Dependencies[nodes,inputs,~]
		}{
			met? <- Yes
		}
	}{
		met? <- No
	}
}

Check Dependencies@NWorker[worker,nodes,candidate:met?]
{
	inputs <- [[[worker]Nodes >>]Index[candidate]]Wires To >>
	[inputs]First
	{
		met? <- [worker]_Check Dependencies[nodes, inputs, ~]
	}{
		met? <- Yes
	}
}

Dependants@NWorker[worker,direct nodes,nodes:out]
{
	candidates <- Keys[Fold[["Collect Dests"]Set Input[0,worker], (), direct nodes]]
	out <- Filter[candidates, [["Check Dependencies"]Set Input[0, worker]]Set Input[1, nodes]]
}

_Dependency Groups@NWorker[worker,last,all,grouped:out]
{
	current <- [worker]Dependants[last,all]
	[current]First
	{
		out <- [worker]_Dependency Groups[current, [all]Concatenate[current], [grouped]Append[current]]
	}{
		out <- grouped
	}
}
Dependency Groups@NWorker[worker:out]
{
	no deps <- [worker]No Dependencies
	out <- [worker]_Dependency Groups[no deps, no deps, [()]Append[no deps]]
}

Format Input@NWorker[worker,noderef:out]
{
	node <- [[worker]Nodes >>]Index[[noderef]Index >>]
	[("call","getfield","setfield")]Find[[node]Type >>]
	{
		out <- AddRef[ [[["__result_"]Append[[noderef]Index >>]]Append["_"]]Append[[noderef]IO Num >>] ]
	}{
		If[[[node]Type >>] = ["input"]]
		{
			input name <- [[worker]Inputs >>]Index[ [node]Data >> ]
			out <- AddRef[input name] 
		}{
			If[[[node]Type >>] = ["const"]]
			{
				If[[Type Of[[node]Data >>]] = ["Type Instance"]]
				{
					//TODO: Support parametric types
					datstring <- [[node]Data >>]Name >>
				}{
					datstring <- [node]Data >>
				}
				out <- Constant[[[Type Of[[node]Data >>]]Append["_"]]Append[datstring]]
					
			}
		}
	}
}

Collect Input@NWorker[worker,nodeinput:out]
{
	inputchoices <- Map[nodeinput, ["Format Input"]Set Input[0, worker]]

	[inputchoices]First
	{
		first <- [inputchoices]Index[~]
		[inputchoices]Next[~]
		{
			out <- _Fold[inputchoices, ~, first, "OrValue"]
		}{
			out <- Val[first]
		}
	}{
		out <- No
	}
}

Collect Inputs@NWorker[worker,node:out]
{
	out <- Map[Tail[[node]Wires To>>, 1], ["Collect Input"]Set Input[0, worker]]
}

Collect Input Condition@NWorker[worker,set,noderef:out]
{
	node <- [[worker]Nodes >>]Index[ [noderef]Index >> ]
	If[[[node]Outputs >>] > [1]]
	{
		out <- [set]Add Condition[ [["__result_"]Append[[noderef]Index >>]]Append[["_"]Append[[noderef]IO Num >>]] ]
	}{
		out <- [set]Add Condition[[node]Conditions >>]
	}
}

Collect Condition@NWorker[worker,set,nodeinput:out]
{
	out <- [set]Add Condition[Fold[["Collect Input Condition"]Set Input[0, worker], OrSet[], nodeinput]]
}

Collect Conditions@NWorker[worker,node:out]
{
	Print["Collect Conditions"]
	{
	out <- Fold[["Collect Condition"]Set Input[0, worker], AndSet[], [node]Wires To>>]
	{ Print["done Collect Conditions"] }
	}
}

Save Result[func,num,node index:out]
{
	Print["Save Result"]
	out var <- [[["__result_"]Append[node index]]Append["_"]]Append[num]
	Print[out var]
	/*out <- [[func]Allocate Var[out var, "Any Type"]
		]Move[Result[num], out var]
	*/
	out <- [func]Move[Result[num], out var]	
}

Compile Call Node[node,program,func,inputs,node index:out]
{
	If[[[node]Type >>] = ["getfield"]]
	{
		with call <- [func]Get Field Call[[node]Data >>, [inputs]Index[0]]
	}{
		If[[[node]Type >>] = ["setfield"]]
		{
			with call <- [func]Set Field Call[[node]Data >>, [inputs]Index[0], [inputs]Index[1]]
		}{
			Print[["Call: "]Append[[[node]Data >>]Name >>]]
			{
			[program]Method?[[[node]Data >>]Name >>]
			{
				Print["Method!"]
				with call <- [func]Method Call[[[node]Data >>]Name >>, inputs]
				{ Print["Method Call done"] }
			}{
				Print["Function!"]
				with call <- [func]Call[[[node]Data >>]Name >>, inputs]
			}
			}
		}
	}
	out <- Fold[["Save Result"]Set Input[2, node index], with call, Range[0, [node]Outputs >>]]
}

Compile Node@NWorker[worker,program,func,nodes,current:out,out worker]
{
	Print[["Compile Node: "]Append[[node]Type >>]]
	node index <- [nodes]Index[current]
	node <- [[worker]Nodes >>]Index[node index]
	conditions <- [worker]Collect Conditions[node]
	[("call","getfield","setfield")]Find[[node]Type >>]
	{
		inputs <- [worker]Collect Inputs[node]
		[conditions]For Backend
		{
			Print["Conditional execution, do if"]
			stream <- [func]Instruction Stream
			nfunc <- [func]Do If[~, nstream]
		}{
			Print["No conditions, full steam ahead"]
			stream <- Val[func]
			nfunc <- Val[nstream]
		}
		nstream <- Compile Call Node[node, program, stream, inputs, node index]
	}{
		If[[[node]Type >>] = ["output"]]
		{
			inputs <- [worker]Collect Inputs[node]
			[conditions]For Backend
			{
				stream <- [func]Instruction Stream
				nfunc <- [func]Do If[~, nstream]
			}{
				stream <- Val[func]
				nfunc <- Val[nstream]
			}
			nstream <- [stream]Move[[inputs]Index[0], [[worker]Outputs >>]Index[ [node]Data >> ] ]
		}{
			If[[[node]Type >>] = ["const"]]
			{
				//TODO: Handle list constants
				If[[Type Of[[node]Data >>]] = ["Type Instance"]]
				{
					//TODO: Support parametric types
					datstring <- [[node]Data >>]Name >>
				}{
					datstring <- [node]Data >>
				}
				nfunc <- [func]Register Constant[[[Type Of[[node]Data >>]]Append["_"]]Append[datstring], [node]Data >>]
			}{
				nfunc <- Val[func]
			}
			
		}
	}
	If[[[node]Outputs >>] = [0]]
	{
		nworker <- Val[worker]
	}{
		nworker <- [worker]Nodes <<[ [[worker]Nodes >>]Set[node index, [node]Conditions <<[conditions]] ]
	}
	[nodes]Next[current]
	{
		out,out worker <- [nworker]Compile Node[program,nfunc,nodes,~]
	}{
		out <- Val[nfunc]
		out worker <- Val[nworker]
	}
}

Compile Group@NWorker[worker,program,func,groups,current:out,out worker]
{
	nodes <- [groups]Index[current]
	[nodes]First
	{
		nfunc,nworker <- [worker]Compile Node[program,func,nodes,~]
	}{
		nfunc <- Val[func]
		nworker <- Val[worker]
	}
	[groups]Next[current]
	{
		out,out worker <- [nworker]Compile Group[program,nfunc,groups,~]
	}{
		out <- Val[nfunc]
		out worker <- Val[nworker]
	}
}

Release Var@NWorker[worker,func,name:out]
{
	//_result_index_ionum
	parts <- [name]Split["_"]
	index <- <String@Whole Number[ [parts]Index[2] ]
	io num <- <String@Whole Number[ [parts]Index[3] ]
	node <- [[worker]Nodes >>]Index[index]
	do if <- If[[[node]Outputs >>] > [1]] {}
	{
		,do if <- [[node]Conditions >>]Empty?
		{
			out <- [func]Release[name]
		}
	}
	
	Val[do if]
	{
		stream <- [[func]Instruction Stream]Release[name]
		out <- [func]Do If[name, stream]
	}
}

Result Var[vars,io num,index:out]
{
	out <- [vars]Append[[[["__result_"]Append[index]]Append["_"]]Append[io num]]
}

Node Result Vars[vars,node,index:out]
{
	[("call","getfield","setfield")]Find[[node]Type >>]
	{
		out <- Fold[["Result Var"]Set Input[2, index], vars, Range[0, [node]Outputs >>]]
	}{
		out <- vars
	}
}

Result Vars@NWorker[worker:out]
{
	out <- Fold["Node Result Vars", (), [worker]Nodes >>]
}

Compile Worker@NWorker[worker,program,name:out]
{
	Print[["Compiling: "]Append[name]]
	{
	ifunc <- Fold["Set Output Type", Fold["Set Input Type", [program]Create Function[name,[worker]Inputs >>, [worker]Outputs >>, [worker]Convention >>], [worker]Input Types >>], [worker]Output Types >>]
	
	res vars <- [worker]Result Vars
	func <- Fold["Set Null", Fold["Set Null", Fold[["Allocate Var"]Set Input[2, "Any Type"], ifunc, res vars], res vars], [worker]Outputs >>]
	
	groups <- [worker]Dependency Groups
	[groups]First
	{
		final func <- [worker]Compile Group[program,func,groups, ~]
	}{
		final func <- Val[func]
	}
	out <- [program]Store Function[Fold["Release", Fold[["Release Var"]Set Input[0, worker], final func, res vars], [worker]Inputs >>]]
	}
}

Test[:out]
{
	ref+ <- Worker Ref["+","rhope",2,1]
	ref* <- Worker Ref["*","rhope",2,1]
	,a <- [NWorker["rhope"]
	]Add Input["a", 0] {
		,b <- [~]Add Input["b", 1] {
		,c <- [~]Add Input["c", 2] {
		,outref <- [~]Add Output["out", 0] {
		,call+ <- [~]Add Worker Call[ref+] {
		,call* <- [~]Add Worker Call[ref*] {
		out <- [[[[[~]Add Wire[a,0,call+,0]
		]Add Wire[b,0,call+,1]
		]Add Wire[call+,0,call*,0]
		]Add Wire[c,0,call*,1]
		]Add Wire[call*,0,outref,0]
	}}}}}}
}

Test Graph to Backend[:out]
{
	out <- [Test[]]Compile Worker[C Program[], "Test"]
}

Blueprint NBlueprint
{
	Fields
	Methods
}

NBlueprint[:out]
{
	out <- [[Build["NBlueprint"]]Fields <<[()]]Methods <<[New@Dictionary[]]
}

Add Field@NBlueprint[bp,name,type:out]
{
	out <- [bp]Fields <<[ [[bp]Fields >>]Append[ [[()]Append[name]]Append[type] ] ]
}

Add Method@NBlueprint[bp,name:out]
{
	out <- [bp]Methods <<[ [[bp]Methods >>]Set[name, Yes] ]
}

Understands Method@NBlueprint[bp,name:out]
{
	out <- [[bp]Methods >>]Index[name] {}
	{ out <- No }
}

Get Field Type@NBlueprint[bp,name:out,notfound]
{
	,notfound <- [[bp]Fields >>]Index[name]
	{ out <- [~]Index[1] }
}

_Compile Blueprint Fields[type,field:out]
{
	name <- [field]Index[0]
	ftype <- [field]Index[1]
	out <- [type]Add Field[name,ftype]
}

_Compile Blueprint Methods[type,junk,name:out]
{
	out <- [type]Add Method[name]
}

Make Init[func,field:out]
{
	name <- [field]Index[0]
	Print[["Field: "]Append[name]]
	{ Print[["  Variant: "]Append[variant]] }
	variant <- [[field]Index[1]]Variant >>
	If[[variant] = ["Boxed"]]
	{
		out <- [func]Set Field Null["obj", name]
		{ Print["done"] }
	}{
		out <- func
	}
}

Make Copy[func,field:out]
{
	name <- [field]Index[0]
	variant <- [[field]Index[1]]Variant >>
	If[[variant] = ["Boxed"]]
	{
		got <- [func]Read Field["obj", name] {}
		{ 
			stream <- [[got]Instruction Stream
				]AddRef No Dest[~] 
			out <- [got]Do If[~, stream]
		}
	}{
		out <- func
	}
}

Make Cleanup[func,field:out]
{
	name <- [field]Index[0]
	variant <- [[field]Index[1]]Variant >>
	If[[variant] = ["Boxed"]]
	{
		got <- [func]Read Field["obj", name] {}
		{ 
			stream <- [[got]Instruction Stream
				]Release[~] 
			out <- [got]Do If[~, stream]
		}
	}{
		out <- func
	}
}

Make Special@NBlueprint[bp,backend,func name,bp name,pop worker:out]
{
	Print[[["Make Special: "]Append[func name]]Append[bp name]]
	func <- [[backend]Create Function[func name,("obj"),(),"cdecl"]
		]Set Input Type[Type Instance[bp name], 0]
	out <- [backend]Store Function[Fold[pop worker, func, [bp]Fields >>]]
}

Getters Setters[backend,field,type name:out]
{
	//TODO: Throw an exception or something if we read a field that is empty
	Print[["Getters Setters: "]Append[name]]
	name <- [field]Index[0]
	type <- [field]Index[1]
	mytype <- Type Instance[type name]
	start getter,getref <- [[[[backend]Create Function[ [[[name]Append[" >>"]]Append["@"]]Append[type name], ("obj"), ("out"), "rhope"]
		]Set Input Type[mytype, 0]
		]Set Output Type[[type]Set Variant["Boxed"], 0]
		]Read Field["obj", name]
	If[[[type]Variant >>] = ["Boxed"]]
	{
		getter <- [[start getter]Do AddRef[getref, "out"]]Release["obj"]
	}{
		getter <- [[start getter]Box[getref, "out", type]]Release["obj"]
	}
		
	begin setter <- [[[[[backend]Create Function[ [[[name]Append[" <<"]]Append["@"]]Append[type name], ("obj","newval"), ("out"), "rhope"]
		]Set Input Type[mytype, 0]
		]Set Input Type[[type]Set Variant["Boxed"], 1]
		]Set Output Type[mytype, 0]
		]Copy["obj"]
		
	If[[[type]Variant >>] = ["Boxed"]]
	{
		,origref <- [begin setter]Read Field["obj", name]
		{ 
			stream <- [[~]Instruction Stream
			]Release[origref]
			,setref <- [[~]Do If[origref, stream]
			]Write Field["obj", name]
			{
				setter <- [[~]Move["newval", setref]
				]Move["obj", "out"]
				{ Print["got setter"] }
			}
		}
	}{
		,setref <- [begin setter]Write Field["obj", name]
		{ 
			setter <- [[~]Unbox["newval", setref]
			]Move["obj", "out"]
		}
	}
	
	out <- [[backend]Store Function[getter]]Store Function[setter]
	
}

Compile Blueprint@NBlueprint[bp,backend,name:out]
{
	Print[["Compiling blueprint: "]Append[name]]
	//Rhope identifiers can't start with spaces, so we can use identifiers that start with spaces for special functions
	init name <- [" init "]Append[name]
	copy name <- [" copy "]Append[name]
	cleanup name <- [" cleanup "]Append[name]
	type <- [[[Fold["_Compile Blueprint Methods", Fold["_Compile Blueprint Fields", [backend]Create Type[name], [bp]Fields >>], [bp]Methods >>]
	]Init <<[init name]
	]Copy <<[copy name]
	]Cleanup <<[cleanup name]
	{ Print["Created type on backend"] }
	
	out <- [backend]Register Type[type]
}

Compile Special@NBlueprint[bp,backend,name:out]
{
	init name <- [" init "]Append[name]
	copy name <- [" copy "]Append[name]
	cleanup name <- [" cleanup "]Append[name]
	got specials <- [bp]Make Special[
				[bp]Make Special[
					[bp]Make Special[backend, init name, name, "Make Init"], 
					copy name, name, "Make Copy"], 
			cleanup name, name, "Make Cleanup"]
	out <- Fold[["Getters Setters"]Set Input[2, name], got specials, [bp]Fields >>]
}

Blueprint NProgram
{
	Blueprints
	Workers
	Worker Refs
}

NProgram[:out]
{
	out <- [[[Build["NProgram"]]Blueprints <<[New@Dictionary[]]]Workers <<[New@Dictionary[]]]Worker Refs <<[New@Dictionary[]]
}

Bind Worker@NProgram[prog,name,worker:out]
{	
	after bind <- [prog]Workers << [ [[prog]Workers >>]Set[name, worker] ]
	parts <- [name]Split["@"]
	[parts]Index[1]
	{
		out <- [after bind]Blueprints <<[ [[after bind]Blueprints >>]Set[~, [[[after bind]Blueprints >>]Index[~]]Add Method[[parts]Index[0]] ] ]
	}{
		out <- Val[after bind]
	}
}

Bind Blueprint@NProgram[prog,name,blueprint:out]
{
	Print[["Bind blueprint: "]Append[name]]
	out <- [prog]Blueprints << [ [[prog]Blueprints >>]Set[name, blueprint] ]
}

_Compile Program BP[backend, blueprint, name:out]
{
	out <- [blueprint]Compile Blueprint[backend, name]
}

_Compile Program BP Special[backend, blueprint, name:out]
{
	out <- [blueprint]Compile Special[backend, name]
}

_Compile Program[backend, worker, name:out]
{
	out <- [worker]Compile Worker[backend, name]
}

Compile Program@NProgram[prog, backend:out]
{
	out <- Fold["_Compile Program", Fold["_Compile Program BP Special", Fold["_Compile Program BP", backend, [prog]Blueprints >>], [prog]Blueprints >>], [prog]Workers >>]
}

Register Worker@NProgram[prog, name, convention, inputs, outputs: out]
{
	Print[["Register Worker "]Append[name]]
	after reg <- [prog]Worker Refs <<[ [[prog]Worker Refs >>]Set[name, Worker Ref[name, convention, inputs, outputs]]]
	parts <- [name]Split["@"]
	[parts]Index[1]
	{
		out <- [prog]Register Worker[[parts]Index[0], convention, inputs, outputs]
	}{
		out <- Val[after reg]
	}
}

Register Builtins@NProgram[prog:out]
{
	out <- [[[[[[[[[[[prog]Register Worker["+@Int32", "rhope", 2, 1]
	]Register Worker["-@Int32", "rhope", 2, 1]
	]Register Worker["*@Int32", "rhope", 2, 1]
	]Register Worker["/@Int32", "rhope", 2, 1]
	]Register Worker["LShift@Int32", "rhope", 2, 1]
	]Register Worker["RShift@Int32", "rhope", 2, 1]
	]Register Worker["Print", "rhope", 1, 1]
	]Register Worker["If@Yes No", "rhope", 1, 2]
	]Register Worker["<@Int32", "rhope", 2, 1]
	]Register Worker[">@Int32", "rhope", 2, 1]
	]Register Worker["Build", "rhope", 1, 1]
}

Find Worker@NProgram[prog, name:out,notfound]
{
	Print[ ["Find Worker@NProgram: "]Append[name] ]
	out,notfound <- [[prog]Worker Refs >>]Index[name]
}

Find Method@NProgram[prog, name, type:out,notfound]
{
	bp,notfound <- [[prog]Blueprints >>]Index[[type]Name >>]
	,notfound <- If[[bp]Understands Method[name]]
	{
		out <- [[prog]Workers >>]Index[[[name]Append["@"]]Append[[type]Name >>]]
	}
}

Find Field@NProgram[prog, name, type:fieldtype,notfound]
{
	bp,notfound <- [[prog]Blueprints >>]Index[[type]Name >>]
	fieldtype,notfound <- [bp]Get Field Type[name]
}