about summary refs log blame commit diff stats
path: root/html/channel.mu.html
blob: 14530ec8e1281f6f1eecca0c63b17946e77c11ce (plain) (tree)
;>(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != <span class="Constant">&quot;type&quot;</span><span class="Delimiter">)</span> raise &lt;&lt; <span class="Constant">&quot;tried to allocate non-type &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot; in recipe &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; die<span class="Delimiter">();</span> if <span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">.</span>find<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>name<span class="Delimiter">)</span> == Type_ordinal<span class="Delimiter">.</span>end<span class="Delimiter">())</span> raise &lt;&lt; <span class="Constant">&quot;unknown type &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; in recipe &quot;</span> &lt;&lt; Recipe[r]<span class="Delimiter">.</span>name &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; die<span class="Delimiter">();</span> <span class="CommentedCode">//? cerr &lt;&lt; &quot;type &quot; &lt;&lt; inst.ingredients.at(0).name &lt;&lt; &quot; =&gt; &quot; &lt;&lt; Type_ordinal[inst.ingredients.at(0).name] &lt;&lt; '\n'; //? 1</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>set_value<span class="Delimiter">(</span>Type_ordinal[inst<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>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; -&gt; &quot;</span> &lt;&lt; inst<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> end_new_transform:<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="SalientComment">//:: Now implement the primitive recipe.</span> <span class="Comment">//: todo: build 'new' in mu itself</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span> NEW<span class="Delimiter">,</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span> Recipe_ordinal[<span class="Constant">&quot;new&quot;</span>] = NEW<span class="Delimiter">;</span> <span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span> case NEW: <span class="Delimiter">{</span> <span class="Comment">// compute the space we need</span> long long int size = <span class="Constant">0</span><span class="Delimiter">;</span> long long int array_length = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">{</span> vector&lt;type_ordinal&gt; type<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>is_literal<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> type<span class="Delimiter">.</span>push_back<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>value<span class="Delimiter">);</span> <span class="CommentedCode">//? trace(Primitive_recipe_depth, &quot;mem&quot;) &lt;&lt; &quot;type &quot; &lt;&lt; current_instruction().ingredients.at(0).to_string() &lt;&lt; ' ' &lt;&lt; type.size() &lt;&lt; ' ' &lt;&lt; type.back() &lt;&lt; &quot; has size &quot; &lt;&lt; size_of(type); //? 1</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// array</span> array_length = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;array size is &quot;</span> &lt;&lt; array_length<span class="Delimiter">;</span> size = array_length*size_of<span class="Delimiter">(</span>type<span class="Delimiter">)</span> + <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> else <span class="Delimiter">{</span> <span class="Comment">// scalar</span> size = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Comment">// compute the region of memory to return</span> <span class="Comment">// really crappy at the moment</span> ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span> const long long int result = Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;mem&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;new alloc: &quot;</span> &lt;&lt; result<span class="Delimiter">;</span> <span class="CommentedCode">//? trace(Primitive_recipe_depth, &quot;mem&quot;) &lt;&lt; &quot;size: &quot; &lt;&lt; size &lt;&lt; &quot; locations&quot;; //? 1</span> <span class="Comment">// save result</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="Comment">// initialize allocated space</span> for <span class="Delimiter">(</span>long long int address = result<span class="Delimiter">;</span> address &lt; result+size<span class="Delimiter">;</span> ++address<span class="Delimiter">)</span> <span class="Delimiter">{</span> Memory[address] = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> if <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> &gt; <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> Memory[result] = array_length<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">// bump</span> Current_routine<span class="Delimiter">-&gt;</span>alloc += size<span class="Delimiter">;</span> <span class="Comment">// no support for reclaiming memory</span> assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>alloc &lt;= Current_routine<span class="Delimiter">-&gt;</span>alloc_max<span class="Delimiter">);</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> void ensure_space<span class="Delimiter">(</span>long long int size<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>size &lt;= Initial_memory_per_routine<span class="Delimiter">);</span> <span class="CommentedCode">//? cout &lt;&lt; Current_routine-&gt;alloc &lt;&lt; &quot; &quot; &lt;&lt; Current_routine-&gt;alloc_max &lt;&lt; &quot; &quot; &lt;&lt; size &lt;&lt; '\n'; //? 1</span> if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-&gt;</span>alloc + size &gt; Current_routine<span class="Delimiter">-&gt;</span>alloc_max<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// waste the remaining space and create a new chunk</span> Current_routine<span class="Delimiter">-&gt;</span>alloc = Memory_allocated_until<span class="Delimiter">;</span> Memory_allocated_until += Initial_memory_per_routine<span class="Delimiter">;</span> Current_routine<span class="Delimiter">-&gt;</span>alloc_max = Memory_allocated_until<span class="Delimiter">;</span> trace<span class="Delimiter">(</span>Primitive_recipe_depth<span class="Delimiter">,</span> <span class="Constant">&quot;new&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;routine allocated memory from &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>alloc &lt;&lt; <span class="Constant">&quot; to &quot;</span> &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>alloc_max<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario new_initializes)</span> <span class="Special">% Memory_allocated_until = 10;</span> <span class="Special">% Memory[Memory_allocated_until] = 1;</span> recipe main [ <span class="Constant">1</span>:address:number<span class="Special"> &lt;- </span>new number:type <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:address:number/deref ] <span class="traceContains">+mem: storing 0 in location 2</span> <span class="Delimiter">:(scenario new_array)</span> recipe main [ <span class="Constant">1</span>:address:array:number/<span class="Special">raw &lt;- </span>new number:type<span class="Delimiter">,</span> <span class="Constant">5</span>:literal <span class="Constant">2</span>:address:number/<span class="Special">raw &lt;- </span>new number:type <span class="Constant">3</span>:number/<span class="Special">raw &lt;- </span>subtract <span class="Constant">2</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:number/<span class="Special">raw</span> ] <span class="traceContains">+run: 1:address:array:number/raw &lt;- new number:type, 5:literal</span> <span class="traceContains">+mem: array size is 5</span> <span class="Comment"># don't forget the extra location for array size</span> <span class="traceContains">+mem: storing 6 in location 3</span> <span class="Delimiter">:(scenario new_empty_array)</span> recipe main [ <span class="Constant">1</span>:address:array:number/<span class="Special">raw &lt;- </span>new number:type<span class="Delimiter">,</span> <span class="Constant">0</span>:literal <span class="Constant">2</span>:address:number/<span class="Special">raw &lt;- </span>new number:type <span class="Constant">3</span>:number/<span class="Special">raw &lt;- </span>subtract <span class="Constant">2</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:number/<span class="Special">raw</span> ] <span class="traceContains">+run: 1:address:array:number/raw &lt;- new number:type, 0:literal</span> <span class="traceContains">+mem: array size is 0</span> <span class="traceContains">+mem: storing 1 in location 3</span> <span class="Comment">//: Make sure that each routine gets a different alloc to start.</span> <span class="Delimiter">:(scenario new_concurrent)</span> recipe f1 [ start-running f2:recipe <span class="Constant">1</span>:address:number/<span class="Special">raw &lt;- </span>new number:type <span class="Comment"># wait for f2 to complete</span> <span class="Delimiter">{</span> loop-unless <span class="Constant">4</span>:number/<span class="Special">raw</span> <span class="Delimiter">}</span> ] recipe f2 [ <span class="Constant">2</span>:address:number/<span class="Special">raw &lt;- </span>new number:type <span class="Comment"># hack: assumes scheduler implementation</span> <span class="Constant">3</span>:boolean/<span class="Special">raw &lt;- </span>equal <span class="Constant">1</span>:address:number/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:number/<span class="Special">raw</span> <span class="Comment"># signal f2 complete</span> <span class="Constant">4</span>:number/<span class="Special">raw &lt;- </span>copy <span class="Constant">1</span>:literal ] <span class="traceContains">+mem: storing 0 in location 3</span> <span class="Comment">//: If a routine runs out of its initial allocation, it should allocate more.</span> <span class="Delimiter">:(scenario new_overflow)</span> <span class="Special">% Initial_memory_per_routine = 2;</span> recipe main [ <span class="Constant">1</span>:address:number/<span class="Special">raw &lt;- </span>new number:type <span class="Constant">2</span>:address:point/<span class="Special">raw &lt;- </span>new point:type <span class="Comment"># not enough room in initial page</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="SalientComment">//:: Next, extend 'new' to handle a unicode string literal argument.</span> <span class="Delimiter">:(scenario new_string)</span> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [abc def] <span class="Constant">2</span>:character<span class="Special"> &lt;- </span>index <span class="Constant">1</span>:address:array:character/deref<span class="Delimiter">,</span> <span class="Constant">5</span>:literal ] <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> recipe main [ <span class="Constant">1</span>:address:array:character<span class="Special"> &lt;- </span>new [a«c] <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>length <span class="Constant">1</span>:address:array:character/deref <span class="Constant">3</span>:character<span class="Special"> &lt;- </span>index <span class="Constant">1</span>:address:array:character/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:literal ] <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 &quot;End NEW Transform Special-cases&quot;)</span> if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; !inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>properties<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; !inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> &amp;&amp; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;literal-string&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// skip transform</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>initialized = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Identifier">goto</span> end_new_transform<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(after &quot;case NEW&quot; following &quot;Primitive Recipe Implementations&quot;)</span> if <span class="Delimiter">(</span>is_literal<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> &amp;&amp; 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>properties<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">&quot;literal-string&quot;</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_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> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> long long int new_string<span class="Delimiter">(</span>const string&amp; contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// allocate an array just large enough for it</span> long long int string_length = unicode_length<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> <span class="CommentedCode">//? cout &lt;&lt; &quot;string_length is &quot; &lt;&lt; string_length &lt;&lt; '\n'; //? 1</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="CommentedCode">//? cout &lt;&lt; &quot;new string literal: &quot; &lt;&lt; current_instruction().ingredients.at(0).name &lt;&lt; '\n'; //? 1</span> long long int result = Current_routine<span class="Delimiter">-&gt;</span>alloc<span class="Delimiter">;</span> Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc++] = string_length<span class="Delimiter">;</span> long long int curr = <span class="Constant">0</span><span class="Delimiter">;</span> const char* raw_contents = contents<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; string_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> uint32_t curr_character<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr &lt; SIZE<span class="Delimiter">(</span>contents<span class="Delimiter">));</span> tb_utf8_char_to_unicode<span class="Delimiter">(</span>&amp;curr_character<span class="Delimiter">,</span> &amp;raw_contents[curr]<span class="Delimiter">);</span> Memory[Current_routine<span class="Delimiter">-&gt;</span>alloc] = 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">-&gt;</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">//: 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> recipe main [ <span class="Constant">1</span>:address:number/<span class="Special">raw &lt;- </span>new number:type <span class="Constant">2</span>:address:array:character/<span class="Special">raw &lt;- </span>new [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> long long int unicode_length<span class="Delimiter">(</span>const string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span> const char* in = s<span class="Delimiter">.</span>c_str<span class="Delimiter">();</span> long long int result = <span class="Constant">0</span><span class="Delimiter">;</span> long long int curr = <span class="Constant">0</span><span class="Delimiter">;</span> while <span class="Delimiter">(</span>curr &lt; 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> </pre> </body> </html> <!-- vim: set foldmethod=manual : -->