Skip to content

Commit

Permalink
feat(xod-project, xod-arduino): bus nodes
Browse files Browse the repository at this point in the history
Closes #1353
  • Loading branch information
evgenykochetkov committed Jul 30, 2018
1 parent 86c1876 commit 5ad3efd
Show file tree
Hide file tree
Showing 40 changed files with 1,466 additions and 301 deletions.
4 changes: 4 additions & 0 deletions packages/holes/src/Holes_Map_String.re
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ let mergeOverride = (xs, ys) =>
| None => ox
}
);

let fromDict = d => d |. Js.Dict.entries |. Map.String.fromArray;

let toDict = m => m |. Map.String.toArray |. Js.Dict.fromArray;
4 changes: 4 additions & 0 deletions packages/holes/src/Holes_Map_String.rei
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ let innerJoin: (t(k), t('v)) => t('v);
/** Merges two maps extending the first map with contents of the second. If a key
presents in both maps, the value of the second map wins. */
let mergeOverride: (t('v), t('v)) => t('v);

let fromDict: Js.Dict.t('v) => t('v);

let toDict: t('v) => Js.Dict.t('v);
2 changes: 1 addition & 1 deletion packages/xod-arduino/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"build:js": "babel src/ -d dist/ --source-maps",
"build:re": "bsb -make-world",
"build": "yarn build:js && yarn build:re",
"build": "yarn build:re && yarn build:js",
"dev:re": "yarn run build:re -w",
"dev": "yarn run build:js --watch",
"doc": "documentation build --format html --output doc --sort-order alpha src/",
Expand Down
1 change: 1 addition & 0 deletions packages/xod-arduino/src/transpiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ const transformProjectWithImpls = def(
() => opts.debug,
R.chain(XP.updatePatch(path, XP.removeDebugNodes))
),
R.map(XP.jumperizePatchRecursively(path)),
XP.validatePatchReqursively(path)
// begin preparing project for transpilation
)(project)
Expand Down
14 changes: 14 additions & 0 deletions packages/xod-client/src/project/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,24 @@ const getTerminalsErrorMap = R.compose(
XP.validatePinLabels
);

const getBusesErrorMap = R.compose(
foldEither(
err =>
R.compose(
R.fromPairs,
R.map(R.pair(R.__, err)),
R.path(['payload', 'nodeIds'])
)(err),
R.always({})
),
XP.validateBuses
);

const markNodesCausingErrors = R.curry((currentPatch, nodes) => {
// :: Map NodeId Error
const errorsMap = R.mergeAll([
getTerminalsErrorMap(currentPatch),
getBusesErrorMap(currentPatch),
getVariadicMarkersErrorMap(currentPatch),
getAbstractMarkersErrorMap(currentPatch),
getConstructorMarkersErrorMap(currentPatch),
Expand Down
2 changes: 2 additions & 0 deletions packages/xod-project/bsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
},
"suffix": ".bs.js",
"bs-dependencies": [
"holes",
"rationale",
"xod-func-tools"
],
"namespace": true,
Expand Down
5 changes: 3 additions & 2 deletions packages/xod-project/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"scripts": {
"build:js": "babel src/ -d dist/ --source-maps",
"build:re": "bsb -make-world",
"build": "yarn build:js && yarn build:re",
"build": "yarn build:re && yarn build:js",
"dev:re": "yarn run build:re -w",
"dev": "yarn run build:js --watch",
"refmt": "find src/ test/ -name '*.re*' -exec refmt --in-place {} +",
"refmt": "find src/ test/ -name '*.re' -or -name '*.rei' -type f -exec refmt --in-place {} +",
"doc": "documentation build --format html --output doc --sort-order alpha src/",
"test": "mocha test/**/*.spec.js",
"test:watch": "yarn run test --watch"
Expand All @@ -22,6 +22,7 @@
"hm-def": "^0.3.2",
"ramda": "^0.24.1",
"ramda-fantasy": "^0.8.0",
"rationale": "^0.1.4",
"sanctuary-def": "^0.14.0",
"shortid": "^2.2.6",
"xod-func-tools": "^0.21.0"
Expand Down
9 changes: 3 additions & 6 deletions packages/xod-project/src/Attachment.re
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
type t;

[@bs.module ".."]
external getFilename : t => string = "getAttachmentFilename";
[@bs.module ".."] external getFilename : t => string = "getAttachmentFilename";

[@bs.module ".."]
external getContent : t => string = "getAttachmentContent";
[@bs.module ".."] external getContent : t => string = "getAttachmentContent";

[@bs.module ".."]
external getEncoding : t => string = "getAttachmentEncoding";
[@bs.module ".."] external getEncoding : t => string = "getAttachmentEncoding";

let isTabtest = att => getFilename(att) == "patch.test.tsv";
88 changes: 88 additions & 0 deletions packages/xod-project/src/Buses.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
open Belt;

type matchingBusNodes = list((Node.t, list(Node.t)));

let getMatchingBusNodes = patch => {
let nodes = Patch.listNodes(patch);

let toBusNodesByLabel =
nodes
|. List.keep(n => Node.getType(n) == "xod/patch-nodes/to-bus")
|. Holes.List.groupBy(Node.getLabel)
/* having multiple `to-bus` nodes with the same label is forbidden,
so exclude them from type resolution */
|. Map.String.keep((_, ns) => List.length(ns) == 1)
|. Holes.Map.String.keepMap(List.head);

if (Map.String.isEmpty(toBusNodesByLabel)) {
[]; /* short-curcuit for optimization */
} else {
nodes
|. List.keep(n => Node.getType(n) == "xod/patch-nodes/from-bus")
|. Holes.List.groupBy(Node.getLabel)
|. Map.String.keep((label, _) =>
Map.String.has(toBusNodesByLabel, label)
)
|. Map.String.mapWithKey((label, fbNodes) =>
(
/* we just made sure that toBusNodesByLabel has those */
Map.String.getExn(toBusNodesByLabel, label),
fbNodes,
)
)
|. Map.String.valuesToArray
|. List.fromArray;
};
};

let jumperizePatch: (Patch.t, matchingBusNodes) => Patch.t =
(patch, matchingBusNodes) => {
let linksByOutputNodeId =
patch |. Patch.listLinks |. Holes.List.groupBy(Link.getOutputNodeId);

List.reduce(
matchingBusNodes,
patch,
(jPatch, (toBusNode, fromBusNodes)) => {
let jumperNodeId = Node.getId(toBusNode);

let linksFromJumperToBusDestinations =
fromBusNodes
|. List.map(fromBusNode =>
Map.String.getWithDefault(
linksByOutputNodeId,
Node.getId(fromBusNode),
[],
)
)
|. List.flatten
|. List.map(link =>
Link.create(
~toPin=Link.getInputPinKey(link),
~toNode=Link.getInputNodeId(link),
~fromPin="__out__",
~fromNode=jumperNodeId,
)
);

let dissocFromBusNodes = patchWithFromBusNodes =>
List.reduce(fromBusNodes, patchWithFromBusNodes, (accP, n) =>
Patch.dissocNode(accP, Node.getId(n))
);

jPatch
|. Patch.assocNode(Node.setType("xod/core/jumper", toBusNode))
|. dissocFromBusNodes
|. Patch.upsertLinks(linksFromJumperToBusDestinations)
|. Result.getExn;
},
);
};

let jumperizePatchRecursively = (project, entryPatchPath) =>
project
|. Project.getPatchDependencies(entryPatchPath)
|. Belt.List.add(entryPatchPath)
|. Belt.List.keepMap(Project.getPatchByPath(project))
|. Belt.List.map(p => jumperizePatch(p, getMatchingBusNodes(p)))
|> Project.assocPatchList(project);
12 changes: 12 additions & 0 deletions packages/xod-project/src/Buses.rei
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

/*
A list of tuples with `to-bus` node as the first element
and a list of corresponding `from-bus` nodes as the second
*/
type matchingBusNodes = list((Node.t, list(Node.t)));

let getMatchingBusNodes: Patch.t => matchingBusNodes;

let jumperizePatch: (Patch.t, matchingBusNodes) => Patch.t;

let jumperizePatchRecursively: (Project.t, Patch.path) => Project.t;
1 change: 1 addition & 0 deletions packages/xod-project/src/Buses_Js.re
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let jumperizePatchRecursivelyU = Buses.jumperizePatchRecursively;
36 changes: 36 additions & 0 deletions packages/xod-project/src/Link.re
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
type t = Js.Types.obj_val;

type id = string;

[@bs.module ".."]
external create :
(~toPin: Pin.key, ~toNode: Node.id, ~fromPin: Pin.key, ~fromNode: Node.id) =>
t =
"createLink";

[@bs.module ".."] external getId : t => id = "getLinkId";

[@bs.module ".."]
external getInputNodeId : t => Node.id = "getLinkInputNodeId";

[@bs.module ".."]
external getOutputNodeId : t => Node.id = "getLinkOutputNodeId";

[@bs.module ".."]
external getInputPinKey : t => Pin.key = "getLinkInputPinKey";

[@bs.module ".."]
external getOutputPinKey : t => Pin.key = "getLinkOutputPinKey";

[@bs.module ".."]
external setInputPinKey : (Pin.key, t) => t = "setLinkInputPinKey";

[@bs.module ".."]
external setOutputPinKey : (Pin.key, t) => t = "setLinkOutputPinKey";

[@bs.module ".."]
external inputNodeIdEquals : (Node.id, t) => bool = "isLinkInputNodeIdEquals";

[@bs.module ".."]
external outputNodeIdEquals : (Node.id, t) => bool =
"isLinkOutputNodeIdEquals";

[@bs.module ".."]
external inputPinKeyEquals : (Pin.key, t) => bool = "isLinkInputPinKeyEquals";

[@bs.module ".."]
external outputPinKeyEquals : (Pin.key, t) => bool =
"isLinkOutputPinKeyEquals";
24 changes: 24 additions & 0 deletions packages/xod-project/src/Link.rei
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
type t;

type id = string;

let create:
(~toPin: Pin.key, ~toNode: Node.id, ~fromPin: Pin.key, ~fromNode: Node.id) =>
t;

let getId: t => id;

let getInputNodeId: t => Node.id;

let getOutputNodeId: t => Node.id;

let getInputPinKey: t => Pin.key;

let getOutputPinKey: t => Pin.key;

let setInputPinKey: (Pin.key, t) => t;

let setOutputPinKey: (Pin.key, t) => t;

let inputNodeIdEquals: (Node.id, t) => bool;

let outputNodeIdEquals: (Node.id, t) => bool;

let inputPinKeyEquals: (Pin.key, t) => bool;

let outputPinKeyEquals: (Pin.key, t) => bool;
6 changes: 6 additions & 0 deletions packages/xod-project/src/Node.re
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ type t = Js.Types.obj_val;

type id = string;

type label = string;

type position = {
.
"x": int,
Expand All @@ -18,3 +20,7 @@ let create = patchPath => _create(origin, patchPath);
[@bs.module ".."] external getId : t => id = "getNodeId";

[@bs.module ".."] external getType : t => PatchPath.t = "getNodeType";

[@bs.module ".."] external setType: (PatchPath.t, t) => t = "setNodeType";

[@bs.module ".."] external getLabel: t => label = "getNodeLabel";
6 changes: 6 additions & 0 deletions packages/xod-project/src/Node.rei
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@ type t;

type id = string;

type label = string;

let create: PatchPath.t => t;

let getId: t => id;

let getType: t => PatchPath.t;

let setType: (PatchPath.t, t) => t;

let getLabel: t => label;
23 changes: 19 additions & 4 deletions packages/xod-project/src/Patch.re
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,28 @@ type path = PatchPath.t;

[@bs.module ".."] external getPath : t => path = "getPatchPath";

[@bs.module ".."]
external _assocNode : (Node.t, t) => t = "assocNode";
[@bs.module ".."] external _assocNode : (Node.t, t) => t = "assocNode";

let assocNode = (patch, node) => _assocNode(node, patch);

[@bs.module ".."] external _dissocNode : (Node.id, t) => t = "dissocNode";

let dissocNode = (patch, nodeId) => _dissocNode(nodeId, patch);

[@bs.module ".."] external _listNodes : t => array(Node.t) = "listNodes";

let listNodes = patch => _listNodes(patch) |. List.fromArray;

[@bs.module ".."]
external _assocLink : (Link.t, t) => Either.t(Js.Exn.t, t) = "assocLink";

let assocLink = (patch, link) => _assocLink(link, patch) |> Either.toResult;

[@bs.module ".."]
external _upsertLinks : (array(Link.t), t) => Either.t(Js.Exn.t, t) = "upsertLinks";

let upsertLinks = (patch, links) => _upsertLinks(List.toArray(links), patch) |> Either.toResult;

let assocLinkExn = (link, patch) =>
switch (assocLink(link, patch)) {
| Ok(patch') => patch'
Expand All @@ -27,8 +39,11 @@ let assocLinkExn = (link, patch) =>
Js.Exn.raiseError(err |> Js.Exn.message |. Option.getWithDefault(""))
};

[@bs.module ".."]
external _listPins : t => array(Pin.t) = "listPins";
[@bs.module ".."] external _listLinks : t => array(Link.t) = "listLinks";

let listLinks = patch => _listLinks(patch) |. List.fromArray;

[@bs.module ".."] external _listPins : t => array(Pin.t) = "listPins";

let listPins = patch => _listPins(patch) |. List.fromArray;

Expand Down
8 changes: 8 additions & 0 deletions packages/xod-project/src/Patch.rei
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ let getPath: t => path;

let assocNode: (t, Node.t) => t;

let dissocNode: (t, Node.id) => t;

let listNodes: t => list(Node.t);

let assocLink: (t, Link.t) => XResult.t(t);

let assocLinkExn: (t, Link.t) => t;

let upsertLinks: (t, list(Link.t)) => XResult.t(t);

let listLinks: t => list(Link.t);

let listPins: t => list(Pin.t);

let listInputPins: t => list(Pin.t);
Expand Down
Loading

0 comments on commit 5ad3efd

Please sign in to comment.