1 domain specific languages based on

27
1 Domain Specific Languages Based on http://martinfowler.com/dslwip

Post on 19-Dec-2015

224 views

Category:

Documents


1 download

TRANSCRIPT

1

Domain Specific Languages

Based on http://martinfowler.com/dslwip

2

[A-Za-z][A-Za-z0-9_]*

3PROGRAMS=ex1_connect ex2_select

all: $(PROGRAMS)

clean:

rm -f $(PROGRAMS) *.o

include $(ORACLE_HOME)/rdbms/lib/env_rdbms.mk

OPTIMIZE=$(OPTIMIZEG)

.SUFFIXES: .o .cc

.cc.o:

$(CCC) $(CFLAGSCC) -c $<

ex1_connect: ex1_connect.o

$(LINKCC) ex1_connect.o $(SHARED_OCCILIBS)

ex2_select: ex2_select.o

$(LINKCC) ex2_select.o $(SHARED_OCCILIBS)

4<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app>

<display-name>IMDB</display-name>

<description>Internet Movie Database</description>

<context-param>

<param-name>db-url</param-name>

<param-value>www.imdb.com/datacenter</param-value>

</context-param>

<servlet>

<servlet-name>search</servlet-name>

<servlet-class>my.package.SearchServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>search</servlet-name>

<url-pattern>/search.html</url-pattern>

</servlet-mapping>

</web-app>

5

<menubar>

<item name="File">

<item name="Open" mnemonic="O">commands.Open</item>

<item name="Save" mnemonic="S">commands.Save</item>

<item name="Save As" mnemonic="A">commands.SaveAs</item>

</item>

<item name="Edit">

<item name="Cut" mnemonic="T">commands.Cut</item>

<item name="Copy" mnemonic="C">commands.Copy</item>

<item name="Paste" mnemonic="P">commands.Paste</item>

</item>

</menubar>

6

last.file.name=c:\\files\\input.dat

x=105

y=99

width=527

height=401

7

DSL

• A language designed for solving a specific class of problems– “Do one thing well”

• Less powerful than a general-purpose language (GPL)– Usually not Turing complete– If it’s not simpler to use than a GPL – no reason to use it

8

Motivation for DSLs

• Initially: Customizability• Currently: Productivity

9

DSL: Customizability

• Allow users to customize a program– Without recompiling it

• Imagine: Unix’s make without the DSL– Make will be a library– User will write a program that uses the library– Will use API for defining the dependencies, actions, etc.– Compile & Run

• In the good old days compilation was an issue

10

DSL: Productivity

• In its domain a DSL is more productive than a general purpose language– Because it does one thing well

• Example: String matching– Very easy with regular expressions– Much harder with manually written Java code

• The direct result: DSLs are all over the place– Even if no user-customizability is needed

11

DSL Oriented Development

• Development that focuses on building and using DSLs to develop a system

• Various DSLs float around – each one solves a particular problem within the broader context

• One cannot build a whole program with one DSL

• Don’t overdo it – implementing a DSL takes effort

12

External DSL

A DSL represented in a separate language to the host programming

language

13

External DSL Highlights

• Syntax– Custom-made– (Or) Follows a common format CSV, XML, etc.

• Stages– Parsing and tree Construction– Semantic Model construction– Execution

• Not all stages must exist– Developer may choose to do execution while parsing

14

[{ name: "File", shortcut:'F', children: [ { name:"Open", shortcut:'o', action:"p1.Main$FileOpen"}, { name:"Exit", shortcut:'x', action:"p1.Main$FileExit"} ] },{ name: "Edit", shortcut:'E', children: [ { name:"Cut", shortcut:'t', action:"p1.Main$EditCut"}, { name:"Paste", shortcut:'p', action:"p1.Main$EditPaste"} ] }]

15

Theory of Compilation & DSLs

• Compilation courses often focus on advanced parsing issues

• In practice, simple recursive descent parsers are fine– Even lexical scanners are not always needed

• => No need to use parser generators– If you do want to use them: modern tools (Antlr, Javacc)

are much simpler than Lex/Yacc

• Bottom line: don’t panic

16

Internal DSL

A DSL expressed within the syntax of a general purpose language.

A stylized use of the language for a domain specific purpose.

17

Menu Definition API

public class Menu { public Menu add(Menu m) { // add m as a child return this; } } public Menu item(String name) { ... } public Menu item(String name, char mnemonic) } ... } public Menu item(String name, char accelerator) } ... } public Menu item(String name, char mnemonic, char

accelerator) } ... } public Menu item(String name, char mnemonic, ActionListener l) { ... } public Menu menubar() { return new Menu(); }

18

Defining a Menu

menubar() .add( item("File", 'f') .add(item("Open", 'o', new FileOpen())) .add(item("Exit", 'o', new FileExit()))) .add( item("Edit", 'e') .add(item("Cut", 'c', new EditCut())) .add(item("Paste", 'p', new EditPaste())));

19

Difficulties of the Proposed API

• Order of parameters

• Too many parenthesis

• Must create an item() method for each subset of desired menu properties

20

A Better API

public interface MenuBuilder {

public MenuBuilder child(String name);

public MenuBuilder shortcut(char c);

public MenuBuilder action(ActionListener al);

public MenuBuilder up();

// ... and a few more

}

21

Defining a Menu (Again)new MenuBuilder() .child("File").shortcut('f') .child("Open") .shortcut('o').action(new FileOpen()) .up() .child("Exit") .shortcut('x').action(new FileExit()) .up() .up() .child("Edit").shortcut('e') .child("Cut") .shortcut('c').action(new EditCut()) .up() .child("Paste") .shortcut('p').action(new EditPaste()) .up() .up()

22

Internal DSL Highlights

• Syntax– Based on the API– Heavy use of fluent interfaces

• Stages– Semantic Model construction– Execution

• Not all stages must exist– API may do the actual execution when called

23

Comparison

• Pros: External DSL– Full control over syntax, semantics– User customizability

• Pros: Internal DSL– Integration with the host language– IDE support

24

Rake File

• Rake: A build system for the Ruby world– Similar to Java’s Ant, Unix’s Make

• As expected uses a DSL for building program

• Here’s a sample Rake file– Q: is this an internal or external DSL?

25

require 'rake/clean'

PROG = "foo" LIBNAME = PROGLIBFILE = "lib#{LIBNAME}.a"

SRC = FileList['**/*.c']

OBJDIR = 'obj'OBJ = SRC.collect { |fn| File.join(OBJDIR,

File.basename(fn).ext('o')) }

CLEAN.include(OBJ, OBJDIR, LIBFILE)CLOBBER.include(PROG)

task :default => [:build, :run]

# continued on next slide

26# continued from previous slide

task :build => [PROG]

task :run => [PROG] do sh "./#{PROG}" end

file PROG => [LIBFILE] do sh "cc -o #{PROG} -L . -l#{LIBNAME}" end

file LIBFILE => OBJ do sh "ar cr #{LIBFILE} #{OBJ}" sh "ranlib #{LIBFILE}" end

27

DSL & Dynamic Languages

• Dynamic languages are flexible– Syntax– Offer new constructs– Redefining semantics of existing constructs

• Thus, they can support a wide spectrum of internal DSL syntaxes

• The best of both worlds– Integration with the host language– IDE support– User customizability– (Almost) Flexible syntax