170 likes | 285 Views
Sumant Tambe * Aniruddha Gokhale Vanderbilt University, Nashville, TN, USA *Contact : sutambe@dre.vanderbilt.edu. An Embedded Declarative Language for Hierarchical Object Structure Traversal.
E N D
SumantTambe* AniruddhaGokhale Vanderbilt University, Nashville, TN, USA *Contact : sutambe@dre.vanderbilt.edu An Embedded Declarative Language for Hierarchical Object Structure Traversal 2nd International Workshop on Domain-Specific Program Development (DSPD), GPCE 2008, Nashville, TN, USA
Object Structures and Operations • Object Structures • Hierarchical data structure (XML) • Object Graph/Network (e.g., Domain-specific Models) • Uses of object structures • Domain-specific modeling language (DSML) interpreters, transformations • Systems using XML data binding • Component deployment & configuration engines • Web services • Common operations • Queries (search) • Traversals (visit each element)
Existing Approaches of Accessing Object Structures • Imperative object-oriented API • Implemented using classes, interfaces, and collections of objects in Java, C++ • Visitor pattern: separates visitation actions from traversal (Good!) • Fancy C++ generic programming techniques using STL/Boost::bind • XQuery / XSLT / XPath • W3C standards • Suitable for hierarchical structures • Suitable for XML-to-XML transformation • Traversal/Visitor Language (TVL) • Separate specification language • Autogenerates traversal code • LINQ (Language Integrated Query) • Used in C# and VB • Based on Microsoft .NET framework class StateMachine { … }; class State { … }; class Transition { … }; Traversal Visitation Action <StateMachine> <State startstate=“Yes” >S1</State> <State>S2</State> <Transitionsrc=“S1”dst=“S2” event=“e1” /> </StateMachine>
Limitations of Existing Techniques • Imperative object-oriented API • Code bloat while using large/complex data models • Intent is lost in low level details • In classic visitor, “visit-all” semantics are inefficient in most cases (visits more elements than necessary) • In other visitor variants traversals are coupled with visitation actions – limits reusability • XQuery / XSLT / Xpath • Only hierarchical. No support for object graphs • Traversal/Visitor Language (TVL) • High cost of development of lexer/parser • Must learn new language (syntax, semantics) and code generator • LINQ • Depends on language extensions in C#, VB • Depends on .NET framework features Visitation Action Traversal &
Solution: LEESA • LEESA: Language for Embedded Query and Traversal • Features of LEESA • A domain-specific embedded language (DSEL) for writing queries and traversals over object graphs (models) • Provides short and expressive syntax for traversal • Supports multiple traversal strategies • Supports Visitor: decouples visitation actions from traversal • Cheap to develop because it is embedded in C++ • Reuses C++ lexer, parser and whole slew of standard libraries • Much flatter learning curve than external DSLs • Seamless transition between LEESA and traditional C++ • Interoperable with other popular C++ DSELs (e.g., Boost.Phoenix, Boost.Lambda)
Layered Architecture of LEESA DSL for query and traversal A C++ generative programming technique OO access API (UDM, XML data binding) In memory representation of object structure
Composition Navigation Using LEESA Example 1:Give all the States under RootFolder RootFolder() >> StateMachine() >> State() Returns a std::set<State> Example 2:Give all the Property atoms under RootFolder RootFolder() >> StateMachine() >> State() >> Property() Returns a std::set<Property> Example 3: Give the parent State of Property P P << State() Returns a std::set<State>of size = 1 Parent/child composition relationship navigation using “>>” and “<<”
Object Structure Queries Using LEESA Example 4:Give all the States under RootFolder whose name starts with “XYZ” RootFolder() >> StateMachine() >> State() >> SelectByName(State(),”XYZ.*”) Example 5:Same as above + apply arbitrary filter + sort RootFolder() >> StateMachine() >> State() >> SelectByName(State(),”XYZ.*”) >> Property() >> Select(Property(), predicate) >> Sort(Property(), comparator) Where predicate and comparator are standard C++ functions or stateful function objects Many query operators are supported such as Unique, Sort, SelectByName, Select (generic)
Association Navigation Using LEESA Association ends can be navigated to using “>>&” followed by the name of the association. Example 6:Give all the States that are at the “dst” end of transitions RootFolder() >> StateMachine() >> Transition() >>& Transition::dstTransition Returns a std::set<State> = { S2, S3, S4 }
Object Structure Visitation Using LEESA • Visitor pattern is supported • Add visitor object in square bracket • Calls corresponding Visit function • Separates visitation actions from traversal order Example 7: Visit each StateMachine, State, and Property and count them CountVisitorcv; RootFolder() >> StateMachine()[cv] >> State()[cv] >> Property()[cv] Example 8: Same as before but in depth-first order • “>>” visits in breadth-first order • “>>=” visits in depth-first order • Query operators work with both strategies • Traversal strategies can be mixed together RootFolder() >>=StateMachine()[cv] >>=State()[cv] >>= Property()[cv]
Combining LEESA Traversal Strategies Example 9: Visit all StateMachines in depth-first order and visit all the properties in sorted order #define DEPTH_FIRST >>= CountVisitorpv; RootFolder() DEPTH_FIRSTStateMachine() >> cv >> State() >> Property() >> Sort(Property(),comparator) >> cv
Layered Architecture of LEESA DSL for query and traversal A C++ generative programming technique OO access API (UDM, XML data binding) In memory representation of object structure
LEESA’s Generic Data Access Layer Automatically generated UDM C++ interface from meta-model: class RootFolder { set<StateMachine> StateMachine_kind_children(); template <class T> set<T> children (); }; class StateMachine { set<State> State_kind_children(); set<Transition> Transition_kind_children(); template <class T> set<T> children (); }; class State { set<Property> Property_kind_children(); template <class T> set<T> children (); }; class Transition { State srcTransition(); State dstTransition(); }; class Property; T determines children kind
Layered Architecture of LEESA DSL for query and traversal A C++ generative programming technique OO access API (UDM, XML data binding) In memory representation of object structure
Overview of Expression Templates • First developed in 1994 by Todd Veldhuizen • Known uses: Boost.Spirit parser, Blitz++ scientific computing library • Based on the idea of lazy evaluation • Execute expressions much later in the program from the point of their definition • Pass an expression -- not the result of the expression -- as a parameter to a function • E.g., foo (x * y + z); • The result of expression is computed before calling the function • Instead, an abstract syntax tree (AST) is created at compile-time using templates and operator overloading + * Z X Y
LEESA’s Expression Templates • LEESA defines a couple of expression templates and many operators • We’ll consider GetChildrenoperator • ChainExpr expression template Returns a set of R RootFolder() >> StateMachine() >> State() >> Property() GetChildren<L, R> L.children<R>(); GetChildren<StateMachine, State> StateMachine.children<State>(); • ChainExpr<L,R> creates an AST that embodies traversal
Future Work & Concluding Remarks • How to improve error reporting? • Promising solution: C++ concept checking • How to make it less dependent on structure? • Structure-shyness property • How to support wildcards? RootFolder() >> ***** >> Property()