about summary refs log tree commit diff stats
path: root/012transform.cc
blob: f62349faad8aec163e24597becf0e3cbc68381da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//: Phase 2: Filter loaded recipes through an extensible list of 'transforms'.
//:
//:   The process of running Mu code:
//:     load -> transform -> run
//:
//: The hope is that this framework of transform tools will provide a
//: deconstructed alternative to conventional compilers.
//:
//: We're going to have many transforms in Mu, and getting their order right
//: (not the same as ordering of layers) is a well-known problem. Some tips:
//:   a) Design each layer to rely on as few previous layers as possible.
//:
//:   b) When positioning transforms, try to find the tightest constraint in
//:   each transform relative to previous layers.
//:
//:   c) Even so you'll periodically need to try adjusting each transform
//:   relative to those in previous layers to find a better arrangement.

:(before "End recipe Fields")
int transformed_until;
:(before "End recipe Constructor")
transformed_until = -1;

:(before "End Types")
typedef void (*transform_fn)(const recipe_ordinal);

:(before "End Globals")
vector<transform_fn> Transform;

:(before "End One-time Setup")
initialize_transforms();
:(code)
void initialize_transforms() {
  // Begin Transforms
    // Begin Instruction Inserting/Deleting Transforms
    // End Instruction Inserting/Deleting Transforms

    // Begin Instruction Modifying Transforms
    // End Instruction Modifying Transforms
  // End Transforms

  // Begin Checks
  // End Checks
}

void transform_all() {
  trace(9990, "transform") << "=== transform_all()" << end();
  // Begin transform_all
  for (int t = 0;  t < SIZE(Transform);  ++t) {
    for (map<recipe_ordinal, recipe>::iterator p = Recipe.begin();  p != Recipe.end();  ++p) {
      recipe& r = p->second;
      if (r.transformed_until != t-1) continue;
      // End Transform Checks
      (*Transform.at(t))(/*recipe_ordinal*/p->first);
      r.transformed_until = t;
    }
  }
  parse_int_reagents();  // do this after all other transforms have run
  // End transform_all
}

//: Even though a run will involve many calls to transform_all() for tests,
//: our logical model is to load all code, then transform all code, then run.
//: If you load new code that should cause already-transformed recipes to
//: change, that's not supported. To help detect such situations and raise
//: helpful errors we track a count of the number of calls made to
//: transform_all().
:(before "End Globals")
int Num_calls_to_transform_all = 0;
:(after "void transform_all()")
  ++Num_calls_to_transform_all;

:(code)
void parse_int_reagents() {
  trace(9991, "transform") << "--- parsing any uninitialized reagents as integers" << end();
  for (map<recipe_ordinal, recipe>::iterator p = Recipe.begin();  p != Recipe.end();  ++p) {
    recipe& r = p->second;
    if (r.steps.empty()) continue;
    for (int index = 0;  index < SIZE(r.steps);  ++index) {
      instruction& inst = r.steps.at(index);
      for (int i = 0;  i < SIZE(inst.ingredients);  ++i) {
        populate_value(inst.ingredients.at(i));
      }
      for (int i = 0;  i < SIZE(inst.products);  ++i) {
        populate_value(inst.products.at(i));
      }
    }
  }
}

void populate_value(reagent& r) {
  if (r.initialized) return;
  // End Reagent-parsing Exceptions
  if (!is_integer(r.name)) return;
  r.set_value(to_integer(r.name));
}

// helper for tests -- temporarily suppress run
void transform(string form) {
  load(form);
  transform_all();
}
>, <span class="Constant">10/height</span> <span class="Comment"># basic recipe</span> <span class="Constant">1</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ </span> <span class="Constant">recipe foo [</span> <span class="Constant"> reply 4</span> <span class="Constant">]</span>] <span class="Comment"># run it</span> <span class="Constant">2</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[foo]</span> assume-console [ press F4 ] <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . reply 4 ┊0 x.</span> <span class="Constant"> .] ┊foo .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] <span class="Comment"># click somewhere on the sandbox</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">30</span> ] run [ event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data ] <span class="Comment"># it pops back into editor</span> screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊foo .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . reply 4 ┊ .</span> <span class="Constant"> .] ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> . ┊ .</span> ] <span class="Comment"># cursor should be in the right place</span> assume-console [ type <span class="Constant">[0]</span> ] run [ event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data ] screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊0foo .</span> <span class="Constant"> .recipe foo [ ┊━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . reply 4 ┊ .</span> <span class="Constant"> .] ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muRecipe">after</span> <span class="Constant">&lt;global-touch&gt;</span> [ <span class="Comment"># below sandbox editor? pop appropriate sandbox contents back into sandbox editor</span> <span class="Delimiter">{</span> sandbox-left-margin:number<span class="Special"> &lt;- </span>get *current-sandbox, <span class="Constant">left:offset</span> click-column:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">column:offset</span> on-sandbox-side?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-column, sandbox-left-margin <span class="muControl">break-unless</span> on-sandbox-side? first-sandbox:address:shared:sandbox-data<span class="Special"> &lt;- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="muControl">break-unless</span> first-sandbox first-sandbox-begins:number<span class="Special"> &lt;- </span>get *first-sandbox, <span class="Constant">starting-row-on-screen:offset</span> click-row:number<span class="Special"> &lt;- </span>get *t, <span class="Constant">row:offset</span> below-sandbox-editor?:boolean<span class="Special"> &lt;- </span>greater-or-equal click-row, first-sandbox-begins <span class="muControl">break-unless</span> below-sandbox-editor? empty-sandbox-editor?:boolean<span class="Special"> &lt;- </span>empty-editor? current-sandbox <span class="muControl">break-unless</span> empty-sandbox-editor? <span class="Comment"># don't clobber existing contents</span> <span class="Comment"># identify the sandbox to edit and remove it from the sandbox list</span> sandbox:address:shared:sandbox-data<span class="Special"> &lt;- </span>extract-sandbox env, click-row <span class="muControl">break-unless</span> sandbox text:address:shared:array:character<span class="Special"> &lt;- </span>get *sandbox, <span class="Constant">data:offset</span> current-sandbox<span class="Special"> &lt;- </span>insert-text current-sandbox, text render-from:address:number<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">render-from:offset</span> *render-from<span class="Special"> &lt;- </span>copy <span class="Constant">-1</span> hide-screen screen screen<span class="Special"> &lt;- </span>render-sandbox-side screen, env screen<span class="Special"> &lt;- </span>update-cursor screen, recipes, current-sandbox, *sandbox-in-focus?, env show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> ] <span class="muRecipe">def</span> empty-editor? editor:address:shared:editor-data<span class="muRecipe"> -&gt; </span>result:boolean [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> head:address:shared:duplex-list:character<span class="Special"> &lt;- </span>get *editor, <span class="Constant">data:offset</span> first:address:shared:duplex-list:character<span class="Special"> &lt;- </span>next head result<span class="Special"> &lt;- </span>not first ] <span class="muRecipe">def</span> extract-sandbox env:address:shared:programming-environment-data, click-row:number<span class="muRecipe"> -&gt; </span>result:address:shared:sandbox-data, env:address:shared:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> sandbox:address:address:shared:sandbox-data<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox:offset</span> start:number<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">starting-row-on-screen:offset</span> in-editor?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, start <span class="muControl">return-if</span> in-editor?, <span class="Constant">0</span> <span class="Delimiter">{</span> next-sandbox:address:shared:sandbox-data<span class="Special"> &lt;- </span>get **sandbox, <span class="Constant">next-sandbox:offset</span> <span class="muControl">break-unless</span> next-sandbox <span class="Comment"># if click-row &lt; sandbox.next-sandbox.starting-row-on-screen, break</span> next-start:number<span class="Special"> &lt;- </span>get *next-sandbox, <span class="Constant">starting-row-on-screen:offset</span> found?:boolean<span class="Special"> &lt;- </span>lesser-than click-row, next-start <span class="muControl">break-if</span> found? sandbox<span class="Special"> &lt;- </span>get-address **sandbox, <span class="Constant">next-sandbox:offset</span> <span class="muControl">loop</span> <span class="Delimiter">}</span> <span class="Comment"># snip sandbox out of its list</span> result<span class="Special"> &lt;- </span>copy *sandbox *sandbox<span class="Special"> &lt;- </span>copy next-sandbox <span class="Comment"># update sandbox count</span> sandbox-count:address:number<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">number-of-sandboxes:offset</span> *sandbox-count<span class="Special"> &lt;- </span>subtract *sandbox-count, <span class="Constant">1</span> <span class="Comment"># position cursor in sandbox editor</span> sandbox-in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address *env, <span class="Constant">sandbox-in-focus?:offset</span> *sandbox-in-focus?<span class="Special"> &lt;- </span>copy <span class="Constant">1/true</span> ] <span class="muScenario">scenario</span> sandbox-with-print-can-be-edited [ trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">100/width</span>, <span class="Constant">20/height</span> <span class="Comment"># left editor is empty</span> <span class="Constant">1</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Comment"># right editor contains an instruction</span> <span class="Constant">2</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[print-integer screen, 4]</span> <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character <span class="Comment"># run the sandbox</span> assume-console [ press F4 ] event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊0 x.</span> <span class="Constant"> . ┊print-integer screen, 4 .</span> <span class="Constant"> . ┊screen: .</span> <span class="Constant"> . ┊ .4 . .</span> <span class="Constant"> . ┊ . . .</span> <span class="Constant"> . ┊ . . .</span> <span class="Constant"> . ┊ . . .</span> <span class="Constant"> . ┊ . . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] <span class="Comment"># edit the sandbox</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">70</span> ] run [ event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data ] screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊print-integer screen, 4 .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> editing-sandbox-after-scrolling-resets-scroll [ trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">30/width</span>, <span class="Constant">10/height</span> <span class="Comment"># initialize environment</span> <span class="Constant">1</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n type <span class="Constant">[add 2, 2]</span> press F4 type <span class="Constant">[add 1, 1]</span> press F4 press down-arrow press down-arrow ] event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊1 x.</span> <span class="Constant"> . ┊add 2, 2 .</span> <span class="Constant"> . ┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] <span class="Comment"># edit the second sandbox</span> assume-console [ left-click <span class="Constant">2</span>, <span class="Constant">20</span> ] run [ event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data ] <span class="Comment"># second sandbox shows in editor; scroll resets to display first sandbox</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ┊add 2, 2 .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊0 x.</span> <span class="Constant"> . ┊add 1, 1 .</span> <span class="Constant"> . ┊2 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] ] <span class="muScenario">scenario</span> editing-sandbox-updates-sandbox-count [ trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">30/width</span>, <span class="Constant">10/height</span> <span class="Comment"># initialize environment</span> <span class="Constant">1</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:shared:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:shared:programming-environment-data<span class="Special"> &lt;- </span>new-programming-environment screen:address:shared:screen, <span class="Constant">1</span>:address:shared:array:character, <span class="Constant">2</span>:address:shared:array:character render-all screen, <span class="Constant">3</span>:address:shared:programming-environment-data <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n type <span class="Constant">[add 2, 2]</span> press F4 type <span class="Constant">[add 1, 1]</span> press F4 ] event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊0 x.</span> <span class="Constant"> . ┊add 1, 1 .</span> <span class="Constant"> . ┊2 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊1 x.</span> ] <span class="Comment"># edit the second sandbox, then resave</span> assume-console [ left-click <span class="Constant">3</span>, <span class="Constant">20</span> press F4 ] run [ event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data ] <span class="Comment"># no change in contents</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ┊ .</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊0 x.</span> <span class="Constant"> . ┊add 1, 1 .</span> <span class="Constant"> . ┊2 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊1 x.</span> ] <span class="Comment"># now try to scroll past end</span> assume-console [ press down-arrow press down-arrow press down-arrow ] run [ event-loop screen:address:shared:screen, console:address:shared:console, <span class="Constant">3</span>:address:shared:programming-environment-data ] <span class="Comment"># screen should show just final sandbox</span> screen-should-contain [ <span class="Constant"> . .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊1 x.</span> <span class="Constant"> . ┊add 2, 2 .</span> <span class="Constant"> . ┊4 .</span> <span class="Constant"> . ┊━━━━━━━━━━━━━━.</span> <span class="Constant"> . ┊ .</span> ] ] </pre> </body> </html> <!-- vim: set foldmethod=manual : -->