Mercurial > repos > rhope
view parser_old_c.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 | 04148770c229 |
children | fc3815b7462f |
line wrap: on
line source
Import nworker_c.rhope //Rather than rewrite the code that uses this //let's implement Get DString using Partition Get DString[str,delims:after,before,delim,not found] { before,delim,after,not found <- [str]Partition[delims] {} {} {} { before <- str } } Blueprint Parser { Arg Begin Arg End Line Comment Comment Begin Comment End Assign Block Begin Block End Blueprint Type Delim Empty Block Binary Operator String Begin String End String Escape List Begin List End List Delim In Out Delim Do Worker Index Begin Index End Previous Block Val Set Field Get Field Import Blueprint Global Separator Uses Hex Escape Escape Map Foreign } Parser[:out] { out <- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[Build[Parser()] ]Arg Begin << ["["] ]Arg End <<["]"] ]Line Comment <<["//"] ]Comment Begin <<["/*"] ]Comment End <<["*/"] ]Assign <<["<-"] ]Block Begin <<["{"] ]Block End <<["}"] ]Blueprint Type Delim <<[":"] ]Empty Block <<[";"] ]Binary Operator <<["`"] ]String Begin <<["\""] ]String End <<["\""] ]String Escape <<["\\"] ]List Begin <<["("] ]List End <<[")"] ]List Delim <<[","] ]In Out Delim <<[":"] ]Do Worker <<["$"] ]Index Begin <<["("] ]Index End <<[")"] ]Previous <<["@"] ]Set Field <<["<<"] ]Get Field <<[">>"] ]Import <<["Import"] ]Blueprint <<["Blueprint"] ]Global Separator <<["::"] ]Hex Escape <<["x"] ]Uses <<["uses"] ]Escape Map <<[[[[Dictionary[]]Set["n","\n"]]Set["r","\r"]]Set["t","\t"]] ]Foreign <<["Foreign"] } Blueprint Output Reference { Index Output Number } Output Reference[index,num:out] { out <- [[Build[Output Reference()]]Index <<[index]]Output Number <<[num] } Add Pipe Reference[refs,name,reference:out] { reflist <- [refs]Index[name] {} { reflist <- () } out <- [refs]Set[name, [reflist]Append[reference]] } Assignment Save Reference[refs,assignment,output num,parse worker,index:out] { [[parse worker]Outputs >>]Find[=[assignment,?]] { out <- refs }{ out <- Add Pipe Reference[refs, assignment, Output Reference[index, output num]] } } Blueprint Foreign Lib { Language Name } New Foreign Lib[language, library:out] { out <- [[Build[Foreign Lib()] ]Language <<[language] ]Name <<[library] } Blueprint Parse Program { Workers Imports Blueprints Errors } Parse Program[:out] { out <- [[[[Build[Parse Program()] ]Workers <<[Dictionary[]] ]Imports <<[[Dictionary[]]Set["kernel.rhope", Yes]] ]Blueprints <<[Dictionary[]] ]Errors <<[()] } Blueprint Blueprint Definition { Name Fields } New Blueprint Definition[name,fields:out] { out <- [[Build[Blueprint Definition()]]Name << [name]]Fields <<[fields] } Blueprint Parse Worker { Name Inputs Outputs Line Number Trees Uses Stores Input Types Output Types } Parse Worker[name,inputs,outputs,intypes,outtypes,line:out] { out <- [[[[[[[[Build[Parse Worker()]]Name <<[name]]Inputs <<[inputs]]Outputs <<[outputs]]Line Number <<[line]]Trees <<[()]]Uses Stores <<[()]]Input Types <<[intypes]]Output Types <<[outtypes] } Blueprint Worker Node { Name Params Assignments Blocks Index } Worker Node[name,params:out] { out <- [[[[Build[Worker Node()]]Name <<[name]]Params <<[params]]Assignments <<[()]]Blocks <<[()] } Add List Helper[inlist,worker,program,key,parse worker,refs:out list,out worker,out refs] { ,nextworker,nextrefs <- [[inlist]Index[key]]Add to Worker[worker, program, parse worker, refs] { nextlist <- [inlist]Set[key, ~] } [inlist]Next[key] { out list,out worker,out refs <- Add List Helper[nextlist, nextworker, program, ~, parse worker, nextrefs] }{ out list <- Val[nextlist] out worker <- Val[nextworker] out refs <- Val[nextrefs] } } Add List to Worker[list,worker,program,parse worker,refs:out list,out worker,out refs] { [list]First { out list,out worker,out refs <- Add List Helper[list, worker, program, ~, parse worker, refs] }{ out list <- list out worker <- worker out refs <- refs } } _Add Blocks to Worker[blocks,worker,program,parse worker,key,refs:out blocks,out worker,out refs] { block, next worker, nextrefs <- Add List to Worker[[blocks]Index[key], worker, program, parse worker, refs] next blocks <- [blocks]Set[key, block] [blocks]Next[key] { out blocks,out worker,out refs <- _Add Blocks to Worker[next blocks, next worker, program, parse worker, ~, nextrefs] }{ out blocks <- Val[next blocks] out worker <- Val[next worker] out refs <- Val[nextrefs] } } Add Blocks to Worker[blocks,worker,program,parse worker,refs:out blocks,out worker,out refs] { [blocks]First { out blocks, out worker, out refs <- _Add Blocks to Worker[blocks, worker, program, parse worker, ~, refs] }{ out blocks <- blocks out worker <- worker out refs <- refs } } Add to Worker@Worker Node[node,worker,program,parse worker,refs:out node,out worker,out refs] { [program]Find Worker[[node]Name >>] { after worker <- [worker]Add Worker Call[~] {} { //Print[[[[node]Name >>]Append[" has index "]]Append[~]] assignment refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>] [node]Index <<[~] { params list, params worker, params refs <- Add List to Worker[[~]Params >>, after worker, program, parse worker, assignment refs] block list, out worker, out refs <- Add Blocks to Worker[[~]Blocks >>, params worker, program, parse worker, params refs] out node <- [[~]Params <<[params list]]Blocks <<[block list] } } }{ Print[["Error: Could not find a worker named "]Append[[node]Name >>]] } } Check Question Mark[params, index:has mark,no mark] { param,no mark <-[params]Index[index] { If[[Blueprint Of[param]]=[Named Pipe Node()]] { has mark <-If[[[param]Name >>] = ["?"]] {} { has mark,no mark <- Check Question Mark[params, [index]+[1]] } }{ has mark,no mark <- Check Question Mark[params, [index]+[1]] } } } Collect Literal Inputs[literal, params, index, complex inputs:literal out,complex out] { param <- [params]Index[index] { If[[Blueprint Of[param]]=[Literal Node()]] { next literal <- [literal]Set Input[index, [param]Value >>] next complex <- Val[complex inputs] }{ ,doset <- If[[Blueprint Of[param]]=[Named Pipe Node()]] { ,doset <- If[[[param]Name >>] = ["?"]] { //Question mark indicates unpopulated input next complex <- Val[complex inputs] next literal <- Val[literal] } } Val[doset] { next complex <- [complex inputs]Set[index, param] next literal <- Val[literal] } } literal out, complex out <- Collect Literal Inputs[next literal, params, [index]+[1], next complex] }{ literal out <- literal complex out <- complex inputs } } Do Set Input[literal,param,index:out] { out <- Worker Node["Set Input", [[[()]Append[literal]]Append[Literal Node[index]]]Append[param]] } Check Worker Literals@Worker Node[node,program:out] { new params <- Map[[node]Params >>, Check Worker Literals[?, program]] Check Question Mark[new params, 0] { base literal, complex inputs <- Collect Literal Inputs[Worker Literal[[node]Name >>], new params, 0, ()] new node <- Fold[Do Set Input[?], Literal Node[base literal], complex inputs] }{ new node <- [node]Params <<[new params] } out <- [new node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ] } Add Multi Wire[worker,ref,junk,end index,input num:out] { out <- [worker]Add Wire[[ref]Index >>, [ref]Output Number >>, end index, input num] } Add Param Wire[worker,param,input num,end index,blocks,parse worker,assignments:out] { param worker, start index, output num <- [param]Add Wires[worker, blocks, parse worker, assignments] {} { out <- [param worker]Add Wire[start index, output num, end index, input num] }{}{ out <- Fold[Add Multi Wire[?, ?, ?, end index, input num], param worker, ~] } } _Add Block Wire[worker,node,junk,blocks,parse worker,assignments:out] { out <- [node]Add Wires[worker, blocks, parse worker, assignments] } Add Block Wire[worker,block nodes,output num,parent index,existing blocks,parse worker,assignments:out] { blocks <- [existing blocks]Append[Output Reference[parent index, output num]] out <- Fold[_Add Block Wire[?, ?, ?, blocks, parse worker, assignments], worker, block nodes] } Assignments Add Wires[worker,assignment,output num,parse worker,start index:out worker] { [[parse worker]Outputs >>]Find[=[assignment,?]] { ,output index <- [worker]Add Typed Output[assignment, ~, [[parse worker]Output Types >>]Index[~]] { out worker <- [~]Add Wire[start index, output num, output index, 0] } }{ //Ugly hack alert! If[[assignment]Contains["::"]] { parts <- [assignment]Split["::"] ,global index <- [worker]Add Global Set[[parts]Index[0], [parts]Index[1]] { out worker <- [~]Add Wire[start index, output num, global index, 0] } }{ out worker <- worker } } } Has Block@Worker Node[junk:out,unused] { out <- Yes } _Has Block Params[param list,key:out] { param <- [param list]Index[key] out <- [param]Has Block {} { [param list]Next[key] { out <- _Has Block Params[param list, ~] }{ out <- No } } } Has Block Params[param list:out] { [param list]First { out <- _Has Block Params[param list, ~] }{ out <- No } } Add Wires@Worker Node[node,worker,blocks,parse worker,assignments:outworker,index,num,unused] { outworker,index,num <- Add Wires Worker or Field[node, worker, blocks, parse worker, assignments] } Add Wires Worker or Field[node,worker,blocks,parse worker,assignments:outworker,index,num,unused] { Fold[Assignments Add Wires[?, ?, ?, parse worker, [node]Index >>], worker, [node]Assignments >>] { Fold[Add Block Wire[?, ?, ?, [node]Index >>, blocks, parse worker, assignments], ~, [node]Blocks >>] { params worker <- Fold[Add Param Wire[?, ?, ?, [node]Index >>, blocks, parse worker, assignments], ~, [node]Params >>] { index <- [node]Index >> num <- 0 } } } If[Has Block Params[[node]Params >>]] { outworker <- Val[params worker] }{ [blocks]Peek { outworker <- [params worker]Add Wire[[~]Index >>, [~]Output Number >>, [node]Index >>, [0]-[1]] }{ outworker <- Val[params worker] } } } Blueprint Field Node { Name Params Assignments Blocks Index Set? } Has Block@Field Node[junk:has block,unused] { has block <- Yes } Field Node[name,params,set:out] { out <- [[[[[Build[Field Node()]]Name <<[name]]Assignments <<[()]]Blocks <<[()]]Set? <<[set]]Params <<[params] } Add to Worker@Field Node[node,worker,program,parse worker,refs:out node,out worker,out refs] { If[[node]Set? >>] { after worker,index <- [worker]Add Object Set[[node]Name >>] }{ after worker,index <- [worker]Add Object Get[[node]Name >>] } Val[index] { assignment refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>] [node]Index <<[~] { params list, params worker, params refs <- Add List to Worker[[~]Params >>, after worker, program, parse worker, assignment refs] block list, out worker, out refs <- Add Blocks to Worker[[~]Blocks >>, params worker, program, parse worker, params refs] out node <- [[~]Params <<[params list]]Blocks <<[block list] } } } Add Wires@Field Node[node,worker,blocks,parse worker,assignments:outworker,index,num] { outworker,index,num <- Add Wires Worker or Field[node, worker, blocks, parse worker, assignments] } Check Worker Literals@Field Node[node,program:out] { new params <- Map[[node]Params >>, Check Worker Literals[?, program]] out <- [[node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ] ]Params <<[new params] } Blueprint Named Pipe Node { Name Assignments Blocks Index } Has Block@Named Pipe Node[node:has block,no block] { If[[[node]Index >>] < [0]] { //~ should really be a parser parameter If[[[node]Name >>] = ["~"]] { has block <- Yes }{ no block <- No } }{ has block <- Yes } } Named Pipe Node[name:out] { out <- [[[Build[Named Pipe Node()]]Name <<[name]]Assignments <<[()]]Blocks <<[()] } Add to Worker@Named Pipe Node[node,worker,program,parse worker,refs:out node,out worker,out refs] { [[parse worker]Inputs >>]Find[=[[node]Name >>, ?]] { after add <- [worker]Add Typed Input[[node]Name >>, ~, [[parse worker]Input Types>>]Index[~]] {} { assign refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>] index node <- [node]Index <<[~] } }{ after add <- worker index node <- [node]Index <<[[0]-[1]] //TODO: Handle assignments from a named pipe that isn't an input assign refs <- refs } block list, out worker, out refs <- Add Blocks to Worker[[node]Blocks >>, after add, program, parse worker, assign refs] out node <- [index node]Blocks <<[block list] } Add Wires@Named Pipe Node[node,worker,blocks,parse worker,assignments:outworker,index,num,reflist] { reflist <- [assignments]Index[[node]Name >>] { //TODO: Fix support for a named pipe with a block outworker <- worker }{ If[[[node]Name >>] = ["~"]] { wires worker <- worker [blocks]Peek { my index <- [~]Index >> num <- [~]Output Number >> }{ //TODO: Propagate an error rather than printing it out Print["Error, block reference symbol located outside of a block"] } }{ If[[[node]Index >>] < [0]] { Print[[[["Error, reference to named pipe "]Append[[node]Name >>]]Append[" that was never assigned to in worker "]]Append[[parse worker]Name >>]] }{ my index <- [node]Index >> num <- 0 assignments worker <- Fold[Assignments Add Wires[?, ?, ?, parse worker, [node]Index >>], worker, [node]Assignments >>] [blocks]Peek { wires worker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number >>, [node]Index >>, [0]-[1]] }{ wires worker <- Val[assignments worker] } } } } index <- Val[my index] outworker <- Fold[Add Block Wire[?, ?, ?, my index, blocks, parse worker, assignments], wires worker, [node]Blocks >>] } Check Worker Literals@Named Pipe Node[node,program:out] { out <- [node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ] } Blueprint Global Node { Store Name Assignments Blocks Index } Global Node[store,name:out] { out <- [[[[Build[Global Node()]]Store <<[store]]Name <<[name]]Assignments <<[()]]Blocks <<[()] } Add to Worker@Global Node[node,worker,unused,parse worker,refs:out node,out worker,outrefs] { out worker <- [worker]Add Global Get[[node]Store >>, [node]Name >>] {} { outrefs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>] out node <- [node]Index <<[~] } outrefs <- refs } Add Wires@Global Node[node,worker,blocks,parse worker,assignments:outworker,index,num,unused] { outworker,index,num <- Add Wires Literal or Global[node, worker, blocks, parse worker, assignments] } Has Block@Global Node[junk:out,unused] { out <- Yes } Check Worker Literals@Global Node[node,program:out] { out <- [node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ] } Blueprint Literal Node { Value Assignments Blocks Index } Has Block@Literal Node[junk:out,unused] { out <- Yes } Literal Node[value:out] { out <- [[[Build[Literal Node()]]Value <<[value]]Assignments <<[()]]Blocks <<[()] } Add to Worker@Literal Node[node,worker,unused,parse worker,refs:out node,out worker,out refs] { out worker <- [worker]Add Constant[[node]Value >>] {} { out refs <- Fold[Assignment Save Reference[?, ?, ?, parse worker, ~], refs, [node]Assignments >>] out node <- [node]Index <<[~] } } Add Wires@Literal Node[node,worker,blocks,parse worker,assignments:outworker,index,num,unused] { outworker,index,num <- Add Wires Literal or Global[node, worker, blocks, parse worker, assignments] } Check Worker Literals@Literal Node[node,program:out] { out <- [node]Blocks <<[ Map[[node]Blocks >>, Map[?, Check Worker Literals[?, program]]] ] } Add Wires Literal or Global[node,worker,blocks,parse worker,junk:outworker,index,num,unused] { assignments worker <- Fold[Assignments Add Wires[?, ?, ?, parse worker, [node]Index >>], worker, [node]Assignments >>] [blocks]Peek { outworker <- [assignments worker]Add Wire[[~]Index >>, [~]Output Number>>, [node]Index >>, [0]-[1]] }{ outworker <- Val[assignments worker] } index <- [node]Index >> num <- 0 } Blueprint Block Node { Number } Blueprint Parse Error { Type Text Line Number } Parse Error[type,text,number:out] { out <- [[[Build[Parse Error()]]Type <<[type]]Text <<[text]]Line Number <<[number] } Not Empty[string:out] { If[[[string]Length] > [0]] { out <- Yes }{ out <- No } } Blueprint Blueprint Field { Name Type } New Blueprint Field[name,type:out] { out <- [[Build[Blueprint Field()]]Name <<[name]]Type <<[type] } Process Blueprint Field[list,field,params:out] { ,name <- [field]Get DString[[params]List Begin >>] { type info <- Parse List[~,params,()] type <- [type info]Index[0] { If[[Blueprint Of[~]] = [Named Pipe Node()]] { before variant <- Type Instance[[type]Name >>] }{ before variant <- [type]Params <<[ Map[[type]Params >>, Remove Named Pipe Node[?]] ] } variant <- [type info]Index[1] { ,warn <- If[[Blueprint Of[~]] = [Named Pipe Node()]] { fieldtype,warn <- [before variant]Set Variant[[variant]Name >>] } Val[warn] { Print[[[["Warning: Invalid variant for type "]Append[[before variant]Name >>]]Append[" on field "]]Append[name]] fieldtype <- Val[before variant] } }{ fieldtype <- Val[before variant] } }{ fieldtype <- Type Instance["Any Type"] } out <- [list]Append[New Blueprint Field[name, fieldtype]] } {} {} { out <- [list]Append[New Blueprint Field[name, Type Instance["Any Type"]]] } } Block Comment[string,begin comment,end comment,block count:out] { If[[block count] > [0]] { after, before <- [string]Get DString[[[()]Append[begin comment]]Append[end comment]] {} {} { If[[~] = [begin comment]] { out <- Block Comment[after, begin comment, end comment, [block count]+[1]] }{ out <- Block Comment[after, begin comment, end comment, [block count]-[1]] } }{ //No match out <- "" } }{ out <- string } } Line Comment[string:out] { [string]Get DString["\n"] { out <- ["\n"]Append[~] } {} {} { out <- "" } } _Get Comment DString[string,delims,line comment,begin comment,end comment,prev before:rest,before,delim,nomatch] { after,befored,used delim,nomatch <- [string]Get DString[delims] { If[[used delim] = [line comment]] { after comment <- Line Comment[after] }{ If[[used delim] = [begin comment]] { after comment <- Block Comment[after, begin comment, end comment, 1] }{ rest <- Val[after] before <- [prev before]Append[befored] delim <- Val[used delim] } } } {} {} { before <- [prev before]Append[befored] } after comment { rest,more before,delim,nomatch <- _Get Comment DString[~, delims, line comment, begin comment, end comment, prev before] before <- [before]Append[more before] } } As List[val:out] { [(List(),List Leaf())]Find[=[Blueprint Of[val], ?]] { out <- val }{ out <- [()]Append[val] } } Get Comment DString[string,delims,params:rest,before,delim,not found] { line comment <- [params]Line Comment >> begin comment <- [params]Comment Begin >> end comment <- [params]Comment End >> all delims <- [[[delims]As List]Append[begin comment]]Append[line comment] rest, before, delim, not found <- _Get Comment DString[string, delims, line comment, begin comment, end comment, ""] } Comment Left Trim[string,trim chars,params:out] { line comment <- [params]Line Comment >> end comment <- [params]Comment End >> trimmed <- Left Trim[string, trim chars] If[[trimmed]Starts With[line comment]] { ,after delim <- [trimmed]Slice[[line comment]Length] out <- Comment Left Trim[Line Comment[after delim], trim chars, params] }{ begin comment <- [params]Comment Begin >> If[[trimmed]Starts With[begin comment]] { ,after delim <- [trimmed]Slice[[line comment]Length] out <- Comment Left Trim[Block Comment[after delim, begin comment, end comment, 1], trim chars, params] }{ out <- Val[trimmed] } } } PBlueprint[string,params,tree,lines:out] { ,whitespace name <- [string]Get Comment DString[[params]Block Begin >>, params] { ,no blueprint <- [whitespace name]Slice[ [[params]Blueprint >>]Length ] name <- Trim[no blueprint, "\r\n\t "] name lines <- 0 ,body <- [~]Get Comment DString[ [params]Block End >>, params] { body lines <- [body]Split["\n"] more lines <- [[[body lines]Length] - [1]] + [name lines] fields <- Fold[Process Blueprint Field[?, ?, params], (), Filter[Map[body lines, Trim[?,"\n\r\t "]], Not Empty[?]]] new tree <- [tree]Blueprints << [ [[tree]Blueprints >>]Set[name, New Blueprint Definition[name, fields]] ] out <- Null[~, params, new tree, [lines] + [more lines]] } {} {} { out <- [tree]Errors <<[ [[tree]Errors >>]Append[Parse Error["Error",[["Blueprint is missing an block close symbol \""]Append[[params]Block End >>]]Append["\""], lines]] ] } } {} {} { out <- [tree]Errors <<[ [[tree]Errors >>]Append[Parse Error["Error",[["Blueprint is missing an block open symbol \""]Append[[params]Block Begin >>]]Append["\""], lines]] ] } } Parse Import[string,params,tree,lines:out] { [line]Slice[ [[params]Import >>]Length ] {} { filename <- Trim[~, " \n\r\t"] } new tree <- [tree]Imports <<[[[tree]Imports >>]Set[filename, Yes]] ,line <- [string]Get Comment DString["\n", params] { out <- Null[~, params, new tree, [lines] + [1]] } {} {} { out <- Val[new tree] } } Get Expression Blocks[string,params,blocks:outblocks,after] { check block <- Comment Left Trim[string, "\n\r\t ", params] If[[check block]Starts With[[params]Block Begin >>]] { ,begin block <- [check block]Slice[[[params]Block Begin >>]Length] trees, after block <- Worker Body[begin block, params, ()] outblocks, after <- Get Expression Blocks[after block, params, [blocks]Append[trees]] }{ If[[check block]Starts With[[params]Empty Block >>]] { outblocks <- blocks ,after <- [check block]Slice[[[params]Empty Block >>]Length] }{ outblocks <- blocks after <- Val[check block] } } } Parse Escape[string,params:char,after] { code,rest <- [string]Slice[1] If[[code] = [[params]Hex Escape >>]] { hex,after <- [rest]Slice[2] char <- String[[Array[]]Append[Trunc UInt8[Abs UInt[Hex Int32[hex]]]]] }{ after <- Val[rest] char <- [[params]Escape Map >>]Index[code] {} { char <- Val[code] } } } Parse String[string,params,current:value,after] { delims <- [[()]Append[[params]String End >>]]Append[[params]String Escape >>] afters, before, delim <- [string]Get Comment DString[delims, params] { If[[delim] = [[params]String End >>]] { value <- [current]Append[before] after <- Val[afters] }{ char,after escape <- Parse Escape[afters, params] value,after <- Parse String[after escape, params, [[current]Append[before]]Append[char]] } } } Parse List[string,params,list:value,after] { trimmed <- Comment Left Trim[string, "\r\n\t ", params] If[[trimmed]Starts With[[params]List End >>]] { value <- list ,after <- [trimmed]Slice[[[params]List End >>]Length] }{ If[[trimmed]Starts With[[params]List Delim >>]] { ,el string <- [trimmed]Slice[[[params]List Delim >>]Length] }{ el string <- Val[trimmed] } element,after el <- Named Pipe or Literal[el string, params] value,after <- Parse List[after el, params, [list]Append[[element]Get Value]] } } Get Value@Literal Node[node:out] { out <- [node]Value >> } Get Value@Named Pipe Node[node:out] { out <- node } Machine Integer[val, size, signed?:out] { conv <- [[[[[[[[() ]Append[UInt8[?]] ]Append[Int8[?]] ]Append[UInt16[?]] ]Append[Int16[?]] ]Append[UInt32[?]] ]Append[Int32[?]] ]Append[UInt64[?]] ]Append[Int64[?]] base idx <- [[(8,16,32,64)]Find[=[size,?]]]*[2] If[signed?] { idx <- [base idx]+[1] }{ idx <- Val[base idx] } out <- [[conv]Index[idx]]Call[val] } Parse Number[string,params:value,after] { delims <- [[[[(" ","\t","\n","\r")]Append[[params]List Delim >>]]Append[[params]Block Begin >>]]Append[[params]Arg End >>]]Append[[params]List End >>] after delim,valstring <- [string]Get Comment DString[delims, params] {} {} { after <- [~]Append[after delim] }{ after <- "" } first two,rest <- [valstring]Slice[2] If[[first two] = ["0x"]] { value <- Hex Int32[rest] }{ If[[valstring]Contains["."]] { value <- Real64[valstring] }{ size, val, type <- [valstring]Get DString[("i","u")] { value <- Machine Integer[val, Int32[size], [type]=["i"]] } {} {} { value <- Int32[valstring] } } } } Parse Params@Type Instance[literal,params,string:out,after] { plist,after <- Parse List[string,params,()] out <- [literal]Params <<[plist] } Named Pipe or Literal[string,params:out,after] { name <- Comment Left Trim[string, "\n\r\t ", params] If[[name]Starts With[[params]String Begin >>]] { ,string begin <- [name]Slice[[[params]String Begin >>]Length] value,after <- Parse String[string begin, params, ""] }{ If[[name]Starts With[[params]List Begin >>]] { ,list start <- [name]Slice[[[params]List Begin >>]Length] value,after <- Parse List[list start, params, ()] }{ If[[[name]Slice[1]]In["-0123456789"]] { value,after <- Parse Number[name, params] }{ delims <- [[[[[[[("\n")]Append[[params]Block Begin >>]]Append[[params]Block End >>]]Append[[params]Empty Block >>]]Append[[params]Arg End >>]]Append[[params]List Delim >>]]Append[[params]List End >>]]Append[[params]List Begin >>] afterdelim,raw before,delim,nodelim <- [name]Get Comment DString[delims, params] before <- Trim[raw before, "\r\n\t "] If[[delim] = [[params]List Begin >>]] { value,after <- [Type Instance[before]]Parse Params[params,afterdelim] }{ Val[afterdelim] { after <- [delim]Append[~] } Val[nodelim] { after <- "" } If[[before] = ["Yes"]] { yesno <- Yes }{ If[[before] = ["No"]] { yesno <- No }{ If[[before] = [""]] { Print[[["Found "]Append[delim]]Append[" where a named pipe or literal was expected"]] { Print[["Near: "]Append[ [afterdelim]Slice[80]]] } }{ If[[before]Contains[[params]Global Separator >>]] { parts <- [before]Split[[params]Global Separator >>] out <- Global Node[Right Trim[[parts]Index[0],"\r\n\t "], Trim[[parts]Index[1], "\r\n\t "]] }{ out <- Named Pipe Node[Right Trim[before,"\r\n\t "]] } } } } out <- Literal Node[yesno] } } } } out <- Literal Node[value] } Parse Arguments[string,params,arglist:args,after] { targs <- Comment Left Trim[string, "\r\n\t ", params] If[[targs]Starts With[[params]List Delim >>]] { [targs]Slice[[[params]List Delim >>]Length] {} { final args <- Comment Left Trim[~, "\r\n\t ", params] } }{ If[[targs]Starts With[[params]Arg End >>]] { args <- arglist ,after <- [targs]Slice[[[params]Arg End >>]Length] }{ final args <- Val[targs] } } arg, after arg <- Parse Expression[final args, params] args, after <- Parse Arguments[after arg, params, [arglist]Append[arg]] } Worker or Field[name,args,params:out] { get field <- [params]Get Field >> If[[name]Ends With[get field]] { field <- Right Trim[[name]Slice[[[name]Length] - [[get field]Length]], "\n\r\t "] out <- Field Node[field, args, No] }{ set field <- [params]Set Field >> If[[name]Ends With[set field]] { field <- Right Trim[[name]Slice[[[name]Length] - [[set field]Length]], "\n\r\t "] out <- Field Node[field, args, Yes] }{ out <- Worker Node[name, args] } } } Prefix[string,params,name,existing args:expression,after] { //Parse argument list more args,after <- Parse Arguments[string, params, existing args] expression <- Worker or Field[name, more args, params] } Postfix or Infix[string,params:expression,after] { args, after args <- Parse Arguments[string, params, ()] delims <- [[[[[("\n")]Append[[params]Arg Begin >>]]Append[[params]Empty Block >>]]Append[[params]Block Begin >>]]Append[[params]Arg End >>]]Append[[params]List Delim >>] aftere,before,delim <- [after args]Get Comment DString[delims, params] { If[[delim] = [[params]Arg Begin >>]] { expression, after <- Prefix[aftere, params, Trim[before,"\r\n\t "], args] }{ If[[delim] = [[params]Empty Block >>]] { after <- Val[aftere] }{ ,after <- [after args]Slice[[before]Length] } expression <- Worker or Field[Trim[before,"\r\n\t "], args, params] } } } Parse Expression[trimmed,params:final expression,after blocks] { delims <- [[[[[[[("\n")]Append[[params]Arg Begin >>]]Append[[params]Arg End >>]]Append[[params]Assign >>]]Append["\n"]]Append[[params]Empty Block >>]]Append[[params]Block End >>]]Append[[params]String Begin >>] after, before, delim <- [trimmed]Get Comment DString[delims, params] { //If we find an arg begin token, we have a worker expression If[[delim] = [[params]Arg Begin >>]] { maybe name <- Right Trim[before, "\r\t "] //Prefix expressions will have the worker name before the first arg begin token If[[maybe name] = [""]] { expression, after expression <- Postfix or Infix[after, params] }{ If[[maybe name]Contains[[params]List Delim >>]] { after expression <- [after literal]Append[[delim]Append[after]] expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params] }{ expression, after expression <- Prefix[after, params, maybe name, ()] } } }{ If[[delim] = [[params]Assign >>]] { //Expressions starting with an assignment can be prefix, postfix or infix //or they can be a simple literal or named pipe assignments <- Map[[before]Split[[params]List Delim >>], Trim[?,"\n\r\t "]] ,after blocks <- Parse Expression[Comment Left Trim[after, " \n\r\t", params], params] { final expression <- [~]Assignments <<[assignments] } }{ //If[[delim] = [[params]String Begin >>]] //{ // If[[Trim[before, "\r\n\t "]] = [""]] // { // expression, after expression <- Named Pipe or Literal[[delim]Append[after], params] // }{ // after expression <- [after literal]Append[[delim]Append[after]] // expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params] // } //}{ // after expression <- [after literal]Append[[delim]Append[after]] // expression, after literal <- Named Pipe or Literal[Right Trim[before, "\r\n\t "], params] //} expression, after expression <- Named Pipe or Literal[trimmed, params] } } //Any expression can be followed by one or more blocks mapping the inputs of other expressions //to the outputs of the current one blocks,after blocks <- Get Expression Blocks[after expression, params, ()] final expression <- [expression]Blocks <<[blocks] } } Worker Body[string,params,trees:outtrees,after end] { trimmed <- Comment Left Trim[string, "\n\r\t ", params] If[[trimmed]Starts With[[params]Block End >>]] { //We're done with this block, return ,after end <- [trimmed]Slice[[[params]Block End >>]Length] outtrees <- trees }{ expression, after expression <- Parse Expression[trimmed, params] outtrees,after end <- Worker Body[after expression, params, [trees]Append[expression]] } } Process Modifiers[worker,params,modifiers:out] { //Eventually this will need to be more sophisticated to handle more modifiers trimmed <- Comment Left Trim[modifiers, "\n\r\t ", params] If[[trimmed]Starts With[[params]Uses >>]] { ,after uses <- [trimmed]Slice[[[params]Uses >>]Length] ,stores string <- [after uses]Get Comment DString["\n", params] out <- [worker]Uses Stores <<[Map[[stores string]Split[[params]List Delim >>], Trim[?, "\r\n\t "]]] }{ out <- worker } } Remove Named Pipe Node[element:out] { If[[Blueprint Of[element]] = [Named Pipe Node()]] { out <- [element]Name >> }{ If[[Blueprint Of[element]] = [Type Instance()]] { out <- [element]Params <<[ Map[[element]Params >>, Remove Named Pipe Node[?]] ] }{ out <- element } } } Parse Param List[text,paramlist,typelist,params:out params,out types] { delims <- [[()]Append[[params]List Begin >>]]Append[[params]List Delim >>] after,param name <-[text]Get DString[delims] {} { tname <- Trim[~, "\r\n\t "] If[[tname] = [""]] { nextlist <- Val[paramlist] next types <- Val[typelist] }{ nextlist <- [paramlist]Append[tname] next types <- [typelist]Append[paramtype] } }{ If[[~] = [[params]List Begin >>]] { type info,after type <- Parse List[after,params,()] type <- [type info]Index[0] { If[[Blueprint Of[~]] = [Named Pipe Node()]] { before variant <- Type Instance[[type]Name >>] }{ before variant <- <- [type]Params <<[ Map[[type]Params >>, Remove Named Pipe Node[?]] ] } variant <- [type info]Index[1] { ,warn <- If[[Blueprint Of[~]] = [Named Pipe Node()]] { before mutable,warn <- [before variant]Set Variant[[variant]Name >>] } Val[warn] { Print[[[["Warning: Invalid variant for type "]Append[[before variant]Name >>]]Append[" on input "]]Append[param name]] before mutable <- Val[before variant] } }{ before mutable <- Val[before variant] } [type info]Index[2] { paramtype <- [before mutable]Mutable? <<[ [[~]Name >>] = ["Mutable"] ] }{ paramtype <- Val[before mutable] } }{ paramtype <- Type Instance["Any Type"] } [after type]Get DString[","] { out params,out types <- Parse Param List[~,nextlist,next types,params] } {} {} { out params <- Val[nextlist] out types <- Val[next types] } }{ paramtype <- Type Instance["Any Type"] out params,out types <- Parse Param List[after,nextlist,next types,params] } }{ paramtype <- Type Instance["Any Type"] out params <- Val[nextlist] out types <- Val[next types] } } Worker Declaration[string,params:worker,rest,no match] { ,whitespace name <- [string]Get Comment DString[[params]Arg Begin >>, params] { worker name <- Trim[whitespace name, "\n\r\t "] in out <- [params]In Out Delim >> arg end <- [params]Arg End >> delims <- [[()]Append[in out]]Append[arg end] after <- [~]Get Comment DString[delims, params] {} { arglist <- Trim[~,"\r\n\t "] }{ //check if there is an in/out separator //if it isn't present, everything in the arglist is an input If[[~] = [in out]] { rest <- [after]Get Comment DString[arg end, params] {} { outputs,output types <- Parse Param List[~, (), (), params] } }{ rest <- Val[after] outputs <- () output types <- () } inputs,input types <- Parse Param List[arglist, (), (), params] worker <- Parse Worker[worker name, inputs, outputs, input types, output types, 0] } }{}{}{ no match <- string } } Worker Name[string,params,tree,lines:out] { ,after arglist <- Worker Declaration[string, params] { worker name <- [~]Name >> body text, modifiers <- [after arglist]Get Comment DString[[params]Block Begin >>, params] modified <- Process Modifiers[~, params, modifiers] expression trees, after body <- Worker Body[body text, params, ()] worker <- [modified]Trees <<[expression trees] new worker dict <- [[tree]Workers >>]Set[worker name, worker] out <- Null[after body, params, [tree]Workers <<[new worker dict], 0] } {} { out <- tree } } Parse Foreign Worker[tree, string, lib, params:out] { ,rest <- Worker Declaration[string, params] { foreign <- [~]Trees << [lib] next <- [tree]Workers << [[[tree]Workers >>]Set[[foreign]Name >>, foreign]] out <- Parse Foreign Worker[next, rest, lib, params] } {} { out <- tree } } Parse Foreign[string,params,tree,lines:out] { ,after foreign <- [string]Slice[[[params]Foreign >>]Length] [after foreign]Get Comment DString[[params]Blueprint Type Delim >>, params] { [~]Get Comment DString[[params]Block Begin >>, params] { rest, body <- [~]Get Comment DString[[params]Block End >>, params] } { lib <- Trim[~, "\r\n\t "] } } { language <- Trim[~, "\r\n\t "] } Parse Foreign Worker[tree, body, New Foreign Lib[language, lib], params] { out <- Null[rest, params, ~, 0] } } Null[string,params,tree,lines:out] { trimmed <- Comment Left Trim[string, " \n\r\t", params] current line <- 0 If[[trimmed]Starts With[ [params]Blueprint >> ]] { out <- PBlueprint[trimmed, params, tree, current line] }{ If[[trimmed]Starts With[ [params]Import >> ]] { out <- Parse Import[trimmed, params, tree, current line] }{ If[[trimmed]Starts With[ [params]Foreign >> ]] { out <- Parse Foreign[trimmed, params, tree, current line] }{ If[trimmed] { out <- Worker Name[trimmed, params, tree, current line] }{ out <- tree } } } } } Check Worker Literals@Parse Worker[worker,program:out] { [(List(),List Leaf())]Find[=[Blueprint Of[[worker]Trees >>], ?]] { out <- [worker]Trees <<[ Map[[worker]Trees >>, Check Worker Literals[?, program]] ] }{ out <- worker } } Register Workers Compile[prog, worker, name:out] { //Print[["Registering "]Append[name]] If[[ Blueprint Of[[worker]Trees >>] ] = [Foreign Lib()]] { convention <- Val[[[worker]Trees >>]Language >>] } { convention <- "rhope" } out <- [prog]Register Worker[name, convention, [[worker]Inputs >>]Length, [[worker]Outputs >>]Length] } Add Workers Compile[prog, worker, name:out] { Print[["Transforming "]Append[name]] If[[Blueprint Of[[worker]Trees >>]] = [Foreign Lib()]] { //TODO: Handle foreign func final nworker <- [[[[[NWorker[[[worker]Trees >>]Language >>] ]Inputs <<[ [worker]Inputs >> ] ]Input Types <<[ [worker]Input Types >> ] ]Outputs <<[ [worker]Outputs >> ] ]Output Types <<[ [worker]Output Types >> ] ]Library <<[ [[worker]Trees >>]Name >> ] }{ trees, nworker, refs <- Add List to Worker[[worker]Trees >>, [[NWorker["rhope"]]Uses[[worker]Uses Stores >>]]Outputs <<[ [worker]Outputs >> ], prog, worker, Dictionary[]] { final nworker <- Fold[Add Wires Helper[?, ?, ?, worker, refs], nworker, trees] } } out <- [prog]Bind Worker[name, final nworker] } Add Wires Helper[worker,node,unused,parse worker,assignments:out] { out <- [node]Add Wires[worker, (), parse worker, assignments] } Add Blueprint Field[blueprint,field,unused:out] { out <- [blueprint]Add Field[[field]Name >>, [field]Type >>] } Add Blueprint Compile[prog,def:out] { out <- [prog]Bind Blueprint[[def]Name >>, Fold[Add Blueprint Field[?], NBlueprint[], [def]Fields >>]] } Tree to Program Native[parse tree:out] { registered <- Fold[Register Workers Compile[?], [Fold[Add Blueprint Compile[?], NProgram[], [parse tree]Blueprints >>]]Register Builtins, [parse tree]Workers >>] out <- Fold[Add Workers Compile[?], registered, [parse tree]Workers >>] { Print["Transformed AST to dataflow graph "] } } Needs Imports[needs import,not imported?,name:out] { If[not imported?] { out <- [needs import]Append[name] }{ out <- needs import } } Do Import[tree,file name,unused,params:out] { Print[["Parsing: "]Append[file name]] file <- [File[file name]]Open["r"] text <- String[[file]Read[[file]Length]] after import <- Null[text, params, tree, 0] out <- [after import]Imports <<[[[after import]Imports >>]Set[file name, No]] } Process Imports[parse tree,params:out] { needs import <- Fold[Needs Imports[?], (), [parse tree]Imports >>] If[[[needs import]Length] > [0]] { import tree <- Fold[Do Import[?, ?, ?, params], parse tree, needs import] out <- Process Imports[import tree, params] }{ out <- parse tree } } Until End[text:out] { line <- Get Input[] If[[line] = ["End"]] { out <- [text]Append["\n"] }{ out <- Until End[[[text]Append["\n"]]Append[line]] } } Add If Store[stores,name,params:out] { If[[name]Contains[[params]Global Separator >>]] { parts <- [name]Split[[params]Global Separator >>] out <- [stores]Set[[parts]Index[0], Yes] }{ out <- stores } } Param Gather Stores[stores,node,params:out] { out <- [node]Gather Stores[params, stores] } Gather Stores@Named Pipe Node[node,params,stores:out] { out <- Fold[Add If Store[?, ?, params], stores, [node]Assignments >>] } Gather Stores@Global Node[node,params,stores:out] { out <- [stores]Set[[node]Store >>, Yes] } Gather Stores@Worker Node[node,params,stores:out] { //TODO: Handle blocks store list <- Fold[Param Gather Stores[?, ?, params], stores, [node]Params >>] out <- Fold[Add If Store[?, ?, params], store list, [node]Assignments >>] } Gather Stores@Field Node[node,params,stores:out] { //TODO: Handle blocks store list <- Fold[Param Gather Stores[?, ?, params], stores, [node]Params >>] out <- Fold[Add If Store[?, ?, params], store list, [node]Assignments >>] } Gather Stores@Literal Node[node,params,stores:out] { out <- Fold[Add If Store[?, ?, params], stores, [node]Assignments >>] }