Mercurial > repos > rhope
view nworker.rhope @ 121:1af91ceaaf49
Fixed memory leak when an output is only attached to a single null input
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 28 Oct 2010 21:04:12 -0400 |
parents | 43cc42df26cc |
children |
line wrap: on
line source
Import extendlib.rhope Import cbackend.rhope Import number.rhope Import boolean.rhope Blueprint Condition Set { Variables Subsets Condition Type } AndSet[:out] { out <- [[[Build["Condition Set"]]Variables <<[Dictionary[]]]Subsets <<[Dictionary[]]]Condition Type <<["And"] } OrSet[:out] { out <- [[[Build["Condition Set"]]Variables <<[Dictionary[]]]Subsets <<[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] { [subset]For Backend { out <- [[<String@Worker[[type]Append["Cond"]]]Do[ [[()]Append[current]]Append[~] ]]Index[0] }{ out <- current } } Empty?@Condition Set[set:not empty,empty] { Print["Empty?@Condition Set"] [[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] { firstvar <- [[set]Variables >>]First { [[set]Variables >>]Next[~] { vars <- _Fold[[set]Variables >>, ~, firstvar, ["_For Backend Var"]Set Input[3, [set]Condition Type >>]] }{ vars <- Val[firstvar] } out <- Fold[["_For Backend Subset"]Set Input[2, [set]Condition Type >>], vars, [set]Subsets >>] }{ [[set]Subsets >>]First Non-empty Set { firstsub <- [[[set]Subsets >>]Index[~]]For Backend [[set]Subsets >>]Next[~] { out <- _Fold[[set]Subsets >>, ~, firstsub, ["_For Backend Subset"]Set Input[2, [set]Condition Type >>]] }{ out <- Val[firstsub] } }{ 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 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] } 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] {} { exist 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]]Length]] { does,does not <- [node]_Has Input Types[[input num]+[1]] } } } } Has Input Types?@NWorker Node[node:does,does not] { If[[[[node]Inputs >>]Length] > [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"]Set Input[0, "_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 << [""] } 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] { 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] } Propagate Types[nodelist,dests,output num,prog,worker,source node:out] { out <- Fold[[[["Propagate Type"]Set Input[2, prog]]Set Input[3, worker]]Set Input[4, [[source node]Output Types >>]Index[output num]], nodelist, dests] } Infer Types Node[nodelist,node,index,prog,worker:out] { If[[[node]Type >>] = ["const"]] { const type <- Type Of[[node]Data >>] //Temporary hack If[[const type] = ["Whole Number"]] { outtype <- Type Instance["Int32"] }{ If[[const type] = ["Type Instance"]] { outtype <- Type Instance["Blueprint"] }{ If[[const type] = ["Machine Integer"]] { If[[[node]Data >>]Signed? >>] { base <- "Int" } { base <- "UInt" } outtype <- Type Instance[[base]Append[ [[node]Data >>]Size >> ]] }{ If[[const type] = ["Worker Literal"]] { outtype <- Type Instance["Worker"] }{ outtype <- Type Instance[const type] } } } } nextnode <- [node]Output Types <<[ [()]Append[outtype] ] }{ If[[[node]Type >>] = ["input"]] { nextnode <- [node]Output Types <<[ [()]Append[ [[worker]Input Types >>]Index[[node]Data >>] ] ] }{ If[[[node]Type >>] = ["output"]] { out <- nodelist }{ [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"]Set Input[1, Type Instance["Any Type"]], (), Range[0, [node]Inputs >>]] }{ worker def <- [prog]Find Method[worker name, first arg type] {} { //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] } outtypes <- [worker def]Output Types >> nextnode <- [node]Output Types <<[ outtypes ] } } }{ out <- nodelist } } } } Val[nextnode] { nextlist <- [nodelist]Set[index, nextnode] out <- Fold[[[["Propagate Types"]Set Input[3, prog]]Set Input[4, worker]]Set Input[5, nextnode], nodelist, [nextnode]Wires From >>] } } Infer Types@NWorker[worker,prog:out] { out <- [worker]Nodes <<[Fold[[["Infer Types Node"]Set Input[3, prog]]Set Input[4, 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[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 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"]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]] } Const Name[val,node index,worker name:out] { If[[Type Of[val]] = ["Type Instance"]] { //TODO: Support parametric types datstring <- [val]Name >> }{ If[[Type Of[val]] = ["Machine Integer"]] { If[[val]Signed? >>] { s <- "i" } { s <- "u" } datstring <- [[[val]Value >>]Append[s]]Append[[val]Size >>] }{ If[[Type Of[val]] = ["Worker Literal"]] { If[[[[val]Args >>]Length] > [0]] { datstring <- [[["Arg "]Append[node index]]Append[" "]]Append[worker name] }{ datstring <- [val]Name >> } }{ If[[Type Of[val]] = ["List"]] { If[[[val]Length] > [0]] { datstring <- [[["Arg "]Append[node index]]Append[" "]]Append[worker name] }{ datstring <- "Empty" } }{ datstring <- val } } } } out <- [[Type Of[val]]Append["_"]]Append[datstring] } Format Input@NWorker[worker,noderef:out] { node <- [[worker]Nodes >>]Index[[noderef]Index >>] [("call","getfield","setfield")]Find[[node]Type >>] { maybe addref <- [[["__result_"]Append[[noderef]Index >>]]Append["_"]]Append[[noderef]IO Num >>] }{ conditions <- [node]Conditions >> If[[[node]Type >>] = ["input"]] { input name <- [[worker]Inputs >>]Index[ [node]Data >> ] [conditions]For Backend { out <- AddRef[ [[["__result_"]Append[[noderef]Index >>]]Append["_"]]Append[[noderef]IO Num >>] ] }{ out <- AddRef[input name] } }{ If[[[node]Type >>] = ["const"]] { [conditions]For Backend { out <- AddRef[ [[["__result_"]Append[[noderef]Index >>]]Append["_"]]Append[[noderef]IO Num >>] ] }{ out <- Constant[Const Name[[node]Data >>, [noderef]Index >>, [worker]Name >>]] } } } } 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"]Set Input[0, 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"]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] { out <- Fold[["Collect Condition"]Set Input[0, worker], AndSet[], [node]Wires To>>] } Save Result[func,num,node index:out] { out var <- [[["__result_"]Append[node index]]Append["_"]]Append[num] /*out <- [[func]Allocate Var[out var, "Any Type"] ]Move[Result[num], out var] */ out <- [func]Move[Result[num], out var] } Save Maybe Result[func,num,node index:out] { out var <- [[["__result_"]Append[node index]]Append["_"]]Append[num] out <- [func]Move[Check Result[num], out var] } 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] }{ [program]Method?[[[node]Data >>]Name >>] { with call <- [func]Method Call[[[node]Data >>]Name >>, inputs] }{ with call <- [func]Call[[[node]Data >>]Name >>, inputs] } first unused <- [Max Used Output[node, [[node]Outputs >>]-[1]]]+[1] If[[first unused] > [[node]Min Outputs >>]] { save outs <- [node]Min Outputs >> after maybe <- Fold[["Save Maybe Result"]Set Input[2, 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"]Set Input[2, node index], with call, Range[0, save outs]] } Compile Node@NWorker[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_"]Append[node index]]Append["_"]]Append[0]] nfunc <- [withconst]Do If[~, stream] }{ nfunc <- Val[withconst] } }{ [conditions]For Backend { input name <- [[worker]Inputs >>]Index[ [node]Data >> ] stream <- [[func]Instruction Stream ]Move[input name, [[["__result_"]Append[node index]]Append["_"]]Append[0]] 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@NWorker[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@NWorker[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@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[3] ] io num <- <String@Whole Number[ [parts]Index[4] ] node <- [[worker]Nodes >>]Index[index] dests <- [[node]Wires From >>]Index[io num] {} { Print["oops"] { Pretty Print[node, ""] { Pretty Print[parts, ""]}} } ,normal <- If[[[dests]Length] = [1]] { dest ionum <- [[dests]Index[0]]IO Num >> If[[[[dests]Index[0]]IO Num >>]=[-1]] { normal <- Yes }{ dest index <- [[dests]Index[0]]Index >> 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[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 >>] { If[[[node]Type >>]=["call"]] { save outs <- [Max Used Output[node, [[node]Outputs >>]-[1]]]+[1] }{ save outs <- [node]Outputs >> } out <- Fold[["Result Var"]Set Input[2, 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 >>]For Backend { out <- Result Var[vars, 0, index] }{ out <- vars } }{ out <- vars } } No Release Results@NWorker[worker:out] { out <- Fold[["_No Release"]Set Input[3, 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"]Set Input[3, [worker]Inputs >>], rfunc, [worker]Input Types >>] { [~]Call Foreign[name, [worker]Convention >>, Map[Zip[[worker]Inputs >>, [worker]Input Types >>], "FParams"], rparam] { Fold[[["Release Raw Inputs"]Set Input[3, [worker]Inputs >>]]Set Input[4, [worker]Outputs >>], ~, [worker]Input Types >>] { Fold[[[["Save Foreign Result"]Set Input[3, [worker]Output Types >>]]Set Input[4, [worker]Inputs >>]]Set Input[5, [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 >>], [worker]Input Types >>], [worker]Output Types >>] groups <- [worker]Dependency Groups [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"]Set Input[2, "Any Type"], ifunc, init vars], init vars], [worker]Outputs >>] out <- [program]Store Function[Fold["Release", Fold[["Release Var"]Set Input[0, with conds], final func, res vars], [worker]Inputs >>]] }{ out <- Compile Foreign Stub[worker,[program]Link[[worker]Convention >>, [worker]Library >> ],name] } } } 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 <<[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] { 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,func name,bp name,pop worker:out] { 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] { init name <- [" init "]Append[name] [("Array","Boxed Array","Worker")]Find[name] { after copyclean <- Val[backend] }{ copy name <- [" copy "]Append[name] cleanup name <- [" cleanup "]Append[name] after copyclean <- [bp]Make Special[ [bp]Make Special[backend, copy name, name, "Make Copy"], cleanup name, name, "Make Cleanup"] } out <- Fold[["Getters Setters"]Set Input[2, name], [bp]Make Special[after copyclean, init name, name, "Make Init"], [bp]Fields >>] } Blueprint NProgram { Blueprints Workers Worker Refs } NProgram[:out] { out <- [[[Build["NProgram"]]Blueprints <<[Dictionary[]]]Workers <<[Dictionary[]]]Worker Refs <<[Dictionary[]] } Bind Worker@NProgram[prog,name,worker:out] { after bind <- [prog]Workers << [ [[prog]Workers >>]Set[name, [worker]Name <<[name]] ] parts <- [name]Split["@"] [parts]Index[1] { orig bp <- [[after bind]Blueprints >>]Index[~] {} { orig bp <- NBlueprint[] } out <- [after bind]Blueprints <<[ [[after bind]Blueprints >>]Set[~, [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, [prog]Blueprints >>], [prog]Blueprints >>]]] workers with infer <- SMap[[prog]Workers >>, ["Infer Types"]Set Input[1, 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] ] }{ 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] { 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@Worker", "rhope", 1, 2] //We're using 2 because we need to assume that the outputs are conditional ]Register Worker["ID", "rhope", 1, 1] ]Register Worker["Blueprint From ID", "rhope", 1, 2] ]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")] ]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]] } 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? >>] } }