xod-arduino
Advanced tools
Comparing version 0.32.0 to 0.35.2
{ | ||
"name": "xod-arduino", | ||
"version": "0.22.0", | ||
"version": "0.33.0", | ||
"sources": [ | ||
@@ -5,0 +5,0 @@ "src" |
@@ -1,2 +0,2 @@ | ||
// Generated by BUCKLESCRIPT VERSION 5.0.0, PLEASE EDIT WITH CARE | ||
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE | ||
'use strict'; | ||
@@ -6,4 +6,13 @@ | ||
var Belt_Array = require("bs-platform/lib/js/belt_Array.js"); | ||
var Belt_SetString = require("bs-platform/lib/js/belt_SetString.js"); | ||
var Directives$XodArduino = require("./Directives.bs.js"); | ||
function getEvaluateOnPinSettings(code) { | ||
var param = Directives$XodArduino.getEvaluateOnPinSettings(code); | ||
return { | ||
enabled: param.enabled, | ||
exceptions: Belt_SetString.toArray(param.exceptions) | ||
}; | ||
} | ||
function findXodPragmas(code) { | ||
@@ -33,2 +42,3 @@ return Belt_Array.map(Belt_List.toArray(Directives$XodArduino.findXodPragmas(code)), Belt_List.toArray); | ||
exports.doesRaiseErrors = doesRaiseErrors; | ||
exports.getEvaluateOnPinSettings = getEvaluateOnPinSettings; | ||
exports.areTimeoutsEnabled = areTimeoutsEnabled; | ||
@@ -35,0 +45,0 @@ exports.stripCppComments = stripCppComments; |
@@ -1,2 +0,2 @@ | ||
// Generated by BUCKLESCRIPT VERSION 5.0.0, PLEASE EDIT WITH CARE | ||
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE | ||
'use strict'; | ||
@@ -8,10 +8,11 @@ | ||
var Caml_option = require("bs-platform/lib/js/caml_option.js"); | ||
var Belt_SetString = require("bs-platform/lib/js/belt_SetString.js"); | ||
function toBoolean(hint, $$default) { | ||
switch (hint) { | ||
case 0: | ||
case /* Enable */0: | ||
return true; | ||
case 1: | ||
case /* Disable */1: | ||
return false; | ||
case 2: | ||
case /* Auto */2: | ||
return $$default; | ||
@@ -95,6 +96,2 @@ | ||
function isOutput(identifier) { | ||
return test(undefined, identifier, "^output_"); | ||
} | ||
function tokenizePragma(pragmaLine) { | ||
@@ -145,3 +142,3 @@ return Belt_List.map(matches(undefined, remove(undefined, pragmaLine, pragmaHeadRegexp), "[\\w._-]+|\".*?\""), function (token) { | ||
function isDirtienessEnabled(code, identifier) { | ||
return Belt_List.reduce(findXodPragmas(code), isOutput(identifier) || doesReferTemplateSymbol("isInputDirty", identifier, code), function (acc, pragma) { | ||
return Belt_List.reduce(findXodPragmas(code), test(undefined, identifier, "^output_") || doesReferTemplateSymbol("isInputDirty", identifier, code), function (acc, pragma) { | ||
if (pragma && pragma[0] === "dirtieness") { | ||
@@ -166,2 +163,49 @@ var match = pragma[1]; | ||
function getEvaluateOnPinSettings(code) { | ||
return Belt_List.reduce(filterPragmasByFeature(findXodPragmas(code), "evaluate_on_pin"), { | ||
enabled: true, | ||
exceptions: Belt_SetString.empty | ||
}, function (acc, pragma) { | ||
if (pragma) { | ||
var match = pragma[1]; | ||
if (match) { | ||
switch (match[0]) { | ||
case "disable": | ||
var disabledPins = match[1]; | ||
if (disabledPins) { | ||
return { | ||
enabled: acc.enabled, | ||
exceptions: acc.enabled ? Belt_SetString.mergeMany(acc.exceptions, Belt_List.toArray(disabledPins)) : Belt_SetString.removeMany(acc.exceptions, Belt_List.toArray(disabledPins)) | ||
}; | ||
} else { | ||
return { | ||
enabled: false, | ||
exceptions: Belt_SetString.empty | ||
}; | ||
} | ||
case "enable": | ||
var enabledPins = match[1]; | ||
if (enabledPins) { | ||
return { | ||
enabled: acc.enabled, | ||
exceptions: acc.enabled ? Belt_SetString.removeMany(acc.exceptions, Belt_List.toArray(enabledPins)) : Belt_SetString.mergeMany(acc.exceptions, Belt_List.toArray(enabledPins)) | ||
}; | ||
} else { | ||
return { | ||
enabled: true, | ||
exceptions: Belt_SetString.empty | ||
}; | ||
} | ||
default: | ||
return acc; | ||
} | ||
} else { | ||
return acc; | ||
} | ||
} else { | ||
return acc; | ||
} | ||
}); | ||
} | ||
function doesCatchErrors(code) { | ||
@@ -177,4 +221,3 @@ return toBoolean(lastPragmaEndis(code, "error_catch"), doesReferSymbol("getError", code)); | ||
var url = match[0]; | ||
var match$1 = test(undefined, url, "^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$"); | ||
if (match$1) { | ||
if (test(undefined, url, "^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$")) { | ||
return (/* :: */[url, acc] | ||
@@ -194,3 +237,3 @@ ); | ||
var Pragma = []; | ||
var Pragma = {}; | ||
@@ -204,2 +247,3 @@ exports.Pragma = Pragma; | ||
exports.findXodPragmas = findXodPragmas; | ||
exports.getEvaluateOnPinSettings = getEvaluateOnPinSettings; | ||
exports.findRequireUrls = findRequireUrls; | ||
@@ -206,0 +250,0 @@ exports.stripCppComments = stripCppComments; |
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var _ramda = require('ramda'); | ||
@@ -24,5 +26,12 @@ | ||
// Convert char literals to decimal byte literals | ||
// E.G. `'a'` -> `97d` | ||
var charLiteralToByteLiteral = R.when(XP.isLikeCharLiteral, R.compose(R.concat(R.__, 'd'), R.toString, function (a) { | ||
return a.charCodeAt(0); | ||
}, R.nth(1), R.match(XP.charLiteralRegExp))); | ||
var formatByteLiteral = R.compose(_templates.byteLiteralToDecimal, charLiteralToByteLiteral); | ||
exports.default = (0, _types.def)('formatTweakMessage :: PatchPath -> NodeId -> DataValue -> String', function (nodeType, nodeId, value) { | ||
var prefix = '+XOD:' + nodeId; | ||
switch (XP.getTweakType(nodeType)) { | ||
@@ -34,3 +43,3 @@ case XP.PIN_TYPE.NUMBER: | ||
case XP.PIN_TYPE.BYTE: | ||
return prefix + ':' + (0, _templates.byteLiteralToDecimal)(value) + '\r\n'; | ||
return prefix + ':' + formatByteLiteral(value) + '\r\n'; | ||
case XP.PIN_TYPE.PULSE: | ||
@@ -42,2 +51,13 @@ return prefix + '\r\n'; | ||
}, R.slice(0, XP.getStringTweakLength(nodeType)), _xodFuncTools.unquote)(value); | ||
case XP.BINDABLE_CUSTOM_TYPES.COLOR: | ||
return R.compose(function (_ref) { | ||
var _ref2 = _slicedToArray(_ref, 3), | ||
r = _ref2[0], | ||
g = _ref2[1], | ||
b = _ref2[2]; | ||
return prefix + ':' + r + ',' + g + ',' + b + '\r\n'; | ||
}, R.map(function (x) { | ||
return parseInt(x, 16); | ||
}), R.splitEvery(2), R.tail)(value); | ||
default: | ||
@@ -44,0 +64,0 @@ return ''; |
@@ -57,2 +57,14 @@ 'use strict'; | ||
}); | ||
Object.defineProperty(exports, 'hasTetheringInternetNode', { | ||
enumerable: true, | ||
get: function get() { | ||
return _transpiler.hasTetheringInternetNode; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'getTetheringInetNodeId', { | ||
enumerable: true, | ||
get: function get() { | ||
return _transpiler.getTetheringInetNodeId; | ||
} | ||
}); | ||
@@ -59,0 +71,0 @@ var _messages = require('./messages'); |
@@ -1,2 +0,2 @@ | ||
// Generated by BUCKLESCRIPT VERSION 5.0.0, PLEASE EDIT WITH CARE | ||
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE | ||
'use strict'; | ||
@@ -12,7 +12,7 @@ | ||
switch (liveness) { | ||
case 0: | ||
case /* None */0: | ||
return "NONE"; | ||
case 1: | ||
case /* Debug */1: | ||
return "DEBUG"; | ||
case 2: | ||
case /* Simulation */2: | ||
return "SIMULATION"; | ||
@@ -25,6 +25,6 @@ | ||
return BeltHoles_Result.map(Either$XodFuncTools.toResult($dot$dot.transformProject(project, patchPath, getLivenessString(liveness), xodGlobals)), function (tProject) { | ||
return (/* record */[ | ||
/* code */$dot$dot.transpile(tProject), | ||
/* nodeIdMap */Belt_MapString.fromArray(Js_dict.entries($dot$dot.getNodeIdsMap(tProject)))] | ||
); | ||
return { | ||
code: $dot$dot.transpile(tProject), | ||
nodeIdMap: Belt_MapString.fromArray(Js_dict.entries($dot$dot.getNodeIdsMap(tProject))) | ||
}; | ||
}); | ||
@@ -31,0 +31,0 @@ } |
@@ -6,3 +6,3 @@ 'use strict'; | ||
}); | ||
exports.transpile = exports.getRequireUrls = exports.transformProject = exports.extendTProjectWithGlobals = exports.listGlobals = exports.getPinsAffectedByErrorRaisers = exports.getNodePinKeysMap = exports.getNodeIdsMap = exports.commentXodPragmas = undefined; | ||
exports.transpile = exports.getRequireUrls = exports.transformProject = exports.extendTProjectWithGlobals = exports.listGlobals = exports.getPinsAffectedByErrorRaisers = exports.getNodePinKeysMap = exports.getNodeIdsMap = exports.commentXodPragmas = exports.getTetheringInetNodeId = exports.hasTetheringInternetNode = undefined; | ||
@@ -48,4 +48,2 @@ var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var getLinksInputNodeIds = (0, _types.def)('getLinksInputNodeIds :: [Link] -> [TNodeId]', R.compose(R.uniq, R.map(R.compose(toInt, XP.getLinkInputNodeId)))); | ||
var getPatchByNodeId = (0, _types.def)('getPatchByNodeId :: Project -> PatchPath -> [TPatch] -> NodeId -> TPatch', function (project, entryPath, patches, nodeId) { | ||
@@ -68,2 +66,7 @@ return R.compose(findPatchByPath(R.__, patches), XP.getNodeType, XP.getNodeByIdUnsafe(nodeId), XP.getPatchByPathUnsafe)(entryPath, project); | ||
var hasTetheringInternetNode = exports.hasTetheringInternetNode = (0, _types.def)('hasTetheringInternetNode :: TProject -> Boolean', R.compose(R.not, R.isNil, _templates.withTetheringInetNode, R.prop('nodes'))); | ||
// :: TProject -> Nullable Int | ||
var getTetheringInetNodeId = exports.getTetheringInetNodeId = R.compose(R.unless(R.isNil, R.prop('id')), _templates.withTetheringInetNode, R.prop('nodes')); | ||
//----------------------------------------------------------------------------- | ||
@@ -131,2 +134,3 @@ // | ||
// :: Patch -> [PatchPath] | ||
// todo: the name is incorrect | ||
var getReferencedCustomTypes = R.compose(R.map(XP.getPinType), XP.listPins); | ||
@@ -162,7 +166,71 @@ | ||
// cause it will be placed at the top of the graph | ||
R.reject(R.compose((0, _xodFuncTools.isAmong)(constructorsPatchPaths), R.prop('patchPath')))(tPatches)), R.map(R.compose(convertPatchToTPatch, XP.getPatchByPathUnsafe(R.__, originalProject))))(constructorsPatchPaths); | ||
R.reject(R.compose((0, _xodFuncTools.isAmong)(constructorsPatchPaths), R.prop('patchPath')))(tPatches)), R.map(R.compose(R.assoc('isConstructor', true), // todo: do this in a separate function? | ||
convertPatchToTPatch, XP.getPatchByPathUnsafe(R.__, originalProject))))(constructorsPatchPaths); | ||
}); | ||
// :: [TPatch] -> Set PatchPath | ||
var listTemplatableCustomTypes = function listTemplatableCustomTypes(toposortedTPatches) { | ||
var constructorPatches = R.filter(R.prop('isConstructor'), toposortedTPatches); | ||
var templatableCustomTypes = new Set(); | ||
// because patches are toposorted, we can do this in a single pass | ||
constructorPatches.forEach(function (_ref) { | ||
var inputs = _ref.inputs, | ||
patchPath = _ref.patchPath; | ||
var isTemplatable = R.any(function (_ref2) { | ||
var type = _ref2.type; | ||
return XP.CONSTANT_PIN_TYPES.includes(type) || templatableCustomTypes.has(type); | ||
}, inputs); | ||
if (isTemplatable) { | ||
templatableCustomTypes.add(patchPath); | ||
} | ||
}); | ||
return templatableCustomTypes; | ||
}; | ||
var assignPinFlags = function assignPinFlags(toposortedTPatches) { | ||
var templatableCustomTypes = listTemplatableCustomTypes(toposortedTPatches); | ||
if (R.isEmpty(templatableCustomTypes)) { | ||
return toposortedTPatches; | ||
} | ||
var isTemplatableCustomTypePin = function isTemplatableCustomTypePin(_ref3) { | ||
var type = _ref3.type; | ||
return templatableCustomTypes.has(type); | ||
}; | ||
return R.map(R.compose(function (tPatch) { | ||
return R.over(R.lensProp('outputs'), R.map(function (pin) { | ||
var pinFlags = R.applySpec({ | ||
// "output-self" type is erased in createPinFromTerminalNode | ||
// (pin type becomes the same as the patch path) | ||
isOutputSelf: function isOutputSelf(_ref4) { | ||
var type = _ref4.type; | ||
return type === tPatch.patchPath; | ||
}, | ||
isTemplatableCustomTypePin: isTemplatableCustomTypePin, | ||
// Finds matching input, like DEV and DEV' | ||
shortCirquitInputKey: function shortCirquitInputKey(_ref5) { | ||
var type = _ref5.type, | ||
pinKey = _ref5.pinKey; | ||
return R.compose((0, _xodFuncTools.foldMaybe)('', R.prop('pinKey')), (0, _xodFuncTools.maybeFind)(function (i) { | ||
return i.type === type && i.pinKey + 'U0027' === pinKey; | ||
}))(tPatch.inputs); | ||
} | ||
})(pin); | ||
return R.merge(pinFlags, pin); | ||
}), tPatch); | ||
}, R.over(R.lensProp('inputs'), R.map(function (pin) { | ||
return R.assoc('isTemplatableCustomTypePin', isTemplatableCustomTypePin(pin), pin); | ||
}))), toposortedTPatches); | ||
}; | ||
var createTPatches = (0, _types.def)('createTPatches :: PatchPath -> Project -> Project -> [TPatch]', function (entryPath, project, originalProject) { | ||
return R.compose( | ||
return R.compose(assignPinFlags, | ||
// Include constructor patches for custom types | ||
@@ -199,10 +267,45 @@ // that are used without an explicit constructor. | ||
var getTNodeOutputDestinations = (0, _types.def)('getTNodeOutputDestinations :: [Link] -> Project -> PatchPath -> [TNodeOutputDestination]', function (links, project, entryPath) { | ||
return R.compose(R.values, R.mapObjIndexed(function (linksFromSingleOutputToSameNode, inputNodeId) { | ||
var patch = R.compose(XP.getPatchByPathUnsafe(R.__, project), XP.getNodeType, XP.getNodeByIdUnsafe(inputNodeId), XP.getPatchByPathUnsafe)(entryPath, project); | ||
var inputPinKeysByLabel = R.compose(R.map(XP.getPinKey), R.indexBy(R.pipe(XP.getPinLabel, _xodFuncTools.cppEscape, function (l) { | ||
return 'input_' + l; | ||
})), XP.normalizeEmptyPinLabels, XP.listInputPins)(patch); | ||
var doesAffectDirtyness = R.compose(function (_ref6) { | ||
var enabled = _ref6.enabled, | ||
exceptions = _ref6.exceptions; | ||
var inputPinKeys = R.map(XP.getLinkInputPinKey, linksFromSingleOutputToSameNode); | ||
var exceptionPinKeys = exceptions.map(function (l) { | ||
return inputPinKeysByLabel[l]; | ||
}); | ||
return enabled ? !exceptionPinKeys.some(function (pk) { | ||
return inputPinKeys.includes(pk); | ||
}) // if not ALL inputs are blacklisted | ||
: exceptionPinKeys.some(function (pk) { | ||
return inputPinKeys.includes(pk); | ||
}); // if at least one input is whitelisted | ||
}, _directives.getEvaluateOnPinSettings, (0, _xodFuncTools.explodeMaybe)('Implementation for ' + XP.getPatchPath(patch) + ' not found'), XP.getImpl)(patch); | ||
return { | ||
id: toInt(inputNodeId), | ||
doesAffectDirtyness: doesAffectDirtyness | ||
}; | ||
}), R.groupBy(XP.getLinkInputNodeId))(links); | ||
}); | ||
var getTNodeOutputs = (0, _types.def)('getTNodeOutputs :: Project -> PatchPath -> Node -> [TNodeOutput]', function (project, entryPath, node) { | ||
var nodeId = XP.getNodeId(node); | ||
var nodePins = getNodePinLabels(node, project); | ||
var nodePinLabels = getNodePinLabels(node, project); | ||
var nodePinTypes = R.compose(R.map(XP.getPinType), R.indexBy(XP.getPinKey), getNodePinsUnsafe)(node, project); | ||
return R.compose(R.values, R.mapObjIndexed(function (links, pinKey) { | ||
return { | ||
to: getLinksInputNodeIds(links), | ||
pinKey: nodePins[pinKey], | ||
type: nodePinTypes[pinKey], | ||
to: getTNodeOutputDestinations(links, project, entryPath), | ||
pinKey: nodePinLabels[pinKey], | ||
value: XP.getBoundValue(pinKey, node).getOrElse(getDefaultPinValue(pinKey, node, project)) | ||
@@ -225,3 +328,4 @@ }; | ||
var nodeId = XP.getNodeId(node); | ||
var nodePins = getNodePinLabels(node, project); | ||
var nodePinLabels = getNodePinLabels(node, project); | ||
var nodePinTypes = R.compose(R.map(XP.getPinType), R.indexBy(XP.getPinKey), getNodePinsUnsafe)(node, project); | ||
@@ -236,4 +340,5 @@ // :: Link -> TPatch | ||
var constructTNodeInput = R.applySpec({ | ||
type: R.compose(R.prop(R.__, nodePinTypes), XP.getLinkInputPinKey), | ||
originalPinKey: XP.getLinkInputPinKey, | ||
pinKey: R.compose(R.prop(R.__, nodePins), XP.getLinkInputPinKey), | ||
pinKey: R.compose(R.prop(R.__, nodePinLabels), XP.getLinkInputPinKey), | ||
fromNodeId: R.compose(toInt, XP.getLinkOutputNodeId), | ||
@@ -276,3 +381,3 @@ fromPatch: getUpstreamNodePatch, | ||
return downstreamTNode.patch.catchesErrors ? [downstreamTNode.id] : R.chain(findDownstreamErrorCatchersForOutput, downstreamTNode.outputs); | ||
}), R.propOr([], 'to'))(tNodeOutput); | ||
}), R.map(R.prop('id')), R.propOr([], 'to'))(tNodeOutput); | ||
} | ||
@@ -344,5 +449,5 @@ | ||
// :: Either Error TProject | ||
R.map(function (_ref) { | ||
var transformedProject = _ref.transformedProject, | ||
nodeIdsMap = _ref.nodeIdsMap; | ||
R.map(function (_ref7) { | ||
var transformedProject = _ref7.transformedProject, | ||
nodeIdsMap = _ref7.nodeIdsMap; | ||
@@ -362,3 +467,3 @@ var patches = createTPatches(path, transformedProject, project); | ||
// end preparing project for transpilation. TODO: extract it into a separate function | ||
R.map(removeUnusedNodes(path)), R.map(XP.extractBoundInputsToConstNodes(path)), R.chain(XP.flatten(R.__, path)), R.map(XP.expandVariadicNodes(path)), R.map(XP.jumperizePatchRecursively(path)), R.chain(XP.autoresolveTypes(path)), R.unless(function () { | ||
R.map(removeUnusedNodes(path)), R.chain(XP.squashTetheringNodes(path)), R.map(XP.extractBoundInputsToConstNodes(path)), R.chain(XP.flatten(R.__, path)), R.map(XP.expandVariadicNodes(path)), R.map(XP.linkifyPatchRecursively(path)), R.chain(XP.autoresolveTypes(path)), R.unless(function () { | ||
return liveness !== _constants.LIVENESS.NONE; | ||
@@ -403,7 +508,7 @@ }, R.map(XP.removeDebugNodes(path))), XP.validatePatchReqursively(path) | ||
*/ | ||
var getUpstreamPinPairsByPinPair = (0, _types.def)('getUpstreamPinPairsByPinPair :: Patch -> Project -> Object -> Maybe Object', function (currentPatch, project, _ref2) { | ||
var originalPinKey = _ref2.originalPinKey, | ||
upstreamErrorRaisers = _ref2.upstreamErrorRaisers, | ||
ownerNodeId = _ref2.ownerNodeId, | ||
ownerNodeType = _ref2.ownerNodeType; | ||
var getUpstreamPinPairsByPinPair = (0, _types.def)('getUpstreamPinPairsByPinPair :: Patch -> Project -> Object -> Maybe Object', function (currentPatch, project, _ref8) { | ||
var originalPinKey = _ref8.originalPinKey, | ||
upstreamErrorRaisers = _ref8.upstreamErrorRaisers, | ||
ownerNodeId = _ref8.ownerNodeId, | ||
ownerNodeType = _ref8.ownerNodeType; | ||
@@ -417,7 +522,7 @@ var parentNodeId = R.compose(R.join('~'), R.init, R.split('~'))(ownerNodeId); | ||
return R.compose(R.map(function (_ref3) { | ||
var _ref4 = _slicedToArray(_ref3, 3), | ||
pin = _ref4[0], | ||
node = _ref4[1], | ||
parentPatch = _ref4[2]; | ||
return R.compose(R.map(function (_ref9) { | ||
var _ref10 = _slicedToArray(_ref9, 3), | ||
pin = _ref10[0], | ||
node = _ref10[1], | ||
parentPatch = _ref10[2]; | ||
@@ -470,6 +575,6 @@ return R.compose(function (pinPairs) { | ||
// Get upstream PinPairGroups for them: | ||
_xodFuncTools.catMaybies, R.map(function (_ref5) { | ||
var _ref6 = _slicedToArray(_ref5, 2), | ||
_ = _ref6[0], | ||
node = _ref6[1]; | ||
_xodFuncTools.catMaybies, R.map(function (_ref11) { | ||
var _ref12 = _slicedToArray(_ref11, 2), | ||
_ = _ref12[0], | ||
node = _ref12[1]; | ||
@@ -476,0 +581,0 @@ return getUpstreamPinPairsByPinPair(currentPatch, project, { |
@@ -78,2 +78,5 @@ 'use strict'; | ||
isDirtyOnBoot: _sanctuaryDef2.default.Boolean | ||
// isTemplatableCustomTypePin: $.Boolean, | ||
// isOutputSelf: $.Boolean, | ||
// shortCirquitInputKey: $.String, | ||
}); | ||
@@ -85,2 +88,3 @@ | ||
isDirtyable: _sanctuaryDef2.default.Boolean | ||
// isTemplatableCustomTypePin: $.Boolean, | ||
}); | ||
@@ -100,6 +104,15 @@ | ||
requirements: _sanctuaryDef2.default.Array(_sanctuaryDef2.default.String) | ||
// isConstructor | ||
}); | ||
var TNodeOutputDestination = Model('TNodeOutputDestination', { | ||
id: TNodeId, | ||
doesAffectDirtyness: _sanctuaryDef2.default.Boolean | ||
}); | ||
// !!!: Before rendering program.tpl.cpp, data from corresponding | ||
// `TPatchOutput`s gets mixed in here by `mergePins` helper | ||
var TNodeOutput = Model('TNodeOutput', { | ||
to: _sanctuaryDef2.default.Array(TNodeId), | ||
type: _sanctuaryDef2.default.String, | ||
to: _sanctuaryDef2.default.Array(TNodeOutputDestination), | ||
pinKey: TPinKey, | ||
@@ -109,3 +122,6 @@ value: _sanctuaryDef2.default.Nullable(DataValue) | ||
// !!!: Before rendering program.tpl.cpp, data from corresponding | ||
// `TPatchInput`s gets mixed in here by `mergePins` helper | ||
var TNodeInput = Model('TNodeInput', { | ||
type: _sanctuaryDef2.default.String, | ||
pinKey: TPinKey, | ||
@@ -143,3 +159,3 @@ fromNodeId: TNodeId, | ||
//----------------------------------------------------------------------------- | ||
var env = _xodProject.env.concat([Liveness, TNodeId, TPinKey, TConfig, TPatchOutput, TPatchInput, TPatch, TNodeOutput, TNodeInput, TNode, TProject]); | ||
var env = _xodProject.env.concat([Liveness, TNodeId, TPinKey, TConfig, TPatchOutput, TPatchInput, TPatch, TNodeOutputDestination, TNodeOutput, TNodeInput, TNode, TProject]); | ||
@@ -146,0 +162,0 @@ var def = exports.def = _hmDef2.default.create({ |
{ | ||
"name": "xod-arduino", | ||
"version": "0.32.0", | ||
"version": "0.35.2", | ||
"description": "XOD project: Arduino transpiler", | ||
"scripts": { | ||
"build:nearley": "nearleyc src/implementationGrammar.ne -o src/implementationGrammar.ne.js", | ||
"build:js": "babel src/ -d dist/ --source-maps", | ||
"build:re": "bsb -make-world", | ||
"build": "yarn build:re && yarn build:js", | ||
"build": "yarn build:nearley && yarn build:re && yarn build:js", | ||
"dev:re": "yarn run build:re -w", | ||
@@ -24,17 +25,19 @@ "dev": "onchange \"src/**/*.js\" \"platform/**/*\" -- yarn run build:js", | ||
"@glennsl/bs-revamp": "^0.1.1", | ||
"belt-holes": "^0.29.0", | ||
"belt-holes": "^0.34.0", | ||
"handlebars": "^4.0.6", | ||
"hm-def": "^0.3.2", | ||
"moo": "^0.5.1", | ||
"nearley": "^2.19.6", | ||
"ramda": "^0.24.1", | ||
"ramda-fantasy": "^0.8.0", | ||
"sanctuary-def": "^0.14.0", | ||
"xod-func-tools": "^0.32.0", | ||
"xod-project": "^0.32.0" | ||
"xod-func-tools": "^0.34.0", | ||
"xod-project": "^0.35.2" | ||
}, | ||
"devDependencies": { | ||
"babel-plugin-inline-import": "^2.0.4", | ||
"bs-platform": "5.0.0", | ||
"bs-platform": "7.1.1", | ||
"chai": "^4.1.2", | ||
"onchange": "^5.2.0", | ||
"xod-fs": "^0.32.0" | ||
"xod-fs": "^0.35.2" | ||
}, | ||
@@ -41,0 +44,0 @@ "files": [ |
@@ -1,2 +0,2 @@ | ||
// Generated by BUCKLESCRIPT VERSION 5.0.0, PLEASE EDIT WITH CARE | ||
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE | ||
'use strict'; | ||
@@ -6,4 +6,13 @@ | ||
var Belt_Array = require("bs-platform/lib/js/belt_Array.js"); | ||
var Belt_SetString = require("bs-platform/lib/js/belt_SetString.js"); | ||
var Directives$XodArduino = require("./Directives.bs.js"); | ||
function getEvaluateOnPinSettings(code) { | ||
var param = Directives$XodArduino.getEvaluateOnPinSettings(code); | ||
return { | ||
enabled: param.enabled, | ||
exceptions: Belt_SetString.toArray(param.exceptions) | ||
}; | ||
} | ||
function findXodPragmas(code) { | ||
@@ -33,2 +42,3 @@ return Belt_Array.map(Belt_List.toArray(Directives$XodArduino.findXodPragmas(code)), Belt_List.toArray); | ||
exports.doesRaiseErrors = doesRaiseErrors; | ||
exports.getEvaluateOnPinSettings = getEvaluateOnPinSettings; | ||
exports.areTimeoutsEnabled = areTimeoutsEnabled; | ||
@@ -35,0 +45,0 @@ exports.stripCppComments = stripCppComments; |
@@ -1,2 +0,2 @@ | ||
// Generated by BUCKLESCRIPT VERSION 5.0.0, PLEASE EDIT WITH CARE | ||
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE | ||
'use strict'; | ||
@@ -8,10 +8,11 @@ | ||
var Caml_option = require("bs-platform/lib/js/caml_option.js"); | ||
var Belt_SetString = require("bs-platform/lib/js/belt_SetString.js"); | ||
function toBoolean(hint, $$default) { | ||
switch (hint) { | ||
case 0 : | ||
case /* Enable */0 : | ||
return true; | ||
case 1 : | ||
case /* Disable */1 : | ||
return false; | ||
case 2 : | ||
case /* Auto */2 : | ||
return $$default; | ||
@@ -24,5 +25,5 @@ | ||
switch (tok) { | ||
case "disable" : | ||
case "disable" : | ||
return /* Disable */1; | ||
case "enable" : | ||
case "enable" : | ||
return /* Enable */0; | ||
@@ -92,6 +93,2 @@ default: | ||
function isOutput(identifier) { | ||
return test(undefined, identifier, "^output_"); | ||
} | ||
function tokenizePragma(pragmaLine) { | ||
@@ -139,3 +136,3 @@ return Belt_List.map(matches(undefined, remove(undefined, pragmaLine, pragmaHeadRegexp), "[\\w._-]+|\".*?\""), (function (token) { | ||
function isDirtienessEnabled(code, identifier) { | ||
return Belt_List.reduce(findXodPragmas(code), isOutput(identifier) || doesReferTemplateSymbol("isInputDirty", identifier, code), (function (acc, pragma) { | ||
return Belt_List.reduce(findXodPragmas(code), test(undefined, identifier, "^output_") || doesReferTemplateSymbol("isInputDirty", identifier, code), (function (acc, pragma) { | ||
if (pragma && pragma[0] === "dirtieness") { | ||
@@ -160,2 +157,49 @@ var match = pragma[1]; | ||
function getEvaluateOnPinSettings(code) { | ||
return Belt_List.reduce(filterPragmasByFeature(findXodPragmas(code), "evaluate_on_pin"), { | ||
enabled: true, | ||
exceptions: Belt_SetString.empty | ||
}, (function (acc, pragma) { | ||
if (pragma) { | ||
var match = pragma[1]; | ||
if (match) { | ||
switch (match[0]) { | ||
case "disable" : | ||
var disabledPins = match[1]; | ||
if (disabledPins) { | ||
return { | ||
enabled: acc.enabled, | ||
exceptions: acc.enabled ? Belt_SetString.mergeMany(acc.exceptions, Belt_List.toArray(disabledPins)) : Belt_SetString.removeMany(acc.exceptions, Belt_List.toArray(disabledPins)) | ||
}; | ||
} else { | ||
return { | ||
enabled: false, | ||
exceptions: Belt_SetString.empty | ||
}; | ||
} | ||
case "enable" : | ||
var enabledPins = match[1]; | ||
if (enabledPins) { | ||
return { | ||
enabled: acc.enabled, | ||
exceptions: acc.enabled ? Belt_SetString.removeMany(acc.exceptions, Belt_List.toArray(enabledPins)) : Belt_SetString.mergeMany(acc.exceptions, Belt_List.toArray(enabledPins)) | ||
}; | ||
} else { | ||
return { | ||
enabled: true, | ||
exceptions: Belt_SetString.empty | ||
}; | ||
} | ||
default: | ||
return acc; | ||
} | ||
} else { | ||
return acc; | ||
} | ||
} else { | ||
return acc; | ||
} | ||
})); | ||
} | ||
function doesCatchErrors(code) { | ||
@@ -171,4 +215,3 @@ return toBoolean(lastPragmaEndis(code, "error_catch"), doesReferSymbol("getError", code)); | ||
var url = match[0]; | ||
var match$1 = test(undefined, url, "^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$"); | ||
if (match$1) { | ||
if (test(undefined, url, "^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$")) { | ||
return /* :: */[ | ||
@@ -190,3 +233,3 @@ url, | ||
var Pragma = []; | ||
var Pragma = { }; | ||
@@ -200,4 +243,5 @@ exports.Pragma = Pragma; | ||
exports.findXodPragmas = findXodPragmas; | ||
exports.getEvaluateOnPinSettings = getEvaluateOnPinSettings; | ||
exports.findRequireUrls = findRequireUrls; | ||
exports.stripCppComments = stripCppComments; | ||
/* No side effect */ |
@@ -10,2 +10,20 @@ import * as R from 'ramda'; | ||
// Convert char literals to decimal byte literals | ||
// E.G. `'a'` -> `97d` | ||
const charLiteralToByteLiteral = R.when( | ||
XP.isLikeCharLiteral, | ||
R.compose( | ||
R.concat(R.__, 'd'), | ||
R.toString, | ||
a => a.charCodeAt(0), | ||
R.nth(1), | ||
R.match(XP.charLiteralRegExp) | ||
) | ||
); | ||
const formatByteLiteral = R.compose( | ||
byteLiteralToDecimal, | ||
charLiteralToByteLiteral | ||
); | ||
export default def( | ||
@@ -15,3 +33,2 @@ 'formatTweakMessage :: PatchPath -> NodeId -> DataValue -> String', | ||
const prefix = `+XOD:${nodeId}`; | ||
switch (XP.getTweakType(nodeType)) { | ||
@@ -23,3 +40,3 @@ case XP.PIN_TYPE.NUMBER: | ||
case XP.PIN_TYPE.BYTE: | ||
return `${prefix}:${byteLiteralToDecimal(value)}\r\n`; | ||
return `${prefix}:${formatByteLiteral(value)}\r\n`; | ||
case XP.PIN_TYPE.PULSE: | ||
@@ -33,2 +50,9 @@ return `${prefix}\r\n`; | ||
)(value); | ||
case XP.BINDABLE_CUSTOM_TYPES.COLOR: | ||
return R.compose( | ||
([r, g, b]) => `${prefix}:${r},${g},${b}\r\n`, | ||
R.map(x => parseInt(x, 16)), | ||
R.splitEvery(2), | ||
R.tail | ||
)(value); | ||
default: | ||
@@ -35,0 +59,0 @@ return ''; |
@@ -10,2 +10,4 @@ export { | ||
extendTProjectWithGlobals, | ||
hasTetheringInternetNode, | ||
getTetheringInetNodeId, | ||
} from './transpiler'; | ||
@@ -12,0 +14,0 @@ |
@@ -9,4 +9,11 @@ import * as R from 'ramda'; | ||
import parseImplementation from './parseImplementation'; | ||
import parseLegacyImplementation from './parseLegacyImplementation'; | ||
import configTpl from '../platform/configuration.tpl.cpp'; | ||
import patchContextTpl from '../platform/patchContext.tpl.cpp'; | ||
import patchPinTypesTpl from '../platform/patchPinTypes.tpl.cpp'; | ||
import patchTemplateDefinitionTpl from '../platform/patchTemplateDefinition.tpl.cpp'; | ||
import legacyPatchTpl from '../platform/patch.legacy.tpl.cpp'; | ||
import patchTpl from '../platform/patch.tpl.cpp'; | ||
import implListTpl from '../platform/implList.tpl.cpp'; | ||
@@ -75,3 +82,3 @@ import programTpl from '../platform/program.tpl.cpp'; | ||
const builtInTypeNames = { | ||
[XP.PIN_TYPE.PULSE]: 'Logic', | ||
[XP.PIN_TYPE.PULSE]: 'Pulse', | ||
[XP.PIN_TYPE.BOOLEAN]: 'Logic', | ||
@@ -91,6 +98,8 @@ [XP.PIN_TYPE.NUMBER]: 'Number', | ||
// it is a custom type | ||
R.pipe(patchPathToNSName, ns => `${ns}::Type`) | ||
R.pipe(patchPathToNSName, ns => `${ns}::Node::Type`) | ||
) | ||
); | ||
const escapeCppString = str => R.replace(/"/g, '\\"', unquote(str)); | ||
// Formats a plain JS string into C++ string object | ||
@@ -110,3 +119,3 @@ const cppStringLiteral = def( | ||
// All other strings: "Hello, world" | ||
[R.T, str => `XStringCString("${R.replace(/"/g, '\\"', unquote(str))}")`], | ||
[R.T, str => `XStringCString("${escapeCppString(str)}")`], | ||
]) | ||
@@ -248,7 +257,16 @@ ); | ||
[XP.PIN_TYPE.PORT]: cppPortLiteral, | ||
[XP.BINDABLE_CUSTOM_TYPES.COLOR]: R.compose( | ||
rgb => `/* RGB */ { ${rgb} }`, | ||
R.join(', '), | ||
R.map(R.concat('0x')), | ||
R.splitEvery(2), | ||
R.tail | ||
), | ||
})(value) | ||
); | ||
Handlebars.registerHelper('escapeCppString', escapeCppString); | ||
const hasUpstreamErrorRaisers = nodeOrInput => | ||
nodeOrInput.upstreamErrorRaisers.length > 0; | ||
R.pathOr(0, ['upstreamErrorRaisers', 'length'], nodeOrInput) > 0; | ||
@@ -262,13 +280,98 @@ Handlebars.registerHelper('hasUpstreamErrorRaisers', hasUpstreamErrorRaisers); | ||
const isTweakNode = R.pipe(R.path(['patch', 'patchPath']), XP.isTweakPath); | ||
const isOutputLinked = R.pipe(R.pathOr(0, ['to', 'length'])); | ||
Handlebars.registerHelper('isTweakNode', isTweakNode); | ||
Handlebars.registerHelper( | ||
'shouldOutputStoreDirtyness', | ||
R.both( | ||
isOutputLinked, | ||
R.propSatisfies(R.any(R.prop('doesAffectDirtyness')), 'to') | ||
) | ||
); | ||
const isLinkedTweakNode = R.both( | ||
R.pipe(R.path(['patch', 'patchPath']), XP.isTweakPath), | ||
R.pathSatisfies(isOutputLinked, ['outputs', 0]) | ||
); | ||
Handlebars.registerHelper('isLinkedTweakNode', isLinkedTweakNode); | ||
const isTweakStringNode = R.pipe( | ||
R.path(['patch', 'patchPath']), | ||
XP.getTweakType, | ||
R.equals(XP.PIN_TYPE.STRING) | ||
); | ||
Handlebars.registerHelper('isTweakStringNode', isTweakStringNode); | ||
Handlebars.registerHelper('isPulse', R.equals(XP.PIN_TYPE.PULSE)); | ||
const isTemplatableCustomTypePin = R.prop('isTemplatableCustomTypePin'); | ||
Handlebars.registerHelper( | ||
'isTemplatableCustomTypePin', | ||
isTemplatableCustomTypePin | ||
); | ||
Handlebars.registerHelper( | ||
'templatableCustomTypeInputs', | ||
R.filter(isTemplatableCustomTypePin) | ||
); | ||
Handlebars.registerHelper( | ||
'containsTemplatableCustomTypeInputs', | ||
R.pipe(R.filter(isTemplatableCustomTypePin), R.isEmpty, R.not) | ||
); | ||
const isConstantType = type => XP.CONSTANT_PIN_TYPES.includes(type); | ||
Handlebars.registerHelper('isConstantType', isConstantType); | ||
const isConstantPin = ({ type }) => isConstantType(type); | ||
Handlebars.registerHelper('constantInputs', R.filter(isConstantPin)); | ||
Handlebars.registerHelper( | ||
'containsConstantInputs', | ||
R.pipe(R.filter(isConstantPin), R.isEmpty, R.not) | ||
); | ||
Handlebars.registerHelper( | ||
'indent', | ||
R.compose( | ||
R.join('\n'), | ||
R.map(R.unless(R.isEmpty, str => ` ${str}`)), | ||
R.split('\n') | ||
) | ||
); | ||
Handlebars.registerHelper('unindent', str => str.replace(/^( {1,4}|\t)/gm, '')); | ||
Handlebars.registerHelper({ | ||
eq: (v1, v2) => v1 === v2, | ||
ne: (v1, v2) => v1 !== v2, | ||
lt: (v1, v2) => v1 < v2, | ||
gt: (v1, v2) => v1 > v2, | ||
lte: (v1, v2) => v1 <= v2, | ||
gte: (v1, v2) => v1 >= v2, | ||
and(...args) { | ||
return Array.prototype.every.call(args, Boolean); | ||
}, | ||
or(...args) { | ||
return Array.prototype.slice.call(args, 0, -1).some(Boolean); | ||
}, | ||
}); | ||
// A helper to quickly introduce a new filtered {{each ...}} loop | ||
function registerHandlebarsFilterLoopHelper(name, predicate) { | ||
Handlebars.registerHelper(name, (list, block) => | ||
R.compose(R.join(''), R.map(node => block.fn(node)), R.filter(predicate))( | ||
list | ||
) | ||
); | ||
Handlebars.registerHelper(name, (list, block) => { | ||
const filteredList = R.filter(predicate, list); | ||
const lastIndex = filteredList.length - 1; | ||
return filteredList | ||
.map((node, index) => | ||
block.fn(node, { | ||
data: { index, first: index === 0, last: index === lastIndex }, | ||
}) | ||
) | ||
.join(''); | ||
}); | ||
} | ||
@@ -288,3 +391,4 @@ | ||
); | ||
registerHandlebarsFilterLoopHelper('eachTweakNode', isTweakNode); | ||
registerHandlebarsFilterLoopHelper('eachLinkedTweakNode', isLinkedTweakNode); | ||
registerHandlebarsFilterLoopHelper('eachTweakStringNode', isTweakStringNode); | ||
registerHandlebarsFilterLoopHelper('eachLinkedInput', R.has('fromNodeId')); | ||
@@ -304,3 +408,28 @@ registerHandlebarsFilterLoopHelper( | ||
); | ||
registerHandlebarsFilterLoopHelper( | ||
'eachNonPulse', | ||
R.complement(R.propEq('type', XP.PIN_TYPE.PULSE)) | ||
); | ||
registerHandlebarsFilterLoopHelper( | ||
'eachNonPulseOrConstant', | ||
({ type }) => type !== XP.PIN_TYPE.PULSE && !isConstantType(type) | ||
); | ||
Handlebars.registerPartial( | ||
'patchTemplateDefinition', | ||
patchTemplateDefinitionTpl | ||
); | ||
export const withTetheringInetNode = R.find( | ||
R.both( | ||
R.pipe(R.path(['patch', 'patchPath']), XP.isTetheringInetPatchPath), | ||
R.pathSatisfies(isOutputLinked, ['outputs', 0]) | ||
) | ||
); | ||
Handlebars.registerHelper('withTetheringInetNode', (nodes, block) => | ||
R.compose(R.ifElse(R.isNil, block.inverse, block.fn), withTetheringInetNode)( | ||
nodes | ||
) | ||
); | ||
// ============================================================================= | ||
@@ -320,3 +449,6 @@ // | ||
patchContext: Handlebars.compile(patchContextTpl, renderingOptions), | ||
patchPinTypes: Handlebars.compile(patchPinTypesTpl, renderingOptions), | ||
implList: Handlebars.compile(implListTpl, renderingOptions), | ||
patchImpl: Handlebars.compile(patchTpl, renderingOptions), | ||
legacyPatchImpl: Handlebars.compile(legacyPatchTpl, renderingOptions), | ||
program: Handlebars.compile(programTpl, renderingOptions), | ||
@@ -338,10 +470,41 @@ }; | ||
); | ||
export const renderImpl = def('renderImpl :: TPatch -> String', data => { | ||
const ctx = R.applySpec({ | ||
patchPath: R.prop('patchPath'), | ||
GENERATED_CODE: renderPatchContext, | ||
})(data); | ||
const patchImpl = R.prop('impl', data); | ||
return Handlebars.compile(patchImpl, renderingOptions)(ctx); | ||
export const renderPatchPinTypes = def( | ||
'renderPatchPinTypes :: TPatch -> String', | ||
templates.patchPinTypes | ||
); | ||
const generatedCodeRegEx = /^\s*{{\s*GENERATED_CODE\s*}}\s*$/gm; | ||
export const renderImpl = def('renderImpl :: TPatch -> String', tPatch => { | ||
const impl = R.prop('impl', tPatch); | ||
const generatedCode = renderPatchContext(tPatch); | ||
const patchPinTypes = renderPatchPinTypes(tPatch); | ||
const isLegacyImplementation = R.test(generatedCodeRegEx, impl); | ||
if (isLegacyImplementation) { | ||
const parsedImpl = R.compose( | ||
parseLegacyImplementation, | ||
R.replace(/ValueType<(input|output)_(.*)>::T/g, 'typeof_$2') | ||
)(impl); | ||
const ctx = R.merge( | ||
{ | ||
patch: tPatch, | ||
generatedCode, | ||
patchPinTypes, | ||
}, | ||
parsedImpl | ||
); | ||
return templates.legacyPatchImpl(ctx); | ||
} | ||
return templates.patchImpl({ | ||
patch: tPatch, | ||
generatedCode, | ||
patchPinTypes, | ||
implBlocks: parseImplementation(impl), | ||
}); | ||
}); | ||
@@ -369,2 +532,4 @@ export const renderImplList = def( | ||
const impls = renderImplList(project.patches); | ||
// TODO: right at the beginning of `program.tpl.cpp` | ||
// TNode pins are mutated by mergePins helper | ||
const program = renderProgram(project.nodes); | ||
@@ -371,0 +536,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Generated by BUCKLESCRIPT VERSION 5.0.0, PLEASE EDIT WITH CARE | ||
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE | ||
'use strict'; | ||
@@ -12,7 +12,7 @@ | ||
switch (liveness) { | ||
case 0 : | ||
case /* None */0 : | ||
return "NONE"; | ||
case 1 : | ||
case /* Debug */1 : | ||
return "DEBUG"; | ||
case 2 : | ||
case /* Simulation */2 : | ||
return "SIMULATION"; | ||
@@ -25,6 +25,6 @@ | ||
return BeltHoles_Result.map(Either$XodFuncTools.toResult($dot$dot.transformProject(project, patchPath, getLivenessString(liveness), xodGlobals)), (function (tProject) { | ||
return /* record */[ | ||
/* code */$dot$dot.transpile(tProject), | ||
/* nodeIdMap */Belt_MapString.fromArray(Js_dict.entries($dot$dot.getNodeIdsMap(tProject))) | ||
]; | ||
return { | ||
code: $dot$dot.transpile(tProject), | ||
nodeIdMap: Belt_MapString.fromArray(Js_dict.entries($dot$dot.getNodeIdsMap(tProject))) | ||
}; | ||
})); | ||
@@ -31,0 +31,0 @@ } |
@@ -8,2 +8,3 @@ import * as R from 'ramda'; | ||
maybeProp, | ||
maybeFind, | ||
foldEither, | ||
@@ -19,3 +20,3 @@ foldMaybe, | ||
import { renderProject } from './templates'; | ||
import { withTetheringInetNode, renderProject } from './templates'; | ||
import { LIVENESS } from './constants'; | ||
@@ -28,2 +29,3 @@ | ||
isDirtienessEnabled, | ||
getEvaluateOnPinSettings, | ||
doesCatchErrors, | ||
@@ -47,7 +49,2 @@ findRequireUrls, | ||
const getLinksInputNodeIds = def( | ||
'getLinksInputNodeIds :: [Link] -> [TNodeId]', | ||
R.compose(R.uniq, R.map(R.compose(toInt, XP.getLinkInputNodeId))) | ||
); | ||
const getPatchByNodeId = def( | ||
@@ -83,2 +80,14 @@ 'getPatchByNodeId :: Project -> PatchPath -> [TPatch] -> NodeId -> TPatch', | ||
export const hasTetheringInternetNode = def( | ||
'hasTetheringInternetNode :: TProject -> Boolean', | ||
R.compose(R.not, R.isNil, withTetheringInetNode, R.prop('nodes')) | ||
); | ||
// :: TProject -> Nullable Int | ||
export const getTetheringInetNodeId = R.compose( | ||
R.unless(R.isNil, R.prop('id')), | ||
withTetheringInetNode, | ||
R.prop('nodes') | ||
); | ||
//----------------------------------------------------------------------------- | ||
@@ -184,2 +193,3 @@ // | ||
// :: Patch -> [PatchPath] | ||
// todo: the name is incorrect | ||
const getReferencedCustomTypes = R.compose(R.map(XP.getPinType), XP.listPins); | ||
@@ -245,2 +255,3 @@ | ||
R.compose( | ||
R.assoc('isConstructor', true), // todo: do this in a separate function? | ||
convertPatchToTPatch, | ||
@@ -253,2 +264,78 @@ XP.getPatchByPathUnsafe(R.__, originalProject) | ||
// :: [TPatch] -> Set PatchPath | ||
const listTemplatableCustomTypes = toposortedTPatches => { | ||
const constructorPatches = R.filter( | ||
R.prop('isConstructor'), | ||
toposortedTPatches | ||
); | ||
const templatableCustomTypes = new Set(); | ||
// because patches are toposorted, we can do this in a single pass | ||
constructorPatches.forEach(({ inputs, patchPath }) => { | ||
const isTemplatable = R.any( | ||
({ type }) => | ||
XP.CONSTANT_PIN_TYPES.includes(type) || | ||
templatableCustomTypes.has(type), | ||
inputs | ||
); | ||
if (isTemplatable) { | ||
templatableCustomTypes.add(patchPath); | ||
} | ||
}); | ||
return templatableCustomTypes; | ||
}; | ||
const assignPinFlags = toposortedTPatches => { | ||
const templatableCustomTypes = listTemplatableCustomTypes(toposortedTPatches); | ||
if (R.isEmpty(templatableCustomTypes)) { | ||
return toposortedTPatches; | ||
} | ||
const isTemplatableCustomTypePin = ({ type }) => | ||
templatableCustomTypes.has(type); | ||
return R.map( | ||
R.compose( | ||
tPatch => | ||
R.over( | ||
R.lensProp('outputs'), | ||
R.map(pin => { | ||
const pinFlags = R.applySpec({ | ||
// "output-self" type is erased in createPinFromTerminalNode | ||
// (pin type becomes the same as the patch path) | ||
isOutputSelf: ({ type }) => type === tPatch.patchPath, | ||
isTemplatableCustomTypePin, | ||
// Finds matching input, like DEV and DEV' | ||
shortCirquitInputKey: ({ type, pinKey }) => | ||
R.compose( | ||
foldMaybe('', R.prop('pinKey')), | ||
maybeFind( | ||
i => i.type === type && `${i.pinKey}U0027` === pinKey | ||
) | ||
)(tPatch.inputs), | ||
})(pin); | ||
return R.merge(pinFlags, pin); | ||
}), | ||
tPatch | ||
), | ||
R.over( | ||
R.lensProp('inputs'), | ||
R.map(pin => | ||
R.assoc( | ||
'isTemplatableCustomTypePin', | ||
isTemplatableCustomTypePin(pin), | ||
pin | ||
) | ||
) | ||
) | ||
), | ||
toposortedTPatches | ||
); | ||
}; | ||
const createTPatches = def( | ||
@@ -258,2 +345,3 @@ 'createTPatches :: PatchPath -> Project -> Project -> [TPatch]', | ||
R.compose( | ||
assignPinFlags, | ||
// Include constructor patches for custom types | ||
@@ -321,2 +409,53 @@ // that are used without an explicit constructor. | ||
const getTNodeOutputDestinations = def( | ||
'getTNodeOutputDestinations :: [Link] -> Project -> PatchPath -> [TNodeOutputDestination]', | ||
(links, project, entryPath) => | ||
R.compose( | ||
R.values, | ||
R.mapObjIndexed((linksFromSingleOutputToSameNode, inputNodeId) => { | ||
const patch = R.compose( | ||
XP.getPatchByPathUnsafe(R.__, project), | ||
XP.getNodeType, | ||
XP.getNodeByIdUnsafe(inputNodeId), | ||
XP.getPatchByPathUnsafe | ||
)(entryPath, project); | ||
const inputPinKeysByLabel = R.compose( | ||
R.map(XP.getPinKey), | ||
R.indexBy(R.pipe(XP.getPinLabel, cppEscape, l => `input_${l}`)), | ||
XP.normalizeEmptyPinLabels, | ||
XP.listInputPins | ||
)(patch); | ||
const doesAffectDirtyness = R.compose( | ||
({ enabled, exceptions }) => { | ||
const inputPinKeys = R.map( | ||
XP.getLinkInputPinKey, | ||
linksFromSingleOutputToSameNode | ||
); | ||
const exceptionPinKeys = exceptions.map( | ||
l => inputPinKeysByLabel[l] | ||
); | ||
return enabled | ||
? !exceptionPinKeys.some(pk => inputPinKeys.includes(pk)) // if not ALL inputs are blacklisted | ||
: exceptionPinKeys.some(pk => inputPinKeys.includes(pk)); // if at least one input is whitelisted | ||
}, | ||
getEvaluateOnPinSettings, | ||
explodeMaybe( | ||
`Implementation for ${XP.getPatchPath(patch)} not found` | ||
), | ||
XP.getImpl | ||
)(patch); | ||
return { | ||
id: toInt(inputNodeId), | ||
doesAffectDirtyness, | ||
}; | ||
}), | ||
R.groupBy(XP.getLinkInputNodeId) | ||
)(links) | ||
); | ||
const getTNodeOutputs = def( | ||
@@ -326,3 +465,8 @@ 'getTNodeOutputs :: Project -> PatchPath -> Node -> [TNodeOutput]', | ||
const nodeId = XP.getNodeId(node); | ||
const nodePins = getNodePinLabels(node, project); | ||
const nodePinLabels = getNodePinLabels(node, project); | ||
const nodePinTypes = R.compose( | ||
R.map(XP.getPinType), | ||
R.indexBy(XP.getPinKey), | ||
getNodePinsUnsafe | ||
)(node, project); | ||
@@ -332,4 +476,5 @@ return R.compose( | ||
R.mapObjIndexed((links, pinKey) => ({ | ||
to: getLinksInputNodeIds(links), | ||
pinKey: nodePins[pinKey], | ||
type: nodePinTypes[pinKey], | ||
to: getTNodeOutputDestinations(links, project, entryPath), | ||
pinKey: nodePinLabels[pinKey], | ||
value: XP.getBoundValue(pinKey, node).getOrElse( | ||
@@ -373,3 +518,8 @@ getDefaultPinValue(pinKey, node, project) | ||
const nodeId = XP.getNodeId(node); | ||
const nodePins = getNodePinLabels(node, project); | ||
const nodePinLabels = getNodePinLabels(node, project); | ||
const nodePinTypes = R.compose( | ||
R.map(XP.getPinType), | ||
R.indexBy(XP.getPinKey), | ||
getNodePinsUnsafe | ||
)(node, project); | ||
@@ -387,4 +537,5 @@ // :: Link -> TPatch | ||
const constructTNodeInput = R.applySpec({ | ||
type: R.compose(R.prop(R.__, nodePinTypes), XP.getLinkInputPinKey), | ||
originalPinKey: XP.getLinkInputPinKey, | ||
pinKey: R.compose(R.prop(R.__, nodePins), XP.getLinkInputPinKey), | ||
pinKey: R.compose(R.prop(R.__, nodePinLabels), XP.getLinkInputPinKey), | ||
fromNodeId: R.compose(toInt, XP.getLinkOutputNodeId), | ||
@@ -467,2 +618,3 @@ fromPatch: getUpstreamNodePatch, | ||
}), | ||
R.map(R.prop('id')), | ||
R.propOr([], 'to') | ||
@@ -609,6 +761,7 @@ )(tNodeOutput); | ||
R.map(removeUnusedNodes(path)), | ||
R.chain(XP.squashTetheringNodes(path)), | ||
R.map(XP.extractBoundInputsToConstNodes(path)), | ||
R.chain(XP.flatten(R.__, path)), | ||
R.map(XP.expandVariadicNodes(path)), | ||
R.map(XP.jumperizePatchRecursively(path)), | ||
R.map(XP.linkifyPatchRecursively(path)), | ||
R.chain(XP.autoresolveTypes(path)), | ||
@@ -615,0 +768,0 @@ R.unless( |
@@ -59,2 +59,5 @@ import * as R from 'ramda'; | ||
isDirtyOnBoot: $.Boolean, | ||
// isTemplatableCustomTypePin: $.Boolean, | ||
// isOutputSelf: $.Boolean, | ||
// shortCirquitInputKey: $.String, | ||
}); | ||
@@ -66,2 +69,3 @@ | ||
isDirtyable: $.Boolean, | ||
// isTemplatableCustomTypePin: $.Boolean, | ||
}); | ||
@@ -81,6 +85,15 @@ | ||
requirements: $.Array($.String), | ||
// isConstructor | ||
}); | ||
const TNodeOutputDestination = Model('TNodeOutputDestination', { | ||
id: TNodeId, | ||
doesAffectDirtyness: $.Boolean, | ||
}); | ||
// !!!: Before rendering program.tpl.cpp, data from corresponding | ||
// `TPatchOutput`s gets mixed in here by `mergePins` helper | ||
const TNodeOutput = Model('TNodeOutput', { | ||
to: $.Array(TNodeId), | ||
type: $.String, | ||
to: $.Array(TNodeOutputDestination), | ||
pinKey: TPinKey, | ||
@@ -90,3 +103,6 @@ value: $.Nullable(DataValue), | ||
// !!!: Before rendering program.tpl.cpp, data from corresponding | ||
// `TPatchInput`s gets mixed in here by `mergePins` helper | ||
const TNodeInput = Model('TNodeInput', { | ||
type: $.String, | ||
pinKey: TPinKey, | ||
@@ -132,2 +148,3 @@ fromNodeId: TNodeId, | ||
TPatch, | ||
TNodeOutputDestination, | ||
TNodeOutput, | ||
@@ -134,0 +151,0 @@ TNodeInput, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
505637
71
3869
11
+ Addedmoo@^0.5.1
+ Addednearley@^2.19.6
+ Addedbelt-holes@0.34.0(transitive)
+ Addedxod-func-tools@0.34.0(transitive)
+ Addedxod-project@0.35.2(transitive)
- Removedbelt-holes@0.29.0(transitive)
- Removedxod-func-tools@0.32.0(transitive)
- Removedxod-project@0.32.0(transitive)
Updatedbelt-holes@^0.34.0
Updatedxod-func-tools@^0.34.0
Updatedxod-project@^0.35.2