mobl - model-driven engineering lecture

Post on 15-May-2015

2.383 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Zef Hemel

http://www.mobl-lang.org

230,000 300,000

Objective-C Java J2ME/C++

HTML/Javascript Java .NET

portability

Objective-C Java J2ME/C++

HTML/Javascript Java .NET

Webkit browser Webkit browser J2ME/C++

Webkit browser Webkit browser .NET

WebDatabases

WebDatabases

Location information (GPS)

WebDatabases

Location information (GPS)

Canvas

WebDatabases

Location information (GPS)

Canvas

Multi-touch

WebDatabases

Location information (GPS)

Canvas

Multi-touch

Offline support

WebDatabases

Location information (GPS)

Canvas

Multi-touch

Offline support

Full-screen support

WebDatabases

Location information (GPS)

Canvas

Multi-touch

Offline support

Full-screen support

Accelerator support

Address book

Address book

Camera

Address book

Camera

Compass

Address book

Camera

Compass

File IO

Address book

Camera

Compass

File IO

Audio

Address book

Camera

Compass

File IO

Audio

Notifications

mobl program

1. language

2. behind the scenes

today

language

user interface

styling

data modeling

scripting

web services

user interface

demo

screen name(farg*) : ReturnType? { screenelem*}

control name(farg*) { screenelem*}

ui syntax

screen root() { ...}

screen root() { ...}

screen promptString(q : String) : String { ...}

screen root() { ...}

screen promptString(q : String) : String { ...}

control button(s : String, onclick : Callback = {}) { ...}

control calls

variable declarations

inline HTML

script blocks

control structures

button("Click me")

control calls

button("Click me")

button("Click me", { alert("Click!");})

control calls

button("Click me")

button("Click me", { alert("Click!");})

button("Click me", onclick={ alert("Click!");})

control calls

group() { item() { "Item 1" } item() { "Item 2" }}

control calls with body

group { item { "Item 1" } item { "Item 2" }}

control calls with body

variable declarations

var b = true

variable declarations

var b = truevar b : Bool = true

variable declarations

var b = true

var newTask = Task()

var b : Bool = true

variable declarations

var b = true

var newTask = Task()

var b : Bool = true

var newTask : Task = Task()

when

var b = true

checkBox(b)

when(b) { label("Yep")} else { label("Nope")}

list

var nums = [1, 2, 3]

group { list(n in nums) { item { label(n) } }}

inline HTML

<img src="img/icon.png"/>

inline HTML

<img src="img/icon.png"/>

<div class=selected ? selectedStyle : notSelectedStyle> ...</div>

script blocks

var n = -1script { n = Math.sqrt(9);}

avoid if possible

higher-order controls

demo

styling

style bigAndBlue { color: blue; font-size: 40px;}

style bigAndBlue { color: blue; font-size: 40px;}

Style

control block(style : Style) { ...}

block(bigAndBlueStyle) { label("I am big and blue!");}

style $baseColor = rgb(100, 100, 100)

style myStyle { color: rgb($baseColor.r+10, $baseColor.g+50, $baseColor.b-20); font-size: 20px;}

style mixin borderRadiusMixin($radius) { -moz-border-radius: $radius; -webkit-border-radius: $radius; border-radius: $radius;}

style mixin borderRadiusMixin($radius) { -moz-border-radius: $radius; -webkit-border-radius: $radius; border-radius: $radius;}

style myStyle { color: $baseColor; borderRadiusMixin(10px);}

demo

data modeling& query

entity Task { name : String (searchable) done : Bool tags : Collection<Tag> (inverse: tasks)}

entity Tag { name : String (searchable) tasks : Collection<Task> (inverse: tags)}

var newTask = Task(name="New task");newTask.done = false;add(newTask);

var doneTasks = Task.all()

var doneTasks = Task.all()

Collection<Task>

var doneTasks = Task.all()

Collection<Task>

.filter("done", "=", true)

.order("date", false)

.limit(10);

var tagDoneTasks = tag.tasks .filter("done", "=", true) .order("date", false) .limit(10);

Collection<Task>

var doneTasks = Task.all()

Collection<Task>

var doneTasks = Task.all()

Collection<Task>

where done == trueorder by date desclimit 10;

var tagDoneTasks = tag.tasks where done == true order by date desc limit 10;

Collection<Task>

var searchTasks = Task.search("task") where done == true limit 10;

Collection<Task>

screen root() { header("Tasks") group { list(t in Task.all() order by date desc) { item { label(t.name) } } }}

scripting

label("Total tasks: " + Task.all().count())

script in ui

button("Click me", onclick={ alert("You clicked me!");})

label("Total tasks: " + Task.all().count())

script in ui

var n = 7;var n2 = Math.round(n/2);

if(n2 > 3) { alert("More than three!");} else { alert("Less than three!");}

var n = 7;var n2 = Math.round(n/2);

if(n2 > 3) { alert("More than three!");} else { alert("Less than three!");}

type inference

var done = 0;foreach(t in Task.all()) { if(t.done) { done = done + 1; }}

var done = 0;foreach(t in Task.all()) { if(t.done) { done = done + 1; }}

var done = (Task.all() where done == true) .count();

function sqr(n : Num) : Num { return n * n;}

demo: todo list

web serviceaccess

service SomeService { resource tasks() : JSON { uri = "/tasks" }

resource search(query : String) : JSON { uri = "/search?q=" + escape(query) }}

service Twitter { resource trends() : JSON { uri = "/_proxy/api.twitter.com/1/trends.json" }

resource search(query : String) : JSON { uri = "/_proxy/search.twitter.com/search.json?q=" + escape(query) }}

ajax same-source restriction

{"trends": [{"url":"http:\/\/search.twitter.com\/search?q=...", "name":"#ihaveadream"}, {"url":"http:\/\/search.twitter.com\/search?q=...", "name":"#mlkday"} ... ]}

http://api.twitter.com/1/trends.json

type Trend { name : String url : String}

function trendsMapper(json : JSON) : [Trend] { return json.trends;}

resource trends() : JSON { uri = "/_proxy/api.twitter.com/1/trends.json" mapper = trendsMapper}

screen root() { var trends = Twitter.trends()

header("Twitter trends") group { list(topic in trends) { item { label(topic.name) } } }}

user interface

styling

data modeling

scripting

web services

slower than native

no native UI

not great for games

limitations

behind the scenes

goals

coverage

portability

completeness

goals

coverage

portability

completeness

web

goals

coverage

portability

completeness 100% code gen

web

design bottom-up

1. design core abstractions + native interface

roadmap

1. design core abstractions + native interface

2. enable user land abstractions

roadmap

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

roadmap

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

3b. support common native interface cases with core abstractions

roadmap

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

3b. support common native interface cases with core abstractions

roadmap

synchronous programming

core abstraction:

no more asynchronous spaghetti code

var results = Task.all().list();for(var i = 0; i < results.length; i++) { alert(results[i].name);}

synchronous programming

render page

query database and process

results

...

time

render page

query database and process

results

...

timebrowser freeze

render page

send query

...

process query result

...

time

Task.all.list(function(results) { for(var i = 0; i < results.length; i++) { alert(results[i].name); } });...

asynchronous programming

Task.all().list(function(results) { alert("Hello, "); });alert("world!");

Task.all().list(function(results) { alert("Hello, "); });alert("world!");

breaks sequential execution assumption

Task.all().list(function(results) { // make changes ... persistence.flush(function() { alert("Changes saved!"); });});

continuation-passing styletransformation

function displayLocationAndReturn() : Coordinates { var position = mobl::location::getPosition(); log("Lat: " + position.latitude); log("Long: " + position.longitude); return position;}

function displayLocationAndReturn() : Coordinates { var position = mobl::location::getPosition(); log("Lat: " + position.latitude); log("Long: " + position.longitude); return position;}

function displayLocationAndReturn(callback) { mobl.location.getPosition(function(position) { console.log("Lat: " + position.latitude); console.log("Long: " + position.longitude); callback(position); });};

function displayLocationAndReturn() : Coordinates { var position = mobl::location::getPosition(); log("Lat: " + position.latitude); log("Long: " + position.longitude); return position;}

function displayLocationAndReturn(callback) { mobl.location.getPosition(function(position) { console.log("Lat: " + position.latitude); console.log("Long: " + position.longitude); callback(position); });};

function displayLocationAndReturn() : Coordinates { var position = mobl::location::getPosition(); log("Lat: " + position.latitude); log("Long: " + position.longitude); return position;}

function displayLocationAndReturn(callback) { mobl.location.getPosition(function(position) { console.log("Lat: " + position.latitude); console.log("Long: " + position.longitude); callback(position); });};

data bindingcore abstraction:

no more copying data from and to UI

screen root() { var n = 8 label(n * n) button("Inc", onclick={ n = n + 1; })}

var n = 8

var n = ref(8);

var n = 8

var n = ref(8);

Observable- set(value)- get()- addEventListener(eventType, callback)

label(n * n)

var node = $("<span>");node.text(n.get() * n.get());n.addEventListener("change", function() { node.text(n.get() * n.get());});root.append(node);

label(n * n)

var node = $("<span>");node.text(n.get() * n.get());n.addEventListener("change", function() { node.text(n.get() * n.get());});root.append(node);

label(n * n)

var node = $("<span>");node.text(n.get() * n.get());n.addEventListener("change", function() { node.text(n.get() * n.get());});root.append(node);

button("Inc", onclick={ n = n + 1;})

var node = $("<button ...>");node.text("Inc");node.click(function() { n.set(n.get() + 1);});root.append(node);

button("Inc", onclick={ n = n + 1;})

var node = $("<button ...>");node.text("Inc");node.click(function() { n.set(n.get() + 1);});root.append(node);

screen root() { var n = 8 label(n * n) button("Inc", onclick={ n = n + 1; })}

screen root() { var n = 8 label(n * n) button("Inc", onclick={ n = n + 1; })}

screen root() { var n = 8 label(n * n) button("Inc", onclick={ n = n + 1; })}

data modeling & query

core abstraction:

no more SQL

uses persistence.jshttp://persistencejs.org

entity Task { name : String (searchable) description : String (searchable) done : Bool date : DateTime}

var Task = persistence.define('Task', { name: 'VARCHAR(255)', description: 'VARCHAR(255)', done: 'BOOL', date: 'DATE'});

Task.textIndex('description');Task.textIndex('name');

foreach(t in Task.all()) { alert(t.name);}

Task.all().forEach(function(t) { alert(t.name);});

foreach(t in Task.all() where done == true) { alert(t.name);}

Task.all().filter("done", "=", true).forEach(function(t) { alert(t.name);});

native interface

external entity MyEntity

external control contextMenu()

external screen specialScreen()

external sync function add(o : Object) : void

external style myStyle

external type MyType

external sync function add(o : Object) : void

<javascript>__ns.add = function(o) { persistence.add(o);};</javascript>

load styles/default.cssload js/persistence.js

where do abstractions come from?

where do abstractions come from?

domain

where do abstractions come from?

domain

experience

domain

domain

screen

domain

screen

control

domain

screen

control

entity

domain

screen

control

entity

event

domain

screen

control

entity

event web service

experience

experience

other DSLs

experience

programming paradigms

other DSLs

experience

programming paradigms

annoyancesother DSLs

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

3b. support common native interface cases with core abstractions

roadmap

goal

compiler small

library large (and extensible)

how?

- built-in types- built-in controls

+ native interface+ sufficiently low-level primitives+ abstraction mechanisms (screens, controls, functions, types)

native interfaceexternal type Object { sync function toString() : String}

external type String : Object { length : Num sync function charAt(index : Num) : String sync function charCodeAt(index : Num) : Num ...}

external type Num : Object { }external type Bool : Object { }external type Dynamic : Object { }external type Style : String { }

external type Array<T> { length : Num

sync function get(n : Num) : T sync function push(item : T) : void sync function join(sep : String) : String ...}

control image(url : String, onclick : Callback = null) { <img src=url onclick=onclick/>}

low-level primitives

control slideupBlock() { div@<div onclick={ div.slideUp(); }> elements() </div>}

...

slideupBlock { label("Click me to slide up")}

low-level primitives

control slideupBlock() { div@<div onclick={ div.slideUp(); }> elements() </div>}

...

slideupBlock { label("Click me to slide up")}

low-level primitives

JQuery

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

3b. support common native interface cases with core abstractions

roadmap

var doneTasks = Task.all()

var doneTasks = Task.all().filter("done", "=", true).order("date", false).limit(10);

var doneTasks = Task.all()

var doneTasks = Task.all()where done == trueorder by date desclimit 10;

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

3b. support common native interface cases with core abstractions

roadmap

load styles/default.css

div.header { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(72, 100, 180)), to(rgb(32, 60, 140))); background: -moz-linear-gradient(top, rgb(72, 100, 180), rgb(32, 60, 140)); padding: 0; height: 2.3em; font-size: 1.3em; line-height: 2.3em; font-weight: bold; text-align: center; text-shadow: #477 0px 1px 1px; color: white; font-weight: bold; margin: 0; z-index: 2;}

issue

out of sight,out of mind no checking

<div class="headerr"></div>

little abstraction

div.header { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(72, 100, 180)), to(rgb(32, 60, 140))); background: -moz-linear-gradient(top, rgb(72, 100, 180), rgb(32, 60, 140)); padding: 0; height: 2.3em; font-size: 1.3em; line-height: 2.3em; font-weight: bold; text-align: center; text-shadow: #477 0px 1px 1px; color: white; font-weight: bold; margin: 0; z-index: 2;}

little abstraction

div.header { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(72, 100, 180)), to(rgb(32, 60, 140))); background: -moz-linear-gradient(top, rgb(72, 100, 180), rgb(32, 60, 140)); padding: 0; height: 2.3em; font-size: 1.3em; line-height: 2.3em; font-weight: bold; text-align: center; text-shadow: #477 0px 1px 1px; color: white; font-weight: bold; margin: 0; z-index: 2;}

mixins

1. design core abstractions + native interface

2. enable user land abstractions

3a. support successful ULAs with syntax

3b. support common native interface cases with core abstractions

http://www.mobl-lang.org

top related