Skip to content

Commit

Permalink
fix: revisions to debugger and finale
Browse files Browse the repository at this point in the history
  • Loading branch information
gvwilson committed Dec 5, 2023
1 parent 9289253 commit 4e38ce9
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 84 deletions.
2 changes: 1 addition & 1 deletion docs/bib/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ <h1>Appendix A: Bibliography</h1>
<dt id="Wilson2022b" class="bib-def">Wilson2022b</dt>
<dd>Greg Wilson.
<em>Software Design by Example: A Tool-Based Introduction with JavaScript</em>.
CRC Press/Taylor and Francis, 2022.
CRC Press/Taylor &amp; Francis, 2022.
ISBN 978-1032399676.</dd>

<dt id="Wirth1976" class="bib-def">Wirth1976</dt>
Expand Down
73 changes: 36 additions & 37 deletions docs/debugger/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@ <h2 id="debugger-step">Section 26.1: One Step at a Time</h2>
</code></pre></div>
</div>
<p>For now,
<code>write</code> just prints things to whatever output stream the VM was given:</p>
<code>write</code> just prints things to whatever output stream
the virtual machine (VM) was given:</p>
<div class="pagebreak"></div>

<div class="code-sample lang-py" title="vm_base.py">
Expand Down Expand Up @@ -426,19 +427,19 @@ <h2 id="debugger-step">Section 26.1: One Step at a Time</h2>
</code></pre></div>
</div>
<p class="continue">(Again,
if we were writing this code under normal circumstances
if we were writing this code under normal circumstances,
we would enhance the existing class,
but since we want to keep several versions around for teaching,
we derive and extend.)</p>
<p>The old <code>run</code> method kept going until the program finished.
The new <code>run</code> method is necessarily more complicated.
The VM is initially in the <code>STEPPING</code> state
(because if we start it in the <code>RUNNING</code> state
(because if we start it in the <code>RUNNING</code> state,
we would never have an opportunity to interact with it
to change its state).
As long as the program isn&rsquo;t finished
As long as the program isn&rsquo;t finished,
we fetch, decode, and execute the next instruction as usual,
but stop after each one if we&rsquo;re single-stepping:</p>
but we stop after each one if we&rsquo;re single-stepping:</p>
<div class="code-sample lang-py" title="vm_step.py">
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">VMState</span><span class="o">.</span><span class="n">STEPPING</span>
Expand Down Expand Up @@ -477,7 +478,7 @@ <h2 id="debugger-step">Section 26.1: One Step at a Time</h2>
in which case the method breaks out of the loop
without changing the VM&rsquo;s state.
<code>run</code> will then see that the VM is still in single-stepping mode
and execute a single instruction.</p>
and will execute a single instruction.</p>
</li>
</ol>
<p>The method that disassembles an instruction to show us what we&rsquo;re about to do
Expand Down Expand Up @@ -536,12 +537,12 @@ <h2 id="debugger-test">Section 26.2: Testing</h2>
and capture its output for later inspection.
We had a similar problem when testing
the web server of <a class="x-ref" href="../ftp/">Chapter 21</a> and the editor of <a class="x-ref" href="../undo/">Chapter 24</a>,
and our solution is the similar:
and our solution is similar:
we will replace <code>input</code> and <code>print</code> with <span class="ix-entry" ix-key="mock object" markdown="1">mock objects</span>.</p>
<p>As shown earlier,
our VM uses an object with a <code>write</code> method to produce output.
We can define a class that provides this method,
but which saves messages in a list for later inspection
We can define a class which provides this method
but saves messages in a list for later inspection
instead of printing them:</p>
<div class="code-sample lang-py" title="test_vm.py">
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Writer</span><span class="p">:</span>
Expand All @@ -555,7 +556,7 @@ <h2 id="debugger-test">Section 26.2: Testing</h2>
<p>Similarly,
our VM gets input from a function that takes a prompt as an argument
and returns whatever the user typed.
We can define a class with a <code>__call__</code> method that acts like such a function,
We can define a class with a <code>__call__</code> method which acts like such a function
but which returns strings from a list instead of waiting for the user:</p>
<div class="code-sample lang-py" title="test_vm.py">
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Reader</span><span class="p">:</span>
Expand All @@ -581,8 +582,7 @@ <h2 id="debugger-test">Section 26.2: Testing</h2>
<span class="n">vm</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</code></pre></div>
</div>
<p>We are now ready to start writing tests.
Here&rsquo;s one that checks the debugger&rsquo;s &ldquo;disassemble&rdquo; command:</p>
<p>We can no write tests, like this one for the &ldquo;disassemble&rdquo; command:</p>
<div class="code-sample lang-py" title="test_vm.py">
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">test_disassemble</span><span class="p">():</span>
<span class="n">source</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;</span>
Expand Down Expand Up @@ -616,8 +616,7 @@ <h2 id="debugger-test">Section 26.2: Testing</h2>
</ol>
<p>Defining two classes and a helper function to test a one-line program
may seem like a lot of work,
but we&rsquo;re not testing the one-line program or the VM:
we&rsquo;re testing the debugger.
but we&rsquo;re not testing the one-line program or the VM—we&rsquo;re testing the debugger.
For example,
the close below:</p>
<ol>
Expand Down Expand Up @@ -705,7 +704,7 @@ <h2 id="debugger-extensibility">Section 26.3: Extensibility</h2>
Once that&rsquo;s done,
we modify <code>interact</code> to choose operations from a lookup table
called <code>self.handlers</code>.
Its keys are the commands typed by the user
Its keys are the commands typed by the user,
and its values are the operation methods we just created:</p>
<div class="code-sample lang-py" title="vm_extend.py">
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">interact</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">addr</span><span class="p">):</span>
Expand Down Expand Up @@ -769,11 +768,12 @@ <h2 id="debugger-breakpoints">Section 26.4: Breakpoints</h2>
we want to set a <a class="gl-ref" href="../glossary/#gl:breakpoint" title="A point in a program where a debugger should halt execution in order to interact with a user." markdown="1">breakpoint</a>
to tell the computer to stop at a particular location
and drop us into the debugger.
(We might even use
We might even use
a <a class="gl-ref" href="../glossary/#gl:conditional_breakpoint" title="A breakpoint at which the debugger should only halt if some user-specified condition is true." markdown="1">conditional breakpoint</a>
that would only stop if (for example)
that would only stop if,
for example,
the variable <code>x</code> was zero at that point,
but we&rsquo;ll leave that for the exercises.)</p>
but we&rsquo;ll leave that for the exercises.</p>
<p>The easiest way to implement breakpoints would be
to have the VM store their addresses in a set.
We would then modify <code>run</code> to check that set
Expand All @@ -793,7 +793,7 @@ <h2 id="debugger-breakpoints">Section 26.4: Breakpoints</h2>
<a class="gl-ref" href="../glossary/#gl:clear_breakpoint" title="To remove a breakpoint from a program." markdown="1">clears</a>
the breakpoint,
we copy the original instruction back into place,
and if the VM encounters a breakpoint instruction while its running,
and if the VM encounters a breakpoint instruction while it is running,
it drops into interactive mode
(<a class="fig-ref" href="../debugger/#debugger-break">Figure 26.3</a>).</p>
<figure id="debugger-break">
Expand Down Expand Up @@ -864,13 +864,13 @@ <h2 id="debugger-breakpoints">Section 26.4: Breakpoints</h2>
<span class="bp">self</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">key</span><span class="si">:</span><span class="s2">06x</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">disassemble</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">instruction</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</code></pre></div>
</div>
<p>Notice how the implementation first calls the parent&rsquo;s <code>show</code> method
to display everything we&rsquo;ve been displaying so far,
then adds a few lines to display extra information.
<p>The implementation first calls the parent&rsquo;s <code>show</code> method
to display what we&rsquo;ve seen so far
before adding more information.
Extending methods by <span class="ix-entry" ix-key="upcall" markdown="1">upcalling</span> this way
saves us typing,
saves typing
and ensures that changes in the parent class
will automatically show up in the <span class="ix-entry" ix-key="child class" markdown="1">child class</span>.</p>
automatically show up in the <span class="ix-entry" ix-key="child class" markdown="1">child class</span>.</p>
<p>The final step is to change <code>run</code>
so that the VM actually stops at a breakpoint:</p>
<div class="code-sample lang-py" title="vm_break.py">
Expand All @@ -894,28 +894,25 @@ <h2 id="debugger-breakpoints">Section 26.4: Breakpoints</h2>
<span class="bp">self</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">op</span><span class="p">,</span> <span class="n">arg0</span><span class="p">,</span> <span class="n">arg1</span><span class="p">)</span>
</code></pre></div>
</div>
<p>Given everything we&rsquo;ve done so far,
the logic is relatively straightforward.
<p>The logic here is relatively straightforward.
If the instruction is a breakpoint,
the VM fetches and decodes the original from the breakpoint lookup table.
It then gives the user a chance to interact
the VM uses the original instruction from the breakpoint lookup table,
then gives the user a chance to interact
before executing that original instruction.
If the instruction <em>isn&rsquo;t</em> a breakpoint,
on the other hand,
the VM interacts with the user if it is in single-stepping mode,
Otherwise,
the VM interacts with the user if it is in single-stepping mode
and then carries on as before.</p>
<p>We can test our new-and-improved VM
using the tools developed earlier in this chapter,
but even before we do that,
the changes to <code>run</code> tell us that we should re-think some of our design.
the changes to <code>run</code> tell us that we should rethink some of our design.
Using a lookup table for interactive commands
allowed us to add commands without modifying <code>interact</code>;
another lookup table would enable us to add new instructions
without having to modify <code>run</code>.
We will explore this in the exercises.</p>
<div class="pagebreak"></div>

<h2 id="debugger-summary">Section 26.5: Summary</h2>
<p><a class="fig-ref" href="../debugger/#debugger-concept-map">Figure 26.4</a> summarizes the key ideas in this chapter.</p>
<figure id="debugger-concept-map" class="here">
<img src="./concept_map.svg" alt="Concept map for debugger"/>
<figcaption markdown="1">Figure 26.4: Concepts for debugger.</figcaption>
Expand All @@ -924,8 +921,9 @@ <h2 id="debugger-summary">Section 26.5: Summary</h2>
<h2 id="debugger-exercises">Section 26.6: Exercises</h2>
<h3 class="exercise">Show Memory Range</h3>
<p>Modify the debugger so that if the user provides a single address to the <code>"memory"</code> command,
the debugger shows the value at that address,
while if the user provides two addresses,
the debugger shows the value at that address.
If the user provides two addresses,
on the other hand,
the debugger shows all the memory between those addresses.</p>
<ol>
<li>
Expand Down Expand Up @@ -954,7 +952,8 @@ <h3 class="exercise">Conditional Breakpoints</h3>
if R0 contains zero
or if the value at a particular location in memory is greater than 3.
(This exercise is potentially very large;
you may restrict the kinds of conditions the user can set to make it more manageable,
you may restrict the kinds of conditions the user can set
to make the problem more tractable,
or explore ways of using <code>eval</code> to support the general case.)</p>
<h3 class="exercise">Watchpoints</h3>
<p>Modify the debugger and VM so that the user can create
Expand Down
8 changes: 4 additions & 4 deletions docs/finale/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ <h1>Chapter 27: Conclusion</h1>
<p>English doesn&rsquo;t have a word for things like this,
but there are lots of other examples.
Architecture and typography have deep roots,
and starting in the early 20th Century,
and starting in the early 20th century,
people like <a href="https://en.wikipedia.org/wiki/Christopher_Dresser">Christopher Dresser</a>,
<a href="https://en.wikipedia.org/wiki/Joseph_Claude_Sinel">Jo Sinel</a>,
and <a href="https://en.wikipedia.org/wiki/Raymond_Loewy">Raymond Loewy</a>
Expand Down Expand Up @@ -395,12 +395,12 @@ <h1>Chapter 27: Conclusion</h1>
Will people understand how to use it without having to wade through a manual?
Will it please the eye when it&rsquo;s sitting on the counter?
Training in industrial design gives weight to all of these separately and together,
and gives students the tools they need to tell the good from the bad.</p>
and gives students the tools they need to distinguish the good from the bad.</p>
<p>In retrospect,
this is what <span class="bib-ref">[<a class="bib-ref" href="../bib/#Oram2007">Oram2007</a>, <a class="bib-ref" href="../bib/#Brown2011">Brown2011</a>, <a class="bib-ref" href="../bib/#Brown2012">Brown2012</a>]</span> were groping toward.
If we had decided fifty years ago to call programming &ldquo;industrial design for software&rdquo;
If we had decided 50 years ago to call programming &ldquo;industrial design for software&rdquo;
rather than &ldquo;software engineering&rdquo;,
our conversations would be intellectually richer today.
our conversations might be intellectually richer today.
I hope this book will help us get there.
I hope that some day we&rsquo;ll be able to talk to each other about the beauty of software
because it <em>is</em> beautiful and we deserve to have ways to say that.
Expand Down
2 changes: 1 addition & 1 deletion info/bibliography.bib
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ @article{Wilson2022a
@book{Wilson2022b,
author = {Greg Wilson},
title = {Software Design by Example: A Tool-Based Introduction with JavaScript},
publisher = {CRC Press/Taylor and Francis},
publisher = {CRC Press/Taylor \& Francis},
year = {2022},
isbn = {978-1032399676},
link = {https://third-bit.com/sdxjs/}
Expand Down
Loading

0 comments on commit 4e38ce9

Please sign in to comment.