Mercurial > repos > rhope
view nworker.rhope @ 189:d0e3a13c1bd9 default tip
Remove old calculator example
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 07 Oct 2011 00:24:04 -0700 |
parents | c6ba9fe45910 |
children |
line wrap: on
line source
Import number.rhope Import boolean.rhope Blueprint Condition Set { Variables Subsets Condition Type } AndSet[:out] { out <- [[[Build[Condition Set()]]Variables <<[Dictionary[]]]Subsets <<[()]]Condition Type <<["And"] } OrSet[:out] { out <- [[[Build[Condition Set()]]Variables <<[Dictionary[]]]Subsets <<[()]]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[[Blueprint Of[cond]] = [Condition Set()]] { If[[[set]Condition Type >>]=[[cond]Condition Type >>]] { out <- [[set]Variables <<[ Combine[[set]Variables >>, [cond]Variables >>] ] ]Subsets <<[ Concatenate[[set]Subsets >>, [cond]Subsets >>] ] }{ [cond]Empty? { [cond]Simple? { out <- [set]Variables <<[ Combine[[set]Variables >>, [cond]Variables >>] ] } { out <- [set]Subsets <<[ [[set]Subsets>>]Append[cond] ] } }{ out <- set } } }{ 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] { If[[type]=["And"]] { cond <- Val[AndCond[?]] } { cond <- Val[OrCond[?]] } out <- [cond]Call[current, variable] } _For Backend Subset[current,subset,type:out] { [subset]For Backend { If[[type]=["And"]] { cond <- Val[AndCond[?]] } { cond <- Val[OrCond[?]] } out <- out <- [cond]Call[current, ~] }{ out <- current } } Empty?@Condition Set[set:not empty,empty] { [[set]Variables >>]First { not empty <- Yes }{ ,empty <- [[set]Subsets >>]First { not empty <- Yes } } } Simple?@Condition Set[set:simple,not simple] { ,not simple <- If[[Length[[set]Variables >>]]=[1]] { simple,not simple <- If[[Blueprint Of[[set]Subsets >>]]=[Empty Dictionary()]] } } For Backend@Condition Set[set:out,none] { firstvar <- [[set]Variables >>]First { [[set]Variables >>]Next[~] { vars <- _Fold[[set]Variables >>, ~, firstvar, _For Backend Var[?, ?, ?, [set]Condition Type >>]] }{ vars <- Val[firstvar] } out <- Fold[_For Backend Subset[?, ?, [set]Condition Type >>], vars, [set]Subsets >>] }{ [[set]Subsets >>]First { firstsub <- [[[set]Subsets >>]Index[~]]For Backend [[set]Subsets >>]Next[~] { out <- _Fold[[set]Subsets >>, ~, firstsub, _For Backend Subset[?, ?, [set]Condition Type >>]] }{ out <- Val[firstsub] } }{ none <- Yes } } } List of Lists[num:out] { out <- Fold[Append[?, ()],(), Range[0,num]] } Blueprint Worker Ref { Name Convention Inputs Min Inputs Outputs Min Outputs Is Method? } Worker Ref[name,convention,inputs,outputs,ismethod?:out] { out <- [[[[[[[Build[Worker Ref()]]Name <<[name]]Convention <<[convention]]Inputs <<[inputs]]Outputs <<[outputs]]Is Method? <<[ismethod?]]Min Inputs <<[inputs]]Min Outputs <<[outputs] } String@Worker Ref[ref:out] { out <- [[[[[[[["Worker Ref[" ]Append[[ref]Name >>] ]Append[", "] ]Append[[ref]Convention >>] ]Append[", "] ]Append[String[[ref]Inputs >>]] ]Append[", "] ]Append[String[[ref]Outputs >>]] ]Append["]"] } 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 Min Inputs Input Types Outputs Min Outputs Output Types Wires From Wires To Conditions } Wire To@NWorker Node[node,from,output,pre input:out] { existing cons <- [[node]Wires To >>]Index[input] {} { existing cons <- () } input <- [pre input]+[1] out <- [node]Wires To <<[ [[node]Wires To >>]Set[input, [existing cons]Append[Node Ref[from,output]] ] ] } Wire From@NWorker Node[node,to,input,output:out] { existing cons <- [[node]Wires From >>]Index[output] {} { existing cons <- () } out <- [node]Wires From <<[ [[node]Wires From >>]Set[output, [existing cons]Append[Node Ref[to,input]] ] ] } _Has Input Types@NWorker Node[node,input num:does,does not] { does <- If[[input num] >= [[node]Inputs >>]] {} { ,does not <- [[node]Input Types >>]Index[input num] { count <- [~]Index[1] ,does not <- If[[count] = [[[[node]Wires To >>]Index[[input num]+[1]]]Length]] { does,does not <- [node]_Has Input Types[[input num]+[1]] } } } } Has Input Types?@NWorker Node[node:does,does not] { If[[[node]Inputs >>] > [0]] { does,does not <- _Has Input Types[node,0] }{ does <- Yes } } _Dependency[dlist,ref:out] { [dlist]Find[=[ref, ?]] { out <- dlist }{ out <- [dlist]Append[ref] } } Dependencies@NWorker Node[node:out] { out <- Fold[Fold[_Dependency[?], ?], (), [node]Wires To >>] } NWorker Node[type,data,inputs,outputs:out] { out <- [[[[[[[[[[[Build[NWorker Node()] ]Type <<[type] ]Data <<[data] ]Inputs <<[inputs] ]Min Inputs <<[inputs] ]Outputs <<[outputs] ]Min Outputs <<[outputs] ]Wires From <<[List of Lists[outputs]] ]Wires To <<[List of Lists[[inputs]+[1]]] ]Conditions <<[AndSet[]] ]Input Types <<[()] ]Output Types <<[()] } Blueprint NWorker { Convention Nodes Inputs Input Types Outputs Output Types Uses NodeResults Free Temps Name Builtin? Library } NWorker[convention:out] { out <- [[[[[[[[[[Build[NWorker()]]Convention <<[convention]]Nodes <<[()]]Inputs <<[()]]Outputs <<[()]]Input Types <<[()]]Output Types <<[()]]Name <<["Anonymous"]]Builtin? <<[No]]Library << [""]]Uses <<[()] } String@NWorker[worker:out] { out <- ["NWorker"]Append[[worker]Name >>] } 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 Full Node@NWorker[worker,type,data,inputs,min inputs,outputs,min outputs:out,node index] { out <- [worker]Nodes <<[[[worker]Nodes >>]Append[ [[[NWorker Node[type,data,inputs,outputs] ]Min Inputs <<[min inputs] ]Min Outputs <<[min outputs] ]Wires To <<[List of Lists[[min inputs]+[1]]] ]] node index <- [[worker]Nodes >>]Length } Propagate Type[nodelist,dest,prog,worker,type:out] { If[[[dest]IO Num >>] >= [0]] { node <- [nodelist]Index[[dest]Index >>] [[node]Input Types >>]Index[[dest]IO Num >>] { existing type <- [~]Index[0] new count <- [[~]Index[1]]+[1] If[[[existing type]Name >>] = [[type]Name >>]] { If[[[existing type]Variant >>] = [[type]Variant >>]] { If[[[existing type]Params >>] = [[type]Params >>]] { new type <- Val[existing type] }{ new variant <- [existing type]Variant >> new params <- () } }{ new variant <- "Boxed" If[[[existing type]Params >>] = [[type]Params >>]] { new params <- [existing type]Params >> }{ new params <- () } } new type <- [[existing type]Set Variant[new variant]]Params <<[new params] }{ new type <- Type Instance["Any Type"] } }{ new type <- Val[type] new count <- 1 } new node <- [node]Input Types <<[ [ [node]Input Types >> ]Set[ [dest]IO Num >>, [[()]Append[new type]]Append[new count] ] ] out <- Infer Types Node[[nodelist]Set[[dest]Index >>, new node], new node, [dest]Index >>, prog, worker] }{ out <- nodelist } } Propagate Types[nodelist,dests,output num,prog,worker,source node:out] { [[source node]Output Types >>]Index[output num] { out <- Fold[Propagate Type[?, ?, prog, worker, ~], nodelist, dests] }{ out <- nodelist } } Infer Types Node[nodelist,node,index,prog,worker:out] { If[[[node]Type >>]=["call"]] { extra <- [", worker: "]Append[[[node]Data >>]Name >>] }{ extra <- "" } If[[[node]Type >>] = ["const"]] { const type <- Blueprint Of[[node]Data >>] [(Int8(),UInt8(),Int16(),UInt16(),Int32(),UInt32(),Int64(),UInt64(), Type Instance(),Worker Literal(),List(),List Leaf(),String(),String Slice(),String Cat())]Find[=[const type, ?]] { outtype <- [("Int8","UInt8","Int16","UInt16","Int32","UInt32","Int64","UInt64", "Blueprint","Worker","List","List Leaf","String","String","String")]Index[~] }{ outtype <- "Any Type" } nextnode <- [node]Output Types <<[ [()]Append[Type Instance[outtype]] ] }{ If[[[node]Type >>] = ["setglobal"]] { out <- nodelist }{ If[[[node]Type >>] = ["input"]] { nextnode <- [node]Output Types <<[ [()]Append[ [[worker]Input Types >>]Index[[node]Data >>] ] ] }{ If[[[node]Type >>] = ["output"]] { out <- nodelist }{ If[[[node]Type >>] = ["getglobal"]] { nextnode <- [node]Output Types <<[ [()]Append[Type Instance["Any Type"]] ] }{ [node]Has Input Types? { If[[[node]Type >>] = ["setfield"]] { nextnode <- [node]Output Types <<[ [()]Append[ [[[node]Input Types >>]Index[0]]Index[0] ] ] }{ If[[[node]Type >>] = ["getfield"]] { type <- [[[node]Input Types >>]Index[0]]Index[0] If[[[type]Name >>] = ["Any Type"]] { outtype <- Val[type] }{ outtype <- [prog]Find Field[[node]Data >>, type] {} { //TODO: Return errors rather than printing them Print[ [[[[["Type " ]Append[[type]Name >>] ]Append[" does not have a field named "] ]Append[[node]Data >>] ]Append[" in worker "] ]Append[worker name]] } } nextnode <- [node]Output Types <<[ [()]Append[outtype] ] }{ worker name <- [[node]Data >>]Name >> [prog]Is Method?[worker name] { first arg type <- [[[node]Input Types >>]Index[0]]Index[0] If[[[first arg type]Name >>] = ["Any Type"]] { outtypes <- Fold[Append[?, Type Instance["Any Type"]], (), Range[0, [node]Inputs >>]] nextnode <- [node]Output Types <<[ outtypes ] }{ worker def <- [prog]Find Method[worker name, first arg type] { new worker name <- [[worker name]Append["@"]]Append[[first arg type]Name >>] new ref <- [prog]Find Worker[new worker name] {} { Print[["Could not find worker ref for "]Append[new worker name]] } nextnode <- [[node]Output Types <<[outtypes] ]Data <<[new ref] }{ //TODO: Return errors instead of printing them Print[ [[[[["Type " ]Append[[first arg type]Name >>] ]Append[" does not support method "] ]Append[worker name] ]Append[" in worker "] ]Append[ [worker]Name >> ]] } } }{ worker def <- [prog]Find Worker Def[worker name] {} { Print["Error, could not find worker def"] } nextnode <- [node]Output Types <<[ outtypes ] } outtypes <- [worker def]Output Types >> } } }{ out <- nodelist } } } } } } Val[nextnode] { nextlist <- [nodelist]Set[index, nextnode] out <- Fold[Propagate Types[?, ?, ?, prog, worker, nextnode], nextlist, [nextnode]Wires From >>] } } Infer Types@NWorker[worker,prog:out] { out <- [worker]Nodes <<[Fold[Infer Types Node[?, ?, ?, prog, worker], [worker]Nodes >>, [worker]Nodes >>]] } Add Worker Call@NWorker[worker,tocall:out,node index] { out, node index <- [worker]Add Full Node["call",tocall,[tocall]Inputs >>, [tocall]Min Inputs >>,[tocall]Outputs >>, [tocall]Min 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 Anon Input@NWorker[worker,number:out] { If[[number]>[Length[[worker]Inputs >>]]] { prepped <- [worker]Add Anon Input[[number]-[1]] }{ prepped <- Val[worker] } out <- out <- [[prepped]Inputs <<[[[prepped]Inputs >>]Set[number,[" unnamed"]Append[String[number]]]] ]Input Types <<[[[prepped]Input Types >>]Set[number,Type Instance["Any Type"]]] } Add Typed Input@NWorker[worker,name,number,type:out,node index] { If[[number]>[Length[[worker]Inputs >>]]] { prepped <- [worker]Add Anon Input[[number]-[1]] }{ prepped <- Val[worker] } ,node index <- [prepped]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 Global Get@NWorker[worker,store,var:out,node index] { out, node index <- [worker]Add Node["getglobal",[[()]Append[store]]Append[var],0,1] } Add Global Set@NWorker[worker,store,var:out,node index] { out, node index <- [worker]Add Node["setglobal",[[()]Append[store]]Append[var],1,1] } Add Wire@NWorker[worker,from,output,to,input:out] { fromw <- [[[worker]Nodes >>]Index[from]]Wire From[to,input,output] tow <- [[[worker]Nodes >>]Index[to]]Wire To[from,output,input] nodes <- [[[worker]Nodes >>]Set[from, fromw]]Set[to, tow] out <- [worker]Nodes <<[nodes] } 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[_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[worker, ?], (), direct nodes]] out <- Filter[candidates, Check Dependencies[worker, 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]] } Const Name[val,node index,worker name:out] { valtype <- Blueprint Of[val] If[[valtype] = [Type Instance()]] { //TODO: Support parametric types datstring <- [val]Name >> typename <- "Blueprint" }{ [(Int8(),UInt8(),Int16(),UInt16(),Int32(),UInt32(),Int64(),UInt64())]Find[=[valtype,?]] { size <- [("8","16","32","64")]Index[[~]/[2]] typename <- [("Int8","UInt8","Int16","UInt16","Int32","UInt32","Int64","UInt64")]Index[~] If[[~]Mod[2]] { s <- "UI" } { s <- "I" } datstring <- [[String[val]]Append[s]]Append[size] }{ If[[valtype] = [Worker Literal()]] { typename <- "Worker" If[[[[val]Args >>]Length] > [0]] { datstring <- [[["Arg "]Append[String[node index]]]Append[" "]]Append[worker name] }{ datstring <- [val]Name >> } }{ [(List(),List Leaf())]Find[=[valtype,?]] { typename <- "List" If[[[val]Length] > [0]] { datstring <- [[["Arg "]Append[String[node index]]]Append[" "]]Append[worker name] }{ datstring <- "Empty" } }{ [(String(),String Cat(),String Slice())]Find[=[valtype, ?]] { typename <- "String" datstring <- val }{ typename <- "Unknown" datstring <- String[val] } } } } } out <- [[typename]Append["_"]]Append[datstring] } Format Input@NWorker[worker,noderef:out] { node <- [[worker]Nodes >>]Index[[noderef]Index >>] [("call","getfield","setfield")]Find[=[[node]Type >>, ?]] { maybe addref <- Result Var Name[[noderef]IO Num >>, [noderef]Index >>] }{ conditions <- [node]Conditions >> If[[[node]Type >>] = ["input"]] { input name <- [[worker]Inputs >>]Index[ [node]Data >> ] [conditions]Empty? { out <- AddRef[Result Var Name[[noderef]IO Num >>, [noderef]Index >>]] }{ out <- AddRef[input name] } }{ If[[[node]Type >>] = ["const"]] { [conditions]Empty? { out <- AddRef[Result Var Name[[noderef]IO Num >>, [noderef]Index >>]] }{ out <- Constant[Const Name[[node]Data >>, [noderef]Index >>, [worker]Name >>]] } }{ If[[[node]Type >>]=["getglobal"]] { [conditions]Empty? { out <- AddRef[Result Var Name[[noderef]IO Num >>, [noderef]Index >>]] }{ out <- AddRef[Global Get[[[node]Data >>]Index[0], [[node]Data >>]Index[1]]] } } } } } Val[maybe addref] { If[[Length[[[node]Wires From >>]Index[[noderef]IO Num >>]]] > [1]] { out <- AddRef[maybe addref] }{ out <- Val[maybe addref] } } } Collect Input@NWorker[worker,nodeinput:out] { inputchoices <- Map[nodeinput, Format Input[worker, ?]] [inputchoices]First { first <- [inputchoices]Index[~] [inputchoices]Next[~] { out <- _Fold[inputchoices, ~, first, OrValue[?]] }{ out <- Val[first] } }{ out <- "Missing" } } Collect Inputs@NWorker[worker,node:out] { out <- Map[Tail[[node]Wires To>>, 1], Collect Input[worker, ?]] } Collect Input Condition@NWorker[worker,set,noderef:out] { node <- [[worker]Nodes >>]Index[ [noderef]Index >> ] If[[[node]Outputs >>] > [1]] { out <- [set]Add Condition[ Result Var Name[[noderef]IO Num >>, [noderef]Index >>] ] }{ out <- [set]Add Condition[[node]Conditions >>] } } Collect Condition@NWorker[worker,set,nodeinput:out] { out <- [set]Add Condition[Fold[Collect Input Condition[worker, ?], OrSet[], nodeinput]] } Collect Conditions@NWorker[worker,node:out] { out <- Fold[Collect Condition[worker, ?], AndSet[], [node]Wires To>>] } Save Result[func,num,node index:out] { out <- [func]Move[Result[num], Result Var Name[num, node index]] } Save Maybe Result[func,num,node index:out] { out <- [func]Move[Check Result[num], Result Var Name[num, node index]] } Max Used Output[node,cur:out] { If[[cur] < [0]] { out <- cur }{ [[[node]Wires From >>]Index[cur]]Index[0] { out <- cur }{ out <- Max Used Output[node, [cur]-[1]] } } } 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]] save outs <- [node]Outputs >> out <- Val[after save] }{ If[[[node]Type >>] = ["setfield"]] { with call <- [func]Set Field Call[[node]Data >>, [inputs]Index[0], [inputs]Index[1]] save outs <- [node]Outputs >> out <- Val[after save] }{ fname <- [[node]Data >>]Name >> first unused <- [Max Used Output[node, [[node]Outputs >>]-[1]]]+[1] [program]Method?[fname] { with call <- [func]Method Call[fname, inputs] }{ justfunc,,,normal call <- [fname]Partition["@"] { //Check for inline on static method calls //TODO: Deal with unused output If[[[inputs]Length]=[2]] { out,normal call <- Compile Number Inline Check[func, justfunc, [[[node]Input Types >>]Index[0]]Index[0], [[[node]Input Types >>]Index[1]]Index[0], [inputs]Index[0], [inputs]Index[1], Result Var Name[0, node index]] }{ ,normal call <- If[[[inputs]Length]=[1]] { //TODO: Inline a partial version of If when only one output is used ,normal call <- If[[first unused]>[1]] { out,normal call <- Compile Boolean Inline Check[func, justfunc, [[[node]Input Types >>]Index[0]]Index[0], [inputs]Index[0], Result Var Name[0, node index], Result Var Name[1, node index]] } } } } Val[normal call] { with call <- [func]Call[fname, inputs] } } If[[first unused] > [[node]Min Outputs >>]] { save outs <- [node]Min Outputs >> after maybe <- Fold[Save Maybe Result[?, ?, node index], after save, Range[save outs, first unused]] }{ save outs <- Val[first unused] after maybe <- Val[after save] } If[[first unused] < [[node]Outputs >>]] { out <- [after maybe]Discard Outputs[first unused] }{ out <- Val[after maybe] } } } after save <- Fold[Save Result[?, ?, node index], with call, Range[0, save outs]] } Compile Node[worker,program,func,nodes,current:out,out worker] { node index <- [nodes]Index[current] node <- [[worker]Nodes >>]Index[node index] conditions <- [node]Conditions >> [("call","getfield","setfield")]Find[=[[node]Type >>, ?]] { inputs <- [worker]Collect Inputs[node] [conditions]For Backend { stream <- [func]Instruction Stream nfunc <- [func]Do If[~, nstream] }{ 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"]] { constname <- Const Name[[node]Data >>, node index, [worker]Name >>] withconst <- [func]Register Constant[constname, [node]Data >>] [conditions]For Backend { stream <- [[withconst]Instruction Stream ]Move[Strip Addref[Constant[constname]], Result Var Name[0, node index]] nfunc <- [withconst]Do If[~, stream] }{ nfunc <- Val[withconst] } }{ If[[[node]Type >>]=["getglobal"]] { [conditions]For Backend { stream <- [[func]Instruction Stream ]Move[Global Get[[[node]Data >>]Index[0], [[node]Data >>]Index[1]], Result Var Name[0, node index]] nfunc <- [func]Do If[~, stream] }{ nfunc <- Val[func] } }{ If[[[node]Type >>]=["setglobal"]] { 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]Set Global[[[node]Data >>]Index[0], [[node]Data >>]Index[1], [inputs]Index[0]] }{ [conditions]For Backend { input name <- [[worker]Inputs >>]Index[ [node]Data >> ] stream <- [[func]Instruction Stream ]Move[input name, Result Var Name[0, node index]] nfunc <- [func]Do If[~, stream] }{ nfunc <- Val[func] } } } } } } [nodes]Next[current] { out,out worker <- [worker]Compile Node[program,nfunc,nodes,~] }{ out <- Val[nfunc] out worker <- Val[worker] } } Save Node Conditions[worker,node index:out] { node <- [[worker]Nodes >>]Index[node index] conditions <- [worker]Collect Conditions[node] out <- [worker]Nodes <<[ [[worker]Nodes >>]Set[node index, [node]Conditions <<[conditions]] ] } Save Group Conditions[worker, groups,current:out] { nodes <- [groups]Index[current] nworker <- Fold[Save Node Conditions[?], worker, nodes] [groups]Next[current] { out <- [nworker]Save Group Conditions[groups,~] }{ out <- Val[nworker] } } Compile Group[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 <- Int32[ [parts]Index[3] ] io num <- Int32[ [parts]Index[4] ] node <- [[worker]Nodes >>]Index[index] dests <- [[node]Wires From >>]Index[io num] {} ,normal <- If[[[dests]Length] = [1]] { [dests]Index[0] { dest index <- [~]Index >> dest IO <- [~]IO Num >> } normal <- If[[dest IO] = [-1]] {} { dest node <- [[worker]Nodes >>]Index[dest index] [[dest node]Conditions >>]For Backend { out <- [func]Do If[AndCond[NotCond[~], name], [[func]Instruction Stream]Release[name]] }{ out <- func } } } Val[normal] { 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 Name[io num, index:out] { out <- [[["__result_"]Append[String[index]]]Append["_"]]Append[String[io num]] } Result Var[vars,io num,index:out] { out <- [vars]Append[Result Var Name[io num, index]] } Node Result Vars[vars,node,index:out] { [("call","getfield","setfield","getglobal")]Find[=[[node]Type >>, ?]] { If[[[node]Type >>]=["call"]] { save outs <- [Max Used Output[node, [[node]Outputs >>]-[1]]]+[1] }{ save outs <- [node]Outputs >> } out <- Fold[Result Var[?, ?, index], vars, Range[0, save outs]] }{ out <- vars } } Result Vars@NWorker[worker:out] { out <- Fold[Node Result Vars[?], (), [worker]Nodes >>] } _No Release[vars,node,index,worker:out] { [("const","input")]Find[=[[node]Type >>, ?]] { [[node]Conditions >>]Empty? { out <- Result Var[vars, 0, index] }{ out <- vars } }{ out <- vars } } No Release Results@NWorker[worker:out] { out <- Fold[_No Release[?, ?, ?, worker], (), [worker]Nodes >>] } Make Basic Type[type:out] { out <- [Type Instance[[type]Name >>]]Params <<[ [type]Params >> ] } FInputs[ifunc, input type, index, inputs:out] { func <- [ifunc]Set Input Type[Make Basic Type[input type], index] name <- [inputs]Index[index] If[[[input type]Variant >>] = ["Naked"]] { naked <- [" naked"]Append[name] out <- [[[func]Allocate Var[naked, input type] ]Unbox[name, naked] ]Release[name] }{ If[[input type]Mutable? >>] { name <- [inputs]Index[index] copied <- [func]Copy[name, name] }{ copied <- Val[func] } If[[[input type]Variant >>] = ["Raw Pointer"]] { raw <- [" raw"]Append[name] If[[[input type]Name >>]=["Array"]] { out <- [[copied]Allocate Var[raw, input type] ]Array Raw Pointer[name, raw] }{ out <- [[copied]Allocate Var[raw, input type] ]Get Raw Pointer[name, raw] } }{ out <- Val[copied] } } } Release Raw Inputs[func,input type,index,inputs,outputs:out] { If[[[input type]Variant >>] = ["Raw Pointer"]] { name <- [inputs]Index[index] If[[input type]Mutable? >>] { [outputs]Find[=[?,[inputs]Index[index]]] { out <- func }{ out <- [func]Release[name] } }{ out <- [func]Release[name] } }{ out <- func } } FParams[input:out] { iname <- [input]Index[0] type <- [input]Index[1] If[[[type]Variant >>] = ["Naked"]] { out <- [" naked"]Append[iname] } { If[[[type]Variant >>] = ["Raw Pointer"]] { out <- [" raw"]Append[iname] } { out <- Val[iname] } } } _Return Param[outputs, inputs, input types, index:out,none] { output <- [outputs]Index[index] [inputs]Find[=[output, ?]] { If[[[input types]Index[~]]Mutable? >>] { ,none <- [outputs]Next[index] { out,none <- _Return Param[outputs, inputs, input types, ~] } } { out <- index } }{ out <- index } } Return Param[outputs, inputs, input types:out,none] { ,none <- [outputs]First { out,none <- _Return Param[outputs, inputs, input types, ~] } } Save Foreign Result[func, output, index, output types, inputs, input types:out] { type <- [output types]Index[index] If[[[type]Variant >>] = ["Naked"]] { out <- [func]Box[[" naked"]Append[output], output, type] }{ [inputs]Find[=[output, ?]] { If[[[input types]Index[~]]Mutable? >>] { out <- [func]Move[output, Output[output]] }{ out <- func } }{ out <- func } } } Compile Foreign Stub[worker,program,name:out] { ifunc <- [[program]Create Function[name, [worker]Inputs >>, [worker]Outputs >>, "rhope"] ]Output Types <<[Map[[worker]Output Types >>, Make Basic Type[?]]] rp num <- Return Param[[worker]Outputs >>, [worker]Inputs >>, [worker]Input Types >>] { rbase <- [[worker]Outputs >>]Index[rp num] If[[[[[worker]Output Types >>]Index[rp num]]Variant >>] = ["Naked"]] { rparam <- [" naked"]Append[rbase] rfunc <- [ifunc]Allocate Var[rparam, [[worker]Output Types >>]Index[rp num]] }{ rparam <- Val[rbase] rfunc <- Val[ifunc] } }{ rparam <- "" rfunc <- Val[ifunc] } Fold[FInputs[?, ?, ?, [worker]Inputs >>], rfunc, [worker]Input Types >>] { [~]Call Foreign[name, [worker]Convention >>, Map[Zip[[worker]Inputs >>, [worker]Input Types >>], FParams[?]], rparam] { Fold[Release Raw Inputs[?, ?, ?, [worker]Inputs >>, [worker]Outputs >>], ~, [worker]Input Types >>] { Fold[Save Foreign Result[?, ?, ?, [worker]Output Types >>, [worker]Inputs >>, [worker]Input Types >>], ~, [worker]Outputs >>] { out <- [program]Store Function[~] }}}} } Compile Worker@NWorker[worker,program,name:out] { If[[worker]Builtin? >>] { out <- program }{ If[[[worker]Library >>] = [""]] { ifunc <- Fold[Set Output Type[?], Fold[Set Input Type[?], [[program]Create Function[name,[worker]Inputs >>, [worker]Outputs >>, [worker]Convention >>]]Uses <<[[worker]Uses >>], [worker]Input Types >>], [worker]Output Types >>] groups <- [worker]Dependency Groups fgroup <- [groups]First { with conds <- [worker]Save Group Conditions[groups, ~] final func <- [with conds]Compile Group[program,func,groups, ~] }{ final func <- Val[func] } res vars <- [worker]Result Vars init vars <- Concatenate[res vars, [with conds]No Release Results] func <- Fold[Set Null[?], Fold[Set Null[?], Fold[Allocate Var[?, ?, "Any Type"], ifunc, init vars], init vars], [worker]Outputs >>] out <- [program]Store Function[Fold[Release[?], Fold[Release Var[with conds, ?], final func, res vars], [worker]Inputs >>]] }{ out <- Compile Foreign Stub[worker,[program]Link[[worker]Convention >>, [worker]Library >> ],name] } } } Blueprint NBlueprint { Fields Methods } String@NBlueprint[nbp:out] { out <- [[[["NBlueprint: Fields(" ]Append[Join[Map[[nbp]Fields >>, [?]Index[0]], ", "]] ]Append["), Methods("] ]Append[Join[Keys[[nbp]Methods >>], ", "]] ]Append[")"] } NBlueprint[:out] { out <- [[Build[NBlueprint()]]Fields <<[()]]Methods <<[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 } } Eq Field Name[field,name:out] { out <- [[field]Index[0]]=[name] } Get Field Type@NBlueprint[bp,name:out,notfound] { ,not found <- [[bp]Fields >>]Find[Eq Field Name[?, name]] { out <- [[[bp]Fields >>]Index[~]]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] { If[[[name]=["Call"]] And [[[type]Name >>] = ["Worker"]]] { out <- type }{ out <- [type]Add Method[name] } } Make Init[func,field:out] { name <- [field]Index[0] variant <- [[field]Index[1]]Variant >> If[[variant] = ["Boxed"]] { out <- [func]Set Field Null["obj", name] }{ 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,info,bp name:out] { func name <- [info]Index[0] pop worker <- [info]Index[1] 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 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"] } } }{ ,setref <- [begin setter]Write Field["obj", name] { setter <- [[[~]Unbox["newval", setref] ]Release["newval"] ]Move["obj", "out"] } } out <- [[backend]Store Function[getter]]Store Function[setter] } Compile Blueprint@NBlueprint[bp,backend,name:out] { //Rhope identifiers can't start with spaces, so we can use identifiers that start with spaces for special functions init name <- [" init "]Append[name] [("Array","Boxed Array","Worker")]Find[=[?,name]] { [("internalarraynaked","internalarrayboxed","internalworker")]Index[~] { copy name <- [~]Append["copy"] cleanup name <- [~]Append["cleanup"] } }{ 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] out <- [backend]Register Type[type] } Compile Special@NBlueprint[bp,backend,name:out] { makespecial <- [[[Dictionary[] ]Set["init", Make Init[?]] ]Set["copy", Make Copy[?]] ]Set["cleanup", Make Cleanup[?]] after specials <- Fold[[bp]Make Special[?, ?, name], backend, [backend]Needed Specials[name,makespecial]] out <- Fold[Getters Setters[?, ?, name], after specials, [bp]Fields >>] } Blueprint NProgram { Blueprints Workers Worker Refs Numtypes Global Stores } NProgram[:out] { out <- [[[[[Build[NProgram()] ]Blueprints <<[Dictionary[]] ]Workers <<[Dictionary[]] ]Worker Refs <<[Dictionary[]] ]Numtypes << [("Int8","Int16","Int32","Int64","UInt8","UInt16","UInt32","UInt64")] ]Global Stores <<[Dictionary[]] } Supported Number Types@NProgram[program:out] { out <- [program]Numtypes >> } Bind Worker@NProgram[prog,name,worker:out] { after bind <- [prog]Workers << [ [[prog]Workers >>]Set[name, [worker]Name <<[name]] ] parts <- [name]Split["@"] bpname <- [parts]Index[1] { If[[~]=[""]] { out <- Val[after bind] }{ orig bp <- [[after bind]Blueprints >>]Index[bpname] {} { orig bp <- NBlueprint[] } out <- [after bind]Blueprints <<[ [[after bind]Blueprints >>]Set[bpname, [orig bp]Add Method[[parts]Index[0]] ] ] } }{ out <- Val[after bind] } } Bind Blueprint@NProgram[prog,name,blueprint:out] { 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] { backend with bps <- Generate Boolean Methods[Generate Number Methods[Fold[_Compile Program BP Special[?], Fold[_Compile Program BP[?], [backend]Global Stores <<[[prog]Global Stores >>], [prog]Blueprints >>], [prog]Blueprints >>]]] workers with infer <- Map[[prog]Workers >>, Infer Types[?, prog]] out <- Fold[_Compile Program[?], backend with bps, workers with infer] } Register Method@NProgram[prog, name, convention, inputs, outputs: out] { [[prog]Worker Refs >>]Index[name] { ref <- [[[[[~]Inputs <<[ Max[[~]Inputs >>, inputs] ] ]Min Inputs <<[ Min[[~]Min Inputs >>, inputs] ] ]Outputs <<[ Max[[~]Outputs >>, outputs] ] ]Min Outputs <<[ Min[[~]Min Outputs >>, outputs] ] ]Is Method? <<[Yes] }{ ref <- Worker Ref[name, convention, inputs, outputs, Yes] } out <- [prog]Worker Refs <<[ [[prog]Worker Refs >>]Set[name, ref]] } Register Worker@NProgram[prog, name, convention, inputs, outputs: out] { [[prog]Worker Refs >>]Index[name] { ref <- [[[[~]Inputs <<[ Max[[~]Inputs >>, inputs] ] ]Min Inputs <<[ Min[[~]Min Inputs >>, inputs] ] ]Outputs <<[ Max[[~]Outputs >>, outputs] ] ]Min Outputs <<[ Min[[~]Min Outputs >>, outputs] ] }{ ref <- Worker Ref[name, convention, inputs, outputs, No] } after reg <- [prog]Worker Refs <<[ [ [prog]Worker Refs >> ]Set[name, ref] ] parts <- [name]Split["@"] [parts]Index[1] { If[[~]=[""]] { out <- [after reg]Register Worker[[parts]Index[0], convention, inputs, outputs] }{ out <- [after reg]Register Method@NProgram[[parts]Index[0], convention, inputs, outputs] } }{ out <- Val[after reg] } } Register Builtins@NProgram[prog:out] { registered <- [[[[[[[[[[[[prog]Register Worker["Print", "rhope", 1, 1] ]Register Worker["If@Boolean", "rhope", 1, 2] ]Register Worker["Build", "rhope", 1, 1] ]Register Worker["Blueprint Of", "rhope", 1, 1] ]Register Worker["Call", "rhope", 1, 1]//This will ensure that min outputs is 1 ]Register Worker["Call@Worker", "rhope", 1, 10]//10 is a quick workaround for the lack of proper varargs ]Register Worker["ID", "rhope", 1, 1] ]Register Worker["Blueprint From ID", "rhope", 1, 2] ]Register Worker["Pause", "rhope", 1, 1] ]Register Worker["Resume", "rhope", 2, 2] ]Register Worker["Run Bytecode", "rhope", 2, 1] ]Register Number Methods out <- [[[[[[[[[[registered]Bind Worker["If@Boolean", [[[[[NWorker["rhope"] ]Inputs <<[("condition")] ]Input Types <<[ [()]Append[Type Instance["Boolean"]] ] ]Outputs <<[("isyes","isno")] ]Output Types <<[ [[()]Append[Type Instance["Boolean"]]]Append[Type Instance["Boolean"]] ] ]Builtin? <<[Yes]] ]Bind Worker["Print", [[[[[NWorker["rhope"] ]Inputs <<[("value")] ]Input Types <<[ [()]Append[Type Instance["Any Type"]] ] ]Outputs <<[("out")] ]Output Types <<[ [()]Append[Type Instance["Int32"]] ] ]Builtin? <<[Yes]] ]Bind Worker["Build", [[[[[NWorker["rhope"] ]Inputs <<[("type")] ]Input Types <<[ [()]Append[Type Instance["Blueprint"]] ] ]Outputs <<[("out")] ]Output Types <<[ [()]Append[Type Instance["Any Type"]] ] ]Builtin? <<[Yes]] ]Bind Worker["Blueprint Of", [[[[[NWorker["rhope"] ]Inputs <<[("object")] ]Input Types <<[ [()]Append[Type Instance["Any Type"]]] ]Outputs <<[("type")] ]Output Types <<[ [()]Append[Type Instance["Blueprint"]]] ]Builtin? <<[Yes]] ]Bind Worker["Call@Worker", [[[[[NWorker["rhope"] ]Inputs <<[("worker")] ]Input Types <<[ [()]Append[Type Instance["Worker"]] ] ]Outputs <<[("ret1","ret2","ret3","ret4","ret5","ret6","ret7","ret8","ret9","ret10")] ]Output Types <<[ [[()]Append[Type Instance["Any Type"]]]Append[Type Instance["Any Type"]] ] ]Builtin? << [Yes]] ]Bind Worker["ID", [[[[[NWorker["rhope"] ]Inputs <<[("bp")] ]Input Types <<[ [()]Append[Type Instance["Blueprint"]]] ]Outputs <<[("id")] ]Output Types <<[ [()]Append[Type Instance["UInt32"]]] ]Builtin? << [Yes]] ]Bind Worker["Blueprint From ID", [[[[[NWorker["rhope"] ]Inputs <<[("id")] ]Input Types <<[ [()]Append[Type Instance["UInt32"]]] ]Outputs <<[("bp","none")] ]Output Types <<[ [[()]Append[Type Instance["Blueprint"]]]Append[Type Instance["Any Type"]]] ]Builtin? << [Yes]] ]Bind Worker["Pause", [[[[[NWorker["rhope"] ]Inputs <<[("tocall")] ]Input Types <<[ [()]Append[Type Instance["Worker"]]] ]Outputs <<[("resumeval")] ]Output Types <<[ [()]Append[Type Instance["Any Type"]] ] ]Builtin? <<[Yes]] ]Bind Worker["Resume", [[[[[NWorker["rhope"] ]Inputs <<[("toresume","resumeval")] ]Input Types <<[ [[()]Append[Type Instance["Contest"]]]Append[Type Instance["Any Type"]] ] ]Outputs <<[("success","cantresume")] ]Output Types <<[ [[()]Append[Type Instance["Any Type"]]]Append[Type Instance["Any Type"]] ] ]Builtin? <<[Yes]] ]Bind Worker["Run Bytecode", [[[[[NWorker["rhope"] ]Inputs <<[("bytecode","constants")] ]Input Types <<[ [[()]Append[Type Instance["Array"]]]Append[Type Instance["Boxed Array"]] ] ]Outputs <<[("ret1")] ]Output Types <<[ [()]Append[Type Instance["Any Type"]] ] ]Builtin? <<[Yes] ] } Find Worker@NProgram[prog, name:out,notfound] { out,notfound <- [[prog]Worker Refs >>]Index[name] } Find Worker Def@NProgram[prog,name:out,notfound] { out,notfound <- [[prog]Workers >>]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] } Implicit Conversion@NProgram[prog, fromtype, totype:func,notfound] { notfound <- No } Is Method?@NProgram[prog,name:is,is not] { ,is not <- [[prog]Worker Refs>>]Index[name] { is,is not <- If[[~]Is Method? >>] } }