diff options
Diffstat (limited to 'html')
47 files changed, 9125 insertions, 0 deletions
diff --git a/html/000organization.cc.html b/html/000organization.cc.html new file mode 100644 index 00000000..b4eab9e7 --- /dev/null +++ b/html/000organization.cc.html @@ -0,0 +1,156 @@ +<!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/000organization.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; } +.Delimiter { color: #c000c0; } +.Comment { color: #8080ff; } +.Constant { color: #008080; } +.Identifier { color: #008080; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: You guessed right: the '000' prefix means you should start reading here.</span> +<span class="Comment">//:</span> +<span class="Comment">//: This project is setup to load all files with a numeric prefix. Just create</span> +<span class="Comment">//: a new file and start hacking.</span> +<span class="Comment">//:</span> +<span class="Comment">//: The first few files (00*) are independent of what this program does, an</span> +<span class="Comment">//: experimental skeleton that will hopefully make it both easier for others to</span> +<span class="Comment">//: understand and more malleable, easier to rewrite and remould into radically</span> +<span class="Comment">//: different shapes without breaking in subtle corner cases. The premise is</span> +<span class="Comment">//: that understandability and rewrite-friendliness are related in a virtuous</span> +<span class="Comment">//: cycle. Doing one well makes it easier to do the other.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Lower down, this file contains a legal, bare-bones C++ program. It doesn't</span> +<span class="Comment">//: do anything yet; subsequent files will contain :(...) directives to insert</span> +<span class="Comment">//: lines into it. For example:</span> +<span class="Comment">//: :(after "more events")</span> +<span class="Comment">//: This directive means: insert the following lines after a line in the</span> +<span class="Comment">//: program containing the words "more events".</span> +<span class="Comment">//:</span> +<span class="Comment">//: A simple tool is included to 'tangle' all the files together in sequence</span> +<span class="Comment">//: according to their directives into a single source file containing all the</span> +<span class="Comment">//: code for the project, and then feed the source file to the compiler.</span> +<span class="Comment">//: (It'll drop these comments starting with a '//:' prefix that only make</span> +<span class="Comment">//: sense before tangling.)</span> +<span class="Comment">//:</span> +<span class="Comment">//: Directives free up the programmer to order code for others to read rather</span> +<span class="Comment">//: than as forced by the computer or compiler. Each individual feature can be</span> +<span class="Comment">//: organized in a self-contained 'layer' that adds code to many different data</span> +<span class="Comment">//: structures and functions all over the program. The right decomposition into</span> +<span class="Comment">//: layers will let each layer make sense in isolation.</span> +<span class="Comment">//:</span> +<span class="Comment">//: "If I look at any small part of it, I can see what is going on -- I don't</span> +<span class="Comment">//: need to refer to other parts to understand what something is doing.</span> +<span class="Comment">//:</span> +<span class="Comment">//: If I look at any large part in overview, I can see what is going on -- I</span> +<span class="Comment">//: don't need to know all the details to get it.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Every level of detail is as locally coherent and as well thought-out as</span> +<span class="Comment">//: any other level."</span> +<span class="Comment">//:</span> +<span class="Comment">//: -- Richard Gabriel, "The Quality Without A Name"</span> +<span class="Comment">//: (<a href="http://dreamsongs.com/Files/PatternsOfSoftware.pdf">http://dreamsongs.com/Files/PatternsOfSoftware.pdf</a>, page 42)</span> +<span class="Comment">//:</span> +<span class="Comment">//: Directives are powerful; they permit inserting or modifying any point in</span> +<span class="Comment">//: the program. Using them tastefully requires mapping out specific lines as</span> +<span class="Comment">//: waypoints for future layers to hook into. Often such waypoints will be in</span> +<span class="Comment">//: comments, capitalized to hint that other layers rely on their presence.</span> +<span class="Comment">//:</span> +<span class="Comment">//: A single waypoint might have many different code fragments hooking into</span> +<span class="Comment">//: it from all over the codebase. Use 'before' directives to insert</span> +<span class="Comment">//: code at a location in order, top to bottom, and 'after' directives to</span> +<span class="Comment">//: insert code in reverse order. By convention waypoints intended for insertion</span> +<span class="Comment">//: before begin with 'End'. Notice below how the layers line up above the "End</span> +<span class="Comment">//: Foo" waypoint.</span> +<span class="Comment">//:</span> +<span class="Comment">//: File 001 File 002 File 003</span> +<span class="Comment">//: ============ =================== ===================</span> +<span class="Comment">//: // Foo</span> +<span class="Comment">//: ------------</span> +<span class="Comment">//: <---- :(before "End Foo")</span> +<span class="Comment">//: ....</span> +<span class="Comment">//: ...</span> +<span class="Comment">//: ------------</span> +<span class="Comment">//: <---------------------------- :(before "End Foo")</span> +<span class="Comment">//: ....</span> +<span class="Comment">//: ...</span> +<span class="Comment">//: // End Foo</span> +<span class="Comment">//: ============</span> +<span class="Comment">//:</span> +<span class="Comment">//: Here's part of a layer in color: <a href="http://i.imgur.com/0eONnyX.png">http://i.imgur.com/0eONnyX.png</a>. Directives</span> +<span class="Comment">//: are shaded dark.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Layers do more than just shuffle code around. Their guarantee is that it</span> +<span class="Comment">//: should be possible to stop loading after any file/layer, build and run the</span> +<span class="Comment">//: program, and pass all tests for loaded features. (Relevant is</span> +<span class="Comment">//: <a href="http://youtube.com/watch?v=c8N72t7aScY">http://youtube.com/watch?v=c8N72t7aScY</a>, a scene from "2001: A Space</span> +<span class="Comment">//: Odyssey".) Use the included script called 'test_all_layers' to check the</span> +<span class="Comment">//: guarantee if you make any changes.</span> +<span class="Comment">//:</span> +<span class="Comment">//: This 'subsetting guarantee' ensures that this directory contains a</span> +<span class="Comment">//: cleaned-up narrative of the evolution of this codebase. Organizing</span> +<span class="Comment">//: autobiographically allows a newcomer to rapidly orient himself, reading the</span> +<span class="Comment">//: first few files to understand a simple gestalt of a program's core purpose</span> +<span class="Comment">//: and features, and later gradually working his way through other features as</span> +<span class="Comment">//: the need arises.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Programmers shouldn't need to understand everything about a program to hack</span> +<span class="Comment">//: on it. But they shouldn't be prevented from a thorough understanding of</span> +<span class="Comment">//: each aspect either. The goal of layers is to reward curiosity.</span> + +<span class="Comment">// Includes</span> +<span class="Comment">// End Includes</span> + +<span class="Comment">// Types</span> +<span class="Comment">// End Types</span> + +<span class="Comment">// prototypes are auto-generated; define your functions in any order</span> +<span class="PreProc">#include </span><span class="Constant">"function_list"</span> <span class="Comment">// by convention, files ending with '_list' are auto-generated</span> + +<span class="Comment">// Globals</span> +<span class="Comment">// End Globals</span> + +int main<span class="Delimiter">(</span>int argc<span class="Delimiter">,</span> char* argv[]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + + <span class="Comment">// End One-time Setup</span> + + <span class="Comment">// End Commandline Parsing</span> + + <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">// End Main</span> +<span class="Delimiter">}</span> + +void setup<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// End Setup</span> +<span class="Delimiter">}</span> + +void teardown<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// End Teardown</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Without directives or with the :(code) directive, lines get added at the</span> +<span class="Comment">//: end.</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/001help.cc.html b/html/001help.cc.html new file mode 100644 index 00000000..80dc9e44 --- /dev/null +++ b/html/001help.cc.html @@ -0,0 +1,87 @@ +<!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/001help.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.SalientComment { color: #00ffff; } +.Identifier { color: #008080; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Everything this project/binary supports.</span> +<span class="Comment">//: This should give you a sense for what to look forward to in later layers.</span> + +<span class="Delimiter">:(before "End Commandline Parsing")</span> +if <span class="Delimiter">(</span>argc <= <span class="Constant">1</span> || is_equal<span class="Delimiter">(</span>argv[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"--help"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// this is the functionality later layers will provide</span> + <span class="Comment">// currently no automated tests for commandline arg parsing</span> + cerr << <span class="Constant">"To load files and run 'main':</span><span class="cSpecial">\n</span><span class="Constant">"</span> + << <span class="Constant">" mu file1.mu file2.mu ...</span><span class="cSpecial">\n</span><span class="Constant">"</span> + << <span class="Constant">"To run all tests:</span><span class="cSpecial">\n</span><span class="Constant">"</span> + << <span class="Constant">" mu test</span><span class="cSpecial">\n</span><span class="Constant">"</span> + << <span class="Constant">"To load files and then run all tests:</span><span class="cSpecial">\n</span><span class="Constant">"</span> + << <span class="Constant">" mu test file1.mu file2.mu ...</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Helper function used by the above fragment of code (and later layers too,</span> +<span class="SalientComment">//:: who knows?).</span> +<span class="Comment">//: The :(code) directive appends function definitions to the end of the</span> +<span class="Comment">//: project. Regardless of where functions are defined, we can call them</span> +<span class="Comment">//: anywhere we like as long as we format the function header in a specific</span> +<span class="Comment">//: way: put it all on a single line without indent, end the line with ') {'</span> +<span class="Comment">//: and no trailing whitespace. As long as functions uniformly start this</span> +<span class="Comment">//: way, our makefile contains a little command to automatically generate</span> +<span class="Comment">//: declarations for them.</span> +<span class="Delimiter">:(code)</span> +bool is_equal<span class="Delimiter">(</span>char* s<span class="Delimiter">,</span> const char* lit<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> strncmp<span class="Delimiter">(</span>s<span class="Delimiter">,</span> lit<span class="Delimiter">,</span> strlen<span class="Delimiter">(</span>lit<span class="Delimiter">))</span> == <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include</span><span class="Constant"><assert.h></span> + +<span class="PreProc">#include</span><span class="Constant"><iostream></span> +using std::istream<span class="Delimiter">;</span> +using std::ostream<span class="Delimiter">;</span> +using std::iostream<span class="Delimiter">;</span> +using std::cin<span class="Delimiter">;</span> +using std::cout<span class="Delimiter">;</span> +using std::cerr<span class="Delimiter">;</span> + +<span class="PreProc">#include</span><span class="Constant"><cstring></span> +<span class="PreProc">#include</span><span class="Constant"><string></span> +using std::string<span class="Delimiter">;</span> +typedef size_t index_t<span class="Delimiter">;</span> +const index_t NOT_FOUND = string::npos<span class="Delimiter">;</span> +<span class="Delimiter">:(after "int main(int argc, char* argv[])")</span> +assert<span class="Delimiter">(</span>sizeof<span class="Delimiter">(</span>string::size_type<span class="Delimiter">)</span> == sizeof<span class="Delimiter">(</span>size_t<span class="Delimiter">));</span> +assert<span class="Delimiter">(</span>sizeof<span class="Delimiter">(</span>index_t<span class="Delimiter">)</span> == sizeof<span class="Delimiter">(</span>size_t<span class="Delimiter">));</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/002test.cc.html b/html/002test.cc.html new file mode 100644 index 00000000..073aad8d --- /dev/null +++ b/html/002test.cc.html @@ -0,0 +1,129 @@ +<!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/002test.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Identifier { color: #008080; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: A simple test harness. To create new tests define functions starting with</span> +<span class="Comment">//: 'test_'. To run all tests so defined, run:</span> +<span class="Comment">//: $ wart test</span> +<span class="Comment">//:</span> +<span class="Comment">//: So far it seems tasteful for layers to never ever reach back to modify</span> +<span class="Comment">//: previously-defined tests. Every test is a contract once written, and should</span> +<span class="Comment">//: pass as-is if it is included, regardless of how much later layers change</span> +<span class="Comment">//: the program. Avoid writing 'temporary' tests that only work with some</span> +<span class="Comment">//: subsets of the program.</span> + +<span class="Delimiter">:(before "End Types")</span> +typedef void <span class="Delimiter">(</span>*test_fn<span class="Delimiter">)(</span>void<span class="Delimiter">);</span> + +<span class="Delimiter">:(before "End Globals")</span> +const test_fn Tests[] = <span class="Delimiter">{</span> +<span class="PreProc"> #include </span><span class="Constant">"test_list"</span> <span class="Comment">// auto-generated; see makefile</span> +<span class="Delimiter">};</span> + +bool Run_tests = <span class="Constant">false</span><span class="Delimiter">;</span> +bool Passed = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// set this to false inside any test to indicate failure</span> +long Num_failures = <span class="Constant">0</span><span class="Delimiter">;</span> + +<span class="PreProc">#define CHECK(X) \</span> +<span class="PreProc"> </span>if<span class="PreProc"> (!(X)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span> +<span class="PreProc"> ++Num_failures</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> cerr << </span><span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F "</span><span class="PreProc"> << __FUNCTION__ << </span><span class="Constant">"("</span><span class="PreProc"> << </span><span class="Constant">__FILE__</span><span class="PreProc"> << </span><span class="Constant">":"</span><span class="PreProc"> << </span><span class="Constant">__LINE__</span><span class="PreProc"> << </span><span class="Constant">"): "</span><span class="PreProc"> << #X << </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc"> </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span> +<span class="PreProc"> </span><span class="Delimiter">}</span> + +<span class="PreProc">#define CHECK_EQ(X</span><span class="Delimiter">,</span><span class="PreProc"> Y) \</span> +<span class="PreProc"> </span>if<span class="PreProc"> ((X) != (Y)) </span><span class="Delimiter">{</span><span class="PreProc"> \</span> +<span class="PreProc"> ++Num_failures</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> cerr << </span><span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F "</span><span class="PreProc"> << __FUNCTION__ << </span><span class="Constant">"("</span><span class="PreProc"> << </span><span class="Constant">__FILE__</span><span class="PreProc"> << </span><span class="Constant">":"</span><span class="PreProc"> << </span><span class="Constant">__LINE__</span><span class="PreProc"> << </span><span class="Constant">"): "</span><span class="PreProc"> << #X << </span><span class="Constant">" == "</span><span class="PreProc"> << #Y << </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> cerr << </span><span class="Constant">" got "</span><span class="PreProc"> << (X) << </span><span class="cSpecial">'\n'</span><span class="Delimiter">;</span><span class="PreProc"> </span><span class="Comment">/*</span><span class="Comment"> BEWARE: multiple eval </span><span class="Comment">*/</span><span class="PreProc"> \</span> +<span class="PreProc"> Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc"> </span><span class="Comment">/*</span><span class="Comment"> Currently we stop at the very first failure. </span><span class="Comment">*/</span><span class="PreProc"> \</span> +<span class="PreProc"> </span><span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Setup")</span> +Passed = <span class="Constant">true</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Commandline Parsing")</span> +if <span class="Delimiter">(</span>argc > <span class="Constant">1</span> && is_equal<span class="Delimiter">(</span>argv[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"test"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + Run_tests = <span class="Constant">true</span><span class="Delimiter">;</span> --argc<span class="Delimiter">;</span> ++argv<span class="Delimiter">;</span> <span class="Comment">// shift 'test' out of commandline args</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Main")</span> +if <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// Test Runs</span> + <span class="Comment">// we run some tests and then exit; assume no state need be maintained afterward</span> + + <span class="Comment">// End Test Run Initialization</span> + time_t t<span class="Delimiter">;</span> time<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> + cerr << <span class="Constant">"C tests: "</span> << ctime<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>index_t i=<span class="Constant">0</span><span class="Delimiter">;</span> i < sizeof<span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/sizeof<span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + run_test<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Tests</span> + cerr << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Num_failures > <span class="Constant">0</span><span class="Delimiter">)</span> + cerr << Num_failures << <span class="Constant">" failure"</span> + << <span class="Delimiter">(</span>Num_failures > <span class="Constant">1</span> ? <span class="Constant">"s"</span> : <span class="Constant">""</span><span class="Delimiter">)</span> + << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void run_test<span class="Delimiter">(</span>index_t i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>i >= sizeof<span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/sizeof<span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + cerr << <span class="Constant">"no test "</span> << i << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + setup<span class="Delimiter">();</span> + <span class="Comment">// End Test Setup</span> + <span class="Delimiter">(</span>*Tests[i]<span class="Delimiter">)();</span> + teardown<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool is_number<span class="Delimiter">(</span>const string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> s<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">"0123456789-."</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +long long int to_int<span class="Delimiter">(</span>string n<span class="Delimiter">)</span> <span class="Delimiter">{</span> + char* end = <span class="Constant">NULL</span><span class="Delimiter">;</span> + long long int result = strtoll<span class="Delimiter">(</span>n<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &end<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">any base</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>*end == <span class="cSpecial">'\0'</span><span class="Delimiter">);</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include</span><span class="Constant"><cstdlib></span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/003trace.cc.html b/html/003trace.cc.html new file mode 100644 index 00000000..1798bf07 --- /dev/null +++ b/html/003trace.cc.html @@ -0,0 +1,516 @@ +<!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/003trace.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Identifier { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.SalientComment { color: #00ffff; } +.CommentedCode { color: #6c6c6c; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: The goal of this skeleton is to make programs more easy to understand and</span> +<span class="Comment">//: more malleable, easy to rewrite in radical ways without accidentally</span> +<span class="Comment">//: breaking some corner case. Tests further both goals. They help</span> +<span class="Comment">//: understandability by letting one make small changes and get feedback. What</span> +<span class="Comment">//: if I wrote this line like so? What if I removed this function call, is it</span> +<span class="Comment">//: really necessary? Just try it, see if the tests pass. Want to explore</span> +<span class="Comment">//: rewriting this bit in this way? Tests put many refactorings on a firmer</span> +<span class="Comment">//: footing.</span> +<span class="Comment">//:</span> +<span class="Comment">//: But the usual way we write tests seems incomplete. Refactorings tend to</span> +<span class="Comment">//: work in the small, but don't help with changes to function boundaries. If</span> +<span class="Comment">//: you want to extract a new function you have to manually test-drive it to</span> +<span class="Comment">//: create tests for it. If you want to inline a function its tests are no</span> +<span class="Comment">//: longer valid. In both cases you end up having to reorganize code as well as</span> +<span class="Comment">//: tests, an error-prone activity.</span> +<span class="Comment">//:</span> +<span class="Comment">//: This file tries to fix this problem by supporting domain-driven testing</span> +<span class="Comment">//: We try to focus on the domain of inputs the program should work on. All</span> +<span class="Comment">//: tests invoke the program in a single way: by calling run() with different</span> +<span class="Comment">//: inputs. The program operates on the input and logs _facts_ it deduces to a</span> +<span class="Comment">//: trace:</span> +<span class="Comment">//: trace("label") << "fact 1: " << val;</span> +<span class="Comment">//:</span> +<span class="Comment">//: The tests check for facts:</span> +<span class="Comment">//: :(scenario foo)</span> +<span class="Comment">//: 34 # call run() with this input</span> +<span class="Comment">//: +label: fact 1: 34 # trace should have logged this at the end</span> +<span class="Comment">//: -label: fact 1: 35 # trace should never contain such a line</span> +<span class="Comment">//:</span> +<span class="Comment">//: Since we never call anything but the run() function directly, we never have</span> +<span class="Comment">//: to rewrite the tests when we reorganize the internals of the program. We</span> +<span class="Comment">//: just have to make sure our rewrite deduces the same facts about the domain,</span> +<span class="Comment">//: and that's something we're going to have to do anyway.</span> +<span class="Comment">//:</span> +<span class="Comment">//: To avoid the combinatorial explosion of integration tests, we organize the</span> +<span class="Comment">//: program into different layers, and each fact is logged to the trace with a</span> +<span class="Comment">//: specific label. Individual tests can focus on specific labels. In essence,</span> +<span class="Comment">//: validating the facts logged with a specific label is identical to calling</span> +<span class="Comment">//: some internal subsystem.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Traces interact salubriously with layers. Thanks to our ordering</span> +<span class="Comment">//: directives, each layer can contain its own tests. They may rely on other</span> +<span class="Comment">//: layers, but when a test fails its usually due to breakage in the same</span> +<span class="Comment">//: layer. When multiple tests fail, it's usually useful to debug the very</span> +<span class="Comment">//: first test to fail. This is in contrast with the traditional approach,</span> +<span class="Comment">//: where changes can cause breakages in faraway subsystems, and picking the</span> +<span class="Comment">//: right test to debug can be an important skill to pick up.</span> +<span class="Comment">//:</span> +<span class="Comment">//: A final wrinkle is for recursive functions; it's often useful to segment</span> +<span class="Comment">//: calls of different depth in the trace:</span> +<span class="Comment">//: +eval/1: => 34 # the topmost call to eval should have logged this line</span> +<span class="Comment">//: (look at new_trace_frame below)</span> +<span class="Comment">//:</span> +<span class="Comment">//: To build robust tests, trace facts about your domain rather than details of</span> +<span class="Comment">//: how you computed them.</span> +<span class="Comment">//:</span> +<span class="Comment">//: More details: <a href="http://akkartik.name/blog/tracing-tests">http://akkartik.name/blog/tracing-tests</a></span> +<span class="Comment">//:</span> +<span class="Comment">//: ---</span> +<span class="Comment">//:</span> +<span class="Comment">//: Between layers and domain-driven testing, programming starts to look like a</span> +<span class="Comment">//: fundamentally different activity. Instead of a) superficial, b) local rules</span> +<span class="Comment">//: on c) code [like <a href="http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],">http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet],</a></span> +<span class="Comment">//: we allow programmers to engage with the a) deep, b) global structure of the</span> +<span class="Comment">//: c) domain. If you can systematically track discontinuities in the domain</span> +<span class="Comment">//: you don't care if the code used gotos as long as it passed the tests. If</span> +<span class="Comment">//: tests become more robust to run it becomes easier to try out radically</span> +<span class="Comment">//: different implementations for the same program. If code is super-easy to</span> +<span class="Comment">//: rewrite, it becomes less important what indentation style it uses, or that</span> +<span class="Comment">//: the objects are appropriately encapsulated, or that the functions are</span> +<span class="Comment">//: referentially transparent.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Instead of plumbing, programming becomes building and gradually refining a</span> +<span class="Comment">//: map of the environment the program must operate under. Whether a program is</span> +<span class="Comment">//: 'correct' at a given point in time is a red herring; what matters is</span> +<span class="Comment">//: avoiding regression by monotonically nailing down the more 'eventful' parts</span> +<span class="Comment">//: of the terrain. It helps readers new and old and rewards curiosity to</span> +<span class="Comment">//: organize large programs in self-similar hiearchies of example scenarios</span> +<span class="Comment">//: colocated with the code that makes them work.</span> +<span class="Comment">//:</span> +<span class="Comment">//: "Programming properly should be regarded as an activity by which</span> +<span class="Comment">//: programmers form a mental model, rather than as production of a program."</span> +<span class="Comment">//: -- Peter Naur (<a href="http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)">http://alistair.cockburn.us/ASD+book+extract%3A+%22Naur,+Ehn,+Musashi%22)</a></span> + +<span class="Delimiter">:(before "int main")</span> +<span class="Comment">// End Tracing // hack to ensure most code in this layer comes before anything else</span> + +<span class="Delimiter">:(before "End Tracing")</span> +bool Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +<span class="CommentedCode">//? cerr << "AAA setup\n"; //? 2</span> +Hide_warnings = <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Tracing")</span> +struct trace_stream <span class="Delimiter">{</span> + vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > > past_lines<span class="Delimiter">;</span> <span class="Comment">// [(layer label, frame, line)]</span> + map<string<span class="Delimiter">,</span> int> frame<span class="Delimiter">;</span> + <span class="Comment">// accumulator for current line</span> + ostringstream* curr_stream<span class="Delimiter">;</span> + string curr_layer<span class="Delimiter">;</span> + string dump_layer<span class="Delimiter">;</span> + trace_stream<span class="Delimiter">()</span> :curr_stream<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + ~trace_stream<span class="Delimiter">()</span> <span class="Delimiter">{</span> if <span class="Delimiter">(</span>curr_stream<span class="Delimiter">)</span> delete curr_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span> + + ostringstream& stream<span class="Delimiter">(</span>string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span> + newline<span class="Delimiter">();</span> + curr_stream = new ostringstream<span class="Delimiter">;</span> + curr_layer = layer<span class="Delimiter">;</span> + <span class="Identifier">return</span> *curr_stream<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + + <span class="Comment">// be sure to call this before messing with curr_stream or curr_layer or frame</span> + void newline<span class="Delimiter">()</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!curr_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + string curr_contents = curr_stream<span class="Delimiter">-></span>str<span class="Delimiter">();</span> + curr_contents<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>curr_contents<span class="Delimiter">.</span>find_last_not_of<span class="Delimiter">(</span><span class="Constant">"</span><span class="cSpecial">\r\n</span><span class="Constant">"</span><span class="Delimiter">)</span>+<span class="Constant">1</span><span class="Delimiter">);</span> + past_lines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> ><span class="Delimiter">(</span>curr_layer<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string><span class="Delimiter">(</span>frame[curr_layer]<span class="Delimiter">,</span> curr_contents<span class="Delimiter">)));</span> + if <span class="Delimiter">(</span>curr_layer == dump_layer || curr_layer == <span class="Constant">"dump"</span> || dump_layer == <span class="Constant">"all"</span> || + <span class="Delimiter">(</span>!Hide_warnings && curr_layer == <span class="Constant">"warn"</span><span class="Delimiter">))</span> + cerr << curr_layer << <span class="Constant">'/'</span> << frame[curr_layer] << <span class="Constant">": "</span> << curr_contents << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + delete curr_stream<span class="Delimiter">;</span> + curr_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + + <span class="Comment">// Useful for debugging.</span> + string readable_contents<span class="Delimiter">(</span>string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// missing layer = everything, frame, hierarchical layers</span> + newline<span class="Delimiter">();</span> + ostringstream output<span class="Delimiter">;</span> + string real_layer<span class="Delimiter">,</span> frame<span class="Delimiter">;</span> + parse_layer_and_frame<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> &real_layer<span class="Delimiter">,</span> &frame<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> + if <span class="Delimiter">(</span>layer<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> || prefix_match<span class="Delimiter">(</span>real_layer<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> + output << p<span class="Delimiter">-></span>first << <span class="Constant">"/"</span> << p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>first << <span class="Constant">": "</span> << p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> output<span class="Delimiter">.</span>str<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + + <span class="Comment">// Useful for a newcomer to visualize the program at work.</span> + void dump_browseable_contents<span class="Delimiter">(</span>string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ofstream dump<span class="Delimiter">(</span><span class="Constant">"dump"</span><span class="Delimiter">);</span> + dump << <span class="Constant">"<div class='frame' frame_index='1'>start</div></span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>first != layer<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + dump << <span class="Constant">"<div class='frame"</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>first > <span class="Constant">1</span><span class="Delimiter">)</span> dump << <span class="Constant">" hidden"</span><span class="Delimiter">;</span> + dump << <span class="Constant">"' frame_index='"</span> << p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>first << <span class="Constant">"'>"</span><span class="Delimiter">;</span> + dump << p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second<span class="Delimiter">;</span> + dump << <span class="Constant">"</div></span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + dump<span class="Delimiter">.</span>close<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">};</span> + +^L + +trace_stream* Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> + +<span class="Comment">// Top-level helper. IMPORTANT: can't nest.</span> +<span class="PreProc">#define trace(layer) !Trace_stream ? cerr </span><span class="Comment">/*</span><span class="Comment">print nothing</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-></span><span class="PreProc">stream(layer)</span> +<span class="Comment">// Warnings should go straight to cerr by default since calls to trace() have</span> +<span class="Comment">// some unfriendly constraints (they delay printing, they can't nest)</span> +<span class="PreProc">#define raise ((!Trace_stream || !Hide_warnings) ? cerr </span><span class="Comment">/*</span><span class="Comment">do print</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-></span><span class="PreProc">stream(</span><span class="Constant">"warn"</span><span class="PreProc">))</span> + +<span class="Comment">// A separate helper for debugging. We should only trace domain-specific</span> +<span class="Comment">// facts. For everything else use log.</span> +<span class="PreProc">#define xlog </span>if<span class="PreProc"> (</span><span class="Constant">false</span><span class="PreProc">) log</span> +<span class="Comment">// To turn on logging replace 'xlog' with 'log'.</span> +<span class="PreProc">#define log cerr</span> + +<span class="Delimiter">:(before "End Types")</span> +<span class="Comment">// raise << die exits after printing -- unless Hide_warnings is set.</span> +struct die <span class="Delimiter">{};</span> +<span class="Delimiter">:(before "End Tracing")</span> +ostream& operator<<<span class="Delimiter">(</span>ostream& os<span class="Delimiter">,</span> unused die<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Hide_warnings<span class="Delimiter">)</span> <span class="Identifier">return</span> os<span class="Delimiter">;</span> + os << <span class="Constant">"dying"</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="PreProc">#define CLEAR_TRACE </span>delete<span class="PreProc"> Trace_stream</span><span class="Delimiter">,</span><span class="PreProc"> Trace_stream = </span>new<span class="PreProc"> trace_stream</span><span class="Delimiter">;</span> + +<span class="PreProc">#define DUMP(layer) </span>if<span class="PreProc"> (Trace_stream) cerr << Trace_stream</span><span class="Delimiter">-></span><span class="PreProc">readable_contents(layer)</span><span class="Delimiter">;</span> + +<span class="Comment">// Trace_stream is a resource, lease_tracer uses RAII to manage it.</span> +string Trace_file<span class="Delimiter">;</span> +static string Trace_dir = <span class="Constant">".traces/"</span><span class="Delimiter">;</span> +struct lease_tracer <span class="Delimiter">{</span> + lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span> Trace_stream = new trace_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span> + ~lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << "write to file? " << Trace_file << "$\n"; //? 2</span> + if <span class="Delimiter">(</span>!Trace_file<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << "writing\n"; //? 2</span> + ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> + fout << Trace_stream<span class="Delimiter">-></span>readable_contents<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> + fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + delete Trace_stream<span class="Delimiter">,</span> Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">,</span> Trace_file = <span class="Constant">""</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">};</span> + +<span class="Comment">// To transparently save traces, start tests with the TEST() macro.</span> +<span class="PreProc">#define TEST(name) </span>void<span class="PreProc"> test_</span><span class="SalientComment">##name() { Trace_file = #name;</span> + +<span class="PreProc">#define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Test Setup")</span> +START_TRACING_UNTIL_END_OF_SCOPE +<span class="CommentedCode">//? Trace_stream->dump_layer = "all"; //? 1</span> + +<span class="Delimiter">:(before "End Tracing")</span> +void trace_all<span class="Delimiter">(</span>const string& label<span class="Delimiter">,</span> const list<string>& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>list<string>::const_iterator p = in<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != in<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> + trace<span class="Delimiter">(</span>label<span class="Delimiter">)</span> << *p<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool check_trace_contents<span class="Delimiter">(</span>string FUNCTION<span class="Delimiter">,</span> string FILE<span class="Delimiter">,</span> int LINE<span class="Delimiter">,</span> string expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// missing layer == anywhere, frame, hierarchical layers</span> + vector<string> expected_lines = split<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">"^D"</span><span class="Delimiter">);</span> + index_t curr_expected_line = <span class="Constant">0</span><span class="Delimiter">;</span> + while <span class="Delimiter">(</span>curr_expected_line < expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> && expected_lines[curr_expected_line]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + string layer<span class="Delimiter">,</span> frame<span class="Delimiter">,</span> contents<span class="Delimiter">;</span> + parse_layer_frame_contents<span class="Delimiter">(</span>expected_lines[curr_expected_line]<span class="Delimiter">,</span> &layer<span class="Delimiter">,</span> &frame<span class="Delimiter">,</span> &contents<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!layer<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && !prefix_match<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + + if <span class="Delimiter">(</span>!frame<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && strtol<span class="Delimiter">(</span>frame<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> <span class="Constant">NULL</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">)</span> != p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>first<span class="Delimiter">)</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + + if <span class="Delimiter">(</span>contents != p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second<span class="Delimiter">)</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + + ++curr_expected_line<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>curr_expected_line < expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> && expected_lines[curr_expected_line]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + parse_layer_frame_contents<span class="Delimiter">(</span>expected_lines[curr_expected_line]<span class="Delimiter">,</span> &layer<span class="Delimiter">,</span> &frame<span class="Delimiter">,</span> &contents<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + + ++Num_failures<span class="Delimiter">;</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F "</span> << FUNCTION << <span class="Constant">"("</span> << FILE << <span class="Constant">":"</span> << LINE << <span class="Constant">"): missing ["</span> << contents << <span class="Constant">"] in trace:</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + DUMP<span class="Delimiter">(</span>layer<span class="Delimiter">);</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +void parse_layer_frame_contents<span class="Delimiter">(</span>const string& orig<span class="Delimiter">,</span> string* layer<span class="Delimiter">,</span> string* frame<span class="Delimiter">,</span> string* contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string layer_and_frame<span class="Delimiter">;</span> + parse_contents<span class="Delimiter">(</span>orig<span class="Delimiter">,</span> <span class="Constant">": "</span><span class="Delimiter">,</span> &layer_and_frame<span class="Delimiter">,</span> contents<span class="Delimiter">);</span> + parse_layer_and_frame<span class="Delimiter">(</span>layer_and_frame<span class="Delimiter">,</span> layer<span class="Delimiter">,</span> frame<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void parse_contents<span class="Delimiter">(</span>const string& s<span class="Delimiter">,</span> const string& delim<span class="Delimiter">,</span> string* prefix<span class="Delimiter">,</span> string* contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> + index_t pos = s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>pos == NOT_FOUND<span class="Delimiter">)</span> <span class="Delimiter">{</span> + *prefix = <span class="Constant">""</span><span class="Delimiter">;</span> + *contents = s<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + *prefix = s<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> pos<span class="Delimiter">);</span> + *contents = s<span class="Delimiter">.</span>substr<span class="Delimiter">(</span>pos+delim<span class="Delimiter">.</span>size<span class="Delimiter">());</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void parse_layer_and_frame<span class="Delimiter">(</span>const string& orig<span class="Delimiter">,</span> string* layer<span class="Delimiter">,</span> string* frame<span class="Delimiter">)</span> <span class="Delimiter">{</span> + index_t last_slash = orig<span class="Delimiter">.</span>rfind<span class="Delimiter">(</span><span class="Constant">'/'</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>last_slash == NOT_FOUND + || orig<span class="Delimiter">.</span>find_last_not_of<span class="Delimiter">(</span><span class="Constant">"0123456789"</span><span class="Delimiter">)</span> != last_slash<span class="Delimiter">)</span> <span class="Delimiter">{</span> + *layer = orig<span class="Delimiter">;</span> + *frame = <span class="Constant">""</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + *layer = orig<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> last_slash<span class="Delimiter">);</span> + *frame = orig<span class="Delimiter">.</span>substr<span class="Delimiter">(</span>last_slash+<span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +^L + +bool check_trace_contents<span class="Delimiter">(</span>string FUNCTION<span class="Delimiter">,</span> string FILE<span class="Delimiter">,</span> int LINE<span class="Delimiter">,</span> string layer<span class="Delimiter">,</span> string expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// empty layer == everything, multiple layers, hierarchical layers</span> + vector<string> expected_lines = split<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">"^D"</span><span class="Delimiter">);</span> + index_t curr_expected_line = <span class="Constant">0</span><span class="Delimiter">;</span> + while <span class="Delimiter">(</span>curr_expected_line < expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> && expected_lines[curr_expected_line]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + vector<string> layers = split<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!layer<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && !any_prefix_match<span class="Delimiter">(</span>layers<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second != expected_lines[curr_expected_line]<span class="Delimiter">)</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + ++curr_expected_line<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>curr_expected_line < expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> && expected_lines[curr_expected_line]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + + ++Num_failures<span class="Delimiter">;</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F "</span> << FUNCTION << <span class="Constant">"("</span> << FILE << <span class="Constant">":"</span> << LINE << <span class="Constant">"): missing ["</span> << expected_lines[curr_expected_line] << <span class="Constant">"] in trace:</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + DUMP<span class="Delimiter">(</span>layer<span class="Delimiter">);</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="PreProc">#define CHECK_TRACE_CONTENTS(</span><span class="Delimiter">...</span><span class="PreProc">) check_trace_contents(__FUNCTION__</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">__FILE__</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">__LINE__</span><span class="Delimiter">,</span><span class="PreProc"> __VA_ARGS__)</span> + +int trace_count<span class="Delimiter">(</span>string layer<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> trace_count<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +int trace_count<span class="Delimiter">(</span>string layer<span class="Delimiter">,</span> string line<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + long result = <span class="Constant">0</span><span class="Delimiter">;</span> + vector<string> layers = split<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>any_prefix_match<span class="Delimiter">(</span>layers<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> + if <span class="Delimiter">(</span>line == <span class="Constant">""</span> || p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second == line<span class="Delimiter">)</span> + ++result<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +int trace_count<span class="Delimiter">(</span>string layer<span class="Delimiter">,</span> int frame<span class="Delimiter">,</span> string line<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + long result = <span class="Constant">0</span><span class="Delimiter">;</span> + vector<string> layers = split<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>any_prefix_match<span class="Delimiter">(</span>layers<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">)</span> && p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>first == frame<span class="Delimiter">)</span> + if <span class="Delimiter">(</span>line == <span class="Constant">""</span> || p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second == line<span class="Delimiter">)</span> + ++result<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="PreProc">#define CHECK_TRACE_WARNS() CHECK(trace_count(</span><span class="Constant">"warn"</span><span class="PreProc">) > </span><span class="Constant">0</span><span class="PreProc">)</span> +<span class="PreProc">#define CHECK_TRACE_DOESNT_WARN() \</span> +<span class="PreProc"> </span>if<span class="PreProc"> (trace_count(</span><span class="Constant">"warn"</span><span class="PreProc">) > </span><span class="Constant">0</span><span class="PreProc">) </span><span class="Delimiter">{</span><span class="PreProc"> \</span> +<span class="PreProc"> ++Num_failures</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> cerr << </span><span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F "</span><span class="PreProc"> << __FUNCTION__ << </span><span class="Constant">"("</span><span class="PreProc"> << </span><span class="Constant">__FILE__</span><span class="PreProc"> << </span><span class="Constant">":"</span><span class="PreProc"> << </span><span class="Constant">__LINE__</span><span class="PreProc"> << </span><span class="Constant">"): unexpected warnings</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> DUMP(</span><span class="Constant">"warn"</span><span class="PreProc">)</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> Passed = </span><span class="Constant">false</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> </span><span class="Identifier">return</span><span class="Delimiter">;</span><span class="PreProc"> \</span> +<span class="PreProc"> </span><span class="Delimiter">}</span> + +bool trace_doesnt_contain<span class="Delimiter">(</span>string layer<span class="Delimiter">,</span> string line<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> trace_count<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> line<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool trace_doesnt_contain<span class="Delimiter">(</span>string expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<string> tmp = split<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">": "</span><span class="Delimiter">);</span> + <span class="Identifier">return</span> trace_doesnt_contain<span class="Delimiter">(</span>tmp[<span class="Constant">0</span>]<span class="Delimiter">,</span> tmp[<span class="Constant">1</span>]<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool trace_doesnt_contain<span class="Delimiter">(</span>string layer<span class="Delimiter">,</span> int frame<span class="Delimiter">,</span> string line<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> trace_count<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> frame<span class="Delimiter">,</span> line<span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="PreProc">#define CHECK_TRACE_DOESNT_CONTAIN(</span><span class="Delimiter">...</span><span class="PreProc">) CHECK(trace_doesnt_contain(__VA_ARGS__))</span> + +^L + +<span class="Comment">// manage layer counts in Trace_stream using RAII</span> +struct lease_trace_frame <span class="Delimiter">{</span> + string layer<span class="Delimiter">;</span> + lease_trace_frame<span class="Delimiter">(</span>string l<span class="Delimiter">)</span> :layer<span class="Delimiter">(</span>l<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + ++Trace_stream<span class="Delimiter">-></span>frame[layer]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + ~lease_trace_frame<span class="Delimiter">()</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + --Trace_stream<span class="Delimiter">-></span>frame[layer]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">};</span> +<span class="PreProc">#define new_trace_frame(layer) lease_trace_frame leased_frame(layer)</span><span class="Delimiter">;</span> + +bool check_trace_contents<span class="Delimiter">(</span>string FUNCTION<span class="Delimiter">,</span> string FILE<span class="Delimiter">,</span> int LINE<span class="Delimiter">,</span> string layer<span class="Delimiter">,</span> int frame<span class="Delimiter">,</span> string expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// multiple layers, hierarchical layers</span> + vector<string> expected_lines = split<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">"^D"</span><span class="Delimiter">);</span> <span class="Comment">// hack: doesn't handle newlines in embedded in lines</span> + index_t curr_expected_line = <span class="Constant">0</span><span class="Delimiter">;</span> + while <span class="Delimiter">(</span>curr_expected_line < expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> && expected_lines[curr_expected_line]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + vector<string> layers = split<span class="Delimiter">(</span>layer<span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!layer<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && !any_prefix_match<span class="Delimiter">(</span>layers<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>first != frame<span class="Delimiter">)</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second != expected_lines[curr_expected_line]<span class="Delimiter">)</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + ++curr_expected_line<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>curr_expected_line < expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">()</span> && expected_lines[curr_expected_line]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + + ++Num_failures<span class="Delimiter">;</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F "</span> << FUNCTION << <span class="Constant">"("</span> << FILE << <span class="Constant">":"</span> << LINE << <span class="Constant">"): missing ["</span> << expected_lines[curr_expected_line] << <span class="Constant">"] in trace/"</span> << frame << <span class="Constant">":</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + DUMP<span class="Delimiter">(</span>layer<span class="Delimiter">);</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="PreProc">#define CHECK_TRACE_TOP(layer</span><span class="Delimiter">,</span><span class="PreProc"> expected) CHECK_TRACE_CONTENTS(layer</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Constant">1</span><span class="Delimiter">,</span><span class="PreProc"> expected)</span> + +^L + +vector<string> split<span class="Delimiter">(</span>string s<span class="Delimiter">,</span> string delim<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<string> result<span class="Delimiter">;</span> + index_t begin=<span class="Constant">0</span><span class="Delimiter">,</span> end=s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">);</span> + while <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>end == NOT_FOUND<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>string<span class="Delimiter">(</span>s<span class="Delimiter">,</span> begin<span class="Delimiter">,</span> NOT_FOUND<span class="Delimiter">));</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>string<span class="Delimiter">(</span>s<span class="Delimiter">,</span> begin<span class="Delimiter">,</span> end-begin<span class="Delimiter">));</span> + begin = end+delim<span class="Delimiter">.</span>size<span class="Delimiter">();</span> + end = s<span class="Delimiter">.</span>find<span class="Delimiter">(</span>delim<span class="Delimiter">,</span> begin<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool any_prefix_match<span class="Delimiter">(</span>const vector<string>& pats<span class="Delimiter">,</span> const string& needle<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>pats<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>*pats[<span class="Constant">0</span>]<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> != <span class="Constant">'/'</span><span class="Delimiter">)</span> + <span class="Comment">// prefix match not requested</span> + <span class="Identifier">return</span> find<span class="Delimiter">(</span>pats<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pats<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> needle<span class="Delimiter">)</span> != pats<span class="Delimiter">.</span>end<span class="Delimiter">();</span> + <span class="Comment">// first pat ends in a '/'; assume all pats do.</span> + for <span class="Delimiter">(</span>vector<string>::const_iterator p = pats<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != pats<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> + if <span class="Delimiter">(</span>headmatch<span class="Delimiter">(</span>needle<span class="Delimiter">,</span> *p<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool prefix_match<span class="Delimiter">(</span>const string& pat<span class="Delimiter">,</span> const string& needle<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>*pat<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> != <span class="Constant">'/'</span><span class="Delimiter">)</span> + <span class="Comment">// prefix match not requested</span> + <span class="Identifier">return</span> pat == needle<span class="Delimiter">;</span> + <span class="Identifier">return</span> headmatch<span class="Delimiter">(</span>needle<span class="Delimiter">,</span> pat<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +bool headmatch<span class="Delimiter">(</span>const string& s<span class="Delimiter">,</span> const string& pat<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>pat<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > s<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> std::mismatch<span class="Delimiter">(</span>pat<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pat<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> s<span class="Delimiter">.</span>begin<span class="Delimiter">()).</span>first == pat<span class="Delimiter">.</span>end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include</span><span class="Constant"><vector></span> +using std::vector<span class="Delimiter">;</span> +<span class="PreProc">#include</span><span class="Constant"><list></span> +using std::list<span class="Delimiter">;</span> +<span class="PreProc">#include</span><span class="Constant"><utility></span> +using std::pair<span class="Delimiter">;</span> +<span class="PreProc">#include</span><span class="Constant"><map></span> +using std::map<span class="Delimiter">;</span> +<span class="PreProc">#include</span><span class="Constant"><set></span> +using std::set<span class="Delimiter">;</span> +<span class="PreProc">#include</span><span class="Constant"><algorithm></span> + +<span class="PreProc">#include</span><span class="Constant"><iostream></span> +using std::istream<span class="Delimiter">;</span> +using std::ostream<span class="Delimiter">;</span> +using std::cin<span class="Delimiter">;</span> +using std::cout<span class="Delimiter">;</span> +using std::cerr<span class="Delimiter">;</span> + +<span class="PreProc">#include</span><span class="Constant"><sstream></span> +using std::istringstream<span class="Delimiter">;</span> +using std::ostringstream<span class="Delimiter">;</span> + +<span class="PreProc">#include</span><span class="Constant"><fstream></span> +using std::ifstream<span class="Delimiter">;</span> +using std::ofstream<span class="Delimiter">;</span> + +<span class="PreProc">#define unused __attribute__((unused))</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/003trace.test.cc.html b/html/003trace.test.cc.html new file mode 100644 index 00000000..d2154cfd --- /dev/null +++ b/html/003trace.test.cc.html @@ -0,0 +1,204 @@ +<!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/003trace.test.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Delimiter { color: #c000c0; } +.Comment { color: #8080ff; } +.Identifier { color: #008080; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +void test_trace_check_compares<span class="Delimiter">()</span> <span class="Delimiter">{</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer"</span><span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_check_filters_layers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_check_ignores_other_lines<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_ignores_trailing_whitespace<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_check_always_finds_empty_lines<span class="Delimiter">()</span> <span class="Delimiter">{</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_check_treats_empty_layers_as_wildcards<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_check_multiple_lines_at_once<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">,</span> <span class="Constant">"foo^Dbar^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_check_always_finds_empty_lines2<span class="Delimiter">()</span> <span class="Delimiter">{</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">"^D^D^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_orders_across_layers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"qux"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">,</span> <span class="Constant">"foo^Dbar^Dqux^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_orders_across_layers2<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"qux"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"foo^Dbar^Dqux^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_checks_ordering_spanning_multiple_layers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"layer1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"layer2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"layer1"</span><span class="Delimiter">)</span> << <span class="Constant">"qux"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"layer1: foo^Dlayer2: bar^Dlayer1: qux^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_segments_within_layers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + new_trace_frame<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"qux"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">"foo^Dqux^D"</span><span class="Delimiter">);</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">"foo^D"</span><span class="Delimiter">);</span> + CHECK_TRACE_DOESNT_CONTAIN<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">"foo^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_checks_ordering_across_layers_and_frames<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + new_trace_frame<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"qux"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1/0: foo^Dtest layer 2: bar^Dtest layer 1: qux"</span><span class="Delimiter">);</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1: foo^Dtest layer 2: bar^Dtest layer 1/1: qux"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void trace_test_fn<span class="Delimiter">(</span>int n<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>n == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + new_trace_frame<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">)</span> << <span class="Constant">"before: "</span> << n<span class="Delimiter">;</span> + trace_test_fn<span class="Delimiter">(</span>n-<span class="Constant">1</span><span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">)</span> << <span class="Constant">"after: "</span> << n<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +void test_trace_keeps_level_together<span class="Delimiter">()</span> <span class="Delimiter">{</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> + trace_test_fn<span class="Delimiter">(</span><span class="Constant">4</span><span class="Delimiter">);</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"foo"</span><span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">"before: 3^Dafter: 3^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_supports_multiple_layers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 2"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"qux"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer 1,test layer 2"</span><span class="Delimiter">,</span> <span class="Constant">"foo^Dbar^Dqux^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_supports_hierarchical_layers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer/a"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"different layer/c"</span><span class="Delimiter">)</span> << <span class="Constant">"foo 2"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer/b"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + CHECK_TRACE_CONTENTS<span class="Delimiter">(</span><span class="Constant">"test layer/"</span><span class="Delimiter">,</span> <span class="Constant">"foo^Dbar^D"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_supports_count<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + CHECK_EQ<span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">,</span> <span class="Constant">"foo"</span><span class="Delimiter">),</span> <span class="Constant">2</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_trace_supports_count2<span class="Delimiter">()</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"foo"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">)</span> << <span class="Constant">"bar"</span><span class="Delimiter">;</span> + CHECK_EQ<span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">"test layer 1"</span><span class="Delimiter">),</span> <span class="Constant">2</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">// pending: DUMP tests</span> +<span class="Comment">// pending: readable_contents() adds newline if necessary.</span> +<span class="Comment">// pending: raise also prints to stderr.</span> +<span class="Comment">// pending: raise doesn't print to stderr if Hide_warnings is set.</span> +<span class="Comment">// pending: raise doesn't have to be saved if Hide_warnings is set, just printed.</span> +<span class="Comment">// pending: raise prints to stderr if Trace_stream is NULL.</span> +<span class="Comment">// pending: raise prints to stderr if Trace_stream is NULL even if Hide_warnings is set.</span> +<span class="Comment">// pending: raise << ... die() doesn't die if Hide_warnings is set.</span> + +^L + +<span class="Comment">// can't check trace because trace methods call 'split'</span> + +void test_split_returns_at_least_one_elem<span class="Delimiter">()</span> <span class="Delimiter">{</span> + vector<string> result = split<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result<span class="Delimiter">.</span>size<span class="Delimiter">(),</span> <span class="Constant">1</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">0</span>]<span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_split_returns_entire_input_when_no_delim<span class="Delimiter">()</span> <span class="Delimiter">{</span> + vector<string> result = split<span class="Delimiter">(</span><span class="Constant">"abc"</span><span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result<span class="Delimiter">.</span>size<span class="Delimiter">(),</span> <span class="Constant">1</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">0</span>]<span class="Delimiter">,</span> <span class="Constant">"abc"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_split_works<span class="Delimiter">()</span> <span class="Delimiter">{</span> + vector<string> result = split<span class="Delimiter">(</span><span class="Constant">"abc,def"</span><span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result<span class="Delimiter">.</span>size<span class="Delimiter">(),</span> <span class="Constant">2</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">0</span>]<span class="Delimiter">,</span> <span class="Constant">"abc"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"def"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_split_works2<span class="Delimiter">()</span> <span class="Delimiter">{</span> + vector<string> result = split<span class="Delimiter">(</span><span class="Constant">"abc,def,ghi"</span><span class="Delimiter">,</span> <span class="Constant">","</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result<span class="Delimiter">.</span>size<span class="Delimiter">(),</span> <span class="Constant">3</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">0</span>]<span class="Delimiter">,</span> <span class="Constant">"abc"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"def"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">2</span>]<span class="Delimiter">,</span> <span class="Constant">"ghi"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void test_split_handles_multichar_delim<span class="Delimiter">()</span> <span class="Delimiter">{</span> + vector<string> result = split<span class="Delimiter">(</span><span class="Constant">"abc,,def,,ghi"</span><span class="Delimiter">,</span> <span class="Constant">",,"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result<span class="Delimiter">.</span>size<span class="Delimiter">(),</span> <span class="Constant">3</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">0</span>]<span class="Delimiter">,</span> <span class="Constant">"abc"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">1</span>]<span class="Delimiter">,</span> <span class="Constant">"def"</span><span class="Delimiter">);</span> + CHECK_EQ<span class="Delimiter">(</span>result[<span class="Constant">2</span>]<span class="Delimiter">,</span> <span class="Constant">"ghi"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/010vm.cc.html b/html/010vm.cc.html new file mode 100644 index 00000000..6622bb86 --- /dev/null +++ b/html/010vm.cc.html @@ -0,0 +1,296 @@ +<!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/010vm.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.SalientComment { color: #00ffff; } +.Identifier { color: #008080; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Delimiter">:(after "Types")</span> +<span class="Comment">// A program is a book of 'recipes' (functions)</span> +typedef size_t recipe_number<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Globals")</span> +map<string<span class="Delimiter">,</span> recipe_number> Recipe_number<span class="Delimiter">;</span> +map<recipe_number<span class="Delimiter">,</span> recipe> Recipe<span class="Delimiter">;</span> +recipe_number Next_recipe_number = <span class="Constant">1</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Types")</span> +<span class="Comment">// Recipes are lists of instructions. To run a recipe, the computer runs its</span> +<span class="Comment">// instructions.</span> +struct recipe <span class="Delimiter">{</span> + string name<span class="Delimiter">;</span> + vector<instruction> steps<span class="Delimiter">;</span> + <span class="Comment">// End recipe Fields</span> +<span class="Delimiter">};</span> + +<span class="Delimiter">:(before "struct recipe")</span> +<span class="Comment">// Each instruction is either of the form:</span> +<span class="Comment">// product1, product2, product3, ... <- operation ingredient1, ingredient2, ingredient3, ...</span> +<span class="Comment">// or just a single 'label' starting with a non-alphanumeric character</span> +<span class="Comment">// +label</span> +<span class="Comment">// Labels don't do anything, they're just waypoints.</span> +struct instruction <span class="Delimiter">{</span> + bool is_label<span class="Delimiter">;</span> + string label<span class="Delimiter">;</span> <span class="Comment">// only if is_label</span> + string name<span class="Delimiter">;</span> <span class="Comment">// only if !is_label</span> + recipe_number operation<span class="Delimiter">;</span> <span class="Comment">// Recipe_number[name]</span> + vector<reagent> ingredients<span class="Delimiter">;</span> <span class="Comment">// only if !is_label</span> + vector<reagent> products<span class="Delimiter">;</span> <span class="Comment">// only if !is_label</span> + instruction<span class="Delimiter">();</span> + void clear<span class="Delimiter">();</span> + string to_string<span class="Delimiter">()</span> const<span class="Delimiter">;</span> +<span class="Delimiter">};</span> + +<span class="Delimiter">:(before "struct instruction")</span> +<span class="Comment">// Ingredients and products are a single species -- a reagent. Reagents refer</span> +<span class="Comment">// either to numbers or to locations in memory along with 'type' tags telling</span> +<span class="Comment">// us how to interpret them. They also can contain arbitrary other lists of</span> +<span class="Comment">// properties besides types, but we're getting ahead of ourselves.</span> +struct reagent <span class="Delimiter">{</span> + vector<pair<string<span class="Delimiter">,</span> vector<string> > > properties<span class="Delimiter">;</span> + string name<span class="Delimiter">;</span> + long long int value<span class="Delimiter">;</span> + bool initialized<span class="Delimiter">;</span> + vector<type_number> types<span class="Delimiter">;</span> + reagent<span class="Delimiter">(</span>string s<span class="Delimiter">);</span> + reagent<span class="Delimiter">();</span> + void set_value<span class="Delimiter">(</span>long long int v<span class="Delimiter">)</span> <span class="Delimiter">{</span> value = v<span class="Delimiter">;</span> initialized = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + string to_string<span class="Delimiter">()</span> const<span class="Delimiter">;</span> +<span class="Delimiter">};</span> + +<span class="Delimiter">:(before "struct reagent")</span> +struct property <span class="Delimiter">{</span> + vector<string> values<span class="Delimiter">;</span> +<span class="Delimiter">};</span> + +<span class="Delimiter">:(before "End Globals")</span> +<span class="Comment">// Locations refer to a common 'memory'. Each location can store a number.</span> +map<index_t<span class="Delimiter">,</span> long long int> Memory<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +Memory<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + +<span class="Delimiter">:(after "Types")</span> +<span class="Comment">// Mu types encode how the numbers stored in different parts of memory are</span> +<span class="Comment">// interpreted. A location tagged as a 'character' type will interpret the</span> +<span class="Comment">// number 97 as the letter 'a', while a different location of type 'integer'</span> +<span class="Comment">// would not.</span> +<span class="Comment">//</span> +<span class="Comment">// Unlike most computers today, mu stores types in a single big table, shared</span> +<span class="Comment">// by all the mu programs on the computer. This is useful in providing a</span> +<span class="Comment">// seamless experience to help understand arbitrary mu programs.</span> +typedef size_t type_number<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Globals")</span> +map<string<span class="Delimiter">,</span> type_number> Type_number<span class="Delimiter">;</span> +map<type_number<span class="Delimiter">,</span> type_info> Type<span class="Delimiter">;</span> +type_number Next_type_number = <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +void setup_types<span class="Delimiter">()</span> <span class="Delimiter">{</span> + Type<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> Type_number<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + Type_number[<span class="Constant">"literal"</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> + Next_type_number = <span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Comment">// Mu Types Initialization</span> + type_number integer = Type_number[<span class="Constant">"integer"</span>] = Next_type_number++<span class="Delimiter">;</span> + Type_number[<span class="Constant">"location"</span>] = Type_number[<span class="Constant">"integer"</span>]<span class="Delimiter">;</span> <span class="Comment">// wildcard type: either a pointer or a scalar</span> + Type[integer]<span class="Delimiter">.</span>name = <span class="Constant">"integer"</span><span class="Delimiter">;</span> + type_number address = Type_number[<span class="Constant">"address"</span>] = Next_type_number++<span class="Delimiter">;</span> + Type[address]<span class="Delimiter">.</span>name = <span class="Constant">"address"</span><span class="Delimiter">;</span> + type_number boolean = Type_number[<span class="Constant">"boolean"</span>] = Next_type_number++<span class="Delimiter">;</span> + Type[boolean]<span class="Delimiter">.</span>name = <span class="Constant">"boolean"</span><span class="Delimiter">;</span> + type_number character = Type_number[<span class="Constant">"character"</span>] = Next_type_number++<span class="Delimiter">;</span> + Type[character]<span class="Delimiter">.</span>name = <span class="Constant">"character"</span><span class="Delimiter">;</span> + <span class="Comment">// Array types are a special modifier to any other type. For example,</span> + <span class="Comment">// array:integer or array:address:boolean.</span> + type_number array = Type_number[<span class="Constant">"array"</span>] = Next_type_number++<span class="Delimiter">;</span> + Type[array]<span class="Delimiter">.</span>name = <span class="Constant">"array"</span><span class="Delimiter">;</span> + <span class="Comment">// End Mu Types Initialization</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End One-time Setup")</span> +setup_types<span class="Delimiter">();</span> + +<span class="Delimiter">:(before "End Types")</span> +<span class="Comment">// You can construct arbitrary new types. New types are either 'containers'</span> +<span class="Comment">// with multiple 'elements' of other types, or 'exclusive containers' containing</span> +<span class="Comment">// one of multiple 'variants'. (These are similar to C structs and unions,</span> +<span class="Comment">// respectively, though exclusive containers implicitly include a tag element</span> +<span class="Comment">// recording which variant they should be interpreted as.)</span> +<span class="Comment">//</span> +<span class="Comment">// For example, storing bank balance and name for an account might require a</span> +<span class="Comment">// container, but if bank accounts may be either for individuals or groups,</span> +<span class="Comment">// with different properties for each, that may require an exclusive container</span> +<span class="Comment">// whose variants are individual-account and joint-account containers.</span> +enum kind_of_type <span class="Delimiter">{</span> + primitive<span class="Delimiter">,</span> + container<span class="Delimiter">,</span> + exclusive_container +<span class="Delimiter">};</span> + +struct type_info <span class="Delimiter">{</span> + string name<span class="Delimiter">;</span> + kind_of_type kind<span class="Delimiter">;</span> + size_t size<span class="Delimiter">;</span> <span class="Comment">// only if type is not primitive; primitives and addresses have size 1 (except arrays are dynamic)</span> + vector<vector<type_number> > elements<span class="Delimiter">;</span> + vector<string> element_names<span class="Delimiter">;</span> + <span class="Comment">// End type_info Fields</span> + type_info<span class="Delimiter">()</span> :kind<span class="Delimiter">(</span>primitive<span class="Delimiter">),</span> size<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> +<span class="Delimiter">};</span> + +enum primitive_recipes <span class="Delimiter">{</span> + IDLE = <span class="Constant">0</span><span class="Delimiter">,</span> + COPY<span class="Delimiter">,</span> + <span class="Comment">// End Primitive Recipe Declarations</span> + MAX_PRIMITIVE_RECIPES<span class="Delimiter">,</span> +<span class="Delimiter">};</span> +<span class="Delimiter">:(code)</span> +<span class="Comment">//: It's all very well to construct recipes out of other recipes, but we need</span> +<span class="Comment">//: to know how to do *something* out of the box. For the following</span> +<span class="Comment">//: recipes there are only codes, no entries in the book, because mu just knows</span> +<span class="Comment">//: what to do for them.</span> +void setup_recipes<span class="Delimiter">()</span> <span class="Delimiter">{</span> + Recipe<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> Recipe_number<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + Recipe_number[<span class="Constant">"idle"</span>] = IDLE<span class="Delimiter">;</span> + <span class="Comment">// Primitive Recipe Numbers</span> + Recipe_number[<span class="Constant">"copy"</span>] = COPY<span class="Delimiter">;</span> + <span class="Comment">// End Primitive Recipe Numbers</span> +<span class="Delimiter">}</span> +<span class="Comment">//: We could just reset the recipe table after every test, but that gets slow</span> +<span class="Comment">//: all too quickly. Instead, initialize the common stuff just once at</span> +<span class="Comment">//: startup. Later layers will carefully undo each test's additions after</span> +<span class="Comment">//: itself.</span> +<span class="Delimiter">:(before "End One-time Setup")</span> +setup_recipes<span class="Delimiter">();</span> +assert<span class="Delimiter">(</span>MAX_PRIMITIVE_RECIPES < <span class="Constant">100</span><span class="Delimiter">);</span> <span class="Comment">// level 0 is primitives; until 99</span> +Next_recipe_number = <span class="Constant">100</span><span class="Delimiter">;</span> +<span class="Comment">// End Load Recipes</span> +<span class="Delimiter">:(before "End Test Run Initialization")</span> +assert<span class="Delimiter">(</span>Next_recipe_number < <span class="Constant">1000</span><span class="Delimiter">);</span> <span class="Comment">// functions being tested didn't overflow into test space</span> +<span class="Delimiter">:(before "End Setup")</span> +Next_recipe_number = <span class="Constant">1000</span><span class="Delimiter">;</span> <span class="Comment">// consistent new numbers for each test</span> + +^L + +<span class="SalientComment">//:: Helpers</span> + +<span class="Delimiter">:(code)</span> +instruction::instruction<span class="Delimiter">()</span> :is_label<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">),</span> operation<span class="Delimiter">(</span>IDLE<span class="Delimiter">)</span> <span class="Delimiter">{}</span> +void instruction::clear<span class="Delimiter">()</span> <span class="Delimiter">{</span> is_label=<span class="Constant">false</span><span class="Delimiter">;</span> label<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> operation=IDLE<span class="Delimiter">;</span> ingredients<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> products<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">}</span> + +<span class="Comment">// Reagents have the form <name>:<type>:<type>:.../<property>/<property>/...</span> +reagent::reagent<span class="Delimiter">(</span>string s<span class="Delimiter">)</span> :value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> initialized<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + istringstream in<span class="Delimiter">(</span>s<span class="Delimiter">);</span> + in >> std::noskipws<span class="Delimiter">;</span> + <span class="Comment">// properties</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + istringstream row<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">'/'</span><span class="Delimiter">));</span> + row >> std::noskipws<span class="Delimiter">;</span> + string name = slurp_until<span class="Delimiter">(</span>row<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span> + vector<string> values<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!row<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> + values<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>row<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span>name<span class="Delimiter">,</span> values<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Comment">// structures for the first row of properties</span> + name = properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>first<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>second<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_number[properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>second[i]]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>name == <span class="Constant">"_"</span> && types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>second<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"dummy"</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +reagent::reagent<span class="Delimiter">()</span> :value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> initialized<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// The first property is special, so ensure we always have it.</span> + <span class="Comment">// Other properties can be pushed back, but the first must always be</span> + <span class="Comment">// assigned to.</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">,</span> vector<string><span class="Delimiter">()));</span> +<span class="Delimiter">}</span> +string reagent::to_string<span class="Delimiter">()</span> const <span class="Delimiter">{</span> + ostringstream out<span class="Delimiter">;</span> + out << <span class="Constant">"{name: </span><span class="cSpecial">\"</span><span class="Constant">"</span> << name << <span class="Constant">"</span><span class="cSpecial">\"</span><span class="Constant">, value: "</span> << value << <span class="Constant">", type: "</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < types<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << types[i]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>i < types<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">)</span> out << <span class="Constant">"-"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!properties<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + out << <span class="Constant">", properties: ["</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < properties<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << <span class="Constant">"</span><span class="cSpecial">\"</span><span class="Constant">"</span> << properties[i]<span class="Delimiter">.</span>first << <span class="Constant">"</span><span class="cSpecial">\"</span><span class="Constant">: "</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t j = <span class="Constant">0</span><span class="Delimiter">;</span> j < properties[i]<span class="Delimiter">.</span>second<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << <span class="Constant">"</span><span class="cSpecial">\"</span><span class="Constant">"</span> << properties[i]<span class="Delimiter">.</span>second[j] << <span class="Constant">"</span><span class="cSpecial">\"</span><span class="Constant">"</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>j < properties[i]<span class="Delimiter">.</span>second<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">)</span> out << <span class="Constant">":"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>i < properties<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">)</span> out << <span class="Constant">", "</span><span class="Delimiter">;</span> + else out << <span class="Constant">"]"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + out << <span class="Constant">"}"</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +string instruction::to_string<span class="Delimiter">()</span> const <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_label<span class="Delimiter">)</span> <span class="Identifier">return</span> label<span class="Delimiter">;</span> + ostringstream out<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < products<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>i > <span class="Constant">0</span><span class="Delimiter">)</span> out << <span class="Constant">", "</span><span class="Delimiter">;</span> + out << products[i]<span class="Delimiter">.</span>to_string<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>!products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> out << <span class="Constant">" <- "</span><span class="Delimiter">;</span> + out << name << <span class="Constant">'/'</span> << operation << <span class="Constant">' '</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < ingredients<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>i > <span class="Constant">0</span><span class="Delimiter">)</span> out << <span class="Constant">", "</span><span class="Delimiter">;</span> + out << ingredients[i]<span class="Delimiter">.</span>to_string<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +string slurp_until<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> char delim<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ostringstream out<span class="Delimiter">;</span> + char c<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>in >> c<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>c == delim<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// drop the delim</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + out << c<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +void dump_memory<span class="Delimiter">()</span> <span class="Delimiter">{</span> + map<int<span class="Delimiter">,</span> int> ordered<span class="Delimiter">(</span>Memory<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> Memory<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + for <span class="Delimiter">(</span>map<int<span class="Delimiter">,</span> int>::iterator p = ordered<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != ordered<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + cout << p<span class="Delimiter">-></span>first << <span class="Constant">": "</span> << p<span class="Delimiter">-></span>second << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include </span><span class="Constant"><map></span> +using std::map<span class="Delimiter">;</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/011load.cc.html b/html/011load.cc.html new file mode 100644 index 00000000..1928668e --- /dev/null +++ b/html/011load.cc.html @@ -0,0 +1,355 @@ +<!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/011load.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; } +.cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Phase 1 of running mu code: load it from a textual representation.</span> + +<span class="Delimiter">:(scenarios load)</span> +<span class="Delimiter">:(scenario first_recipe)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> + +<span class="Delimiter">:(code)</span> +vector<recipe_number> load<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> + istringstream in<span class="Delimiter">(</span>form<span class="Delimiter">);</span> + in >> std::noskipws<span class="Delimiter">;</span> + <span class="Identifier">return</span> load<span class="Delimiter">(</span>in<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +vector<recipe_number> load<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<recipe_number> result<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + string command = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Comment">// Command Handlers</span> + if <span class="Delimiter">(</span>command == <span class="Constant">"recipe"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string recipe_name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>recipe_name<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + raise << <span class="Constant">"empty recipe name</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Recipe_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>recipe_name<span class="Delimiter">)</span> == Recipe_number<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Recipe_number[recipe_name] = Next_recipe_number++<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Recipe_number[recipe_name]<span class="Delimiter">)</span> != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"redefining recipe "</span> << Recipe[Recipe_number[recipe_name]]<span class="Delimiter">.</span>name << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe_number[recipe_name]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + Recipe[Recipe_number[recipe_name]] = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + Recipe[Recipe_number[recipe_name]]<span class="Delimiter">.</span>name = recipe_name<span class="Delimiter">;</span> + <span class="Comment">// track added recipes because we may need to undo them in tests; see below</span> + recently_added_recipes<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Recipe_number[recipe_name]<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Recipe_number[recipe_name]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Command Handlers</span> + else <span class="Delimiter">{</span> + raise << <span class="Constant">"unknown top-level command: "</span> << command << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +recipe slurp_recipe<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe result<span class="Delimiter">;</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> + raise << <span class="Constant">"recipe body must begin with '['</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + instruction curr<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>next_instruction<span class="Delimiter">(</span>in<span class="Delimiter">,</span> &curr<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// End Rewrite Instruction(curr)</span> + result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool next_instruction<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> instruction* curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + curr<span class="Delimiter">-></span>clear<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + + vector<string> words<span class="Delimiter">;</span> +<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> + while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? show_rest_of_stream(in); //? 1</span> + string word = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + words<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>word<span class="Delimiter">);</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + +<span class="CommentedCode">//? if (words.size() == 1) cout << words[0] << ' ' << words[0].size() << '\n'; //? 1</span> + if <span class="Delimiter">(</span>words<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span> && words[<span class="Constant">0</span>] == <span class="Constant">"]"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA\n"; //? 1</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// end of recipe</span> + <span class="Delimiter">}</span> + + if <span class="Delimiter">(</span>words<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span> && !isalnum<span class="Delimiter">(</span>words[<span class="Constant">0</span>][<span class="Constant">0</span>]<span class="Delimiter">)</span> && words[<span class="Constant">0</span>][<span class="Constant">0</span>] != <span class="Constant">'$'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + curr<span class="Delimiter">-></span>is_label = <span class="Constant">true</span><span class="Delimiter">;</span> + curr<span class="Delimiter">-></span>label = words[<span class="Constant">0</span>]<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"label: "</span> << curr<span class="Delimiter">-></span>label<span class="Delimiter">;</span> + <span class="Identifier">return</span> !in<span class="Delimiter">.</span>eof<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + + vector<string>::iterator p = words<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>find<span class="Delimiter">(</span>words<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> words<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> <span class="Constant">"<-"</span><span class="Delimiter">)</span> != words<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(;</span> *p != <span class="Constant">"<-"</span><span class="Delimiter">;</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>*p == <span class="Constant">","</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + curr<span class="Delimiter">-></span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>*p<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + ++p<span class="Delimiter">;</span> <span class="Comment">// skip <-</span> + <span class="Delimiter">}</span> + + curr<span class="Delimiter">-></span>name = *p<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Recipe_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>*p<span class="Delimiter">)</span> == Recipe_number<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Recipe_number[*p] = Next_recipe_number++<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "AAA: " << *p << " is now " << Recipe_number[*p] << '\n'; //? 1</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>Recipe_number[*p] == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"Recipe "</span> << *p << <span class="Constant">" has number 0, which is reserved for IDLE.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << die<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + curr<span class="Delimiter">-></span>operation = Recipe_number[*p]<span class="Delimiter">;</span> ++p<span class="Delimiter">;</span> + + for <span class="Delimiter">(;</span> p != words<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>*p == <span class="Constant">","</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + curr<span class="Delimiter">-></span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>*p<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"instruction: "</span> << curr<span class="Delimiter">-></span>name<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>vector<reagent>::iterator p = curr<span class="Delimiter">-></span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != curr<span class="Delimiter">-></span>ingredients<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">" ingredient: "</span> << p<span class="Delimiter">-></span>to_string<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>vector<reagent>::iterator p = curr<span class="Delimiter">-></span>products<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != curr<span class="Delimiter">-></span>products<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">" product: "</span> << p<span class="Delimiter">-></span>to_string<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> !in<span class="Delimiter">.</span>eof<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +string next_word<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA next_word\n"; //? 1</span> + ostringstream out<span class="Delimiter">;</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + slurp_word<span class="Delimiter">(</span>in<span class="Delimiter">,</span> out<span class="Delimiter">);</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +void slurp_word<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA slurp_word\n"; //? 1</span> + char c<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + in >> c<span class="Delimiter">;</span> + out << c<span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + while <span class="Delimiter">(</span>in >> c<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << c << '\n'; //? 1</span> + if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>c<span class="Delimiter">)</span> || c == <span class="Constant">','</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + in<span class="Delimiter">.</span>putback<span class="Delimiter">(</span>c<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + out << c<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void skip_whitespace<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">())</span> && in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void skip_whitespace_and_comments<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + while <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>isspace<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()))</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + else if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + else <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void skip_comment<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'#'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + while <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void skip_comma<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">','</span><span class="Delimiter">)</span> in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">// for debugging</span> +<span class="Delimiter">:(before "End Globals")</span> +bool Show_rest_of_stream = <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +void show_rest_of_stream<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!Show_rest_of_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + cerr << <span class="Constant">'^'</span><span class="Delimiter">;</span> + char c<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>in >> c<span class="Delimiter">)</span> <span class="Delimiter">{</span> + cerr << c<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + cerr << <span class="Constant">"$</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Have tests clean up any recipes they added.</span> +<span class="Delimiter">:(before "End Globals")</span> +vector<recipe_number> recently_added_recipes<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < recently_added_recipes<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA clearing " << Recipe[recently_added_recipes[i]].name << '\n'; //? 2</span> + Recipe_number<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe[recently_added_recipes[i]]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_recipes[i]<span class="Delimiter">);</span> +<span class="Delimiter">}</span> +<span class="Comment">// Clear Other State For recently_added_recipes</span> +recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + +<span class="Delimiter">:(scenario parse_comment_outside_recipe)</span> +<span class="Comment"># this comment will be dropped by the tangler, so we need a dummy recipe to stop that</span> +recipe f1 [ ] +<span class="Comment"># this comment will go through to 'load'</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_comment_amongst_instruction)</span> +recipe main [ + <span class="Comment"># comment</span> + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_comment_amongst_instruction2)</span> +recipe main [ + <span class="Comment"># comment</span> + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + <span class="Comment"># comment</span> +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_comment_amongst_instruction3)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + <span class="Comment"># comment</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_comment_after_instruction)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal <span class="Comment"># comment</span> +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_label)</span> +recipe main [ + +foo +] +<span class="traceContains">+parse: label: +foo</span> + +<span class="Delimiter">:(scenario parse_dollar_as_recipe_name)</span> +recipe main [ + $foo +] +<span class="traceContains">+parse: instruction: $foo</span> + +<span class="Delimiter">:(scenario parse_multiple_properties)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal/foo:bar:baz +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal", "foo": "bar":"baz"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_multiple_products)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> +<span class="traceContains">+parse: product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_multiple_ingredients)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal<span class="Delimiter">,</span> <span class="Constant">4</span>:integer +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: ingredient: {name: "4", value: 0, type: 1, properties: ["4": "integer"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> +<span class="traceContains">+parse: product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}</span> + +<span class="Delimiter">:(scenario parse_multiple_types)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:address:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal<span class="Delimiter">,</span> <span class="Constant">4</span>:integer +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "23", value: 0, type: 0, properties: ["23": "literal"]}</span> +<span class="traceContains">+parse: ingredient: {name: "4", value: 0, type: 1, properties: ["4": "integer"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}</span> +<span class="traceContains">+parse: product: {name: "2", value: 0, type: 2-1, properties: ["2": "address":"integer"]}</span> + +<span class="Delimiter">:(scenario parse_properties)</span> +recipe main [ + <span class="Constant">1</span>:integer:address/deref<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 1-2, properties: ["1": "integer":"address", "deref": ]}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/012transform.cc.html b/html/012transform.cc.html new file mode 100644 index 00000000..87650650 --- /dev/null +++ b/html/012transform.cc.html @@ -0,0 +1,91 @@ +<!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/012transform.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; } +.cSpecial { color: #008000; } +.Identifier { color: #008080; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Phase 2: Filter loaded recipes through an extensible list of 'transforms'.</span> +<span class="Comment">//:</span> +<span class="Comment">//: The hope is that this framework of transform tools will provide a</span> +<span class="Comment">//: deconstructed alternative to conventional compilers.</span> + +<span class="Delimiter">:(before "End recipe Fields")</span> +index_t transformed_until<span class="Delimiter">;</span> + recipe<span class="Delimiter">()</span> :transformed_until<span class="Delimiter">(</span>-<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + +<span class="Delimiter">:(before "End Types")</span> +typedef void <span class="Delimiter">(</span>*transform_fn<span class="Delimiter">)(</span>recipe_number<span class="Delimiter">);</span> + +<span class="Delimiter">:(before "End Globals")</span> +vector<transform_fn> Transform<span class="Delimiter">;</span> + +<span class="Delimiter">:(code)</span> +void transform_all<span class="Delimiter">()</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA transform_all\n"; //? 1</span> + for <span class="Delimiter">(</span>index_t t = <span class="Constant">0</span><span class="Delimiter">;</span> t < Transform<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++t<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>map<recipe_number<span class="Delimiter">,</span> recipe>::iterator p = Recipe<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe& r = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>transformed_until != t-<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">(</span>*Transform[t]<span class="Delimiter">)(</span><span class="Comment">/*</span><span class="Comment">recipe_number</span><span class="Comment">*/</span>p<span class="Delimiter">-></span>first<span class="Delimiter">);</span> + r<span class="Delimiter">.</span>transformed_until = t<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + parse_int_reagents<span class="Delimiter">();</span> <span class="Comment">// do this after all other transforms have run</span> +<span class="Delimiter">}</span> + +void parse_int_reagents<span class="Delimiter">()</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "parse_int_reagents\n"; //? 1</span> + for <span class="Delimiter">(</span>map<recipe_number<span class="Delimiter">,</span> recipe>::iterator p = Recipe<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + recipe& r = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t index = <span class="Constant">0</span><span class="Delimiter">;</span> index < r<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction& inst = r<span class="Delimiter">.</span>steps[index]<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + populate_value<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + populate_value<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void populate_value<span class="Delimiter">(</span>reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + char* end = <span class="Constant">NULL</span><span class="Delimiter">;</span> + int result = strtol<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> &end<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">any base</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>*end != <span class="cSpecial">'\0'</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "setting value\n"; //? 1</span> + r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>result<span class="Delimiter">);</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/013literal_string.cc.html b/html/013literal_string.cc.html new file mode 100644 index 00000000..61f6105b --- /dev/null +++ b/html/013literal_string.cc.html @@ -0,0 +1,115 @@ +<!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/013literal_string.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; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: For convenience, some instructions will take literal arrays of characters (strings).</span> +<span class="Comment">//:</span> +<span class="Comment">//: Instead of quotes, we'll use [] to delimit strings. That'll reduce the</span> +<span class="Comment">//: need for escaping since we can support nested brackets. And we can also</span> +<span class="Comment">//: imagine that 'recipe' might one day itself be defined in mu, doing its own</span> +<span class="Comment">//: parsing.</span> + +<span class="Delimiter">:(scenarios load)</span> +<span class="Delimiter">:(scenario string_literal)</span> +recipe main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>copy [abc def] <span class="Comment"># copy can't really take a string</span> +] +<span class="traceContains">+parse: ingredient: {name: "abc def", value: 0, type: 0, properties: ["abc def": "literal-string"]}</span> + +<span class="Delimiter">:(scenario string_literal_with_colons)</span> +recipe main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>copy [abc:def/ghi] +] +<span class="traceContains">+parse: ingredient: {name: "abc:def/ghi", value: 0, type: 0, properties: ["abc:def/ghi": "literal-string"]}</span> + +<span class="Delimiter">:(before "End Mu Types Initialization")</span> +Type_number[<span class="Constant">"literal-string"</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(after "string next_word(istream& in)")</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string result = slurp_quoted<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_comment<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +string slurp_quoted<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span> + assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> == <span class="Constant">'['</span><span class="Delimiter">);</span> + ostringstream out<span class="Delimiter">;</span> + int size = <span class="Constant">0</span><span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + char c = in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> +<span class="CommentedCode">//? cout << c << '\n'; //? 1</span> + out << c<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << out.str() << "$\n"; //? 1</span> + if <span class="Delimiter">(</span>c == <span class="Constant">'['</span><span class="Delimiter">)</span> ++size<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>c == <span class="Constant">']'</span><span class="Delimiter">)</span> --size<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>size == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after "reagent::reagent(string s)")</span> +<span class="CommentedCode">//? cout << s[0] << '\n'; //? 1</span> + if <span class="Delimiter">(</span>s[<span class="Constant">0</span>] == <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>s[s<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span>] == <span class="Constant">']'</span><span class="Delimiter">);</span> + <span class="Comment">// delete [] delimiters</span> + s<span class="Delimiter">.</span>erase<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> + s<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>s<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">,</span> s<span class="Delimiter">.</span>size<span class="Delimiter">());</span> + name = s<span class="Delimiter">;</span> + types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span>name<span class="Delimiter">,</span> vector<string><span class="Delimiter">()));</span> + properties<span class="Delimiter">.</span>back<span class="Delimiter">().</span>second<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"literal-string"</span><span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario string_literal_nested)</span> +recipe main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>copy [abc [def]] +] +<span class="traceContains">+parse: ingredient: {name: "abc [def]", value: 0, type: 0, properties: ["abc [def]": "literal-string"]}</span> + +<span class="Delimiter">:(scenario string_literal_and_comment)</span> +recipe main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>copy [abc] <span class="Comment"># comment</span> +] +<span class="traceContains">+parse: instruction: copy</span> +<span class="traceContains">+parse: ingredient: {name: "abc", value: 0, type: 0, properties: ["abc": "literal-string"]}</span> +<span class="traceContains">+parse: product: {name: "1", value: 0, type: 2-5-4, properties: ["1": "address":"array":"character"]}</span> +<span class="Comment"># no other ingredients</span> +$parse: <span class="Constant">3</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/014types.cc.html b/html/014types.cc.html new file mode 100644 index 00000000..a76c616c --- /dev/null +++ b/html/014types.cc.html @@ -0,0 +1,134 @@ +<!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/014types.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; } +.cSpecial { color: #008000; } +.Identifier { color: #008080; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.SalientComment { color: #00ffff; } +.CommentedCode { color: #6c6c6c; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Textual form for types.</span> + +<span class="Delimiter">:(scenarios load)</span> +<span class="Delimiter">:(scenario container)</span> +container foo [ + x:integer + y:integer +] +<span class="traceContains">+parse: reading 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 "End Command Handlers")</span> +else if <span class="Delimiter">(</span>command == <span class="Constant">"container"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> container<span class="Delimiter">,</span> in<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void insert_container<span class="Delimiter">(</span>const string& command<span class="Delimiter">,</span> kind_of_type kind<span class="Delimiter">,</span> istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + string name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"reading "</span> << command << <span class="Constant">' '</span> << name<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << name << '\n'; //? 1</span> + assert<span class="Delimiter">(</span>Type_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>name<span class="Delimiter">)</span> == Type_number<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + Type_number[name] = Next_type_number++<span class="Delimiter">;</span> + skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">"'container' must begin with '['"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>Type<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Type_number[name]<span class="Delimiter">)</span> == Type<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + type_info& t = Type[Type_number[name]]<span class="Delimiter">;</span> + recently_added_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_number[name]<span class="Delimiter">);</span> + t<span class="Delimiter">.</span>name = name<span class="Delimiter">;</span> + t<span class="Delimiter">.</span>kind = kind<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + string element = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>element == <span class="Constant">"]"</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + istringstream inner<span class="Delimiter">(</span>element<span class="Delimiter">);</span> + t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">" element name: "</span> << t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>back<span class="Delimiter">();</span> + vector<type_number> types<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!inner<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span> + string type_name = slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>Type_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> == Type_number<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + raise << <span class="Constant">"unknown type "</span> << type_name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_number[type_name]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">" type: "</span> << types<span class="Delimiter">.</span>back<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>types<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>size<span class="Delimiter">());</span> + t<span class="Delimiter">.</span>size = t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>size<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Similarly for exclusive_container.</span> + +<span class="Delimiter">:(scenario exclusive_container)</span> +exclusive-container foo [ + x:integer + y:integer +] +<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 "End Command Handlers")</span> +else if <span class="Delimiter">(</span>command == <span class="Constant">"exclusive-container"</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> + +<span class="SalientComment">//:: ensure types created in one scenario don't leak outside it.</span> +<span class="Delimiter">:(before "End Globals")</span> +vector<type_number> recently_added_types<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < recently_added_types<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "erasing " << Type[recently_added_types[i]].name << '\n'; //? 1</span> + Type_number<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Type[recently_added_types[i]]<span class="Delimiter">.</span>name<span class="Delimiter">);</span> + Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types[i]<span class="Delimiter">);</span> +<span class="Delimiter">}</span> +recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Comment">//: lastly, ensure scenarios are consistent by always starting them at the</span> +<span class="Comment">//: same type number.</span> +Next_type_number = <span class="Constant">1000</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Test Run Initialization")</span> +assert<span class="Delimiter">(</span>Next_type_number < <span class="Constant">1000</span><span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Setup")</span> +Next_type_number = <span class="Constant">1000</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(code)</span> +void skip_bracket<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> string message<span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span> + raise << message << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/020run.cc.html b/html/020run.cc.html new file mode 100644 index 00000000..9f16cdce --- /dev/null +++ b/html/020run.cc.html @@ -0,0 +1,246 @@ +<!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/020run.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; } +.cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } +.SalientComment { color: #00ffff; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +.traceAbsent { color: #c00000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Phase 3: Start running a loaded and transformed recipe.</span> +<span class="Comment">//:</span> +<span class="Comment">//: So far we've seen recipes as lists of instructions, and instructions point</span> +<span class="Comment">//: at other recipes. To kick things off mu needs to know how to run certain</span> +<span class="Comment">//: 'primitive' recipes. That will then give the ability to run recipes</span> +<span class="Comment">//: containing these primitives.</span> +<span class="Comment">//:</span> +<span class="Comment">//: This layer defines a skeleton with just two primitive recipes: IDLE which</span> +<span class="Comment">//: does nothing, and COPY, which can copy numbers from one memory location to</span> +<span class="Comment">//: another. Later layers will add more primitives.</span> + +<span class="Delimiter">:(scenario copy_literal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 23</span> +<span class="traceContains">+mem: storing 23 in location 1</span> + +<span class="Delimiter">:(scenario copy)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:integer +] +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 23</span> +<span class="traceContains">+mem: storing 23 in location 2</span> + +<span class="Delimiter">:(before "End Types")</span> +<span class="Comment">// Book-keeping while running a recipe.</span> +<span class="Comment">//: Later layers will change this.</span> +struct routine <span class="Delimiter">{</span> + recipe_number running_recipe<span class="Delimiter">;</span> + index_t running_step_index<span class="Delimiter">;</span> + routine<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> :running_recipe<span class="Delimiter">(</span>r<span class="Delimiter">),</span> running_step_index<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + bool completed<span class="Delimiter">()</span> const<span class="Delimiter">;</span> +<span class="Delimiter">};</span> + +<span class="Delimiter">:(before "End Globals")</span> +routine* Current_routine = <span class="Constant">NULL</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(code)</span> +void run<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + routine rr<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + Current_routine = &rr<span class="Delimiter">;</span> + run_current_routine<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +void run_current_routine<span class="Delimiter">()</span> +<span class="Delimiter">{</span> <span class="Comment">// curly on a separate line, because later layers will modify header</span> + while <span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>completed<span class="Delimiter">())</span> <span class="Comment">// later layers will modify condition</span> + <span class="Delimiter">{</span> + <span class="Comment">// Running One Instruction.</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> ++current_step_index<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"instruction "</span> << current_recipe_name<span class="Delimiter">()</span> << <span class="Constant">'/'</span> << current_step_index<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">();</span> +<span class="CommentedCode">//? cout << "operation " << current_instruction().operation << '\n'; //? 3</span> + switch <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// Primitive Recipe Implementations</span> + case COPY: <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> + vector<long long int> data = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</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> data<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Primitive Recipe Implementations</span> + default: <span class="Delimiter">{</span> + cout << <span class="Constant">"not a primitive op: "</span> << current_instruction<span class="Delimiter">().</span>operation << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + ++current_step_index<span class="Delimiter">();</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Some helpers.</span> +<span class="Comment">//: We'll need to override these later as we change the definition of routine.</span> +<span class="Comment">//: Important that they return referrences into the routine.</span> + +inline index_t& current_step_index<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Current_routine<span class="Delimiter">-></span>running_step_index<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +inline const string& current_recipe_name<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-></span>running_recipe]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +inline const instruction& current_instruction<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-></span>running_recipe]<span class="Delimiter">.</span>steps[Current_routine<span class="Delimiter">-></span>running_step_index]<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +inline bool routine::completed<span class="Delimiter">()</span> const <span class="Delimiter">{</span> + <span class="Identifier">return</span> running_step_index >= Recipe[running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Commandline Parsing")</span> +if <span class="Delimiter">(</span>argc > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>int i = <span class="Constant">1</span><span class="Delimiter">;</span> i < argc<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + load_permanently<span class="Delimiter">(</span>argv[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Main")</span> +if <span class="Delimiter">(</span>!Run_tests<span class="Delimiter">)</span> <span class="Delimiter">{</span> + setup<span class="Delimiter">();</span> + Trace_stream = new trace_stream<span class="Delimiter">;</span> +<span class="CommentedCode">//? Trace_stream->dump_layer = "all"; //? 2</span> + transform_all<span class="Delimiter">();</span> + recipe_number r = Recipe_number[string<span class="Delimiter">(</span><span class="Constant">"main"</span><span class="Delimiter">)</span>]<span class="Delimiter">;</span> +<span class="CommentedCode">//? Trace_stream->dump_layer = "all"; //? 1</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">)</span> run<span class="Delimiter">(</span>r<span class="Delimiter">);</span> +<span class="CommentedCode">//? dump_memory(); //? 1</span> + teardown<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void load_permanently<span class="Delimiter">(</span>string filename<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ifstream fin<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">());</span> + if <span class="Delimiter">(</span>!fin<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"no such file "</span> << filename << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + fin >> std::noskipws<span class="Delimiter">;</span> + load<span class="Delimiter">(</span>fin<span class="Delimiter">);</span> + transform_all<span class="Delimiter">();</span> + fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span> + <span class="Comment">// freeze everything so it doesn't get cleared by tests</span> + recently_added_recipes<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: On startup, load everything in core.mu</span> +<span class="Delimiter">:(before "End Load Recipes")</span> +load_permanently<span class="Delimiter">(</span><span class="Constant">"core.mu"</span><span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +<span class="Comment">// helper for tests</span> +void run<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<recipe_number> tmp = load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + transform_all<span class="Delimiter">();</span> + run<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>front<span class="Delimiter">());</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Reading from memory, writing to memory.</span> + +vector<long long int> read_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "read_memory: " << x.to_string() << '\n'; //? 1</span> + vector<long long int> result<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + index_t base = x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + size_t size = size_of<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>index_t offset = <span class="Constant">0</span><span class="Delimiter">;</span> offset < size<span class="Delimiter">;</span> ++offset<span class="Delimiter">)</span> <span class="Delimiter">{</span> + int val = Memory[base+offset]<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"location "</span> << base+offset << <span class="Constant">" is "</span> << val<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>val<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +void write_memory<span class="Delimiter">(</span>reagent x<span class="Delimiter">,</span> vector<long long int> data<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + index_t base = x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> != data<span class="Delimiter">.</span>size<span class="Delimiter">())</span> + raise << <span class="Constant">"size mismatch in storing to "</span> << x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t offset = <span class="Constant">0</span><span class="Delimiter">;</span> offset < data<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++offset<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"storing "</span> << data[offset] << <span class="Constant">" in location "</span> << base+offset<span class="Delimiter">;</span> + Memory[base+offset] = data[offset]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +size_t size_of<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">);</span> +<span class="Delimiter">}</span> +size_t size_of<span class="Delimiter">(</span>const vector<type_number>& types<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// End size_of(types) Cases</span> + <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool is_dummy<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>name == <span class="Constant">"_"</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool isa_literal<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span> && r<span class="Delimiter">.</span>types[<span class="Constant">0</span>] == <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario run_label)</span> +recipe main [ + +foo + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:integer +] +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+run: instruction main/2</span> +<span class="traceAbsent">-run: instruction main/0</span> + +<span class="Delimiter">:(scenario run_dummy)</span> +recipe main [ + _<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/021arithmetic.cc.html b/html/021arithmetic.cc.html new file mode 100644 index 00000000..ecdbd98b --- /dev/null +++ b/html/021arithmetic.cc.html @@ -0,0 +1,262 @@ +<!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/021arithmetic.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Arithmetic primitives</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +ADD<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"add"</span>] = ADD<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case ADD: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] + arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario add_literal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>add <span class="Constant">23</span>:literal<span class="Delimiter">,</span> <span class="Constant">34</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 23</span> +<span class="traceContains">+run: ingredient 1 is 34</span> +<span class="traceContains">+run: product 0 is 57</span> +<span class="traceContains">+mem: storing 57 in location 1</span> + +<span class="Delimiter">:(scenario add)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + <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>add <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 23</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 34</span> +<span class="traceContains">+run: product 0 is 57</span> +<span class="traceContains">+mem: storing 57 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +SUBTRACT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"subtract"</span>] = SUBTRACT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case SUBTRACT: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] - arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario subtract_literal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>subtract <span class="Constant">5</span>:literal<span class="Delimiter">,</span> <span class="Constant">2</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 5</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+run: product 0 is 3</span> +<span class="traceContains">+mem: storing 3 in location 1</span> + +<span class="Delimiter">:(scenario subtract)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + <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>subtract <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 23</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 34</span> +<span class="traceContains">+run: product 0 is -11</span> +<span class="traceContains">+mem: storing -11 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MULTIPLY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"multiply"</span>] = MULTIPLY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MULTIPLY: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> << arg1[<span class="Constant">0</span>]<span class="Delimiter">;</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] * arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario multiply_literal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>multiply <span class="Constant">2</span>:literal<span class="Delimiter">,</span> <span class="Constant">3</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 2</span> +<span class="traceContains">+run: ingredient 1 is 3</span> +<span class="traceContains">+run: product 0 is 6</span> +<span class="traceContains">+mem: storing 6 in location 1</span> + +<span class="Delimiter">:(scenario multiply)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">4</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">6</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>multiply <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 4</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 6</span> +<span class="traceContains">+run: product 0 is 24</span> +<span class="traceContains">+mem: storing 24 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +DIVIDE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"divide"</span>] = DIVIDE<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case DIVIDE: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> << arg1[<span class="Constant">0</span>]<span class="Delimiter">;</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] / arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario divide_literal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>divide <span class="Constant">8</span>:literal<span class="Delimiter">,</span> <span class="Constant">2</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 8</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+run: product 0 is 4</span> +<span class="traceContains">+mem: storing 4 in location 1</span> + +<span class="Delimiter">:(scenario divide)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">27</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>divide <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 27</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 3</span> +<span class="traceContains">+run: product 0 is 9</span> +<span class="traceContains">+mem: storing 9 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +DIVIDE_WITH_REMAINDER<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"divide-with-remainder"</span>] = DIVIDE_WITH_REMAINDER<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case DIVIDE_WITH_REMAINDER: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result0<span class="Delimiter">;</span> + result0<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] / arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result0[<span class="Constant">0</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> result0<span class="Delimiter">);</span> + vector<long long int> result1<span class="Delimiter">;</span> + result1<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] % arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 1 is "</span> << result1[<span class="Constant">0</span>]<span class="Delimiter">;</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> result1<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario divide_with_remainder_literal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer<span class="Special"> <- </span>divide-with-remainder <span class="Constant">9</span>:literal<span class="Delimiter">,</span> <span class="Constant">2</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 9</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+run: product 0 is 4</span> +<span class="traceContains">+mem: storing 4 in location 1</span> +<span class="traceContains">+run: product 1 is 1</span> +<span class="traceContains">+mem: storing 1 in location 2</span> + +<span class="Delimiter">:(scenario divide_with_remainder)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">27</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">11</span>:literal + <span class="Constant">3</span>:integer<span class="Delimiter">,</span> <span class="Constant">4</span>:integer<span class="Special"> <- </span>divide-with-remainder <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 27</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 11</span> +<span class="traceContains">+run: product 0 is 2</span> +<span class="traceContains">+mem: storing 2 in location 3</span> +<span class="traceContains">+run: product 1 is 5</span> +<span class="traceContains">+mem: storing 5 in location 4</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/022boolean.cc.html b/html/022boolean.cc.html new file mode 100644 index 00000000..3ee1cad8 --- /dev/null +++ b/html/022boolean.cc.html @@ -0,0 +1,130 @@ +<!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/022boolean.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Boolean primitives</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +AND<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"and"</span>] = AND<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case AND: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] && arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario and)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>and <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 1</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 0</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +OR<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"or"</span>] = OR<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case OR: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] || arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario or)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>or <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 1</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 0</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +NOT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"not"</span>] = NOT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case NOT: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>!arg0[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario not)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>not <span class="Constant">1</span>:integer +] +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 1</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/023jump.cc.html b/html/023jump.cc.html new file mode 100644 index 00000000..c20ce9b6 --- /dev/null +++ b/html/023jump.cc.html @@ -0,0 +1,152 @@ +<!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/023jump.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +.traceAbsent { color: #c00000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Jump primitives</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +JUMP<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"jump"</span>] = JUMP<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case JUMP: <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>value<span class="Delimiter">;</span> + current_step_index<span class="Delimiter">()</span> += current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"jumping to instruction "</span> << current_step_index<span class="Delimiter">()</span>+<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario jump_can_skip_instructions)</span> +recipe main [ + jump <span class="Constant">1</span>:offset + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceAbsent">-run: instruction main/1</span> +<span class="traceAbsent">-mem: storing 1 in location 1</span> + +<span class="Delimiter">:(scenario jump_backward)</span> +recipe main [ + jump <span class="Constant">1</span>:offset <span class="Comment"># 0 -+</span> + jump <span class="Constant">1</span>:offset <span class="Comment"># | +-+ 1</span> + <span class="Comment"># \/ /\ |</span> + jump -<span class="Constant">2</span>:offset <span class="Comment"># 2 +-->+ |</span> +] <span class="Comment"># \/ 3</span> +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: instruction main/1</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +JUMP_IF<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"jump-if"</span>] = JUMP_IF<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case JUMP_IF: <span class="Delimiter">{</span> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> << arg0[<span class="Constant">0</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!arg0[<span class="Constant">0</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"jump-if fell through"</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <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> + current_step_index<span class="Delimiter">()</span> += current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"jumping to instruction "</span> << current_step_index<span class="Delimiter">()</span>+<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario jump_if)</span> +recipe main [ + jump-if <span class="Constant">999</span>:literal <span class="Constant">1</span>:offset + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 1 is 1</span> +<span class="traceContains">+run: jumping to instruction 2</span> +<span class="traceAbsent">-run: instruction main/1</span> +<span class="traceAbsent">-mem: storing 1 in location 1</span> + +<span class="Delimiter">:(scenario jump_if_fallthrough)</span> +recipe main [ + jump-if <span class="Constant">0</span>:literal <span class="Constant">1</span>:offset + <span class="Constant">123</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: jump-if fell through</span> +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+mem: storing 1 in location 123</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +JUMP_UNLESS<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"jump-unless"</span>] = JUMP_UNLESS<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case JUMP_UNLESS: <span class="Delimiter">{</span> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> << arg0[<span class="Constant">0</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>arg0[<span class="Constant">0</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"jump-unless fell through"</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <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> + current_step_index<span class="Delimiter">()</span> += current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"jumping to instruction "</span> << current_step_index<span class="Delimiter">()</span>+<span class="Constant">1</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario jump_unless)</span> +recipe main [ + jump-unless <span class="Constant">0</span>:literal <span class="Constant">1</span>:offset + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 1 is 1</span> +<span class="traceContains">+run: jumping to instruction 2</span> +<span class="traceAbsent">-run: instruction main/1</span> +<span class="traceAbsent">-mem: storing 1 in location 1</span> + +<span class="Delimiter">:(scenario jump_unless_fallthrough)</span> +recipe main [ + jump-unless <span class="Constant">999</span>:literal <span class="Constant">1</span>:offset + <span class="Constant">123</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: ingredient 0 is 999</span> +<span class="traceContains">+run: jump-unless fell through</span> +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+mem: storing 1 in location 123</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/024compare.cc.html b/html/024compare.cc.html new file mode 100644 index 00000000..8a5274e6 --- /dev/null +++ b/html/024compare.cc.html @@ -0,0 +1,298 @@ +<!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/024compare.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Comparison primitives</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +EQUAL<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"equal"</span>] = EQUAL<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case EQUAL: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>equal<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> arg0<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> arg1<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario equal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(scenario equal2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <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>equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 34</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +GREATER_THAN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"greater-than"</span>] = GREATER_THAN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case GREATER_THAN: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] > arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario greater_than)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>greater-than <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario greater_than2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <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>greater-than <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 34</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +LESSER_THAN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"lesser-than"</span>] = LESSER_THAN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case LESSER_THAN: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] < arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario lesser_than)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">32</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>lesser-than <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 32</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario lesser_than2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>lesser-than <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +GREATER_OR_EQUAL<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"greater-or-equal"</span>] = GREATER_OR_EQUAL<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case GREATER_OR_EQUAL: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] >= arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario greater_or_equal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>greater-or-equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario greater_or_equal2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <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>greater-or-equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 34</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario greater_or_equal3)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>greater-or-equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 35</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +LESSER_OR_EQUAL<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"lesser-or-equal"</span>] = LESSER_OR_EQUAL<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case LESSER_OR_EQUAL: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><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> + vector<long long int> arg1 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg1<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] <= arg1[<span class="Constant">0</span>]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Delimiter">:(scenario lesser_or_equal)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">32</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>lesser-or-equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 32</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario lesser_or_equal2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>lesser-or-equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 33</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 1</span> +<span class="traceContains">+mem: storing 1 in location 3</span> + +<span class="Delimiter">:(scenario lesser_or_equal3)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">33</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>lesser-or-equal <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:integer +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+run: ingredient 1 is 2</span> +<span class="traceContains">+mem: location 2 is 33</span> +<span class="traceContains">+run: product 0 is 0</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/025trace.cc.html b/html/025trace.cc.html new file mode 100644 index 00000000..d58d0b83 --- /dev/null +++ b/html/025trace.cc.html @@ -0,0 +1,56 @@ +<!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/025trace.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Allow mu programs to log facts just like we've been doing in C++ so far.</span> + +<span class="Delimiter">:(scenario trace)</span> +recipe main [ + trace [foo]<span class="Delimiter">,</span> [this is a trace in mu] +] +<span class="traceContains">+foo: this is a trace in mu</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +TRACE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"trace"</span>] = TRACE<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case TRACE: <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">0</span>]<span class="Delimiter">));</span> + string label = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</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> + string message = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span>label<span class="Delimiter">)</span> << message<span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/026assert.cc.html b/html/026assert.cc.html new file mode 100644 index 00000000..14a471bc --- /dev/null +++ b/html/026assert.cc.html @@ -0,0 +1,56 @@ +<!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/026assert.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Delimiter">:(scenario assert)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + assert <span class="Constant">0</span>:literal<span class="Delimiter">,</span> [this is an assert in mu] +] +<span class="traceContains">+warn: this is an assert in mu</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +ASSERT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"assert"</span>] = ASSERT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case ASSERT: <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> + vector<long long int> arg0 = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>arg0<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>arg0[<span class="Constant">0</span>] == <span class="Constant">0</span><span class="Delimiter">)</span> + raise << current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/027debug.cc.html b/html/027debug.cc.html new file mode 100644 index 00000000..a9125522 --- /dev/null +++ b/html/027debug.cc.html @@ -0,0 +1,87 @@ +<!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/027debug.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; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Identifier { color: #008080; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Recipe to look at elements of containers.</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_PRINT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"$print"</span>] = _PRINT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case _PRINT: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"$print: "</span> << current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + cout << current_instruction<span class="Delimiter">().</span>ingredients[<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> + vector<long long int> result<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<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 < result<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"$print: "</span> << result[i]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>i > <span class="Constant">0</span><span class="Delimiter">)</span> cout << <span class="Constant">" "</span><span class="Delimiter">;</span> + cout << result[i]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_START_TRACING<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"$start-tracing"</span>] = _START_TRACING<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case _START_TRACING: <span class="Delimiter">{</span> + Trace_stream<span class="Delimiter">-></span>dump_layer = <span class="Constant">"all"</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << Trace_stream << ": " << Trace_stream->dump_layer << '\n'; //? 1</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_STOP_TRACING<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"$stop-tracing"</span>] = _STOP_TRACING<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case _STOP_TRACING: <span class="Delimiter">{</span> + Trace_stream<span class="Delimiter">-></span>dump_layer = <span class="Constant">""</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_EXIT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"$exit"</span>] = _EXIT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case _EXIT: <span class="Delimiter">{</span> + exit<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">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/030container.cc.html b/html/030container.cc.html new file mode 100644 index 00000000..8efeb1bb --- /dev/null +++ b/html/030container.cc.html @@ -0,0 +1,206 @@ +<!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/030container.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; } +.SalientComment { color: #00ffff; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Containers contain a fixed number of elements of different types.</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> +type_number point = Type_number[<span class="Constant">"point"</span>] = Next_type_number++<span class="Delimiter">;</span> +Type[point]<span class="Delimiter">.</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> +Type[point]<span class="Delimiter">.</span>kind = container<span class="Delimiter">;</span> +Type[point]<span class="Delimiter">.</span>name = <span class="Constant">"point"</span><span class="Delimiter">;</span> +vector<type_number> i<span class="Delimiter">;</span> +i<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>integer<span class="Delimiter">);</span> +Type[point]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>i<span class="Delimiter">);</span> +Type[point]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>i<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario copy_multiple_locations)</span> +<span class="Comment"># Containers can be copied around with a single instruction just like integers,</span> +<span class="Comment"># no matter how large they are.</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + <span class="Constant">3</span>:point<span class="Special"> <- </span>copy <span class="Constant">1</span>:point +] +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 34</span> +<span class="traceContains">+mem: location 2 is 35</span> +<span class="traceContains">+mem: storing 34 in location 3</span> +<span class="traceContains">+mem: storing 35 in location 4</span> + +<span class="Delimiter">:(before "End Mu Types Initialization")</span> +<span class="Comment">// A more complex container, containing another container as one of its</span> +<span class="Comment">// elements.</span> +type_number point_integer = Type_number[<span class="Constant">"point-integer"</span>] = Next_type_number++<span class="Delimiter">;</span> +Type[point_integer]<span class="Delimiter">.</span>size = <span class="Constant">2</span><span class="Delimiter">;</span> +Type[point_integer]<span class="Delimiter">.</span>kind = container<span class="Delimiter">;</span> +Type[point_integer]<span class="Delimiter">.</span>name = <span class="Constant">"point-integer"</span><span class="Delimiter">;</span> +vector<type_number> p2<span class="Delimiter">;</span> +p2<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>point<span class="Delimiter">);</span> +Type[point_integer]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>p2<span class="Delimiter">);</span> +vector<type_number> i2<span class="Delimiter">;</span> +i2<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>integer<span class="Delimiter">);</span> +Type[point_integer]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>i2<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario copy_handles_nested_container_elements)</span> +recipe main [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</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">15</span>:point-integer<span class="Special"> <- </span>copy <span class="Constant">12</span>:point-integer +] +<span class="traceContains">+mem: storing 36 in location 17</span> + +<span class="Delimiter">:(before "End size_of(types) Cases")</span> +type_info t = Type[types[<span class="Constant">0</span>]]<span class="Delimiter">;</span> +if <span class="Delimiter">(</span>t<span class="Delimiter">.</span>kind == container<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// size of a container is the sum of the sizes of its elements</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>elements<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result += size_of<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: To access elements of a container, use 'get'</span> +<span class="Delimiter">:(scenario get)</span> +recipe main [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + <span class="Constant">15</span>:integer<span class="Special"> <- </span>get <span class="Constant">12</span>:point<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 12</span> +<span class="traceContains">+run: ingredient 1 is 1</span> +<span class="traceContains">+run: address to copy is 13</span> +<span class="traceContains">+run: its type is 1</span> +<span class="traceContains">+mem: location 13 is 35</span> +<span class="traceContains">+run: product 0 is 35</span> +<span class="traceContains">+mem: storing 35 in location 15</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +GET<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"get"</span>] = GET<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case GET: <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 = 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 == 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 offset = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + index_t src = base_address<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + src += size_of<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>kind == container<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > offset<span class="Delimiter">);</span> + type_number src_type = Type[base_type]<span class="Delimiter">.</span>elements[offset][<span class="Constant">0</span>]<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"its type is "</span> << src_type<span class="Delimiter">;</span> + reagent tmp<span class="Delimiter">;</span> + tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span> + tmp<span class="Delimiter">.</span>types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>src_type<span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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> + +<span class="Comment">//: 'get' requires a literal in ingredient 1. We'll use a synonym called</span> +<span class="Comment">//: 'offset'.</span> +<span class="Delimiter">:(before "End Mu Types Initialization")</span> +Type_number[<span class="Constant">"offset"</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(scenario get_handles_nested_container_elements)</span> +recipe main [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</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">15</span>:integer<span class="Special"> <- </span>get <span class="Constant">12</span>:point-integer<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 12</span> +<span class="traceContains">+run: ingredient 1 is 1</span> +<span class="traceContains">+run: address to copy is 14</span> +<span class="traceContains">+run: its type is 1</span> +<span class="traceContains">+mem: location 14 is 36</span> +<span class="traceContains">+run: product 0 is 36</span> +<span class="traceContains">+mem: storing 36 in location 15</span> + +<span class="SalientComment">//:: To write to elements of containers, you need their address.</span> + +<span class="Delimiter">:(scenario get_address)</span> +recipe main [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + <span class="Constant">15</span>:address:integer<span class="Special"> <- </span>get-address <span class="Constant">12</span>:point<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: ingredient 0 is 12</span> +<span class="traceContains">+run: ingredient 1 is 1</span> +<span class="traceContains">+run: address to copy is 13</span> +<span class="traceContains">+mem: storing 13 in location 15</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +GET_ADDRESS<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"get-address"</span>] = GET_ADDRESS<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case GET_ADDRESS: <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 = 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 == 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 offset = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + index_t src = base_address<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < offset<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + src += size_of<span class="Delimiter">(</span>Type[base_type]<span class="Delimiter">.</span>elements[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src<span class="Delimiter">;</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>src<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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 : --> diff --git a/html/031address.cc.html b/html/031address.cc.html new file mode 100644 index 00000000..5b213874 --- /dev/null +++ b/html/031address.cc.html @@ -0,0 +1,168 @@ +<!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/031address.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; } +.CommentedCode { color: #6c6c6c; } +.SalientComment { color: #00ffff; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Instructions can read from addresses pointing at other locations using the</span> +<span class="Comment">//: 'deref' property.</span> + +<span class="Delimiter">:(scenario copy_indirect)</span> +recipe main [ + <span class="Constant">1</span>:address:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Comment"># This loads location 1 as an address and looks up *that* location.</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:address:integer/deref +] +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+mem: location 1 is 2</span> +<span class="traceContains">+mem: location 2 is 34</span> +<span class="traceContains">+mem: storing 34 in location 3</span> + +<span class="Delimiter">:(before "index_t base = x.value" following "vector<long long int> read_memory(reagent x)")</span> +x = canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + +<span class="Comment">//: similarly, write to addresses pointing at other locations using the</span> +<span class="Comment">//: 'deref' property</span> +<span class="Delimiter">:(scenario store_indirect)</span> +recipe main [ + <span class="Constant">1</span>:address:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:literal + <span class="Constant">1</span>:address:integer/deref<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal +] +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+mem: location 1 is 2</span> +<span class="traceContains">+mem: storing 34 in location 2</span> + +<span class="Delimiter">:(before "index_t base = x.value" following "void write_memory(reagent x, vector<long long int> data)")</span> +x = canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +reagent canonize<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "canonize\n"; //? 1</span> + reagent r = x<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << x.to_string() << " => " << r.to_string() << '\n'; //? 1</span> + while <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"deref"</span><span class="Delimiter">))</span> + r = deref<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + <span class="Identifier">return</span> r<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +reagent deref<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "deref: " << x.to_string() << "\n"; //? 2</span> + static const type_number ADDRESS = Type_number[<span class="Constant">"address"</span>]<span class="Delimiter">;</span> + reagent result<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>x<span class="Delimiter">.</span>types[<span class="Constant">0</span>] == ADDRESS<span class="Delimiter">);</span> + + <span class="Comment">// compute value</span> + result<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>Memory[x<span class="Delimiter">.</span>value]<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"location "</span> << x<span class="Delimiter">.</span>value << <span class="Constant">" is "</span> << result<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + + <span class="Comment">// populate types</span> + copy<span class="Delimiter">(</span>++x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>result<span class="Delimiter">.</span>types<span class="Delimiter">,</span> result<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> + + <span class="Comment">// drop-one 'deref'</span> + index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> + size_t len = x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>size<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>i = <span class="Constant">0</span><span class="Delimiter">;</span> i < len<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[i]<span class="Delimiter">.</span>first == <span class="Constant">"deref"</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + result<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + ++i<span class="Delimiter">;</span> <span class="Comment">// skip first deref</span> + for <span class="Delimiter">(;</span> i < len<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: 'get' can read from container address</span> +<span class="Delimiter">:(scenario get_indirect)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:literal + <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<span class="Special"> <- </span>get <span class="Constant">1</span>:address:point/deref<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+run: instruction main/3</span> +<span class="traceContains">+run: address to copy is 2</span> +<span class="traceContains">+run: product 0 is 34</span> +<span class="traceContains">+mem: storing 34 in location 4</span> + +<span class="Delimiter">:(scenario include_nonderef_properties)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:literal + <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<span class="Special"> <- </span>get <span class="Constant">1</span>:address:point/deref/foo<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+run: instruction main/3</span> +<span class="traceContains">+run: address to copy is 2</span> +<span class="traceContains">+run: product 0 is 34</span> +<span class="traceContains">+mem: storing 34 in location 4</span> + +<span class="Delimiter">:(after "reagent base = " following "case GET:")</span> +base = canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> + +<span class="Delimiter">:(scenario get_address_indirect)</span> +<span class="Comment"># 'get' can read from container address</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:literal + <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<span class="Special"> <- </span>get-address <span class="Constant">1</span>:address:point/deref<span class="Delimiter">,</span> <span class="Constant">0</span>:offset +] +<span class="traceContains">+run: instruction main/3</span> +<span class="traceContains">+run: address to copy is 2</span> +<span class="traceContains">+run: product 0 is 2</span> + +<span class="Delimiter">:(after "reagent base = " following "case GET_ADDRESS:")</span> +base = canonize<span class="Delimiter">(</span>base<span class="Delimiter">);</span> + +<span class="SalientComment">//:: helpers</span> + +<span class="Delimiter">:(code)</span> +bool has_property<span class="Delimiter">(</span>reagent x<span class="Delimiter">,</span> string name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[i]<span class="Delimiter">.</span>first == name<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +vector<string> property<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">,</span> const string& name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t p = <span class="Constant">0</span><span class="Delimiter">;</span> p != r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>properties[p]<span class="Delimiter">.</span>first == name<span class="Delimiter">)</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>properties[p]<span class="Delimiter">.</span>second<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> vector<string><span class="Delimiter">();</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/032array.cc.html b/html/032array.cc.html new file mode 100644 index 00000000..0686fb16 --- /dev/null +++ b/html/032array.cc.html @@ -0,0 +1,218 @@ +<!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/032array.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; } +.CommentedCode { color: #6c6c6c; } +.SalientComment { color: #00ffff; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Arrays contain a variable number of elements of the same type. Their value</span> +<span class="Comment">//: starts with the length of the array.</span> +<span class="Comment">//:</span> +<span class="Comment">//: You can create arrays of containers, but containers can only contain</span> +<span class="Comment">//: elements of a fixed size, so you can't create containers containing arrays.</span> +<span class="Comment">//: Create containers containing addresses to arrays instead.</span> + +<span class="Delimiter">:(scenario copy_array)</span> +<span class="Comment"># Arrays can be copied around with a single instruction just like integers,</span> +<span class="Comment"># no matter how large they are.</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:array:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:array:integer +] +<span class="traceContains">+run: instruction main/4</span> +<span class="traceContains">+run: ingredient 0 is 1</span> +<span class="traceContains">+mem: location 1 is 3</span> +<span class="traceContains">+mem: location 2 is 14</span> +<span class="traceContains">+mem: location 3 is 15</span> +<span class="traceContains">+mem: location 4 is 16</span> +<span class="traceContains">+mem: storing 3 in location 5</span> +<span class="traceContains">+mem: storing 14 in location 6</span> +<span class="traceContains">+mem: storing 15 in location 7</span> +<span class="traceContains">+mem: storing 16 in location 8</span> + +<span class="Delimiter">:(scenario copy_array_indirect)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:address:array:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal + <span class="Constant">6</span>:array:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:address:array:integer/deref +] +<span class="traceContains">+run: instruction main/5</span> +<span class="traceContains">+run: ingredient 0 is 5</span> +<span class="traceContains">+mem: location 1 is 3</span> +<span class="traceContains">+mem: location 2 is 14</span> +<span class="traceContains">+mem: location 3 is 15</span> +<span class="traceContains">+mem: location 4 is 16</span> +<span class="traceContains">+mem: storing 3 in location 6</span> +<span class="traceContains">+mem: storing 14 in location 7</span> +<span class="traceContains">+mem: storing 15 in location 8</span> +<span class="traceContains">+mem: storing 16 in location 9</span> + +<span class="Comment">//: disable the size mismatch check since the destination array need not be initialized</span> +<span class="Delimiter">:(replace "if (size_of(x) != data.size())" following "void write_memory(reagent x, vector<long long int> data)")</span> +if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types[<span class="Constant">0</span>] != Type_number[<span class="Constant">"array"</span>] && size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> != data<span class="Delimiter">.</span>size<span class="Delimiter">())</span> +<span class="Delimiter">:(after "size_t size_of(const reagent& r)")</span> + static const type_number ARRAY = Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>types[<span class="Constant">0</span>] == ARRAY<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Comment">// skip the 'array' type to get at the element type</span> + <span class="Identifier">return</span> <span class="Constant">1</span> + Memory[r<span class="Delimiter">.</span>value]*size_of<span class="Delimiter">(</span>array_element<span class="Delimiter">(</span>r<span class="Delimiter">.</span>types<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + +<span class="SalientComment">//:: To access elements of an array, use 'index'</span> + +<span class="Delimiter">:(scenario index)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:integer<span class="Special"> <- </span>index <span class="Constant">1</span>:array:integer<span class="Delimiter">,</span> <span class="Constant">0</span>:literal +] +<span class="traceContains">+run: instruction main/4</span> +<span class="traceContains">+run: address to copy is 2</span> +<span class="traceContains">+run: its type is 1</span> +<span class="traceContains">+mem: location 2 is 14</span> +<span class="traceContains">+run: product 0 is 14</span> +<span class="traceContains">+mem: storing 14 in location 5</span> + +<span class="Delimiter">:(scenario index_direct_offset)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">6</span>:integer<span class="Special"> <- </span>index <span class="Constant">1</span>:array:integer<span class="Delimiter">,</span> <span class="Constant">5</span>:integer +] +<span class="traceContains">+run: instruction main/5</span> +<span class="traceContains">+run: address to copy is 2</span> +<span class="traceContains">+run: its type is 1</span> +<span class="traceContains">+mem: location 2 is 14</span> +<span class="traceContains">+run: product 0 is 14</span> +<span class="traceContains">+mem: storing 14 in location 6</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +INDEX<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"index"</span>] = INDEX<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case INDEX: <span class="Delimiter">{</span> + static const type_number ARRAY = Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">;</span> +<span class="CommentedCode">//? if (Trace_stream) Trace_stream->dump_layer = "run"; //? 1</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>to_string<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> +<span class="CommentedCode">//? trace("run") << "ingredient 0 after canonize: " << base.to_string(); //? 1</span> + index_t base_address = base<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types[<span class="Constant">0</span>] == ARRAY<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>to_string<span class="Delimiter">();</span> + reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> +<span class="CommentedCode">//? trace("run") << "ingredient 1 after canonize: " << offset.to_string(); //? 1</span> + vector<long long int> offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> + vector<type_number> element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span> +<span class="CommentedCode">//? trace("run") << "offset: " << offset_val[0]; //? 1</span> +<span class="CommentedCode">//? trace("run") << "size of elements: " << size_of(element_type); //? 1</span> + index_t src = base_address + <span class="Constant">1</span> + offset_val[<span class="Constant">0</span>]*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"its type is "</span> << element_type[<span class="Constant">0</span>]<span class="Delimiter">;</span> + reagent tmp<span class="Delimiter">;</span> + tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>src<span class="Delimiter">);</span> + copy<span class="Delimiter">(</span>element_type<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> element_type<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> inserter<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>types<span class="Delimiter">,</span> tmp<span class="Delimiter">.</span>types<span class="Delimiter">.</span>begin<span class="Delimiter">()));</span> +<span class="CommentedCode">//? trace("run") << "AAA: " << tmp.to_string() << '\n'; //? 3</span> + vector<long long int> result<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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="CommentedCode">//? if (Trace_stream) Trace_stream->dump_layer = ""; //? 1</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +vector<type_number> array_element<span class="Delimiter">(</span>const vector<type_number>& types<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> vector<type_number><span class="Delimiter">(</span>++types<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> types<span class="Delimiter">.</span>end<span class="Delimiter">());</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario index_address)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:integer<span class="Special"> <- </span>index-address <span class="Constant">1</span>:array:integer<span class="Delimiter">,</span> <span class="Constant">0</span>:literal +] +<span class="traceContains">+run: instruction main/4</span> +<span class="traceContains">+run: address to copy is 2</span> +<span class="traceContains">+mem: storing 2 in location 5</span> + +<span class="SalientComment">//:: To write to elements of containers, you need their address.</span> + +<span class="Delimiter">:(scenario index_indirect)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:address:array:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal + <span class="Constant">6</span>:integer<span class="Special"> <- </span>index <span class="Constant">5</span>:address:array:integer/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:literal +] +<span class="traceContains">+run: instruction main/5</span> +<span class="traceContains">+mem: storing 15 in location 6</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +INDEX_ADDRESS<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"index-address"</span>] = INDEX_ADDRESS<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case INDEX_ADDRESS: <span class="Delimiter">{</span> + static const type_number ARRAY = Type_number[<span class="Constant">"array"</span>]<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> + assert<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types[<span class="Constant">0</span>] == ARRAY<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>to_string<span class="Delimiter">();</span> + reagent offset = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + vector<long long int> offset_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>offset<span class="Delimiter">));</span> + vector<type_number> element_type = array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>types<span class="Delimiter">);</span> + index_t src = base_address + <span class="Constant">1</span> + offset_val[<span class="Constant">0</span>]*size_of<span class="Delimiter">(</span>element_type<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy is "</span> << src<span class="Delimiter">;</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>src<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> << result[<span class="Constant">0</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 : --> diff --git a/html/033length.cc.html b/html/033length.cc.html new file mode 100644 index 00000000..bb7fef38 --- /dev/null +++ b/html/033length.cc.html @@ -0,0 +1,68 @@ +<!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/033length.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; } +.cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Recipe to compute the length of an array.</span> + +<span class="Delimiter">:(scenario array_length)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">14</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">15</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">16</span>:literal + <span class="Constant">5</span>:integer<span class="Special"> <- </span>length <span class="Constant">1</span>:array:integer +] +<span class="traceContains">+run: instruction main/4</span> +<span class="traceContains">+mem: storing 3 in location 5</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +LENGTH<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"length"</span>] = LENGTH<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case LENGTH: <span class="Delimiter">{</span> + reagent x = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types[<span class="Constant">0</span>] != Type_number[<span class="Constant">"array"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"tried to calculate length of non-array "</span> << x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + vector<long long int> result<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "length: " << x.value << '\n'; //? 1</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Memory[x<span class="Delimiter">.</span>value]<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 : --> diff --git a/html/034exclusive_container.cc.html b/html/034exclusive_container.cc.html new file mode 100644 index 00000000..20c0af47 --- /dev/null +++ b/html/034exclusive_container.cc.html @@ -0,0 +1,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 : --> diff --git a/html/035call.cc.html b/html/035call.cc.html new file mode 100644 index 00000000..43c4a42b --- /dev/null +++ b/html/035call.cc.html @@ -0,0 +1,144 @@ +<!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/035call.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; } +.cSpecial { color: #008000; } +.SalientComment { color: #00ffff; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: So far the recipes we define can't run each other. Let's fix that.</span> + +<span class="Delimiter">:(scenario calling_recipe)</span> +recipe main [ + f +] +recipe f [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>add <span class="Constant">2</span>:literal<span class="Delimiter">,</span> <span class="Constant">2</span>:literal +] +<span class="traceContains">+mem: storing 4 in location 3</span> + +<span class="Delimiter">:(scenario return_on_fallthrough)</span> +recipe main [ + f + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <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">34</span>:literal +] +recipe f [ + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">5</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: instruction f/0</span> +<span class="traceContains">+run: instruction f/1</span> +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+run: instruction main/3</span> + +<span class="Delimiter">:(before "struct routine {")</span> +<span class="Comment">// Everytime a recipe runs another, we interrupt it and start running the new</span> +<span class="Comment">// recipe. When that finishes, we continue this one where we left off.</span> +<span class="Comment">// This requires maintaining a 'stack' of interrupted recipes or 'calls'.</span> +struct call <span class="Delimiter">{</span> + recipe_number running_recipe<span class="Delimiter">;</span> + index_t running_step_index<span class="Delimiter">;</span> + <span class="Comment">// End call Fields</span> + call<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> :running_recipe<span class="Delimiter">(</span>r<span class="Delimiter">),</span> running_step_index<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> +<span class="Delimiter">};</span> +typedef stack<call> call_stack<span class="Delimiter">;</span> + +<span class="Delimiter">:(replace{} "struct routine")</span> +struct routine <span class="Delimiter">{</span> + call_stack calls<span class="Delimiter">;</span> + <span class="Comment">// End routine Fields</span> + routine<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">);</span> + bool completed<span class="Delimiter">()</span> const<span class="Delimiter">;</span> + const vector<instruction>& steps<span class="Delimiter">()</span> const<span class="Delimiter">;</span> +<span class="Delimiter">};</span> +<span class="Delimiter">:(code)</span> +routine::routine<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + calls<span class="Delimiter">.</span>push<span class="Delimiter">(</span>call<span class="Delimiter">(</span>r<span class="Delimiter">));</span> + <span class="Comment">// End routine Constructor</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: now update routine's helpers</span> + +<span class="Delimiter">:(replace{} "inline index_t& current_step_index()")</span> +inline index_t& current_step_index<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>running_step_index<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(replace{} "inline const string& current_recipe_name()")</span> +inline const string& current_recipe_name<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>running_recipe]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(replace{} "inline const instruction& current_instruction()")</span> +inline const instruction& current_instruction<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Recipe[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>running_recipe]<span class="Delimiter">.</span>steps[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>running_step_index]<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(replace{} "default:" following "End Primitive Recipe Implementations")</span> +default: <span class="Delimiter">{</span> + <span class="Comment">// not a primitive; try to look up the book of recipes</span> + if <span class="Delimiter">(</span>Recipe<span class="Delimiter">.</span>find<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">)</span> == Recipe<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"undefined operation "</span> << current_instruction<span class="Delimiter">().</span>operation << <span class="Constant">": "</span> << current_instruction<span class="Delimiter">().</span>name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>push<span class="Delimiter">(</span>call<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">));</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// not done with caller; don't increment current_step_index()</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: finally, we need to fix the termination conditions for the run loop</span> + +<span class="Delimiter">:(replace{} "inline bool routine::completed() const")</span> +inline bool routine::completed<span class="Delimiter">()</span> const <span class="Delimiter">{</span> + <span class="Identifier">return</span> calls<span class="Delimiter">.</span>empty<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +inline const vector<instruction>& routine::steps<span class="Delimiter">()</span> const <span class="Delimiter">{</span> + <span class="Identifier">return</span> Recipe[calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>running_recipe]<span class="Delimiter">.</span>steps<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "Running One Instruction")</span> +<span class="Comment">// when we reach the end of one call, we may reach the end of the one below</span> +<span class="Comment">// it, and the one below that, and so on</span> +while <span class="Delimiter">(</span>current_step_index<span class="Delimiter">()</span> >= Current_routine<span class="Delimiter">-></span>steps<span class="Delimiter">().</span>size<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>pop<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Comment">// todo: no results returned warning</span> + ++current_step_index<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include </span><span class="Constant"><stack></span> +using std::stack<span class="Delimiter">;</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/036call_ingredient.cc.html b/html/036call_ingredient.cc.html new file mode 100644 index 00000000..3fc4df85 --- /dev/null +++ b/html/036call_ingredient.cc.html @@ -0,0 +1,165 @@ +<!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/036call_ingredient.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Calls can take ingredients just like primitives. To access a recipe's</span> +<span class="Comment">//: ingredients, use 'next-ingredient'.</span> + +<span class="Delimiter">:(scenario next_ingredient)</span> +recipe main [ + f <span class="Constant">2</span>:literal +] +recipe f [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>next-ingredient + <span class="Constant">13</span>:integer<span class="Special"> <- </span>add <span class="Constant">1</span>:literal<span class="Delimiter">,</span> <span class="Constant">12</span>:integer +] +<span class="traceContains">+run: instruction f/1</span> +<span class="traceContains">+mem: location 12 is 2</span> +<span class="traceContains">+mem: storing 3 in location 13</span> + +<span class="Delimiter">:(scenario next_ingredient_missing)</span> +recipe main [ + f +] +recipe f [ + _<span class="Delimiter">,</span> <span class="Constant">12</span>:integer<span class="Special"> <- </span>next-ingredient +] +<span class="traceContains">+mem: storing 0 in location 12</span> + +<span class="Delimiter">:(before "End call Fields")</span> +vector<vector<long long int> > ingredient_atoms<span class="Delimiter">;</span> +index_t next_ingredient_to_process<span class="Delimiter">;</span> +<span class="Delimiter">:(replace{} "call(recipe_number r)")</span> +call<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> :running_recipe<span class="Delimiter">(</span>r<span class="Delimiter">),</span> running_step_index<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> next_ingredient_to_process<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + +<span class="Delimiter">:(replace "Current_routine->calls.push(call(current_instruction().operation))" following "End Primitive Recipe Implementations")</span> +call callee<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>operation<span class="Delimiter">);</span> +for <span class="Delimiter">(</span>size_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + callee<span class="Delimiter">.</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[i]<span class="Delimiter">));</span> +<span class="Delimiter">}</span> +Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>push<span class="Delimiter">(</span>callee<span class="Delimiter">);</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +NEXT_INGREDIENT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"next-ingredient"</span>] = NEXT_INGREDIENT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case NEXT_INGREDIENT: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process < Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> + << Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process][<span class="Constant">0</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> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<long long int> ingredient_exists<span class="Delimiter">;</span> + ingredient_exists<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> ingredient_exists<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + ++Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<long long int> no_ingredient<span class="Delimiter">;</span> + no_ingredient<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> no_ingredient<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario rewind_ingredients)</span> +recipe main [ + f <span class="Constant">2</span>:literal +] +recipe f [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>next-ingredient <span class="Comment"># consume ingredient</span> + _<span class="Delimiter">,</span> <span class="Constant">1</span>:boolean<span class="Special"> <- </span>next-ingredient <span class="Comment"># will not find any ingredients</span> + rewind-ingredients + <span class="Constant">13</span>:integer<span class="Delimiter">,</span> <span class="Constant">2</span>:boolean<span class="Special"> <- </span>next-ingredient <span class="Comment"># will find ingredient again</span> +] +<span class="traceContains">+mem: storing 2 in location 12</span> +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 2 in location 13</span> +<span class="traceContains">+mem: storing 1 in location 2</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +REWIND_INGREDIENTS<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"rewind-ingredients"</span>] = REWIND_INGREDIENTS<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case REWIND_INGREDIENTS: <span class="Delimiter">{</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario ingredient)</span> +recipe main [ + f <span class="Constant">1</span>:literal<span class="Delimiter">,</span> <span class="Constant">2</span>:literal +] +recipe f [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>ingredient <span class="Constant">1</span>:literal <span class="Comment"># consume second ingredient first</span> + <span class="Constant">13</span>:integer<span class="Delimiter">,</span> <span class="Constant">1</span>:boolean<span class="Special"> <- </span>next-ingredient <span class="Comment"># next-ingredient tries to scan past that</span> +] +<span class="traceContains">+mem: storing 2 in location 12</span> +<span class="traceContains">+mem: storing 0 in location 1</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +INGREDIENT<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"ingredient"</span>] = INGREDIENT<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case INGREDIENT: <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>static_cast<index_t><span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>value<span class="Delimiter">)</span> < Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Delimiter">{</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"product 0 is "</span> + << Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process][<span class="Constant">0</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> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms[Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<long long int> ingredient_exists<span class="Delimiter">;</span> + ingredient_exists<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> ingredient_exists<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + ++Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>next_ingredient_to_process<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<long long int> no_ingredient<span class="Delimiter">;</span> + no_ingredient<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> no_ingredient<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/037call_reply.cc.html b/html/037call_reply.cc.html new file mode 100644 index 00000000..0359d9fe --- /dev/null +++ b/html/037call_reply.cc.html @@ -0,0 +1,132 @@ +<!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/037call_reply.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Calls can also generate products, using 'reply'.</span> + +<span class="Delimiter">:(scenario reply)</span> +recipe main [ + <span class="Constant">3</span>:integer<span class="Delimiter">,</span> <span class="Constant">4</span>:integer<span class="Special"> <- </span>f <span class="Constant">2</span>:literal +] +recipe f [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>next-ingredient + <span class="Constant">13</span>:integer<span class="Special"> <- </span>add <span class="Constant">1</span>:literal<span class="Delimiter">,</span> <span class="Constant">12</span>:integer + reply <span class="Constant">12</span>:integer<span class="Delimiter">,</span> <span class="Constant">13</span>:integer +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: result 0 is 2</span> +<span class="traceContains">+mem: storing 2 in location 3</span> +<span class="traceContains">+run: result 1 is 3</span> +<span class="traceContains">+mem: storing 3 in location 4</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +REPLY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"reply"</span>] = REPLY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case REPLY: <span class="Delimiter">{</span> + vector<vector<long long int> > callee_results<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + callee_results<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[i]<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + const instruction& reply_inst = current_instruction<span class="Delimiter">();</span> <span class="Comment">// save pointer into recipe before pop</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>pop<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + const instruction& caller_instruction = current_instruction<span class="Delimiter">();</span> + assert<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>size<span class="Delimiter">()</span> <= callee_results<span class="Delimiter">.</span>size<span class="Delimiter">());</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < caller_instruction<span class="Delimiter">.</span>products<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"result "</span> << i << <span class="Constant">" is "</span> << to_string<span class="Delimiter">(</span>callee_results[i]<span class="Delimiter">);</span> + <span class="Comment">// check that any reply ingredients with /same-as-ingredient connect up</span> + <span class="Comment">// the corresponding ingredient and product in the caller.</span> + if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients[i]<span class="Delimiter">,</span> <span class="Constant">"same-as-ingredient"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + vector<string> tmp = property<span class="Delimiter">(</span>reply_inst<span class="Delimiter">.</span>ingredients[i]<span class="Delimiter">,</span> <span class="Constant">"same-as-ingredient"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + long long int ingredient_index = to_int<span class="Delimiter">(</span>tmp[<span class="Constant">0</span>]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products[i]<span class="Delimiter">.</span>value != caller_instruction<span class="Delimiter">.</span>ingredients[ingredient_index]<span class="Delimiter">.</span>value<span class="Delimiter">)</span> + raise << <span class="Constant">"'same-as-ingredient' result "</span> << caller_instruction<span class="Delimiter">.</span>products[i]<span class="Delimiter">.</span>value << <span class="Constant">" must be location "</span> << caller_instruction<span class="Delimiter">.</span>ingredients[ingredient_index]<span class="Delimiter">.</span>value << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + write_memory<span class="Delimiter">(</span>caller_instruction<span class="Delimiter">.</span>products[i]<span class="Delimiter">,</span> callee_results[i]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// instruction loop will increment caller's step_index</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Products can include containers and exclusive containers, addresses and arrays.</span> +<span class="Delimiter">:(scenario reply_container)</span> +recipe main [ + <span class="Constant">3</span>:point<span class="Special"> <- </span>f <span class="Constant">2</span>:literal +] +recipe f [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>next-ingredient + <span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + reply <span class="Constant">12</span>:point +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+run: result 0 is [2, 35]</span> +<span class="traceContains">+mem: storing 2 in location 3</span> +<span class="traceContains">+mem: storing 35 in location 4</span> + +<span class="Comment">//: In mu we'd like to assume that any instruction doesn't modify its</span> +<span class="Comment">//: ingredients unless they're also products. The /same-as-ingredient inside</span> +<span class="Comment">//: the recipe's 'reply' will help catch accidental misuse of such</span> +<span class="Comment">//: 'ingredient-results' (sometimes called in-out parameters in other languages).</span> +<span class="Delimiter">:(scenario reply_same_as_ingredient)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + <span class="Constant">1</span>:address:integer<span class="Special"> <- </span>new integer:type + <span class="Constant">2</span>:address:integer<span class="Special"> <- </span>test1 <span class="Constant">1</span>:address:integer <span class="Comment"># call with different ingredient and product</span> +] +recipe test1 [ + <span class="Constant">10</span>:address:integer<span class="Special"> <- </span>next-ingredient + reply <span class="Constant">10</span>:address:integer/same-as-ingredient:<span class="Constant">0</span> +] +<span class="traceContains">+warn: 'same-as-ingredient' result 2 must be location 1</span> + +<span class="Delimiter">:(code)</span> +string to_string<span class="Delimiter">(</span>const vector<long long int>& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">"[]"</span><span class="Delimiter">;</span> + ostringstream out<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + out << in[<span class="Constant">0</span>]<span class="Delimiter">;</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + out << <span class="Constant">"["</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < in<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>i > <span class="Constant">0</span><span class="Delimiter">)</span> out << <span class="Constant">", "</span><span class="Delimiter">;</span> + out << in[i]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + out << <span class="Constant">"]"</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/038scheduler.cc.html b/html/038scheduler.cc.html new file mode 100644 index 00000000..37cd96b4 --- /dev/null +++ b/html/038scheduler.cc.html @@ -0,0 +1,283 @@ +<!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/038scheduler.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; } +.SalientComment { color: #00ffff; } +.Identifier { color: #008080; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.CommentedCode { color: #6c6c6c; } +.traceContains { color: #008000; } +.traceAbsent { color: #c00000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Run a second routine concurrently using fork, without any guarantees on</span> +<span class="Comment">//: how the operations in each are interleaved with each other.</span> + +<span class="Delimiter">:(scenario scheduler)</span> +recipe f1 [ + start-running f2:recipe + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal +] +recipe f2 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">4</span>:literal +] +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+schedule: f2</span> + +<span class="Comment">//: first, add a deadline to run(routine)</span> +<span class="Comment">//: these changes are ugly and brittle; just close your nose and get through the next few lines</span> +<span class="Delimiter">:(replace "void run_current_routine()")</span> +void run_current_routine<span class="Delimiter">(</span>size_t time_slice<span class="Delimiter">)</span> +<span class="Delimiter">:(replace "while (!Current_routine->completed())" following "void run_current_routine(size_t time_slice)")</span> +size_t ninstrs = <span class="Constant">0</span><span class="Delimiter">;</span> +while <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>state == RUNNING && ninstrs < time_slice<span class="Delimiter">)</span> +<span class="Delimiter">:(after "Running One Instruction")</span> +ninstrs++<span class="Delimiter">;</span> + +<span class="Comment">//: now the rest of the scheduler is clean</span> + +<span class="Delimiter">:(before "struct routine")</span> +enum routine_state <span class="Delimiter">{</span> + RUNNING<span class="Delimiter">,</span> + COMPLETED<span class="Delimiter">,</span> + <span class="Comment">// End routine States</span> +<span class="Delimiter">};</span> +<span class="Delimiter">:(before "End routine Fields")</span> +enum routine_state state<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Constructor")</span> +state = RUNNING<span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Globals")</span> +vector<routine*> Routines<span class="Delimiter">;</span> +index_t Current_routine_index = <span class="Constant">0</span><span class="Delimiter">;</span> +size_t Scheduling_interval = <span class="Constant">500</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +Scheduling_interval = <span class="Constant">500</span><span class="Delimiter">;</span> +<span class="Delimiter">:(replace{} "void run(recipe_number r)")</span> +void run<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new routine<span class="Delimiter">(</span>r<span class="Delimiter">));</span> + Current_routine_index = <span class="Constant">0</span><span class="Delimiter">,</span> Current_routine = Routines[<span class="Constant">0</span>]<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>!all_routines_done<span class="Delimiter">())</span> <span class="Delimiter">{</span> + skip_to_next_routine<span class="Delimiter">();</span> +<span class="CommentedCode">//? cout << "scheduler: " << Current_routine_index << '\n'; //? 1</span> + assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>state == RUNNING<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"schedule"</span><span class="Delimiter">)</span> << current_recipe_name<span class="Delimiter">();</span> + run_current_routine<span class="Delimiter">(</span>Scheduling_interval<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>completed<span class="Delimiter">())</span> + Current_routine<span class="Delimiter">-></span>state = COMPLETED<span class="Delimiter">;</span> + <span class="Comment">// End Scheduler State Transitions</span> + <span class="Delimiter">}</span> +<span class="CommentedCode">//? cout << "done with run\n"; //? 1</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +bool all_routines_done<span class="Delimiter">()</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "routine " << i << ' ' << Routines[i]->state << '\n'; //? 1</span> + if <span class="Delimiter">(</span>Routines[i]<span class="Delimiter">-></span>state == RUNNING<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">// skip Current_routine_index past non-RUNNING routines</span> +void skip_to_next_routine<span class="Delimiter">()</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!Routines<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + assert<span class="Delimiter">(</span>Current_routine_index < Routines<span class="Delimiter">.</span>size<span class="Delimiter">());</span> + for <span class="Delimiter">(</span>index_t i = <span class="Delimiter">(</span>Current_routine_index+<span class="Constant">1</span><span class="Delimiter">)</span>%Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> i != Current_routine_index<span class="Delimiter">;</span> i = <span class="Delimiter">(</span>i+<span class="Constant">1</span><span class="Delimiter">)</span>%Routines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Routines[i]<span class="Delimiter">-></span>state == RUNNING<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "switching to " << i << '\n'; //? 1</span> + Current_routine_index = i<span class="Delimiter">;</span> + Current_routine = Routines[i]<span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="CommentedCode">//? cout << "all done\n"; //? 1</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Teardown")</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> + delete Routines[i]<span class="Delimiter">;</span> +Routines<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + +<span class="SalientComment">//:: To schedule new routines to run, call 'start-scheduling'.</span> + +<span class="Comment">//: 'start-scheduling' will return a unique id for the routine that was</span> +<span class="Comment">//: created.</span> +<span class="Delimiter">:(before "End routine Fields")</span> +index_t id<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Globals")</span> +index_t Next_routine_id = <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +Next_routine_id = <span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Constructor")</span> +id = Next_routine_id<span class="Delimiter">;</span> +Next_routine_id++<span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +START_RUNNING<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"start-running"</span>] = START_RUNNING<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case START_RUNNING: <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> + assert<span class="Delimiter">(</span>!current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>initialized<span class="Delimiter">);</span> + routine* new_routine = new routine<span class="Delimiter">(</span>Recipe_number[current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name]<span class="Delimiter">);</span> + <span class="Comment">// populate ingredients</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">1</span><span class="Delimiter">;</span> i < current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> + new_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>ingredient_atoms<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[i]<span class="Delimiter">));</span> + Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">-></span>id<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="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario scheduler_runs_single_routine)</span> +<span class="Special">% Scheduling_interval = 1;</span> +recipe f1 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+run: instruction f1/0</span> +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+run: instruction f1/1</span> + +<span class="Delimiter">:(scenario scheduler_interleaves_routines)</span> +<span class="Special">% Scheduling_interval = 1;</span> +recipe f1 [ + start-running f2:recipe + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +recipe f2 [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">4</span>:literal + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">4</span>:literal +] +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+run: instruction f1/0</span> +<span class="traceContains">+schedule: f2</span> +<span class="traceContains">+run: instruction f2/0</span> +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+run: instruction f1/1</span> +<span class="traceContains">+schedule: f2</span> +<span class="traceContains">+run: instruction f2/1</span> +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+run: instruction f1/2</span> + +<span class="Delimiter">:(scenario start_running_takes_args)</span> +recipe f1 [ + start-running f2:recipe<span class="Delimiter">,</span> <span class="Constant">3</span>:literal +] +recipe f2 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>next-ingredient + <span class="Constant">2</span>:integer<span class="Special"> <- </span>add <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">1</span>:literal +] +<span class="traceContains">+mem: storing 4 in location 2</span> + +<span class="Delimiter">:(scenario start_running_returns_routine_id)</span> +recipe f1 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>start-running f2:recipe +] +recipe f2 [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">44</span>:literal +] +<span class="traceContains">+mem: storing 2 in location 1</span> + +<span class="Delimiter">:(scenario scheduler_skips_completed_routines)</span> +<span class="Comment"># this scenario will require some careful setup in escaped C++</span> +<span class="Comment"># (straining our tangle capabilities to near-breaking point)</span> +<span class="Special">% recipe_number f1 = load("recipe f1 [\n1:integer <- copy 0:literal\n]").front();</span> +<span class="Special">% recipe_number f2 = load("recipe f2 [\n2:integer <- copy 0:literal\n]").front();</span> +<span class="Special">% Routines.push_back(new routine(f1)); // f1 meant to run</span> +<span class="Special">% Routines.push_back(new routine(f2));</span> +<span class="Special">% Routines.back()->state = COMPLETED; // f2 not meant to run</span> +<span class="CommentedCode">#? % Trace_stream->dump_layer = "all";</span> +<span class="Comment"># must have at least one routine without escaping</span> +recipe f3 [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="Comment"># by interleaving '+' lines with '-' lines, we allow f1 and f3 to run in any order</span> +<span class="traceContains">+schedule: f1</span> +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceAbsent">-schedule: f2</span> +<span class="traceAbsent">-mem: storing 0 in location 2</span> +<span class="traceContains">+schedule: f3</span> +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(scenario scheduler_starts_at_middle_of_routines)</span> +<span class="Special">% Routines.push_back(new routine(COPY));</span> +<span class="Special">% Routines.back()->state = COMPLETED;</span> +recipe f1 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+schedule: f1</span> +<span class="traceAbsent">-run: idle</span> + +<span class="SalientComment">//:: 'routine-state' can tell if a given routine id is running</span> + +<span class="Delimiter">:(scenario routine_state_test)</span> +<span class="Special">% Scheduling_interval = 2;</span> +recipe f1 [ + <span class="Constant">1</span>:integer/child-id<span class="Special"> <- </span>start-running f2:recipe + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal <span class="Comment"># race condition since we don't care about location 12</span> + <span class="Comment"># thanks to Scheduling_interval, f2's one instruction runs in between here and completes</span> + <span class="Constant">2</span>:integer/state<span class="Special"> <- </span>routine-state <span class="Constant">1</span>:integer/child-id +] +recipe f2 [ + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Comment"># trying to run a second instruction marks routine as completed</span> +] +<span class="Comment"># recipe f2 should be in state COMPLETED</span> +<span class="traceContains">+mem: storing 1 in location 2</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +ROUTINE_STATE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"routine-state"</span>] = ROUTINE_STATE<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case ROUTINE_STATE: <span class="Delimiter">{</span> + vector<long long int> result<span class="Delimiter">;</span> + index_t id = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">)</span>[<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 < Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Routines[i]<span class="Delimiter">-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Routines[i]<span class="Delimiter">-></span>state<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> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/039wait.cc.html b/html/039wait.cc.html new file mode 100644 index 00000000..2009d50f --- /dev/null +++ b/html/039wait.cc.html @@ -0,0 +1,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/039wait.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; } +.cSpecial { color: #008000; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Routines can be put in a 'waiting' state, from which it will be ready to</span> +<span class="Comment">//: run again when a specific memory location changes its value. This is mu's</span> +<span class="Comment">//: basic technique for orchestrating the order in which different routines</span> +<span class="Comment">//: operate.</span> + +<span class="Delimiter">:(scenario wait_for_location)</span> +recipe f1 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + start-running f2:recipe + wait-for-location <span class="Constant">1</span>:integer + <span class="Comment"># now wait for f2 to run and modify location 1 before using its value</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:integer +] +recipe f2 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal +] +<span class="Comment"># if we got the synchronization wrong we'd be storing 0 in location 2</span> +<span class="traceContains">+mem: storing 34 in location 2</span> + +<span class="Comment">//: define the new state that all routines can be in</span> + +<span class="Delimiter">:(before "End routine States")</span> +WAITING<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End routine Fields")</span> +<span class="Comment">// only if state == WAITING</span> +index_t waiting_on_location<span class="Delimiter">;</span> +int old_value_of_wating_location<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Constructor")</span> +waiting_on_location = old_value_of_wating_location = <span class="Constant">0</span><span class="Delimiter">;</span> + +<span class="Comment">//: primitive recipe to put routines in that state</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +WAIT_FOR_LOCATION<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"wait-for-location"</span>] = WAIT_FOR_LOCATION<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case WAIT_FOR_LOCATION: <span class="Delimiter">{</span> + reagent loc = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + Current_routine<span class="Delimiter">-></span>state = WAITING<span class="Delimiter">;</span> + Current_routine<span class="Delimiter">-></span>waiting_on_location = loc<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + Current_routine<span class="Delimiter">-></span>old_value_of_wating_location = Memory[loc<span class="Delimiter">.</span>value]<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"waiting for location "</span> << loc<span class="Delimiter">.</span>value << <span class="Constant">" to change from "</span> << Memory[loc<span class="Delimiter">.</span>value]<span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: scheduler tweak to get routines out of that state</span> + +<span class="Delimiter">:(before "End Scheduler State Transitions")</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Routines[i]<span class="Delimiter">-></span>state != WAITING<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Memory[Routines[i]<span class="Delimiter">-></span>waiting_on_location] && + Memory[Routines[i]<span class="Delimiter">-></span>waiting_on_location] != Routines[i]<span class="Delimiter">-></span>old_value_of_wating_location<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"schedule"</span><span class="Delimiter">)</span> << <span class="Constant">"waking up routine</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + Routines[i]<span class="Delimiter">-></span>state = RUNNING<span class="Delimiter">;</span> + Routines[i]<span class="Delimiter">-></span>waiting_on_location = Routines[i]<span class="Delimiter">-></span>old_value_of_wating_location = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: also allow waiting on a routine</span> + +<span class="Delimiter">:(scenario wait_for_routine)</span> +recipe f1 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer/routine<span class="Special"> <- </span>start-running f2:recipe + wait-for-routine <span class="Constant">2</span>:integer/routine + <span class="Comment"># now wait for f2 to run and modify location 1 before using its value</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:integer +] +recipe f2 [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal +] +<span class="Comment"># if we got the synchronization wrong we'd be storing 0 in location 3</span> +<span class="traceContains">+mem: storing 34 in location 3</span> + +<span class="Delimiter">:(before "End routine Fields")</span> +<span class="Comment">// only if state == WAITING</span> +index_t waiting_on_routine<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Constructor")</span> +waiting_on_routine = <span class="Constant">0</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +WAIT_FOR_ROUTINE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"wait-for-routine"</span>] = WAIT_FOR_ROUTINE<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case WAIT_FOR_ROUTINE: <span class="Delimiter">{</span> + reagent loc = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + Current_routine<span class="Delimiter">-></span>state = WAITING<span class="Delimiter">;</span> + Current_routine<span class="Delimiter">-></span>waiting_on_routine = loc<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"waiting for routine "</span> << loc<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Scheduler State Transitions")</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Routines[i]<span class="Delimiter">-></span>state != WAITING<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!Routines[i]<span class="Delimiter">-></span>waiting_on_routine<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + index_t id = Routines[i]<span class="Delimiter">-></span>waiting_on_routine<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>id != i<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>index_t j = <span class="Constant">0</span><span class="Delimiter">;</span> j < Routines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Routines[j]<span class="Delimiter">-></span>id == id && Routines[j]<span class="Delimiter">-></span>state != WAITING<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"schedule"</span><span class="Delimiter">)</span> << <span class="Constant">"waking up routine</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + Routines[i]<span class="Delimiter">-></span>state = RUNNING<span class="Delimiter">;</span> + Routines[i]<span class="Delimiter">-></span>waiting_on_routine = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/040brace.cc.html b/html/040brace.cc.html new file mode 100644 index 00000000..c7180da3 --- /dev/null +++ b/html/040brace.cc.html @@ -0,0 +1,421 @@ +<!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/040brace.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; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Structured programming</span> +<span class="Comment">//:</span> +<span class="Comment">//: Our jump recipes are quite inconvenient to use, so mu provides a</span> +<span class="Comment">//: lightweight tool called 'transform_braces' to work in a slightly more</span> +<span class="Comment">//: convenient format with nested braces:</span> +<span class="Comment">//:</span> +<span class="Comment">//: {</span> +<span class="Comment">//: some instructions</span> +<span class="Comment">//: {</span> +<span class="Comment">//: more instructions</span> +<span class="Comment">//: }</span> +<span class="Comment">//: }</span> +<span class="Comment">//:</span> +<span class="Comment">//: Braces are just labels, they require no special parsing. The pseudo</span> +<span class="Comment">//: recipes 'loop' and 'break' jump to just after the enclosing '{' and '}'</span> +<span class="Comment">//: respectively.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Conditional and unconditional 'loop' and 'break' should give us 80% of the</span> +<span class="Comment">//: benefits of the control-flow primitives we're used to in other languages,</span> +<span class="Comment">//: like 'if', 'while', 'for', etc.</span> + +<span class="Delimiter">:(scenarios transform)</span> +<span class="Delimiter">:(scenario brace_conversion)</span> +recipe main [ + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: jump 1:offset</span> +<span class="traceContains">+after-brace: copy ...</span> + +<span class="Comment">//: one-time setup</span> +<span class="Delimiter">:(after "int main")</span> + Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_braces<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +void transform_braces<span class="Delimiter">(</span>const recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA transform_braces\n"; //? 1</span> +<span class="CommentedCode">//? exit(0); //? 1</span> + const int OPEN = <span class="Constant">0</span><span class="Delimiter">,</span> CLOSE = <span class="Constant">1</span><span class="Delimiter">;</span> + list<pair<int<span class="Comment">/*</span><span class="Comment">OPEN/CLOSE</span><span class="Comment">*/</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">step</span><span class="Comment">*/</span>index_t> > braces<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t index = <span class="Constant">0</span><span class="Delimiter">;</span> index < Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps[index]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">"{"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"brace"</span><span class="Delimiter">)</span> << r << <span class="Constant">": push (open, "</span> << index << <span class="Constant">")"</span><span class="Delimiter">;</span> + braces<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<int<span class="Delimiter">,</span>index_t><span class="Delimiter">(</span>OPEN<span class="Delimiter">,</span> index<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">"}"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"brace"</span><span class="Delimiter">)</span> << <span class="Constant">"push (close, "</span> << index << <span class="Constant">")"</span><span class="Delimiter">;</span> + braces<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<int<span class="Delimiter">,</span>index_t><span class="Delimiter">(</span>CLOSE<span class="Delimiter">,</span> index<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + stack<<span class="Comment">/*</span><span class="Comment">step</span><span class="Comment">*/</span>index_t> open_braces<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"recipe "</span> << Recipe[r]<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t index = <span class="Constant">0</span><span class="Delimiter">;</span> index < Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps[index]<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "AAA " << inst.name << ": " << inst.operation << '\n'; //? 1</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">"{"</span><span class="Delimiter">)</span> open_braces<span class="Delimiter">.</span>push<span class="Delimiter">(</span>index<span class="Delimiter">);</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label == <span class="Constant">"}"</span><span class="Delimiter">)</span> open_braces<span class="Delimiter">.</span>pop<span class="Delimiter">();</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> + <span class="Delimiter">;</span> <span class="Comment">// do nothing</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"loop"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"jump"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">0</span> && isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// explicit target; a later phase will handle it</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + reagent ing<span class="Delimiter">;</span> + ing<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">()</span>-index<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ing<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << ing<span class="Delimiter">.</span>value << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << index << <span class="Constant">": "</span> << ing<span class="Delimiter">.</span>to_string<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << index << <span class="Constant">": "</span> << Recipe[r]<span class="Delimiter">.</span>steps[index]<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>to_string<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"break"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"jump"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">0</span> && isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// explicit target; a later phase will handle it</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + reagent ing<span class="Delimiter">;</span> + ing<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>matching_brace<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">(),</span> braces<span class="Delimiter">)</span> - index - <span class="Constant">1</span><span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ing<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << ing<span class="Delimiter">.</span>value << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"loop-if"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"jump-if"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span> && isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// explicit target; a later phase will handle it</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + reagent ing<span class="Delimiter">;</span> + ing<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">()</span>-index<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ing<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump-if "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">", "</span> << ing<span class="Delimiter">.</span>value << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"break-if"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"jump-if"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span> && isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// explicit target; a later phase will handle it</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + reagent ing<span class="Delimiter">;</span> + ing<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>matching_brace<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">(),</span> braces<span class="Delimiter">)</span> - index - <span class="Constant">1</span><span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ing<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump-if "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">", "</span> << ing<span class="Delimiter">.</span>value << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"loop-unless"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"jump-unless"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span> && isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// explicit target; a later phase will handle it</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + reagent ing<span class="Delimiter">;</span> + ing<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">()</span>-index<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ing<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump-unless "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">", "</span> << ing<span class="Delimiter">.</span>value << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"break-unless"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA break-unless\n"; //? 1</span> + inst<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"jump-unless"</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span> && isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// explicit target; a later phase will handle it</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + reagent ing<span class="Delimiter">;</span> + ing<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>matching_brace<span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>top<span class="Delimiter">(),</span> braces<span class="Delimiter">)</span> - index - <span class="Constant">1</span><span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ing<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << <span class="Constant">"jump-unless "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">", "</span> << ing<span class="Delimiter">.</span>value << <span class="Constant">":offset"</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + else <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"after-brace"</span><span class="Delimiter">)</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" ..."</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +int matching_brace<span class="Delimiter">(</span>index_t index<span class="Delimiter">,</span> const list<pair<int<span class="Delimiter">,</span> index_t> >& braces<span class="Delimiter">)</span> <span class="Delimiter">{</span> + int stacksize = <span class="Constant">0</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>list<pair<int<span class="Delimiter">,</span> index_t> >::const_iterator p = braces<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != braces<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">-></span>second < index<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + stacksize += <span class="Delimiter">(</span>p<span class="Delimiter">-></span>first ? <span class="Constant">1</span> : -<span class="Constant">1</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>stacksize == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span><span class="Constant">false</span><span class="Delimiter">);</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">// temporarily suppress run</span> +void transform<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> + load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> + transform_all<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Make sure these pseudo recipes get consistent numbers in all tests, even</span> +<span class="Comment">//: though they aren't implemented.</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +BREAK<span class="Delimiter">,</span> +BREAK_IF<span class="Delimiter">,</span> +BREAK_UNLESS<span class="Delimiter">,</span> +LOOP<span class="Delimiter">,</span> +LOOP_IF<span class="Delimiter">,</span> +LOOP_UNLESS<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"break"</span>] = BREAK<span class="Delimiter">;</span> +Recipe_number[<span class="Constant">"break-if"</span>] = BREAK_IF<span class="Delimiter">;</span> +Recipe_number[<span class="Constant">"break-unless"</span>] = BREAK_UNLESS<span class="Delimiter">;</span> +Recipe_number[<span class="Constant">"loop"</span>] = LOOP<span class="Delimiter">;</span> +Recipe_number[<span class="Constant">"loop-if"</span>] = LOOP_IF<span class="Delimiter">;</span> +Recipe_number[<span class="Constant">"loop-unless"</span>] = LOOP_UNLESS<span class="Delimiter">;</span> + +<span class="Delimiter">:(scenario loop)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + loop + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump -2:offset</span> + +<span class="Delimiter">:(scenario break_empty_block)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump 0:offset</span> + +<span class="Delimiter">:(scenario break_cascading)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump 0:offset</span> +<span class="traceContains">+after-brace: jump 0:offset</span> + +<span class="Delimiter">:(scenario break_cascading2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump 1:offset</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump 0:offset</span> + +<span class="Delimiter">:(scenario break_if)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Identifier">break</span>-if <span class="Constant">2</span>:integer + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Identifier">break</span> + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump-if 2, 1:offset</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump 0:offset</span> + +<span class="Delimiter">:(scenario break_nested)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Identifier">break</span> + <span class="Delimiter">{</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: jump 4:offset</span> + +<span class="Delimiter">:(scenario break_nested_degenerate)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Identifier">break</span> + <span class="Delimiter">{</span> + <span class="Delimiter">}</span> + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: jump 3:offset</span> + +<span class="Delimiter">:(scenario break_nested_degenerate2)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Identifier">break</span> + <span class="Delimiter">{</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: jump 2:offset</span> + +<span class="Delimiter">:(scenario break_label)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Identifier">break</span> +foo:offset + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: jump +foo:offset</span> + +<span class="Delimiter">:(scenario break_unless)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Identifier">break</span>-unless <span class="Constant">2</span>:integer + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump-unless 2, 1:offset</span> +<span class="traceContains">+after-brace: copy ...</span> + +<span class="Delimiter">:(scenario loop_unless)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + loop-unless <span class="Constant">2</span>:integer + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: jump-unless 2, -1:offset</span> +<span class="traceContains">+after-brace: copy ...</span> + +<span class="Delimiter">:(scenario loop_nested)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> + loop-if <span class="Constant">4</span>:boolean + <span class="Constant">5</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Delimiter">}</span> +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: jump-if 4, -5:offset</span> + +<span class="Delimiter">:(scenario loop_label)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +foo + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+after-brace: recipe main</span> +<span class="traceContains">+after-brace: copy ...</span> +<span class="traceContains">+after-brace: copy ...</span> + +<span class="Comment">//: test how things actually run</span> +<span class="Delimiter">:(scenarios run)</span> +<span class="Delimiter">:(scenario brace_conversion_and_run)</span> +recipe test-factorial [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">1</span>:literal + <span class="Delimiter">{</span> + <span class="Constant">3</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:integer <span class="Constant">1</span>:literal + <span class="Identifier">break</span>-if <span class="Constant">3</span>:boolean +<span class="Comment"># $print 1:integer</span> + <span class="Constant">2</span>:integer<span class="Special"> <- </span>multiply <span class="Constant">2</span>:integer<span class="Delimiter">,</span> <span class="Constant">1</span>:integer + <span class="Constant">1</span>:integer<span class="Special"> <- </span>subtract <span class="Constant">1</span>:integer<span class="Delimiter">,</span> <span class="Constant">1</span>:literal + loop + <span class="Delimiter">}</span> + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:integer <span class="Comment"># trigger a read</span> +] +<span class="traceContains">+mem: location 2 is 120</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/041name.cc.html b/html/041name.cc.html new file mode 100644 index 00000000..a6553f50 --- /dev/null +++ b/html/041name.cc.html @@ -0,0 +1,244 @@ +<!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/041name.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; } +.cSpecial { color: #008000; } +.Identifier { color: #008080; } +.SalientComment { color: #00ffff; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.CommentedCode { color: #6c6c6c; } +.traceContains { color: #008000; } +.traceAbsent { color: #c00000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: A big convenience high-level languages provide is the ability to name memory</span> +<span class="Comment">//: locations. In mu, a transform called 'transform_names' provides this</span> +<span class="Comment">//: convenience.</span> + +<span class="Delimiter">:(scenario convert_names)</span> +recipe main [ + x:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+name: assign x 1</span> +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+mem: storing 0 in location 1</span> + +<span class="Delimiter">:(scenario convert_names_warns)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + x:integer<span class="Special"> <- </span>copy y:integer +] +<span class="traceContains">+warn: use before set: y in main</span> + +<span class="Delimiter">:(after "int main")</span> + Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>transform_names<span class="Delimiter">);</span> + +<span class="Delimiter">:(before "End Globals")</span> +map<recipe_number<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> index_t> > Name<span class="Delimiter">;</span> +<span class="Delimiter">:(after "Clear Other State For recently_added_recipes")</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < recently_added_recipes<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Name<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_recipes[i]<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +void transform_names<span class="Delimiter">(</span>const recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + map<string<span class="Delimiter">,</span> index_t>& names = Name[r]<span class="Delimiter">;</span> + <span class="Comment">// store the indices 'used' so far in the map</span> + index_t& curr_idx = names[<span class="Constant">""</span>]<span class="Delimiter">;</span> + ++curr_idx<span class="Delimiter">;</span> <span class="Comment">// avoid using index 0, benign skip in some other cases</span> +<span class="CommentedCode">//? cout << "Recipe " << r << ": " << Recipe[r].name << '\n'; //? 3</span> +<span class="CommentedCode">//? cout << Recipe[r].steps.size() << '\n'; //? 2</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "instruction " << i << '\n'; //? 2</span> + instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps[i]<span class="Delimiter">;</span> + <span class="Comment">// Per-recipe Transforms</span> + <span class="Comment">// map names to addresses</span> + for <span class="Delimiter">(</span>index_t in = <span class="Constant">0</span><span class="Delimiter">;</span> in < inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++in<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "ingredients\n"; //? 2</span> + if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "ingredient " << inst.ingredients[in].name << '\n'; //? 3</span> +<span class="CommentedCode">//? cout << "ingredient " << inst.ingredients[in].to_string() << '\n'; //? 1</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>name == <span class="Constant">"default-space"</span><span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>initialized = <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + raise << <span class="Constant">"missing type in "</span> << inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>types<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>types[<span class="Constant">0</span>] <span class="Comment">// not a literal</span> + && !inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>initialized + && !is_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!already_transformed<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">,</span> names<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"use before set: "</span> << inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>name << <span class="Constant">" in "</span> << Recipe[r]<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>lookup_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[in]<span class="Delimiter">,</span> r<span class="Delimiter">));</span> +<span class="CommentedCode">//? cout << "lookup ingredient " << Recipe[r].name << "/" << i << ": " << inst.ingredients[in].to_string() << '\n'; //? 1</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + for <span class="Delimiter">(</span>index_t out = <span class="Constant">0</span><span class="Delimiter">;</span> out < inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++out<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "products\n"; //? 1</span> + if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "product " << out << '/' << inst.products.size() << " " << inst.products[out].name << '\n'; //? 4</span> +<span class="CommentedCode">//? cout << inst.products[out].types[0] << '\n'; //? 1</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>name == <span class="Constant">"default-space"</span><span class="Delimiter">)</span> + inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>initialized = <span class="Constant">true</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>types[<span class="Constant">0</span>] <span class="Comment">// not a literal</span> + && !inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>initialized + && !is_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == names<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"name"</span><span class="Delimiter">)</span> << <span class="Constant">"assign "</span> << inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>name << <span class="Constant">" "</span> << curr_idx<span class="Delimiter">;</span> + names[inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>name] = curr_idx<span class="Delimiter">;</span> + curr_idx += size_of<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>lookup_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[out]<span class="Delimiter">,</span> r<span class="Delimiter">));</span> +<span class="CommentedCode">//? cout << "lookup product " << Recipe[r].name << "/" << i << ": " << inst.products[out].to_string() << '\n'; //? 1</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +bool already_transformed<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">,</span> const map<string<span class="Delimiter">,</span> index_t>& names<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != names<span class="Delimiter">.</span>end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> + +index_t lookup_name<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">,</span> const recipe_number default_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Name[default_recipe][r<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +type_number skip_addresses<span class="Delimiter">(</span>const vector<type_number>& types<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < types<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>types[i] != Type_number[<span class="Constant">"address"</span>]<span class="Delimiter">)</span> <span class="Identifier">return</span> types[i]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + raise << <span class="Constant">"expected a container"</span> << <span class="cSpecial">'\n'</span> << die<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +int find_element_name<span class="Delimiter">(</span>const type_number t<span class="Delimiter">,</span> const string& name<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const type_info& container = Type[t]<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "looking for element " << name << " in type " << container.name << " with " << container.element_names.size() << " elements\n"; //? 1</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < container<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>container<span class="Delimiter">.</span>element_names[i] == name<span class="Delimiter">)</span> <span class="Identifier">return</span> i<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + raise << <span class="Constant">"unknown element "</span> << name << <span class="Constant">" in container "</span> << t << <span class="cSpecial">'\n'</span> << die<span class="Delimiter">();</span> + <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +bool is_raw<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t i = <span class="Comment">/*</span><span class="Comment">skip value+type</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> i < r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>r<span class="Delimiter">.</span>properties[i]<span class="Delimiter">.</span>first == <span class="Constant">"raw"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario convert_names_passes_dummy)</span> +<span class="Comment"># _ is just a dummy result that never gets consumed</span> +recipe main [ + _<span class="Delimiter">,</span> x:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+name: assign x 1</span> +<span class="traceAbsent">-name: assign _ 1</span> + +<span class="Comment">//: one reserved word that we'll need later</span> +<span class="Delimiter">:(scenario convert_names_passes_default_space)</span> +recipe main [ + default-space:integer<span class="Delimiter">,</span> x:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+name: assign x 1</span> +<span class="traceAbsent">-name: assign default-space 1</span> + +<span class="Comment">//: an escape hatch to suppress name conversion that we'll use later</span> +<span class="Delimiter">:(scenario convert_names_passes_raw)</span> +recipe main [ + x:integer/<span class="Special">raw <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceAbsent">-name: assign x 1</span> + +<span class="SalientComment">//:: Support element names for containers in 'get' and 'get-address'.</span> + +<span class="Comment">//: update our running example container for the next test</span> +<span class="Delimiter">:(before "End Mu Types Initialization")</span> +Type[point]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"x"</span><span class="Delimiter">);</span> +Type[point]<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"y"</span><span class="Delimiter">);</span> +<span class="Delimiter">:(scenario convert_names_transforms_container_elements)</span> +recipe main [ + a:integer<span class="Special"> <- </span>get <span class="Constant">0</span>:point<span class="Delimiter">,</span> y:offset + b:integer<span class="Special"> <- </span>get <span class="Constant">0</span>:point<span class="Delimiter">,</span> x:offset +] +<span class="traceContains">+name: element y of type point is at offset 1</span> +<span class="traceContains">+name: element x of type point is at offset 0</span> + +<span class="Delimiter">:(after "Per-recipe Transforms")</span> +<span class="Comment">// replace element names of containers with offsets</span> +if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"get"</span>] + || inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"get-address"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// at least 2 args, and second arg is offset</span> + assert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> >= <span class="Constant">2</span><span class="Delimiter">);</span> +<span class="CommentedCode">//? cout << inst.ingredients[1].to_string() << '\n'; //? 1</span> + assert<span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">"0123456789"</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// since first non-address in base type must be a container, we don't have to canonize</span> + type_number base_type = skip_addresses<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>types<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">"name"</span><span class="Delimiter">)</span> << <span class="Constant">"element "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="Constant">" of type "</span> << Type[base_type]<span class="Delimiter">.</span>name << <span class="Constant">" is at offset "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: this test is actually illegal so can't call run</span> +<span class="Delimiter">:(scenarios transform)</span> +<span class="Delimiter">:(scenario convert_names_handles_containers)</span> +recipe main [ + a:point<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + b:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+name: assign a 1</span> +<span class="traceContains">+name: assign b 3</span> + +<span class="SalientComment">//:: Support variant names for exclusive containers in 'maybe-convert'.</span> + +<span class="Delimiter">:(scenarios run)</span> +<span class="Delimiter">:(scenario maybe_convert_named)</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> p:variant +] +<span class="traceContains">+name: variant p of type integer-or-point has tag 1</span> +<span class="traceContains">+mem: storing 13 in location 20</span> + +<span class="Delimiter">:(after "Per-recipe Transforms")</span> +<span class="Comment">// convert variant names of exclusive containers</span> +if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"maybe-convert"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// at least 2 args, and second arg is offset</span> + assert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> >= <span class="Constant">2</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">"0123456789"</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// since first non-address in base type must be an exclusive container, we don't have to canonize</span> + type_number base_type = skip_addresses<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>types<span class="Delimiter">);</span> + inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name<span class="Delimiter">));</span> + trace<span class="Delimiter">(</span><span class="Constant">"name"</span><span class="Delimiter">)</span> << <span class="Constant">"variant "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>name << <span class="Constant">" of type "</span> << Type[base_type]<span class="Delimiter">.</span>name << <span class="Constant">" has tag "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/042new.cc.html b/html/042new.cc.html new file mode 100644 index 00000000..d6bca4bf --- /dev/null +++ b/html/042new.cc.html @@ -0,0 +1,195 @@ +<!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/042new.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">//: A simple memory allocator to create space for new variables at runtime.</span> + +<span class="Delimiter">:(scenarios run)</span> +<span class="Delimiter">:(scenario new)</span> +<span class="Comment"># call new two times with identical arguments; you should get back different results</span> +recipe main [ + <span class="Constant">1</span>:address:integer/<span class="Special">raw <- </span>new integer:type + <span class="Constant">2</span>:address:integer/<span class="Special">raw <- </span>new integer:type + <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:address:integer/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:integer/<span class="Special">raw</span> +] +<span class="traceContains">+mem: storing 0 in location 3</span> + +<span class="Delimiter">:(before "End Globals")</span> +size_t Reserved_for_tests = <span class="Constant">1000</span><span class="Delimiter">;</span> +index_t Memory_allocated_until = Reserved_for_tests<span class="Delimiter">;</span> +size_t Initial_memory_per_routine = <span class="Constant">100000</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +Memory_allocated_until = Reserved_for_tests<span class="Delimiter">;</span> +Initial_memory_per_routine = <span class="Constant">100000</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Fields")</span> +index_t alloc<span class="Delimiter">,</span> alloc_max<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End routine Constructor")</span> +alloc = Memory_allocated_until<span class="Delimiter">;</span> +Memory_allocated_until += Initial_memory_per_routine<span class="Delimiter">;</span> +alloc_max = Memory_allocated_until<span class="Delimiter">;</span> +trace<span class="Delimiter">(</span><span class="Constant">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"routine allocated memory from "</span> << alloc << <span class="Constant">" to "</span> << alloc_max<span class="Delimiter">;</span> + +<span class="SalientComment">//:: First handle 'type' operands.</span> + +<span class="Delimiter">:(before "End Mu Types Initialization")</span> +Type_number[<span class="Constant">"type"</span>] = <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "Per-recipe Transforms")</span> +<span class="Comment">// replace type names with type_numbers</span> +if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == Recipe_number[<span class="Constant">"new"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// first arg must be of type 'type'</span> + assert<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> >= <span class="Constant">1</span><span class="Delimiter">);</span> +<span class="CommentedCode">//? cout << inst.ingredients[0].to_string() << '\n'; //? 1</span> + assert<span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">));</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>second[<span class="Constant">0</span>] == <span class="Constant">"type"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>Type_number[inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">"new"</span><span class="Delimiter">)</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">" -> "</span> << inst<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>value<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Now implement the primitive recipe.</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +NEW<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"new"</span>] = NEW<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case NEW: <span class="Delimiter">{</span> + <span class="Comment">// compute the space we need</span> + size_t size = <span class="Constant">0</span><span class="Delimiter">;</span> + size_t array_length = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Delimiter">{</span> + vector<type_number> type<span class="Delimiter">;</span> + type<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>value<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// array</span> + vector<long long int> capacity = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + array_length = capacity[<span class="Constant">0</span>]<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"array size is "</span> << 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 resulting location</span> + <span class="Comment">// really crappy at the moment</span> + assert<span class="Delimiter">(</span>size <= Initial_memory_per_routine<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc + size >= Current_routine<span class="Delimiter">-></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">-></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">-></span>alloc_max = Memory_allocated_until<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"new"</span><span class="Delimiter">)</span> << <span class="Constant">"routine allocated memory from "</span> << Current_routine<span class="Delimiter">-></span>alloc << <span class="Constant">" to "</span> << Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + const index_t result = Current_routine<span class="Delimiter">-></span>alloc<span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"new alloc: "</span> << result<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// initialize array</span> + Memory[result] = array_length<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Comment">// write result to memory</span> + vector<long long int> tmp<span class="Delimiter">;</span> + tmp<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc<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> tmp<span class="Delimiter">);</span> + <span class="Comment">// bump</span> + Current_routine<span class="Delimiter">-></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">-></span>alloc <= Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario new_array)</span> +recipe main [ + <span class="Constant">1</span>:address:array:integer/<span class="Special">raw <- </span>new integer:type<span class="Delimiter">,</span> <span class="Constant">5</span>:literal + <span class="Constant">2</span>:address:integer/<span class="Special">raw <- </span>new integer:type + <span class="Constant">3</span>:integer/<span class="Special">raw <- </span>subtract <span class="Constant">2</span>:address:integer/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">1</span>:address:array:integer/<span class="Special">raw</span> +] +<span class="traceContains">+run: instruction main/0</span> +<span class="traceContains">+mem: array size is 5</span> +<span class="traceContains">+run: instruction main/1</span> +<span class="traceContains">+run: instruction main/2</span> +<span class="traceContains">+mem: storing 6 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:integer/<span class="Special">raw <- </span>new integer:type +] +recipe f2 [ + <span class="Constant">2</span>:address:integer/<span class="Special">raw <- </span>new integer:type + <span class="Comment"># hack: assumes scheduler implementation</span> + <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal <span class="Constant">1</span>:address:integer/<span class="Special">raw</span><span class="Delimiter">,</span> <span class="Constant">2</span>:address:integer/<span class="Special">raw</span> +] +<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:integer/<span class="Special">raw <- </span>new integer:type + <span class="Constant">2</span>:address:point/<span class="Special">raw <- </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 string literal argument.</span> + +<span class="Delimiter">:(scenario new_string)</span> +recipe main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new [abc def] + <span class="Constant">2</span>:character<span class="Special"> <- </span>index <span class="Constant">1</span>:address:array:character/deref<span class="Delimiter">,</span> <span class="Constant">5</span>:literal +] +<span class="Comment"># integer code for 'e'</span> +<span class="traceContains">+mem: storing 101 in location 2</span> + +<span class="Delimiter">:(after "case NEW" following "Primitive Recipe Implementations")</span> +if <span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>second[<span class="Constant">0</span>] == <span class="Constant">"literal-string"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// allocate an array just large enough for it</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc<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="Comment">// assume that all characters fit in a single location</span> +<span class="CommentedCode">//? cout << "new string literal: " << current_instruction().ingredients[0].name << '\n'; //? 1</span> + Memory[Current_routine<span class="Delimiter">-></span>alloc++] = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name<span class="Delimiter">.</span>size<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Memory[Current_routine<span class="Delimiter">-></span>alloc++] = current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name[i]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Comment">// mu strings are not null-terminated in memory</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/043space.cc.html b/html/043space.cc.html new file mode 100644 index 00000000..c52c5d42 --- /dev/null +++ b/html/043space.cc.html @@ -0,0 +1,169 @@ +<!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/043space.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; } +.cSpecial { color: #008000; } +.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">//: Spaces help isolate functions from each other. You can create them at will,</span> +<span class="Comment">//: and all addresses in arguments are implicitly based on the 'default-space'</span> +<span class="Comment">//: (unless they have the /raw property)</span> + +<span class="Delimiter">:(scenario set_default_space)</span> +<span class="Comment"># if default-space is 10, and if an array of 5 locals lies from location 11 to 15 (inclusive),</span> +<span class="Comment"># then location 0 is really location 11, location 1 is really location 12, and so on.</span> +recipe main [ + <span class="Constant">10</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal <span class="Comment"># pretend array; in practice we'll use new</span> + default-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>:literal + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal +] +<span class="traceContains">+mem: storing 23 in location 12</span> + +<span class="Delimiter">:(scenario deref_sidesteps_default_space)</span> +recipe main [ + <span class="Comment"># pretend pointer from outside</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Comment"># pretend array</span> + <span class="Constant">1000</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal + <span class="Comment"># actual start of this function</span> + default-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>:literal + <span class="Constant">1</span>:address:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">8</span>:integer/<span class="Special">raw <- </span>copy <span class="Constant">1</span>:address:integer/deref +] +<span class="traceContains">+mem: storing 34 in location 8</span> + +<span class="Delimiter">:(before "End call Fields")</span> +index_t default_space<span class="Delimiter">;</span> +<span class="Delimiter">:(replace "call(recipe_number r) :running_recipe(r)")</span> +call<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> :running_recipe<span class="Delimiter">(</span>r<span class="Delimiter">),</span> running_step_index<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> next_ingredient_to_process<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> default_space<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + +<span class="Delimiter">:(replace "reagent r = x" following "reagent canonize(reagent x)")</span> +reagent r = absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> +<span class="Delimiter">:(code)</span> +reagent absolutize<span class="Delimiter">(</span>reagent x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? if (Recipe_number.find("increment-counter") != Recipe_number.end()) //? 1</span> +<span class="CommentedCode">//? cout << "AAA " << "increment-counter/2: " << Recipe[Recipe_number["increment-counter"]].steps[2].products[0].to_string() << '\n'; //? 1</span> +<span class="CommentedCode">//? cout << "absolutize " << x.to_string() << '\n'; //? 4</span> +<span class="CommentedCode">//? cout << is_raw(x) << '\n'; //? 1</span> + if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "not raw: " << x.to_string() << '\n'; //? 1</span> + assert<span class="Delimiter">(</span>x<span class="Delimiter">.</span>initialized<span class="Delimiter">);</span> + reagent r = x<span class="Delimiter">;</span> + r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">(</span>r<span class="Delimiter">.</span>value<span class="Delimiter">,</span> space_base<span class="Delimiter">(</span>r<span class="Delimiter">)));</span> +<span class="CommentedCode">//? cout << "after absolutize: " << r.value << '\n'; //? 1</span> + r<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> vector<string><span class="Delimiter">()));</span> + assert<span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>r<span class="Delimiter">));</span> + <span class="Identifier">return</span> r<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "return result" following "reagent deref(reagent x)")</span> +result<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> vector<string><span class="Delimiter">()));</span> + +<span class="SalientComment">//:: fix 'get'</span> + +<span class="Delimiter">:(scenario deref_sidesteps_default_space_in_get)</span> +recipe main [ + <span class="Comment"># pretend pointer to container from outside</span> + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + <span class="Comment"># pretend array</span> + <span class="Constant">1000</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal + <span class="Comment"># actual start of this function</span> + default-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>:literal + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">12</span>:literal + <span class="Constant">9</span>:integer/<span class="Special">raw <- </span>get <span class="Constant">1</span>:address:point/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:offset +] +<span class="traceContains">+mem: storing 35 in location 9</span> + +<span class="Delimiter">:(after "reagent tmp" following "case GET:")</span> +tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> vector<string><span class="Delimiter">()));</span> + +<span class="SalientComment">//:: fix 'index'</span> + +<span class="Delimiter">:(scenario deref_sidesteps_default_space_in_index)</span> +recipe main [ + <span class="Comment"># pretend pointer to array from outside</span> + <span class="Constant">12</span>:integer<span class="Special"> <- </span>copy <span class="Constant">2</span>:literal + <span class="Constant">13</span>:integer<span class="Special"> <- </span>copy <span class="Constant">34</span>:literal + <span class="Constant">14</span>:integer<span class="Special"> <- </span>copy <span class="Constant">35</span>:literal + <span class="Comment"># pretend array</span> + <span class="Constant">1000</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal + <span class="Comment"># actual start of this function</span> + default-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">1000</span>:literal + <span class="Constant">1</span>:address:array:integer<span class="Special"> <- </span>copy <span class="Constant">12</span>:literal + <span class="Constant">9</span>:integer/<span class="Special">raw <- </span>index <span class="Constant">1</span>:address:array:integer/deref<span class="Delimiter">,</span> <span class="Constant">1</span>:literal +] +<span class="traceContains">+mem: storing 35 in location 9</span> + +<span class="Delimiter">:(after "reagent tmp" following "case INDEX:")</span> +tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> vector<string> ><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> vector<string><span class="Delimiter">()));</span> + +<span class="SalientComment">//:: helpers</span> + +<span class="Delimiter">:(code)</span> +index_t space_base<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>default_space<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +index_t address<span class="Delimiter">(</span>index_t offset<span class="Delimiter">,</span> index_t base<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>base == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> offset<span class="Delimiter">;</span> <span class="Comment">// raw</span> +<span class="CommentedCode">//? cout << base << '\n'; //? 2</span> + if <span class="Delimiter">(</span>offset >= static_cast<index_t><span class="Delimiter">(</span>Memory[base]<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Comment">// todo: test</span> + raise << <span class="Constant">"location "</span> << offset << <span class="Constant">" is out of bounds "</span> << Memory[base] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> base+<span class="Constant">1</span> + offset<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after "void write_memory(reagent x, vector<long long int> data)")</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">"default-space"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>data<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>default_space = data[<span class="Constant">0</span>]<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << "AAA " << Current_routine->calls.top().default_space << '\n'; //? 1</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario get_default_space)</span> +recipe main [ + default-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>:literal + <span class="Constant">1</span>:integer/<span class="Special">raw <- </span>copy default-space:address:array:location +] +<span class="traceContains">+mem: storing 10 in location 1</span> + +<span class="Delimiter">:(after "vector<long long int> read_memory(reagent x)")</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">"default-space"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>default_space<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 : --> diff --git a/html/044space_surround.cc.html b/html/044space_surround.cc.html new file mode 100644 index 00000000..2cfb49f0 --- /dev/null +++ b/html/044space_surround.cc.html @@ -0,0 +1,87 @@ +<!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/044space_surround.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; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: So far you can have global variables by not setting default-space, and</span> +<span class="Comment">//: local variables by setting default-space. You can isolate variables</span> +<span class="Comment">//: between those extremes by creating 'surrounding' spaces.</span> +<span class="Comment">//:</span> +<span class="Comment">//: (Surrounding spaces are like lexical scopes in other languages.)</span> + +<span class="Delimiter">:(scenario surrounding_space)</span> +<span class="Comment"># location 1 in space 1 refers to the space surrounding the default space, here 20.</span> +recipe main [ + <span class="Constant">10</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal <span class="Comment"># pretend array</span> + <span class="Constant">20</span>:integer<span class="Special"> <- </span>copy <span class="Constant">5</span>:literal <span class="Comment"># pretend array</span> + default-space:address:array:location<span class="Special"> <- </span>copy <span class="Constant">10</span>:literal + <span class="Constant">0</span>:address:array:location/names:dummy<span class="Special"> <- </span>copy <span class="Constant">20</span>:literal <span class="Comment"># later layers will explain the /names: property</span> + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">32</span>:literal + <span class="Constant">1</span>:integer/space:<span class="Constant">1</span><span class="Special"> <- </span>copy <span class="Constant">33</span>:literal +] +<span class="traceContains">+run: instruction main/3</span> +<span class="traceContains">+mem: storing 20 in location 11</span> +<span class="traceContains">+run: instruction main/4</span> +<span class="traceContains">+mem: storing 32 in location 12</span> +<span class="traceContains">+run: instruction main/5</span> +<span class="traceContains">+mem: storing 33 in location 22</span> + +<span class="Comment">//: If you think of a space as a collection of variables with a common</span> +<span class="Comment">//: lifetime, surrounding allows managing shorter lifetimes inside a longer</span> +<span class="Comment">//: one.</span> + +<span class="Delimiter">:(replace{} "index_t space_base(const reagent& x)")</span> +index_t space_base<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> space_base<span class="Delimiter">(</span>x<span class="Delimiter">,</span> space_index<span class="Delimiter">(</span>x<span class="Delimiter">),</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +index_t space_base<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">,</span> index_t space_index<span class="Delimiter">,</span> index_t base<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? trace("foo") << "base of space " << space_index << '\n'; //? 1</span> + if <span class="Delimiter">(</span>space_index == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? trace("foo") << "base of space " << space_index << " is " << base << '\n'; //? 1</span> + <span class="Identifier">return</span> base<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="CommentedCode">//? trace("foo") << "base of space " << space_index << " is " << Memory[base+1] << '\n'; //? 1</span> + index_t result = space_base<span class="Delimiter">(</span>x<span class="Delimiter">,</span> space_index-<span class="Constant">1</span><span class="Delimiter">,</span> Memory[base+<span class="Constant">1</span>]<span class="Delimiter">);</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +index_t space_index<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[i]<span class="Delimiter">.</span>first == <span class="Constant">"space"</span><span class="Delimiter">)</span> + <span class="Identifier">return</span> to_int<span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[i]<span class="Delimiter">.</span>second[<span class="Constant">0</span>]<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/045closure_name.cc.html b/html/045closure_name.cc.html new file mode 100644 index 00000000..e97e71ae --- /dev/null +++ b/html/045closure_name.cc.html @@ -0,0 +1,171 @@ +<!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/045closure_name.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; } +.cSpecial { color: #008000; } +.Identifier { color: #008080; } +.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">//: Writing to a literal (not computed) address of 0 in a recipe chains two</span> +<span class="Comment">//: spaces together. When a variable has a property of /space:1, it looks up</span> +<span class="Comment">//: the variable in the chained/surrounding space. /space:2 looks up the</span> +<span class="Comment">//: surrounding space of the surrounding space, etc.</span> + +<span class="Delimiter">:(scenario closure)</span> +recipe main [ + default-space:address:array:location<span class="Special"> <- </span>new location:type<span class="Delimiter">,</span> <span class="Constant">30</span>:literal + <span class="Constant">1</span>:address:array:location/names:init-counter<span class="Special"> <- </span>init-counter +<span class="CommentedCode">#? $print [AAAAAAAAAAAAAAAA]</span> +<span class="CommentedCode">#? $print 1:address:array:location</span> + <span class="Constant">2</span>:integer/<span class="Special">raw <- </span>increment-counter <span class="Constant">1</span>:address:array:location/names:init-counter + <span class="Constant">3</span>:integer/<span class="Special">raw <- </span>increment-counter <span class="Constant">1</span>:address:array:location/names:init-counter +] + +recipe init-counter [ + default-space:address:array:location<span class="Special"> <- </span>new location:type<span class="Delimiter">,</span> <span class="Constant">30</span>:literal + x:integer<span class="Special"> <- </span>copy <span class="Constant">23</span>:literal + y:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal <span class="Comment"># variable that will be incremented</span> + reply default-space:address:array:location +] + +recipe increment-counter [ + default-space:address:array:location<span class="Special"> <- </span>new space:literal<span class="Delimiter">,</span> <span class="Constant">30</span>:literal + <span class="Constant">0</span>:address:array:location/names:init-counter<span class="Special"> <- </span>next-ingredient <span class="Comment"># outer space must be created by 'init-counter' above</span> + y:integer/space:<span class="Constant">1</span><span class="Special"> <- </span>add y:integer/space:<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">1</span>:literal <span class="Comment"># increment</span> + y:integer<span class="Special"> <- </span>copy <span class="Constant">234</span>:literal <span class="Comment"># dummy</span> + reply y:integer/space:<span class="Constant">1</span> +] + +<span class="traceContains">+name: recipe increment-counter is surrounded by init-counter</span> +<span class="traceContains">+mem: storing 5 in location 3</span> + +<span class="Comment">//: To make this work, compute the recipe that provides names for the</span> +<span class="Comment">//: surrounding space of each recipe. This must happen before transform_names.</span> + +<span class="Delimiter">:(before "End Globals")</span> +map<recipe_number<span class="Delimiter">,</span> recipe_number> Surrounding_space<span class="Delimiter">;</span> + +<span class="Delimiter">:(after "int main")</span> + Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>collect_surrounding_spaces<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +void collect_surrounding_spaces<span class="Delimiter">(</span>const recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction& inst = Recipe[r]<span class="Delimiter">.</span>steps[i]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t j = <span class="Constant">0</span><span class="Delimiter">;</span> j < inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++j<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>isa_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>name != <span class="Constant">"0"</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>types<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != <span class="Constant">3</span> + || inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>types[<span class="Constant">0</span>] != Type_number[<span class="Constant">"address"</span>] + || inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>types[<span class="Constant">1</span>] != Type_number[<span class="Constant">"array"</span>] + || inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>types[<span class="Constant">2</span>] != Type_number[<span class="Constant">"location"</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"slot 0 should always have type address:array:location, but is "</span> << inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + vector<string> s = property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">,</span> <span class="Constant">"names"</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>s<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> + raise << <span class="Constant">"slot 0 requires a /names property in recipe "</span> << Recipe[r]<span class="Delimiter">.</span>name << die<span class="Delimiter">();</span> + if <span class="Delimiter">(</span>s<span class="Delimiter">.</span>size<span class="Delimiter">()</span> > <span class="Constant">1</span><span class="Delimiter">)</span> raise << <span class="Constant">"slot 0 should have a single value in /names, got "</span> << inst<span class="Delimiter">.</span>products[j]<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + string surrounding_recipe_name = s[<span class="Constant">0</span>]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Surrounding_space<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">)</span> != Surrounding_space<span class="Delimiter">.</span>end<span class="Delimiter">()</span> + && Surrounding_space[r] != Recipe_number[surrounding_recipe_name]<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"recipe "</span> << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">" can have only one 'surrounding' recipe but has "</span> << Recipe[Surrounding_space[r]]<span class="Delimiter">.</span>name << <span class="Constant">" and "</span> << surrounding_recipe_name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + trace<span class="Delimiter">(</span><span class="Constant">"name"</span><span class="Delimiter">)</span> << <span class="Constant">"recipe "</span> << Recipe[r]<span class="Delimiter">.</span>name << <span class="Constant">" is surrounded by "</span> << surrounding_recipe_name<span class="Delimiter">;</span> + Surrounding_space[r] = Recipe_number[surrounding_recipe_name]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Once surrounding spaces are available, transform_names uses them to handle</span> +<span class="Comment">//: /space properties.</span> + +<span class="Delimiter">:(replace{} "index_t lookup_name(const reagent& r, const recipe_number default_recipe)")</span> +index_t lookup_name<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">,</span> const recipe_number default_recipe<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA " << default_recipe << " " << Recipe[default_recipe].name << '\n'; //? 2</span> +<span class="CommentedCode">//? cout << "AAA " << x.to_string() << '\n'; //? 1</span> + if <span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"space"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Name[default_recipe]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise << <span class="Constant">"name not found: "</span> << x<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span> << die<span class="Delimiter">();</span> + <span class="Identifier">return</span> Name[default_recipe][x<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + vector<string> p = property<span class="Delimiter">(</span>x<span class="Delimiter">,</span> <span class="Constant">"space"</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>p<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != <span class="Constant">1</span><span class="Delimiter">)</span> raise << <span class="Constant">"/space property should have exactly one (non-negative integer) value</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + int n = to_int<span class="Delimiter">(</span>p[<span class="Constant">0</span>]<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>n >= <span class="Constant">0</span><span class="Delimiter">);</span> + recipe_number surrounding_recipe = lookup_surrounding_recipe<span class="Delimiter">(</span>default_recipe<span class="Delimiter">,</span> n<span class="Delimiter">);</span> + set<recipe_number> done<span class="Delimiter">;</span> + vector<recipe_number> path<span class="Delimiter">;</span> + <span class="Identifier">return</span> lookup_name<span class="Delimiter">(</span>x<span class="Delimiter">,</span> surrounding_recipe<span class="Delimiter">,</span> done<span class="Delimiter">,</span> path<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">// If the recipe we need to lookup this name in doesn't have names done yet,</span> +<span class="Comment">// recursively call transform_names on it.</span> +index_t lookup_name<span class="Delimiter">(</span>const reagent& x<span class="Delimiter">,</span> const recipe_number r<span class="Delimiter">,</span> set<recipe_number>& done<span class="Delimiter">,</span> vector<recipe_number>& path<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>!Name[r]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> Name[r][x<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>done<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">)</span> != done<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"can't compute address of "</span> << x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> << <span class="Constant">" because "</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">1</span><span class="Delimiter">;</span> i < path<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << path[i-<span class="Constant">1</span>] << <span class="Constant">" requires computing names of "</span> << path[i] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + raise << path[path<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span>] << <span class="Constant">" requires computing names of "</span> << r << <span class="Constant">"..ad infinitum</span><span class="cSpecial">\n</span><span class="Constant">"</span> << die<span class="Delimiter">();</span> + <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + done<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + path<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>r<span class="Delimiter">);</span> + transform_names<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Comment">// Not passing 'done' through. Might this somehow cause an infinite loop?</span> + assert<span class="Delimiter">(</span>!Name[r]<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + <span class="Identifier">return</span> Name[r][x<span class="Delimiter">.</span>name]<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +recipe_number lookup_surrounding_recipe<span class="Delimiter">(</span>const recipe_number r<span class="Delimiter">,</span> index_t n<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>n == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> r<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Surrounding_space<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">)</span> == Surrounding_space<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"don't know surrounding recipe of "</span> << Recipe[r]<span class="Delimiter">.</span>name << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span>Surrounding_space[r]<span class="Delimiter">);</span> + <span class="Identifier">return</span> lookup_surrounding_recipe<span class="Delimiter">(</span>Surrounding_space[r]<span class="Delimiter">,</span> n-<span class="Constant">1</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: weaken use-before-set warnings just a tad</span> +<span class="Delimiter">:(replace{} "bool already_transformed(const reagent& r, const map<string, index_t>& names)")</span> +bool already_transformed<span class="Delimiter">(</span>const reagent& r<span class="Delimiter">,</span> const map<string<span class="Delimiter">,</span> index_t>& names<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"space"</span><span class="Delimiter">))</span> <span class="Delimiter">{</span> + vector<string> p = property<span class="Delimiter">(</span>r<span class="Delimiter">,</span> <span class="Constant">"space"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>p<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == <span class="Constant">1</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>p[<span class="Constant">0</span>] != <span class="Constant">"0"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> names<span class="Delimiter">.</span>find<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">)</span> != names<span class="Delimiter">.</span>end<span class="Delimiter">();</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html new file mode 100644 index 00000000..89766a6e --- /dev/null +++ b/html/050scenario.cc.html @@ -0,0 +1,517 @@ +<!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/050scenario.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; } +.cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.SalientComment { color: #00ffff; } +.traceAbsent { color: #c00000; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Mu scenarios. This will get long, but these are the tests we want to</span> +<span class="Comment">//: support in this layer.</span> + +<span class="Comment">//: You can use variable names in scenarios, but for the most part we'll use</span> +<span class="Comment">//: raw location numbers, because that lets us make assertions on memory.</span> +<span class="Comment">//: Tests should avoid abstraction as far as possible.</span> +<span class="Delimiter">:(scenarios run_mu_scenario)</span> +<span class="Delimiter">:(scenario scenario_block)</span> +scenario foo [ + run [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + ] + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">13</span> + ] +] +<span class="Comment"># checks are inside scenario</span> + +<span class="Delimiter">:(scenario scenario_multiple_blocks)</span> +scenario foo [ + run [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + ] + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">13</span> + ] + run [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + ] + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">13</span> + <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">13</span> + ] +] + +<span class="Delimiter">:(scenario scenario_check_memory_and_trace)</span> +scenario foo [ + run [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + trace [a]<span class="Delimiter">,</span> [a b c] + ] + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">13</span> + ] + trace-should-contain [ + a: a b c + ] + trace-should-not-contain [ + a: x y z + ] +] + +<span class="SalientComment">//:: Core data structure</span> + +<span class="Delimiter">:(before "End Types")</span> +struct scenario <span class="Delimiter">{</span> + string name<span class="Delimiter">;</span> + string to_run<span class="Delimiter">;</span> +<span class="Delimiter">};</span> + +<span class="Delimiter">:(before "End Globals")</span> +vector<scenario> Scenarios<span class="Delimiter">;</span> + +<span class="SalientComment">//:: Parse the 'scenario' form.</span> +<span class="Comment">//: Simply store the text of the scenario.</span> + +<span class="Delimiter">:(before "End Command Handlers")</span> +else if <span class="Delimiter">(</span>command == <span class="Constant">"scenario"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + Scenarios<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>parse_scenario<span class="Delimiter">(</span>in<span class="Delimiter">));</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +scenario parse_scenario<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + scenario result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">"'scenario' must begin with '['"</span><span class="Delimiter">);</span> + ostringstream buffer<span class="Delimiter">;</span> + slurp_until_matching_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> buffer<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>to_run = buffer<span class="Delimiter">.</span>str<span class="Delimiter">();</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Run scenarios when we run 'mu test'.</span> +<span class="Comment">//: Treat the text of the scenario as a regular series of instructions.</span> + +<span class="Delimiter">:(before "End Tests")</span> +time_t mu_time<span class="Delimiter">;</span> time<span class="Delimiter">(</span>&mu_time<span class="Delimiter">);</span> +cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">Mu tests: "</span> << ctime<span class="Delimiter">(</span>&mu_time<span class="Delimiter">);</span> +for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Scenarios<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << Passed << '\n'; //? 1</span> + run_mu_scenario<span class="Delimiter">(</span>Scenarios[i]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Globals")</span> +const scenario* Current_scenario = <span class="Constant">NULL</span><span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +void run_mu_scenario<span class="Delimiter">(</span>const scenario& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Current_scenario = &s<span class="Delimiter">;</span> + bool not_already_inside_test = !Trace_stream<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>not_already_inside_test<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Trace_file = s<span class="Delimiter">.</span>name<span class="Delimiter">;</span> + Trace_stream = new trace_stream<span class="Delimiter">;</span> + setup<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + run<span class="Delimiter">(</span><span class="Constant">"recipe "</span>+s<span class="Delimiter">.</span>name+<span class="Constant">" [ "</span> + s<span class="Delimiter">.</span>to_run + <span class="Constant">" ]"</span><span class="Delimiter">);</span> + if <span class="Delimiter">(</span>not_already_inside_test<span class="Delimiter">)</span> <span class="Delimiter">{</span> + teardown<span class="Delimiter">();</span> + ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> + fout << Trace_stream<span class="Delimiter">-></span>readable_contents<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> + fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span> + delete Trace_stream<span class="Delimiter">;</span> + Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> + Trace_file = <span class="Constant">""</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + Current_scenario = <span class="Constant">NULL</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: The special instructions we want to support inside scenarios.</span> +<span class="Comment">//: In a compiler for the mu VM these will require more work.</span> + +<span class="Comment">//: 'run' interprets a string as a set of instructions</span> + +<span class="Delimiter">:(scenarios run)</span> +<span class="Delimiter">:(scenario run)</span> +<span class="CommentedCode">#? % Trace_stream->dump_layer = "all";</span> +recipe main [ + run [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + ] +] +<span class="traceContains">+mem: storing 13 in location 1</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +RUN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"run"</span>] = RUN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case RUN: <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "recipe " << current_instruction().ingredients[0].name << '\n'; //? 1</span> + ostringstream tmp<span class="Delimiter">;</span> + tmp << <span class="Constant">"recipe run"</span> << Next_recipe_number << <span class="Constant">" [ "</span> << current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>name << <span class="Constant">" ]"</span><span class="Delimiter">;</span> +<span class="CommentedCode">//? Show_rest_of_stream = true; //? 1</span> + vector<recipe_number> tmp_recipe = load<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<span class="Delimiter">());</span> + <span class="Comment">// Predefined Scenario Locals In Run.</span> + <span class="Comment">// End Predefined Scenario Locals In Run.</span> + transform_all<span class="Delimiter">();</span> +<span class="CommentedCode">//? cout << tmp_recipe[0] << ' ' << Recipe_number["main"] << '\n'; //? 1</span> + Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>push<span class="Delimiter">(</span>call<span class="Delimiter">(</span>tmp_recipe[<span class="Constant">0</span>]<span class="Delimiter">));</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// not done with caller; don't increment current_step_index()</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario run_multiple)</span> +recipe main [ + run [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + ] + run [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">13</span>:literal + ] +] +<span class="traceContains">+mem: storing 13 in location 1</span> +<span class="traceContains">+mem: storing 13 in location 2</span> + +<span class="Comment">//: 'memory-should-contain' raises warnings if specific locations aren't as expected</span> +<span class="Comment">//: Also includes some special support for checking strings.</span> + +<span class="Delimiter">:(scenario memory_check)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">13</span> + ] +] +<span class="traceContains">+run: checking location 1</span> +<span class="traceContains">+warn: expected location 1 to contain 13 but saw 0</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MEMORY_SHOULD_CONTAIN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"memory-should-contain"</span>] = MEMORY_SHOULD_CONTAIN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MEMORY_SHOULD_CONTAIN: <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << current_instruction().ingredients[0].name << '\n'; //? 1</span> + check_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<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> +void check_memory<span class="Delimiter">(</span>const string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + istringstream in<span class="Delimiter">(</span>s<span class="Delimiter">);</span> + in >> std::noskipws<span class="Delimiter">;</span> + set<index_t> locations_checked<span class="Delimiter">;</span> + while <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + string lhs = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>!is_number<span class="Delimiter">(</span>lhs<span class="Delimiter">))</span> <span class="Delimiter">{</span> + check_type<span class="Delimiter">(</span>lhs<span class="Delimiter">,</span> in<span class="Delimiter">);</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + int address = to_int<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + string _assign<span class="Delimiter">;</span> in >> _assign<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>_assign == <span class="Constant">"<-"</span><span class="Delimiter">);</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + int value = <span class="Constant">0</span><span class="Delimiter">;</span> in >> value<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>locations_checked<span class="Delimiter">.</span>find<span class="Delimiter">(</span>address<span class="Delimiter">)</span> != locations_checked<span class="Delimiter">.</span>end<span class="Delimiter">())</span> + raise << <span class="Constant">"duplicate expectation for location "</span> << address << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"checking location "</span> << address<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Memory[address] != value<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Current_scenario<span class="Delimiter">)</span> + raise << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << Current_scenario<span class="Delimiter">-></span>name << <span class="Constant">": expected location "</span> << address << <span class="Constant">" to contain "</span> << value << <span class="Constant">" but saw "</span> << Memory[address] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + else + raise << <span class="Constant">"expected location "</span> << address << <span class="Constant">" to contain "</span> << value << <span class="Constant">" but saw "</span> << Memory[address] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + locations_checked<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>address<span class="Delimiter">);</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +void check_type<span class="Delimiter">(</span>const string& lhs<span class="Delimiter">,</span> istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + reagent x<span class="Delimiter">(</span>lhs<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>properties[<span class="Constant">0</span>]<span class="Delimiter">.</span>second[<span class="Constant">0</span>] == <span class="Constant">"string"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>to_int<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">));</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + string _assign = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>_assign == <span class="Constant">"<-"</span><span class="Delimiter">);</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + string literal = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + index_t address = x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> + <span class="Comment">// exclude quoting brackets</span> + assert<span class="Delimiter">(</span>literal[<span class="Constant">0</span>] == <span class="Constant">'['</span><span class="Delimiter">);</span> literal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>literal[literal<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span>] == <span class="Constant">']'</span><span class="Delimiter">);</span> literal<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>literal<span class="Delimiter">.</span>size<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">);</span> + check_string<span class="Delimiter">(</span>address<span class="Delimiter">,</span> literal<span class="Delimiter">);</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + raise << <span class="Constant">"don't know how to check memory for "</span> << lhs << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +void check_string<span class="Delimiter">(</span>index_t address<span class="Delimiter">,</span> const string& literal<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"checking string length at "</span> << address<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Memory[address] != static_cast<signed><span class="Delimiter">(</span>literal<span class="Delimiter">.</span>size<span class="Delimiter">()))</span> + raise << <span class="Constant">"expected location "</span> << address << <span class="Constant">" to contain length "</span> << literal<span class="Delimiter">.</span>size<span class="Delimiter">()</span> << <span class="Constant">" of string ["</span> << literal << <span class="Constant">"] but saw "</span> << Memory[address] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + ++address<span class="Delimiter">;</span> <span class="Comment">// now skip length</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < literal<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"checking location "</span> << address+i<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>Memory[address+i] != literal[i]<span class="Delimiter">)</span> + raise << <span class="Constant">"expected location "</span> << <span class="Delimiter">(</span>address+i<span class="Delimiter">)</span> << <span class="Constant">" to contain "</span> << literal[i] << <span class="Constant">" but saw "</span> << Memory[address+i] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario memory_check_multiple)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> + ] +] +<span class="traceContains">+warn: duplicate expectation for location 1</span> + +<span class="Delimiter">:(scenario memory_check_string_length)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">97</span>:literal <span class="Comment"># 'a'</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">98</span>:literal <span class="Comment"># 'b'</span> + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">99</span>:literal <span class="Comment"># 'c'</span> + memory-should-contain [ + <span class="Constant">1</span>:string<span class="Special"> <- </span>[ab] + ] +] +<span class="traceContains">+warn: expected location 1 to contain length 2 of string [ab] but saw 3</span> + +<span class="Delimiter">:(scenario memory_check_string)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">3</span>:literal + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">97</span>:literal <span class="Comment"># 'a'</span> + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">98</span>:literal <span class="Comment"># 'b'</span> + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">99</span>:literal <span class="Comment"># 'c'</span> + memory-should-contain [ + <span class="Constant">1</span>:string<span class="Special"> <- </span>[abc] + ] +] +<span class="traceContains">+run: checking string length at 1</span> +<span class="traceContains">+run: checking location 2</span> +<span class="traceContains">+run: checking location 3</span> +<span class="traceContains">+run: checking location 4</span> + +<span class="Delimiter">:(code)</span> +<span class="Comment">//: 'trace-should-contain' is like the '+' lines in our scenarios so far</span> +<span class="Comment">// Like runs of contiguous '+' lines, order is important. The trace checks</span> +<span class="Comment">// that the lines are present *and* in the specified sequence. (There can be</span> +<span class="Comment">// other lines in between.)</span> + +<span class="Delimiter">:(scenario trace_check_warns_on_failure)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + trace-should-contain [ + a: b + a: d + ] +] +<span class="traceContains">+warn: missing [b] in trace layer a</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +TRACE_SHOULD_CONTAIN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"trace-should-contain"</span>] = TRACE_SHOULD_CONTAIN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case TRACE_SHOULD_CONTAIN: <span class="Delimiter">{</span> + check_trace<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<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> +<span class="Comment">// simplified version of check_trace_contents() that emits warnings rather</span> +<span class="Comment">// than just printing to stderr</span> +bool check_trace<span class="Delimiter">(</span>const string& expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + vector<pair<string<span class="Delimiter">,</span> string> > expected_lines = parse_trace<span class="Delimiter">(</span>expected<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>expected_lines<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + index_t curr_expected_line = <span class="Constant">0</span><span class="Delimiter">;</span> + for <span class="Delimiter">(</span>vector<pair<string<span class="Delimiter">,</span> pair<int<span class="Delimiter">,</span> string> > >::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>expected_lines[curr_expected_line]<span class="Delimiter">.</span>first != p<span class="Delimiter">-></span>first<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>expected_lines[curr_expected_line]<span class="Delimiter">.</span>second != p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>second<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// match</span> + ++curr_expected_line<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>curr_expected_line == expected_lines<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + + raise << <span class="Constant">"missing ["</span> << expected_lines[curr_expected_line]<span class="Delimiter">.</span>second << <span class="Constant">"] "</span> + << <span class="Constant">"in trace layer "</span> << expected_lines[curr_expected_line]<span class="Delimiter">.</span>first << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +vector<pair<string<span class="Delimiter">,</span> string> > parse_trace<span class="Delimiter">(</span>const string& expected<span class="Delimiter">)</span> <span class="Delimiter">{</span> + vector<string> buf = split<span class="Delimiter">(</span>expected<span class="Delimiter">,</span> <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> + vector<pair<string<span class="Delimiter">,</span> string> > result<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < buf<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + buf[i] = trim<span class="Delimiter">(</span>buf[i]<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>buf[i]<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + index_t delim = buf[i]<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">": "</span><span class="Delimiter">);</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string><span class="Delimiter">(</span>buf[i]<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> delim<span class="Delimiter">),</span> buf[i]<span class="Delimiter">.</span>substr<span class="Delimiter">(</span>delim+<span class="Constant">2</span><span class="Delimiter">)));</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario trace_check_warns_on_failure_in_later_line)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + run [ + trace [a]<span class="Delimiter">,</span> [b] + ] + trace-should-contain [ + a: b + a: d + ] +] +<span class="traceContains">+warn: missing [d] in trace layer a</span> + +<span class="Delimiter">:(scenario trace_check_passes_silently)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + run [ + trace [a]<span class="Delimiter">,</span> [b] + ] + trace-should-contain [ + a: b + ] +] +<span class="traceAbsent">-warn: missing [b] in trace layer a</span> + +<span class="Comment">//: 'trace-should-not-contain' is like the '-' lines in our scenarios so far</span> +<span class="Comment">//: Each trace line is separately checked for absense. Order is *not*</span> +<span class="Comment">//: important, so you can't say things like "B should not exist after A."</span> + +<span class="Delimiter">:(scenario trace_negative_check_warns_on_failure)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + run [ + trace [a]<span class="Delimiter">,</span> [b] + ] + trace-should-not-contain [ + a: b + ] +] +<span class="traceContains">+warn: unexpected [b] in trace layer a</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +TRACE_SHOULD_NOT_CONTAIN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"trace-should-not-contain"</span>] = TRACE_SHOULD_NOT_CONTAIN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case TRACE_SHOULD_NOT_CONTAIN: <span class="Delimiter">{</span> + check_trace_missing<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<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> +<span class="Comment">// simplified version of check_trace_contents() that emits warnings rather</span> +<span class="Comment">// than just printing to stderr</span> +bool check_trace_missing<span class="Delimiter">(</span>const string& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Trace_stream<span class="Delimiter">-></span>newline<span class="Delimiter">();</span> + vector<pair<string<span class="Delimiter">,</span> string> > lines = parse_trace<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < lines<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span>lines[i]<span class="Delimiter">.</span>first<span class="Delimiter">,</span> lines[i]<span class="Delimiter">.</span>second<span class="Delimiter">)</span> != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << <span class="Constant">"unexpected ["</span> << lines[i]<span class="Delimiter">.</span>second << <span class="Constant">"] in trace layer "</span> << lines[i]<span class="Delimiter">.</span>first << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario trace_negative_check_passes_silently)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + trace-should-not-contain [ + a: b + ] +] +<span class="traceAbsent">-warn: unexpected [b] in trace layer a</span> + +<span class="Delimiter">:(scenario trace_negative_check_warns_on_any_unexpected_line)</span> +<span class="Special">% Hide_warnings = true;</span> +recipe main [ + run [ + trace [a]<span class="Delimiter">,</span> [d] + ] + trace-should-not-contain [ + a: b + a: d + ] +] +<span class="traceContains">+warn: unexpected [d] in trace layer a</span> + +<span class="SalientComment">//:: Helpers</span> + +<span class="Delimiter">:(code)</span> +<span class="Comment">// just for the scenarios running scenarios in C++ layers</span> +void run_mu_scenario<span class="Delimiter">(</span>const string& form<span class="Delimiter">)</span> <span class="Delimiter">{</span> + istringstream in<span class="Delimiter">(</span>form<span class="Delimiter">);</span> + in >> std::noskipws<span class="Delimiter">;</span> + string _scenario = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> +<span class="CommentedCode">//? cout << _scenario << '\n'; //? 1</span> + assert<span class="Delimiter">(</span>_scenario == <span class="Constant">"scenario"</span><span class="Delimiter">);</span> + scenario s = parse_scenario<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + run_mu_scenario<span class="Delimiter">(</span>s<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +void slurp_until_matching_bracket<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> + int brace_depth = <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Comment">// just scanned '['</span> + char c<span class="Delimiter">;</span> + while <span class="Delimiter">(</span>in >> c<span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>c == <span class="Constant">'['</span><span class="Delimiter">)</span> ++brace_depth<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>c == <span class="Constant">']'</span><span class="Delimiter">)</span> --brace_depth<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>brace_depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Comment">// drop final ']'</span> + out << c<span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Comment">// see tests for this function in tangle/030tangle.test.cc</span> +string trim<span class="Delimiter">(</span>const string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> + string::const_iterator first = s<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> + while <span class="Delimiter">(</span>first != s<span class="Delimiter">.</span>end<span class="Delimiter">()</span> && isspace<span class="Delimiter">(</span>*first<span class="Delimiter">))</span> + ++first<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>first == s<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> + + string::const_iterator last = --s<span class="Delimiter">.</span>end<span class="Delimiter">();</span> + while <span class="Delimiter">(</span>last != s<span class="Delimiter">.</span>begin<span class="Delimiter">()</span> && isspace<span class="Delimiter">(</span>*last<span class="Delimiter">))</span> + --last<span class="Delimiter">;</span> + ++last<span class="Delimiter">;</span> + <span class="Identifier">return</span> string<span class="Delimiter">(</span>first<span class="Delimiter">,</span> last<span class="Delimiter">);</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/051scenario_test.mu.html b/html/051scenario_test.mu.html new file mode 100644 index 00000000..f5724398 --- /dev/null +++ b/html/051scenario_test.mu.html @@ -0,0 +1,103 @@ +<!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/051scenario_test.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># tests for 'scenario' in previous layer</span> + +scenario first_scenario_in_mu <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:integer<span class="Special"> <- </span>add 2:literal, 2:literal + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 1<span class="Special"> <- </span>4 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario scenario_with_comment_in_mu <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + <span class="Comment"># comment</span> + 1:integer<span class="Special"> <- </span>add 2:literal, 2:literal + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 1<span class="Special"> <- </span>4 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario scenario_with_multiple_comments_in_mu <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + <span class="Comment"># comment1</span> + <span class="Comment"># comment2</span> + 1:integer<span class="Special"> <- </span>add 2:literal, 2:literal + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 1<span class="Special"> <- </span>4 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario check_string_in_memory <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:integer<span class="Special"> <- </span>copy 3:literal + 2:character<span class="Special"> <- </span>copy 97:literal <span class="Comment"># 'a'</span> + 3:character<span class="Special"> <- </span>copy 98:literal <span class="Comment"># 'b'</span> + 4:character<span class="Special"> <- </span>copy 99:literal <span class="Comment"># 'c'</span> + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 1:string<span class="Special"> <- </span><span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario check_trace <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:integer<span class="Special"> <- </span>add 2:literal, 2:literal + <span class="Delimiter">]</span> + trace-should-contain <span class="Delimiter">[</span> + mem: storing 4 in location 1 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario check_trace_negative <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:integer<span class="Special"> <- </span>add 2:literal, 2:literal + <span class="Delimiter">]</span> + trace-should-not-contain <span class="Delimiter">[</span> + mem: storing 5 in location 1 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario check_trace_instruction <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + trace <span class="Delimiter">[</span>foo<span class="Delimiter">]</span>, <span class="Delimiter">[</span>aaa<span class="Delimiter">]</span> + <span class="Delimiter">]</span> + trace-should-contain <span class="Delimiter">[</span> + foo: aaa + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/060string.mu.html b/html/060string.mu.html new file mode 100644 index 00000000..3323c51b --- /dev/null +++ b/html/060string.mu.html @@ -0,0 +1,541 @@ +<!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/060string.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.CommentedCode { color: #6c6c6c; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># Some useful helpers for dealing with strings.</span> + +recipe string-equal <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + a:address:array:character<span class="Special"> <- </span>next-ingredient + a-len:integer<span class="Special"> <- </span>length a:address:array:character/deref + b:address:array:character<span class="Special"> <- </span>next-ingredient + b-len:integer<span class="Special"> <- </span>length b:address:array:character/deref + <span class="Comment"># compare lengths</span> + <span class="Delimiter">{</span> + trace <span class="Delimiter">[</span>string-equal<span class="Delimiter">]</span>, <span class="Delimiter">[</span>comparing lengths<span class="Delimiter">]</span> + length-equal?:boolean<span class="Special"> <- </span>equal a-len:integer, b-len:integer + <span class="Identifier">break-if</span> length-equal?:boolean + <span class="Identifier">reply</span> 0:literal + <span class="Delimiter">}</span> + <span class="Comment"># compare each corresponding character</span> + trace <span class="Delimiter">[</span>string-equal<span class="Delimiter">]</span>, <span class="Delimiter">[</span>comparing characters<span class="Delimiter">]</span> + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, a-len:integer + <span class="Identifier">break-if</span> done?:boolean + a2:character<span class="Special"> <- </span>index a:address:array:character/deref, i:integer + b2:character<span class="Special"> <- </span>index b:address:array:character/deref, i:integer + <span class="Delimiter">{</span> + chars-match?:boolean<span class="Special"> <- </span>equal a2:character, b2:character + <span class="Identifier">break-if</span> chars-match?:boolean + <span class="Identifier">reply</span> 0:literal + <span class="Delimiter">}</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> 1:literal +<span class="Delimiter">]</span> + +scenario string-equal-reflexive <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + 3:boolean/<span class="Special">raw <- </span>string-equal x:address:array:character, x:address:array:character + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># x == x for all x</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario string-equal-identical <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + 3:boolean/<span class="Special">raw <- </span>string-equal x:address:array:character, y:address:array:character + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># abc == abc</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario string-equal-distinct-lengths <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abcd<span class="Delimiter">]</span> + 3:boolean/<span class="Special">raw <- </span>string-equal x:address:array:character, y:address:array:character + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># abc != abcd</span> + <span class="Delimiter">]</span> + trace-should-contain <span class="Delimiter">[</span> + string-equal: comparing lengths + <span class="Delimiter">]</span> + trace-should-not-contain <span class="Delimiter">[</span> + string-equal: comparing characters + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario string-equal-with-empty <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abcd<span class="Delimiter">]</span> + 3:boolean/<span class="Special">raw <- </span>string-equal x:address:array:character, y:address:array:character + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># "" != abcd</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario string-equal-common-lengths-but-distinct <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + y:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>abd<span class="Delimiter">]</span> + 3:boolean/<span class="Special">raw <- </span>string-equal x:address:array:character, y:address:array:character + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># abc != abd</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +<span class="Comment"># A new type to help incrementally construct strings.</span> +container buffer <span class="Delimiter">[</span> + length:integer + data:address:array:character +<span class="Delimiter">]</span> + +recipe init-buffer <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal +<span class="CommentedCode">#? $print default-space:address:array:location</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> + result:address:buffer<span class="Special"> <- </span>new buffer:type + len:address:integer<span class="Special"> <- </span>get-address result:address:buffer/deref, length:offset + len:address:integer/deref<span class="Special"> <- </span>copy 0:literal + s:address:address:array:character<span class="Special"> <- </span>get-address result:address:buffer/deref, data:offset + capacity:integer<span class="Special"> <- </span>next-ingredient + s:address:address:array:character/deref<span class="Special"> <- </span>new character:type, capacity:integer +<span class="CommentedCode">#? $print s:address:address:array:character/deref</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> + <span class="Identifier">reply</span> result:address:buffer +<span class="Delimiter">]</span> + +recipe grow-buffer <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + in:address:buffer<span class="Special"> <- </span>next-ingredient + <span class="Comment"># double buffer size</span> + x:address:address:array:character<span class="Special"> <- </span>get-address in:address:buffer/deref, data:offset + oldlen:integer<span class="Special"> <- </span>length x:address:address:array:character/deref/deref + newlen:integer<span class="Special"> <- </span>multiply oldlen:integer, 2:literal + olddata:address:array:character<span class="Special"> <- </span>copy x:address:address:array:character/deref + x:address:address:array:character/deref<span class="Special"> <- </span>new character:type, newlen:integer + <span class="Comment"># copy old contents</span> + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, oldlen:integer + <span class="Identifier">break-if</span> done?:boolean + src:character<span class="Special"> <- </span>index olddata:address:array:character/deref, i:integer + dest:address:character<span class="Special"> <- </span>index-address x:address:address:array:character/deref/deref, i:integer + dest:address:character/deref<span class="Special"> <- </span>copy src:character + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> in:address:buffer +<span class="Delimiter">]</span> + +recipe buffer-full? <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + in:address:buffer<span class="Special"> <- </span>next-ingredient + len:integer<span class="Special"> <- </span>get in:address:buffer/deref, length:offset + s:address:array:character<span class="Special"> <- </span>get in:address:buffer/deref, data:offset + capacity:integer<span class="Special"> <- </span>length s:address:array:character/deref + result:boolean<span class="Special"> <- </span>greater-or-equal len:integer, capacity:integer + <span class="Identifier">reply</span> result:boolean +<span class="Delimiter">]</span> + +<span class="Comment"># in:address:buffer <- buffer-append in:address:buffer, c:character</span> +recipe buffer-append <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + in:address:buffer<span class="Special"> <- </span>next-ingredient + c:character<span class="Special"> <- </span>next-ingredient + <span class="Delimiter">{</span> + <span class="Comment"># grow buffer if necessary</span> + full?:boolean<span class="Special"> <- </span>buffer-full? in:address:buffer + <span class="Identifier">break-unless</span> full?:boolean + in:address:buffer<span class="Special"> <- </span>grow-buffer in:address:buffer + <span class="Delimiter">}</span> + len:address:integer<span class="Special"> <- </span>get-address in:address:buffer/deref, length:offset + s:address:array:character<span class="Special"> <- </span>get in:address:buffer/deref, data:offset + dest:address:character<span class="Special"> <- </span>index-address s:address:array:character/deref, len:address:integer/deref + dest:address:character/deref<span class="Special"> <- </span>copy c:character + len:address:integer/deref<span class="Special"> <- </span>add len:address:integer/deref, 1:literal + <span class="Identifier">reply</span> in:address:buffer/same-as-ingredient:0 +<span class="Delimiter">]</span> + +scenario buffer-append-works <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:buffer<span class="Special"> <- </span>init-buffer 3:literal + s1:address:array:character<span class="Special"> <- </span>get x:address:buffer/deref, data:offset + x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, 97:literal <span class="Comment"># 'a'</span> + x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, 98:literal <span class="Comment"># 'b'</span> + x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, 99:literal <span class="Comment"># 'c'</span> + s2:address:array:character<span class="Special"> <- </span>get x:address:buffer/deref, data:offset + 1:boolean/<span class="Special">raw <- </span>equal s1:address:array:character, s2:address:array:character +<span class="CommentedCode">#? $print s2:address:array:character</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> +<span class="CommentedCode">#? $print 1060:integer/raw</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> +<span class="CommentedCode">#? $print 1061:integer/raw</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> +<span class="CommentedCode">#? $print 1062:integer/raw</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> +<span class="CommentedCode">#? $print 1063:integer/raw</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> +<span class="CommentedCode">#? $print 1064:integer/raw</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> +<span class="CommentedCode">#? $print 1065:integer/raw</span> +<span class="CommentedCode">#? $print [</span> +<span class="CommentedCode">#? ]</span> + 2:array:character/<span class="Special">raw <- </span>copy s2:address:array:character/deref + <span class="Identifier"> +buffer-filled</span> + x:address:buffer<span class="Special"> <- </span>buffer-append x:address:buffer, 100:literal <span class="Comment"># 'd'</span> + s3:address:array:character<span class="Special"> <- </span>get x:address:buffer/deref, data:offset + 10:boolean/<span class="Special">raw <- </span>equal s1:address:array:character, s3:address:array:character + 11:integer/<span class="Special">raw <- </span>get x:address:buffer/deref, length:offset + 12:array:character/<span class="Special">raw <- </span>copy s3:address:array:character/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + <span class="Comment"># before +buffer-filled</span> + 1<span class="Special"> <- </span>1 <span class="Comment"># no change in data pointer</span> + 2<span class="Special"> <- </span>3 <span class="Comment"># size of data</span> + 3<span class="Special"> <- </span>97 <span class="Comment"># data</span> + 4<span class="Special"> <- </span>98 + 5<span class="Special"> <- </span>99 + <span class="Comment"># in the end</span> + 10<span class="Special"> <- </span>0 <span class="Comment"># data pointer has grown</span> + 11<span class="Special"> <- </span>4 <span class="Comment"># final length</span> + 12<span class="Special"> <- </span>6 <span class="Comment"># but data's capacity has doubled</span> + 13<span class="Special"> <- </span>97 <span class="Comment"># data</span> + 14<span class="Special"> <- </span>98 + 15<span class="Special"> <- </span>99 + 16<span class="Special"> <- </span>100 + 17<span class="Special"> <- </span>0 + 18<span class="Special"> <- </span>0 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +<span class="Comment"># result:address:array:character <- integer-to-decimal-string n:integer</span> +recipe integer-to-decimal-string <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + n:integer<span class="Special"> <- </span>next-ingredient + <span class="Comment"># is it zero?</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-if</span> n:integer + result:address:array:character<span class="Special"> <- </span>new <span class="Delimiter">[</span>0<span class="Delimiter">]</span> + <span class="Identifier">reply</span> result:address:array:character + <span class="Delimiter">}</span> + <span class="Comment"># save sign</span> + negate-result:boolean<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + negative?:boolean<span class="Special"> <- </span>lesser-than n:integer, 0:literal + <span class="Identifier">break-unless</span> negative?:boolean + negate-result:boolean<span class="Special"> <- </span>copy 1:literal + n:integer<span class="Special"> <- </span>multiply n:integer,<span class="Identifier"> -1</span>:literal + <span class="Delimiter">}</span> + <span class="Comment"># add digits from right to left into intermediate buffer</span> + tmp:address:buffer<span class="Special"> <- </span>init-buffer 30:literal + digit-base:integer<span class="Special"> <- </span>copy 48:literal <span class="Comment"># '0'</span> + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>equal n:integer, 0:literal + <span class="Identifier">break-if</span> done?:boolean + n:integer, digit:integer<span class="Special"> <- </span>divide-with-remainder n:integer, 10:literal + c:character<span class="Special"> <- </span>add digit-base:integer, digit:integer + tmp:address:buffer<span class="Special"> <- </span>buffer-append tmp:address:buffer, c:character + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># add sign</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> negate-result:boolean + tmp:address:buffer<span class="Special"> <- </span>buffer-append tmp:address:buffer, 45:literal <span class="Comment"># '-'</span> + <span class="Delimiter">}</span> + <span class="Comment"># reverse buffer into string result</span> + len:integer<span class="Special"> <- </span>get tmp:address:buffer/deref, length:offset + buf:address:array:character<span class="Special"> <- </span>get tmp:address:buffer/deref, data:offset + result:address:array:character<span class="Special"> <- </span>new character:type, len:integer + i:integer<span class="Special"> <- </span>subtract len:integer, 1:literal + j:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while i >= 0</span> + done?:boolean<span class="Special"> <- </span>lesser-than i:integer, 0:literal + <span class="Identifier">break-if</span> done?:boolean + <span class="Comment"># result[j] = tmp[i]</span> + src:character<span class="Special"> <- </span>index buf:address:array:character/deref, i:integer + dest:address:character<span class="Special"> <- </span>index-address result:address:array:character/deref, j:integer + dest:address:character/deref<span class="Special"> <- </span>copy src:character + <span class="Comment"># ++i</span> + i:integer<span class="Special"> <- </span>subtract i:integer, 1:literal + <span class="Comment"># --j</span> + j:integer<span class="Special"> <- </span>add j:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> result:address:array:character +<span class="Delimiter">]</span> + +scenario integer-to-decimal-digit-zero <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>integer-to-decimal-string 0:literal + 2:array:character/<span class="Special">raw <- </span>copy 1:address:array:character/deref/<span class="Special">raw</span> + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2:string<span class="Special"> <- </span><span class="Delimiter">[</span>0<span class="Delimiter">]</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario integer-to-decimal-digit-positive <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>integer-to-decimal-string 234:literal + 2:array:character/<span class="Special">raw <- </span>copy 1:address:array:character/deref/<span class="Special">raw</span> + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2:string<span class="Special"> <- </span><span class="Delimiter">[</span>234<span class="Delimiter">]</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario integer-to-decimal-digit-negative <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>integer-to-decimal-string<span class="Identifier"> -1</span>:literal + 2:array:character/<span class="Special">raw <- </span>copy 1:address:array:character/deref/<span class="Special">raw</span> + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>2 + 3<span class="Special"> <- </span>45 <span class="Comment"># '-'</span> + 4<span class="Special"> <- </span>49 <span class="Comment"># '1'</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +recipe string-append <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + <span class="Comment"># result = new string[a.length + b.length]</span> + a:address:array:character<span class="Special"> <- </span>next-ingredient + a-len:integer<span class="Special"> <- </span>length a:address:array:character/deref + b:address:array:character<span class="Special"> <- </span>next-ingredient + b-len:integer<span class="Special"> <- </span>length b:address:array:character/deref + result-len:integer<span class="Special"> <- </span>add a-len:integer, b-len:integer + result:address:array:character<span class="Special"> <- </span>new character:type, result-len:integer + <span class="Comment"># copy a into result</span> + result-idx:integer<span class="Special"> <- </span>copy 0:literal + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while i < a.length</span> + a-done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, a-len:integer + <span class="Identifier">break-if</span> a-done?:boolean + <span class="Comment"># result[result-idx] = a[i]</span> + out:address:character<span class="Special"> <- </span>index-address result:address:array:character/deref, result-idx:integer + in:character<span class="Special"> <- </span>index a:address:array:character/deref, i:integer + out:address:character/deref<span class="Special"> <- </span>copy in:character + <span class="Comment"># ++i</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Comment"># ++result-idx</span> + result-idx:integer<span class="Special"> <- </span>add result-idx:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># copy b into result</span> + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while i < b.length</span> + b-done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, b-len:integer + <span class="Identifier">break-if</span> b-done?:boolean + <span class="Comment"># result[result-idx] = a[i]</span> + out:address:character<span class="Special"> <- </span>index-address result:address:array:character/deref, result-idx:integer + in:character<span class="Special"> <- </span>index b:address:array:character/deref, i:integer + out:address:character/deref<span class="Special"> <- </span>copy in:character + <span class="Comment"># ++i</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Comment"># ++result-idx</span> + result-idx:integer<span class="Special"> <- </span>add result-idx:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> result:address:array:character +<span class="Delimiter">]</span> + +scenario string-append-1 <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>hello,<span class="Delimiter">]</span> + 2:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span> world!<span class="Delimiter">]</span> + 3:address:array:character/<span class="Special">raw <- </span>string-append 1:address:array:character/<span class="Special">raw</span>, 2:address:array:character/<span class="Special">raw</span> + 4:array:character/<span class="Special">raw <- </span>copy 3:address:array:character/<span class="Special">raw</span>/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 4:string<span class="Special"> <- </span><span class="Delimiter">[</span>hello, world!<span class="Delimiter">]</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +<span class="Comment"># replace underscores in first with remaining args</span> +<span class="Comment"># result:address:array:character <- interpolate template:address:array:character, ...</span> +recipe interpolate <span class="Delimiter">[</span> + default-space:array:address:location<span class="Special"> <- </span>new location:type, 60:literal + template:address:array:character<span class="Special"> <- </span>next-ingredient + <span class="Comment"># compute result-len, space to allocate for result</span> + tem-len:integer<span class="Special"> <- </span>length template:address:array:character/deref + result-len:integer<span class="Special"> <- </span>copy tem-len:integer + <span class="Delimiter">{</span> + <span class="Comment"># while arg received</span> + a:address:array:character, arg-received?:boolean<span class="Special"> <- </span>next-ingredient + <span class="Identifier">break-unless</span> arg-received?:boolean + <span class="Comment"># result-len = result-len + arg.length - 1 for the 'underscore' being replaced</span> + a-len:integer<span class="Special"> <- </span>length a:address:array:character/deref + result-len:integer<span class="Special"> <- </span>add result-len:integer, a-len:integer + result-len:integer<span class="Special"> <- </span>subtract result-len:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> +<span class="CommentedCode">#? $print tem-len:integer #? 1</span> +<span class="CommentedCode">#? $print [ ] #? 1</span> +<span class="CommentedCode">#? $print result-len:integer #? 1</span> +<span class="CommentedCode">#? $print [ #? 1</span> +<span class="CommentedCode">#? ] #? 1</span> + rewind-ingredients + _<span class="Special"> <- </span>next-ingredient <span class="Comment"># skip template</span> + <span class="Comment"># result = new array:character[result-len]</span> + result:address:array:character<span class="Special"> <- </span>new character:type, result-len:integer + <span class="Comment"># repeatedly copy sections of template and 'holes' into result</span> + result-idx:integer<span class="Special"> <- </span>copy 0:literal + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while arg received</span> + a:address:array:character, arg-received?:boolean<span class="Special"> <- </span>next-ingredient + <span class="Identifier">break-unless</span> arg-received?:boolean + <span class="Comment"># copy template into result until '_'</span> + <span class="Delimiter">{</span> + <span class="Comment"># while i < template.length</span> + tem-done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, tem-len:integer + <span class="Identifier">break-if</span> tem-done?:boolean, 2:blocks + <span class="Comment"># while template[i] != '_'</span> + in:character<span class="Special"> <- </span>index template:address:array:character/deref, i:integer + underscore?:boolean<span class="Special"> <- </span>equal in:character, 95:literal <span class="Comment"># '_'</span> + <span class="Identifier">break-if</span> underscore?:boolean + <span class="Comment"># result[result-idx] = template[i]</span> + out:address:character<span class="Special"> <- </span>index-address result:address:array:character/deref, result-idx:integer + out:address:character/deref<span class="Special"> <- </span>copy in:character + <span class="Comment"># ++i</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Comment"># ++result-idx</span> + result-idx:integer<span class="Special"> <- </span>add result-idx:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># copy 'a' into result</span> + j:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while j < a.length</span> + arg-done?:boolean<span class="Special"> <- </span>greater-or-equal j:integer, a-len:integer + <span class="Identifier">break-if</span> arg-done?:boolean + <span class="Comment"># result[result-idx] = a[j]</span> + in:character<span class="Special"> <- </span>index a:address:array:character/deref, j:integer + out:address:character<span class="Special"> <- </span>index-address result:address:array:character/deref, result-idx:integer + out:address:character/deref<span class="Special"> <- </span>copy in:character + <span class="Comment"># ++j</span> + j:integer<span class="Special"> <- </span>add j:integer, 1:literal + <span class="Comment"># ++result-idx</span> + result-idx:integer<span class="Special"> <- </span>add result-idx:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># skip '_' in template</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Identifier">loop</span> <span class="Comment"># interpolate next arg</span> + <span class="Delimiter">}</span> + <span class="Comment"># done with holes; copy rest of template directly into result</span> + <span class="Delimiter">{</span> + <span class="Comment"># while i < template.length</span> + tem-done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, tem-len:integer + <span class="Identifier">break-if</span> tem-done?:boolean + <span class="Comment"># result[result-idx] = template[i]</span> + in:character<span class="Special"> <- </span>index template:address:array:character/deref, i:integer + out:address:character<span class="Special"> <- </span>index-address result:address:array:character/deref, result-idx:integer + out:address:character/deref<span class="Special"> <- </span>copy in:character + <span class="Comment"># ++i</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Comment"># ++result-idx</span> + result-idx:integer<span class="Special"> <- </span>add result-idx:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> result:address:array:character +<span class="Delimiter">]</span> + +scenario interpolate-works <span class="Delimiter">[</span> +<span class="CommentedCode">#? dump run #? 1</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>abc _<span class="Delimiter">]</span> + 2:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>def<span class="Delimiter">]</span> + 3:address:array:character/<span class="Special">raw <- </span>interpolate 1:address:array:character/<span class="Special">raw</span>, 2:address:array:character/<span class="Special">raw</span> + 4:array:character/<span class="Special">raw <- </span>copy 3:address:array:character/<span class="Special">raw</span>/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 4:string<span class="Special"> <- </span><span class="Delimiter">[</span>abc def<span class="Delimiter">]</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario interpolate-at-start <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>_, hello!<span class="Delimiter">]</span> + 2:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + 3:address:array:character/<span class="Special">raw <- </span>interpolate 1:address:array:character/<span class="Special">raw</span>, 2:address:array:character/<span class="Special">raw</span> + 4:array:character/<span class="Special">raw <- </span>copy 3:address:array:character/<span class="Special">raw</span>/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 4:string<span class="Special"> <- </span><span class="Delimiter">[</span>abc, hello!<span class="Delimiter">]</span> + 16<span class="Special"> <- </span>0 <span class="Comment"># out of bounds</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario interpolate-at-end <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>hello, _<span class="Delimiter">]</span> + 2:address:array:character/<span class="Special">raw <- </span>new <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + 3:address:array:character/<span class="Special">raw <- </span>interpolate 1:address:array:character/<span class="Special">raw</span>, 2:address:array:character/<span class="Special">raw</span> + 4:array:character/<span class="Special">raw <- </span>copy 3:address:array:character/<span class="Special">raw</span>/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 4:string<span class="Special"> <- </span><span class="Delimiter">[</span>hello, abc<span class="Delimiter">]</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/061channel.mu.html b/html/061channel.mu.html new file mode 100644 index 00000000..2c6f19d3 --- /dev/null +++ b/html/061channel.mu.html @@ -0,0 +1,301 @@ +<!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/061channel.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.SalientComment { color: #00ffff; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># Mu synchronizes using channels rather than locks, like Erlang and Go.</span> +<span class="Comment">#</span> +<span class="Comment"># The two ends of a channel will usually belong to different routines, but</span> +<span class="Comment"># each end should only be used by a single one. Don't try to read from or</span> +<span class="Comment"># write to it from multiple routines at once.</span> +<span class="Comment">#</span> +<span class="Comment"># The key property of channels is that writing to a full channel or reading</span> +<span class="Comment"># from an empty one will put the current routine in 'waiting' state until the</span> +<span class="Comment"># operation can be completed.</span> + +scenario channel <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 3:literal/capacity + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + 2:integer, 1:address:channel<span class="Special"> <- </span>read 1:address:channel + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>34 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +container channel <span class="Delimiter">[</span> + <span class="Comment"># To avoid locking, writer and reader will never write to the same location.</span> + <span class="Comment"># So channels will include fields in pairs, one for the writer and one for the</span> + <span class="Comment"># reader.</span> + first-full:integer <span class="Comment"># for write</span> + first-free:integer <span class="Comment"># for read</span> + <span class="Comment"># A circular buffer contains values from index first-full up to (but not</span> + <span class="Comment"># including) index first-empty. The reader always modifies it at first-full,</span> + <span class="Comment"># while the writer always modifies it at first-empty.</span> + data:address:array:location +<span class="Delimiter">]</span> + +<span class="Comment"># result:address:channel <- init-channel capacity:integer</span> +recipe init-channel <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + <span class="Comment"># result = new channel</span> + result:address:channel<span class="Special"> <- </span>new channel:type + <span class="Comment"># result.first-full = 0</span> + full:address:integer<span class="Special"> <- </span>get-address result:address:channel/deref, first-full:offset + full:address:integer/deref<span class="Special"> <- </span>copy 0:literal + <span class="Comment"># result.first-free = 0</span> + free:address:integer<span class="Special"> <- </span>get-address result:address:channel/deref, first-free:offset + free:address:integer/deref<span class="Special"> <- </span>copy 0:literal + <span class="Comment"># result.data = new location[ingredient+1]</span> + capacity:integer<span class="Special"> <- </span>next-ingredient + capacity:integer<span class="Special"> <- </span>add capacity:integer, 1:literal <span class="Comment"># unused slot for 'full?' below</span> + dest:address:address:array:location<span class="Special"> <- </span>get-address result:address:channel/deref, data:offset + dest:address:address:array:location/deref<span class="Special"> <- </span>new location:type, capacity:integer + <span class="Identifier">reply</span> result:address:channel +<span class="Delimiter">]</span> + +<span class="Comment"># chan:address:channel <- write chan:address:channel, val:location</span> +recipe write <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + chan:address:channel<span class="Special"> <- </span>next-ingredient + val:location<span class="Special"> <- </span>next-ingredient + <span class="Delimiter">{</span> + <span class="Comment"># block if chan is full</span> + full:boolean<span class="Special"> <- </span>channel-full? chan:address:channel + <span class="Identifier">break-unless</span> full:boolean + full-address:address:integer<span class="Special"> <- </span>get-address chan:address:channel/deref, first-full:offset + wait-for-location full-address:address:integer/deref + <span class="Delimiter">}</span> + <span class="Comment"># store val</span> + circular-buffer:address:array:location<span class="Special"> <- </span>get chan:address:channel/deref, data:offset + free:address:integer<span class="Special"> <- </span>get-address chan:address:channel/deref, first-free:offset + dest:address:location<span class="Special"> <- </span>index-address circular-buffer:address:array:location/deref, free:address:integer/deref + dest:address:location/deref<span class="Special"> <- </span>copy val:location + <span class="Comment"># increment free</span> + free:address:integer/deref<span class="Special"> <- </span>add free:address:integer/deref, 1:literal + <span class="Delimiter">{</span> + <span class="Comment"># wrap free around to 0 if necessary</span> + len:integer<span class="Special"> <- </span>length circular-buffer:address:array:location/deref + at-end?:boolean<span class="Special"> <- </span>greater-or-equal free:address:integer/deref, len:integer + <span class="Identifier">break-unless</span> at-end?:boolean + free:address:integer/deref<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> chan:address:channel/same-as-ingredient:0 +<span class="Delimiter">]</span> + +<span class="Comment"># result:location, chan:address:channel <- read chan:address:channel</span> +recipe read <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + chan:address:channel<span class="Special"> <- </span>next-ingredient + <span class="Delimiter">{</span> + <span class="Comment"># block if chan is empty</span> + empty:boolean<span class="Special"> <- </span>channel-empty? chan:address:channel + <span class="Identifier">break-unless</span> empty:boolean + free-address:address:integer<span class="Special"> <- </span>get-address chan:address:channel/deref, first-free:offset + wait-for-location free-address:address:integer/deref + <span class="Delimiter">}</span> + <span class="Comment"># read result</span> + full:address:integer<span class="Special"> <- </span>get-address chan:address:channel/deref, first-full:offset + circular-buffer:address:array:location<span class="Special"> <- </span>get chan:address:channel/deref, data:offset + result:location<span class="Special"> <- </span>index circular-buffer:address:array:location/deref, full:address:integer/deref + <span class="Comment"># increment full</span> + full:address:integer/deref<span class="Special"> <- </span>add full:address:integer/deref, 1:literal + <span class="Delimiter">{</span> + <span class="Comment"># wrap full around to 0 if necessary</span> + len:integer<span class="Special"> <- </span>length circular-buffer:address:array:location/deref + at-end?:boolean<span class="Special"> <- </span>greater-or-equal full:address:integer/deref, len:integer + <span class="Identifier">break-unless</span> at-end?:boolean + full:address:integer/deref<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> result:location, chan:address:channel/same-as-ingredient:0 +<span class="Delimiter">]</span> + +scenario channel-initialization <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 3:literal/capacity + 2:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-full:offset + 3:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-free:offset + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># first-full</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># first-free</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario channel-write-increments-free <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 3:literal/capacity + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + 2:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-full:offset + 3:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-free:offset + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># first-full</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># first-free</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario channel-read-increments-full <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 3:literal/capacity + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + _, 1:address:channel<span class="Special"> <- </span>read 1:address:channel + 2:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-full:offset + 3:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-free:offset + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># first-full</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># first-free</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario channel-wrap <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + <span class="Comment"># channel with just 1 slot</span> + 1:address:channel<span class="Special"> <- </span>init-channel 1:literal/capacity + <span class="Comment"># write and read a value</span> + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + _, 1:address:channel<span class="Special"> <- </span>read 1:address:channel + <span class="Comment"># first-free will now be 1</span> + 2:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-free:offset + 3:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-free:offset + <span class="Comment"># write second value, verify that first-free wraps</span> + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + 4:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-free:offset + <span class="Comment"># read second value, verify that first-full wraps</span> + _, 1:address:channel<span class="Special"> <- </span>read 1:address:channel + 5:integer<span class="Special"> <- </span>get 1:address:channel/deref, first-full:offset + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># first-free after first write</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># first-full after first read</span> + 4<span class="Special"> <- </span>0 <span class="Comment"># first-free after second write, wrapped</span> + 5<span class="Special"> <- </span>0 <span class="Comment"># first-full after second read, wrapped</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +<span class="SalientComment">## helpers</span> + +<span class="Comment"># An empty channel has first-empty and first-full both at the same value.</span> +recipe channel-empty? <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + chan:address:channel<span class="Special"> <- </span>next-ingredient + <span class="Comment"># return chan.first-full == chan.first-free</span> + full:integer<span class="Special"> <- </span>get chan:address:channel/deref, first-full:offset + free:integer<span class="Special"> <- </span>get chan:address:channel/deref, first-free:offset + result:boolean<span class="Special"> <- </span>equal full:integer, free:integer + <span class="Identifier">reply</span> result:boolean +<span class="Delimiter">]</span> + +<span class="Comment"># A full channel has first-empty just before first-full, wasting one slot.</span> +<span class="Comment"># (Other alternatives: <a href="https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)">https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)</a></span> +recipe channel-full? <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + chan:address:channel<span class="Special"> <- </span>next-ingredient + <span class="Comment"># tmp = chan.first-free + 1</span> + tmp:integer<span class="Special"> <- </span>get chan:address:channel/deref, first-free:offset + tmp:integer<span class="Special"> <- </span>add tmp:integer, 1:literal + <span class="Delimiter">{</span> + <span class="Comment"># if tmp == chan.capacity, tmp = 0</span> + len:integer<span class="Special"> <- </span>channel-capacity chan:address:channel + at-end?:boolean<span class="Special"> <- </span>greater-or-equal tmp:integer, len:integer + <span class="Identifier">break-unless</span> at-end?:boolean + tmp:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">}</span> + <span class="Comment"># return chan.first-full == tmp</span> + full:integer<span class="Special"> <- </span>get chan:address:channel/deref, first-full:offset + result:boolean<span class="Special"> <- </span>equal full:integer, tmp:integer + <span class="Identifier">reply</span> result:boolean +<span class="Delimiter">]</span> + +<span class="Comment"># result:integer <- channel-capacity chan:address:channel</span> +recipe channel-capacity <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + chan:address:channel<span class="Special"> <- </span>next-ingredient + q:address:array:location<span class="Special"> <- </span>get chan:address:channel/deref, data:offset + result:integer<span class="Special"> <- </span>length q:address:array:location/deref + <span class="Identifier">reply</span> result:integer +<span class="Delimiter">]</span> + +scenario channel-new-empty-not-full <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 3:literal/capacity + 2:integer<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:integer<span class="Special"> <- </span>channel-full? 1:address:channel + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># full?</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario channel-write-not-empty <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 3:literal/capacity + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + 2:integer<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:integer<span class="Special"> <- </span>channel-full? 1:address:channel + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># full?</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario channel-write-full <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 1:literal/capacity + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + 2:integer<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:integer<span class="Special"> <- </span>channel-full? 1:address:channel + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>0 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>1 <span class="Comment"># full?</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario channel-read-not-full <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:channel<span class="Special"> <- </span>init-channel 1:literal/capacity + 1:address:channel<span class="Special"> <- </span>write 1:address:channel, 34:literal + _, 1:address:channel<span class="Special"> <- </span>read 1:address:channel + 2:integer<span class="Special"> <- </span>channel-empty? 1:address:channel + 3:integer<span class="Special"> <- </span>channel-full? 1:address:channel + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># empty?</span> + 3<span class="Special"> <- </span>0 <span class="Comment"># full?</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/062array.mu.html b/html/062array.mu.html new file mode 100644 index 00000000..e765ca2a --- /dev/null +++ b/html/062array.mu.html @@ -0,0 +1,74 @@ +<!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/062array.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +scenario array-from-args <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> + 1:address:array:location<span class="Special"> <- </span>init-array 0:literal, 1:literal, 2:literal + 2:array:location<span class="Special"> <- </span>copy 1:address:array:location/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 2<span class="Special"> <- </span>3 <span class="Comment"># array length</span> + 3<span class="Special"> <- </span>0 + 4<span class="Special"> <- </span>1 + 5<span class="Special"> <- </span>2 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +<span class="Comment"># create an array out of a list of scalar args</span> +recipe init-array <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + capacity:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while read curr-value</span> + curr-value:location, exists?:boolean<span class="Special"> <- </span>next-ingredient + <span class="Identifier">break-unless</span> exists?:boolean + capacity:integer<span class="Special"> <- </span>add capacity:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + result:address:array:location<span class="Special"> <- </span>new location:type, capacity:integer + rewind-ingredients + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + <span class="Comment"># while read curr-value</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, capacity:integer + <span class="Identifier">break-if</span> done?:boolean + curr-value:location, exists?:boolean<span class="Special"> <- </span>next-ingredient + assert exists?:boolean, <span class="Delimiter">[</span>error in rewinding ingredients to init-array<span class="Delimiter">]</span> + tmp:address:location<span class="Special"> <- </span>index-address result:address:array:location/deref, i:integer + tmp:address:location/deref<span class="Special"> <- </span>copy curr-value:location + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> result:address:array:location +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/070display.cc.html b/html/070display.cc.html new file mode 100644 index 00000000..2f9504da --- /dev/null +++ b/html/070display.cc.html @@ -0,0 +1,250 @@ +<!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/070display.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; } +.cSpecial { color: #008000; } +.Identifier { color: #008080; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.SalientComment { color: #00ffff; } +.CommentedCode { color: #6c6c6c; } +.PreProc { color: #c000c0; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Take charge of the text-mode display and keyboard.</span> + +<span class="Comment">// uncomment to debug console programs</span> +<span class="Delimiter">:(before "End Globals")</span> +<span class="CommentedCode">//? ofstream LOG("log.txt");</span> + +<span class="SalientComment">//:: Display management</span> + +<span class="Delimiter">:(before "End Globals")</span> +index_t Display_row = <span class="Constant">0</span><span class="Delimiter">,</span> Display_column = <span class="Constant">0</span><span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +SWITCH_TO_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"switch-to-display"</span>] = SWITCH_TO_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case SWITCH_TO_DISPLAY: <span class="Delimiter">{</span> + tb_init<span class="Delimiter">();</span> + Display_row = Display_column = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +RETURN_TO_CONSOLE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"return-to-console"</span>] = RETURN_TO_CONSOLE<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case RETURN_TO_CONSOLE: <span class="Delimiter">{</span> + tb_shutdown<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +CLEAR_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"clear-display"</span>] = CLEAR_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case CLEAR_DISPLAY: <span class="Delimiter">{</span> + tb_clear<span class="Delimiter">();</span> + Display_row = Display_column = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +CLEAR_LINE_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"clear-line-on-display"</span>] = CLEAR_LINE_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case CLEAR_LINE_ON_DISPLAY: <span class="Delimiter">{</span> + size_t width = tb_width<span class="Delimiter">();</span> + for <span class="Delimiter">(</span>index_t x = Display_column<span class="Delimiter">;</span> x < width<span class="Delimiter">;</span> ++x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + tb_change_cell<span class="Delimiter">(</span>x<span class="Delimiter">,</span> Display_row<span class="Delimiter">,</span> <span class="Constant">' '</span><span class="Delimiter">,</span> TB_WHITE<span class="Delimiter">,</span> TB_DEFAULT<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +PRINT_CHARACTER_TO_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"print-character-to-display"</span>] = PRINT_CHARACTER_TO_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span> + vector<long long int> arg = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + int h=tb_height<span class="Delimiter">(),</span> w=tb_width<span class="Delimiter">();</span> + size_t height = <span class="Delimiter">(</span>h >= <span class="Constant">0</span><span class="Delimiter">)</span> ? h : <span class="Constant">0</span><span class="Delimiter">;</span> + size_t width = <span class="Delimiter">(</span>w >= <span class="Constant">0</span><span class="Delimiter">)</span> ? w : <span class="Constant">0</span><span class="Delimiter">;</span> + if <span class="Delimiter">(</span>arg[<span class="Constant">0</span>] == <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + if <span class="Delimiter">(</span>Display_row < height<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Display_column = <span class="Constant">0</span><span class="Delimiter">;</span> + ++Display_row<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + tb_change_cell<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">,</span> arg[<span class="Constant">0</span>]<span class="Delimiter">,</span> TB_WHITE<span class="Delimiter">,</span> TB_DEFAULT<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>Display_column < width<span class="Delimiter">)</span> <span class="Delimiter">{</span> + Display_column++<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +CURSOR_POSITION_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"cursor-position-on-display"</span>] = CURSOR_POSITION_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case CURSOR_POSITION_ON_DISPLAY: <span class="Delimiter">{</span> + vector<long long int> row<span class="Delimiter">;</span> + row<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Display_row<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> row<span class="Delimiter">);</span> + vector<long long int> column<span class="Delimiter">;</span> + column<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Display_column<span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> column<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MOVE_CURSOR_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"move-cursor-on-display"</span>] = MOVE_CURSOR_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MOVE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span> + vector<long long int> row = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">);</span> + vector<long long int> column = read_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<span class="Constant">1</span>]<span class="Delimiter">);</span> + Display_row = row[<span class="Constant">0</span>]<span class="Delimiter">;</span> + Display_column = column[<span class="Constant">0</span>]<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MOVE_CURSOR_DOWN_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"move-cursor-down-on-display"</span>] = MOVE_CURSOR_DOWN_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MOVE_CURSOR_DOWN_ON_DISPLAY: <span class="Delimiter">{</span> + Display_row++<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MOVE_CURSOR_UP_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"move-cursor-up-on-display"</span>] = MOVE_CURSOR_UP_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MOVE_CURSOR_UP_ON_DISPLAY: <span class="Delimiter">{</span> + Display_row--<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MOVE_CURSOR_RIGHT_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"move-cursor-right-on-display"</span>] = MOVE_CURSOR_RIGHT_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MOVE_CURSOR_RIGHT_ON_DISPLAY: <span class="Delimiter">{</span> + Display_column++<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +MOVE_CURSOR_LEFT_ON_DISPLAY<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"move-cursor-left-on-display"</span>] = MOVE_CURSOR_LEFT_ON_DISPLAY<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case MOVE_CURSOR_LEFT_ON_DISPLAY: <span class="Delimiter">{</span> + Display_column--<span class="Delimiter">;</span> + tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span> + tb_present<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="SalientComment">//:: Keyboard management</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +WAIT_FOR_KEY_FROM_KEYBOARD<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"wait-for-key-from-keyboard"</span>] = WAIT_FOR_KEY_FROM_KEYBOARD<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case WAIT_FOR_KEY_FROM_KEYBOARD: <span class="Delimiter">{</span> +<span class="CommentedCode">//? LOG << "AAA\n"; LOG.flush();</span> + struct tb_event event<span class="Delimiter">;</span> + do <span class="Delimiter">{</span> + tb_poll_event<span class="Delimiter">(</span>&event<span class="Delimiter">);</span> + <span class="Delimiter">}</span> while <span class="Delimiter">(</span>event<span class="Delimiter">.</span>type != TB_EVENT_KEY<span class="Delimiter">);</span> +<span class="CommentedCode">//? LOG << "AAA 2\n"; LOG.flush();</span> + vector<long long int> result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>ch<span class="Delimiter">);</span> +<span class="CommentedCode">//? LOG << "AAA 3\n"; LOG.flush();</span> + if <span class="Delimiter">(</span>!current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>empty<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="CommentedCode">//? LOG << "AAA 9\n"; LOG.flush();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +READ_KEY_FROM_KEYBOARD<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"read-key-from-keyboard"</span>] = READ_KEY_FROM_KEYBOARD<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case READ_KEY_FROM_KEYBOARD: <span class="Delimiter">{</span> + struct tb_event event<span class="Delimiter">;</span> + int event_type = tb_peek_event<span class="Delimiter">(</span>&event<span class="Delimiter">,</span> <span class="Constant">5</span><span class="Comment">/*</span><span class="Comment">ms</span><span class="Comment">*/</span><span class="Delimiter">);</span> + vector<long long int> result<span class="Delimiter">;</span> + vector<long long int> found<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>event_type != TB_EVENT_KEY<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + found<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">false</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>event<span class="Delimiter">.</span>ch<span class="Delimiter">);</span> + found<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">true</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> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products[<span class="Constant">1</span>]<span class="Delimiter">,</span> found<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include</span><span class="Constant">"termbox/termbox.h"</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/071print.mu.html b/html/071print.mu.html new file mode 100644 index 00000000..04f05a77 --- /dev/null +++ b/html/071print.mu.html @@ -0,0 +1,309 @@ +<!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/071print.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.CommentedCode { color: #6c6c6c; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># Wrappers around print primitives that take a 'screen' object and are thus</span> +<span class="Comment"># easier to test.</span> + +container screen <span class="Delimiter">[</span> + num-rows:integer + num-columns:integer + cursor-row:integer + cursor-column:integer + data:address:array:character +<span class="Delimiter">]</span> + +recipe init-fake-screen <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal/capacity + result:address:screen<span class="Special"> <- </span>new screen:type + width:address:integer<span class="Special"> <- </span>get-address result:address:screen/deref, num-columns:offset + width:address:integer/deref<span class="Special"> <- </span>next-ingredient + height:address:integer<span class="Special"> <- </span>get-address result:address:screen/deref, num-rows:offset + height:address:integer/deref<span class="Special"> <- </span>next-ingredient + row:address:integer<span class="Special"> <- </span>get-address result:address:screen/deref, cursor-row:offset + row:address:integer/deref<span class="Special"> <- </span>copy 0:literal + column:address:integer<span class="Special"> <- </span>get-address result:address:screen/deref, cursor-column:offset + column:address:integer/deref<span class="Special"> <- </span>copy 0:literal + bufsize:integer<span class="Special"> <- </span>multiply width:address:integer/deref, height:address:integer/deref + buf:address:address:array:character<span class="Special"> <- </span>get-address result:address:screen/deref, data:offset + buf:address:address:array:character/deref<span class="Special"> <- </span>new character:literal, bufsize:integer + clear-screen result:address:screen + <span class="Identifier">reply</span> result:address:screen +<span class="Delimiter">]</span> + +recipe clear-screen <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + <span class="Comment"># clear fake screen</span> + buf:address:array:character<span class="Special"> <- </span>get x:address:screen/deref, data:offset + max:integer<span class="Special"> <- </span>length buf:address:array:character/deref + i:integer<span class="Special"> <- </span>copy 0:literal + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i:integer, max:integer + <span class="Identifier">break-if</span> done?:boolean + c:address:character<span class="Special"> <- </span>index-address buf:address:array:character/deref, i:integer + c:address:character/deref<span class="Special"> <- </span>copy <span class="Delimiter">[</span> <span class="Delimiter">]</span> + i:integer<span class="Special"> <- </span>add i:integer, 1:literal + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + clear-display + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +recipe print-character <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + c:character<span class="Special"> <- </span>next-ingredient +<span class="CommentedCode">#? $print x:address:character #? 1</span> +<span class="CommentedCode">#? $print [ print-character #? 1</span> +<span class="CommentedCode">#? ] #? 1</span> + <span class="Delimiter">{</span> + <span class="Comment"># if x exists</span> + <span class="Identifier">break-unless</span> x:address:screen +<span class="CommentedCode">#? $print [print-character2 #? 1</span> +<span class="CommentedCode">#? ] #? 1</span> + <span class="Comment"># save character in fake screen</span> + row:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref, cursor-row:offset + column:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref, cursor-column:offset + width:integer<span class="Special"> <- </span>get x:address:screen/deref, num-columns:offset + index:integer<span class="Special"> <- </span>multiply row:address:integer/deref, width:integer + index:integer<span class="Special"> <- </span>add index:integer, column:address:integer/deref + buf:address:array:character<span class="Special"> <- </span>get x:address:screen/deref, data:offset + cursor:address:character<span class="Special"> <- </span>index-address buf:address:array:character/deref, index:integer +<span class="CommentedCode">#? $print cursor:address:character #? 1</span> +<span class="CommentedCode">#? $print [ #? 1</span> +<span class="CommentedCode">#? ] #? 1</span> + cursor:address:character/deref<span class="Special"> <- </span>copy c:character <span class="Comment"># todo: newline, etc.</span> + <span class="Comment"># increment column unless it's already all the way to the right</span> + <span class="Delimiter">{</span> + at-right?:boolean<span class="Special"> <- </span>equal column:address:integer/deref, width:integer + <span class="Identifier">break-if</span> at-right?:boolean + column:address:integer/deref<span class="Special"> <- </span>add column:address:integer/deref, 1:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + print-character-to-display c:character + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +scenario print-character-at-top-left <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> +<span class="CommentedCode">#? $start-tracing #? 3</span> + 1:address:screen<span class="Special"> <- </span>init-fake-screen 3:literal/width, 2:literal/height + 1:address:screen<span class="Special"> <- </span>print-character 1:address:screen, 97:literal <span class="Comment"># 'a'</span> + 2:address:array:character<span class="Special"> <- </span>get 1:address:screen/deref, data:offset + 3:array:character<span class="Special"> <- </span>copy 2:address:array:character/deref + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 4<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 5<span class="Special"> <- </span>0 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +recipe clear-line <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, clear line in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + n:integer<span class="Special"> <- </span>get x:address:screen/deref, num-columns:offset + column:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref, cursor-column:offset + original-column:integer<span class="Special"> <- </span>copy column:address:integer/deref + <span class="Comment"># space over the entire line</span> + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal column:address:integer/deref, n:integer + <span class="Identifier">break-if</span> done?:boolean + print-character x:address:screen, <span class="Delimiter">[</span> <span class="Delimiter">]</span> <span class="Comment"># implicitly updates 'column'</span> + <span class="Identifier">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># now back to where the cursor was</span> + column:address:integer/deref<span class="Special"> <- </span>copy original-column:integer + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + clear-line-on-display + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +recipe cursor-position <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, lookup cursor in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + row:integer<span class="Special"> <- </span>get x:address:screen/deref, cursor-row:offset + column:integer<span class="Special"> <- </span>get x:address:screen/deref, cursor-column:offset + <span class="Identifier">reply</span> row:integer, column:integer + <span class="Delimiter">}</span> + row:integer, column:integer<span class="Special"> <- </span>cursor-position-on-display + <span class="Identifier">reply</span> row:integer, column:integer +<span class="Delimiter">]</span> + +recipe move-cursor <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + new-row:integer<span class="Special"> <- </span>next-ingredient + new-column:integer<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, move cursor in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + row:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref cursor-row:offset + row:address:integer/deref<span class="Special"> <- </span>copy new-row:integer + column:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref cursor-column:offset + column:address:integer/deref<span class="Special"> <- </span>copy new-column:integer + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + move-cursor-on-display new-row:integer, new-column:integer + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +scenario clear-line-erases-printed-characters <span class="Delimiter">[</span> + run <span class="Delimiter">[</span> +<span class="CommentedCode">#? $start-tracing #? 3</span> + 1:address:screen<span class="Special"> <- </span>init-fake-screen 3:literal/width, 2:literal/height + <span class="Comment"># print a character</span> + 1:address:screen<span class="Special"> <- </span>print-character 1:address:screen, 97:literal <span class="Comment"># 'a'</span> + <span class="Comment"># move cursor to start of line</span> + 1:address:screen<span class="Special"> <- </span>move-cursor 1:address:screen, 0:literal/row, 0:literal/column + <span class="Comment"># clear line</span> + 1:address:screen<span class="Special"> <- </span>clear-line 1:address:screen + 2:address:array:character<span class="Special"> <- </span>get 1:address:screen/deref, data:offset + 3:array:character<span class="Special"> <- </span>copy 2:address:array:character/deref + <span class="Delimiter">]</span> + <span class="Comment"># screen should be blank</span> + memory-should-contain <span class="Delimiter">[</span> + 3<span class="Special"> <- </span>6 <span class="Comment"># width*height</span> + 4<span class="Special"> <- </span>0 + 5<span class="Special"> <- </span>0 + 6<span class="Special"> <- </span>0 + 7<span class="Special"> <- </span>0 + 8<span class="Special"> <- </span>0 + 9<span class="Special"> <- </span>0 + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +recipe cursor-down <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, move cursor in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + <span class="Delimiter">{</span> + <span class="Comment"># if row < height</span> + height:integer<span class="Special"> <- </span>get x:address:screen/deref, num-rows:offset + row:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref cursor-row:offset + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal row:address:integer/deref, height:integer + <span class="Identifier">break-if</span> at-bottom?:boolean + <span class="Comment"># row = row+1</span> + row:address:integer/deref<span class="Special"> <- </span>add row:address:integer, 1:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + move-cursor-down-on-display + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +recipe cursor-up <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, move cursor in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + <span class="Delimiter">{</span> + <span class="Comment"># if row >= 0</span> + row:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref cursor-row:offset + at-top?:boolean<span class="Special"> <- </span>lesser-than row:address:integer/deref, 0:literal + <span class="Identifier">break-if</span> at-top?:boolean + <span class="Comment"># row = row-1</span> + row:address:integer/deref<span class="Special"> <- </span>subtract row:address:integer, 1:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + move-cursor-up-on-display + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +recipe cursor-right <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, move cursor in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + <span class="Delimiter">{</span> + <span class="Comment"># if column < width</span> + width:integer<span class="Special"> <- </span>get x:address:screen/deref, num-columns:offset + column:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref cursor-column:offset + at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal column:address:integer/deref, width:integer + <span class="Identifier">break-if</span> at-bottom?:boolean + <span class="Comment"># column = column+1</span> + column:address:integer/deref<span class="Special"> <- </span>add column:address:integer, 1:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + move-cursor-right-on-display + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> + +recipe cursor-left <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:screen<span class="Special"> <- </span>next-ingredient + <span class="Comment"># if x exists, move cursor in fake screen</span> + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:screen + <span class="Delimiter">{</span> + <span class="Comment"># if column >= 0</span> + column:address:integer<span class="Special"> <- </span>get-address x:address:screen/deref cursor-column:offset + at-top?:boolean<span class="Special"> <- </span>lesser-than column:address:integer/deref, 0:literal + <span class="Identifier">break-if</span> at-top?:boolean + <span class="Comment"># column = column-1</span> + column:address:integer/deref<span class="Special"> <- </span>subtract column:address:integer, 1:literal + <span class="Delimiter">}</span> + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 + <span class="Delimiter">}</span> + <span class="Comment"># otherwise, real screen</span> + move-cursor-left-on-display + <span class="Identifier">reply</span> x:address:screen/same-as-ingredient:0 +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/072scenario_screen.cc.html b/html/072scenario_screen.cc.html new file mode 100644 index 00000000..ddb4b901 --- /dev/null +++ b/html/072scenario_screen.cc.html @@ -0,0 +1,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>~/Desktop/s/mu/072scenario_screen.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; } +.cSpecial { color: #008000; } +.Identifier { color: #008080; } +.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">//: Clean syntax to manipulate and check the screen in scenarios.</span> +<span class="Comment">//: Instructions 'assume-screen' and 'screen-should-contain' implicitly create</span> +<span class="Comment">//: a variable called 'screen' that is accessible inside other 'run'</span> +<span class="Comment">//: instructions in the scenario.</span> + +<span class="Delimiter">:(scenarios run_mu_scenario)</span> +<span class="Delimiter">:(scenario screen_in_scenario)</span> +scenario screen-in-scenario [ +<span class="CommentedCode">#? $start-tracing</span> + assume-screen <span class="Constant">5</span>:literal/width<span class="Delimiter">,</span> <span class="Constant">3</span>:literal/height + run [ + screen:address<span class="Special"> <- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>:literal <span class="Comment"># 'a'</span> + ] + screen-should-contain [ + <span class="Comment"># 01234</span> + <span class="Delimiter">.</span>a <span class="Delimiter">.</span> + <span class="Delimiter">.</span> <span class="Delimiter">.</span> + <span class="Delimiter">.</span> <span class="Delimiter">.</span> + ] +<span class="CommentedCode">#? $exit</span> +] + +<span class="Delimiter">:(scenario screen_in_scenario_error)</span> +<span class="CommentedCode">#? % cerr << "AAA\n";</span> +<span class="Special">% Hide_warnings = true;</span> +scenario screen-in-scenario-error [ + assume-screen <span class="Constant">5</span>:literal/width<span class="Delimiter">,</span> <span class="Constant">3</span>:literal/height + run [ + screen:address<span class="Special"> <- </span>print-character screen:address<span class="Delimiter">,</span> <span class="Constant">97</span>:literal <span class="Comment"># 'a'</span> + ] + screen-should-contain [ + <span class="Comment"># 01234</span> + <span class="Delimiter">.</span>b <span class="Delimiter">.</span> + <span class="Delimiter">.</span> <span class="Delimiter">.</span> + <span class="Delimiter">.</span> <span class="Delimiter">.</span> + ] +] +<span class="traceContains">+warn: expected screen location (0, 0) to contain 'b' instead of 'a'</span> + +<span class="Delimiter">:(before "End Globals")</span> +<span class="Comment">// Scenarios may not define default-space, so they should fit within the</span> +<span class="Comment">// initial area of memory reserved for tests. We'll put the predefined</span> +<span class="Comment">// variables available to them at the end of that region.</span> +const size_t Max_variables_in_scenarios = Reserved_for_tests-<span class="Constant">100</span><span class="Delimiter">;</span> +size_t Next_predefined_global_for_scenarios = Max_variables_in_scenarios<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +assert<span class="Delimiter">(</span>Next_predefined_global_for_scenarios < Reserved_for_tests<span class="Delimiter">);</span> +<span class="Delimiter">:(after "transform_all()" following "case RUN:")</span> +<span class="Comment">// There's a restriction on the number of variables 'run' can use, so that</span> +<span class="Comment">// it can avoid colliding with the dynamic allocator in case it doesn't</span> +<span class="Comment">// initialize a default-space.</span> +assert<span class="Delimiter">(</span>Name[tmp_recipe[<span class="Constant">0</span>]][<span class="Constant">""</span>] < Max_variables_in_scenarios<span class="Delimiter">);</span> + +<span class="Delimiter">:(before "End Globals")</span> +<span class="Comment">// Scenario Globals.</span> +const size_t SCREEN = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span> +<span class="Comment">// End Scenario Globals.</span> +<span class="Delimiter">:(before "End Predefined Scenario Locals In Run")</span> +Name[tmp_recipe[<span class="Constant">0</span>]][<span class="Constant">"screen"</span>] = SCREEN<span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Rewrite Instruction(curr)")</span> +<span class="Comment">// rewrite `assume-screen width, height` to</span> +<span class="Comment">// `screen:address <- init-fake-screen width, height`</span> +<span class="CommentedCode">//? cout << "before: " << curr.to_string() << '\n'; //? 1</span> +if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"assume-screen"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + curr<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"init-fake-screen"</span>]<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"screen:address"</span><span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>products[<span class="Constant">0</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>SCREEN<span class="Delimiter">);</span> +<span class="CommentedCode">//? cout << "after: " << curr.to_string() << '\n'; //? 1</span> +<span class="CommentedCode">//? cout << "AAA " << Recipe_number["init-fake-screen"] << '\n'; //? 1</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: screen-should-contain is a regular instruction</span> +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +SCREEN_SHOULD_CONTAIN<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +Recipe_number[<span class="Constant">"screen-should-contain"</span>] = SCREEN_SHOULD_CONTAIN<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +case SCREEN_SHOULD_CONTAIN: <span class="Delimiter">{</span> +<span class="CommentedCode">//? cout << "AAA\n"; //? 1</span> + check_screen<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients[<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> +void check_screen<span class="Delimiter">(</span>const string& contents<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>top<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Comment">// not supported</span> + index_t screen_location = Memory[SCREEN]<span class="Delimiter">;</span> + int data_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">"screen"</span>]<span class="Delimiter">,</span> <span class="Constant">"data"</span><span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>data_offset >= <span class="Constant">0</span><span class="Delimiter">);</span> + index_t screen_data_location = screen_location+data_offset<span class="Delimiter">;</span> <span class="Comment">// type: address:array:character</span> + index_t screen_data_start = Memory[screen_data_location]<span class="Delimiter">;</span> <span class="Comment">// type: array:character</span> + int width_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">"screen"</span>]<span class="Delimiter">,</span> <span class="Constant">"num-columns"</span><span class="Delimiter">);</span> + size_t screen_width = Memory[screen_location+width_offset]<span class="Delimiter">;</span> + int height_offset = find_element_name<span class="Delimiter">(</span>Type_number[<span class="Constant">"screen"</span>]<span class="Delimiter">,</span> <span class="Constant">"num-rows"</span><span class="Delimiter">);</span> + size_t screen_height = Memory[screen_location+height_offset]<span class="Delimiter">;</span> + string expected_contents<span class="Delimiter">;</span> + istringstream in<span class="Delimiter">(</span>contents<span class="Delimiter">);</span> + in >> std::noskipws<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t row = <span class="Constant">0</span><span class="Delimiter">;</span> row < screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span> + assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span> + for <span class="Delimiter">(</span>index_t column = <span class="Constant">0</span><span class="Delimiter">;</span> column < screen_width<span class="Delimiter">;</span> ++column<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">());</span> + expected_contents += in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + assert<span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> +<span class="CommentedCode">//? assert(in.get() == ']');</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"checking screen size at "</span> << screen_data_start<span class="Delimiter">;</span> +<span class="CommentedCode">//? cout << expected_contents.size() << '\n'; //? 1</span> + if <span class="Delimiter">(</span>Memory[screen_data_start] > static_cast<signed><span class="Delimiter">(</span>expected_contents<span class="Delimiter">.</span>size<span class="Delimiter">()))</span> + raise << <span class="Constant">"expected contents are larger than screen size "</span> << Memory[screen_data_start] << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + ++screen_data_start<span class="Delimiter">;</span> <span class="Comment">// now skip length</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < expected_contents<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"checking location "</span> << screen_data_start+i<span class="Delimiter">;</span> + if <span class="Delimiter">((</span>!Memory[screen_data_start+i] && !isspace<span class="Delimiter">(</span>expected_contents[i]<span class="Delimiter">))</span> <span class="Comment">// uninitialized memory => spaces</span> + || <span class="Delimiter">(</span>Memory[screen_data_start+i] && Memory[screen_data_start+i] != expected_contents[i]<span class="Delimiter">))</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << "CCC " << Trace_stream << " " << Hide_warnings << '\n'; //? 1</span> + raise << <span class="Constant">"expected screen location ("</span> << i/screen_width << <span class="Constant">", "</span> << i%screen_width << <span class="Constant">") to contain '"</span> << expected_contents[i] << <span class="Constant">"' instead of '"</span> << static_cast<char><span class="Delimiter">(</span>Memory[screen_data_start+i]<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + Passed = <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/073scenario_screen_test.mu.html b/html/073scenario_screen_test.mu.html new file mode 100644 index 00000000..01ee413c --- /dev/null +++ b/html/073scenario_screen_test.mu.html @@ -0,0 +1,63 @@ +<!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/073scenario_screen_test.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># To check our support for screens in scenarios, rewrite tests from print.mu</span> + +scenario print-character-at-top-left2 <span class="Delimiter">[</span> + assume-screen 3:literal/width, 2:literal/height + run <span class="Delimiter">[</span> + screen:address<span class="Special"> <- </span>print-character screen:address, 97:literal <span class="Comment"># 'a'</span> + <span class="Delimiter">]</span> + screen-should-contain <span class="Delimiter">[</span> + <span class="Identifier"> .a</span> . + . . + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> + +scenario clear-line-erases-printed-characters2 <span class="Delimiter">[</span> + assume-screen 5:literal/width, 3:literal/height + run <span class="Delimiter">[</span> + <span class="Comment"># print a character</span> + screen:address<span class="Special"> <- </span>print-character screen:address, 97:literal <span class="Comment"># 'a'</span> + <span class="Comment"># move cursor to start of line</span> + screen:address<span class="Special"> <- </span>move-cursor screen:address, 0:literal/row, 0:literal/column + <span class="Comment"># clear line</span> + screen:address<span class="Special"> <- </span>clear-line screen:address + <span class="Delimiter">]</span> + screen-should-contain <span class="Delimiter">[</span> + . . + . . + . . + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/074keyboard.mu.html b/html/074keyboard.mu.html new file mode 100644 index 00000000..0f06c13b --- /dev/null +++ b/html/074keyboard.mu.html @@ -0,0 +1,88 @@ +<!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/074keyboard.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.CommentedCode { color: #6c6c6c; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># Wrappers around keyboard primitives that take a 'keyboard' object and are thus</span> +<span class="Comment"># easier to test.</span> + +container keyboard <span class="Delimiter">[</span> <span class="Comment"># can't think of another word like screen/display, so real and fake keyboards use the same name</span> + index:integer + data:address:array:character +<span class="Delimiter">]</span> + +recipe init-fake-keyboard <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + result:address:keyboard<span class="Special"> <- </span>new keyboard:type + buf:address:address:array:character<span class="Special"> <- </span>get-address result:address:keyboard/deref data:offset +<span class="CommentedCode">#? $start-tracing #? 1</span> + buf:address:address:array:character/deref<span class="Special"> <- </span>next-ingredient +<span class="CommentedCode">#? $stop-tracing #? 1</span> + idx:address:integer<span class="Special"> <- </span>get-address result:address:keyboard/deref index:offset + idx:address:integer/deref<span class="Special"> <- </span>copy 0:literal + <span class="Identifier">reply</span> result:address:keyboard +<span class="Delimiter">]</span> + +recipe read-key <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:keyboard<span class="Special"> <- </span>next-ingredient + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:keyboard + idx:address:integer<span class="Special"> <- </span>get-address x:address:keyboard/deref, index:offset + buf:address:array:character<span class="Special"> <- </span>get x:address:keyboard/deref, data:offset + max:integer<span class="Special"> <- </span>length buf:address:array:character/deref + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal idx:address:integer/deref, max:integer + <span class="Identifier">break-unless</span> done?:boolean + <span class="Identifier">reply</span> 0:literal, 0:literal/done, x:address:keyboard/same-as-ingredient:0 + <span class="Delimiter">}</span> + c:character<span class="Special"> <- </span>index buf:address:array:character/deref, idx:address:integer/deref + idx:address:integer/deref<span class="Special"> <- </span>add idx:address:integer/deref, 1:literal + <span class="Identifier">reply</span> c:character, 1:literal/found, x:address:keyboard/same-as-ingredient:0 + <span class="Delimiter">}</span> + c:character, found?:boolean<span class="Special"> <- </span>read-key-from-keyboard + <span class="Identifier">reply</span> c:character, found?:boolean, x:address:keyboard/same-as-ingredient:0 +<span class="Delimiter">]</span> + +recipe wait-for-key <span class="Delimiter">[</span> + default-space:address:array:location<span class="Special"> <- </span>new location:type, 30:literal + x:address:keyboard<span class="Special"> <- </span>next-ingredient + <span class="Delimiter">{</span> + <span class="Identifier">break-unless</span> x:address:keyboard + <span class="Comment"># on fake keyboards 'wait-for-key' behaves just like 'read-key'</span> + c:character, x:address:keyboard<span class="Special"> <- </span>read-key x:address:keyboard + <span class="Identifier">reply</span> c:character, x:address:keyboard/same-as-ingredient:0 + <span class="Delimiter">}</span> + c:character<span class="Special"> <- </span>wait-for-key-from-keyboard + <span class="Identifier">reply</span> c:character, x:address:keyboard/same-as-ingredient:0 +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/075scenario_keyboard.cc.html b/html/075scenario_keyboard.cc.html new file mode 100644 index 00000000..a83e3dd4 --- /dev/null +++ b/html/075scenario_keyboard.cc.html @@ -0,0 +1,89 @@ +<!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/075scenario_keyboard.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; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Clean syntax to manipulate and check the keyboard in scenarios.</span> +<span class="Comment">//: Instruction 'assume-keyboard' implicitly creates a variable called</span> +<span class="Comment">//: 'keyboard' that is accessible inside other 'run' instructions in the</span> +<span class="Comment">//: scenario.</span> + +<span class="Delimiter">:(scenarios run_mu_scenario)</span> +<span class="Delimiter">:(scenario keyboard_in_scenario)</span> +scenario keyboard-in-scenario [ + assume-keyboard [abc] + run [ + <span class="Constant">1</span>:character<span class="Delimiter">,</span> <span class="Constant">2</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> <- </span>read-key keyboard:address + <span class="Constant">3</span>:character<span class="Delimiter">,</span> <span class="Constant">4</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> <- </span>read-key keyboard:address + <span class="Constant">5</span>:character<span class="Delimiter">,</span> <span class="Constant">6</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> <- </span>read-key keyboard:address + <span class="Constant">7</span>:character<span class="Delimiter">,</span> <span class="Constant">8</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> <- </span>read-key keyboard:address + ] + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">97</span> <span class="Comment"># 'a'</span> + <span class="Constant">2</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># first read-key call found a character</span> + <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">98</span> <span class="Comment"># 'b'</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># second read-key call found a character</span> + <span class="Constant">5</span><span class="Special"> <- </span><span class="Constant">99</span> <span class="Comment"># 'c'</span> + <span class="Constant">6</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># third read-key call found a character</span> + <span class="Constant">7</span><span class="Special"> <- </span><span class="Constant">0</span> + <span class="Constant">8</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># fourth read-key call didn't find a character</span> + ] +] + +<span class="Delimiter">:(before "End Scenario Globals")</span> +const size_t KEYBOARD = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Predefined Scenario Locals In Run")</span> +Name[tmp_recipe[<span class="Constant">0</span>]][<span class="Constant">"keyboard"</span>] = KEYBOARD<span class="Delimiter">;</span> + +<span class="Delimiter">:(before "End Rewrite Instruction(curr)")</span> +<span class="Comment">// rewrite `assume-keyboard string` to</span> +<span class="Comment">// ```</span> +<span class="Comment">// keyboard:address <- new string # hacky reuse of location</span> +<span class="Comment">// keyboard:address <- init-fake-keyboard keyboard:address</span> +<span class="Comment">// ```</span> +if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"assume-keyboard"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// insert first instruction</span> + curr<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"new"</span>]<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"keyboard:address"</span><span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>products[<span class="Constant">0</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>KEYBOARD<span class="Delimiter">);</span> + result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span> <span class="Comment">// hacky that "Rewrite Instruction" is converting to multiple instructions</span> + <span class="Comment">// leave second instruction in curr</span> + curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + curr<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">"init-fake-keyboard"</span>]<span class="Delimiter">;</span> + assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"keyboard:address"</span><span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>ingredients[<span class="Constant">0</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>KEYBOARD<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> + curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"keyboard:address"</span><span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>products[<span class="Constant">0</span>]<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>KEYBOARD<span class="Delimiter">);</span> +<span class="Delimiter">}</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/076scenario_keyboard_test.mu.html b/html/076scenario_keyboard_test.mu.html new file mode 100644 index 00000000..3e3880ba --- /dev/null +++ b/html/076scenario_keyboard_test.mu.html @@ -0,0 +1,56 @@ +<!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/076scenario_keyboard_test.mu.html</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v1"> +<meta name="syntax" content="none"> +<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; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># To check our support for keyboards in scenarios, rewrite tests from</span> +<span class="Comment"># scenario_keyboard.mu</span> +<span class="Comment"># Tests for keyboard interface.</span> + +scenario read-key-in-mu <span class="Delimiter">[</span> + assume-keyboard <span class="Delimiter">[</span>abc<span class="Delimiter">]</span> + run <span class="Delimiter">[</span> + 1:character, 2:boolean, keyboard:address<span class="Special"> <- </span>read-key keyboard:address + 3:character, 4:boolean, keyboard:address<span class="Special"> <- </span>read-key keyboard:address + 5:character, 6:boolean, keyboard:address<span class="Special"> <- </span>read-key keyboard:address + 7:character, 8:boolean, keyboard:address<span class="Special"> <- </span>read-key keyboard:address + <span class="Delimiter">]</span> + memory-should-contain <span class="Delimiter">[</span> + 1<span class="Special"> <- </span>97 <span class="Comment"># 'a'</span> + 2<span class="Special"> <- </span>1 <span class="Comment"># first read-key call found a character</span> + 3<span class="Special"> <- </span>98 <span class="Comment"># 'b'</span> + 4<span class="Special"> <- </span>1 <span class="Comment"># second read-key call found a character</span> + 5<span class="Special"> <- </span>99 <span class="Comment"># 'c'</span> + 6<span class="Special"> <- </span>1 <span class="Comment"># third read-key call found a character</span> + 7<span class="Special"> <- </span>0 + 8<span class="Special"> <- </span>0 <span class="Comment"># fourth read-key call didn't find a character</span> + <span class="Delimiter">]</span> +<span class="Delimiter">]</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/077tangle.cc.html b/html/077tangle.cc.html new file mode 100644 index 00000000..9411e575 --- /dev/null +++ b/html/077tangle.cc.html @@ -0,0 +1,235 @@ +<!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/077tangle.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; } +.CommentedCode { color: #6c6c6c; } +.Constant { color: #008080; } +.Comment { color: #8080ff; } +.Delimiter { color: #c000c0; } +.Special { color: #ff6060; } +.Identifier { color: #008080; } +.traceContains { color: #008000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">//: Allow code for recipes to be pulled in from multiple places.</span> +<span class="Comment">//:</span> +<span class="Comment">//: TODO: switch recipe.steps to a more efficient data structure.</span> + +<span class="Delimiter">:(scenario tangle_before)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +label1 + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] + +before +label1 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">3</span> + +<span class="Comment">//: while loading recipes, load before/after fragments</span> + +<span class="Delimiter">:(before "End Globals")</span> +map<string <span class="Comment">/*</span><span class="Comment">label</span><span class="Comment">*/</span><span class="Delimiter">,</span> recipe> Before_fragments<span class="Delimiter">,</span> After_fragments<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Setup")</span> +Before_fragments<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +After_fragments<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> + +<span class="Delimiter">:(before "End Command Handlers")</span> +else if <span class="Delimiter">(</span>command == <span class="Constant">"before"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + recipe tmp = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>Before_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> +<span class="Delimiter">}</span> +else if <span class="Delimiter">(</span>command == <span class="Constant">"after"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + string label = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + recipe tmp = slurp_recipe<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>After_fragments[label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> tmp<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: after all recipes are loaded, insert fragments at appropriate labels</span> + +<span class="Delimiter">:(after "int main")</span> + Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>insert_fragments<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +void insert_fragments<span class="Delimiter">(</span>const recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// Copy into a new vector because insertions invalidate iterators.</span> + <span class="Comment">// But this way we can't insert into labels created inside before/after.</span> + vector<instruction> result<span class="Delimiter">;</span> + for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + const instruction inst = Recipe[r]<span class="Delimiter">.</span>steps[i]<span class="Delimiter">;</span> + if <span class="Delimiter">(</span>!inst<span class="Delimiter">.</span>is_label<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> + <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + if <span class="Delimiter">(</span>Before_fragments<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != Before_fragments<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> Before_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + <span class="Delimiter">}</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>inst<span class="Delimiter">);</span> + if <span class="Delimiter">(</span>After_fragments<span class="Delimiter">.</span>find<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>label<span class="Delimiter">)</span> != After_fragments<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span> + result<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>result<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> After_fragments[inst<span class="Delimiter">.</span>label]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="CommentedCode">//? for (index_t i = 0; i < result.size(); ++i) { //? 1</span> +<span class="CommentedCode">//? cout << result[i].to_string() << '\n'; //? 1</span> +<span class="CommentedCode">//? } //? 1</span> + Recipe[r]<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>swap<span class="Delimiter">(</span>result<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario tangle_before_and_after)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +label1 + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label1 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label1 [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="traceContains">+mem: storing 0 in location 4</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">4</span> + +<span class="Delimiter">:(scenario tangle_keeps_labels_separate)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +label1 + +label2 + <span class="Constant">6</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label1 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label1 [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label2 [ + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label2 [ + <span class="Constant">5</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="Comment"># 'after' fragments for earlier label always go before 'before' fragments for later label</span> +<span class="traceContains">+mem: storing 0 in location 4</span> +<span class="Comment"># label2</span> +<span class="traceContains">+mem: storing 0 in location 5</span> +<span class="traceContains">+mem: storing 0 in location 6</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">6</span> + +<span class="Delimiter">:(scenario tangle_stacks_multiple_fragments)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +label1 + <span class="Constant">6</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label1 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label1 [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label1 [ + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label1 [ + <span class="Constant">5</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="Comment"># 'before' fragments stack in order</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="traceContains">+mem: storing 0 in location 4</span> +<span class="Comment"># label1</span> +<span class="Comment"># 'after' fragments stack in reverse order</span> +<span class="traceContains">+mem: storing 0 in location 5</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="traceContains">+mem: storing 0 in location 6</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">6</span> + +<span class="Delimiter">:(scenario tangle_supports_fragments_with_multiple_instructions)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +label1 + <span class="Constant">6</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label1 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label1 [ + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + <span class="Constant">5</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 0 in location 4</span> +<span class="traceContains">+mem: storing 0 in location 5</span> +<span class="traceContains">+mem: storing 0 in location 6</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">6</span> + +<span class="Delimiter">:(scenario tangle_tangles_into_all_labels_with_same_name)</span> +recipe main [ + <span class="Constant">1</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal + +label1 + +label1 + <span class="Constant">4</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +before +label1 [ + <span class="Constant">2</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +after +label1 [ + <span class="Constant">3</span>:integer<span class="Special"> <- </span>copy <span class="Constant">0</span>:literal +] +<span class="traceContains">+mem: storing 0 in location 1</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="traceContains">+mem: storing 0 in location 2</span> +<span class="Comment"># label1</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +<span class="traceContains">+mem: storing 0 in location 4</span> +<span class="Comment"># nothing else</span> +$mem: <span class="Constant">6</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> |