software language design & engineering
Post on 05-Dec-2014
1.223 Views
Preview:
DESCRIPTION
TRANSCRIPT
Eelco Visserhttp://eelcovisser.org
Software Language Design & Engineering
Zürich, May 12, 2011
bridging the gap between problem domain and solution domain
Software Engineering
ProblemDomain Machine
HLLs reduce gap
High-Level Languages
ProblemDomain HLL Machine
domain-specific languages support more specialization
Domain-Specific Languages
ProblemDomain HLL MachineDSL
domain-specific languages support more specialization
Domain-Specific Languages
ProblemDomain HLL MachineDSL
Even Higher-Level
Languages
Software Language Design & Engineering
enable software engineers to effectively design, implement, and apply domain-specific
software languages
Research: Software Language Design
Systematically design domain-
specific software languages with optimal tradeoff between expressivity,
completeness, portability, coverage, and maintainability
expressivity: fewer irrelevant details => concisenesscoverage: which portion of domain can we express
Expressivity vs Coverage
Software Language Design Case Studies
Mobl: client-side stateful web applications
WebDSL: server-side restful web applications
Native Applications not Portable
Divergence in Mobile Platforms
Objective-C Java J2ME/C++
HTML/Javascript Java .NET
Convergence in Mobile Platform
Webkit browser
Webkit browser
Webkit browser
Webkit browser
The Universal Userinterface Engine
Mobile Web Architecture
Rich Applications
WebDatabases
Location information (GPS)
Canvas
Multi-touch
Offline support
Full-screen support
Accelerator support
Audio
Native Applications
Address book
Camera
Compass
File IO
Notifications
MVC, No Integration, No Abstraction, Accidental Complexity
Software Engineering with JavaScript
annotated HTML imperative Javascript
declarativetyped
integrated concise
Web Application with Touch
Portable Applications
Mobl Architecture
tipcalculator.mobl
application tipcalculator
import mobl::ui::generic
screen root() { var amount = 20 var percentage = 10 header("Tip calculator") group { item { numField(amount, label="amount") } item { numField(percentage, label="percentage") } item { "$" label(Math.round(amount * (1 + percentage/100))) } } nl()}
Model-View Pattern
Task Manager
HTML5 Data Persistence
Data Model
entity Task { name : String (searchable) done : Bool due : DateTime category : Category (inverse: tasks) tags : Collection<Tag> (inverse: tasks)}entity Category { name : String tasks : Collection<Task> (inverse: category)}entity Tag { name : String tasks : Collection<Task> (inverse: tags)}
statically typed: catch errors early
Logic
entity Task { name : String (searchable) done : Bool due : DateTime category : Category (inverse: tasks) tags : Collection<Tag> (inverse: tasks) function postpone(days : Num) { this.due = DateTime.create( this.due.getFullYear(), this.due.getMonth(), this.due.getDate() + days); } function import(user : String, pw : String) { var tasksJSON = httpRequest("/export?user="+ user + "&pw=" + pw); foreach(t in tasksJSON) { add(Task.fromSelectJSON(t)); } }}
screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}
Reactive User Interfaces
screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}
Reactive User Interfaces
screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}
Navigation
screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}
screen addTask() { var t = Task() header("Add") { button("Done", onclick={ add(t); screen return; }) } textField(t.name) datePicker(t.due)}
Navigation
screen root() { var phrase = "" header("Tasks") { button("Add", onclick={ addTask(); }) } searchBox(phrase) group { list(t in Task.search(phrase) limit 20){ item { checkBox(t.done, label=t.name) } } }}
Navigation
Continuations
screen root() { button("Ask", onclick={ alert("Hello " + prompt("First name") + " " + prompt("Last name")); })}screen prompt(question : String) : String { var answer = "" header(question) { button("Done", onclick={ screen return answer; }) } textField(answer)}
User Interface Idiom: Tab
control tab1() { header("Tab 1") label("This is tab 1")}control tab2() { header("Tab 2") label("This is tab 2")}screen root() { tabSet([("One", tab1), ("Two", tab2)], defaultTab="One")}
increase coverage: developers can create abstractions
Tab Set: Higher-Order Control
control tabSet(tabs : [(String,Control)], activeTab : String) { list((tabName, tabControl) in tabs) { block(onclick={ activeTab = tabName; }, style=activeTab==tabName ? activeTabButton : inactiveTabButton) { label(tabName) } } list((tabName, tabControl) in tabs) { block(activeTab==tabName ? visibleTab : invisibleTab) { tabControl() } }}
User Interface Idiom: Master Detail
control taskItem(t : Task) { checkBox(t.done, label=t.name)}control taskDetail(t : Task) { textField(t.name) datePicker(t.due)}screen root() { header("Tasks") masterDetail(Task.all() order by due desc, taskItem, taskDetail)}
User Interface Idiom: Master Detail
control taskItem(t : Task) { checkBox(t.done, label=t.name)}control taskDetail(t : Task) { textField(t.name) datePicker(t.due)}screen root() { header("Tasks") masterDetail(Task.all() order by due desc, taskItem, taskDetail)}
Master Detail: Higher-Order Control
control masterDetail(items : Collection<?>, masterItem : Control1<?>, detail : Control1<?>) { group { list(it in items) { item(onclick={ detailScreen(it,detail); }) { masterItem(it) } } }}screen detailScreen(it : ?, detail : Control1<?>) { header("Detail") { backButton() } detail(it)}
Mobl Applications
GR8 Conference Program
mPodder
static cross-concern consistency checking
Mobl IDE
Research: Software Language Engineering
Automatically derive efficient, scalable, incremental compiler +
usable IDE from high-level,
declarative language definition
creating full featured IDEs for domain-specific languages
The Spoofax Language Workbench
an IDE for developing languages and their IDEs
The Spoofax Language Workbench
Integrated Language Definition Testing
The Spoofax Language Workbench
Syntax Definition
module MoBL-Data
imports Common MoBL
exports context-free syntax MetaAnno* "entity" QId ":" Type "{" Property* "}" -> Definition {cons("Entity")} MetaAnno* "entity" QId "{" Property* "}" -> Definition {cons("EntityNoSuper")} MetaAnno* ID ":" Type "(" {Anno ","}* ")" -> Property {cons("Property")} MetaAnno* ID ":" Type -> Property {cons("PropertyNoAnnos")} ID -> Anno {cons("SimpleAnno")} "inverse" ":" ID -> Anno {cons("InverseAnno")}
context-free syntax "@sync" UriPath -> MetaAnno {cons("SyncEntityAnno")}
Type Checking
rules
constraint-error : t@SimpleType(_) -> (t, $[Type is not defined: [<pp-mobl-type> t]]) where not(<lookup-type> t)
constraint-error : t@FieldAccess(e, x) -> (t, $[Property [x] not defined]) where <type-of> e where not(type-of)
Code Generation
rules property-to-js(|ent) : Property(_, x, t@SimpleType(_), anno*) -> $['[x]': '[sqlType]'] where not(<is-entity-type> t) with sqlType := <sql-type> t ; if [_] := <filter(?SimpleAnno("searchable"))> anno* then rules ( SearchableProperties :+= (ent, x) ) end
http://researchr.org/search/publication/mobl+spoofax+webdsl
Software Language Design & Engineering
http://eelcovisser.org
http://spoofax.org
http://mobl-lang.org
http://webdsl.org
http://researchr.org
Language Design as Engineering Discipline
(More) Declarative Language Definition
Static Analysis of Language Definitions
Language Workbench in the Cloud
top related