Advanced macros and their implementation Matthew Might University - - PowerPoint PPT Presentation

advanced macros and their implementation
SMART_READER_LITE
LIVE PREVIEW

Advanced macros and their implementation Matthew Might University - - PowerPoint PPT Presentation

Advanced macros and their implementation Matthew Might University of Utah matt.might.net Agenda Syntax-rules Explicit-renaming Implementation Why hygiene is good Two kinds of capture problem Expansion captured by context


slide-1
SLIDE 1

Advanced macros and their implementation

Matthew Might University of Utah matt.might.net

slide-2
SLIDE 2

Agenda

  • Syntax-rules
  • Explicit-renaming
  • Implementation
slide-3
SLIDE 3

Why hygiene is good

  • Two kinds of capture problem
  • Expansion captured by context
  • Context captured by expansion
slide-4
SLIDE 4

Context captures

(let ((v 3)) (+ v 1)) => ((lambda (v) (+ v 1)) 3)

slide-5
SLIDE 5

Context captures

(let ((v 3)) (+ v 1)) => ((lambda (v) (+ v 1)) 3) (lambda (lambda) (let ((v 3)) (+ v 1)))

slide-6
SLIDE 6

Expansion captures

(or #f $tmp) => (let (($tmp #f)) (if $tmp $tmp $tmp))

slide-7
SLIDE 7

Why hygiene is bad

Sometimes you want capture.

slide-8
SLIDE 8

Example

(loop ... (exit) ...)

slide-9
SLIDE 9

Example

(let ((else #f)) (cond (else (begin (display "didn't get here!") (newline))))) (cond (else (begin (display "but got here!") (newline))))

slide-10
SLIDE 10

Syntax-rules

slide-11
SLIDE 11

Syntax-rules

  • High-level pattern language
  • Auto-hygienic -- no capture!
slide-12
SLIDE 12

Syntax-rules

(define-syntax name (syntax-rules (keyword ...) ((_ pat ...) template) ...))

slide-13
SLIDE 13

Patterns

<pattern> ::= <name> | <constant> | (<pattern> ...) | (<pattern> <pattern> ... . <pattern>) | (<pattern> ... <pattern> <ellipsis>)

slide-14
SLIDE 14

Templates

<template> ::= <name> | <constant> | (<element> ...) | (<element> <element> ... . <template>) <element> ::= <template> | <template> <ellipsis>

slide-15
SLIDE 15

Example: Records/Structs

slide-16
SLIDE 16

Low-level mixed hygiene: Explicit renaming

slide-17
SLIDE 17

Explicit-renaming

(define-syntax name (explicit-renamer (lambda (exp rename compare) ...)))

slide-18
SLIDE 18

Meaning

  • exp -- the expression to transform
  • rename -- hygienic renaming procedure
  • compare -- hygienic symbol comparison
slide-19
SLIDE 19

rename

  • Takes a name, yields fresh name
  • Behaves like a pure function (mostly)
slide-20
SLIDE 20

compare

Takes two names, and yields true iff both names have the same meaning in the environment in which the output of the macro is expanded. Purpose: Checks for macro-defined keywords.

slide-21
SLIDE 21

Names (or identifiers)

  • A symbol is a name, but
  • there are non-symbol names
  • generated during expansion.
slide-22
SLIDE 22

Example

(rename ‘foo) = [foo 17]

slide-23
SLIDE 23

Example

(rename ‘[foo 17]) = [foo 21]

slide-24
SLIDE 24

Example

(quote [foo 17]) = (quote foo)

slide-25
SLIDE 25

Example: let

(lambda (exp rename compare) (let ((vars (map car (cadr exp))) (inits (map cadr (cadr exp))) (body (cddr exp))) ‘((lambda ,vars ,@body) ,@inits)))

slide-26
SLIDE 26

Example: let

(lambda (exp rename compare) (let ((vars (map car (cadr exp))) (inits (map cadr (cadr exp))) (body (cddr exp))) ‘((,(rename ’lambda) ,vars ,@body) ,@inits)))

slide-27
SLIDE 27

Classic example

(define-syntax loop (transformer (lambda (x r c) (let ((body (cdr x))) ‘(,(r ’call-with-current-continuation) (,(r ’lambda) (exit) (,(r ’let) ,(r ’f) () ,@body (,(r ’f))))))))) Suppose a macro is implemented using , with the intent

slide-28
SLIDE 28

Example: cond

(lambda (exp rename compare) (let ((clauses (cdr exp))) (if (null? clauses) ‘(,(rename ’quote) unspecified) (let* ((first (car clauses)) (rest (cdr clauses)) (test (car first))) (cond ((and (identifier? test) (compare test (rename ’else))) ‘(,(rename ’begin) ,@(cdr first))) (else ‘(,(rename ’if) ,test (,(rename ’begin) ,@(cdr first)) (cond ,@rest))))))))

slide-29
SLIDE 29

Implementation

slide-30
SLIDE 30

Expansion

  • eval : exp env -> s-exp
  • expand : s-exp senv -> exp
slide-31
SLIDE 31

Environments

  • env = name -> s-exp
  • senv = name -> denotation
slide-32
SLIDE 32

Denotations

denotation = name + syntax-primitive + macro

slide-33
SLIDE 33

Syntax primitives

All binding forms, e.g., lambda and let-syntax.

slide-34
SLIDE 34

Mixed-hygiene macros

A mixed-hygiene macro is a transcriber.

slide-35
SLIDE 35

Transcribers

A transcriber takes a (1) syntactic form to rewrite; (2) a local syntactic environment; to produce: (1) an expanded form (2) an syntactic environment delta.

slide-36
SLIDE 36

Transcribers

(macro s-exp senv) = (s-exp’ Δsenv)

slide-37
SLIDE 37

Expansion core

; expand : s-exp senv -> exp (define (expand s-exp senv) (cond ((boolean? s-exp) s-exp) ((number? s-exp) s-exp) ((string? s-exp) s-exp) ((name? s-exp) (senv-lookup senv s-exp)) ((app? s-exp) (apply-denotation (expand (app->fun s-exp) senv) s-exp senv)) (else (error "unknown expression type: " s-exp))))

slide-38
SLIDE 38

Applying denotations

; apply-denotation : denotation app-exp senv -> senv (define (apply-denotation denotation app-exp senv) (cond ((syntax-primitive? denotation) ((syntax-primitive->expander denotation) app-exp senv)) ((syntax-transformer? denotation) (let* ((exp-senv (expand-transformer denotation app-exp senv)) ($exp (car exp-senv)) (senv-delta (cadr exp-senv))) (expand $exp (senv-divert senv senv-delta)))) (else (cons denotation (map (expand-with senv) (app->args app-exp))))))

slide-39
SLIDE 39

Syntax-rules by example

slide-40
SLIDE 40

Example: test macro

slide-41
SLIDE 41

Example: test macro

slide-42
SLIDE 42

Example: test macro

slide-43
SLIDE 43

Example: test macro

slide-44
SLIDE 44

Further reading

  • Kohlbecker et al. “Hygienic macro expansion.”
  • Kohlbecker et al. “Macro-by-example.”
  • Rees. “Implementing lexically scoped macros.”
  • Clinger & Rees. “Macros that work.”