1
Domain Specific Languages
Based on http://martinfowler.com/dslwip
2
[A-Za-z][A-Za-z0-9_]*
PROGRAMS=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)
3
<?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>
4
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,
public Menu item(String name,
public Menu item(String name,
accelerator) } ... }
public Menu item(String name,
ActionListener l) { ... }
{ ... }
char mnemonic) } ... }
char accelerator) } ... }
char mnemonic, char
char mnemonic,
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
public
public
public
// ...
}
MenuBuilder child(String name);
MenuBuilder shortcut(char c);
MenuBuilder action(ActionListener al);
MenuBuilder up();
and a few more
21
Defining a Menu (Again)
new MenuBuilder()
.child("File").shortcut('f')
.child("Open")
.shortcut('o').action(new
.up()
.child("Exit")
.shortcut('x').action(new
.up()
.up()
.child("Edit").shortcut('e')
.child("Cut")
.shortcut('c').action(new
.up()
.child("Paste")
.shortcut('p').action(new
.up()
.up()
FileOpen())
FileExit())
EditCut())
EditPaste())
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 = PROG
LIBFILE = "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
# 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
26
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
Descargar

Document