Compiler Construction
Mayer Goldberg \ Ben-Gurion University Tuesday 10th December, 2019
Mayer Goldberg \ Ben-Gurion University Compiler Construction 1 / 111
Compiler Construction Compiler Construction 1 / 111 Mayer Goldberg - - PowerPoint PPT Presentation
Compiler Construction Compiler Construction 1 / 111 Mayer Goldberg \ Ben-Gurion University Tuesday 10 th December, 2019 Mayer Goldberg \ Ben-Gurion University Chapter 3 Roadmap Compiler Construction 2 / 111 Expressions in Scheme The
Mayer Goldberg \ Ben-Gurion University Compiler Construction 1 / 111
▶ Expressions in Scheme
▶ The expr datatype ▶ The Tag-Parser ▶ Macros & special forms ▶ Lexical hygiene Mayer Goldberg \ Ben-Gurion University Compiler Construction 2 / 111
▶ A parser for data, known as a reader ▶ A parser for code, known as a tag-parser
Mayer Goldberg \ Ben-Gurion University Compiler Construction 3 / 111
▶ Constants ▶ Variables ▶ if-Expressions ▶ or-Expressions ▶ Sequences ▶ Assignments ▶ Defjnitions ▶ Lambda-expressions of various kinds (more on that later) ▶ Applications
Mayer Goldberg \ Ben-Gurion University Compiler Construction 4 / 111
▶ All other forms (e.g., let, cond, etc) can be written in terms of
▶ The process of translating other forms (e.g., let-expressions)
▶ The Scheme programming language provides facilities for
▶ Users can invent new syntactic forms ▶ Describe their translation into pre-existing forms using Scheme
▶ The Scheme system uses the user-code to translate user-defjned
Mayer Goldberg \ Ben-Gurion University Compiler Construction 5 / 111
▶ Supporting many forms in the compiler will make the compiler
▶ Allowing the compiler to focus on optimizing a small number of
▶ Debugging macro-expanded code is very diffjcult
Mayer Goldberg \ Ben-Gurion University Compiler Construction 6 / 111
▶ On the one hand, the minimalist compiler can focus more on less ▶ On the other hand, the minimalist compiler knows less about
Mayer Goldberg \ Ben-Gurion University Compiler Construction 7 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 8 / 111
▶ The compiler should not be diffjcult to write ▶ The code should not be overly ineffjcient 😊
Mayer Goldberg \ Ben-Gurion University Compiler Construction 9 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 10 / 111
▶ In principle, applications and lambda-expressions are all you need ▶ Alternately, applications, and the following one, single constant
Mayer Goldberg \ Ben-Gurion University Compiler Construction 11 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 12 / 111
▶ Type: Const of sexpr ▶ The type-constructor Const is used both for self-evaluating and
Mayer Goldberg \ Ben-Gurion University Compiler Construction 13 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 14 / 111
▶ Type: Var of string ▶ Variables are literal symbols that are not reserved words
▶ The latest version of Scheme (R6RS) does not have many
▶ Not having reserved words makes the parser more complex ▶ We’re going to ignore this, and assume that words that are
▶ and, begin, cond, define, else, if, lambda, let, let*
▶ There are additional reserved words, but we’ll ignore those Mayer Goldberg \ Ben-Gurion University Compiler Construction 15 / 111
▶ Type: If of expr * expr * expr ▶ Scheme supports if-then variant without an else-clause
▶ These are used when the then-clause contains side-efgects ▶ The “missing”/implicit else-clause is defjned to be
▶ We shall support the if-then variant, and tacitly add the implicit
▶ This is your fjrst recursive case of the expr datatype: An expr
▶ Obviously, the tag-parser will have to be recursive! Mayer Goldberg \ Ben-Gurion University Compiler Construction 16 / 111
▶ Type: Seq of expr list ▶ There are two types of sequences:
▶ Explicit sequences (begin-expressions) ▶ Implicit sequences ▶ Body of lambda ▶ In the Ribs of cond ▶ In the body of let, let*, letrec ▶ Other syntactic forms we shall not support
▶ Both implicit & explicit sequences are encoded as single
▶ All expressions within a sequence are generally executed from
Mayer Goldberg \ Ben-Gurion University Compiler Construction 17 / 111
▶ The value of a sequence is generally the value of the last
▶ Sequences have to do with side-efgects: Expressions that have
▶ Continuation-handling forms, such as call/cc, afgect the
▶ We shall not consider call/cc in this course
▶ It is possible to macro-expand sequences
▶ We will learn the expansion later on ▶ The expansion results in impractically-ineffjcient code ▶ We support sequences directly for reasons of effjciency Mayer Goldberg \ Ben-Gurion University Compiler Construction 18 / 111
▶ Type: Set of expr * expr ▶ The AST node for set! (pronounced “set-bang”) expressions
Mayer Goldberg \ Ben-Gurion University Compiler Construction 19 / 111
▶ Type: Def of expr * expr ▶ The AST node for define-expressions ▶ Two syntaxes for define:
▶ (define ⟨var⟩ ⟨expr⟩) ▶ Example:
▶ (define (⟨var⟩ . ⟨arglist⟩) . (⟨expr⟩+)) ▶ This form is macro-expanded into
▶ Used to defjne functions without specifying the λ: This is
▶ Example: (define (square x) (* x x)) Mayer Goldberg \ Ben-Gurion University Compiler Construction 20 / 111
▶ Type: Or of expr list ▶ (or) = #f (by defjnition) ▶ (or ⟨expr⟩) = ⟨expr⟩ (#f is the unit element of or) ▶ The real work is done here:
▶ It is possible to macro-expand disjunctions
▶ We will learn the expansion later on ▶ The expansion results in impractically-ineffjcient code ▶ We support disjunctions directly for reasons of effjciency Mayer Goldberg \ Ben-Gurion University Compiler Construction 21 / 111
▶ Type: Applic of expr * (expr list) ▶ The AST node separates the expression in the procedure
▶ The tag-parser recurses over the procedure & the list of
Mayer Goldberg \ Ben-Gurion University Compiler Construction 22 / 111
▶ Types:
▶ LambdaSimple of string list * expr ▶ LambdaOpt of string list * string * expr
▶ Scheme has three lambda-forms, and we’re going to represent
Mayer Goldberg \ Ben-Gurion University Compiler Construction 23 / 111
▶ The general form of lambda-expressions is
Mayer Goldberg \ Ben-Gurion University Compiler Construction 24 / 111
▶ The general form of lambda-expressions is
▶ The fjrst n arguments are mandatory, and are assigned to v1
▶ The list of values of any additional arguments is going to be the
▶ If precisely n arguments are given, then the value of vs is going
▶ We represent lambda-expressions with optional arguments by
Mayer Goldberg \ Ben-Gurion University Compiler Construction 25 / 111
▶ The general form of lambda-expressions is
▶ The list of values of the arguments is going to be the value of
▶ If no arguments are given, then the value of vs is going to be
▶ We represent variadic lambda-expressions using the AST node
Mayer Goldberg \ Ben-Gurion University Compiler Construction 26 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 27 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 28 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 29 / 111
▶ Expressions in Scheme
▶ The Tag-Parser ▶ Macros & special forms ▶ Lexical hygiene Mayer Goldberg \ Ben-Gurion University Compiler Construction 30 / 111
▶ Not all valid sexprs are valid exprs ▶ Some sexprs need to be disambiguated before they can be
▶ Plenty of testing needs to be done to ensure that
Mayer Goldberg \ Ben-Gurion University Compiler Construction 31 / 111
SYMBOL * INTEGER 4 SYMBOL atan INTEGER 1 NIL PAIR CAR CDR PAIR CAR CDR NIL PAIR CAR CDR PAIR CAR CDR PAIR CAR CDR
VAR * INTEGER 4 CONST VALUE VAR atan INTEGER 1 CONST VALUE APPLIC PROC ARGS ARG0 APPLIC PROC ARGS ARG0 ARG1
Mayer Goldberg \ Ben-Gurion University Compiler Construction 32 / 111
▶ (lambda (x) . x) (the body is not a [proper] list of exprs) ▶ (quote . a) (not a proper list) ▶ (quote he said he understood unquote) (length does not
▶ (lambda (a b c a a b) (+ a b c)) (the param list contains
Mayer Goldberg \ Ben-Gurion University Compiler Construction 33 / 111
▶ A recursive function tag_parse : sexpr -> expr
▶ For the core forms (we shall deal with macro-expanded forms
▶ Check out the expr datatype so you know what you must
▶ For example, that argument-lists in lambda-expressions contain
Mayer Goldberg \ Ben-Gurion University Compiler Construction 34 / 111
▶ Expressions in Scheme
▶ Macros & special forms ▶ Lexical hygiene Mayer Goldberg \ Ben-Gurion University Compiler Construction 35 / 111
▶ Transformers on source-code
▶ They take source code, and rewrite it ▶ They operate on the concrete syntax
▶ Generally execute at compile time
▶ Some work on run-time macro-expansion has been done in the
▶ Used to provide shallow support for syntactic forms
▶ Macros are syntactic sugar or notational conveniences ▶ They are “expanded away”, and then they are gone ▶ Macros are not supported deep within the compiler ▶ The semantic analysis or code-generation stages of the compiler
Mayer Goldberg \ Ben-Gurion University Compiler Construction 36 / 111
▶ When you think of the word “home”, perhaps you think of:
▶ stability, security, safety ▶ family, relations ▶ mortgage
▶ All this is part of the meaning of “home” ▶ Meaning in the compiler has to do with the semantic analysis
▶ The meaning of “home” enriches anything you say and do that
Mayer Goldberg \ Ben-Gurion University Compiler Construction 37 / 111
▶ Suppose home for you is just shorthand for a location
▶ You could then translate the word “home” to USC
▶ This translation would take place early on, so that ▶ “going home” would mean going to a specifjc coordinate ▶ “longing for home” would mean longing to be at a specifjc
▶ Such sentences would carry none of the meaning, signifjcance,
▶ The word “home” would be disconnected from any meaning
▶ This would be insanity! Mayer Goldberg \ Ben-Gurion University Compiler Construction 38 / 111
▶ When you have a notion of “loop” in your language, the
▶ a code fragment that gets executed over and over ▶ termination conditions ▶ branch prediction information
▶ We can macro-expand a loop into a recursive function with all
▶ All intentions about the code (namely, its loop-like behaviour)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 39 / 111
▶ Some information can be reconstructed through analysis during
▶ Other information is lost
▶ For example, we might want our compiler to keep the index
▶ These would be simple to do when considering loops ▶ These would be diffjcult, and require a great deal of analysis
Mayer Goldberg \ Ben-Gurion University Compiler Construction 40 / 111
▶ We now consider some special forms in Scheme
▶ Some of these will be implemented in our compiler ▶ Some of these are of theoretical interest only ▶ We want to understand what special forms can be dispensed
▶ We don’t want our compiler to be overly ineffjcient Mayer Goldberg \ Ben-Gurion University Compiler Construction 41 / 111
▶ Some languages (such as Java or ocaml) are strict about
▶ Conjunctions, disjunctions, conditionals, etc. only take
▶ The distinction is beteen false and true ▶ Not false is exactly true:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 42 / 111
▶ Some languages (such as Java or ocaml) are strict about
▶ Conjudations, disjunctions, conditionals, etc. only take
▶ The distinction is beteen false and true ▶ Not false is exactly true:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 43 / 111
▶ Some languages (such as C or Scheme) are lenient about
▶ Conjudations, disjunctions, conditionals, etc. can take any
▶ The distinction is between false and not false ▶ Not false is not the same as true:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 44 / 111
▶ Some languages (such as C or Scheme) are lenient about
▶ Conjudations, disjunctions, conditionals, etc. can take any
▶ The distinction is between false and not false ▶ Not false is not the same as true:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 45 / 111
▶ Conjunctions are easily expanded into nested if-expressions:
▶ (and) = #t (by defjnition) ▶ (and ⟨expr⟩) = ⟨expr⟩ (#t is the unit element of and) ▶ (and ⟨expr1⟩ ⟨expr2⟩ · · · ⟨exprn⟩) =
▶ The assembly code generated for and-expansions is no difgerent
Mayer Goldberg \ Ben-Gurion University Compiler Construction 46 / 111
▶ The fjrst two clauses are similar to what we do with
▶ (or) = #f (by defjnition) ▶ (or ⟨expr⟩) = ⟨expr⟩ (because #f is the unit of or)
▶ For the third clause, you might consider something like:
▶ This macro-expansion is, of course, incorrect! (think why)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 47 / 111
▶ Take another look at (or ⟨expr1⟩ ⟨expr2⟩ · · · ⟨exprn⟩) =
▶ Suppose we implemented or-expressions in this way: What
▶ Scheme returns 2 Mayer Goldberg \ Ben-Gurion University Compiler Construction 48 / 111
▶ This is fjne, because or-expressions associate! ▶ What about this macro-expansion: (or ⟨expr1⟩ ⟨expr2⟩) =
▶ This macro-expansion is, of course, incorrect! (think why)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 49 / 111
▶ Take another look at (or ⟨expr1⟩ ⟨expr2⟩) =
▶ Suppose we implemented or-expressions in this way: What
▶ Scheme prints * once and returns #t
▶ We told you side-efgects were tricky! 😊
Mayer Goldberg \ Ben-Gurion University Compiler Construction 50 / 111
▶ What about the expansion: (or ⟨expr1⟩ ⟨expr2⟩) =
▶ This macro-expansion is, of course, incorrect! (think why)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 51 / 111
▶ Take another look at (or ⟨expr1⟩ ⟨expr2⟩) =
▶ Suppose we implemented or-expressions in this way: What
▶ Scheme returns ha-ha!
Mayer Goldberg \ Ben-Gurion University Compiler Construction 52 / 111
▶ Notice how the macro-expansion introduced a new let between
▶ This new let introduced a variable binding that just so
▶ This new variable binding contaminated the code: The value of
Mayer Goldberg \ Ben-Gurion University Compiler Construction 53 / 111
▶ Notice how the macro-expansion introduced a new let between
▶ This is known as a variable-name capture ▶ Macro-expansions that result in variable-name captures are said
Mayer Goldberg \ Ben-Gurion University Compiler Construction 54 / 111
▶ This is often impossible to accomplish without resorting to tricks ▶ This often requires tricky, circuitous, counter-intuitive
▶ This is the case with or ▶ This is why we support disjunctions directly as a core form in
Mayer Goldberg \ Ben-Gurion University Compiler Construction 55 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 56 / 111
▶ Two lambda-expressions, and hence the creation of two closures
▶ This is the same as allocating two objects in an OOPL
▶ Two applications
▶ To create/allocate 2n closures ▶ To evaluate 2n applications
Mayer Goldberg \ Ben-Gurion University Compiler Construction 57 / 111
▶ The general form: (begin ⟨expr1⟩ · · · ⟨exprn⟩) ▶ Sequences are associative, so we need only consider the binary
▶ How might we possibly expand it? How about
▶ This macro-expansion is, of course, incorrect! (think why)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 58 / 111
▶ Take another look at
▶ This expansion introduces the variable x
▶ Notice that ⟨expr2⟩ can access this variable! ▶ This means that this expansion is not hygienic!
▶ Suppose we implemented begin-expressions in this way: What
▶ Scheme returns 3 Mayer Goldberg \ Ben-Gurion University Compiler Construction 59 / 111
▶ We see that fjrst ⟨expr1⟩ evaluates, and then ⟨expr2⟩, so the
▶ No variables are introduced, so there’s no issue of lexical hygiene ▶ This expansion is actually correct, but bad! (think why)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 60 / 111
▶ Take another look at
▶ The text of ⟨expr2⟩ actually appears twice in the expanded
▶ This means that a begin with n + 1 expressions will expand to
▶ This is clearly not practical! Mayer Goldberg \ Ben-Gurion University Compiler Construction 61 / 111
▶ We see that (or ⟨expr1⟩ #t) evaluates fjrst, and that its
▶ So the and continues on to evaluate ⟨expr2⟩
▶ The ordering is correct!
▶ No variables are introduced so there’s no issue of lexical hygiene ▶ No expression is duplicated
Mayer Goldberg \ Ben-Gurion University Compiler Construction 62 / 111
▶ How about
▶ We see that fjrst (and ⟨expr1⟩ #f) evaluates, and then
▶ No variables are introduced, so there’s no issue of lexical hygiene
Mayer Goldberg \ Ben-Gurion University Compiler Construction 63 / 111
▶ We introduced two variables x & y:
▶ Neither ⟨expr1⟩ nor ⟨expr2⟩ can access these variables! ▶ The solution is hygienic!
▶ ⟨expr1⟩ evaluates in parallel with the creation of the closure
Mayer Goldberg \ Ben-Gurion University Compiler Construction 64 / 111
▶ Evaluating (lambda () ⟨expr2⟩) does not evaluate ⟨expr2⟩ ▶ ⟨expr2⟩ is evaluated only when the closure is applied!
Mayer Goldberg \ Ben-Gurion University Compiler Construction 65 / 111
▶ This expansion is actually more effjcient than the previous two
▶ and & or with more than one expression always involve a test
▶ Sequencing does not logically require tests or conditional jumps ▶ So this solution is less expensive Mayer Goldberg \ Ben-Gurion University Compiler Construction 66 / 111
▶ This expansion is actually more effjcient than the previous two
▶ It’s still pretty horrible: Two applications, and two closures
▶ Sequences of n + 1 expressions require 2n applications and the
Mayer Goldberg \ Ben-Gurion University Compiler Construction 67 / 111
▶ This is why we support sequences natively within our compiler
Mayer Goldberg \ Ben-Gurion University Compiler Construction 68 / 111
▶ The let-expression is a way of defjning any number of local
▶ Once the local variables have been initialized, they are accessible
▶ The syntax looks like this:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 69 / 111
▶ Local variables are parameters of lambda-expressions ▶ Expressions that can access local variables come from the bodies
▶ The parameters of lambda-expressions get their values when
▶ The values of the arguments are the initial values of the
Mayer Goldberg \ Ben-Gurion University Compiler Construction 70 / 111
▶ The expansion is hygienic (think why)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 71 / 111
▶ Recall that the ordering of let-bindings is undefjned, and that
▶ This follows from the fact that
▶ The asterisk in name of the let*-form is meant to suggest the
▶ A let*-expression denotes nested let-expressions. The
Mayer Goldberg \ Ben-Gurion University Compiler Construction 72 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 73 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 74 / 111
▶ A nested let-expression for every rib in the original
▶ This means
▶ One more closure created ▶ One application performed ▶ One closure garbage-collected
Mayer Goldberg \ Ben-Gurion University Compiler Construction 75 / 111
▶ The call is tail-call-optimized and replaced with a branch ▶ The allocation/creation of a new closure is avoided through a
▶ Rather than allocating new frames, the old frames are being
▶ So in fact, this code is optimized into simple assignments
Mayer Goldberg \ Ben-Gurion University Compiler Construction 76 / 111
▶ We can use let to defjne local variables ▶ The value of these variables can be anything really, including
▶ Here’s how one might defjne local procedures using let:
Mayer Goldberg \ Ben-Gurion University Compiler Construction 77 / 111
▶ If we were to try to defjne and use the factorial function using
Mayer Goldberg \ Ben-Gurion University Compiler Construction 78 / 111
▶ Notice the body of fact is not able to access the parameter
▶ The parameter fact is only accessible in the body of this
▶ The reference to fact within the text of the body of the
Mayer Goldberg \ Ben-Gurion University Compiler Construction 79 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 80 / 111
▶ Can you see why it works?
Mayer Goldberg \ Ben-Gurion University Compiler Construction 81 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 82 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 83 / 111
▶ The main problem with the expansion has to do with nested
▶ It is possible to use define to defjne a local function within a
▶ Several of such defjnitions may appear at the top of the body ▶ Several of such defjnitions may be grouped together within a
▶ All the nested define-expressions must appear at the top of
▶ It is a syntax error to have a nested define after a
Mayer Goldberg \ Ben-Gurion University Compiler Construction 84 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 85 / 111
▶ In fact, we shall not support nested define-expressions in our
▶ We still need to fjnd a macro-expansion for letrec that can live
Mayer Goldberg \ Ben-Gurion University Compiler Construction 86 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 87 / 111
▶ Notice that the body of the original letrec-expression is now
Mayer Goldberg \ Ben-Gurion University Compiler Construction 88 / 111
▶ The letrec form has to do with defjning locally-recursive
▶ Recursion forms a cornerstone for functional programming ▶ In both cases, the macro-expanded code contains assignments,
▶ Side-efgects are specifjcally excluded in pure functional
Mayer Goldberg \ Ben-Gurion University Compiler Construction 89 / 111
▶ The short answer is that yes, functional programming can
▶ To understand this answer, we will need to
▶ Study some fjxed-point theory ▶ Think harder about what recursion really means
▶ The full answer to this question is one of the most beautiful and
▶ For the time being, we move on to further topics that are
▶ We shall return to the topic in several weeks… Stay tuned!
Mayer Goldberg \ Ben-Gurion University Compiler Construction 90 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 91 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 92 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 93 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 94 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 95 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 96 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 97 / 111
▶ Quasiquote-expressions are expanded twice:
▶ Once in the reader, when the forms `⟨sexpr⟩, ,⟨sexpr⟩,
▶ And a second time when quasiquote-expressions are expanded
Mayer Goldberg \ Ben-Gurion University Compiler Construction 98 / 111
▶ Since R6RS, quasiquote-expressions can be nested, which
▶ We assume we have already received the form (quasiquote
Mayer Goldberg \ Ben-Gurion University Compiler Construction 99 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 100 / 111
▶ If A =(unquote-splicing ⟨sexpr⟩), then return (append
▶ If B =(unquote-splicing ⟨sexpr⟩), then return (cons A
▶ Otherwise, return (cons A B)
Mayer Goldberg \ Ben-Gurion University Compiler Construction 101 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 102 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 103 / 111
▶ The expansion is a trivial recursive procedure ▶ The expansion is hardly ever isn’t always the shortest ▶ The expansion can be made to compete with the best expanders,
Mayer Goldberg \ Ben-Gurion University Compiler Construction 104 / 111
▶ Optimizing for time: The expanded form should call fewer
▶ Optimizing for space: The expanded form should avoid, when
▶ Example: Consider `(a ,b c d e f) ▶ Naïve output: (cons 'a (cons b (cons 'c (cons 'd
▶ Optimized for time: (list 'a b 'c 'd 'e 'f) (save on
▶ Optimized for space: (cons 'a (cons b '(c d e f))) (save
Mayer Goldberg \ Ben-Gurion University Compiler Construction 105 / 111
▶ For macro-expanded forms
▶ Consult the list of special forms that need to be macro-expanded
▶ For example, expand_let, expand_cond, etc ▶ The macro-expanders should convert the concrete syntax of the
▶ You may still use expandable special forms in the expansion ▶ For example, expanding letrec may result in a let-expression,
Mayer Goldberg \ Ben-Gurion University Compiler Construction 106 / 111
▶ For macro-expanded forms (continued)
▶ For example, tag_parse(expand_let e) Mayer Goldberg \ Ben-Gurion University Compiler Construction 107 / 111
▶ Expressions in Scheme
▶ Lexical hygiene Mayer Goldberg \ Ben-Gurion University Compiler Construction 108 / 111
▶ Hygiene problems occur when variables that are introduced
▶ When user-code refers to such variables, this is always an error ▶ We refer to such an error variable-name captures
▶ We can avoid variable-name capture by
▶ Using gensym to generate an uninterned symbol ▶ By fjnding in the expansion a “safe” variable-name to use ▶ By changing the macro-expansion so that administrative
Mayer Goldberg \ Ben-Gurion University Compiler Construction 109 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 110 / 111
Mayer Goldberg \ Ben-Gurion University Compiler Construction 111 / 111