Upload
mitchell-wand
View
90
Download
0
Embed Size (px)
Citation preview
Static Guarantees for Macro
BindingsMitchell Wand
Presentation for Gnosys site visit
12/14/12
Why study macros?
macros are a facility for lightweight compilers
translate DSL into host language (Racket), then let Racket compiler work
easy interoperation with host language, etc.
most translation is on a per-s-expression basis
Racket macro system has features that permit interaction between macros, optimizations, fancier syntax, etc.
Want: static reasoning about
hygiene Does the expansion of a macro obey its
intended scoping rules?
Does my-let act like let?
◦ Is id0 bound in body?
(define-syntax my-let
(syntax-rules ()
[(_ ((id0 val0) (id val) ...) body)
((lambda (id ...) body)
val ...)]))Answer: No
Didn't Dybvig solve this in 1993?
No notion of "intended scoping rules"
Dybvig's algorithm works out binding relationships dynamically.
We want static guarantees.
Didn't the nominal logic guys
solve this? Nominal logic: Pitts, et al. 2000 or so, et seq. Logic for reasoning about names Much work about representing terms with
binding. BUT: Aimed at theorem proving, not
programming Generally involves data representations that
carry their scoping rules with them:◦ lambda-terms, not s-expressions.◦ Macros must translate from s-expressions (or
something like them) to lambda-terms (or something like them)
Our Starting Points (I)
Ott: a specification language for binding patterns, like Ott (ICFP 2007, JFP 2010)
p ::= // patterns
| x binders = x
| { l1=p1,...,ln=pn } binders = binders(p1 ... pn)
t ::= // terms
| let p = t in t’ bind binders(p) in t’
A primitive binder
A composite binder
Bind these variables in t'
This doesn't solve the problem
Ott has back-ends for
◦ Latex
◦ several theorem provers
But it's not a general-purpose tool
Our Starting Points (II)
Dave Herman's thesis (2010)
◦ took Ott-like specification language
◦ static checking for syntax-rules style macros
Would reject my-let from slide 1.
Goal: extend this to procedurally-defined macros (e.g. syntax-case)
Our Starting Points (III)
Pottier's Functional Fresh ML (LICS 2007)
A programming language based on nominal logic.
His goal: programming with binders.
◦ functions map alpha-equivalent objects to alpha-equivalent objects
Attractive semantics
◦ no hidden gensym (!)
Pottier's Result
Theorem 1: Any function in Fresh ML either preserves alpha-equivalence or else faults
◦ careful language design, any bound variable that escapes its scope triggers a fault.
Theorem 2: From any program in Fresh ML, we can derive a formula G s.t. if G is true, then the program never faults.
Dynamic!
Static! Can use SMT prover
Does this solve the problem?
No: his data still carries around its own binding information dynamically
We need to manipulate plain old s-expressions (or something like them)
Our plan
Adapt Pottier's system to use plain old s-expressions.
Keep the binding information in types (static) rather than in the data (dynamic)
Progress [Work by Paul
Stansifer] Core language defined
Static checks defined (extension of Pottier's)
Now working on proofs of theorems
A Binding Specification
// input
Expr' = App' Expr Expr
| Lam' Atom Expr↓0
| Var' Atom
| Let LetClauses Expr↓0
| LetRec LetClauses↓0 Expr
LetClauses = LCNone
| LCBind Atom Expr LetClauses ⇑0⊎2
// output
Expr = App Expr Expr
| Lam Atom Expr↓0
| Var Atom
bindings from Atom and
LetClauses are bound in
Expr
Export bindings from
Atom and LetClauses
0 1
0 1 2
We use positional
notation for now
Atoms export themselves
Next Steps
Interface to SMT prover (w/ Fabian Muehlenboeck)
What adaptations are necessary to make these obligations acceptable to an SMT-style prover?
Actually write some macros in this system.