blob: 20c0af47f563e39fb2674bd928682fb1c2c98061 (
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
137
138
139
140
141
142
143
144
145
146
|
<!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>~/Desktop/s/mu/034exclusive_container.cc.html</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: #000000; }
body { font-family: monospace; color: #d0d0d0; background-color: #000000; }
* { font-size: 1em; }
.Identifier { color: #008080; }
.SalientComment { color: #00ffff; }
.Constant { color: #008080; }
.Comment { color: #8080ff; }
.Delimiter { color: #c000c0; }
.Special { color: #ff6060; }
.CommentedCode { color: #6c6c6c; }
.traceContains { color: #008000; }
-->
</style>
<script type='text/javascript'>
<!--
-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Exclusive containers contain exactly one of a fixed number of 'variants'</span>
<span class="Comment">//: of different types.</span>
<span class="Comment">//:</span>
<span class="Comment">//: They also implicitly contain a tag describing precisely which variant is</span>
<span class="Comment">//: currently stored in them.</span>
<span class="Delimiter">:(before "End Mu Types Initialization")</span>
<span class="Comment">//: We'll use this container as a running example, with two integer elements.</span>
<span class="Delimiter">{</span>
type_number tmp = Type_number[<span class="Constant">"integer-or-point"</span>] = Next_type_number++<span class="Delimiter">;</span>
Type[tmp]<span class="Delimiter">.</span>size = <span class="Constant">2</span><span class="Delimiter">;</span>
Type[tmp]<span class="Delimiter">.</span>kind = exclusive_container<span class="Delimiter">;</span>
Type[tmp]<span class="Delimiter">.</span>name = <span class="Constant">"integer-or-point"</span><span class="Delimiter">;</span>
<span class="CommentedCode">//? cout << tmp << ": " << Type[tmp].elements.size() << '\n'; //? 1</span>
vector<type_number> t1<span class="Delimiter">;</span>
t1<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>integer<span class="Delimiter">);</span>
Type[tmp]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>t1<span class="Delimiter">);</span>
<span class="CommentedCode">//? cout << Type[tmp].elements.size() << '\n'; //? 1</span>
vector<type_number> t2<span class="Delimiter">;</span>
t2<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>point<span class="Delimiter">);</span>
Type[tmp]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>t2<span class="Delimiter">);</span>
<span class="CommentedCode">//? cout << Type[tmp].elements.size() << '\n'; //? 1</span>
<span class="CommentedCode">//? cout << "point: " << point << '\n'; //? 1</span>
Type[tmp]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"i"</span><span class="Delimiter">);</span>
Type[tmp]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"p"</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(scenario copy_exclusive_container)</span>
<span class="Comment"># Copying exclusive containers copies all their contents and an extra location for the tag.</span>
recipe main [
<span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal <span class="Comment"># 'point' variant</span>
<span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal
<span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal
<span class="Constant">4</span>:integer-or-point<span class="Special"> <- </span>copy <span class="Constant">1</span>:integer-or-point
]
<span class="traceContains">+mem: storing 1 in location 4</span>
<span class="traceContains">+mem: storing 34 in location 5</span>
<span class="traceContains">+mem: storing 35 in location 6</span>
<span class="Delimiter">:(before "End size_of(types) Cases")</span>
if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == exclusive_container<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Comment">// size of an exclusive container is the size of its largest variant</span>
<span class="Comment">// (So like containers, it can't contain arrays.)</span>
<span class="CommentedCode">//? cout << "--- " << types[0] << ' ' << t.size << '\n'; //? 1</span>
<span class="CommentedCode">//? cout << "point: " << Type_number["point"] << " " << Type[Type_number["point"]].name << " " << Type[Type_number["point"]].size << '\n'; //? 1</span>
<span class="CommentedCode">//? cout << t.name << ' ' << t.size << ' ' << t.elements.size() << '\n'; //? 1</span>
size_t result = <span class="Constant">0</span><span class="Delimiter">;</span>
for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < t<span class="Delimiter">.</span>size<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
size_t tmp = size_of<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements[i]<span class="Delimiter">);</span>
<span class="CommentedCode">//? cout << i << ": " << t.elements[i][0] << ' ' << tmp << ' ' << result << '\n'; //? 1</span>
if <span class="Delimiter">(</span>tmp > result<span class="Delimiter">)</span> result = tmp<span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Comment">// ...+1 for its tag.</span>
<span class="Identifier">return</span> result+<span class="Constant">1</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="SalientComment">//:: To access variants of an exclusive container, use 'maybe-convert'.</span>
<span class="Comment">//: It always returns an address (so that you can modify it) or null (to</span>
<span class="Comment">//: signal that the conversion failed (because the container contains a</span>
<span class="Comment">//: different variant).</span>
<span class="Comment">//: 'maybe-convert' requires a literal in ingredient 1. We'll use a synonym</span>
<span class="Comment">//: called 'variant'.</span>
<span class="Delimiter">:(before "End Mu Types Initialization")</span>
Type_number[<span class="Constant">"variant"</span>] = <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Delimiter">:(scenario maybe_convert)</span>
recipe main [
<span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal
<span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal
<span class="Constant">14</span>:integer<span class="Special"> <- </span>copy <span class="Constant">36</span>:literal
<span class="Constant">20</span>:address:point<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:integer-or-point<span class="Delimiter">,</span> <span class="Constant">1</span>:variant
]
<span class="traceContains">+mem: storing 13 in location 20</span>
<span class="Delimiter">:(scenario maybe_convert_fail)</span>
recipe main [
<span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal
<span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal
<span class="Constant">14</span>:integer<span class="Special"> <- </span>copy <span class="Constant">36</span>:literal
<span class="Constant">20</span>:address:point<span class="Special"> <- </span>maybe-convert <span class="Constant">12</span>:integer-or-point<span class="Delimiter">,</span> <span class="Constant">0</span>:variant
]
<span class="traceContains">+mem: storing 0 in location 20</span>
<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span>
MAYBE_CONVERT<span class="Delimiter">,</span>
<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span>
Recipe_number[<span class="Constant">"maybe-convert"</span>] = MAYBE_CONVERT<span class="Delimiter">;</span>
<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span>
case MAYBE_CONVERT: <span class="Delimiter">{</span>
trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"ingredient 0 is "</span> << current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
reagent base = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span>
index_t base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
type_number base_type = base<span class="Delimiter">.</span>types[<span class="Constant">0</span>]<span class="Delimiter">;</span>
assert<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>kind == exclusive_container<span class="Delimiter">);</span>
trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"ingredient 1 is "</span> << current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
assert<span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">));</span>
index_t tag = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span>
vector<long long int> result<span class="Delimiter">;</span>
if <span class="Delimiter">(</span>tag == static_cast<index_t><span class="Delimiter">(</span>Memory[base_address]<span class="Delimiter">))</span> <span class="Delimiter">{</span>
result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>base_address+<span class="Constant">1</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>
else <span class="Delimiter">{</span>
result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
<span class="Delimiter">}</span>
write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">0</span>]<span class="Delimiter">,</span> result<span class="Delimiter">);</span>
<span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|