Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sam Tobin-Hochstadt on Composable and Compilable Macros

Sam Tobin-Hochstadt on Composable and Compilable Macros

"Composable and Compilable Macros" introduces the Racket module system, which addresses the following problem: When you have macros that run programs at compile-time, how does this interact with separate compilation and ahead-of-time compilation. The paper introduces "phases", which enable Racket to behave the same regardless of when and how you compile your program. It also introduces the idea of writing different modules in different languages, which is now used for systems like Typed Racket.

A few related papers:

- Syntactic Abstraction in Scheme, Dybvig Hieb & Bruggeman, Lisp andSymbolic Computation 1993

- Macros that Work Together, Flatt, Findler, Culpepper, & Darais, JFP 2012- Submodules in Racket, Flatt GPCE 2013

- Implicit phasing for R6RS libraries, Ghuloum & Dybvig, ICFP 2007

- Extending the scope of syntactic abstraction, Waddell & Dybvig, POPL 1999

Papers_We_Love

February 05, 2015
Tweet

More Decks by Papers_We_Love

Other Decks in Programming

Transcript

  1. Matthew Flatt ICFP 2002 Sam Tobin-Hochstadt Papers �e Love NYC

    Composable & Compilable Macros You want it when?
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. Problem Solution • Declarative • Consistent success/failure in all compilation

    modes • Supports lexically scoped macros macro-defining macros Example Experience
  10. Modules and Macros #' in escapes back to (module a

    (define-syntax m ... ...) (define f ... ...) ... ...) #'(f ...) (f ...)
  11. Modules and Macros (module a (define-syntax m ... ...) (define

    f ... ...) ... ...) (module b (require "a.scm") (define-syntax n ...) (define g ...) ...) #'(f ...) (f ...)
  12. Modules and Macros (module a (define-syntax m ... ...) (define

    f ... ...) ... ...) (module b (require "a.scm") (define-syntax n ...) (define g ... ...) ... ...) #'(f ...) (f ...)
  13. Modules and Macros (module a (define-syntax m ... ...) (define

    f ... ...) ... ...) (module b (require "a.scm") (define-syntax n ... ...) (define g ... ...) ... ...) #'(f ...) (f ...)
  14. 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 ...)
  15. 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 ... ...) ... ...)
  16. 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
  17. 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
  18. 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) ...))
  19. 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
  20. 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)))
  21. 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
  22. 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) ...))
  23. 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) ...))
  24. 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 ...))
  25. 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 ...)
  26. 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 ...)
  27. Implementing Records (module record (require "rt.scm") (define-syntax define-record ... table

    ...) (define-syntax record-switch ... table ...)) (module zoo (require "record.scm") (define-record zebra (wgt sc)) (record-switch ... ((zebra w s) ...)) (module rt (define mkrec ...) (define is-a ...))
  28. Implementing Records (module record (require "rt.scm") (require-for-syntax "ct.scm") (define-syntax define-record

    ... table table ...) (define-syntax record-switch ... table table ...)) (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 ...) ...)
  29. Implementing Records (module record (require "rt.scm") (require-for-syntax "ct.scm") (define-syntax define-record

    ... table table ...) (define-syntax record-switch ... table table ...)) (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 ...) ...) adds zebra to table while expanding
  30. Implementing Records (module record (require "rt.scm") (require-for-syntax "ct.scm") (define-syntax define-record

    ... table table ...) (define-syntax record-switch ... table table ...)) (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 ...) ...) adds zebra to table while expanding finds zebra in table while expanding
  31. Implementing Records (module record (require "rt.scm") (require-for-syntax "ct.scm") (define-syntax define-record

    ...) (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 ...) ...)
  32. Implementing Records (module record (require "rt.scm") (require-for-syntax "ct.scm") (define-syntax define-record

    ...) (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) ...)))
  33. Implementing Records (module record (require "rt.scm") (require-for-syntax "ct.scm") (define-syntax define-record

    ...) (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) ...))) cannot find zebra in table
  34. 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) ...)))
  35. 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 ...))
  36. 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
  37. �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