internal domain-specific languages

19
1 Internal Domain-Specific Languages Ras Bodik, Thibaud Hottelier, James Ide UC Berkeley CS164: Introduction to Programming Languages and Compilers Fall 2010

Upload: geordi

Post on 25-Feb-2016

67 views

Category:

Documents


1 download

DESCRIPTION

Internal Domain-Specific Languages. Ras Bodik, Thibaud Hottelier, James Ide UC Berkeley CS164: Introduction to Programming Languages and Compilers Fall 2010. Example internal DSLs. jQuery rfig rake. jQuery. Before jQuery var nodes = document.getElementsByTagName ('a'); - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Internal Domain-Specific Languages

1

Internal Domain-Specific Languages

Ras Bodik, Thibaud Hottelier, James IdeUC Berkeley

CS164: Introduction to Programming Languages and Compilers Fall 2010

Page 2: Internal Domain-Specific Languages

Example internal DSLs• jQuery• rfig• rake

2

Page 3: Internal Domain-Specific Languages

jQueryBefore jQuery

var nodes = document.getElementsByTagName('a'); for (var i = 0; i < nodes.length; i++) { var a = nodes[i]; a.addEventListener('mouseover', function(event)

{ event.target.style.backgroundColor=‘orange'; }, false ); a.addEventListener('mouseout', function(event)

{ event.target.style.backgroundColor=‘white'; }, false ); }

jQuery abstracts iteration and events

jQuery('a').hover( function() { jQuery(this).css('background-color', 'orange'); }, function() { jQuery(this).css('background-color', 'white'); } );

3

Page 4: Internal Domain-Specific Languages

rfig

4

Page 5: Internal Domain-Specific Languages

rfig: slide authoring DSLEmbedding a domain-specific language (DSL) into Ruby.

see slide 8 in http://cs164fa09.pbworks.com/f/01-rfig-tutorial.pdf

5…

Page 6: Internal Domain-Specific Languages

The animation in rfig, a Ruby-based language

slide!('Overlays',

'Using overlays, we can place things on top of each other.', 'The pivot specifies the relative positions', 'that should be used to align the objects in the overlay.',

overlay('0 = 1', hedge.color(red).thickness(2)).pivot(0, 0),

staggeredOverlay(true, # True means that old objects disappear 'the elements', 'in this', 'overlay should be centered',

nil).pivot(0, 0),

cr, pause, # pivot(x, y): -1 = left, 0 = center, +1 = right

staggeredOverlay(true, 'whereas the ones', 'here', 'should be right justified',

nil).pivot(1, 0), nil) { |slide| slide.label('overlay').signature(8) }

rfig was developed by Percy Liang, now a Berkeley student 6

Page 7: Internal Domain-Specific Languages

rake

7

Page 8: Internal Domain-Specific Languages

rake rake: an internal DSL, embedded in RubyAuthor: Jim Weirich

functionality similar to make– has nice extensions, and flexibility, since it's

embedded– ie can use any ruby commands

even the syntax is close (perhaps better):– embedded in Ruby, so all syntax is legal Ruby

http://martinfowler.com/articles/rake.html8

Page 9: Internal Domain-Specific Languages

Example rake filetask :codeGen do # do the code generationend

task :compile => :codeGen do #do the compilationend

task :dataLoad => :codeGen do # load the test dataend

task :test => [:compile, :dataLoad] do # run the testsend 9

Page 10: Internal Domain-Specific Languages

How to implement internal DSLs

First, define simple OO programming in 164.

Then we show how to build a jQuery like language

10

Page 11: Internal Domain-Specific Languages

Initial OO extensions to 164 def myObj = {} # build an objectmyObj.field = 3myObj.foo = lambda(self, a, b) { print self.field + a }myObj.foo(myObj,1,2)myObj:foo(1,2)

p:foo(x,y) desugars to p.foo(p,x,y)p.foo desugars to p[“foo”] 11

Page 12: Internal Domain-Specific Languages

164Query# usage: q('myklass'):fill('ivory2'):font('Helvetica 8')def Q = {} # empty Query objectQ.each = lambda(self,f) { for (n in preorder(window)) { if ("klass" in n) { if (n.klass == self.klass) { f(n) } } } # return the query object to allow call chaining self}def q(clss) { def query = copy(Q) query.klass=clss query}

12

Page 13: Internal Domain-Specific Languages

ContinuedQ.fill = lambda(self,color) { self:each(lambda(node) { node.fill = color }) }

Q.font = lambda(self,font) { self:each(lambda(node) { for (n in preorder(node)) { if (n:class() == Word) { n.font = font } } })}

13

Page 14: Internal Domain-Specific Languages

Example rake filetask :codeGen do # do the code generationend

task :compile => :codeGen do #do the compilationend

task :dataLoad => :codeGen do # load the test dataend

task :test => [:compile, :dataLoad] do # run the testsend 14

Page 15: Internal Domain-Specific Languages

How is rake legal ruby?Deconstructing rake (teaches us a lot about

Ruby):

task :dataLoad => :codeGen do # load the test dataend

task :test => [:compile, :dataLoad] do # run the testsend

15

Page 16: Internal Domain-Specific Languages

Two kinds of tasksFile task: dependences between files (like in

main)file 'build/dev/rake.html' => 'dev/rake.xml' do |t|

require 'paper' maker = PaperMaker.new t.prerequisites[0], t.name

maker.runend

16

Page 17: Internal Domain-Specific Languages

Two kinds of tasksRake task: dependences between jobs

task :build_refact => [:clean] do target = SITE_DIR + 'refact/' mkdir_p target, QUIET require 'refactoringHome' OutputCapturer.new.run {run_refactoring}end

17

Page 18: Internal Domain-Specific Languages

Orthogonalize dependences and rulestask :second do #second's bodyend

task :first do #first's bodyendtask :second => :first

18

Page 19: Internal Domain-Specific Languages

General rulesSort of like make's %.c : %.c

BLIKI = build('bliki/index.html')

FileList['bliki/*.xml'].each do |src|file BLIKI => src

end

file BLIKI do #code to build the blikiend

19