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
|
<!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 - 034new_text.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; }
.traceContains { color: #008000; }
.Comment { color: #9090ff; }
.Delimiter { color: #800080; }
.Special { color: #c00000; }
.Identifier { color: #fcb165; }
.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; }
.CommentedCode { color: #6c6c6c; }
-->
</style>
<script type='text/javascript'>
<!--
-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment">//: Extend 'new' to handle a unicode string literal argument.</span>
<span class="Delimiter">:(scenario new_string)</span>
def main [
<span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc def]
<span class="Constant">2</span>:character<span class="Special"> <- </span>index *<span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">5</span>
]
<span class="Comment"># number code for 'e'</span>
<span class="traceContains">+mem: storing 101 in location 2</span>
<span class="Delimiter">:(scenario new_string_handles_unicode)</span>
def main [
<span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [a«c]
<span class="Constant">2</span>:number<span class="Special"> <- </span>length *<span class="Constant">1</span>:address:array:character
<span class="Constant">3</span>:character<span class="Special"> <- </span>index *<span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> <span class="Constant">1</span>
]
<span class="traceContains">+mem: storing 3 in location 2</span>
<span class="Comment"># unicode for '«'</span>
<span class="traceContains">+mem: storing 171 in location 3</span>
<span class="Delimiter">:(before "End NEW Check Special-cases")</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>is_literal_string<span class="Delimiter">(</span>inst<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="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">:(before "Convert 'new' To 'allocate'")</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>name == <span class="Constant">"new"</span> && is_literal_string<span class="Delimiter">(</span>inst<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="Identifier">continue</span><span class="Delimiter">;</span>
<span class="Delimiter">:(after "case NEW" following "Primitive Recipe Implementations")</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>is_literal_string<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="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>new_mu_string<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>name<span class="Delimiter">));</span>
trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new string alloc: "</span> << products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span>
<span class="Identifier">break</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(code)</span>
<span class="Normal">int</span> new_mu_string<span class="Delimiter">(</span><span class="Normal">const</span> string& contents<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Comment">// allocate an array just large enough for it</span>
<span class="Normal">int</span> string_length = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span>
<span class="CommentedCode">//? Total_alloc += string_length+1;</span>
<span class="CommentedCode">//? Num_alloc++;</span>
ensure_space<span class="Delimiter">(</span>string_length+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// don't forget the extra location for array size</span>
<span class="Comment">// initialize string</span>
<span class="Normal">int</span> result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span>
<span class="Comment">// initialize refcount</span>
put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc++<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span>
<span class="Comment">// store length</span>
put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc++<span class="Delimiter">,</span> string_length<span class="Delimiter">);</span>
<span class="Normal">int</span> curr = <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Normal">const</span> <span class="Normal">char</span>* raw_contents = contents<span class="Delimiter">.</span>c_str<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 < string_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Normal">uint32_t</span> curr_character<span class="Delimiter">;</span>
assert<span class="Delimiter">(</span>curr < SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span>
tb_utf8_char_to_unicode<span class="Delimiter">(</span>&curr_character<span class="Delimiter">,</span> &raw_contents[curr]<span class="Delimiter">);</span>
put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">,</span> curr_character<span class="Delimiter">);</span>
curr += tb_utf8_char_length<span class="Delimiter">(</span>raw_contents[curr]<span class="Delimiter">);</span>
++Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Comment">// mu strings are not null-terminated in memory</span>
<span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Comment">//: stash recognizes strings</span>
<span class="Delimiter">:(scenario stash_string)</span>
def main [
<span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc]
stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character
]
<span class="traceContains">+app: foo: abc</span>
<span class="Delimiter">:(before "End print Special-cases(reagent r, data)")</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Delimiter">{</span>
assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span>
<span class="Identifier">return</span> read_mu_string<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span>+<span class="Constant">' '</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="Delimiter">:(scenario unicode_string)</span>
def main [
<span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [♠]
stash [foo:]<span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:character
]
<span class="traceContains">+app: foo: ♠</span>
<span class="Delimiter">:(scenario stash_space_after_string)</span>
def main [
<span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc]
stash <span class="Constant">1</span>:address:array:character<span class="Delimiter">,</span> [foo]
]
<span class="traceContains">+app: abc foo</span>
<span class="Comment">//: Allocate more to routine when initializing a literal string</span>
<span class="Delimiter">:(scenario new_string_overflow)</span>
<span class="Special">% Initial_memory_per_routine = 2;</span>
def main [
<span class="Constant">1</span>:address:number/<span class="Special">raw <- </span><span class="Normal">new</span> number:type
<span class="Constant">2</span>:address:array:character/<span class="Special">raw <- </span><span class="Normal">new</span> [a] <span class="Comment"># not enough room in initial page, if you take the array size into account</span>
]
<span class="traceContains">+new: routine allocated memory from 1000 to 1002</span>
<span class="traceContains">+new: routine allocated memory from 1002 to 1004</span>
<span class="Comment">//: helpers</span>
<span class="Delimiter">:(code)</span>
<span class="Normal">int</span> unicode_length<span class="Delimiter">(</span><span class="Normal">const</span> string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Normal">const</span> <span class="Normal">char</span>* in = s<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span>
<span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Normal">int</span> curr = <span class="Constant">0</span><span class="Delimiter">;</span>
<span class="Normal">while</span> <span class="Delimiter">(</span>curr < SIZE<span class="Delimiter">(</span>s<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Comment">// carefully bounds-check on the string</span>
<span class="Comment">// before accessing its raw pointer</span>
++result<span class="Delimiter">;</span>
curr += tb_utf8_char_length<span class="Delimiter">(</span>in[curr]<span class="Delimiter">);</span>
<span class="Delimiter">}</span>
<span class="Identifier">return</span> result<span class="Delimiter">;</span>
<span class="Delimiter">}</span>
string read_mu_string<span class="Delimiter">(</span><span class="Normal">int</span> address<span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span>
address++<span class="Delimiter">;</span> <span class="Comment">// skip refcount</span>
<span class="Normal">int</span> size = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">);</span>
<span class="Normal">if</span> <span class="Delimiter">(</span>size == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span>
ostringstream tmp<span class="Delimiter">;</span>
<span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address+<span class="Constant">1</span><span class="Delimiter">;</span> curr <= address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span>
tmp << to_unicode<span class="Delimiter">(</span><span class="Normal">static_cast</span><<span class="Normal">uint32_t</span>><span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)));</span>
<span class="Delimiter">}</span>
<span class="Identifier">return</span> tmp<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
<span class="Delimiter">}</span>
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
|