about summary refs log tree commit diff stats
path: root/html/034exclusive_container.cc.html
blob: 5dc88c302538fbe3efcb8ed5117cd090c0fd19d8 (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<!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 - 034exclusive_container.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: #eeeeee; background-color: #080808; }
body { font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 1em; }
.traceContains { color: #008000; }
.Constant { color: #008080; }
.SalientComment { color: #00ffff; }
.Comment { color: #8080ff; }
.Delimiter { color: #c000c0; }
.Special { color: #ff6060; }
.CommentedCode { color: #6c6c6c; }
.Identifier { color: #804000; }
-->
</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 &quot;End Mu Types Initialization&quot;)</span>
<span class="Comment">//: We'll use this container as a running example, with two number elements.</span>
<span class="Delimiter">{</span>
type_number tmp = Type_number[<span class="Constant">&quot;number-or-point&quot;</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">&quot;number-or-point&quot;</span><span class="Delimiter">;</span>
<span class="CommentedCode">//? cout &lt;&lt; tmp &lt;&lt; &quot;: &quot; &lt;&lt; SIZE(Type[tmp].elements) &lt;&lt; '\n'; //? 1</span>
vector&lt;type_number&gt; t1<span class="Delimiter">;</span>
t1<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>number<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 &lt;&lt; SIZE(Type[tmp].elements) &lt;&lt; '\n'; //? 1</span>
vector&lt;type_number&gt; 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 &lt;&lt; SIZE(Type[tmp].elements) &lt;&lt; '\n'; //? 1</span>
<span class="CommentedCode">//? cout &lt;&lt; &quot;point: &quot; &lt;&lt; point &lt;&lt; '\n'; //? 1</span>
Type[tmp]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">&quot;i&quot;</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">&quot;p&quot;</span><span class="Delimiter">);</span>
<span class="Delimiter">}</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_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>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal  <span class="Comment"># 'point' variant</span>
  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">34</span>:literal
  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
  <span class="Constant">4</span>:number-or-point<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number-or-point/<span class="Special">raw</span>  <span class="Comment"># unsafe</span>
]
<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 &quot;End size_of(types) Cases&quot;)</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 &lt;&lt; &quot;--- &quot; &lt;&lt; types.at(0) &lt;&lt; ' ' &lt;&lt; t.size &lt;&lt; '\n'; //? 1</span>
<span class="CommentedCode">//?   cout &lt;&lt; &quot;point: &quot; &lt;&lt; Type_number[&quot;point&quot;] &lt;&lt; &quot; &quot; &lt;&lt; Type[Type_number[&quot;point&quot;]].name &lt;&lt; &quot; &quot; &lt;&lt; Type[Type_number[&quot;point&quot;]].size &lt;&lt; '\n'; //? 1</span>
<span class="CommentedCode">//?   cout &lt;&lt; t.name &lt;&lt; ' ' &lt;&lt; t.size &lt;&lt; ' ' &lt;&lt; SIZE(t.elements) &lt;&lt; '\n'; //? 1</span>
  long long int result = <span class="Constant">0</span><span class="Delimiter">;</span>
  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; t<span class="Delimiter">.</span>size<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
    long long int tmp = size_of<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span>
<span class="CommentedCode">//?     cout &lt;&lt; i &lt;&lt; &quot;: &quot; &lt;&lt; t.elements.at(i).at(0) &lt;&lt; ' ' &lt;&lt; tmp &lt;&lt; ' ' &lt;&lt; result &lt;&lt; '\n'; //? 1</span>
    if <span class="Delimiter">(</span>tmp &gt; 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 &quot;End Mu Types Initialization&quot;)</span>
Type_number[<span class="Constant">&quot;variant&quot;</span>] = <span class="Constant">0</span><span class="Delimiter">;</span>

<span class="Delimiter">:(scenario maybe_convert)</span>
recipe main [
  <span class="Constant">12</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
  <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>:literal
  <span class="Constant">20</span>:address:point<span class="Special"> &lt;- </span>maybe-convert <span class="Constant">12</span>:number-or-point/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:variant  <span class="Comment"># unsafe</span>
]
<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>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
  <span class="Constant">13</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">35</span>:literal
  <span class="Constant">14</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">36</span>:literal
  <span class="Constant">20</span>:address:point<span class="Special"> &lt;- </span>maybe-convert <span class="Constant">12</span>:number-or-point/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">0</span>:variant  <span class="Comment"># unsafe</span>
]
<span class="traceContains">+mem: storing 0 in location 20</span>

<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
MAYBE_CONVERT<span class="Delimiter">,</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
Recipe_number[<span class="Constant">&quot;maybe-convert&quot;</span>] = MAYBE_CONVERT<span class="Delimiter">;</span>
<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
case MAYBE_CONVERT: <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>
  type_number base_type = base<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><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>
  assert<span class="Delimiter">(</span>isa_literal<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>
  long long int tag = 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>value<span class="Delimiter">;</span>
  long long int result<span class="Delimiter">;</span>
  if <span class="Delimiter">(</span>tag == static_cast&lt;long long int&gt;<span class="Delimiter">(</span>Memory[base_address]<span class="Delimiter">))</span> <span class="Delimiter">{</span>
    result = base_address+<span class="Constant">1</span><span class="Delimiter">;</span>
  <span class="Delimiter">}</span>
  else <span class="Delimiter">{</span>
    result = <span class="Constant">0</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>result<span class="Delimiter">);</span>
  <span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>

<span class="SalientComment">//:: Allow exclusive containers to be defined in mu code.</span>

<span class="Delimiter">:(scenario exclusive_container)</span>
exclusive-container foo [
  x:number
  y:number
]
<span class="traceContains">+parse: reading exclusive-container foo</span>
<span class="traceContains">+parse:   element name: x</span>
<span class="traceContains">+parse:   type: 1</span>
<span class="traceContains">+parse:   element name: y</span>
<span class="traceContains">+parse:   type: 1</span>

<span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span>
else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;exclusive-container&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
  insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> exclusive_container<span class="Delimiter">,</span> in<span class="Delimiter">);</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->