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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
<!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 - 032array.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v1">
<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: #d0d0d0; background-color: #080808; }
body { font-family: monospace; color: #d0d0d0; background-color: #080808; }
* { font-size: 1em; }
.traceContains { color: #008000; }
.cSpecial { color: #008000; }
.Constant { color: #008080; }
.SalientComment { color: #00ffff; }
.Comment { color: #8080ff; }
.Delimiter { color: #c000c0; }
.Special { color: #ff6060; }
.Identifier { color: #008080; }
.CommentedCode { color: #6c6c6c; }
-->
</style>
<script type='text/javascript'>
<!--
-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Arrays contain a variable number of elements of the same type. Their value</span>
<span class="Comment">//: starts with the length of the array.</span>
<span class="Comment">//:</span>
<span class="Comment">//: You can create arrays of containers, but containers can only contain</span>
<span class="Comment">//: elements of a fixed size, so you can't create containers containing arrays.</span>
<span class="Comment">//: Create containers containing addresses to arrays instead.</span>
<span class="Comment">//: Tests in this layer often explicitly setup memory before reading it as an</span>
<span class="Comment">//: array. Don't do this in general. I'm tagging exceptions with /raw to</span>
<span class="Comment">//: avoid warnings.</span>
<span class="Delimiter">:(scenario copy_array)</span>
<span class="Comment"># Arrays can be copied around with a single instruction just like numbers,</span>
<span class="Comment"># no matter how large they are.</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:array:number/<span class="Special">raw</span> <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 3 in location 5</span>
<span class="traceContains">+mem: storing 14 in location 6</span>
<span class="traceContains">+mem: storing 15 in location 7</span>
<span class="traceContains">+mem: storing 16 in location 8</span>
<span class="Delimiter">:(scenario copy_array_indirect)</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal
<span class="Constant">6</span>:array:number<span class="Special"> <- </span>copy <span class="Constant">5</span>:address:array:number/deref
]
<span class="traceContains">+mem: storing 3 in location 6</span>
<span class="traceContains">+mem: storing 14 in location 7</span>
<span class="traceContains">+mem: storing 15 in location 8</span>
<span class="traceContains">+mem: storing 16 in location 9</span>
<span class="Comment">//: disable the size mismatch check since the destination array need not be initialized</span>
<span class="Delimiter">:(replace "if (size_of(x) != SIZE(data))" following "void write_memory(reagent x, vector<double> data)")</span>
if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != Type_number[<span class="Constant">"array"</span>] && size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>data<span class="Delimiter">))</span>
<span class="Delimiter">:(after "long long int size_of(const reagent& r)")</span>
if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">);</span>
<span class="Comment">// skip the 'array' type to get at the element type</span>
<span class="Identifier">return</span> <span class="Constant">1</span> + Memory[r<span class="Delimiter">.</span>value]*size_of<span class="Delimiter">(</span>array_element<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">));</span>
<span class="Delimiter">}</span>
<span class="SalientComment">//:: To access elements of an array, use 'index'</span>
<span class="Delimiter">:(scenario index)</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:number<span class="Special"> <- </span>index <span class="Constant">1</span>:array:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">0</span>:literal <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 14 in location 5</span>
<span class="Delimiter">:(scenario index_direct_offset)</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal
<span class="Constant">6</span>:number<span class="Special"> <- </span>index <span class="Constant">1</span>:array:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">5</span>:number <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 14 in location 6</span>
<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span>
INDEX<span class="Delimiter">,</span>
<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span>
Recipe_number[<span class="Constant">"index"</span>] = INDEX<span class="Delimiter">;</span>
<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span>
case INDEX: <span class="Delimiter">{</span>
<span class="CommentedCode">//? if (Trace_stream) Trace_stream->dump_layer = "run"; //? 1</span>
reagent base = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
<span class="CommentedCode">//? trace(Primitive_recipe_depth, "run") << "ingredient 0 after canonize: " << base.to_string(); //? 1</span>
long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
assert<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">);</span>
reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span>
<span class="CommentedCode">//? trace(Primitive_recipe_depth, "run") << "ingredient 1 after canonize: " << offset.to_string(); //? 1</span>
vector<double> offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span>
vector<type_number> element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span>
<span class="CommentedCode">//? trace(Primitive_recipe_depth, "run") << "offset: " << offset_val.at(0); //? 1</span>
<span class="CommentedCode">//? trace(Primitive_recipe_depth, "run") << "size of elements: " << size_of(element_type); //? 1</span>
long long int src = base_address + <span class="Constant">1</span> + offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span>
trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src<span class="Delimiter">;</span>
trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"its type is "</span> << element_type<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
reagent tmp<span class="Delimiter">;</span>
tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span>
copy<span class="Delimiter">(</span>element_type<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> element_type<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>types<span class="Delimiter">,</span> tmp<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span>
products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">));</span>
<span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(code)</span>
vector<type_number> array_element<span class="Delimiter">(</span>const vector<type_number>& types<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Identifier">return</span> vector<type_number><span class="Delimiter">(</span>++types<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> types<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(scenario index_address)</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:number<span class="Special"> <- </span>index-address <span class="Constant">1</span>:array:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">0</span>:literal <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 2 in location 5</span>
<span class="SalientComment">//:: To write to elements of containers, you need their address.</span>
<span class="Delimiter">:(scenario index_indirect)</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal
<span class="Constant">6</span>:number<span class="Special"> <- </span>index <span class="Constant">5</span>:address:array:number/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:literal
]
<span class="traceContains">+mem: storing 15 in location 6</span>
<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span>
INDEX_ADDRESS<span class="Delimiter">,</span>
<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span>
Recipe_number[<span class="Constant">"index-address"</span>] = INDEX_ADDRESS<span class="Delimiter">;</span>
<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span>
case INDEX_ADDRESS: <span class="Delimiter">{</span>
reagent base = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
long long int base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
assert<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">);</span>
reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span>
vector<double> offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span>
vector<type_number> element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span>
long long int result = base_address + <span class="Constant">1</span> + offset_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span>
products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span>
<span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="SalientComment">//:: compute the length of an array</span>
<span class="Delimiter">:(scenario array_length)</span>
recipe main [
<span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># length</span>
<span class="Constant">2</span>:number<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal
<span class="Constant">3</span>:number<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal
<span class="Constant">4</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal
<span class="Constant">5</span>:number<span class="Special"> <- </span>length <span class="Constant">1</span>:array:number/<span class="Special">raw</span> <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 3 in location 5</span>
<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span>
LENGTH<span class="Delimiter">,</span>
<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span>
Recipe_number[<span class="Constant">"length"</span>] = LENGTH<span class="Delimiter">;</span>
<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span>
case LENGTH: <span class="Delimiter">{</span>
reagent x = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
raise << <span class="Constant">"tried to calculate length of non-array "</span> << x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
<span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>Memory[x<span class="Delimiter">.</span>value]<span class="Delimiter">);</span>
<span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|