Mercurial > repos > rhope
view nworker.rhope @ 75:0083b2f7b3c7
Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Jul 2010 07:52:59 -0400 |
parents | a844c623c7df |
children | 2e2e55fc12f9 |
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] { [[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] ]] 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 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] { 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]] } 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 >> }{ If[[Type Of[[node]Data >>]] = ["Machine Integer"]] { If[[[node]Data >>]Signed? >>] { s <- "i" } { s <- "u" } datstring <- [[[[node]Data >>]Value >>]Append[s]]Append[[[node]Data >>]Size >>] }{ If[[Type Of[[node]Data >>]] = ["Worker Literal"]] { If[[[[[node]Data >>]Args >>]Length] > [0]] { datstring <- [[["Arg "]Append[[noderef]Index >>]]Append[" "]]Append[[worker]Name >>] }{ 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] { 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 <- [worker]Collect Conditions[node] [("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"]] { //TODO: Handle list constants If[[Type Of[[node]Data >>]] = ["Type Instance"]] { //TODO: Support parametric types datstring <- [[node]Data >>]Name >> }{ If[[Type Of[[node]Data >>]] = ["Machine Integer"]] { If[[[node]Data >>]Signed? >>] { s <- "i" } { s <- "u" } datstring <- [[[[node]Data >>]Value >>]Append[s]]Append[[[node]Data >>]Size >>] }{ If[[Type Of[[node]Data >>]] = ["Worker Literal"]] { If[[[[[node]Data >>]Args >>]Length] > [0]] { datstring <- [[["Arg "]Append[node index]]Append[" "]]Append[[worker]Name >>] }{ 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 >>] { 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 >>] } 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] } } } 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[[[["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 >>] 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 >>]] }{ 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] ]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] 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] 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 <<[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] { out <- [prog]Worker Refs <<[ [[prog]Worker Refs >>]Set[name, Worker Ref[name, convention, inputs, outputs, Yes]]] } 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 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]] } 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? >>] } }