University of Dublin Trinity College Department of Computer
University of Dublin Trinity College Department of Computer Science Fragmenting languages Simon Dobson simon. dobson@cs. tcd. ie http: //www. cs. tcd. ie/
Introduction We’re starting to see more emphasis on componentbased software engineering • compose and re-use relatively large-scale modules Affects applications and languages • languages for building component-based systems • changes in emphasis in constructs Languages themselves as component-based systems • rapid experimentation • domain-specific languages made easy My aim: to tell you about some work we’ve been doing in this area Fragmenting programming languages - 2
Outsourcing information systems Program becomes a high-level script executed in response to events when(shop purchase made) accounts bill(shop buyer, shop total); stock withdraw(shop purchases); fulfilment ship(shop purchases); Accounts Retain only core business services on-site Programmer deals with components ranging from objects to full-sized sub-systems Fragmenting programming languages - 3 Internet Shop window Honest Ron’s Fulfilment Inc Outsource fulfilment and warehousing Widget Packers of London Ltd
From remote interaction. . . Information exposed to browsers via the web These two worlds don’t interact as well as they might CORBA Selectively expose parts of the information system Fragmenting programming languages - 4
…to enterprise embedding Admit a remote component to an enterprise’s intranet, and run in a controlled environment Keep a close eye on the embedded component’s activities and connections Embed part of one organisation into another Fragmenting programming languages - 5
Language challenges Technologies • component repositories, scripting languages Do we understand composition? • it becomes the key factor - “programming in the huge” • the internals of the individual components are less interesting • type systems, objects, exceptions, . . . Do we understand security, at this level? • Java applets and Active. X signed components are too coarse What are the “right” languages for component systems? • changes in programmer demographics • low-level - control, generality, complexity • high-level - domain-specific, simple, limited Fragmenting programming languages - 6
How do we address these issues? Need to experiment with languages quickly • • language - composition operators, re-use models trust management - security, authentication, webs of trust tools - selecting code, repositories, integration with OS services the balance between control and expressiveness Not facilitated by current language technologies • a compiler is a big piece of kit - hard to get source, hard to understand once you’ve got it • barrier to entry into language design too high for many Fragmenting programming languages - 7
A language as a component system Many (most? ) language features are orthogonal • don’t need to know exactly what expressions are available to describe a sequential composition of them (fun( Int n ) n + 1)(12) auto Int with [| 1, 2, 3 |] “hello” 12 exp 1 ; exp 2 The details of the features aren’t really important Features tend to be compositional: they often work by combining sub-expressions without inspecting them • this applies to syntax, types and behaviour Fragmenting programming languages - 8
What does this mean? A “language” is simply a composition of fragments • syntax, typing and behaviour Specify the features independently, and compose • there will be some dependencies… • …but a lot more independence Effects ü ü û û re-use - leverage feature independence easy experimentation - just a composition exercise extensibility - present features as syntax, or libraries, or hidden targeting - exactly the features you want, how you want them performance - generality brings overheads complexity - “so what language do we program in? ? ” Fragmenting programming languages - 9
Vanilla We’ve been developing a language design system called Vanilla • build interpreters from language fragments (“pods”) • re-use existing fragments • incrementally construct language tools Standard pods cover a large sub-set of the language design space • imperative, functional, “typeful”, object-based • direct interaction with CORBA objects • 100% pure Java The idea is to be able to experiment with (and deploy) new language variants quickly and easily Fragmenting programming languages - 10
Vanilla architecture A core algorithm running over a set of components providing the actual functionality Parser Sub-typing Type checker Services Attributes Fragmenting programming languages - 11 Interpreter
Pods The set of components needed to implement a language feature • • syntax - a parser component types - new types, the type-checking of constructs, . . . behaviour - interpretation of the abstract syntax tree auxiliary services - initialisation, daemons, CORBA mappings, … The critical observation is that language features are largely independent of each other • how does it matter what type an object’s methods return? • apply a construct uniformly across other constructs Strive to make them independent • although of course there are dependencies Fragmenting programming languages - 12
Parsing A parser is typically “all one piece” • complete syntax in a set of tokens and productions public export void Type. Specifier() : { } { Ground. Type() | Constructed. Type() } Type. Specifier Int String Sequence( ) A recursive use of the Type. Specifier() production Fragmenting programming languages - 13
Modular parsing Parser components • imports tokens and productions from other components • express bits of grammar Int • recursive descent, parser combinators Type. Specifier String Sequence( ) All(X <: T) Extend the production with another disjunct The body of the universal is itself a Type. Specifier() Can result in ambiguities, but a good way to experiment with syntax Fragmenting programming languages - 14
Component typing and behaviour Both type-checking and interpretation walk to abstract syntax tree A type (interpreter) component “expresses an interest” in particular AST node types • assign a type • determine absolutely that the node is type-incorrect • “pass the buck” to another interested component Overload syntax by having several interested pods • risky, risky… • …but sometimes fits really well, e. g. functions taking types, or the “dot” operator for addressing into various structures Fragmenting programming languages - 15
Components ASTString. Type ASTUniversal. Type ASTFunction Try each interested component until one succeeds, one fails, or all decline to commit themselves Sub-system Fragmenting programming languages - 16 Components express interest in the different node types
What’s in a pod Parser ALL(X <: T) X Concrete syntax to abstract syntax fun(X <: T) … new Universal. Type(…) Type-checker Abstract syntax to type Attributes Behaviour may depend on attributes derived from type-checking Interpreter Fragmenting programming languages - 17 new IClosure(…) Abstract syntax to behaviour
Standard pods Core • ground types, simple constructed types, control structures Functions • higher-order closures with currying The essentials of functional programming Kinds Universally polymorphic types • like C++ templates without the re-compilation Higher-order type systems Automorphic values • dynamic typing Objects Client-side CORBA Fragmenting programming languages - 18 Object types: haven’t done classes yet Currently an incomplete IDL mapping
Languages A language, in Vanilla terms, is just a set of pods composed together within the framework • language definition files name the classes • omit CORBA support by omitting ORB services Parser Typing and sub-typing // core pod ie. tcd. cs. vanilla. syntax. Core Interpreter ie. tcd. cs. vanilla. types. Core. Type. Component ie. tcd. cs. vanilla. types. Core. Subtype. Component ie. tcd. cs. vanilla. interpreter. Core. Interpreter. Component ie. tcd. cs. vanilla. interpreter. Core. Initial. Value. Component ie. tcd. cs. vanilla. interpreter. CORBA. Core. Corba. Mapping Core Vanilla => IDL Default initial values Fragmenting programming languages - 19
Pod re-use Pod usage • change a pod in a language without re-writing the whole thing • change a component of a pod, without changing the others Same pods in several languages or variants • e. g. implement all Pascal and a lot of Java using the standard pods FOR i : = 1 TO 10 DO j : = j + f(i) END; Basically we just eliminate some of the possibilities syntactically for(i = 1; i < 11; j = j + f(i); i = i + 1) ASTFor ASTInteger ASTLess ASTAdd. . . Fragmenting programming languages - 20
Ions Why do we name the super-class of a class? • just need to know the (minimal) type of possible super-classes Ions • “class with a free super-class” • bind to a real super-class before instanciating • just change the pod implementing classes - nowhere else Reify ion with a particular superclass before instanciating the resulting class Apply the same functionality to a family of legal super-classes Must have Fragmenting programming languages - 21 Don’t over-commit to the super-class
Binding Take tight control of binding for mobile code • no covert channels, uniform access control • dynamic bindings - re-bind to the “equivalent” object on entering a new environment Retain static bindings Disallow some bindings Add logging or encryption to channels Re-bind dynamic objects Fragmenting programming languages - 22
Active buildings Quite a complex domain • compound events and combinations, unstable predicates • asymmetric communications, two distinct networks • humans, agents and robots living together High-level scripting to control building actions Code is implicitly event-driven “Place” could actually be quite complex when(person “simon” enters office “F 35”) { execute(“quake 2. exe”) on enya. dsg. cs. tcd. ie; tell(all in “dsg”) “Quake time!!”; } Complex location and group communication tasks hidden inside simple statements Fragmenting programming languages - 23 Details are written once and then hidden, rather than being exposed throughout the applications
CORBA integration - 1 Client-side CORBA interactions as standard Import IDL directly, rather than through a stub compiler • import an IDL file directly • importing results in a set of Vanilla module and type declarations, in terms of the other pods Build stub by binding an object type to an IOR • each method on the object type induces a method stub • use DII to actually make the call Component-based CORBA mapping • map from Vanilla value to IDL any • each pod may add its own mapping Fragmenting programming languages - 24
CORBA integration - 2 Vanilla’s random numbers are really random…. Pull the IDL definitions in off the web import idl "http: //www. random. org/Random. idl"; Random r = bind(Random, ior "http: //www. random. org/Random. ior"); Bind a type from the IDL to an IOR also pulled off the web Int i; Sequence(Int) rs = for(i = 0; i < 10; i = i + 1) r. lrand 48(); println(rs); Call the stub like any other method Fragmenting programming languages - 25
Conclusion Component systems provide a new computer science context We’ll need new language variants • composition, security, trust management • high-level, domain-specific Vanilla provides an infrastructure for experimentation • define language features as fragments, and compose • lots of standard pods to re-use • experiment quickly across the spectrum of language design Fragmenting programming languages - 26
- Slides: 26