<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Eli Bendersky's website - SICP</title><link href="https://eli.thegreenplace.net/" rel="alternate"></link><link href="https://eli.thegreenplace.net/feeds/sicp.atom.xml" rel="self"></link><id>https://eli.thegreenplace.net/</id><updated>2023-02-04T15:35:51-08:00</updated><entry><title>Signed copy of SICP</title><link href="https://eli.thegreenplace.net/2008/06/06/signed-copy-of-sicp" rel="alternate"></link><published>2008-06-06T07:59:28-07:00</published><updated>2023-02-04T13:41:52-08:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-06-06:/2008/06/06/signed-copy-of-sicp</id><summary type="html">
    &lt;p&gt;
        A lot of people were impressed by my finishing the read-through of SICP,
        completing the vast majority of the exercises. I received a lot of warm
        comments on my &lt;a href="https://eli.thegreenplace.net/2008/04/18/sicp-conclusion/"&gt;conclusion
    post&lt;/a&gt; - in the blog, on email, and on the &lt;a href="http://www.reddit.com/info/6g9mq/comments/"&gt;Reddit link&lt;/a&gt; that
immediately took place #1 in the Programming section …&lt;/p&gt;</summary><content type="html">
    &lt;p&gt;
        A lot of people were impressed by my finishing the read-through of SICP,
        completing the vast majority of the exercises. I received a lot of warm
        comments on my &lt;a href="https://eli.thegreenplace.net/2008/04/18/sicp-conclusion/"&gt;conclusion
    post&lt;/a&gt; - in the blog, on email, and on the &lt;a href="http://www.reddit.com/info/6g9mq/comments/"&gt;Reddit link&lt;/a&gt; that
immediately took place #1 in the Programming section and held it for a day.
        &lt;/p&gt;&lt;p&gt;

The most interesting feedback was, however, from Geoffrey S. Knauth. He's
acquainted with the book authors, and when he told them about my project, they
agreed to sign a book for me, which Geoffrey then shipped to Israel on his own
expense.
        &lt;/p&gt;

&lt;p&gt;Here's the book and a slip of paper displaying the complex logistics behind
this shipment:&lt;/p&gt;

&lt;img class="align-center" src="https://eli.thegreenplace.net/images/2008/06/img_2182.thumbnail.jpg" /&gt;

&lt;p&gt;And this is the opening page, with the authors' signatures:&lt;/p&gt;

&lt;img class="align-center" src="https://eli.thegreenplace.net/images/2008/06/signed_copy.thumbnail.PNG" /&gt;&lt;/a&gt;

&lt;p&gt;I'm really happy about this, and want to thank Geoffrey again for his initiative.&lt;/p&gt;

    </content><category term="misc"></category><category term="SICP"></category></entry><entry><title>Book review: "Structure and Interpretation of Computer Programs" by Harold Abelson, Gerald Jay Sussman</title><link href="https://eli.thegreenplace.net/2008/05/28/book-review-structure-and-interpretation-of-computer-programs-by-harold-abelson-gerald-jay-sussman" rel="alternate"></link><published>2008-05-28T07:38:56-07:00</published><updated>2023-02-04T15:35:51-08:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-05-28:/2008/05/28/book-review-structure-and-interpretation-of-computer-programs-by-harold-abelson-gerald-jay-sussman</id><summary type="html">
    &lt;p&gt;
        I have the habit of writing &lt;a href="https://eli.thegreenplace.net/tag/book-reviews"&gt;reviews&lt;/a&gt; for
        the books I've read, and recently I noticed that something is missing.
        SICP. I've definitely &lt;a href="https://eli.thegreenplace.net/tag/sicp"&gt;read&lt;/a&gt; it, so I should
        probably write a review, eh ?
    &lt;/p&gt;&lt;p&gt;

The real reason for my writing this review is, however, its Amazon entry.
Although the first page …&lt;/p&gt;</summary><content type="html">
    &lt;p&gt;
        I have the habit of writing &lt;a href="https://eli.thegreenplace.net/tag/book-reviews"&gt;reviews&lt;/a&gt; for
        the books I've read, and recently I noticed that something is missing.
        SICP. I've definitely &lt;a href="https://eli.thegreenplace.net/tag/sicp"&gt;read&lt;/a&gt; it, so I should
        probably write a review, eh ?
    &lt;/p&gt;&lt;p&gt;

The real reason for my writing this review is, however, its Amazon entry.
Although the first page shines with glimmering reviews by, no less, Peter Norvig
and Paul Graham, the book has a 3.5 star average, which is really inexplicable.
Many far inferior books have higher grades! So I want to make my small
contribution by writing SICP the review it deserves, give it the grade it
deserves (5!!!!), and post it to Amazon as well. Lets get started, then.
    &lt;/p&gt;&lt;p&gt;

My first encounter with SICP was in the second year of university, where I took
a course named "SICP 1". I already had working programming experience by that
time, so the course wasn't hard, but I was struck by the beauty of the subjects
it taught, by the Scheme language it used and by the long and interesting
homework assignments it had. This course woke my curiosity about functional
programming, and the Lisp family of languages in particular.
    &lt;/p&gt;&lt;p&gt;

A few years later, with much more experience behind my back, I've decided to
tackle SICP seriously and read the whole book, solving the vast majority of the
exercises. This endeavor took about 10 months, and I enjoyed it immensely. I
think SICP is a wonderful book, a seminal work in the field of programming. It
is one of those rare books every programmer should read. In this review I'll try
to explain why.
    &lt;/p&gt;&lt;p&gt;

In contrast with most introductory books about programming that just teach you a
language, SICP takes a far better approach. The main goal of the authors is not
to teach Scheme, it is to teach programming. From the beginning, the book takes
an integrative path, where the basic axioms of programming are presented, and
later are fortified with examples and exercises. SICP teaches about
computational processes - iterative and recursive. How to use them best in each
situation, and how to implement them. It also explains abstraction by functional
composition. These are topics rarely presented in programming books, but SICP
puts them rightly in the first chapter, because they are the real stuff
programming is based on. 
    &lt;/p&gt;&lt;p&gt;

The example programs developed in the book are real, large, and exciting. You'll
get to develop a powerful picture language, a generic object-oriented arithmetic
package including complex and polynomial arithmetic, a simulator for digital
circuits, a symbolic differentiation package, an interpreter for Scheme written
in Scheme, an interpreter for a logic programming language similar to Prolog, a
virtual machine for a simplified pseudo-assembly DSL, an interpreter for Scheme
written in this pseudo-assembly, and finally a compiler from Scheme to the
assembly language. All these examples are real, well-thought out exercises for
skill, taken from beginning to a very complete end. In no other book such a
wealth of topics is addressed in an accessible manner.
    &lt;/p&gt;&lt;p&gt;

A word about exercises in SICP. They are numerous, some of them are hard, but
the exercises are the best way to really understand what the book tries to
teach. In a manner, they're as integral part of the book as the text itself. The
exercises are very well prepared and lead the reader through the examples coded
by the authors into greater understanding of the topics taught. At times, it
feels like the exercises are specifically designed to force you to think about
the essence of the topics, and not just grasp them superficially.
    &lt;/p&gt;&lt;p&gt;

SICP commonly suffers from the criticism that it's too hard for beginners. Maybe
this criticism is rightful, and universities should give a simpler introductory
course to programming before SICP. But this is an aspect of the educational
systems, not pertaining to the book itself. I wouldn't know, I never read SICP
as a beginner. However it is being taught, SICP is an amazing book. It is by far
the best programming book I have ever laid by hands on, and I seriously doubt
that it will be surpassed any time soon. Reading SICP will enlighten you as a
programmer, and make you a better one. I can't imagine one programmer who won't
gain something important by reading SICP. 
    &lt;/p&gt;

    </content><category term="misc"></category><category term="Book reviews"></category><category term="SICP"></category></entry><entry><title>SICP - conclusion</title><link href="https://eli.thegreenplace.net/2008/04/18/sicp-conclusion" rel="alternate"></link><published>2008-04-18T16:54:27-07:00</published><updated>2023-02-04T13:41:52-08:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-04-18:/2008/04/18/sicp-conclusion</id><summary type="html">
        &lt;p&gt;I've completed the &lt;span class="caps"&gt;SICP&lt;/span&gt; reading project, which I began on &lt;a href="https://eli.thegreenplace.net/2007/06/19/introducing-the-sicp-reading-notes/"&gt;June 19th, 2007&lt;/a&gt;. In hindsight, it seems like a very long time (almost a year!), during which this was my main hacking project at home. So, in this conclusion I want to examine my progress, and compare the result with …&lt;/p&gt;</summary><content type="html">
        &lt;p&gt;I've completed the &lt;span class="caps"&gt;SICP&lt;/span&gt; reading project, which I began on &lt;a href="https://eli.thegreenplace.net/2007/06/19/introducing-the-sicp-reading-notes/"&gt;June 19th, 2007&lt;/a&gt;. In hindsight, it seems like a very long time (almost a year!), during which this was my main hacking project at home. So, in this conclusion I want to examine my progress, and compare the result with my initial goals.&lt;/p&gt;


	&lt;p&gt;&lt;a href="https://eli.thegreenplace.net/2007/06/19/introducing-the-sicp-reading-notes/"&gt;The original plan&lt;/a&gt; was:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Read the book&lt;/li&gt;
		&lt;li&gt;See all the video lectures by Sussman and Abelson themselves &lt;/li&gt;
		&lt;li&gt;Do most of the interesting exercises in the book&lt;/li&gt;
		&lt;li&gt;Do some of the larger projects listed &lt;a href="http://mitpress.mit.edu/sicp/psets/index.html"&gt;here&lt;/a&gt; and &lt;a href="http://ocw.mit.edu/OcwWeb/Electrical-Engineering-and-Computer-Science/6-001Spring-2005/CourseHome/index.htm"&gt;here&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Let's see how I've managed:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Done&lt;/li&gt;
		&lt;li&gt;Done&lt;/li&gt;
		&lt;li&gt;This is the point I'm most happy with. I've completed the vast majority of the exercises in &lt;span class="caps"&gt;SICP&lt;/span&gt; and posted them online. Of the 356 exercises in the book, I've skipped about 20, so I've completed 94% of the exercises &amp;#8211; which is far above my initial plans.&lt;/li&gt;
		&lt;li&gt;I didn't do this, but there's no need, having completed so many of the exercises. I feel I gained a completely solid understanding of the material, and won't gain much by doing the projects.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Also, I originally planned to reimplement all the code do all the exercises in Common Lisp. Later I changed my mind and decided to use &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme for some of them. Eventually, I've been using both languages interchangeably, which is a good thing, as I got some practice with both.&lt;/p&gt;


	&lt;p&gt;Here are some numerical statistics that emphasize the magnitude of this endeavor:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;I've written 52 blog posts (not including this one) in the &lt;span class="caps"&gt;SICP&lt;/span&gt; category, spread over 10 months.&lt;/li&gt;
		&lt;li&gt;The combined total length of my posts (including code snippets) is 66,265 words. For comparison, Jack London's "Son of the Wolf" is 50K words long.&lt;/li&gt;
		&lt;li&gt;Some of the large projects from the book I've re-implemented in wholeness: a constraint propagation solver, an evaluator (interpreter) for Scheme, a generic object-oriented arithmetic package including complex and polynomial arithmetic, Huffman encoding, an interpreter for a logic programming language similar to Prolog (as a &lt;span class="caps"&gt;DSL&lt;/span&gt; on top of Lisp), a picture-language interpreter, a simulator for digital circuits, a symbolic differentiation package, a virtual machine for a simplified pseudo-assembly &lt;span class="caps"&gt;DSL&lt;/span&gt;, an interpreter for Scheme written in this pseudo-assembly, and finally, a compiler for Scheme that spits out pseudo-assembly code.&lt;/li&gt;
		&lt;li&gt;Counting with the &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=174787"&gt;cloc&lt;/a&gt; tool (Count Lines Of Code), the total physical &lt;span class="caps"&gt;LOC&lt;/span&gt; count&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; for the code I've written during this time: 7,300 &lt;span class="caps"&gt;LOC&lt;/span&gt; of Common Lisp, 4,100 &lt;span class="caps"&gt;LOC&lt;/span&gt; of Scheme. If you prefer raw LOCs&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;, it's 10,800 &lt;span class="caps"&gt;LOC&lt;/span&gt; of Common Lisp, 5,600 &lt;span class="caps"&gt;LOC&lt;/span&gt; of Scheme. So this is more than 10 &lt;span class="caps"&gt;KLOC&lt;/span&gt; of Lisp code, any way you look at it, which is a lot, since Lisp is a very expressive high-level functional language.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;A word on &lt;span class="caps"&gt;SICP&lt;/span&gt; and its exercises. Abelson and Sussman have created a masterpiece, a book initially written in the 1980s, and that still hasn't lost one bit of relevance. Everything it contains must, &lt;strong&gt;must&lt;/strong&gt; be learned and understood by any aspiring programmer. It teaches algorithms and data structures, good programming style, provides some contact with large systems, experimenting with their implementation and modification. You will learn about functional programming, imperative programming, object-oriented programming in it. You will learn how to implement interpreters, compilers, arithmetic systems, simulators, a whole virtual machine in it, and much more.&lt;/p&gt;


	&lt;p&gt;The exercises of &lt;span class="caps"&gt;SICP&lt;/span&gt; are essential to understanding. Looking back at the work I've done on the book, I don't think I would have understood it near so well without doing a lot of the exercises. There's only so much material that can be gained from reading. Getting your hands dirty with code is essential to true understanding. And the authors of &lt;span class="caps"&gt;SICP&lt;/span&gt; brought this concept to perfection, with their excellent exercises, that are an unreplaceable companion to the book. Although they're not 100% perfect, for the most part the exercises are very well thought out and tuned to aid understanding and practice writing parts of large systems.&lt;/p&gt;


&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Physical &lt;span class="caps"&gt;LOC&lt;/span&gt;: lines of code, excluding comments and blank lines. To test my Common Lisp and Scheme code counts with &lt;code&gt;cloc.pl&lt;/code&gt;, I used these commands:&lt;/p&gt;


&lt;pre&gt;
cloc.pl --force-lang="Lisp",lisp *.lisp
cloc.pl --force-lang="Lisp",scm *.scm
&lt;/pre&gt;

	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Including comments and blank lines, as output by &lt;code&gt;wc -l&lt;/code&gt;.&lt;/p&gt;

    </content><category term="misc"></category><category term="SICP"></category></entry><entry><title>SICP section 5.5</title><link href="https://eli.thegreenplace.net/2008/04/18/sicp-section-55" rel="alternate"></link><published>2008-04-18T12:17:37-07:00</published><updated>2022-10-04T14:08:24-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-04-18:/2008/04/18/sicp-section-55</id><summary type="html">
        &lt;p&gt;It took me some effort to get the compiler code to work in conjunction with the explicit control evaluator, especially when it came to linking compiled and interpreted code. The prime problem was additions I've made to the register machine simulator in previous chapters, in answer to exercises, and that …&lt;/p&gt;</summary><content type="html">
        &lt;p&gt;It took me some effort to get the compiler code to work in conjunction with the explicit control evaluator, especially when it came to linking compiled and interpreted code. The prime problem was additions I've made to the register machine simulator in previous chapters, in answer to exercises, and that didn't work well with the needs of the compiler.&lt;/p&gt;


	&lt;p&gt;For example, in one of the exercises it was requested to test whether operations are being done on labels, and flag these cases as errors. However, in &lt;code&gt;compile-lambda&lt;/code&gt;, the compiler creates this assignment:&lt;/p&gt;


&lt;pre&gt;
`((assign ,target
    (op make-compiled-procedure)
    (label ,proc-entry)
    (reg env)))))
&lt;/pre&gt;

&lt;!--more--&gt;

	&lt;p&gt;Note that it acts upon a label. So, I had to modify &lt;code&gt;make-operation-exp&lt;/code&gt; and remove the error caused by operations on labels.&lt;/p&gt;


	&lt;p&gt;Another place where a change was needed is in &lt;code&gt;lookup-variable-value&lt;/code&gt;, which, to answer an exercise, was modified to prepend &lt;code&gt;bound&lt;/code&gt; or &lt;code&gt;unbound&lt;/code&gt; to variables that were looked up. So I modified the code of &lt;code&gt;compile-variable&lt;/code&gt; to:&lt;/p&gt;


&lt;pre&gt;
(define (compile-variable exp target linkage)
  (end-with-linkage linkage
    (make-instruction-sequence '(env) (list target)
      `((assign ,target
                (op lookup-variable-value)
                (const ,exp)
                (reg env))
        (assign ,target
                (op var-val-extract-value)
                (reg ,target))))))
&lt;/pre&gt;

	&lt;p&gt;The addition is another &lt;code&gt;assign&lt;/code&gt; which uses &lt;code&gt;var-val-extract-value&lt;/code&gt; to extract the bound symbol values. As before the exercise, this code assumes that all the looked up variables are actually bound, and does not signal an error&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;p&gt;All the code required to run the compiler and execute the compiled code together with the explicit control evaluator on the register machine simulator can be downloaded in this bundle&lt;/p&gt;


	&lt;p&gt;In case you've missed it, consider what we have here. We have a compiler for Scheme, written in Scheme. This compiler spits out custom assembly code that executes on a register machine simulator, also written in Scheme. Moreover, this code can coexist with an interpreter for Scheme, written in the same assembly code. Isn't this just awesome ?&lt;/p&gt;


	&lt;p&gt;Anyway, since we now have all the infrastructure running, we're ready to tackle the exercises.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.31&lt;/h4&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;(f 'x 'y)&lt;/code&gt; &amp;#8211; all those saves and restores are superfluous, because looking up the operator and operands does not modify any registers.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;((f) 'x 'y)&lt;/code&gt; &amp;#8211; again, all the saves are superfluous. At first sight it might seem that &lt;code&gt;(f)&lt;/code&gt; may modify the &lt;code&gt;env&lt;/code&gt; register, so &lt;code&gt;env&lt;/code&gt; must be saved. But note that &lt;code&gt;env&lt;/code&gt; is not needed to evaluate the operands, since they are constants. Had the expression been &lt;code&gt;((f) x 'y)&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt; should've been saved, because it's needed to evaluate the variable &lt;code&gt;x&lt;/code&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;(f (g 'x) y)&lt;/code&gt; &amp;#8211; &lt;code&gt;proc&lt;/code&gt; must be saved around the evaluation of the first operand, because it involves an application, which modifies &lt;code&gt;proc&lt;/code&gt;. The application also modifies &lt;code&gt;argl&lt;/code&gt;, so that one has to be saved too. &lt;code&gt;env&lt;/code&gt;, however, needs not be saved. To understand why, recall that the compiler builds the argument list in reverse. So first it evaluates &lt;code&gt;y&lt;/code&gt;, and only then &lt;code&gt;(g 'x)&lt;/code&gt;. Evaluating &lt;code&gt;y&lt;/code&gt; does not modify &lt;code&gt;env&lt;/code&gt;, so saving it isn't required.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;(f (g 'x) 'y)&lt;/code&gt; &amp;#8211; exactly similar to the previous case. Since the argument list is built in reverse, &lt;code&gt;(g 'x)&lt;/code&gt; is constructed last, and there's really no difference in the effects of looking up &lt;code&gt;y&lt;/code&gt; or &lt;code&gt;'y&lt;/code&gt; on the registers.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h4&gt;Exercise 5.32&lt;/h4&gt;


	&lt;p&gt;&lt;strong&gt;a.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;The section beginning with &lt;code&gt;ev-application&lt;/code&gt; has to be modified to:&lt;/p&gt;


&lt;pre&gt;
ev-application
  (save continue)
  (assign unev (op operands) (reg exp))
  (assign exp (op operator) (reg exp))
  (test (op symbol?) (reg exp))
  (branch (label ev-appl-operator-symbol))
  (save env)
  (save unev)      
  (assign continue (label ev-appl-did-operator))
  (goto (label eval-dispatch))
ev-appl-operator-symbol
  (assign continue (label ev-appl-did-operator-no-restore))
  (goto (label eval-dispatch))
ev-appl-did-operator
  (restore unev)              ; the operands
  (restore env)
ev-appl-did-operator-no-restore
  (assign argl (op empty-arglist))
  (assign proc (reg val))     ; the operator
  (test (op no-operands?) (reg unev))
  (branch (label apply-dispatch))
  (save proc)
&lt;/pre&gt;

	&lt;p&gt;Note the test for &lt;code&gt;symbol?&lt;/code&gt; that jumps over the saves, and assigns &lt;code&gt;continue&lt;/code&gt; to a label that skips the restores.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;b.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Alyssa is wrong for two reasons.&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Note that the test and branch inserted in the code of part &lt;strong&gt;a.&lt;/strong&gt; does not come for free &amp;#8211; it has to be executed for each operator, so the performance increase is less than expected. The compiler does its optimizations at compile-time, investing the time once but causing the code to run faster every time it's executed.&lt;/li&gt;
		&lt;li&gt;Another major reason for the compiler's speed advantage over the interpreter is "parsing" of expressions. The evaluator has to take the expression &lt;code&gt;(+ 1 2)&lt;/code&gt; apart each time, figuring out that &lt;code&gt;+&lt;/code&gt; is the operator and 1 and 2 the operands. The compiler does this step just once, and generates code that already knows where everything is located.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h4&gt;Exercise 5.33&lt;/h4&gt;


	&lt;p&gt;The difference in the compiled code of the alternative is that it handles the invocation of the recursive call before evaluating &lt;code&gt;n&lt;/code&gt; in the multiplication, while the original code first evaluates &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Since the amount of instruction executed by each version of the compiled code is the same, I would expect the runtimes to be close to identical.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.34&lt;/h4&gt;


	&lt;p&gt;Here's the compiled code, annotated with comments:&lt;/p&gt;


&lt;pre&gt;
;; Construct the procedure and skip over code for
;; the procedure body
;;
  (assign val (op make-compiled-procedure) (label entry1) (reg env))
  (goto (label after-lambda2))
;; Entry point for calls to factorial
;;
entry1
  (assign env (op compiled-procedure-env) (reg proc))
  (assign env (op extend-environment) (const (n)) (reg argl) (reg env))
;; Construct the internal procedure 'iter'
;; 
  (assign val (op make-compiled-procedure) (label entry3) (reg env))
  (goto (label after-lambda4))
entry3
  (assign env (op compiled-procedure-env) (reg proc))
  (assign env (op extend-environment) (const (product counter)) (reg argl) (reg env))
  (save continue)
  (save env)
;; evaluate the 'if' predicate: (&amp;gt; counter n)
;;
  (assign proc (op lookup-variable-value) (const &amp;gt;) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (op lookup-variable-value) (const n) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op list) (reg val))
  (assign val (op lookup-variable-value) (const counter) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch8))
compiled-branch9
  (assign continue (label after-call10))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch8
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
after-call10
  (restore env)
  (restore continue)
;; Test the 'if' predicate
;;
  (test (op false?) (reg val))
  (branch (label false-branch6))
;; In the true branch, evaluate and return 'product'
;;
true-branch5
  (assign val (op lookup-variable-value) (const product) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (goto (reg continue))
;; In the false branch, evaluate the application
;; of iter.
;;
false-branch6
  (assign proc (op lookup-variable-value) (const iter) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (save continue)
  (save proc)
  (save env)
;; Evaluate (+ counter 1)
;;
  (assign proc (op lookup-variable-value) (const +) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (const 1))
  (assign argl (op list) (reg val))
  (assign val (op lookup-variable-value) (const counter) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch14))
compiled-branch15
  (assign continue (label after-call16))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch14
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
after-call16
  (assign argl (op list) (reg val))
  (restore env)
  (save argl)
;; Evaluate (* counter product)
;;
  (assign proc (op lookup-variable-value) (const *) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (op lookup-variable-value) (const product) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op list) (reg val))
  (assign val (op lookup-variable-value) (const counter) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch11))
compiled-branch12
  (assign continue (label after-call13))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch11
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
after-call13
  (restore argl)
  (assign argl (op cons) (reg val) (reg argl))
  (restore proc)
  (restore continue)
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch17))
;; The "recursive" call is done here.
;;
compiled-branch18
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch17
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
  (goto (reg continue))
after-call19
after-if7
;; After the body of the internal procedure,
;; we can compile the rest of the body of 
;; 'factorial'
;;
after-lambda4
;; Assign the variable 'iter' its procedure body
;;
  (perform (op define-variable!) (const iter) (reg val) (reg env))
  (assign val (const ok))
;; Execute (iter 1 1)
;;
  (assign proc (op lookup-variable-value) (const iter) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (const 1))
  (assign argl (op list) (reg val))
  (assign val (const 1))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch20))
compiled-branch21
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch20
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
  (goto (reg continue))
after-call22
;; Now assign 
;;
after-lambda2
  (perform (op define-variable!) (const factorial) (reg val) (reg env))
  (assign val (const ok))
&lt;/pre&gt;

	&lt;p&gt;Note that nothing is saved before the recursive call to &lt;code&gt;iter&lt;/code&gt;, in order to be restored later. It just jumps back to &lt;code&gt;iter&lt;/code&gt; using &lt;code&gt;(goto (reg val))&lt;/code&gt;. Contrary to the recursive case, where &lt;code&gt;continue&lt;/code&gt; was assigned to just after the recursive call before executing it, here &lt;code&gt;continue&lt;/code&gt; is just restored from the stack to its pre-call value. This is the essence of tail-call optimization.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.35&lt;/h4&gt;


	&lt;p&gt;Following the code carefully, and remembering that the argument list is being built from right to left, it's not difficult to see that the Scheme code that compiled into this was:&lt;/p&gt;


&lt;pre&gt;
(define (f x)
  (+ x (g (+ x 2))))
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.36&lt;/h4&gt;


	&lt;p&gt;The compiler produces right-to-left order of evaluation for operands of a combinations. This can be easily seen in the compiled code for &lt;code&gt;(+ x y)&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;
  (assign proc (op lookup-variable-value) (const +) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (op lookup-variable-value) (const y) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op list) (reg val))
  (assign val (op lookup-variable-value) (const x) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch1))
compiled-branch2
  (assign continue (label after-call3))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch1
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
after-call3
&lt;/pre&gt;

	&lt;p&gt;Note the order of &lt;code&gt;lookup-variable-value&lt;/code&gt; calls. &lt;code&gt;y&lt;/code&gt; is first, &lt;code&gt;x&lt;/code&gt; second.&lt;/p&gt;


	&lt;p&gt;The reason for this is also clear and was thoroughly explained in section 5.5.3 &amp;#8211; "Compiling Combinations"&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;The code to construct the argument list will evaluate each operand into val and then cons that value onto the argument list being accumulated in argl. Since we cons the arguments onto argl in sequence, we must start with the last argument and end with the first, so that the arguments will appear in order from first to last in the resulting list.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;In the compiler code, the culprit is function &lt;code&gt;construct-arglist&lt;/code&gt;, which calls &lt;code&gt;reverse&lt;/code&gt; on the list of operand codes before generating the actual code for them.&lt;/p&gt;


	&lt;p&gt;In order to modify the order to left-to-right, we'll need to move the &lt;code&gt;reverse&lt;/code&gt; from compile-time to run-time. The instructions will be generated in left-to-right order, and &lt;code&gt;reverse&lt;/code&gt; will be called on &lt;code&gt;argl&lt;/code&gt; afterwards. Here's the modified &lt;code&gt;construct-arglist&lt;/code&gt; that does the job:&lt;/p&gt;


&lt;pre&gt;
(define (construct-arglist operand-codes)
  (let ((operand-codes operand-codes))
    (if (null? operand-codes)
      (make-instruction-sequence '() '(argl)
        `((assign argl (const ()))))
      (let ((code-to-get-last-arg
              (append-instruction-sequences
                (car operand-codes)
                (make-instruction-sequence '(val) '(argl)
                  `((assign argl (op list) (reg val)))))))
        (if (null? (cdr operand-codes))
          code-to-get-last-arg
          (tack-on-instruction-sequence 
            (preserving '(env)
              code-to-get-last-arg
              (code-to-get-rest-args
                (cdr operand-codes)))
            (make-instruction-sequence '() '()
              '((assign argl (op reverse) (reg argl))))))))))
&lt;/pre&gt;

	&lt;p&gt;Now the compiled code for &lt;code&gt;(+ x y)&lt;/code&gt; will be:&lt;/p&gt;


&lt;pre&gt;
  (assign proc (op lookup-variable-value) (const +) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (op lookup-variable-value) (const x) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op list) (reg val))
  (assign val (op lookup-variable-value) (const y) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (assign argl (op reverse) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch1))
compiled-branch2
  (assign continue (label after-call3))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch1
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
after-call3
&lt;/pre&gt;

	&lt;p&gt;This version of the compiler generates slower code, because the &lt;code&gt;reverse&lt;/code&gt; now has to be performed at run-time, something that was spared before.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.37&lt;/h4&gt;


	&lt;p&gt;The function &lt;code&gt;preserving&lt;/code&gt; generates a &lt;code&gt;save&lt;/code&gt; and &lt;code&gt;restore&lt;/code&gt; for a register only if the first statement modifies a register the second one needs. By removing this condition, we can make &lt;code&gt;preserving&lt;/code&gt; generate the instructions always:&lt;/p&gt;


&lt;pre&gt;
(define (preserving regs seq1 seq2)
  (if (null? regs)
    (append-instruction-sequences seq1 seq2)
    (let ((first-reg (car regs)))
      (preserving (cdr regs)
        (make-instruction-sequence
          (list-union (list first-reg) (registers-needed seq1))
          (list-difference
            (registers-modified seq1)
            (list first-reg))
          (append 
            `((save ,first-reg))
            (statements seq1)
            `((restore ,first-reg))))
        seq2))))
&lt;/pre&gt;

	&lt;p&gt;Here's the compiled code for &lt;code&gt;(f 1 2)&lt;/code&gt; with the original &lt;code&gt;preserving&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;
  (assign proc (op lookup-variable-value) (const f) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (const 2))
  (assign argl (op list) (reg val))
  (assign val (const 1))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch1))
compiled-branch2
  (assign continue (label after-call3))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch1
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
after-call3
&lt;/pre&gt;

	&lt;p&gt;Note that no saves and restores are generated, because none are needed here (see solution for Exercise 5.31)&lt;/p&gt;


	&lt;p&gt;Now, the same expression with the modified &lt;code&gt;preserving&lt;/code&gt; is compiled to:&lt;/p&gt;


&lt;pre&gt;
  (save continue)
  (save env)
  (save continue)
  (assign proc (op lookup-variable-value) (const f) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (restore continue)
  (restore env)
  (restore continue)
  (save continue)
  (save proc)
  (save env)
  (save continue)
  (assign val (const 2))
  (restore continue)
  (assign argl (op list) (reg val))
  (restore env)
  (save argl)
  (save continue)
  (assign val (const 1))
  (restore continue)
  (restore argl)
  (assign argl (op cons) (reg val) (reg argl))
  (restore proc)
  (restore continue)
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch1))
compiled-branch2
  (assign continue (label after-call3))
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch1
  (save continue)
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
  (restore continue)
after-call3
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.38&lt;/h4&gt;


	&lt;p&gt;&lt;strong&gt;a &amp;#38; b&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;I'll add this new dispatch to &lt;code&gt;compile&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;
((memq (car exp) '(+ - * / =))
  (compile-open-binary-op exp target linkage))
&lt;/pre&gt;

	&lt;p&gt;And the extra code is:&lt;/p&gt;


&lt;pre&gt;
(define (spread-arguments a1 a2)
  (let ((ca1 (compile a1 'arg1 'next))
        (ca2 (compile a2 'arg2 'next)))
    (list ca1 ca2)))

(define (compile-open-binary-op exp target linkage)
  (if (= (length exp) 3)
    (let ((op (car exp))
          (args (spread-arguments (cadr exp) (caddr exp))))
      (end-with-linkage linkage
        (append-instruction-sequences
          (car args)
          (preserving '(arg1)
            (cadr args)
            (make-instruction-sequence '(arg1 arg2) (list target)
              `((assign ,target (op ,op) (reg arg1) (reg arg2))))))))
    (error "Expected a 3-element list -- COMPILE-OPEN-BINARY-OP" exp)))
&lt;/pre&gt;

	&lt;p&gt;Note that &lt;code&gt;spread-arguments&lt;/code&gt; accepts strictly two arguments, because it has to place them in &lt;code&gt;arg1&lt;/code&gt; and &lt;code&gt;arg2&lt;/code&gt;. Also, I made it return a normal list, rather than an instruction sequence. This is because the appropriate place what to preserve is &lt;code&gt;compile-open-binary-op&lt;/code&gt;, that has 3 instruction sequences to append:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;The evaluation of the first argument into &lt;code&gt;arg1&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;The evaluation of the second argument into &lt;code&gt;arg2&lt;/code&gt;, preserving &lt;code&gt;arg1&lt;/code&gt; because it will be needed later&lt;/li&gt;
		&lt;li&gt;The application of the operator to &lt;code&gt;arg1&lt;/code&gt; and &lt;code&gt;arg2&lt;/code&gt;&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Here are a couple of examples of code generated with these functions:&lt;/p&gt;


&lt;pre&gt;
'(* 4 5)
=&amp;gt;
  (assign arg1 (const 4))
  (assign arg2 (const 5))
  (assign val (op *) (reg arg1) (reg arg2))
  (goto (reg continue))

(* 66 (+ 1 3))
=&amp;gt;
  (assign arg1 (const 66))
  (save arg1)
  (assign arg1 (const 1))
  (assign arg2 (const 3))
  (assign arg2 (op +) (reg arg1) (reg arg2))
  (restore arg1)
  (assign val (op *) (reg arg1) (reg arg2))
  (goto (reg continue))
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.39&lt;/h4&gt;


&lt;pre&gt;
(define (make-lexaddr framenum displacement)
  (list framenum displacement))

(define (lexaddr-framenum lexaddr)
  (car lexaddr))

(define (lexaddr-displacement lexaddr)
  (cadr lexaddr))

; Note, the following two functions operate on the _runtime_
; environment, where each frame is a pair: list of variables 
; with a list of their values.
;
(define (lexical-address-lookup lexaddr rt-env)
  (let ((addr-frame (list-ref rt-env (lexaddr-framenum lexaddr))))
    (let ((addr-val (list-ref (frame-values addr-frame) (lexaddr-displacement lexaddr))))
      (if (eq? addr-val '*unassigned*)
        (error "Var is unassigned"))
        (cons 'bound addr-val))))

(define (lexical-address-set! lexaddr rt-env newval)
  (let ((addr-frame (list-ref rt-env (lexaddr-framenum lexaddr))))
    (define (iter vals count)
      (cond ((null? vals)
              (error "Invalid lexical address - bad displacement"))
            ((= count 0)
              (set-car! vals newval))
            (else (iter (cdr vals) (+ 1 count)))))
    (iter (frame-values addr-frame) (lexaddr-displacement lexaddr))))
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.40&lt;/h4&gt;


	&lt;p&gt;The full code for this section, including the modified compiler, can be downloaded here&lt;/p&gt;


	&lt;p&gt;He're the code generator for &lt;code&gt;lambda&lt;/code&gt;, which extends the compile-time environment:&lt;/p&gt;


&lt;pre&gt;
(define (compile-lambda-body exp proc-entry ct-env)
  (let ((formals (lambda-parameters exp)))
    (append-instruction-sequences
      (make-instruction-sequence '(env proc argl) '(env)
        `(,proc-entry
          (assign env (op compiled-procedure-env) (reg proc))
          (assign env
                  (op extend-environment)
                  (const ,formals)
                  (reg argl)
                  (reg env))))
      (compile-sequence 
        (lambda-body exp) 
        'val 'return 
        (extend-ct-env ct-env formals)))))
&lt;/pre&gt;

	&lt;p&gt;It uses this utility function:&lt;/p&gt;


&lt;pre&gt;
(define (extend-ct-env ct-env frame)
  (cons frame ct-env))
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.41&lt;/h4&gt;


&lt;pre&gt;
(define (find-variable var ct-env)
  (define (frame-iter var frames count)
    (if (null? frames) 
      '()
      (let ((var-index (index-in-list 
                        (lambda (i) (eq? i var))
                        (car frames))))
        (if (null? var-index)
          (frame-iter var (cdr frames) (+ count 1))
          (make-lexaddr count var-index)))))
  (frame-iter var ct-env 0))

; Returns the numerical index (0-based) of the first 
; item from the list that satisfies the predicate.
; If no suitable item is found, returns '()
;
(define (index-in-list pred lst)
  (define (iter pred lst count)
    (cond
      ((null? lst) '())
      ((pred (car lst)) count)
      (else (iter pred (cdr lst) (+ count 1)))))
  (iter pred lst 0)) 
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.42&lt;/h4&gt;


	&lt;p&gt;To understand how this works, it's important to keep in mind that the structure of the compile-time environment follows the structure of the run-time environment. The compiler, by knowing where inside the stack of &lt;code&gt;lambda&lt;/code&gt; statements it's located, can figure out which value is referenced in the code.&lt;/p&gt;


&lt;pre&gt;
(define (compile-variable exp target linkage ct-env)
  (let ((lookup-instruction 
          (let ((lexaddr-of-var (find-variable exp ct-env)))
            (if (null? lexaddr-of-var)
              `(assign ,target
                        (op lookup-variable-value)
                        (const ,exp)
                        (reg env))
              `(assign ,target
                        (op lexical-address-lookup)
                        (const ,lexaddr-of-var)
                        (reg env))))))
    (end-with-linkage linkage
      (make-instruction-sequence '(env) (list target)
        (list
          lookup-instruction
          `(assign ,target
                  (op var-val-extract-value)
                  (reg ,target)))))))

(define (compile-assignment exp target linkage ct-env)
  (let ((var (assignment-variable exp))
        (get-value-code
          (compile (assignment-value exp) 'val 'next ct-env)))
    (end-with-linkage linkage
      (preserving '(env)
        get-value-code
        (make-instruction-sequence '(env val) (list target)
          (let ((lexaddr-of-var (find-variable var ct-env)))
            (if (null? lexaddr-of-var)
              `((perform 
                  (op set-variable-value!)
                  (const ,var)
                  (reg val)
                  (reg env))
                (assign ,target (const ok)))
              `((perform
                  (op lexical-address-set!)
                  (const ,lexaddr-of-var)
                  (reg env)
                  (reg val))
                (assign ,target (const ok))))))))))
&lt;/pre&gt;

	&lt;p&gt;Here's an example that demonstrates how these modifications work. This code:&lt;/p&gt;


&lt;pre&gt;
(define code
  '((lambda (x y) 
      (lambda (u v w)
        (set! x 60)
        (+ v w x))
      10 20 30)
    1 2)
)
&lt;/pre&gt;

	&lt;p&gt;Is compiled into:&lt;/p&gt;


&lt;pre&gt;
  (assign proc (op make-compiled-procedure) (label entry1) (reg env))
  (goto (label after-lambda2))
entry1
  (assign env (op compiled-procedure-env) (reg proc))
  (assign env (op extend-environment) (const (x y)) (reg argl) (reg env))
  (assign val (op make-compiled-procedure) (label entry3) (reg env))
  (goto (label after-lambda4))
entry3
  (assign env (op compiled-procedure-env) (reg proc))
  (assign env (op extend-environment) (const (u v w)) (reg argl) (reg env))
  (assign val (const 60))
  (perform (op lexical-address-set!) (const (1 0)) (reg env) (reg val))
  (assign val (const ok))
  (assign proc (op lookup-variable-value) (const +) (reg env))
  (assign proc (op var-val-extract-value) (reg proc))
  (assign val (op lexical-address-lookup) (const (1 0)) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op list) (reg val))
  (assign val (op lexical-address-lookup) (const (0 2)) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (assign val (op lexical-address-lookup) (const (0 1)) (reg env))
  (assign val (op var-val-extract-value) (reg val))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch5))
compiled-branch6
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch5
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
  (goto (reg continue))
after-call7
after-lambda4
  (assign val (const 10))
  (assign val (const 20))
  (assign val (const 30))
  (goto (reg continue))
after-lambda2
  (assign val (const 2))
  (assign argl (op list) (reg val))
  (assign val (const 1))
  (assign argl (op cons) (reg val) (reg argl))
  (test (op primitive-procedure?) (reg proc))
  (branch (label primitive-branch8))
compiled-branch9
  (assign val (op compiled-procedure-entry) (reg proc))
  (goto (reg val))
primitive-branch8
  (assign val (op apply-primitive-procedure) (reg proc) (reg argl))
  (goto (reg continue))
after-call10
&lt;/pre&gt;

	&lt;p&gt;Note how the relevant variables are accessed using &lt;code&gt;lexical-address-lookup&lt;/code&gt;, where applicable.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.43&lt;/h4&gt;


	&lt;p&gt;The change required here is very simple. &lt;code&gt;compile-lambda-body&lt;/code&gt; is modified to execute &lt;code&gt;scan-out-defines&lt;/code&gt; on the lambda body before passing it on to compilation:&lt;/p&gt;


&lt;pre&gt;
(define (compile-lambda-body exp proc-entry ct-env)
  (let ((formals (lambda-parameters exp)))
    (append-instruction-sequences
      (make-instruction-sequence '(env proc argl) '(env)
        `(,proc-entry
          (assign env (op compiled-procedure-env) (reg proc))
          (assign env
                  (op extend-environment)
                  (const ,formals)
                  (reg argl)
                  (reg env))))
      (compile-sequence 
        (scan-out-defines (lambda-body exp))  ;; change!
        'val 'return 
        (extend-ct-env ct-env formals)))))
&lt;/pre&gt;

	&lt;h4&gt;The rest of section 5.5&lt;/h4&gt;


	&lt;p&gt;I think I'll skip the rest of the exercises.&lt;/p&gt;


&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Although such error signaling shouldn't be difficult to add.&lt;/p&gt;

    </content><category term="misc"></category><category term="SICP"></category></entry><entry><title>SICP section 5.4</title><link href="https://eli.thegreenplace.net/2008/04/04/sicp-section-54" rel="alternate"></link><published>2008-04-04T08:39:25-07:00</published><updated>2022-10-04T14:08:24-07:00</updated><author><name>Eli Bendersky</name></author><id>tag:eli.thegreenplace.net,2008-04-04:/2008/04/04/sicp-section-54</id><summary type="html">
        &lt;p&gt;When I began writing the explicit-control evaluator code for this section, I ran into a minor language incompatibility. While I've used CL to implement the meta-circular evaluator of chapter 4, I've employed Scheme for the implementation of the register machine simulator earlier in this chapter. This means that I can't …&lt;/p&gt;</summary><content type="html">
        &lt;p&gt;When I began writing the explicit-control evaluator code for this section, I ran into a minor language incompatibility. While I've used CL to implement the meta-circular evaluator of chapter 4, I've employed Scheme for the implementation of the register machine simulator earlier in this chapter. This means that I can't use the meta-circular evaluator's primitive functions directly in my register-machine code.&lt;/p&gt;

&lt;!--more--&gt;
	&lt;p&gt;So I've downloaded the code from chapter 4 of the book from &lt;a href="http://mitpress.mit.edu/sicp/code/index.html"&gt;here&lt;/a&gt;. The specific file that is included in my code is this one &amp;#8211; I've cleaned it up and modified it a little to be compatible with &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme, and provide only the required functionality.&lt;/p&gt;


	&lt;p&gt;The explicit-control evaluator itself is available here. I've modified it a little, adding some functionality for non-interactive evaluation. Specifically, this code:&lt;/p&gt;


&lt;pre&gt;
non-interactive-eval
  (perform (op initialize-stack))
  (test (op null?) (reg machine-args))
  (branch (label machine-end))
  (assign exp (op car) (reg machine-args))
  (assign machine-args (op cdr) (reg machine-args))
  (assign env (op get-global-environment))
  (assign continue (label non-interactive-eval))
  (goto (label eval-dispatch))
&lt;/pre&gt;

	&lt;p&gt;Can be jumped to instead of &lt;code&gt;read-eval-print-loop&lt;/code&gt;. It assumes there is a list of expressions to be evaluated in the &lt;code&gt;machine-args&lt;/code&gt; register, and goes over them, evaluating them from left to right. This allows for convenient execution of the evaluator as follows:&lt;/p&gt;


&lt;pre&gt;
(define code
  '(
    (define (sumsq a b)
      (+ (* a a) (* b b)))
    (define x 5)
    (define y 7)
    (define ans (sumsq x y))
    (print ans)
    ))

(set-register-contents! ec-eval 'machine-args code)
(start ec-eval)
=&amp;gt;
74
&lt;/pre&gt;

	&lt;p&gt;You'll also see in the beginning of the controller code these two lines:&lt;/p&gt;


&lt;pre&gt;
  ; (goto (label read-eval-print-loop))
  (goto (label non-interactive-eval))
&lt;/pre&gt;

	&lt;p&gt;Currently the jump to &lt;code&gt;read-eval-print-loop&lt;/code&gt; is commented, but this can be easily changed.&lt;/p&gt;


	&lt;p&gt;Another change you'll note in the definition of the machine's operations. I got tired of writing each operator name twice (once quoted, and once plain), and wrote the macro&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;code&gt;qq&lt;/code&gt; to handle it for me:&lt;/p&gt;


&lt;pre&gt;
(define-macro (qq e)
  `(list ',e ,e))
&lt;/pre&gt;

	&lt;p&gt;For example, &lt;code&gt;(qq adjoin-arg)&lt;/code&gt; gets translated in "compile-time" into &lt;code&gt;(list 'adjoin-arg adjoin-arg)&lt;/code&gt; so I have less repetitive typing to do.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.23&lt;/h4&gt;


	&lt;p&gt;Adding support for &lt;code&gt;cond&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;
ev-cond
  (assign exp (op cond-&amp;gt;if) (reg exp))
  (goto (label ev-if))
&lt;/pre&gt;

	&lt;p&gt;And the appropriate dispatch is:&lt;/p&gt;


&lt;pre&gt;
(test (op cond?) (reg exp))
(branch (label ev-cond))
&lt;/pre&gt;

	&lt;p&gt;Finally, to make it all work the operations &lt;code&gt;cond?&lt;/code&gt; and &lt;code&gt;cond-&amp;gt;if&lt;/code&gt; must be added to the machine.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.24&lt;/h4&gt;


	&lt;p&gt;Here's the code:&lt;/p&gt;


&lt;pre&gt;
  ;; Implemented explicitly as a basic special form, 
  ;; without converting to a nested if
  ;;
ev-cond-basic
  (assign unev (op cond-clauses) (reg exp))
ev-cond-ev-clause
  (assign exp (op first-exp) (reg unev))
  (test (op cond-else-clause?) (reg exp))
  (branch (label ev-cond-action))
  (save exp)
  (save env)
  (save unev)
  (save continue)
  ;; Setup an evaluation of the clause predicate
  (assign exp (op cond-predicate) (reg exp))
  (assign continue (label ev-cond-clause-decide))
  (goto (label eval-dispatch))

ev-cond-clause-decide
  (restore continue)
  (restore unev)
  (restore env)
  (restore exp)
  (test (op true?) (reg val))
  (branch (label ev-cond-action))
ev-cond-next-clause
  (assign unev (op rest-exps) (reg unev))
  (goto (label ev-cond-ev-clause)) ; loop to next clause

  ;; We get here when the clause condition was found to
  ;; be true (or it was an 'else' clause), and we want
  ;; the actions to be evaluated. The clause is in exp.
  ;; We setup a call to ev-sequence and jump to it.
  ;;
ev-cond-action
  (assign unev (op cond-actions) (reg exp))
  (save continue)
  (goto (label ev-sequence))
&lt;/pre&gt;

	&lt;p&gt;Now &lt;code&gt;eval-dispatch&lt;/code&gt; can jump to &lt;code&gt;ev-cond-basic&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;
  (test (op cond?) (reg exp))
  (branch (label ev-cond-basic))
&lt;/pre&gt;

	&lt;h4&gt;Exercise 5.25&lt;/h4&gt;


	&lt;p&gt;I'll pass.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.26&lt;/h4&gt;


	&lt;p&gt;To make this work, I've re-included the modified &lt;code&gt;make-new-machine&lt;/code&gt; and &lt;code&gt;make-stack&lt;/code&gt; from exercise 5.14, and removed the command to reinitialize the stack after each executed expression in &lt;code&gt;non-interactive-eval&lt;/code&gt;. The code I'm running is:&lt;/p&gt;


&lt;pre&gt;
(define code
  '(
    (define (factorial n)
      (define (iter product counter)
        (if (&amp;gt; counter n)
            product
            (iter (* counter product)
                  (+ counter 1))))
      (iter 1 1))

    (newline)
    (print (factorial 3))
    (newline)
  ))

(set-register-contents! ec-eval 'machine-args code)
(start ec-eval)

(newline)
(newline)
&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;a.&lt;/strong&gt; The maximal depth required for this code is 13&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;b.&lt;/strong&gt;&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;n&lt;/th&gt;
			&lt;th&gt;pushes&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2&lt;/td&gt;
			&lt;td&gt;113&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;3&lt;/td&gt;
			&lt;td&gt;148&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;4&lt;/td&gt;
			&lt;td&gt;183&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;5&lt;/td&gt;
			&lt;td&gt;218&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;From this, the number of pushes is &lt;code&gt;35n + 43&lt;/code&gt;.&lt;/p&gt;


	&lt;h4&gt;Exercise 5.27&lt;/h4&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;Type&lt;/th&gt;
			&lt;th&gt;Maximal depth&lt;/th&gt;
			&lt;th&gt;Number of pushes&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Recursive&lt;/td&gt;
			&lt;td&gt;5n + 6&lt;/td&gt;
			&lt;td&gt;32n &amp;#8211; 2&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Iterative&lt;/td&gt;
			&lt;td&gt;13&lt;/td&gt;
			&lt;td&gt;35n + 43&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;h4&gt;Exercise 5.28&lt;/h4&gt;


	&lt;p&gt;After changing &lt;code&gt;ev-sequence&lt;/code&gt; to:&lt;/p&gt;


&lt;pre&gt;
ev-sequence
  (test (op no-more-exps?) (reg unev))
  (branch (label ev-sequence-end))
  (assign exp (op first-exp) (reg unev))
  (save unev)
  (save env)
  (assign continue (label ev-sequence-continue))
  (goto (label eval-dispatch))
ev-sequence-continue
  (restore env)
  (restore unev)
  (assign unev (op rest-exps) (reg unev))
  (goto (label ev-sequence))
ev-sequence-end
  (restore continue)
  (goto (reg continue))
&lt;/pre&gt;

	&lt;p&gt;The table of exercise 5.27 turns into:&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;Type&lt;/th&gt;
			&lt;th&gt;Maximal depth&lt;/th&gt;
			&lt;th&gt;Number of pushes&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Recursive&lt;/td&gt;
			&lt;td&gt;8n + 6&lt;/td&gt;
			&lt;td&gt;34n &amp;#8211; 2&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;Iterative&lt;/td&gt;
			&lt;td&gt;3n + 17&lt;/td&gt;
			&lt;td&gt;37n + 47&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;h4&gt;Exercise 5.29&lt;/h4&gt;


	&lt;p&gt;&lt;strong&gt;a.&lt;/strong&gt;&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;n&lt;/th&gt;
			&lt;th&gt;depth&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2&lt;/td&gt;
			&lt;td&gt;16&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;3&lt;/td&gt;
			&lt;td&gt;21&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;4&lt;/td&gt;
			&lt;td&gt;26&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;5&lt;/td&gt;
			&lt;td&gt;31&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;From this, the formula for depth is &lt;code&gt;5n + 6&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;b.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Let's collect some more data for this:&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;th&gt;n&lt;/th&gt;
			&lt;th&gt;pushes&lt;/th&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;2&lt;/td&gt;
			&lt;td&gt;86&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;3&lt;/td&gt;
			&lt;td&gt;142&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;4&lt;/td&gt;
			&lt;td&gt;254&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;5&lt;/td&gt;
			&lt;td&gt;422&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;6&lt;/td&gt;
			&lt;td&gt;702&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;7&lt;/td&gt;
			&lt;td&gt;1150&lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt;8&lt;/td&gt;
			&lt;td&gt;1878&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;p&gt;It can be easily seen that &lt;code&gt;S(n) = S(n-1) + S(n-2) + 26&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;To find out &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, I'll subtract &lt;code&gt;S(n)&lt;/code&gt; from &lt;code&gt;S(n+1)&lt;/code&gt; to cancel out &lt;code&gt;b&lt;/code&gt;: &lt;code&gt;S(n+1)-S(n) = a*Fib(n+2) - a*Fib(n+1) = a*(Fib(n+2) - Fib(n+1))&lt;/code&gt;. But due to the property of the Fibonacci series, this means that: &lt;code&gt;S(n+1)-S(n) = a*Fib(n)&lt;/code&gt;. And since &lt;code&gt;S(n) = S(n-1) + S(n-2) + 26&lt;/code&gt;, we can rewrite it as &lt;code&gt;a*Fib(n-1) = S(n-2) + 26&lt;/code&gt;, or &lt;code&gt;S(n) = a*Fib(n+1) - 26&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Now we're ready to assign the various results into this to compute &lt;code&gt;a&lt;/code&gt;. Having the formula and &lt;code&gt;b&lt;/code&gt; in our hands, it's easy to see that &lt;code&gt;a = 56&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;So, finally: &lt;code&gt;S(n) = 56Fib(n+1) - 26&lt;/code&gt;&lt;/p&gt;


	&lt;h4&gt;Exercise 5.30&lt;/h4&gt;


	&lt;p&gt;&lt;strong&gt;a.&lt;/strong&gt; 
Maybe I'm missing something, but this doesn't seem to be so much work. After all, a variable is only handled in a single place in the &lt;code&gt;eval&lt;/code&gt; dispatch, so this is the place to make a modification. First of all, I'll change the supporting Scheme code to have special values for unbound variables:&lt;/p&gt;


&lt;pre&gt;
(define (lookup-variable-value var env)
  (define (env-loop env)
    (define (scan vars vals)
      (cond ((null? vars)
              (env-loop (enclosing-environment env)))
            ((eq? var (car vars))
              (cons 'bound (car vals)))
            (else (scan (cdr vars) (cdr vals)))))
    (if (eq? env the-empty-environment)
        (cons 'unbound '())
        (let ((frame (first-frame env)))
          (scan (frame-variables frame)
                (frame-values frame)))))
  (env-loop env))

(define (var-val-bound? varval)
  (and 
    (pair? varval) 
    (eq? (car varval) 'bound)))

(define (var-val-extract-value varval)
  (cdr varval))
&lt;/pre&gt;

	&lt;p&gt;Now, changing &lt;code&gt;ev-variable&lt;/code&gt; in the evaluator code:&lt;/p&gt;


&lt;pre&gt;
ev-variable
  (assign val (op lookup-variable-value) (reg exp) (reg env))
  (test (op var-val-bound?) (reg val))
  (branch (label ev-variable-var-bound))
  (goto (label unbound-variable))
ev-variable-var-bound
  (assign val (op var-val-extract-value) (reg val))
  (goto (reg continue))
&lt;/pre&gt;

	&lt;p&gt;And finally, a new error type:&lt;/p&gt;


&lt;pre&gt;
unbound-variable
  (assign val (const unbound-variable-error))
  (goto (label signal-error))
&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;b.&lt;/strong&gt;
Well, this indeed is a lot of work, and it's very repetitive, so I'm reluctant to do it. The basic model is identical to what I've written in part &lt;strong&gt;a&lt;/strong&gt; of this question.&lt;/p&gt;


	&lt;p&gt;Each primitive that can signal an error must be modified similarly to the way &lt;code&gt;lookup-variable-value&lt;/code&gt; was modified, to return a pair of &lt;code&gt;(error? value)&lt;/code&gt;, with the appropriate support procedures. The evaluator code in &lt;code&gt;primitive-apply&lt;/code&gt; must check for the error, similarly to the modified &lt;code&gt;ev-variable&lt;/code&gt; in the code above.&lt;/p&gt;


&lt;img class="align-center" src="https://eli.thegreenplace.net/images/hline.jpg" style="width: 320px; height: 5px;" /&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Personally, I like the &lt;code&gt;define-macro&lt;/code&gt; utility more than the Scheme's &lt;code&gt;syntax-rules&lt;/code&gt; and &lt;code&gt;syntax-case&lt;/code&gt; macro tools. &lt;code&gt;define-macro&lt;/code&gt; is almost identical to Common Lisp's &lt;code&gt;defmacro&lt;/code&gt; and is natively supported by the most common Scheme implementations (Bigloo, Chicken, Gambit, Gauche and &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme). To use it in &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme you'll have to include the &lt;code&gt;defmacro.ss&lt;/code&gt; library:&lt;/p&gt;


&lt;pre&gt;
(require (lib "defmacro.ss"))
&lt;/pre&gt;

    </content><category term="misc"></category><category term="SICP"></category></entry></feed>