4 dec 2001kestrel1 from patterns to programming languages matthias felleisen northeastern university
TRANSCRIPT
4 Dec 2001
Kestrel 1
From Patterns to Programming Languages
Matthias FelleisenNortheastern University
4 Dec 2001
Kestrel 2
Background and Experience
• Theory of PL Expressiveness• PLT Scheme (IDE, tools, Scheme)
– 200 Kloc Scheme, 200Kloc C++ (inh)– 400 downloads/day for last year
• 94/95: design patterns– use in implementation– implementing patterns in Scheme – “A Little Java, A Few Patterns”– papers on patterns for extensibility
• 96/97: Patterns in the IDE (ESOP)
4 Dec 2001
Kestrel 4
Patterns (GoF)
• pattern name
• problem
• solution
• consequences
• adapter
• mismatch of interface
• create adapter class
• e.g., class adapters may introduce additional behavior
4 Dec 2001
Kestrel 5
Patterns (PL)
• name
• problem
• solution
• consequences
• store passing
• mismatch of interface: have FP, need state
• pass store as data structure; lookup & modify locations man.
• introduce additional behavior
4 Dec 2001
Kestrel 6
Patterns (PL: store passing)
val xcount = ref 0;
// xf : unit -> TypeGfun xf () = … xcount = !xcount + 1; G;
would like, but don’t have
val xcount = ref 0;
// xf : int -> (TypeG, int)fun xf (xcount) = … let val xcount = !xcount + 1; in (G, xcount);
here we go:
4 Dec 2001
Kestrel 8
Patterns (PL)
• name
• problem
• solution
• consequences
• continuation passin g
• mismatch of interface: have FP, need exceptions
• pass control as function
• introduce additional behavior
4 Dec 2001
Kestrel 9
Patterns (PL: continuation passing)
// xf : unit -> TypeGfun xf () = … if cond then exit(10); else G;
would like, but don’t have
// xf : (GType -> FA) -> FAfun xf (roc) = … if cond then 10; else roc(G);
here we go:
4 Dec 2001
Kestrel 11
Patterns (PL)
• name
• problem
• solution
• consequences
• nested blocks
• lack blocks in FPL
• apply anonymous function
• physically separate variables from values
4 Dec 2001
Kestrel 12
Patterns (PL: nested blocks)
(let ([x 10] [y 20]) … x … y … )
would like, but don’t have
((lambda (x y) … x … y … ) 10 20)
here we go:
4 Dec 2001
Kestrel 13
Patterns (PL)
• name
• problem
• solution
• consequences
• for-loop
• lack for-loop in FPL
• use recursive function
• physically separate loop variable from initial value
4 Dec 2001
Kestrel 14
Patterns (PL: nested blocks)
(for j = 10 to 20 (set! sum (+ sum j)))
would like, but don’t have
(for-each (lambda (j) (set! sum (+ sum j))) (build-list 10 (lambda (k) (+ k 10))))
here we go:
4 Dec 2001
Kestrel 15
Patterns from PL
• Landin: patterns are everywhere – some are local --> syntactic sugar– some are global --> essential constructs
• Strachey, Wadsworth: – denotational semantics & global patterns
• Felleisen (1988): – theory of expressiveness relative to a base
language
4 Dec 2001
Kestrel 17
Pattern Programming
• Programming with patterns is good.
• With Patterns, programmers can discuss lots of code with a few words.
• Patterns suggest invariants, helping reasoning about code.
4 Dec 2001
Kestrel 18
Pattern Programming
• Programming patterns explicitly is bad.
• Programmers may “lie” about patterns.
• Pattern maintenance may break logical invariants
4 Dec 2001
Kestrel 19
The Adapter Pattern: One More Time
/* Adapter Pattern: object adapter
GraphicalOutput adapts VendorGraphics to OutputRoutines
*/
interface OutputRoutines { … }
class GraphicalOutput implements OutputRoutines { … }
class VendorGraphics { … }
two lines of comments explain 100 lines of code
4 Dec 2001
Kestrel 20
The Adapter Pattern: One More Time
/* Adapter Pattern: object adapter
GraphicalOutput adapts VendorGraphics to OutputRoutines
*/
class OutputRoutines { … }
class GraphicalOutput extends OutputRoutines { … }
class VendorGraphics { … }
it’s no longer an adaptation -- it’s implementation inheritance
4 Dec 2001
Kestrel 21
Patterns as Comments
• When patterns are comments and informal language, nobody knows whether our claims are true.
• Somebody else may change the code or the comments. – Then they are out of sync.
• Are such patterns useful?
4 Dec 2001
Kestrel 22
Patterns as Language Constructs
• local patterns vs global patterns
• local patterns via syntactic extensions
• global patterns via aspects (?)– if aspects work, we can experiment with a
pattern and see whether it is useful– if so, we should add them to the language.
4 Dec 2001
Kestrel 23
Scheme’s Macros: Principles
• Macros are transformations on the abstract syntax trees
• Macros respect the scoping (and other) information of the input ASTs.
• Macros respect the scoping information of their “host” module.
4 Dec 2001
Kestrel 24
Scheme’s Macros: Example
(define-syntax let (syntax-rules () [(let ([<x:var> <rhs:exp>] ...) <body:exp> ...) ((lambda (<x:var> ...) <body:exp> ...) <rhs:exp> ...)]))
;; use: (let ([x 10][y 20]) (printf "the variables are: ~s ~s ~n" x y) (+ x y))
4 Dec 2001
Kestrel 25
Local Patterns as Language Constructs
(define-syntax-pattern Adapter [rewrite (_ <aN> adapts <aT> to <dI> as <aV> (fields <fd> ...) (methods <md> ...))] [as (class <aN> implements <dI> (fields (<aT> <aV>) <fd> ...) (methods <md> ...))])
4 Dec 2001
Kestrel 26
Pattern Elaboration
aN
aT
d I
aV
m d
m eth od s
fd
fie ld s
A d ap te r
aN
d I
aT aV
fd
fie ld sm d
m eth od s
c lass
4 Dec 2001
Kestrel 28
Making Patterns as Constructs Work
Programmers need to see information at the level at which they program.
Information is: syntax error type error run-time exception reporting
4 Dec 2001
Kestrel 29
Information about Programs Matters
MultiplicationExpression<class LazyBinaryExpression<class AdditionExpression<class MatrixICCL::Matrix<class MatrixICCL::BoundsChecker<class MatrixICCL::ArrFormat<class MatrixICCL::StatExt<struct MatrixDSL::int_number<int,7>,struct MatrixDSL::int_number<int,7>>,class MatrixICCL::Rect<class MatrixICCL::StatExt<struct MatrixDSL::int_number<int,7>,struct MatrixDSL::int_number<int,7>>>,class MatrixICCL::Dyn2DCContainer<class MATRIX_ASSEMBLE_COMPONENTS<class MATRIX_DSL_ASSIGN_DEFAULTS<class MATRIX_DSL_PARSER<struct MatrixDSL::matrix<int,struct MatrixDSL::structure<struct MatrixDSL::rect<struct MatrixDSL::stat_val<struct MatrixDSL::int_number<int,7>>,struct MatrixDSL::stat_val<struct MatrixDSL::int_number<int,7>>,struct MatrixDSL::unspecified_DSL_feature>,struct MatrixDSL::dense<struct MatrixDSL::unspecified_DSL_feature>,struct MatrixDSL::dyn<struct MatrixDSL::unspecified_DSL_feature>>,struct MatrixDSL::speed<struct MatrixDSL::unspecified_DSL_feature>,struct MatrixDSL::unspecified_DSL_feature,struct MatrixDSL::unspecified_DSL_feature,struct MatrixDSL::unspecified_DSL_feature,struct MatrixDSL::unspecified_DSL_feature>>::DSLConfig>::DSLConfig>>>>>,class MatrixICCL::Matrix<class MatrixICCL::BoundsChecker<class MatrixICCL::ArrFormat<class MatrixICCL::StatExt<struct MatrixDSL::int_number<int,7>,struct MatrixDSL::int_number<int,7>>,class MatrixICCL::Rect<class MatrixICCL::StatExt<struct MatrixDSL::int_number<int,7>,struct MatrixDSL::int_number<int,7>>>,class MatrixICCL::Dyn2DCContainer<class MATRIX_ASSEMBLE_COMPONENTS<class MATRIX_DSL_ASSIGN_DEFAULTS<class MATRIX_DSL_PARSER<struct MatrixDSL::matrix<int,struct MatrixDSL::structure<struct MatrixDSL::rect<struct MatrixDSL::stat_val<struct MatrixDSL::int_number<int,7>>,struct MatrixDSL::stat_val<struct MatrixDSL::int_number<int,7>>,struct MatrixDSL::unspecified_DSL_feature>,struct MatrixDSL::dense<struct MatrixDSL::unspecified_DSL_feature>,struct Ma…
(A + B) * C : misuse of variable produces:
4 Dec 2001
Kestrel 31
Pattern Macros: A Full Example
• expansion rules • instance from GoF
• consistency error • syntax check, scope check• type check
4 Dec 2001
Kestrel 32
The Composite Pattern: New Syntax
(COMPOSITE
(ABSTRACT <abs:variable> (FIELDS (<f:variable> <f:exp>)...) (METHODS (<m:variable> <m:exp>)) (ABSTRACT:METHODS <am:variable> ...)) (CONCRETE <con1:variable> (FIELDS (<cf:variable> <cf:exp>) ...) (METHODS (<cm:variable> <cm:exp>) ...)) (COMPOSITE:METHODS (<cm:variable> <cm:exp>) ...))
4 Dec 2001
Kestrel 33
(begin ;; --- ABSTRACT CLASS (define <abs:variable> (class* object% () () (private (<f:variable> <f:exp>) ...) (public (<am:variable> (lambda x (error '<am:variable> "not implemented ...))) ;; --- CONCRETE CLASSES (define <con1:variable> (class* etc. ….. ………………………………………………)))
The Composite Pattern: Elaboration
4 Dec 2001
Kestrel 38
Source Correlation
• to track source information through expansions
• to provide feedback in terms of original source
4 Dec 2001
Kestrel 39
Elaboration Tracking
• to keep track of history of macro transformations
• to help IDE untangle complex interactions between complex pattern embeddings
4 Dec 2001
Kestrel 41
Summary
• patterns have a long history, pre-GoF
• patterns should be language constructs for the obvious reasons
• macros (and an expressive base language) can turn most patterns into language constructs
4 Dec 2001
Kestrel 42
Patterns via Macros
• abstract factory, factory, singleton, adapter, bridge, composite, decorator, façade, proxy, chain, command, interpreter, iterator, observer, state, strategy, visitor, template
• from local macros using a base language with higher-order functions and assignment
4 Dec 2001
Kestrel 43
Challenges
• global patterns
• a well-founded theory of patterns
• more experience with pattern in languages with explicit type declarations