about summary refs log tree commit diff stats
path: root/html/012transform.cc.html
blob: c7e405eb8fd695236f9e410cffde2d5294f9d01d (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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 012transform.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.Constant { color: #00a0a0; }
.Comment { color: #9090ff; }
.Delimiter { color: #800080; }
.Identifier { color: #c0a020; }
.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Phase 2: Filter loaded recipes through an extensible list of 'transforms'.</span>
<span class="Comment">//:</span>
<span class="Comment">//:   The process of running mu code:</span>
<span class="Comment">//:     load -&gt; transform -&gt; run</span>
<span class="Comment">//:</span>
<span class="Comment">//: The hope is that this framework of transform tools will provide a</span>
<span class="Comment">//: deconstructed alternative to conventional compilers.</span>
<span class="Comment">//:</span>
<span class="Comment">//: We're going to have many transforms in mu, and getting their order right</span>
<span class="Comment">//: (not the same as ordering of layers) is a well-known problem. Some tips:</span>
<span class="Comment">//:   a) Design each layer to rely on as few previous layers as possible.</span>
<span class="Comment">//:</span>
<span class="Comment">//:   b) When positioning transforms, try to find the tightest constraint in</span>
<span class="Comment">//:   each transform relative to previous layers.</span>
<span class="Comment">//:</span>
<span class="Comment">//:   c) Even so you'll periodically need to try adjusting each transform</span>
<span class="Comment">//:   relative to those in previous layers to find a better arrangement.</span>

<span class="Delimiter">:(before &quot;End recipe Fields&quot;)</span>
<span class="Normal">int</span> transformed_until<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End recipe Constructor&quot;)</span>
transformed_until = -<span class="Constant">1</span><span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End Types&quot;)</span>
<span class="Normal">typedef</span> <span class="Normal">void</span> <span class="Delimiter">(</span>*transform_fn<span class="Delimiter">)(</span><span class="Normal">const</span> recipe_ordinal<span class="Delimiter">);</span>

<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
vector&lt;transform_fn&gt; Transform<span class="Delimiter">;</span>

<span class="Delimiter">:(before &quot;End One-time Setup&quot;)</span>
initialize_transforms<span class="Delimiter">();</span>
<span class="Delimiter">:(code)</span>
<span class="Normal">void</span> initialize_transforms<span class="Delimiter">()</span> <span class="Delimiter">{</span>
  <span class="Comment">// Begin Transforms</span>
    <span class="Comment">// Begin Instruction Inserting/Deleting Transforms</span>
    <span class="Comment">// End Instruction Inserting/Deleting Transforms</span>

    <span class="Comment">// Begin Instruction Modifying Transforms</span>
    <span class="Comment">// End Instruction Modifying Transforms</span>
  <span class="Comment">// End Transforms</span>

  <span class="Comment">// Begin Checks</span>
  <span class="Comment">// End Checks</span>
<span class="Delimiter">}</span>

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

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

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

<span class="Normal">void</span> populate_value<span class="Delimiter">(</span>reagent&amp; r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  <span class="Comment">// End Reagent-parsing Exceptions</span>
  <span class="Normal">if</span> <span class="Delimiter">(</span>!is_integer<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
  r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>to_integer<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">));</span>
<span class="Delimiter">}</span>

<span class="Comment">// helper for tests -- temporarily suppress run</span>
<span class="Normal">void</span> transform<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span>
  load<span class="Delimiter">(</span>form<span class="Delimiter">);</span>
  transform_all<span class="Delimiter">();</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->