KEMBAR78
mobl - model-driven engineering lecture | PDF
http://www.mobl-lang.org


Zef Hemel
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)
                       Offline support
      Canvas

  Multi-touch
WebDatabases
                 Full-screen support
Location information
       (GPS)
                       Offline support
      Canvas

  Multi-touch
WebDatabases
                 Full-screen support
Location information
       (GPS)
                       Offline support
      Canvas
                 Accelerator support
  Multi-touch
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
today
1. language

2. behind the scenes
language
user interface

   styling

data modeling

  scripting

web services
user interface
demo
ui syntax


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


control name(farg*) {
  screenelem*
}
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

  control structures

      inline HTML


      script blocks
control calls
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 with body


  group() {
    item() { "Item 1" }
    item() { "Item 2" }
  }
control calls with body


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

var b = true
variable declarations

var b = true
var b : Bool = true
variable declarations

var b = true
var b : Bool = true
var newTask = Task()
variable declarations

var   b = true
var   b : Bool = true
var   newTask = Task()
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
         avoid if possible



var n = -1
script {
  n = Math.sqrt(9);
}
higher-order controls
demo
styling
style bigAndBlue {
  color:     blue;
  font-size: 40px;
}
Style
style bigAndBlue {
  color:      blue;
  font-size: 40px;
}
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()
Collection<Task>
var doneTasks = Task.all()
Collection<Task>
var doneTasks = Task.all()
                .filter("done", "=", true)
                .order("date", false)
                .limit(10);
Collection<Task>
var tagDoneTasks = tag.tasks
                .filter("done", "=", true)
                .order("date", false)
                .limit(10);
Collection<Task>
var doneTasks = Task.all()
Collection<Task>
var doneTasks = Task.all()
                where done == true
                order by date desc
                limit 10;
Collection<Task>
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;
screen root() {
  header("Tasks")
  group {
    list(t in Task.all() order by date desc) {
      item { label(t.name) }
    }
  }
}
scripting
script in ui


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


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


button("Click me", onclick={
   alert("You clicked me!");
})
var n = 7;
var n2 = Math.round(n/2);

if(n2 > 3) {
  alert("More than three!");
} else {
  alert("Less than three!");
}
type inference
var n = 7;
var n2 = Math.round(n/2);

if(n2 > 3) {
  alert("More than three!");
} else {
  alert("Less than three!");
}
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 service
  access
service SomeService {
  resource tasks() : JSON {
    uri = "/tasks"
  }

    resource search(query : String) : JSON {
      uri = "/search?q=" + escape(query)
    }
}
ajax same-source restriction


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)
    }
}
http://api.twitter.com/1/trends.json


{"trends":
  [{"url":"http://search.twitter.com/search?q=...",
     "name":"#ihaveadream"},
    {"url":"http://search.twitter.com/search?q=...",
     "name":"#mlkday"}
    ...
  ]
}
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
limitations


slower than native


   no native UI


not great for games
behind the scenes
goals


 portability


completeness


  coverage
goals


 portability   web


completeness


  coverage
goals


 portability   web


completeness   100% code gen


  coverage
design bottom-up
roadmap
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
core abstraction:

synchronous programming


      no more asynchronous
          spaghetti code
synchronous programming


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




                 time
query database
 and process
    results




      ...
render page




                                  time
                 query database
browser freeze    and process
                     results




                       ...
render page

 send query




                time
     ...


process query
    result


     ...
asynchronous programming


Task.all.list(function(results) {
    for(var i = 0; i < results.length; i++) {
       alert(results[i].name);
    }
  });
...
Task.all().list(function(results) {
  alert("Hello, ");
});
alert("world!");
Task.all().list(function(results) {
  alert("Hello, ");
});                      breaks sequential
alert("world!");
                     execution assumption
Task.all().list(function(results) {
  // make changes
  ...
  persistence.flush(function() {
    alert("Changes saved!");
  });
});
continuation-passing style
     transformation
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);
   });
};
core abstraction:

 data binding

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;
  })
}
core abstraction:

data modeling & query



       no more SQL
uses persistence.js
  http://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 type MyType

external control contextMenu()

external screen specialScreen()

external sync function add(o : Object) : void

external style myStyle
external sync function add(o : Object) : void

<javascript>
__ns.add = function(o) {
    persistence.add(o);
};
</javascript>
load styles/default.css
load js/persistence.js
where do abstractions
    come from?
where do abstractions
    come from?

        domain
where do abstractions
    come from?

        domain

      experience
domain
screen



         domain
control

screen



         domain
control

screen              entity



         domain
control

screen              entity



         domain

 event
control

screen                 entity



         domain

 event              web service
experience
other DSLs



         experience
other DSLs



         experience


             programming
              paradigms
other DSLs                 annoyances



         experience


             programming
              paradigms
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
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 interface
external 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
    ...
}
low-level primitives


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() {
JQuery div@<div onclick={
          div.slideUp();
       }>
          elements()
       </div>
     }

      ...

      slideupBlock {
        label("Click me to slide up")
      }
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
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 == true
                order by date desc
                limit 10;
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
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,
                        no checking
out of mind


    <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 {                                             mixins
  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;
}
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

mobl - model-driven engineering lecture