71
Eelco Visser Zef Hemel @mobllang @zef @eelcovisser Slides from keynote at MOSE 2010, Malaga, June 29, 2010

mobl

Embed Size (px)

DESCRIPTION

slides from keynote for MOSE 2010 in Malaga on June 29, 2010

Citation preview

Page 1: mobl

Eelco VisserZef Hemel

@mobllang @zef @eelcovisser

Slides from keynote at MOSE 2010, Malaga, June 29, 2010

Page 2: mobl

Domain-Specific Language Engineering

WebDSL

SpoofaxSDF Stratego

Page 3: mobl

domain:mobile applications

Page 4: mobl

50 million

iPhones

20 million

iPod Touches

Page 5: mobl

1.5 million

G1

1.2 million

Droid

outsells iPhone in US

Page 6: mobl
Page 7: mobl

applicationdevelopment

Page 8: mobl

Objective-C Java J2ME/C++

HTML/Javascript Java

Page 9: mobl

Objective-C

Android Java

Blackberry Java

J2ME

HTML/JS

Page 10: mobl
Page 11: mobl

3.3.1

Page 12: mobl

3.3.1 – Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

Page 13: mobl
Page 14: mobl

AppStore

Page 15: mobl
Page 16: mobl

cross-platform development

arbitrary rejections

we want high-level models

Page 17: mobl
Page 18: mobl

Webkit

Page 19: mobl

HTML

Page 20: mobl

WebDatabases

Location information (GPS)

Threading

Canvas

WebDatabases

Multi-touch

Offline support

Full-screen support

Page 21: mobl
Page 22: mobl

We believe the web has won and over the next several years, the browser [..] will become the platform that matters and certainly that’s where Google is investing.

“ ”Vic Gundotra, Google VP of Engineering

Page 23: mobl
Page 24: mobl
Page 25: mobl

syntax similar to

Page 26: mobl

data model

user interface

script

web service access

Page 27: mobl

data model

Page 28: mobl

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

Page 29: mobl

entity Task { name : String (searchable) done : Bool dueDate : DateTime categories : Collection<Category>}

entity Category { name : String tasks : Collection<Task> (inverse: categories)}

Page 30: mobl

user interface

Page 31: mobl

screen root() { header("Todo") group { list(t in Task.all()) { item { checkbox(t.done) " " label(t.name) } } }}

Page 32: mobl

screen root() { header("Todo") topButton("Add", onclick={ addTask(); }) group { list(t in Task.all()) { item { checkbox(t.done) " " label(t.name) } } }}

Page 33: mobl

screen addTask() { var newTask = Task { done = false, dueDate = now() }

header("Add") backButton("Back", onclick={ screen return; }) group { item { textField(newTask.name) } item { datePicker(newTask.dueDate) } } button("Add", onclick={ add(newTask); screen return; })}

Page 34: mobl

screen root() { header("Todo") topButton("Add", onclick={ addTask(); }) group { list(t in Task.all()) { item { checkbox(t.done) " " label(t.name) } } }}

Page 35: mobl

screen root() { var query = ""

header("Todo") topButton("Add", onclick={ addTask(); }) searchBox(query) group { list(t in Task.search(query)) { item { checkbox(t.done) " " label(t.name) } } }}

Page 36: mobl

scripting

Page 37: mobl

function cleanDoneTasks() : Num { var removed = 0; for(t in Task.all()) { if(t.done) { remove(t); removed = removed + 1; } } return removed;}

Page 38: mobl

data binding

Page 39: mobl

var n = 0

label(n)

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

one-way

Page 40: mobl

var n = 0

inputNum(n)label(n)

two-way

Page 41: mobl

reactive/dataflow programming

Page 42: mobl
Page 43: mobl

var amount = 10var percentage = 10var total <- amount * (1 + percentage/100)

inputNum(amount)inputNum(percentage)label(total)

Page 44: mobl

web services

Page 45: mobl
Page 46: mobl
Page 47: mobl

{ "total": 746646, "page": 1, "pagesize": 30, "questions": [ { "tags": ["string", "assembly", "arm"], "answers": [], "question_id": 3092029, "owner": { "user_id": 320124, "user_type": "registered", "display_name": "SoulBeaver", "reputation": 195 }, "creation_date": 1277200629, "score": 0, "title": "ARM - Infinite Loop While Searching String", "body": "...", ... }, ... ]}

http://api.stackoverflow.com/0.8/questions?answers=true&body=true

Page 48: mobl

{ "total": 746646, "page": 1, "pagesize": 30, "questions": [ { "tags": ["string", "assembly", "arm"], "answers": [], "question_id": 3092029, "owner": { "user_id": 320124, "user_type": "registered", "display_name": "SoulBeaver", "reputation": 195 }, "creation_date": 1277200629, "score": 0, "title": "ARM - Infinite Loop While Searching String", "body": "...", ... }, ... ]}

external type QuestionsResultSet { total : Num page : Num pagesize : Num questions : Array<QuestionResult>}

Page 49: mobl

{ "tags": ["string", "assembly", "arm"], "answers": [], "question_id": 3092029, "owner": { "user_id": 320124, "user_type": "registered", "display_name": "SoulBeaver", "reputation": 195 }, "creation_date": 1277200629, "score": 0, "title": "ARM - Infinite Loop While Searching String", "body": "...", ...}

external type QuestionResult { tags : Array<String> answers : Array<AnswerResult> owner : OwnerResult creation_date : Num ...}

Page 50: mobl

service StackOverflow { root = "http://api.stackoverflow.com/0.8" resource questions(answers : Bool, body : Bool) : QuestionsResultSet { uri = "/questions" method = "GET" encoding = "json" } ...}

Page 51: mobl

function fetchQuestions() { var res = StackOverflow.questions(answers=true, body=true); for(question : QuestionResult in res.questions) { mapQuestion(question); }}

Page 52: mobl

entity Question { questionId : Num title : String body : Text answers : Collection<Answer> (inverse: question) creationDate : DateTime owner : User}

entity Answer { question : Question answerId : Num owner : User body : Text}

entity User { userId : Num name : String reputation : Num}

Page 53: mobl

function mapQuestion(qr : QuestionResult) : Question { var q : Question = cachedQuestion(remote.question_id); if(q == null) { q = Question { questionId = qr.question_id, title = qr.title, body = qr.body, answers = mapAnswers(qr.answers), creationDate = DateTime.fromTimestamp(qr.creation_date), owner = mapUser(qr.owner) }; add(q); } return q;}

Page 54: mobl
Page 55: mobl

implementation

Page 56: mobl

parse

check

desugar

generate code

mobl code

HTML/Javascript

Page 57: mobl

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

tasks.Task = persistence.define('tasks__Task', { 'name': 'TEXT', 'done': 'BOOL', 'dueDate': 'DATE'});tasks.Task.textIndex('name');

Javascript usingpersistence.js

HTML5 ORM

Page 58: mobl

screen root() { header("Todo") ...}

tasks.root = function(callback, screenCallback) { var root1018 = $("<div>"); mobl.header(ref("Todo"), function(node) { root1018.append(node); ... });};

Javascript functions building DOM

Page 59: mobl

function cleanDoneTasks() : Num { var removed = 0; for(t in Task.all()) { if(t.done) { remove(t); removed = removed + 1; } } return removed;}

tasks.cleanDoneTasks = function() { var removed = 0; var results = Task.all(); for(var i = 0; i < results.length; i++) { var t = results[i]; if(t.done) { remove(t); removed = removed + 1; } } return removed;}

Page 60: mobl

function cleanDoneTasks() : Num { var removed = 0; for(t in Task.all()) { if(t.done) { remove(t); removed = removed + 1; } } return removed;}

tasks.cleanDoneTasks = function() { var removed = 0; var results = Task.all(); for(var i = 0; i < results.length; i++) { var t = results[i]; if(t.done) { remove(t); removed = removed + 1; } } return removed;};

Page 61: mobl

tasks.cleanDoneTasks = function(callback) { var removed = 0; Task.all(function(results) { for(var i = 0; i < results.length; i++) { var t = results[i]; if(t.done) { remove(t); removed = removed + 1; } } callback(removed); });};

tasks.cleanDoneTasks = function() { var removed = 0; var results = Task.all(); for(var i = 0; i < results.length; i++) { var t = results[i]; if(t.done) { remove(t); removed = removed + 1; } } return removed;};

continuation-passing style transform

Page 62: mobl

reactive programming

Page 63: mobl

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

Page 64: mobl

var n = 8

var n = ref(8);

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

Page 65: mobl

label(n * n)

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

Page 66: mobl

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

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

Page 67: mobl

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

Page 68: mobl

conclusion

Page 69: mobl

many mobile platforms

HTML5/JS

avoid AppStore approval

Page 70: mobl

statically-typed WebDSL-like language

generates HTML/JS

CPS transform/reactive programming