SS.k 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. / ====================================================================================
  2. / Notes ==============================================================================
  3. / ====================================================================================
  4. / This code uses zipped lists in multiple occasions. Any hardcoded indexing in the code
  5. / is most probably a result of that.
  6. / \d changes the namespace before import to add a prefix to the functions imported to
  7. / avoid overlaps. It is used whe the imported file doesn't define a namespace itself.
  8. / ====================================================================================
  9. / Imports ============================================================================
  10. / ====================================================================================
  11. / utils (ppr -> pretty print)
  12. \d u
  13. \l utils.k
  14. / csv parser
  15. \d csv
  16. \l ngnk-libs/csv/csv.k
  17. \d .
  18. / excel pattern finder
  19. \l excelpm.k
  20. \d .
  21. / ====================================================================================
  22. / helpers ============================================================================
  23. / ====================================================================================
  24. slice: {[l;s;e] s_(e)#l}; / slice a list (l) from start (s) til end (e)
  25. listize: {1_(,/(";",)'{"(",x,")"}'x)}; / turn a list(l) of strings into a string representation of a k list
  26. 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)
  27. s2n: {[s] `i$s;}; / string to number
  28. parseidx: {core: slice[x;1;#x]; split[core;";"]}; / parse a string containing k index
  29. str: `k@;
  30. gi: {[r;c;rb;cb] / generate indices of a rowxcol sheet starting from row=rb and col=cb
  31. i: r#(,!c)
  32. i: ((!r)+rb) {x,'y}'(i+cb);
  33. :i
  34. };
  35. hasloops: {deps:&'x; d:deps; #,/((#deps)(,/'deps@)/d)>0}; / determine if dependency sheet contains loops
  36. order: { / come up with an order of calculations for a dependency graph
  37. deps: {$[+/x>0;&x;()]}'x;
  38. d: ?,/deps;
  39. all: !(#deps);
  40. :d,(all^d)
  41. };
  42. / ====================================================================================
  43. / excel formula handler ==============================================================
  44. / ====================================================================================
  45. mc: {[c;i] / generate indices for column-based indexing
  46. i: gi[(#sheet);i+1;0;c];
  47. :i
  48. };
  49. mr: {[r;i] / generate indices for row-based indexing
  50. i: gi[i+1;(#sheet[0]);r;0];
  51. :i
  52. };
  53. drr: {[s;e] / decode range of indices from start(s) to end(e) with one indicator missing (full rows or full column selection)
  54. r: $[s[0]<0;mc[s[1];(e[1]-s[1])];mr[s[0];(e[0]-s[0])]];
  55. :r
  56. };
  57. dre: {[s;e] / decode range of indices from start(s) to end(e) with both indices present
  58. :gi[(e[0]-s[0])+1;(e[1]-s[1])+1;s[0];s[1]]
  59. };
  60. dr: {[s;e] / decode range from start(s) to end(e)
  61. ln: (s[0]<0) | (s[1]<0);
  62. rn: (e[0]<0) | (e[1]<0);
  63. :$[ln|rn;drr[s;e];dre[s;e]]
  64. };
  65. dbit: {[b] / decode bit - refering to A3 or C5 part of A3:C5
  66. ci: (`i$(b@&(pat.testAtZ'b)))-65; // col index
  67. ri: (`i$(b@&(pat.test0t9'b)))-49; // row index
  68. ci: $[(#ci)>0;*ci;-1];
  69. ri: $[(#ri)>0;*ri;-1];
  70. :(ri;ci)
  71. };
  72. lr: {[f] / turn A3:C5 into left and right bits
  73. ci: *&(":"~'f);
  74. l: slice[f;0;ci];
  75. r: slice[f;ci+1;#f];
  76. lb: dbit[l];
  77. rb: dbit[r];
  78. :(lb;rb);
  79. };
  80. de:{[idx;cell] / decode excel string in a cell
  81. / unwrap input
  82. ci: cell[0]; / cell index
  83. cell: cell[1]; / cell string
  84. idx: (*idx); / index of detected excel string in cell string
  85. f: slice[cell;idx[0];idx[1]]; / excel string
  86. l: slice[cell;0;idx[0]]; / what's before the string
  87. r: slice[cell;idx[1];#cell]; / what's after the string
  88. (fl;fr): lr[f];
  89. range: dr[fl;fr];
  90. / register dependencies
  91. i: (ci[0]*3) + ci[1];
  92. {
  93. i:(*y);
  94. i: (i[0]*3)+i[1];
  95. deps[x;i]: 1;
  96. }[(ci[0]*3)+ci[1];]'range;
  97. / compiled list
  98. cl: {i:(*x); "self[",(`k@x[0;0]),";",(`k@x[0;1]),"]"}'range;
  99. cl: l,"(",({x,";",y}/cl),")",r;
  100. sheet[ci[0];ci[1];1]:: cl;
  101. };
  102. / ====================================================================================
  103. / Compiler ===========================================================================
  104. / ====================================================================================
  105. tstkey: "States/Events"; / key indicating start of transition section
  106. cstkey: "Events"; / key indicating start of events condition section
  107. astkey: "Actions"; / key indicating start of actions section
  108. sectionkeys: (tstkey;cstkey;astkey);
  109. fname: "SS.csv";
  110. tname: "SS";
  111. lines: {x,"\n",y}/(0: fname);
  112. sheet:: csv.csv[lines];
  113. d: (#sheet)*(#sheet[0]);
  114. deps:: (d;d)#0;
  115. / excel patterns
  116. :pats: pat.run''sheet;
  117. u.ppr'sheet;
  118. lasts:{:((#x[0])-1)_x[0]}''pats;
  119. firsts:{:$[(#x[0])>1;((#x[0])-1)#x[0];0]}''pats;
  120. / start with last to maintain prior index accuracy
  121. f: pats {
  122. :$[x[2]=5;y;0]
  123. }''lasts;
  124. ti: gi[#sheet;#sheet [0];0;0];
  125. sheet::ti {(,x),,y}''sheet; / zip sheet and indices
  126. sheet{
  127. :$[y~0;0;de[y;x]]
  128. }''f;
  129. sheet{
  130. :$[y~0;0;de[y;x]]
  131. }''firsts;
  132. ord:order[deps];
  133. / ====================================================================================
  134. / Generator ==========================================================================
  135. / ====================================================================================
  136. compstr:: "/ compiled ",fname,"\n\n";
  137. al: {[l;indt] tab: "" {[x;y] x,"\t"}/(indt#0); compstr:: compstr,tab,l,"\n"}; // add line with indentation
  138. al[(tname,":{[]");0];
  139. al["self:(", (str (#sheet)),";", (str (#sheet[0])), ")#0;\n";1];
  140. {
  141. d: #sheet;
  142. i0: `i$(_(x%d));
  143. i1: x-(i0*d);
  144. al["self[",(str(i0)),";",(str(i1)),"]: ", sheet[i0;i1;1], ";";1];
  145. }'ord;
  146. al[":self";1];
  147. al[("};");0];
  148. `0: compstr;