internal domain-specific languages

Post on 25-Feb-2016

69 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

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

1

Internal Domain-Specific Languages

Ras Bodik, Thibaud Hottelier, James IdeUC Berkeley

CS164: Introduction to Programming Languages and Compilers Fall 2010

Example internal DSLs• jQuery• rfig• rake

2

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

rfig

4

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…

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

rake

7

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

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

How to implement internal DSLs

First, define simple OO programming in 164.

Then we show how to build a jQuery like language

10

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

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

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

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

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

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

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

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

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

18

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

top related