790 likes | 896 Views
Strategic Programming Across Programming Paradigms Tutorial SBLP. João Saraiva Joost Visser Departamento de Informática Universidade do Minho, Portugal. Strategic Programming Context. Fundação para a Ciência e Tecnologia, grants No. SFRH/BPD/11609/2002 and POSI/CHS/44304/2002
E N D
Strategic Programming Across Programming Paradigms Tutorial SBLP João Saraiva Joost Visser Departamento de Informática Universidade do Minho, Portugal
Strategic ProgrammingContext • Fundação para a Ciência e Tecnologia, grants No. SFRH/BPD/11609/2002 and POSI/CHS/44304/2002 • Area: Language processing and formal methods • Related projects: • PURe - program understanding and reverse eng. • IKF - information knowledge fusion • Looking for motivated MSc and PhD students!
Strategic ProgrammingSchedule • Motivation (30 min) • What? Why? Examples. • Basic concepts (45 min) • Definition, combinators, semantics. • Incarnations (45 min) • FP, OOP, TRS, AG • Patterns and idioms (30 min) • In the large (30 min) • Applications
MotivationWhat is Strategic Programming? A form of generic programming .. .. combining type-case and one-step traversal .. .. into a combinatorial style of program construction.
MotivationExample: regular expressions data RegExp = Literal Char | Empty | Star RegExp | Plus RegExp | Opt RegExp | Seq RegExp RegExp | Alt RegExp RegExp 1 data type with 7 constructors. 1 non-terminal with 7 productions.
MotivationExample: regular expressions norm :: RegExp -> RegExp norm (Literal char)= Literal char norm (Empty) = Empty norm (Star re) = Star (norm re) norm (Plus re) = Plus (norm re) norm (Opt re) = Alt Empty (norm re) norm (Seq re1 re2) = Seq (norm re1) (norm re2) norm (Alt re1 re2) = Alt (norm re1) (norm re2) Turn a? into | a 7 equations: 1 interesting, 6 boring! Traversal strategy: fixed,type-specific, not reusable,coded with explicit recursion.
MotivationRealities of language processing Typed representation: • FP: datatypes & their constructors • OO: abstract classes & their concrete subclasses • TRS: sorts & function symbols • AG: non-terminals & productions
Motivation Problems Loss of conciseness: Multiple implementation of the same functionality over and over again for each type. Loss of robustness: Changes in data format invalidate traversal functionality developed so far. Numerous modifications needed. Loss of reusability: Functionality can not be reused between types within an application or across applications. Lack of traversal control: Recursion scheme is encoded throughout the functions. Strategic programming comes to the rescue! Structure-shy!
MotivationExample revisited norm1 :: RegExp -> RegExp norm1 (Opt re) = Alt Empty (norm re) norm = bottomup norm1 Turn a? into | a 1 equation: 1 interesting, 0 boring! Traversal strategy as combinator: bottomup Mention only constructors relevant to the problem being solved.
MotivationWhat is it good for? Conciseness Write less code. No boring equations. Composability Reuse within and across applications. No hardwired recursion. Traversal control In which order, under what conditions. Reusable schemes, like BU, TD, innermost. Robustness Tolerant against representation changes.
MotivationWhat is Strategic Programming? A form of generic programming .. .. combining type-case and one-step traversal .. .. into a combinatorial style of program construction.
MotivationWhat is Generic Programming? 3 1 35 3 3 35 1 3 data structure sum 42 42
MotivationWhat is Strategic Programming? Non-structured programming Assembly, Cobol Structured programming Algol, Pascal, C If, while, procedures, scopes Polymorphism ML, Miranda, Haskell, C++, Java Type parameters, inheritance Generic programming Polytypic programming, Strategic programming Once and for all for all types.
Strategic ProgrammingSchedule • Motivation (30 min) • Basic concepts (30 min) • Incarnations (45 min) • Patterns and idioms (45 min) • In the large (30 min)
Basic ConceptsOne-step traversal Recursion scheme One-step traversal Recursive call topdown s = s `seq` (all (topdown s)) bottomup s = (all (bottomup s)) `seq s once_td s = s `choice` (one (once_td s)) ...
Basic ConceptsDynamic type-case Generic function Type-specific function Generic function (g † f) x = f x if x has type Dom(f) (g † f) x = g x otherwise (id † inc) 42 = 43 (id † inc) true = true
Basic ConceptsMethodology Brew your own in three steps: • Definition of the problem specific ingredients • Identification of a reusable traversal scheme • Synthesis of the traversal by passing specific ingredients as parameters to the scheme.
Basic ConceptsDefining New Combinators topdown s = sequence s (all (topdown s)) bottomup s = sequence (all (bottomup s)) s
Basic ConceptsDefining New Combinators onceBU s = choice (one (onceBU s)) s onceTD s = choice s (one(onceTD s))
Basic ConceptsDefining New Combinators stopTD s = choice s (all (stopTD s)) stopBU s = choice (all (stopBU s)) s
Basic ConceptsDefining New Combinators try s = choice s id repeat s = try (sequence s (repeat s)) isLeaf = all fail pathTD s = sequence s (choice isLeaf (one (pathTD s))) innermost s = repeat (onceBU s) innermost’ s = sequence (all (innermost’ s)) (try (sequence s (innermost’ s))) belowEq s1 s2 = onceTD (sequence s2 (onceTD s1)) below s1 s2 = belowEq (one s1) s2
Strategic ProgrammingSchedule • Motivation (30 min) • Basic concepts (30 min) • Incarnations (45 min) • Patterns and idioms (45 min) • In the large (30 min)
IncarnationsOverview • Functional Programming (Haskell) • Term Rewriting (Stratego) • Object Oriented Prog. (Java) • Attribute Grammars (LRC) Other paradigms similarly.
What is it? Strafunski Strafunski = Strategies + functions Strafunski = • a Haskell-based bundle • for generic programming, based on the concept of a functional strategy, and • for language processing, using GLR Strafunski = combinator library + precompiler + parser generator
Strategies in HaskellWhat are functional stategies? freely mix generic and type-specific behaviour only uniform behaviour induction over sums-and-products composed from simple combinators Characteristics: • first-class, generic functions • composed and updated in combinator style • allow generic traversal into subterms • mix type-specific and uniform behaviour functional strategy =/= parametric polymorphic function functional strategy =/= polytypic function
Strategies in HaskellWhat are functional strategies? increment = apply (topdown (adhoc identity (+1))) Example: increment all integers in a term > :i increment increment :: Term a => a -> a > increment [0,1,2] [1,2,3] > increment (True,[0,1],Just 2) (True,[1,2],Just 3)
Strategies in HaskellWhat are functional strategies? data TP m = … data TU a m = … applyTP s x :: TP m -> x -> m x applyTU s x :: TU a m -> x -> m a Two abstract types: TP = type-preserving TU = type-unifying
Strategies in HaskellWhat are functional strategies? refTypeNames :: Term a => a -> [HsName] refTypeNames = runId . applyTU traversal where traversal = crush nodeAction nodeAction = adhocTU (constTU []) getName getName (HsTyCon (UnQual n)) = return [n] getName _ = return [] Example: • Haskell itself (30 datatypes, 100 constructors) • Collect all type constructor names • Mention two constructors only • Works on any Haskell fragment / dialect
Strategies in HaskellWhat makes it work? • no new language (cf. PolyP, GH, FISh) • rely on Term class that captures extras • instantiate for every algebraic datatype • use precompiler (extended version of DrIFT) • various instantiation models are possible • preferred model uses unsafeCoerce (in a hidden manner) to realize dynamic type-case.
Strategies in HaskellStrafunski: architecture StrategyLib Strategies FixpointTheme Datatypes PathTheme NameTheme DrIFT Term instances StrategyPrimitives TermRep Library Application Precompiler Strafunski = Library + Precompiler
Strategies in Haskell getting to terms DTD Grammar Dtd2Haskell Sdf2Haskell PGEN Datatypes DrIFT Term instances XML instances ATerm instances GLR parser document Strategies AST program
Strategies in HaskellLearn more Principles: Typed combinators for generic traversal (PADL 2002) Applications: A Strafunski application letter (PADL 2003) Cook book: Design patterns for functional strategic programming (RULE 2002) Implementation: Strategic polymorphism requires just two combinators! (IFL 2002) http://www.cs.vu.nl/Strafunski/
Strategies in JavaGeneral idea Concerns: • Representation of source code • Parsing • Traversal Solutions: • Grammar describes language syntax • Generate hierarchy, parser, visitors • Use visitor combinators to compose traversals
Strategies in JavaFrom grammar to class hierarchy Shape Non-terminal ~ abstract superclass production ~ concrete subclass context-free syntax X Y Z Shape {cons("cross")} P Q R Shape {cons("diamond")} A B C Shape {cons("circle")}
Strategies in JavaThe Visitor design pattern Visitor Visitable accept(Visitor) Visitor A Encapsulate polymorphic behavior outside class hierarchy
Strategies in JavaLimitations of visitors How to combine multiple visitors? • Sequentially fire several visitors • Alternatively attempt several visitors • Guard one visitor by another + = How to control traversal with a visitor? • Topdown iteration over object graph • Along a path between two objects • Once at the closest reachable object of certain type How to make visitors robust against hierarchy changes?
Strategies in JavaWhat are visitor combinators? Reusable classes that capture basic functionality ... CombinatorArgsDescription Identity - Do nothing Sequence v1, v2 First v1, then v2 Fail - Raise exception Choice v1, v2 Try v1. If it fails try v2. All v Apply v to all immediate kids One v Apply v to one immediate kid … which can be composed in different constellations to obtain new functionality. TopDown(v) = Sequence(v,All(TopDown(v))) OnceTD(v) = Choice(v,One(OnceTD(v))) Above(v1,v2) = OnceBU(Sequence(v1,OnceTD(v2)))
Sequence First v1 then v2 Sequence v1 v2
Sequence First v1 then v2 Sequence v1 v2
class Sequence implements Visitor { Visitor v1; Visitor v2; public Sequence(Visitor nv1, Visitor nv2) { v1 = nv1; v2 = nv2; } public void visitCross(Cross cross) { cross.accept(v1); cross.accept(v2); } ... Sequence v1 v2 First v1 then v2
Choice v1 or else v2 (left-biased) Failure: raise exception VisitFailure Choice v1 v2
Choice v1 or else v2 (left-biased) Failure: raise exception VisitFailure Choice v1 v2 Failure
class Choice implements Visitor { Visitor v1; Visitor v2; public Choice(Visitor f, Visitor t) { v1 = f; v2 = t; } public void visitCross(Cross cross) { try { cross.accept(v1); } catch (VisitFailure m) { cross.accept(v2); } } ... Choice v1 v2 v1 or else v2
All Apply v to all immediate kids All v
class All implements Visitor { Visitor v; public All(Visitor f) { v = f; } public void visitCross(Cross cross) { for (int i=0; i<cross.nrOfKids(); i++){ cross.getKid(i).accept(v); } } ... All v Apply v to all immediate kids
"Staggered" visitor John Vlissides, Visitor in Frameworks, C++Report, 1999 Genericity ? • duplication of visit methods • brittle w.r.t. hierarchy changes Fail Failure Failure Failure IsCross Skip
Framework Application Refactoring (step 1) Fail V Failure Fwd IsCross Skip
Refactoring (step 1) Visitor V Fail Sequence V V Failure Framework Application Fwd IsCross Skip