https://github.com/akkartik/mu/blob/master/032array.cc
1
2
3
4
5
6
7
8
9 :(scenario create_array)
10 def main [
11
12 1:array:num:3 <- create-array
13 ]
14 +run: creating array from 4 locations
15
16 :(before "End Primitive Recipe Declarations")
17 CREATE_ARRAY,
18 :(before "End Primitive Recipe Numbers")
19 put(Recipe_ordinal, "create-array", CREATE_ARRAY);
20 :(before "End Primitive Recipe Checks")
21 case CREATE_ARRAY: {
22 if (inst.products.empty()) {
23 raise << maybe(get(Recipe, r).name) << "'create-array' needs one product and no ingredients but got '" << to_original_string(inst) << '\n' << end();
24 break;
25 }
26 reagent product = inst.products.at(0);
27
28 if (!is_mu_array(product)) {
29 raise << maybe(get(Recipe, r).name) << "'create-array' cannot create non-array '" << product.original_string << "'\n" << end();
30 break;
31 }
32 if (!product.type->right) {
33 raise << maybe(get(Recipe, r).name) << "create array of what? '" << to_original_string(inst) << "'\n" << end();
34 break;
35 }
36
37 type_tree* array_length_from_type = product.type->right->right;
38 if (!array_length_from_type) {
39 raise << maybe(get(Recipe, r).name) << "create array of what size? '" << to_original_string(inst) << "'\n" << end();
40 break;
41 }
42 if (!product.type->right->right->atom)
43 array_length_from_type = array_length_from_type->left;
44 if (!is_integer(array_length_from_type->name)) {
45 raise << maybe(get(Recipe, r).name) << "'create-array' product should specify size of array after its element type, but got '" << product.type->right->right->name << "'\n" << end();
46 break;
47 }
48 break;
49 }
50 :(before "End Primitive Recipe Implementations")
51 case CREATE_ARRAY: {
52 reagent product = current_instruction().products.at(0);
53
54 int base_address = product.value;
55 type_tree* array_length_from_type = product.type->right->right;
56 if (!product.type->right->right->atom)
57 array_length_from_type = array_length_from_type->left;
58 int array_length = to_integer(array_length_from_type->name);
59
60 trace("mem") << "storing " << array_length << " in location " << base_address << end();
61 put(Memory, base_address, array_length);
62 int size = size_of(product);
63 trace(9998, "run") << "creating array from " << size << " locations" << end();
64
65 for (int i = 1; i <= size_of(product); ++i)
66 put(Memory, base_address+i, 0);
67
68 write_products = false;
69 break;
70 }
71
72 :(scenario copy_array)
73
74
75
76
77
78
79 def main [
80 1:array:num:3 <- create-array
81 2:num <- copy 14
82 3:num <- copy 15
83 4:num <- copy 16
84 5:array:num <- copy 1:array:num:3
85 ]
86 +mem: storing 3 in location 5
87 +mem: storing 14 in location 6
88 +mem: storing 15 in location 7
89 +mem: storing 16 in location 8
90
91 :(scenario stash_array)
92 def main [
93 1:array:num:3 <- create-array
94 2:num <- copy 14
95 3:num <- copy 15
96 4:num <- copy 16
97 stash [foo:], 1:array:num:3
98 ]
99 +app: foo: 3 14 15 16
100
101 :(before "End types_coercible Special-cases")
102 if (is_mu_array(from) && is_mu_array(to))
103 return types_strictly_match(array_element(from.type), array_element(to.type));
104
105 :(before "End size_of(reagent r) Special-cases")
106 if (!r.type->atom && r.type->left->atom && r.type->left->value == Array_type_ordinal) {
107 if (!r.type->right) {
108 raise << maybe(current_recipe_name()) << "'" << r.original_string << "' is an array of what?\n" << end();
109 return 1;
110 }
111 return 1 + array_length(r)*size_of(array_element(r.type));
112 }
113
114 :(before "End size_of(type) Non-atom Special-cases")
115 if (type->left->value == Array_type_ordinal) return static_array_length(type);
116 :(code)
117 int static_array_length(const type_tree* type) {
118 if (!type->atom && type->right && !type->right->atom && type->right->right && !type->right->right->atom && !type->right->right->right
119 && type->right->right->left && type->right->right->left->atom && is_integer(type->right->right->left->name)) {
120
121 return to_integer(type->right->right->left->name);
122 }
123 cerr << to_string(type) << '\n';
124 assert(false);
125 }
126
127
128
129 :(before "End size_mismatch(x) Special-cases")
130 if (x.type && !x.type->atom && x.type->left->value == Array_type_ordinal) return false;
131
132
133
134
135
136 :(scenario container_permits_static_array_element)
137 container foo [
138 x:array:num:3
139 ]
140 $error: 0
141
142 :(before "End insert_container Special-cases")
143 else if (is_integer(type->name)) {
144 type->value = 0;
145 }
146
147 :(scenario container_disallows_dynamic_array_element)
148 % Hide_errors = true;
149 container foo [
150 x:array:num
151 ]
152 +error: container 'foo' cannot determine size of element 'x'
153
154 :(before "End Load Container Element Definition")
155 {
156 const type_tree* type = info.elements.back().type;
157 if (type && type->atom && type->name == "array") {
158 raise << "container '" << name << "' doesn't specify type of array elements for '" << info.elements.back().name << "'\n" << end();
159 continue;
160 }
161 if (type && !type->atom && type->left->atom && type->left->name == "array") {
162 if (!type->right) {
163 raise << "container '" << name << "' doesn't specify type of array elements for '" << info.elements.back().name << "'\n" << end();
164 continue;
165 }
166 if (!type->right->right || !is_integer(type->right->right->left->name)) {
167 raise << "container '" << name << "' cannot determine size of element '" << info.elements.back().name << "'\n" << end();
168 continue;
169 }
170 }
171 }
172
173
174
175 :(before "End size_mismatch(x) Special-cases")
176 if (current_call().running_step_index < SIZE(get(Recipe, current_call().running_recipe).steps)
177 && current_instruction().operation == MERGE) {
178 return false;
179 }
180
181 :(scenario merge_static_array_into_container)
182 container foo [
183 x:num
184 y:array:num:3
185 ]
186 def main [
187 1:array:num:3 <- create-array
188 10:foo <- merge 34, 1:array:num:3
189 ]
190
191
192 :(scenario code_inside_container)
193 % Hide_errors = true;
194 container card [
195 rank:num <- next-ingredient
196 ]
197 def foo [
198 1:card <- merge 3
199 2:num <- get 1:card rank:offset
200 ]
201
202
203
204
205 :(scenario index)
206 def main [
207 1:array:num:3 <- create-array
208 2:num <- copy 14
209 3:num <- copy 15
210 4:num <- copy 16
211 10:num <- index 1:array:num:3, 0/index
212 ]
213 +mem: storing 14 in location 10
214
215 :(scenario index_compound_element)
216 def main [
217 {1: (array (address number) 3)} <- create-array
218
219 3:num <- copy 14
220
221 5:num <- copy 15
222
223 7:num <- copy 16
224 10:address:num <- index {1: (array (address number) 3)}, 0
225 ]
226
227 +mem: storing 14 in location 11
228
229 :(scenario index_direct_offset)
230 def main [
231 1:array:num:3 <- create-array
232 2:num <- copy 14
233 3:num <- copy 15
234 4:num <- copy 16
235 10:num <- copy 0
236 20:num <- index 1:array:num, 10:num
237 ]
238 +mem: storing 14 in location 20
239
240 :(before "End Primitive Recipe Declarations")
241 INDEX,
242 :(before "End Primitive Recipe Numbers")
243 put(Recipe_ordinal, "index", INDEX);
244 :(before "End Primitive Recipe Checks")
245 case INDEX: {
246 if (SIZE(inst.ingredients) != 2) {
247 raise << maybe(get(Recipe, r).name) << "'index' expects exactly 2 ingredients in '" << to_original_string(inst) << "'\n" << end();
248 break;
249 }
250 reagent base = inst.ingredients.at(0);
251
252 if (!is_mu_array(base)) {
253 raise << maybe(get(Recipe, r).name) << "'index' on a non-array '" << base.original_string << "'\n" << end();
254 break;
255 }
256 reagent index = inst.ingredients.at(1);
257
258 if (!is_mu_number(index)) {
259 raise << maybe(get(Recipe, r).name) << "second ingredient of 'index' should be a number, but got '" << index.original_string << "'\n" << end();
260 break;
261 }
262 if (instpre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */<!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 - 035labels.cc</title>
<meta name="Generator" content="Vim/8.1">
<meta name="plugin-version" content="vim8.1_v1">
<meta name="syntax" content="cpp">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.LineNr { }
.Constant { color: #008787; }
.Comment { color: #005faf; }
.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; }
.Special { color: #d70000; }
.Identifier { color: #af5f00; }
.Delimiter { color: #c000c0; }
.cSpecial { color: #008000; }
-->
</style>
<script type='text/javascript'>
<!--
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
var lineNum;
lineNum = window.location.hash;
lineNum = lineNum.substr(1); /* strip off '#' */
if (lineNum.indexOf('L') == -1) {
lineNum = 'L'+lineNum;
}
var lineElem = document.getElementById(lineNum);
/* Always jump to new location even if the line was hidden inside a fold, or
* we corrected the raw number to a line ID.
*/
if (lineElem) {
lineElem.scrollIntoView(true);
}
return true;
}
if ('onhashchange' in window) {
window.onhashchange = JumpToLine;
}
-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/master/035labels.cc'>https://github.com/akkartik/mu/blob/master/035labels.cc</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="Comment">//: Labels are defined by ending names with a ':'. This layer will compute</span>
<span id="L2" class="LineNr"> 2 </span><span class="Comment">//: displacements for labels, and compute the offset for instructions using them.</span>
<span id="L3" class="LineNr"> 3 </span><span class="Comment">//:</span>
<span id="L4" class="LineNr"> 4 </span><span class="Comment">//: We won't check this, but our convention will be that jump targets will</span>
<span id="L5" class="LineNr"> 5 </span><span class="Comment">//: start with a '$', while functions will not. Function names will never be</span>
<span id="L6" class="LineNr"> 6 </span><span class="Comment">//: jumped to, and jump targets will never be called.</span>
<span id="L7" class="LineNr"> 7 </span>
<span id="L8" class="LineNr"> 8 </span><span class="Comment">//: We're introducing non-number names for the first time, so it's worth</span>
<span id="L9" class="LineNr"> 9 </span><span class="Comment">//: laying down some ground rules all transforms will follow, so things don't</span>
<span id="L10" class="LineNr"> 10 </span><span class="Comment">//: get too confusing:</span>
<span id="L11" class="LineNr"> 11 </span><span class="Comment">//: - if it starts with a digit, it's treated as a number. If it can't be</span>
<span id="L12" class="LineNr"> 12 </span><span class="Comment">//: parsed as hex it will raise an error.</span>
<span id="L13" class="LineNr"> 13 </span><span class="Comment">//: - if it starts with '-' it's treated as a number.</span>
<span id="L14" class="LineNr"> 14 </span><span class="Comment">//: - if it starts with '0x' it's treated as a number.</span>
<span id="L15" class="LineNr"> 15 </span><span class="Comment">//: - if it's two characters long, it can't be a name. Either it's a hex</span>
<span id="L16" class="LineNr"> 16 </span><span class="Comment">//: byte, or it raises an error.</span>
<span id="L17" class="LineNr"> 17 </span><span class="Comment">//: That's it. Names can start with any non-digit that isn't a dash. They can</span>
<span id="L18" class="LineNr"> 18 </span><span class="Comment">//: be a single character long. 'a' is not a hex number, it's a variable.</span>
<span id="L19" class="LineNr"> 19 </span><span class="Comment">//: Later layers may add more conventions partitioning the space of names. But</span>
<span id="L20" class="LineNr"> 20 </span><span class="Comment">//: the above rules will remain inviolate.</span>
<span id="L21" class="LineNr"> 21 </span>
<span id="L22" class="LineNr"> 22 </span><span class="Comment">//: One special label is 'Entry', the address to start running the program at.</span>
<span id="L23" class="LineNr"> 23 </span><span class="Comment">//: It can be non-unique; the last declaration overrides earlier ones.</span>
<span id="L24" class="LineNr"> 24 </span><span class="Comment">//: It must exist in a program. Otherwise we don't know where to start running</span>
<span id="L25" class="LineNr"> 25 </span><span class="Comment">//: programs.</span>
<span id="L26" class="LineNr"> 26 </span>
<span id="L27" class="LineNr"> 27 </span><span class="Normal">void</span> <a href='035labels.cc.html#L27'>test_Entry_label</a><span class="Delimiter">()</span> <span class="Delimiter">{</span>
<span id="L28" class="LineNr"> 28 </span> <a href='011run.cc.html#L83'>run</a><span class="Delimiter">(</span>
<span id="L29" class="LineNr"> 29 </span> <span class="Constant">"== code 0x1\n"</span>
<span id="L30" class="LineNr"> 30 </span> <span class="Constant">"05 0x0d0c0b0a/imm32\n"</span>
<span id="L31" class="LineNr"> 31 </span> <span class="Constant">"Entry:\n"</span>
<span id="L32" class="LineNr"> 32 </span> <span class="Constant">"05 0x0d0c0b0a/imm32\n"</span>
<span id="L33" class="LineNr"> 33 </span> <span class="Delimiter">);</span>
<span id="L34" class="LineNr"> 34 </span> <a href='003trace.cc.html#L290'>CHECK_TRACE_CONTENTS</a><span class="Delimiter">(</span>
<span id="L35" class="LineNr"> 35 </span> <span class="Constant">"run: 0x00000006 opcode: 05\n"</span>
<span id="L36" class="LineNr"> 36 </span> <span class="Delimiter">);</span>
<span id="L37" class="LineNr"> 37 </span> <a href='003trace.cc.html#L292'>CHECK_TRACE_DOESNT_CONTAIN</a><span class="Delimiter">(</span><span class="Constant">"run: 0x00000001 opcode: 05"</span><span class="Delimiter">);</span>
<span id="L38" class="LineNr"> 38 </span><span class="Delimiter">}</span>
<span id="L39" class="LineNr"> 39 </span>
<span id="L40" class="LineNr"> 40 </span><span class="Delimiter">:(before "End looks_like_hex_int(s) Detectors")</span>
<span id="L41" class="LineNr"> 41 </span><span class="Normal">if</span> <span class="Delimiter">(</span><a href='001help.cc.html#L164'>SIZE</a><span class="Delimiter">(</span>s<span class="Delimiter">)</span> == <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
<span id="L42" class="LineNr"> 42 </span>
<span id="L43" class="LineNr"> 43 </span><span class="Delimiter">:(code)</span>
<span id="L44" class="LineNr"> 44 </span><span class="Normal">void</span> <a href='035labels.cc.html#L44'>test_pack_immediate_ignores_single_byte_nondigit_operand</a><span class="Delimiter">()</span> <span class="Delimiter">{</span>
<span id="L45" class="LineNr"> 45 </span> <span class="Special">Hide_errors</span> = <span class="Constant">true</span><span class="Delimiter">;</span>
<span id="L46" class="LineNr"> 46 </span> transform<span class="Delimiter">(</span>
<span id="L47" class="LineNr"> 47 </span> <span class="Constant">"== code 0x1\n"</span>
<span id="L48" class="LineNr"> 48 </span> <span class="Constant">"b9/copy a/imm32\n"</span>
<span id="L49" class="LineNr"> 49 </span> <span class="Delimiter">);</span>
<span id="L50" class="LineNr"> 50 </span> <a href='003trace.cc.html#L290'>CHECK_TRACE_CONTENTS</a><span class="Delimiter">(</span>
<span id="L51" class="LineNr"> 51 </span> <span class="Constant">"transform: packing instruction 'b9/copy a/imm32'\n"</span>
<span id="L52" class="LineNr"> 52 </span> <span class="Comment">// no change (we're just not printing metadata to the trace)</span>
<span id="L53" class="LineNr"> 53 </span> <span class="Constant">"transform: instruction after packing: 'b9 a'\n"</span>
<