Presentation is loading. Please wait.

Presentation is loading. Please wait.

Good Advice for Type-directed Programming Aspect-oriented Programming and Extensible Generic Functions Geoffrey Washburn [ ] Joint.

Similar presentations


Presentation on theme: "Good Advice for Type-directed Programming Aspect-oriented Programming and Extensible Generic Functions Geoffrey Washburn [ ] Joint."— Presentation transcript:

1 Good Advice for Type-directed Programming Aspect-oriented Programming and Extensible Generic Functions Geoffrey Washburn [ geoffw@cis.upenn.edu ] Joint work with Stephanie Weirich [ sweirich@cis.upenn.edu ]

2 Good Advice for Type-directed Programming 2006/09/16 2  Type-directed programming is a form of generic programming.  operation determined by the “shape” of data  many applications (serialization, iteration, etc…)  improves reusability  Key idea: AOP is compelling mechanism for specializing type- directed functions. Introduction

3 Good Advice for Type-directed Programming 2006/09/16 3 Outline  Aspect-oriented programming in Aspect ML.  Type-directed programming in Aspect ML.  Specializing type-directed operations via advice.  Comparison of generic extension via aspects with “Scrap Your Boilerplate With Class”.

4 Good Advice for Type-directed Programming 2006/09/16 4 AOP in Aspect ML  Aspects cut across the boundaries of other sorts of abstractions.  Aspects are coherent collections of advice.  Advice specifies when and where to perform a computation.

5 Good Advice for Type-directed Programming 2006/09/16 5 val f : Int → Bool val g : Int → Int (* trace the argument to f & g *) advice before (|f,g|) (in:Int,stk,info): Int = print ((getFunName info) ^ “ ” ^ (intToString in)); in advice is a declaration form. “where” the advice applies: functions f and g “when” the advice applies: before f and g are called the argument that was passed to f and g advice also gets the current call stack and function metadata. Example advice

6 Good Advice for Type-directed Programming 2006/09/16 6 around f:a→b before after in out advice after (|f|) (out:b, stk, info) : b = … proceed advice around (|f|) (in:a, stk, info) : b = … proceed … advice before (|f|) (in:a, stk, info) : a = … Advice times

7 Good Advice for Type-directed Programming 2006/09/16 7  “where” is specified by a pointcut.  sets of in-scope function identifiers, (|f 1,…,f n |)  the any pointcut  “when” is specified by a time: before, after, or around.  Syntax of advice: advice time expression (x,y,z)= expression Advice in Aspect ML

8 Good Advice for Type-directed Programming 2006/09/16 8 Aspect ML is dynamic  advice installed during program execution  fun init_module () = let advice before … advice after … in … end  advice has global scope  installation order determines execution order  pointcuts are first-class values  let val x = (| f, g |) advice before x …

9 Good Advice for Type-directed Programming 2006/09/16 9 val f : Int → Bool val g : Int → Int (* trace the return value of f & g *) advice after (|f,g|) (out:???,stk,info):??? = print ((getFunName info) ^ “ ” ^ (???)); in Polymorphic advice  Return type could either be Bool or Int.

10 Good Advice for Type-directed Programming 2006/09/16 10  Solution: polymorphic pointcuts and advice  In general pointcuts have a type pc ( σ 1 →σ 2 ).  σ 1 corresponds to argument type of before and around advice.  σ 2 corresponds to argument type of after advice.  Type of (|f,g|) is pc ( Int→a).  Int→a is least common instance of Int→Bool and Int→Int. Polymorphic pointcuts

11 Good Advice for Type-directed Programming 2006/09/16 11 (* trace the return value of f & g *) advice after (|f,g|) (out:a,stk,info):a = print ((getFunName info) ^ “ ” ^ (???)); in (* trace the return value of f & g *) advice after (|f,g|) (out:a,stk,info):a = print ((getFunName info) ^ “ ” ^ (typecase a of | Bool ⇒ boolToString out | Int ⇒ intToString out)); in a = Bool a = Int Type analysis

12 Good Advice for Type-directed Programming 2006/09/16 12 (* trace the return value of f & g *) advice after (|f,g|) (out:a,stk,info):a = print ((getFunName info) ^ “ ” ^ (typecase a of | Bool ⇒ boolToString out | Int ⇒ intToString out)); in (* type-directed serialization *) fun toString (x : a) : String = typecase a of | Bool ⇒ boolToString x | Int ⇒ intToString x | ??? Generic programming

13 Good Advice for Type-directed Programming 2006/09/16 13  Need generic way to handle arbitrary data constructors.  Adapt spines, as developed by Hinze, Löh, and Oliveira. datatype Spine = | SCons : a → Spine a | SApp : Spine (a → b) → a → Spine b  Spines are a generic representation of data type structure Data type generic programming

14 Good Advice for Type-directed Programming 2006/09/16 14  Aspect ML primitive toSpine : a → Option (Spine a).  Spines are recursive in argument, not data type. datatype Foo = Bar : Int → Bool → Char → Foo toSpine (Bar 3 True ‘a’) ⇒ Some (SApp (SApp (SApp (SCons Bar) 3) True) ‘a’) Creating spines SApp SCons ‘a’BarTrue SApp 3

15 Good Advice for Type-directed Programming 2006/09/16 15  Only produces Spine if applied to a data constructor.  toSpine 1 ⇒ None List spine toSpine [1,2] ⇒ Some (SApp (SApp (SCons ::) 1) [2]) SAppSCons ::[2] SApp 1

16 Good Advice for Type-directed Programming 2006/09/16 16 (* type-directed serialization *) fun toString (x: a) : String = typecase a of | Bool ⇒ boolToString x | Int ⇒ intToString x | (b → c) ⇒ “ ” | _ ⇒ (case (toSpine x) | Some x’ ⇒ spineToString x’ | None ⇒ raise Error) and spineToString (x: Spine a) : String = case x of | SCons c ⇒ consToString c | SApp spn arg ⇒ “(“ ^ (spineToString spn) ^ “ ” ^ (toString arg) ^ “)” Total type-directed function

17 Good Advice for Type-directed Programming 2006/09/16 17  toString works for all values now.  But toString [1,2] produces “(((::) 1) ((:: 2) Nil)))”.  Would like to override the default printing behavior for lists.  Unrealistic to edit toString every time we want to refine the behavior.  Need some kind of specialization mechanism. Overriding defaults

18 Good Advice for Type-directed Programming 2006/09/16 18 (* extend toString for lists *) advice around (|toString|) (in:a,stk,info)= typecase a of | [b] ⇒ “[” ^ (concat “,” (map toString in)) ^ “]”) | _ ⇒ proceed in) (* extend toString for lists *) case-advice around (|toString|) (in:[a],stk,info) = “[” ^ (concat “,” (map toString in)) ^ “]”) Overriding with advice

19 Good Advice for Type-directed Programming 2006/09/16 19  Pay as you go: original function does not need to be designed for specialization in advance.  Specialized may occur in separate modules from definition.  Separation of function author from data type author.  Specialization without access to the source code.  Specialization at run-time, by dynamically loaded code. Benefits of using advice

20 Good Advice for Type-directed Programming 2006/09/16 20 Related approaches to extensibility  How do aspects compare for generic extension with type-classes, ala “Scrap Your Boilerplate with Class”?  Type-classes traditionally a very static mechanism, while aspects in Aspect ML are very dynamic.  Trade-off: more aggressive optimization may be possible with type-classes versus dynamic extension.

21 Good Advice for Type-directed Programming 2006/09/16 21  Each type-directed operation defined as type-class. class Show a where show :: a → String  Default type-directed operation is implemented by SYB library using explicit dictionary. instance Data ShowD t ⇒ Show t where show v = showConstr (toConstr v) ++ (concat “ “ (gmapQ showPrxy (showD dict) v))  Specialized behavior by specifying an instance for a type. instance Show a ⇒ Show [a] where show xs = “[” ++ (concat “,” (map show xs)) ++ “]” Scrapping your boilerplate with class

22 Good Advice for Type-directed Programming 2006/09/16 22 Problems with existentials  Can’t directly write a specialized case instance Show Exists where show (Ex (x :: a)) = “pack “ ++ (show x)  Ill typed because don’t know if a has instance for Show.  Could rewrite data type as data Exists = Ex :: forall a. Show a ⇒ a → Exists  Requires unsupported compiler extension.  Unrealistic to modify Exists for every type-directed operation. data Exists = Ex :: forall a. a → Exists

23 Good Advice for Type-directed Programming 2006/09/16 23  Type-classes an entirely compile-time mechanism, not possible to construct new instances at runtime.  Aspect ML can install aspects at any time.  Useful when working with mobile or dynamically loaded code that may export new data types. More comparison

24 Good Advice for Type-directed Programming 2006/09/16 24 More comparison  Type-class constraints in SYB can become complicated for the user, over- constrained, non-terminating, or unsolvable in practice.  Type-classes have the advantage of enforcing and describing the domain of type-directed functions.

25 Good Advice for Type-directed Programming 2006/09/16 25 Summary  Advice can be used to specify when and where a computation should occur.  Aspects are symbiotic with type analysis.  Writing extensible type-directed operations with advice avoids limitations of type-class based SYB.

26 Good Advice for Type-directed Programming 2006/09/16 26 The future  Using information-flow to reason about the use of type analysis and aspects.  Extending Aspect ML implementation.  Writing large scale software with these techniques.  Ask me if you would like a demo or snapshot of Aspect ML.


Download ppt "Good Advice for Type-directed Programming Aspect-oriented Programming and Extensible Generic Functions Geoffrey Washburn [ ] Joint."

Similar presentations


Ads by Google