2020
2121@title[#:tag "Fraud " ]{Fraud: local binding and variables}
2222
23+ @emph{To be is to be the value of a variable.}
24+
25+ @table-of-contents[]
26+
27+ @section{Variables}
28+
2329@;defmodule[(file "/Users/dvanhorn/git/cmsc430-www/www/notes/fraud/interp.rkt")]
2430@;declare-exporting[(file "/Users/dvanhorn/git/cmsc430-www/www/notes/fraud/interp.rkt")]
2531@;defidform/inline[interp]
@@ -373,22 +379,39 @@ address of a variable occurrence is count of variable names that occur
373379before it in the list. When a variable is bound (via-@racket[let ])
374380the list grows:
375381
382+ @codeblock-include["fraud/translate.rkt " ]
383+
384+ Notice that @racket[translate] is a kind of mini-compiler that
385+ compiles @tt{Expr}s to @tt{IExpr}s. It's only job is to eliminate
386+ variable names by replacing variable occurrences with their lexical
387+ addresses. It does a minor amount of syntax checking while it's at it
388+ by raising a (compile-time) error in the case of unbound variables.
389+
390+ The interpreter for @tt{IExpr}s will still have an environment data
391+ structure, however it will be simpler the association list we started
392+ with. The run-time environment will consist only of a list of values;
393+ the lexical address of (what used to be a) variable indicates the
394+ position in this list. When a value is bound by a @racket[let ], the
395+ list grows:
396+
376397@codeblock-include["fraud/interp-lexical.rkt " ]
377398
399+ Try to convince yourself that the two version of @racket[interp]
400+ compute the same function.
378401
379402
380403@section{An Example of Fraud compilation}
381404
382- Suppose we want to compile @racket[' (let ((x 7 )) (add1 x))]. There
383- are two new forms we need to compile: the @racket[' (let ((x ... ))
384- ... )] part and the @racket[' x ] part in the body.
405+ Suppose we want to compile @racket[(let ((x 7 )) (add1 x))]. There
406+ are two new forms we need to compile: the @racket[(let ((x ... ))
407+ ... )] part and the @racket[x] part in the body.
385408
386- We already know how to compile the @racket[' (add1 ... )] part and the
409+ We already know how to compile the @racket[(add1 ... )] part and the
387410@racket[7 ] part.
388411
389412What needs to happen? Compiling the @racket[7 ] part will emit
390413instructions that, when run, leave @racket[7 ] in the @racket['rax ]
391- register. Compiling the @racket[' (add1 ... )] part relies on the
414+ register. Compiling the @racket[(add1 ... )] part relies on the
392415result of evaluating it's subexpression to be in @racket['rax ] when it
393416increments it. So, compile the variable binding needs to stash the
394417@racket[7 ] somewhere and compiling the variable occurrence needs to
@@ -401,16 +424,16 @@ a let, after the right-hand side has been run, the result should be
401424pushed. When evaluating a variable occurrence, the bound value is on
402425the stack. After exiting the let , the stack can be popped.
403426
404- Suppose we want to compile @racket[' (let ((x 7 )) (let ((y 2 )) (add1
427+ Suppose we want to compile @racket[(let ((x 7 )) (let ((y 2 )) (add1
405428x)))]. Using the intuition developed so far, we should push 7 , push
4064298 , and then run the body. But notice that the value of @racket['x ] is
407- no longer on the top of the stack; @racket[' y] is. So to retrieve the
408- value of @racket[' x ] we need jump past the @racket[' y ]. But
409- calculating these offsets is pretty straightforward. In this example
410- there is one binding between the binding of @racket[' x ] and this
411- occurrence. Since we push every time we enter a let and pop every
412- time we leave, the number of bindings between an occurrence and its
413- binder is exactly the offset from the top of the stack we need use.
430+ no longer on the top of the stack; @racket[y] is. So to retrieve the
431+ value of @racket[x] we need jump past the @racket[y]. But calculating
432+ these offsets is pretty straightforward. In this example there is one
433+ binding between the binding of @racket[x] and this occurrence. Since
434+ we push every time we enter a let and pop every time we leave, the
435+ number of bindings between an occurrence and its binder is exactly the
436+ offset from the top of the stack we need use.
414437
415438@filebox-include-fake[codeblock "fraud/asm/ast.rkt " ]{
416439#lang racket
0 commit comments