Page Numbers: Yes X: 306 Y: 1.0" First Page: 1 Margins: Top: 1.0" Bottom: 1.3" Heading: z18344l3000e2qk40(0,65535) LECTURE NOTES #11 LISP: LANGUAGE AND LITERATURE May 17, 1984 l3000d2469y756e2qk40(0,2999)(1,8079)(2,16733)(13,0)\f3 1f1 19f3 1f1 32f3 1f1 13f8 44f1 l3528d2999e2jk40(0,3528)(1,4798)(2,6068)(3,7338)(4,8608)(5,9878)(6,11148)(7,12418)(13,65535) Lecture Notes #11  Quotation and Structural Abstractionl3528d2999e9ck40\f5b21f8B1f0 2f5b Filed as: [phylum]<3-lisp>course>notes>Lecture-11.notes User.cm: [phylum]system>user.classic Last edited: May 17, 1984 1:35 PMe17k40(0,5248)(1,7680)\f1 9f3 1f1 54f3 1f1 52f3 1f1 e10jk40(0,3528)(1,4798)\f8 44f0 A. Introductory Notesl3528d2999e15jk40\b22B  Still no problem set #2!l3528d2999x0e10j\f8 1f0  A draft is done, but the TA's are working through it first. Will definitely be ready on Monday.l4798d4269x0e3j\f8 1f0  So have a relaxed weekend; things will start up in earnest at the beginning of next week.l4798d4269x0e3j\f8 1f0  Be encouraged to play with the machines; the definition of OBJECT, if you want to use it, is on both of:l4798d4269x0e3j\f8 1f0 60f3 6f0 {turing}<3-lisp.utilities>object.3-lisp {phylum}<3-lisp>course>utilities>object.3-lispl6068d5539x0e3j\f3 92f0  Today: Quotation and processing:l3528d2999x0e3j\f8 1f0 33f8  Have talked so far about various kinds of abstraction:l4798d4269x0e3j\f8 1f0  The use of higher-order functions and higher-order proceduresl6068d5539x0e3j\f8 1f0  Compound objects to represent various kinds of complex objectsl6068d5539x0e3j\f8 1f0  Control abstractions (last time)l6068d5539x0e3j\f8 1f0  Have presented enough basic machinery to enable people to go off and program for a year or two.l4798d4269x0e3j\f8 1f0  There are three more things that we will want to examine before the class is over:l4798d4269x0e3j\f8 1f0  Meta-linguistic techniques (today)l6068d5539x0e3j\f8 1f0  Explicit theories of how it all worksl6068d5539x0e3j\f8 1f0  Implementation and other architectures l6068d5539x0e3j\f8 1f0  Today will focus on the first of these: meta-linguistic and "meta-structural" abstractions: dealing with quotation, macros, so-called "meta-circular processors", etc.l4798d4269x0e3j\f8 1f0  Will pick up on the "internal account" presented in lectures 4 and 5.l6068d5539x0e3j\f8 1f0  This first task is a pre-requisite for the other two, sincel6068d5539x0e3j\f8 1f0 60i  what the semantics needs to describe, andl7338d6809x0e3j\f8 1f0 1i36I  how this (or any other) implementation worksl7338d6809x0e3j\f8 1f0 1i9I14i21I depend onl6068d5539x0e3j\f3 2f0  the explicit encoding of information (in procedures, programs, whatever)l7338d6809x0e3j\f8 1f0 1i36I which is, in essence, what quotation and meta-structural techniques deal with.l6068d5539x0e3j\f3 1f0  Things this will enable us to do:l4798d4269x0e3j\f8 1f0  discharge the debt taken out when we introduced OBJECT.l6068d5539x0e3j\f8 1f0 49f3 6f0  provide general macro definitions.l6068d5539x0e3j\f8 1f0  define things like IF*, which we couldn't do at the time of the first problem set.l6068d5539x0e3j\f8 1f0 20f3 3f0  explain, in much clearer detail, how the 3-LISP processor works.l6068d5539x0e3j\f8 1f0 42f7 6f0  Should read Abelson and Sussman Chapter 4.l3528d2999x0e3j\f8 1f0 B. Quotation and Structuresl3528d2999e15jk40\b28B  Quotation: what it is (rigid designation of other linguistic expressions)l3528d2999x0e10j\f8 1f0  Different kinds:l4798d4269x0e3j\f8 1f0  notational (designators of characters and character-strings)l6068d5539x0e3j\f8 1f0 1i10I  structural (designation of internal structures)l6068d5539x0e3j\f8 1f0 1i10I  Deal primarily with structural quotationl4798d4269x0e3j\f8 1f0  But important to see that there is a little algebra of all this stuff.l4798d4269x0e3j\f8 1f0  Review the various structure types, and operations defined over them.l3528d2999x0e3j\f8 1f0  Structures introduced to designate structure and notation:l4798d4269x0e3j\f8 1f0  Handles: for structural quotation;l6068d5539x0e3j\f8 1f0 1i7I  Stringers and charats: for notational quotationl6068d5539x0e3j\f8 1f0 1i9I5i7I  Note both are normal-form; charats and handles are canonical.l6068d5539x0e3j\f8 1f0  Notations used to notate the handles etc.l4798d4269x0e3j\f8 1f0  notation n1 for a structure s1 that designates structure s2l6068d5539x0e3j\f8 1f0  notation n1 for a structure s1 that designates notation n2l6068d5539x0e3j\f8 1f0  etc.l6068d5539x0e3j\f8 1f0  Figs 1, 2, and 3:l4798d4269x0e3j\f8 1f0 l4798d4269x0e3j l4798d4269x0e3j l4798d4269x0e3j  Operations that help mediate Q and F:l4798d4269x0e3jk100\f8 1f0 30f2 1f0 5f2 1f0  INTERNALIZE and EXTERNALIZEl6068d5539x0e3j\f8 1f0 1f3 11f0 5f3  ATOM-NOTATED and ATOM-NOTATIONl6068d5539x0e3j\f8 1f0 1f3 12f0 5f3 13f0  For example:l4798d4269x0e3j\f8 1f0 13f8 1 (internalize "2") 1= '2 1> (internalize "(+ x y)") 1= '(+ x y) 1> (internalize " (first ; this is a comment ;;; ;;; and some more ;;; x)") 1= '(first x)l7338d1760x0e3\f4 1f3  F(INTERNALIZE) = Ql4798d4269x0e3j\f8 1f0 1f2 1f3 12f0 4f2 1f8  PCONS, RCONS, etc. (ACONS)l4798d4269x0e3j\f8 1f0 1f3 5f0 2f3 5f0 8f3 5f0  FIRST and REST defined (polymorphic), PPROC and PARGS, etc.l4798d4269x0e3j\f8 1f0 1f3 5f0 5f3 4f0 24f3 5f0 5f3 5f0 C. Macrosl3528d2999e15jk40\b10B  Quotation: what it is (rigid designation of other linguistic expressions)l3528d2999x0e10j\f8 1f0  two kinds (as you might expect):l4798d4269x0e3j\f8 1f0  notational macrosl6068d5539x0e3j\f8 1f0  ^exp', for example, is a notational abbreviation for (UPexp)'l7338d6809x0e3j\f8 1f0 1f8 1f3 1i3f8I1f0 48f8 1f3 3f7 1f3i3I1f8 1f0  Also: ^exp' for (DOWN exp)'l7338d6809x0e3j\f8 1f0 7f8 1f4 1f3i3f8I1f0 5f8 1f3 6i3I1f8 1f3  Also: (e1e2...ek)' for (e1.[e2...ek])' l7338d6809x0e3j\f8 1f0 7f8 1f3 3f7 1f3 2f7 5f3 3f8 1f0 5f8 1f3 3f7 1f3 1f7 1f3 3f7 5f3 4f8 1f0  structural macrosl6068d5539x0e3j\f8 1f0  to motivate all of this, plunge in to structural macros:l3528d2999x0e3j\f8 1f0  a new kind of procedure-defining operator: MLAMBDA.l4798d4269x0e3j\f8 1f0 44f3 7f0  defines a procedure that computes a function from structures to structures, that is used in a particular way:l4798d4269x0e3j\f8 1f0  if F signifies (nb!) a procedure P, then normalizing (F.args) will first compute P((F.args)), and then normalize the result.l6068d5539x0e3j\f8 1f0 4f3 1f0 29f7 1f0 19f3 2f7 1f3 1f7 1f3i4I1f0 20f7 2f3 2f7 1f3 1f7 1f3i4I1f7 1f0  clear as mud; so an example:l4798d4269x0e3j\f8 1f0 1 (define INCREMENT (mlambda [call] (pcons '+ (rcons '1 (pargs call)))))l7338d1760x0e3\f4 1f3  don't despair; will make this much clearer in a moment. But first notice how it works:l4798d4269x0e3j\f8 1f0 31i4I  In processing (INCREMENTX), we run the procedure associated with INCREMENT, giving it as argument the full structure (remember, these are structural macros) (INCREMENTX).l4798d4269x0e3j\f8 1f0 15f3 10f7 1f3 2f0 39f3 9f0 33i9I41f3 10f7 1f3 2f0 1f8  The procedure is just as if it were defined using:l4798d4269x0e3j\f8 1f0 51f8 1 (lambda [call] (pcons '+ (rcons '1 (pargs call))))l7338d1760x0e3\f4 1f3 So, we have the equivalent of:l4798d4269x0e3j\f3 2f0 30f8 ((lambda [call] (pcons '+ (rcons '1 (pargs call)))) '(increment x))l7338d6809x0e3\f3 Which, through a series of normalization steps, would yield:l4798d4269x0e3j\f3 2f0 60f8 (pcons '+ (rcons '1 (pargs '(increment x))))l7338d6809x0e3\f3 (pcons '+ (rcons '1 '[x]))l7338d6809x0e3\f3 (pcons '+ '[1 x]))l7338d6809x0e3\f3 '(+ 1 x)l7338d6809x0e3\f3 This is just what we wanted.l4798d4269x0e3j\f3 2f0 28f8  But of course '(+ 1 x) isn't what (INCREMENT X) should normalize to; rather, it is the structure that we want normalized in place of (INCREMENT X). So the 3-LISP processor, as soon as it obtains the '(+ 1 X), then normalizes the result of running the structure_structure procedure.l4798d4269x0e3j\f8 1f0 15f3 8f0 12f3 13f0 86f3 13f0 10f7 6f0 38f3 8f0 18i35f4I1f0i9I1i9I  I.e., it then normalizes (+ 1 X), which (supposing X were bound to 3), would yield 4.l4798d4269x0e3j\f8 1f0 26f3 7f0 19f3 1f0 15f3 1f0 15f3 1f0 1f8  What happened to the quote? To be more precise, how did the quote appear on the (INCREMENT X) when it was used as the argument to the procedure associated with INCREMENT?l3528d2999x0e3j\f8 1f0 82f3 13f0 67f3 9f0  Answer: macro processing  structure to structure mappings like this  are inherently meta-structural; that's what you want.l4798d4269x0e3j\f8 1f0 76i27I  I.e., if you declarel4798d4269x0e3j\f8 1f0 CSLI' is an abbreviation for The Center for the Study of Language and Information'.l6068d5539x0e3j\f3 2f8i1f0 4f8 1f0 24f8 1f0 52f8 1f0I and then you sayl4798d4269x0e3j\f3 1f0 I went over to CSLI the other day.l6068d5539x0e3j\f3 2f0i34I Then a person, in reacting to your comment, has to shift levels, do the substitution of the longer name for the abbreviation (which requires mentioning the abbreviation, the longer name, and in general the sentence as a whole), and then shifts back down again to "use" the expanded sentence.l4798d4269x0e3j\f3 1f0 141i10I  Note, in other words, that there is a shift-up and then a shift-down, all very smoothly integrated into what is going on.l4798d4269x0e3j\f8 1f0  Similar shift of levels in 3-LISP in dealing with macros.l4798d4269x0e3j\f8 1f0 28f7 6f0  Go back to the definition of INCREMENT:l3528d2999x0e3j\f8 1f0 30f3 9f0 1 (define INCREMENT (mlambda [call] (pcons '+ (rcons '1 (pargs call)))))l6068d1760x0e3\f4 1f3  A more interesting example. Want to define an IF* then enables us to use explicit "then" and "else". I.e., would like to be able to write:l4798d4269x0e3j\f8 1f0 48f3 3f0 1 (if* (= 1 2) then (+ 10 (factorial ... )) else [( ... )])l6068d1760x0e3\f4 1f3 43f7 3f3 14f7 6f3  Straighforward enough:l4798d4269x0e3j\f8 1f0 1 (define IF* (mlambda [call] (pcons 'if (rcons (first (pargs call)) (third (pargs call)) (fifth (pargs call))))))l6068d1760x0e3\f4 1f3  Perhaps clearer:l4798d4269x0e3j\f8 1f0 1 (define IF* (mlambda [call] (let [[premise (first (pargs call))] [c1 (third (pargs call))] [c2 (fifth (pargs call))]] (pcons 'if (rcons premise c1 c2))))))l6068d1760x0e3\f4 1f3  We would then write (using W>' to mean "expands into"):l4798d4269x0e3j\f8 1f0 28f8 1f4 1f3 1f8 1f0 25f8 1 (if* e1 then e2 else e3) W> (if e1 e2 e3)l6068d1760x0e3\f4 1f3 8i2I6i2I6i2I4f4 1f3 9i8I  For example:l4798d4269x0e3j\f8 1f0 13f8 1 1> (define CAREFUL-DIVISION (lambda [dividend divisor] (if* (= divisor 0) then "can't divide by zero" else (/ dividend divisor)))) 1= 'careful-division 1> (careful-division 12 3) 1= 4 1> (careful-division 12 0) 1= "can't divide by zero"l6068d1760x0e3\f4 1f3  Perhaps we should do some error checking:l4798d4269x0e3j\f8 1f0 1 (define IF* (mlambda [call] (let [[premise (first (pargs call))] [noise-1 (second (pargs call))] [c1 (third (pargs call))] [noise-2 (fourth (pargs call))] [c2 (fifth (pargs call))]] (if (and (= noise-1 'then) (= noise-1 'else)) (pcons 'if (rcons premise c1 c2)) (error "Malformed IF*" call)))))l6068d1760x0e3\f4 1f3  Note that this extension to the language  using keywords in the midst of expressions  is a real wrench to the basic 3-LISP style; probably not the greatest macro to define, but it is simple.l4798d4269x0e3j\f8 1f0 119f7 6f0 68f8  Can simplify it even more:l3528d2999x0e3j\f8 1f0 1 (define ARG (lambda [n pair] (nth n (pargs pair))))l6068d1760x0e3\f4 1f3  enables:l4798d4269x0e3j\f8 1f0 1 (define IF* (mlambda [call] (pcons 'if (rcons (arg 1 call) (arg 3 call) (arg 5 call)))))l6068d1760x0e3\f4 1f3  But even this is pretty painful. What we would really like are something like Quine's corner quotes:l3528d2999x0e3j\f8 1f0 1 (define IF* (mlambda [call] '(if (arg 1 call) (arg 3 call) (arg 5 call))))l6068d1760x0e3\f4 1f3 45i12I1i25I  where the italicized structures are not meant to be quoted themselves, but rather are taken as naming structures that are constituents of the overall quoted structure,l4798d4269x0e3j\f8 1f0  I.e., where the italicized structures are somehow meta-structural comments on the code.l4798d4269x0e3j\f8 1f0 51i15I  In fact, can do this:l4798d4269x0e3j\f8 1f0  extend 3-LISP notation to include a comma. Basic idea is that a comma, before a notation within the scope of a single quote mark (i.e., within a handle-notation), means that the immediately following structure is not part of the structure being quoted, but rather is a structure that designates the part of the structure to be quoted.l6068d5539x0e3j\f8 1f0 8f7 6f0 272i10I  I.e.,:l6068d5539x0e3j\f8 1f0 1 (define IF* (mlambda [call] '(if ,(arg 1 call) ,(arg 3 call) ,(arg 5 call))))l6068d1760x0e3\f4 1f3  This works fine.l6068d5539x0e3j\f8 1f0  Indeed, macro definition would be pretty horendous if it weren't for this facility.l6068d5539x0e3j\f8 1f0  Notational quotation principle (maual page 9):l4798d4269x0e3j\f8 2f0i30I  A notational expression E1 preceded by a single quote mark will notate a structure S1 that designates a structure S2 that would be notated by E1, with the exception that those fragments of S2 that would have been notated by portions of E1 that are preceded by a comma will be designated by the structures that those portions notate, rather than notated by them directly.l6068d5539x0e3j\f8 1f0 25f7 1f1o253 1f0o0 57f7 1f1o253 1f0o0 29f7 1f1o253 1f0o0 26f7 1f1o253 1f0o0 45f7 1f1o253 1f0o0 45f7 1f1o253 1f0o0  What structure these extended notations notate is complex, but you by and large want to ignore that. For example, the expressionl4798d4269x0e3j\f8 1f0  '(/ ,x (if (= ,y 0) 1 ,y)) 'l7338d6809x0e3k40\f3 1f8 1f3 54f8 1f3 notates the structurel4798d4269x0e3j\f3 1f0 (pcons '/ (rcons x (pcons 'if (rcons (pcons '= (rcons y '0)) '1 y))))l7338d6809x0e3\f3 which you wouldn't want to have to type too often.l4798d4269x0e3j\f3 1f0  Some more examples:l4798d4269x0e3j\f8 1f0 1 1> (set X '(= 2 3)) 1= '(= 2 3)l6068d1760x0e3\f4 1f3 1> '(if X A B) 1= '(if X A B)l6068d5539x0e3\f3 1> '(if ,X A B) 1= '(if (+ 2 3) A B)l6068d5539x0e3\f3  Note that the time at which the comma'ed portions are processed, to determine the designation (i.e., when they are used) is not at the time that the notation was internalized, but rather at the time that the internalized structure is itself used.l4798d4269x0e3j\f8 2f0 115i4I127f8  Note the following definition of OBJECT we were using last time:l4798d4269x0e3j\f8 1f0 34f3 6f0 (define OBJECT (letrec [[define-message (lambda [name] '(define ,name (lambda args (((first args) ,^name) . (rest args)))))]] (mlambda [call] (letseq [[state-vars (arg 1 call)] [inited-vars (arg 2 call)] [pairs (tail 2 (pargs call))] [fun-names (map (lambda [pair] (acons)) pairs)]] '(begin ,(map (lambda [pair] (define-message (first pair))) pairs) (lambda ,state-vars (let ,inited-vars (letrec ,(map (lambda [pair fun-name] '[,fun-name ,(second pair)]) pairs fun-names) (lambda [message] (cond . ,(map (lambda [pair fun-name] '[(= message ,^(first pair)) ,fun-name]) pairs fun-names)))))))))))l6068d5539x0e3\f3 1132f0 which converts structures of the form:l4798d4269x0e3j\f3 1f0 (object [ ... ] [[ ] ... [ ]] [ ] [ ] ... [ ])l6068d5539x0e3\f3 into:l4798d4269x0e3j\f3 1f0 (begin [(define-message ) (define-message ) ... (define-message )] (lambda [init-var-1 ... init-var-k] (let [[ ] ... [ ]] (letrec [ ] ... [ ]] (lambda [message] (cond [(= message ') ] [(= message ') ] ... [(= message ') ]))))))l6068d5539x0e3k140\f3  For example:l4798d4269x0e3j\f8 1f0 1 (object [balance] [] [WITHDRAW (lambda [amount] (if (< balance amount) (error "Insufficient funds") (begin (set balance (- balance amount)) balance)))] [DEPOSIT (lambda [amount] (begin (set balance (+ balance amount)) balance))])l6068d1760x0e3\f4 1f3 would be converted into:l4798d4269x0e3j\f3 1f0 1 (begin [(define-message WITHDRAW) (define-message DEPOSIT)] (lambda [balance] (let [] (letrec [[{atom 1} (lambda [amount] (if (< balance amount) (error "Insufficient funds") (begin (set balance (- balance amount)) balance)))] [{atom 2} (lambda [amount] (begin (set balance (+ balance amount)) balance))]] (lambda [message] (cond [(= message 'withdraw) {atom 1}] [(= message 'deposit) {atom 2}]))))))z20355l6068d1760x0e3\f4 1f3 D. Meta-Circular Processorsl3528d2999e15jk40\b28B  In lecture 5, we presented the following description of how the 3-LISP processor worked (it was a function of structures and environments):l3528d2999x0e10j\f8 1f0 65f7 6f0 1  If s1 is in normal-form, then s1.l4798d1764x0e3\f4 1f3 5f7 1f8 1f0 4b1f1o253 1f0o0B25b1f1o253 1f0o0B  If s1 is an atom, then the binding of s1 in e1.l4798d4269e2jk40\f8 1f0 4b1f1o253 1f0o0B33b1f1o253 1f0o0B4b1f1o253 1f0o0B  If s1 is a rail, then the rail of the same length consisting of the results of normalizing (in e1) each of the elements of s1.l4798d4269e2jk40\f8 1f0 4b1f1o253 1f0o0B90b1f1o253 1f0o0B26b1f1o253 1f0o0B  If s1 is a pair, then:l4798d4269e2jk40\f8 1f0 4b1f1o253 1f0o0B  Let proc1 be the result of normalizing the PPROC part of s1.l6068d5539e2jk40\f8 1f0 5b4f1o253 1f0o0B34f7 5f0 9b1f1o253 1f0o0B  If proc1 is simple, then:l6068d5539e2jk40\f8 1f0 4b4f1o253 1f0o0B  let args1 be the result of normalizing the PARGS part of s1.l7338d6809e2jk40\f8 1f0 5b4f1o253 1f0o0B34f7 5f0 9b1f1o253 1f0o0B  If proc1 is primitive, then just go and do the primitive operations to args1, returning the result.l7338d6809e2jk40\f8 1f0 4b4f1o253 1f0o0B63b4f1o253 1f0o0B  Otherwise, normalize the body of proc1, in an environment that results from:l7338d6809e2jk40\f8 1f0 34b4f1o253 1f0o0B  extending the environment represented inside proc1 by:l8608d8079e2jk40\f8 1f0 46b4f1o253 1f0o0B  binding the atoms in the pattern encoded inside proc1 to args1.l8608d8079e2jk40\f8 1f0 49b4f1o253 1f0o0B4b4f1o253 1f0o0B Otherwise (i.e., if it is special):l6068d5539e2jk40\f3 1f0 26i7I  If proc1 is IF0, then normalise the first element of the PARGS part of s1 in e1. Then:l7338d6809e2jk40\f8 1f0 4b4f1o253 1f0o0B4f3b2f1o253 1f0o0B42f7 5f0  If it returns $TRUE, normalise the second element of the PARGS part of s1 in e1.l8608d8079e2jk40\f8 1f0 15f3 5f0 38f7 5f0 9b1f1o253 1f0o0B4b1f1o253 1f0o0B  If it returns $FALSE, then normalise the third element of the PARGS part of s1 in e1.l8608d8079e2jk40\f8 1f0 15f3 6f0 42f7 5f0 9b1f1o253 1f0o0B4b1f1o253 1f0o0B  If proc1 is LAMBDA0, then construct a closure comprising three things:l7338d6809e2jk40\f8 1f0 4b4f1o253 1f0o0B4f3b6f1o253 1f0o0B  a pattern (the first element of the PARGS part of s1);l8608d8079e2jk40\f8 1f0 37f7 5f0 9b1f1o253 1f0o0B  a body (the second element of the PARGS part of s1);l8608d8079e2jk40\f8 1f0 35f7 5f0 9b1f1o253 1f0o0B  a representation of e1.l8608d8079e2jk40\f8 1f0 21b1f1o253 1f0o0B  ... other special cases ...l7338d6809e2jk40\f8 1f0  An obvious idea:l3528d2999x0e3j\f8 1f0  This looks just like a procedure to compute the Y function. And we have been defining procedures for weeks. Couldn't we define a procedure that implements this algorithm?l4798d4269x0e3j\f8 1f0 49f2 1f0  Answer is clearly yes.l4798d4269x0e3j\f8 1f0  Such procedures are typically called meta-circular interpreters; since we are using the word processor instead of interpreter, we will call them meta-circular processors.l4798d4269x0e3j\f8 1f0 38i26I30i9I12i11I20b24B  Would expect such things as:l4798d4269x0e3j\f8 1f0 1 1> (normalize '(+ 1 2) global) 1= '3 1> (normalize '[2 3 4] global) 1= '[2 3 4] 1> (set x 3) 1= 3 1> '[1 2 x] 1= '[1 2 x] 1> (normalize '[1 2 x] global) 1= '[1 2 3] 1> (let [[x '4]] (normalize x global)) 1= '4 1> (let [[x '4]] (normalize '[1 2 x] global)) 1= '[1 2 3] 1> (let [[x '4]] (normalize '[1 2 ,x] global)) 1= '[1 2 4]l6068d1760x0e3\f4 1f3  Start out:l4798d4269x0e3j\f8 1f0 (define NORMALIZE (lambda [struc env] (cond [(normal struc) struc] [(atom struc) (binding struc env)] [(rail struc) (normalize-rail struc env)] [(pair struc) (reduce (pproc struc) (pargs struc) env)])))z18344l4800x2e4k200(0,3328)(1,3680)(2,4032)(3,4384)(4,4704)(5,5056)(6,5408)(7,5760)(8,6080)(9,6432)(10,6784)(11,7136)(12,7488)(13,7808)(14,10936)\f3 8b9B191f7 1f3 6f7 1f3 6f7 1f3 (define REDUCE (lambda [proc args env] (let [[proc-nf (normalize proc env)]] (dispatch (closure-type proc-nf) [simple (let [[args-nf (normalize args env)]] (if (primitive proc-nf) (reduce-primitive-simple proc-nf args-nf) (expand-closure proc-nf args-nf)))] [special (if (primitive proc-nf) (reduce-primitive-special (extract-simple-closure proc-nf) ^args env) (expand-closure proc-nf ^args))] [macro (normalize ^(expand-closure (extract-simple-closure proc-nf) ^args) env))]))))z20108l4800x2e4k20\f3 8b6B635f4 1f3 (define NORMALIZE-RAIL (lambda [rail env] (if (empty rail) (rcons) (cons (normalize (1st rail) env) (normalize-rail (rest rail) env)))))z18344l4800x2e4k20\f3 8b14B (define EXPAND-CLOSURE (lambda [proc-nf args-nf] (normalize (body proc-nf) (bind (pattern proc-nf) args-nf (environment proc-nf)))))z18344l4800x2e4k20\f3 8b14B (define READ-NORMALIZE-PRINT (lambda [env stream] (begin (prompt&reply (normalise (prompt&read stream) env) stream) (read-normalize-print env stream))))z18344l4800x2e8k20\f3 8b20B A Non-Continuation-Passing Meta-circular Processorz18344x3e9ck40(635)\i z18344x3jk40\f8b43f0  Requires lots of new things:l3528d2999x0e3j(0,3528)(1,4798)(2,6068)(3,7338)(4,8608)(5,9878)(6,11148)(7,12418)(8,65535)(9,65535)(10,65535)(11,65535)(12,65535)(13,65535)(14,65535)\f8 1f0  Structures that designate environments, plus associated operations: BINDING, BIND, etc.l4798d4269x0e3j\f8 1f0 69f3 7f0 2f3 4f0  Operations on closures: BODY, CLOSURE-ENVIRONMENT, PATTERN, CLOSURE-TYPEl4798d4269x0e3j\f8 1f0 25f3 4f0 2f3 19f0 2f3 7f0 2f3 12f0  A closure construction procedure: CCONSl4798d4269x0e3j\f8 1f0 35f3 5f0  DISPATCHl4798d4269x0e3j\f8 1f0 1f3 8f0  NORMAL  a predicate true of normal-form structures.l4798d4269x0e3j\f8 1f0 1f3 6f0 1f8 1f0  Will look at these next time.l3528d2999x0e3j\f8 1f0