Commit b0751ec2 authored by Nicolas Biri's avatar Nicolas Biri

Add Mapping model

parent 336ff38f
v0.8:
- Add a JSMF Mapping model, to log transformation
v0.7:
- ES6 migration
v0.6:
......
var JSTL = require('../../index'); var Transformation= JSTL.Transformation;
var JSTL = require('../../src/index'); var Transformation= JSTL.Transformation;
var JSMF = require('jsmf-core'); var Model = JSMF.Model; var Class = JSMF.Class;
//Load the metamodels (in one file for the example)
......
......@@ -10,7 +10,7 @@ Authors : Nicolas Biri
'use strict'
// model imports
const JSTL = require('../../index')
const JSTL = require('../../src/index')
const Transformation = JSTL.Transformation
const NAV = require('jsmf-magellan')
const Model = require('jsmf-core').Model
......@@ -24,99 +24,111 @@ const MMI = require('./MMArduinoML')
const MMO = require('./MMAbstractCode')
// input file
const input = require('./MArduinoML').switchExample
const input = require('./MArduinoML').Switch
const output = new Model('Out')
const transfo = new Transformation()
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
var app = MMO.App.newInstance()
this.assign(app, 'structural', [i])
this.assign(app, 'behavioural', [i])
return [app]
}
const arduinoToCode = new Transformation()
arduinoToCode.addRule({
name: 'Arduino App to Code App',
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
const app = MMO.App.newInstance()
this.assign(app, 'structural', [i])
this.assign(app, 'behavioural', [i])
return [app]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
var s = MMO.StructuralConcerns.newInstance()
this.assign(s, 'alias', i.brick)
this.assign(s, 'pinMode', i.brick)
return [s]
}
arduinoToCode.addRule({
name: 'Structural concerns generation',
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
const s = MMO.StructuralConcerns.newInstance()
this.assign(s, 'alias', i.brick)
this.assign(s, 'pinMode', i.brick)
return [s]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Brick, x),
out: function(i) {
return [MMO.BrickAlias.newInstance({name: i.name, pin: i.pin})]
}
arduinoToCode.addRule({
name: 'Brick Alias generation',
in: x => NAV.allInstancesFromModel(MMI.Brick, x),
out: function(i) {
return [MMO.BrickAlias.newInstance({name: i.name, pin: i.pin})]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Sensor, x),
out: function(i) {
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.INPUT})]
}
arduinoToCode.addRule({
name: 'Pin mode definition for sensors',
in: x => NAV.allInstancesFromModel(MMI.Sensor, x),
out: function(i) {
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.INPUT})]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Actuator, x),
out: function(i) {
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.OUTPUT})]
}
arduinoToCode.addRule({
name: 'Pin mode definition for actuators',
in: x => NAV.allInstancesFromModel(MMI.Actuator, x),
out: function(i) {
return [MMO.PinMode.newInstance({name: i.name, mode: MMO.IO.OUTPUT})]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
var b = MMO.BehaviouralConcerns.newInstance()
b.timeConfig = MMO.TimeConfig.newInstance({initialTime: 0, debounce: 200})
this.assign(b, 'stateFunction', i.state)
this.assign(b, 'mainLoop', i.initial)
return [b]
}
arduinoToCode.addRule({
name: 'Behavioural concerns generation',
in: x => NAV.allInstancesFromModel(MMI.App, x),
out: function(i) {
const b = MMO.BehaviouralConcerns.newInstance()
b.timeConfig = MMO.TimeConfig.newInstance({initialTime: 0, debounce: 200})
this.assign(b, 'stateFunction', i.state)
this.assign(b, 'mainLoop', i.initial)
return [b]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.State, x),
out: function(i) {
var t = i.transition[0]
var s = MMO.StateFunction.newInstance({
name: i.name,
next: t.next[0].name,
readOn: t.sensor[0].name,
read: t.value
})
this.assign(s, 'write', i.action)
return [s]
}
arduinoToCode.addRule({
name: 'Generate state function',
in: x => NAV.allInstancesFromModel(MMI.State, x),
out: function(i) {
const t = i.transition[0]
const s = MMO.StateFunction.newInstance({
name: i.name,
next: t.next[0].name,
readOn: t.sensor[0].name,
read: t.value
})
this.assign(s, 'write', i.action)
return [s]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.State, x),
out: function(i) {
return [MMO.MainLoop.newInstance({ init: i.name })]
}
arduinoToCode.addRule({
name: 'Generate main loop',
in: x => NAV.allInstancesFromModel(MMI.State, x),
out: function(i) {
return [MMO.MainLoop.newInstance({ init: i.name })]
}
})
transfo.addRule({
in: x => NAV.allInstancesFromModel(MMI.Action, x),
out: function(i) {
return [MMO.Write.newInstance({
on: i.actuator[0].name,
value: i.value
})]
}
arduinoToCode.addRule({
name: 'Ganarate Writes',
in: x => NAV.allInstancesFromModel(MMI.Action, x),
out: function(i) {
return [MMO.Write.newInstance({
on: i.actuator[0].name,
value: i.value
})]
}
})
// launch transformation
const log = transfo.apply(input, output, false)
const mapping = arduinoToCode.apply(input, output, true)
module.exports = {arduinoToCode, mapping}
_.forEach(NAV.allInstancesFromModel(MMO.App, output), x => console.log(x.toCode()))
_.forEach( NAV.allInstancesFromModel(MMO.App, output)
, x => console.log(x.toCode()))
'use strict';
var AML = require('./MMArduinoML')
var Model;
const AML = require('./MMArduinoML.js')
const Model = require('jsmf-core').Model
(function() {
var JSMF = require('jsmf-core');
Model = JSMF.Model;
}).call();
var switchExample = new Model('Switch!');
switchExample.setReferenceModel(AML.ArduinoML);
var button = AML.Sensor.newInstance({name: 'button', pin: 9});
switchExample.add(button);
var led = AML.Actuator.newInstance({name: 'led', pin: 13});
switchExample.add(led);
const button = AML.Sensor.newInstance({name: 'button', pin: 9})
const led = AML.Actuator.newInstance({name: 'led', pin: 12})
/*
* on state
*/
var aOn = AML.Action.newInstance({value: AML.Signal.HIGH, actuator: led});
switchExample.add(aOn);
var tOn = AML.Transition.newInstance({value: AML.Signal.LOW, sensor: button});
switchExample.add(tOn);
var on = AML.State.newInstance({name: 'on', action: aOn, transition: tOn})
switchExample.add(on);
const aOn = AML.Action.newInstance({value: AML.Signal.HIGH, actuator: led})
const tOn = AML.Transition.newInstance({value: AML.Signal.HIGH, sensor: button})
const on = AML.State.newInstance({name: 'on'})
on.action = aOn
on.transition = tOn
/*
* off state
*/
var aOff = AML.Action.newInstance({value: AML.Signal.LOW, actuator: led});
switchExample.add(aOff);
var tOff = AML.Transition.newInstance({value: AML.Signal.LOW, sensor: button});
switchExample.add(tOff);
var off = AML.State.newInstance({name: 'off', action: aOff, transition: tOff})
switchExample.add(off);
const aOff = AML.Action.newInstance({value: AML.Signal.LOW, actuator: led})
const tOff = AML.Transition.newInstance({value: AML.Signal.HIGH, sensor: button})
const off = AML.State.newInstance({name: 'off'})
off.action = aOff
off.transition = tOff
/*
* set transitions
*/
tOn.next = off;
tOff.next = on;
tOn.next = off
tOff.next = on
/*
* define app
*/
var switchApp = AML.App.newInstance({
name: 'Switch!',
brick: [button, led],
state: [on, off],
initial: off
});
switchExample.add(switchApp);
const switchApp = AML.App.newInstance({
name: 'Switch!',
bricks: [button, led],
states: [on, off],
initial: off
})
const Switch = new Model('Switch', AML.ArduinoML, switchApp, true)
module.exports = {
switchExample: switchExample,
switchApp: switchApp
Switch: Switch,
switchApp: switchApp
}
'use strict';
'use strict'
var _ = require('lodash');
const _ = require('lodash')
const JSMF = require('jsmf-core')
var Class, Model, Enum;
let Class, Model, Enum
var JSMF = require('jsmf-core');
(function() {
Model = JSMF.Model;
Class = JSMF.Class;
Enum = JSMF.Enum;
}).call();
Model = JSMF.Model
Class = JSMF.Class
Enum = JSMF.Enum
}).call()
var App = Class.newInstance('App');
const App = Class.newInstance('App')
var IO = new Enum('IO', ['INPUT', 'OUTPUT']);
var Signal = new Enum('Signal', ['LOW', 'HIGH']);
const IO = new Enum('IO', ['INPUT', 'OUTPUT'])
const Signal = new Enum('Signal', ['LOW', 'HIGH'])
var StructuralConcerns = Class.newInstance('StructuralConcerns');
App.setReference('structural', StructuralConcerns, 1);
const StructuralConcerns = Class.newInstance('StructuralConcerns')
App.setReference('structural', StructuralConcerns, 1)
var BrickAlias = Class.newInstance('BrickAlias', [], {name: String, pin: JSMF.Range(0,13)});
StructuralConcerns.setReference('alias', BrickAlias, -1);
const BrickAlias = Class.newInstance('BrickAlias', [], {name: String, pin: JSMF.Range(0,13)})
StructuralConcerns.setReference('alias', BrickAlias, -1)
var PinMode = Class.newInstance('PinMode', [], {name: String, mode: IO});
StructuralConcerns.setReference('pinMode', PinMode, -1);
const PinMode = Class.newInstance('PinMode', [], {name: String, mode: IO})
StructuralConcerns.setReference('pinMode', PinMode, -1)
var BehaviouralConcerns = Class.newInstance('BehaviouralConcerns');
App.setReference('behavioural', BehaviouralConcerns, 1);
const BehaviouralConcerns = Class.newInstance('BehaviouralConcerns')
App.setReference('behavioural', BehaviouralConcerns, 1)
var TimeConfig = Class.newInstance('TimeConfig', [], {initialTime: Number, debounce: Number});
BehaviouralConcerns.setReference('timeConfig', TimeConfig, 1);
const TimeConfig = Class.newInstance('TimeConfig', [], {initialTime: Number, debounce: Number})
BehaviouralConcerns.setReference('timeConfig', TimeConfig, 1)
var StateFunction = Class .newInstance(
const StateFunction = Class .newInstance(
'StateFunction',
[],
{name: String, readOn: String, read: Signal, next: String}
);
BehaviouralConcerns.setReference('stateFunction', StateFunction, -1);
)
BehaviouralConcerns.setReference('stateFunction', StateFunction, -1)
var Write = Class.newInstance('Write', [], {on: String, value: Signal});
StateFunction.setReference('write', Write, -1);
const Write = Class.newInstance('Write', [], {on: String, value: Signal})
StateFunction.setReference('write', Write, -1)
var MainLoop = Class.newInstance('MainLoop', [], {init: String});
BehaviouralConcerns.setReference('mainLoop', MainLoop, 1);
const MainLoop = Class.newInstance('MainLoop', [], {init: String})
BehaviouralConcerns.setReference('mainLoop', MainLoop, 1)
var AbstractCode = new Model('AbstractCode', [], App, true);
const AbstractCode = new Model('AbstractCode', [], App, true)
/**
......@@ -53,59 +53,50 @@ var AbstractCode = new Model('AbstractCode', [], App, true);
*/
function toCode(xs, n) {
return _.map(xs, function(x) {return x.toCode()}).join(n);
return _.map(xs, x => x.toCode()).join(n)
}
App.prototype.toCode = function() {
return toCode(this.structural) + '\n\n' + toCode(this.behavioural);
}
StructuralConcerns.prototype.toCode = function() {
return toCode(this.alias, '\n')
+ '\n\n'
+ 'void setup() {\n'
+ toCode(this.pinMode, '\n')
+ '\n}';
}
BrickAlias.prototype.toCode = function() {
return 'int ' + this.name + ' = ' + this.pin + ';';
}
PinMode.prototype.toCode = function() {
return ' pinMode(' + this.name + ', ' + IO.getName(this.mode) + ');';
}
BehaviouralConcerns.prototype.toCode = function() {
return toCode(this.timeConfig)
+ '\n\n'
+ toCode(this.stateFunction, '\n\n')
+ '\n\n'
+ toCode(this.mainLoop);
}
TimeConfig.prototype.toCode = function() {
return 'long time = ' + this.initialTime + '; long debounce = ' + this.debounce + ';';
}
StateFunction.prototype.toCode = function() {
return 'void state_' + this.name + '() {\n'
+ toCode(this.write, '\n\n')
+ ' boolean guard = millis() - time > debounce;\n'
+ ' if (digitalRead(' + this.readOn + ') == ' + Signal.getName(this.read) + ' && guard) {\n'
+ ' time = millis(); state_' +this.next + '();\n'
+ ' } else {\n'
+ ' state_' + this.name + '();\n'
+ ' }\n'
+ '}';
}
Write.prototype.toCode = function() {
return ' digitalWrite(' + this.on + ', ' + Signal.getName(this.value) + ');\n';
}
MainLoop.prototype.toCode = function() {
return 'void loop() { state_' + this.init + '(); }';
}
module.exports = JSMF.modelExport(AbstractCode);
App.prototype.toCode = () =>
toCode(this.structural) + '\n\n' + toCode(this.behavioural)
StructuralConcerns.prototype.toCode =
() => toCode(this.alias, '\n')
+ '\n\n'
+ 'void setup() {\n'
+ toCode(this.pinMode, '\n')
+ '\n}'
BrickAlias.prototype.toCode =
() => 'int ' + this.name + ' = ' + this.pin + ';'
PinMode.prototype.toCode =
() => ' pinMode(' + this.name + ', ' + IO.getName(this.mode) + ');'
BehaviouralConcerns.prototype.toCode =
() => toCode(this.timeConfig)
+ '\n\n'
+ toCode(this.stateFunction, '\n\n')
+ '\n\n'
+ toCode(this.mainLoop)
TimeConfig.prototype.toCode =
() => 'long time = ' + this.initialTime + '; long debounce = ' + this.debounce + ';'
StateFunction.prototype.toCode =
() => 'void state_' + this.name + '() {\n'
+ toCode(this.write, '\n\n')
+ ' boolean guard = millis() - time > debounce;\n'
+ ' if (digitalRead(' + this.readOn + ') == ' + Signal.getName(this.read) + ' && guard) {\n'
+ ' time = millis(); state_' +this.next + '();\n'
+ ' } else {\n'
+ ' state_' + this.name + '();\n'
+ ' }\n'
+ '}'
Write.prototype.toCode =
() => ' digitalWrite(' + this.on + ', ' + Signal.getName(this.value) + ');\n'
MainLoop.prototype.toCode =
() => 'void loop() { state_' + this.init + '(); }'
module.exports = JSMF.modelExport(AbstractCode)
'use strict';
'use strict'
var Class;
var Model;
var Enum;
const JSMF = require('jsmf-core')
(function() {var JSMF = require('jsmf-core');
Model = JSMF.Model;
Class = JSMF.Class;
Enum = JSMF.Enum;
}).call();
let Class, Model, Enum
var ArduinoML = new Model('ArduinoML');
(function() {
Model = JSMF.Model
Class = JSMF.Class
Enum = JSMF.Enum
}).call()
var Signal = new Enum('Signal', {LOW: 0, HIGH: 1});
var NamedElement = Class.newInstance('NamedElement', [], {name: String});
const Signal = new Enum('Signal', ['LOW', 'HIGH'])
var App = Class.newInstance('App', NamedElement);
const NamedElement = Class.newInstance('NamedElement', [], {name: String})
var State = Class.newInstance('State', NamedElement);
App.setReference('state', State, -1);
App.setReference('initial', State, 1);
const App = Class.newInstance('App', NamedElement)
var Brick = Class.newInstance('Brick', NamedElement, {pin: Number});
App.setReference('brick', Brick, -1);
const State = Class.newInstance('State', NamedElement)
App.setReference('states', State, -1)
App.setReference('initial', State, 1)
var Action = Class.newInstance('Action', [], {value: Number});
State.setReference('action', Action, -1);
const Brick = Class.newInstance('Brick', NamedElement, {pin: JSMF.Range(0,13)})
var Transition = Class.newInstance('Transition', [], {value: Number});
Transition.setReference('next', State, 1);
State.setReference('transition', Transition, 1);
const Action = Class.newInstance('Action', [], {value: Signal})
State.setReference('action', Action, -1)
var Sensor = Class.newInstance('Sensor', Brick);
Transition.setReference('sensor', Sensor, 1);
const Transition = Class.newInstance('Transition', [], {value: Signal})
Transition.setReference('next', State, 1)
State.setReference('transition', Transition, 1)
var Actuator = Class.newInstance('Actuator', Brick);
Action.setReference('actuator', Actuator, 1);
const Sensor = Class.newInstance('Sensor', Brick)
Transition.setReference('sensor', Sensor, 1)
var Actuator = Class.newInstance('Actuator', Brick)
Action.setReference('actuator', Actuator, 1)
App.setReference('bricks', Brick, -1)
ArduinoML.setModellingElements([Signal, NamedElement, App, State, Brick, Action, Transition, Sensor, Actuator]);
var ArduinoML = new Model('ArduinoML', {}, App, true)
module.exports = {
ArduinoML: ArduinoML,
Signal: Signal,
NamedElement: NamedElement,
App: App,
State: State,
Brick: Brick,
Action: Action,
Transition: Transition,
Sensor: Sensor,
Actuator: Actuator
}
module.exports = JSMF.modelExport(ArduinoML)
{
"name": "foo",
"version": "0.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "BSD-2-Clause"
}
......@@ -7,7 +7,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Authors : J.S. Sottet
*/
var JSTL = require('../../index'); var Transformation = JSTL.Transformation;
var JSTL = require('../../src/index'); var Transformation = JSTL.Transformation;
var JSMF = require('jsmf-core'); var Model = JSMF.Model;
//Load the metamodels (in one file for the example)
......
'use strict'
const JSTL = require('../../src/index')
const JSMF = require('jsmf-core')
const _ = require('lodash')
const Model = JSMF.Model
const Class = JSMF.Class
const Graph = new Class('Graph')
const Node = new Class('Node', [], {name: String, object: JSMF.JSMFAny})
Graph.addReference('nodes', Node)
const Edge = new Class('Edge', [], {name: String}, {source: Node, target: Node})
Graph.addReference('edges', Edge)
const GraphModel = new Model('GraphModel', {}, Graph, true)
const modelToGraph = new JSTL.Transformation()
modelToGraph.addHelpers({
'allElements': function(m) {
return _.flatten(_.values(m.modellingElements))
},
'elementName': function(m) {
const result = new Map()
const elems = _.flatten(_.values(m.modellingElements))
_.forEach(elems, function(x, i) {
result.set(x, x.conformsTo().__name + '_' + i)
})
return result
}
})
modelToGraph.addRules({
'Generate nodes': {
in: function() {return this.helpers.allElements},
out: function (x) {
const n = new Node()
n.object = x
n.name = n.name || this.helpers.elementName.valuesFor(x)[0]
return [n]
}
},
'Generate edges': {
in: function() {return this.helpers.allElements},
out: function (x) {
const edges = []
for (var rName in x.conformsTo().references) {
_.forEach(x[rName], function(r) {
const e = new Edge()
e.name = rName
this.assign(e, 'source', x)
this.assign(e, 'target', r)
edges.push(e)
})
}
return edges
}
}
})
module.exports = JSMF.modelExport(GraphModel)
module.exports.toGraph = function(source) {
const result = new Model()
const graph = new Graph()
modelToGraph.apply(source, result)
graph.nodes = result.modellingElements.Node || []
graph.edges = result.modellingElements.Edge || []
result.add(graph)
return result
}
......@@ -2,7 +2,7 @@
"name": "jsmf-jstl",
"version": "0.10.2",