Add basics of properly handling ports
This commit is contained in:
parent
740702c0d7
commit
71bb1c8bf9
4 changed files with 46 additions and 14 deletions
|
@ -299,7 +299,8 @@ generate unsafeModule =
|
|||
, [ IfSingleStmt () thisModule (ReturnStmt () (Just thisModule)) ]
|
||||
, [ internalImports (List.intercalate "." (names modul)) ]
|
||||
, concatMap jsImport (imports modul)
|
||||
, concatMap jsPort (ports modul)
|
||||
, checkInPorts (ports modul)
|
||||
, map jsPort (ports modul)
|
||||
, [ assign ["_op"] (ObjectLit () []) ]
|
||||
, concat $ evalState (mapM definition . fst . SD.flattenLets [] $ program modul) 0
|
||||
, [ jsExports ]
|
||||
|
@ -331,10 +332,15 @@ generate unsafeModule =
|
|||
|
||||
addId js = InfixExpr () OpAdd (string (js++"_")) (obj "_elm.id")
|
||||
|
||||
checkInPorts ports =
|
||||
[ ExprStmt () $ obj "_N.checkPorts" `call` [ref "$moduleName", names] ]
|
||||
where
|
||||
names = ArrayLit () [ string name | (name, _, Nothing) <- ports ]
|
||||
|
||||
jsPort (name, _, maybe) =
|
||||
case maybe of
|
||||
Nothing -> error "in-ports are not defined yet"
|
||||
Just expr -> error "out-ports are not defined yet"
|
||||
Nothing -> assign [name] $ dotSep ["_elm","ports_in",name]
|
||||
Just expr -> assign ["_elm","ports_out",name] $ evalState (expression expr) 0
|
||||
|
||||
binop span op e1 e2 =
|
||||
case op of
|
||||
|
|
|
@ -19,7 +19,7 @@ class Simplify a where
|
|||
|
||||
instance Simplify (Declaration t v) where
|
||||
simp (Definition def) = Definition (simp def)
|
||||
simp (ImportEvent js b elm t) = ImportEvent js (simp b) elm t
|
||||
simp (Port name tipe maybe) = Port name tipe (simp `fmap` maybe)
|
||||
simp stmt = stmt
|
||||
|
||||
instance Simplify (Def t v) where
|
||||
|
|
|
@ -207,6 +207,30 @@ Elm.Native.Utils.make = function(elm) {
|
|||
return Tuple2(posx, posy);
|
||||
}
|
||||
|
||||
function checkPorts(moduleName, ports) {
|
||||
var expected = {};
|
||||
for (var i = ports.length; i--; ) {
|
||||
expected[ports[i]] = 1;
|
||||
}
|
||||
for (var key in elm.ports_in) {
|
||||
expected[key] = expected[key] || 0;
|
||||
expected[key] -= 1;
|
||||
}
|
||||
var missing = [];
|
||||
var extra = [];
|
||||
for (var key in expected) {
|
||||
var result = expected[key];
|
||||
if (result > 0) missing.push(key);
|
||||
if (result < 0) extra.push(key);
|
||||
}
|
||||
if (missing.length > 0) {
|
||||
throw new Error("Module " + moduleName + " requires inputs for these ports: " + missing.join(', '));
|
||||
}
|
||||
if (extra.length > 0) {
|
||||
throw new Error("Module " + moduleName + " has been given ports that do not exist: " + extra.join(', '));
|
||||
}
|
||||
}
|
||||
|
||||
return elm.Native.Utils.values = {
|
||||
eq:eq,
|
||||
cmp:cmp,
|
||||
|
@ -226,6 +250,7 @@ Elm.Native.Utils.make = function(elm) {
|
|||
mod : F2(mod),
|
||||
htmlHeight: F2(htmlHeight),
|
||||
getXY: getXY,
|
||||
toFloat: function(x) { return +x; }
|
||||
toFloat: function(x) { return +x; },
|
||||
checkPorts: checkPorts
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
Elm.fullscreen = function(module) {
|
||||
Elm.fullscreen = function(module, ports) {
|
||||
var style = document.createElement('style');
|
||||
style.type = 'text/css';
|
||||
style.innerHTML = "html,head,body { padding:0; margin:0; }" +
|
||||
|
@ -10,24 +10,24 @@ Elm.fullscreen = function(module) {
|
|||
document.head.appendChild(style);
|
||||
var container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
return init(ElmRuntime.Display.FULLSCREEN, container, module);
|
||||
return init(ElmRuntime.Display.FULLSCREEN, container, module, ports);
|
||||
};
|
||||
|
||||
Elm.embed = function(module, container) {
|
||||
Elm.embed = function(module, container, ports) {
|
||||
var tag = container.tagName;
|
||||
if (tag !== 'DIV') {
|
||||
throw new Error('Elm.node must be given a DIV, not a ' + tag + '.');
|
||||
} else if (container.hasChildNodes()) {
|
||||
throw new Error('Elm.node must be given an empty DIV. No children allowed!');
|
||||
}
|
||||
return init(ElmRuntime.Display.COMPONENT, container, module);
|
||||
return init(ElmRuntime.Display.COMPONENT, container, module, ports);
|
||||
};
|
||||
|
||||
Elm.worker = function(module) {
|
||||
return init(ElmRuntime.Display.NONE, {}, module);
|
||||
Elm.worker = function(module, ports) {
|
||||
return init(ElmRuntime.Display.NONE, {}, module, ports);
|
||||
};
|
||||
|
||||
function init(display, container, module, moduleToReplace) {
|
||||
function init(display, container, module, moduleToReplace, ports) {
|
||||
// defining state needed for an instance of the Elm RTS
|
||||
var inputs = [];
|
||||
|
||||
|
@ -67,7 +67,8 @@ function init(display, container, module, moduleToReplace) {
|
|||
display:display,
|
||||
id:ElmRuntime.guid(),
|
||||
addListener:addListener,
|
||||
inputs:inputs
|
||||
inputs:inputs,
|
||||
ports_in:ports
|
||||
};
|
||||
|
||||
// Set up methods to communicate with Elm program from JS.
|
||||
|
@ -123,7 +124,7 @@ function init(display, container, module, moduleToReplace) {
|
|||
}
|
||||
|
||||
reportAnyErrors();
|
||||
return { send:send, recv:recv, swap:swap };
|
||||
return { send:send, recv:recv, swap:swap, ports:elm.ports_out };
|
||||
};
|
||||
|
||||
function filterListeners(inputs, listeners) {
|
||||
|
|
Loading…
Reference in a new issue