Matthew Flatt
ICFP 2002
Sam Tobin-Hochstadt
Papers �e Love NYC
Composable & Compilable Macros
You want it when?
Slide 2
Slide 2 text
Prehistory
• Scheme
No standard module system
Implementations used Common Lisp approach
• Macros
Hygenic macros 15 years old
Still considered esoteric
• PLT Scheme
Mostly designed for teaching
IDE with multiple language levels
Slide 3
Slide 3 text
Composable and Compilable Macros
Matthew Flatt
University of Utah
Slide 4
Slide 4 text
A Scheme Programmer...
Slide 5
Slide 5 text
... Programming in Scheme
Slide 6
Slide 6 text
... in Macro-Extended Scheme!
Slide 7
Slide 7 text
... Trying to Use a Compiler
Slide 8
Slide 8 text
... Accomodating the Compiler
Slide 9
Slide 9 text
... Trying a Different Compiler
Slide 10
Slide 10 text
... Trying a Complex Library
Slide 11
Slide 11 text
The Trouble with Scripting the Compiler
(load "u.scm")
(eval-when
(compile load)
(load "m.scm"))
(load "a.scm")
(load "b.scm")
...
m
(load "ma.scm")
(load "mb.scm")
a
b
u
ma
mb
= load effect
Slide 12
Slide 12 text
The Trouble with Scripting the Compiler
(load "u.scm")
(eval-when
(compile load)
(load "m.scm"))
(load "a.scm")
(load "b.scm")
...
m
(load "ma.scm")
(load "mb.scm")
a
b
u
ma
mb
= dependency
Slide 13
Slide 13 text
The Trouble with Scripting the Compiler
(load "u.scm")
(eval-when
(compile load)
(load "m.scm"))
(load "a.scm")
(load "b.scm")
...
m
(load "ma.scm")
(load "mb.scm")
a
b
u
ma
mb
Slide 14
Slide 14 text
The Trouble with Scripting the Compiler
(load "u.scm")
(eval-when
(compile load)
(load "m.scm"))
(load "a.scm")
(load "b.scm")
...
m
(load "ma.scm")
(load "mb.scm")
a
b
u
ma
mb
never loaded
in compile mode
Slide 15
Slide 15 text
The Trouble with Scripting the Compiler
(load "u.scm")
(eval-when
(compile load)
(load "m.scm"))
(load "a.scm")
(load "b.scm")
...
(load "u.scm")
(load "ma.scm")
(load "mb.scm")
a
b
u
ma
mb
Slide 16
Slide 16 text
The Trouble with Scripting the Compiler
(load "u.scm")
(eval-when
(compile load)
(load "m.scm"))
(load "a.scm")
(load "b.scm")
...
(load "u.scm")
(load "ma.scm")
(load "mb.scm")
a
b
u
ma
mb
loaded twice
in interactive mode
Slide 17
Slide 17 text
Problem
Solution
• Declarative
• Consistent success/failure in all compilation
modes
• Supports
lexically scoped macros
macro-defining macros
Example
Experience
Slide 18
Slide 18 text
Modules and Macros
(module a
(define-syntax m ...)
(define f ...)
...)
Slide 19
Slide 19 text
Modules and Macros
= run-time expressions
(module a
(define-syntax m ...)
(define f ...
...)
...
...)
Slide 20
Slide 20 text
Modules and Macros
= compile-time expressions
(module a
(define-syntax m ...
...)
(define f ...
...)
...
...)
Slide 21
Slide 21 text
Modules and Macros
#' in escapes back to
(module a
(define-syntax m ...
...)
(define f ...
...)
...
...)
#'(f ...)
(f ...)
Slide 22
Slide 22 text
Modules and Macros
(module a
(define-syntax m ...
...)
(define f ...
...)
...
...)
(module b
(require "a.scm")
(define-syntax n ...)
(define g ...)
...)
#'(f ...)
(f ...)
Slide 23
Slide 23 text
Modules and Macros
(module a
(define-syntax m ...
...)
(define f ...
...)
...
...)
(module b
(require "a.scm")
(define-syntax n ...)
(define g ...
...)
...
...)
#'(f ...)
(f ...)
Slide 24
Slide 24 text
Modules and Macros
(module a
(define-syntax m ...
...)
(define f ...
...)
...
...)
(module b
(require "a.scm")
(define-syntax n ...
...)
(define g ...
...)
...
...)
#'(f ...)
(f ...)
Slide 25
Slide 25 text
Modules and Macros
(module u
(define fold ...)
...)
(module a
(define-syntax m ...
...)
(define f ...
...)
...
...)
(module b
(require "a.scm")
(require-for-syntax "u.scm")
(define-syntax n ...
...)
(define g ...
...)
...
...)
#'(f ...)
(f ...)
Slide 26
Slide 26 text
Modules and Macros
(module u
(define fold ...)
...)
(module a
(require "u.scm")
(define-syntax m ...
...)
(define f ...
...)
...
...)
(module b
(require "a.scm")
(require-for-syntax "u.scm")
(define-syntax n ...
...)
(define g ...
...)
...
...)
Slide 27
Slide 27 text
Modules and Macros
(module u
(define fold ...)
...)
(module u
(define fold ...)
...)
(module a
(require "u.scm")
(define-syntax m ...
...)
(define f ...
...)
...
...)
(module b
(require "a.scm")
(require-for-syntax "u.scm")
(define-syntax n ...
...)
(define g ...
...)
...
...)
different instance
for each phase
Slide 28
Slide 28 text
Problem
Solution
Example
• Record matching with static checks
Experience
Slide 29
Slide 29 text
Records and Matching
(define-record zebra (weight stripes))
Slide 30
Slide 30 text
Records and Matching
(define-record zebra (weight stripes))
(zebra 500 24) ; = a zebra instance
Slide 31
Slide 31 text
Records and Matching
(define-record zebra (weight stripes))
(zebra 500 24) ; = a zebra instance
(define-record lizard (weight length color))
(lizard 2 5 'green) ; = a lizard instance
Slide 32
Slide 32 text
Records and Matching
(define-record zebra (weight stripes))
(zebra 500 24) ; = a zebra instance
(define-record lizard (weight length color))
(lizard 2 5 'green) ; = a lizard instance
(record-switch ...
((zebra w s) ...)
((lizard w l c) ...))
Slide 33
Slide 33 text
Records and Matching
(define-record zebra (weight stripes))
(zebra 500 24) ; = a zebra instance
(define-record lizard (weight length color))
(lizard 2 5 'green) ; = a lizard instance
(define (animal-weight a)
(record-switch a
((zebra w s) w)
((lizard w l c) w)))
(animal-weight (zebra 500 24)) ; = 500
(animal-weight (lizard 2 5 'green)) ; = 2
Slide 34
Slide 34 text
Records and Matching
(define-record zebra (weight stripes))
(zebra 500 24) ; = a zebra instance
(define-record lizard (weight length color))
(lizard 2 5 'green) ; = a lizard instance
(define (animal-weight a)
(record-switch a
((zebra w s c) w) syntax error
((lizard w l c) w)))
Slide 35
Slide 35 text
Records and Matching
(define-record zebra (weight stripes))
(zebra 500 24) ; = a zebra instance
(define-record lizard (weight length color))
(lizard 2 5 'green) ; = a lizard instance
(define (animal-weight a)
(record-switch a
((zebra w s c) w) syntax error
((lizard w l c) w)))
compile-time communication
across module boundaries
Slide 36
Slide 36 text
Implementing Records
(module record
(define-syntax define-record
...)
(define-syntax record-switch
...))
Slide 37
Slide 37 text
Implementing Records
(module record
(define-syntax define-record
...)
(define-syntax record-switch
...))
(module zoo
(require "record.scm")
(define-record zebra (wgt sc))
(record-switch ...
((zebra w s) ...))
Slide 38
Slide 38 text
Implementing Records
(module record
(define-syntax define-record
...#'(define name (mkrec ...))...)
(define-syntax record-switch
...#'(is-a name ...) ...))
(module zoo
(require "record.scm")
(define-record zebra (wgt sc))
(record-switch ...
((zebra w s) ...))
Slide 39
Slide 39 text
Implementing Records
(module record
(define-syntax define-record
...#'(define name (mkrec ...))...)
(define-syntax record-switch
...#'(is-a name ...) ...))
(module zoo
(require "record.scm")
(define-record zebra (wgt sc))
(record-switch ...
((zebra w s) ...))
expands to
(define zebra (mkrec ...))
Slide 40
Slide 40 text
Implementing Records
(module record
(define-syntax define-record
...#'(define name (mkrec ...))...)
(define-syntax record-switch
...#'(is-a name ...) ...))
(module zoo
(require "record.scm")
(define-record zebra (wgt sc))
(record-switch ...
((zebra w s) ...))
expands to
(define zebra (mkrec ...))
expands to
(is-a zebra ...)
Slide 41
Slide 41 text
Implementing Records
(module record
(require "rt.scm")
(define-syntax define-record
...#'(define name (mkrec
mkrec ...))...)
(define-syntax record-switch
...#'(is-a
is-a name ...) ...))
(module zoo
(require "record.scm")
(define-record zebra (wgt sc))
(record-switch ...
((zebra w s) ...))
(module rt
(define mkrec ...)
(define is-a ...))
expands to
(define zebra (mkrec
mkrec ...))
expands to
(is-a
is-a zebra ...)
Implementing Records
(module record
(require "rt.scm")
(require-for-syntax "ct.scm")
(define-syntax define-record
...#'(for-syntax ...table
table...)...)
(define-syntax record-switch
...))
(module zoo
(require "record.scm")
(define-record zebra (wgt sc))
(record-switch ...
((zebra w s) ...))
(module rt
(define mkrec ...)
(define is-a ...))
(module ct
(define table ...)
...)
(module client
(require "zoo.scm")
(record-switch ...
((zebra w s) ...)))
now expands to
(for-syntax ...table
table...)
(define zebra (mkrec ...))
finds zebra
in table
Slide 52
Slide 52 text
Problem
Solution
Example
Experience
• The many languages & compilers of PLT Scheme
Slide 53
Slide 53 text
PLT Scheme
Slide 54
Slide 54 text
PLT Scheme
DrScheme supports multiple
languages that share libraries
Slide 55
Slide 55 text
PLT Scheme
Slide 56
Slide 56 text
PLT Scheme
One compilation mode
Slide 57
Slide 57 text
PLT Scheme
Another
compilation mode
Slide 58
Slide 58 text
PLT Scheme
Yet another
compilation mode
Slide 59
Slide 59 text
PLT Scheme
Slide 60
Slide 60 text
�hat happened after
• Modules
Became the basis for Scheme standards
Influenced other module systems
• Macros
syntax-parse, more phases, debugging
Tons of features
• Languages
Typed Racket, datalog, Scribble