/ ==================================================================================== / Notes ============================================================================== / ==================================================================================== / This code uses zipped lists in multiple occasions. Any hardcoded indexing in the code / is most probably a result of that. / \d changes the namespace before import to add a prefix to the functions imported to / avoid overlaps. It is used whe the imported file doesn't define a namespace itself. / ==================================================================================== / Imports ============================================================================ / ==================================================================================== / utils (ppr -> pretty print) \d u \l utils.k / csv parser \d csv \l ngnk-libs/csv/csv.k \d . / excel pattern finder \l excelpm.k \d . / ==================================================================================== / helpers ============================================================================ / ==================================================================================== slice: {[l;s;e] s_(e)#l}; / slice a list (l) from start (s) til end (e) listize: {1_(,/(";",)'{"(",x,")"}'x)}; / turn a list(l) of strings into a string representation of a k list split: {[l;di] idx: (-1,&(di~'l)),(#l); {slice[x;y[0]+1;y[1]+1]}[l]'(idx@(2':!#idx))}; / split a list(l) by delimiter (di) s2n: {[s] `i$s;}; / string to number parseidx: {core: slice[x;1;#x]; split[core;";"]}; / parse a string containing k index str: `k@; gi: {[r;c;rb;cb] / generate indices of a rowxcol sheet starting from row=rb and col=cb i: r#(,!c) i: ((!r)+rb) {x,'y}'(i+cb); :i }; hasloops: {deps:&'x; d:deps; #,/((#deps)(,/'deps@)/d)>0}; / determine if dependency sheet contains loops order: { / come up with an order of calculations for a dependency graph deps: {$[+/x>0;&x;()]}'x; d: ?,/deps; all: !(#deps); :d,(all^d) }; / ==================================================================================== / excel formula handler ============================================================== / ==================================================================================== mc: {[c;i] / generate indices for column-based indexing i: gi[(#sheet);i+1;0;c]; :i }; mr: {[r;i] / generate indices for row-based indexing i: gi[i+1;(#sheet[0]);r;0]; :i }; drr: {[s;e] / decode range of indices from start(s) to end(e) with one indicator missing (full rows or full column selection) r: $[s[0]<0;mc[s[1];(e[1]-s[1])];mr[s[0];(e[0]-s[0])]]; :r }; dre: {[s;e] / decode range of indices from start(s) to end(e) with both indices present :gi[(e[0]-s[0])+1;(e[1]-s[1])+1;s[0];s[1]] }; dr: {[s;e] / decode range from start(s) to end(e) ln: (s[0]<0) | (s[1]<0); rn: (e[0]<0) | (e[1]<0); :$[ln|rn;drr[s;e];dre[s;e]] }; dbit: {[b] / decode bit - refering to A3 or C5 part of A3:C5 ci: (`i$(b@&(pat.testAtZ'b)))-65; // col index ri: (`i$(b@&(pat.test0t9'b)))-49; // row index ci: $[(#ci)>0;*ci;-1]; ri: $[(#ri)>0;*ri;-1]; :(ri;ci) }; lr: {[f] / turn A3:C5 into left and right bits ci: *&(":"~'f); l: slice[f;0;ci]; r: slice[f;ci+1;#f]; lb: dbit[l]; rb: dbit[r]; :(lb;rb); }; de:{[idx;cell] / decode excel string in a cell / unwrap input ci: cell[0]; / cell index cell: cell[1]; / cell string idx: (*idx); / index of detected excel string in cell string f: slice[cell;idx[0];idx[1]]; / excel string l: slice[cell;0;idx[0]]; / what's before the string r: slice[cell;idx[1];#cell]; / what's after the string (fl;fr): lr[f]; range: dr[fl;fr]; / register dependencies i: (ci[0]*3) + ci[1]; { i:(*y); i: (i[0]*3)+i[1]; deps[x;i]: 1; }[(ci[0]*3)+ci[1];]'range; / compiled list cl: {i:(*x); "self[",(`k@x[0;0]),";",(`k@x[0;1]),"]"}'range; cl: l,"(",({x,";",y}/cl),")",r; sheet[ci[0];ci[1];1]:: cl; }; / ==================================================================================== / Compiler =========================================================================== / ==================================================================================== tstkey: "States/Events"; / key indicating start of transition section cstkey: "Events"; / key indicating start of events condition section astkey: "Actions"; / key indicating start of actions section sectionkeys: (tstkey;cstkey;astkey); fname: "SS.csv"; tname: "SS"; lines: {x,"\n",y}/(0: fname); sheet:: csv.csv[lines]; d: (#sheet)*(#sheet[0]); deps:: (d;d)#0; / excel patterns :pats: pat.run''sheet; u.ppr'sheet; lasts:{:((#x[0])-1)_x[0]}''pats; firsts:{:$[(#x[0])>1;((#x[0])-1)#x[0];0]}''pats; / start with last to maintain prior index accuracy f: pats { :$[x[2]=5;y;0] }''lasts; ti: gi[#sheet;#sheet [0];0;0]; sheet::ti {(,x),,y}''sheet; / zip sheet and indices sheet{ :$[y~0;0;de[y;x]] }''f; sheet{ :$[y~0;0;de[y;x]] }''firsts; ord:order[deps]; / ==================================================================================== / Generator ========================================================================== / ==================================================================================== compstr:: "/ compiled ",fname,"\n\n"; al: {[l;indt] tab: "" {[x;y] x,"\t"}/(indt#0); compstr:: compstr,tab,l,"\n"}; // add line with indentation al[(tname,":{[]");0]; al["self:(", (str (#sheet)),";", (str (#sheet[0])), ")#0;\n";1]; { d: #sheet; i0: `i$(_(x%d)); i1: x-(i0*d); al["self[",(str(i0)),";",(str(i1)),"]: ", sheet[i0;i1;1], ";";1]; }'ord; al[":self";1]; al[("};");0]; `0: compstr;