DSL - Domain Specific Languages, Chapter 4, Internal DSL

of 26 /26
Domain Specific Languages Hiro Yoshioka March 15th, 2013 Rakuten Tower 2, Shinagawa, Tokyo, Japan
  • date post

    18-Oct-2014
  • Category

    Technology

  • view

    636
  • download

    4

Embed Size (px)

description

Domain Specific Languages, by Martin Fowler http://martinfowler.com/books/dsl.html Chapter 4, Internal DSL

Transcript of DSL - Domain Specific Languages, Chapter 4, Internal DSL

Domain Specific Languages

Hiro Yoshioka March 15th, 2013 Rakuten Tower 2, Shinagawa, Tokyo, Japan

2

Chapter 4, Internal DSL

Unlike external DSLs, you dont need to learn about grammars and language parsing.

Constrain host language expression Ruby Lisp

uent interface vs API

3

4.1 Fluent and Command-Query APIs

Method Chaining Processor p = new Processor(2, 2500, Processor.Type.i386); Disk d1 = new Disk(150, Disk.UNKNOWN_SPEED, null); Disk d2 = new Disk(75, 7200, Disk.Interface.SATA); return new Computer(p, d1, d2); Method Chaining computer() .processor() .cores(2) .speed(2500) .i386() .disk() .size(150) .disk() .size(75) .speed(7200) .sata() .end();

4

4.1 Fluent and Command-Query APIs

Func]on Sequence computer() processor(); cores(2); speed(2500); i386(); disk(); size(150); disk(); size(75); speed(7200); sata();

5

4.1 Fluent and Command-Query APIs

6

4.1 Fluent and Command-Query APIs

Command-query separa]on Command: may change state, but not

return value Query: does not change state Name without context

Fluent: Name context is important

7

4.2 The Need for a Parsing Layer

Expression Builder input: uent interface output: a sequence of command-query API

Seman]c model Separa]ng the Seman]c model from

Expression Builders You can test them independently.

8

4.3 Using Functions

func]on most successful packaging, (also called subrou]ne, procedure, method)

computer(); processor(); cores(2); speed(2500); i386(); disk(); size(150); disk(); size(75); speed(7200); sata();

9

4.3 Using Functions Method Chaining and Func]on Sequence

Scope of the func]ons Func]on Sequence: ensure the func]ons

resolve properly global func]on complica]ng

namespace and introducing global variables for parsing data. Context Variables

Method Chaining avoids global object scoping avoid globalness,

extensibility nested func]on avoid context

variables

10

4.3 Using Functions

nested func]on combines func]ons by making func]on

calls arguments in higher level func]on calls.

reects the logical syntax tree of the DSL change in evalua]on order (, ), , are explicit. noise Lisp

(third(second(rst))) ** I found typo

computer( processor( cores(2), speed(2500), i386 ), disk( size(150) ), disk( size(75), speed(7200), SATA ) );

11

4.3 Using Functions

nested func]on the hierarchic structure of the

congura]on is echoed by the language constructs themselves

reects the logical syntax tree of the DSL evalua]on order arguments are iden]ed by posi]on rather

than name

12

4.3 Using Functions

hybrid It uses Func]on Sequence, each computer

func]on uses Nested Func]on, each processor and disk is using Method Chaining.

Advantages: Func]on Sequence: each computer

deni]on well separated. Nested Func]on: eliminates a Context

Variable. Method Chaining: mul]ple op]onal

arguments

computer( processor() .cores(2) .speed(2500) .type(i386), disk() .size(150), disk() .size(75) .speed(7200) .iface(SATA) ); computer( processor() .cores(4) );

13

4.3 Using Functions

hybrid problems punctua]onal confusion

comma, periods, semicolons,

14

4.4 Literal Collections

literal list

-- Java or C# computer( processor (...), disk(...), disk(...) ); -- Ruby computer [ processor(...), disk(...), disk(...) ]

15

4.4 Literal Collections

literal map named parameters symbol

immutable, symbol lookup :symbol (ruby syntax)

-- Ruby computer(processor(:cores => 2, :type => :i386), disk(:size => 150), disk(:size => 75, :speed => 7200, :interface => :sata)) -- Ruby 2.0 has a keyword arguments

16

4.4 Literal Collections

symbol

-- Ruby computer(processor(:cores => 2, :type => :i386), disk(:size => 150), disk(:size => 75, :speed => 7200, :interface => :sata))

17

4.5 Using Grammars to Choose Internal Elements

Structure BNF Consider

Mandatory list parent ::= rst second third Nested Func+on (357)

Op]onal list parent ::= rst maybeSecond? maybeThird?

Method Chaining (373), Literal Map (419)

Homogenous bag parent ::= child* Literal List (417), Func+on Sequence (351)

Hetrogenous bag parent ::= (this | that | theOther)* Method Chaining

Set n/a Literal Map

18

4.6 Closures

lambdas, blocks, anonymous func]ons

#ruby... ComputerBuilder.build do |c| c.processor do |p| p.cores 2 p.i386 p.speed 2.2 end c.disk do |d| d.size 150 end c.disk do |d| d.size 75 d.speed 7200 d.sata end end

19

4.6 Closures

Nested Closures inline nes]ng deferred evalua]on limited-scope variables

#ruby... ComputerBuilder.build do |c| c.processor do |p| p.cores 2 p.i386 p.speed 2.2 end c.disk do |d| d.size 150 end c.disk do |d| d.size 75 d.speed 7200 d.sata end end

20

4.7 Parse Tree Manipulation

parse tree manipula]on

ptg9438845

BinaryExpression

MemberAccess

Left

ConstantExpression

Right

Age

Member

aPerson

Expression

18

Value

Figure 4.2 A parse tree representation of aPerson.Age > 18

query in another query language, such as SQL. This is essentially what .NETsLinq language does. Linq allows you to express many SQL queries in C#, whichmany programmers prefer.

The strength of Parse Tree Manipulation is in allowing you to write expressionsin the host language that can then be converted into different expressions thatpopulate the Semantic Model (159) in ways that are beyond just storing the closureitself.

In C#s case above, this manipulation is done with an object model representa-tion of the parse tree. In Lisps case, this manipulation is done by macro transfor-mations on Lisp source code. Lisp is well suited to this because the structure ofits source code is very close to that of a syntax tree. Parse Tree Manipulation ismore widely used in Lisp for DSL workso much so that Lispers often wail atthe lack of macros in other languages. My view is that manipulating an objectmodel of the parse tree in C# style is a more effective way of doing Parse TreeManipulation than Lisp macrosalthough this may be due to my lack of practicewith Lisps macro processing.

Whatever mechanism you use, the next question is how important Parse TreeManipulation is as a technique for DSLs. One very prominent use is in LinqaMicrosoft technology that allows you to express query conditions in C# and turnthem into different query languages for various target data structures. In thisway, one C# query can be turned into SQL for relational databases and XPathfor XML structures, or kept in C# for in-memory C# structures. Its essentiallya mechanism that allows application code to do runtime code translation,generating arbitrary code from C# expressions.

Parse Tree Manipulation is a powerful, but somewhat complex, technique thathasnt been supported much by languages in the past, but these days has beengetting a lot more attention due to its support in C# 3 and Ruby. Since its rela-tively new (at least outside the Lisp world), its hard to evaluate how truly usefulit is. My current perception is that its a marginal techniquesomething that israrely needed but very handy on the occasions when that need arises. Translating

4.7 Parse Tree Manipulation 83

4: Implementingan Internal DSL

From the Library of Hiro Yoshioka

21

4.8 Annotation

Auribute in C#

class Person

validates_length_of :last_name, :maximum => 30

22

4.9 Literal Extension

Method Chaining chain begins on a literal integer,

e.g. 5.days.ago add methods to external library classes Cons: methods globally

23

4.10 Reducing the Syntactic Noise

Textual Polishing

24

4.11 Dynamic Reception

handle an unexpected call by run]me to a special method. programmers can override the method to do other things. method_missing in Ruby, doesNotUnderstand in Smalltalk

e.g., Rails Ac]ve records dynamic nders

25

4.12 Providing Some Type Checking

sta]c type checking or not type checking at compile ]me or run ]me modern IDEs provide excellent support based

on sta]c typing

26

Yoshioka