@buggyorg/functional
Advanced tools
Comparing version
@@ -6,2 +6,5 @@ 'use strict'; | ||
}); | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; | ||
exports.inner = inner; | ||
@@ -38,11 +41,23 @@ exports.functionType = functionType; | ||
function backtrackLambda(graph, node) { | ||
return _graphtools.walk.walkBack(graph, node, function (graph, node) { | ||
return _graphtools.walk.walkBack(graph, node, function (graph, node, port) { | ||
var lambdaPort = graph.parent(node) && graph.node(graph.parent(node)).isLambda; | ||
if (graph.node(node).id === 'functional/lambda') { | ||
return []; | ||
} | ||
var functions = _lodash2.default.invert(graph.node(node).inputPorts || { function: [] })['function']; | ||
var generics = _lodash2.default.invert(graph.node(node).inputPorts || { generic: [] })['generic']; | ||
var ports = _lodash2.default.compact(_lodash2.default.map(_lodash2.default.flatten(_lodash2.default.concat(functions, generics)), function (v) { | ||
var functions = (_lodash2.default.invertBy(graph.node(node).inputPorts) || { function: [] })['function']; | ||
var generics = (_lodash2.default.invertBy(graph.node(node).inputPorts) || { generic: [] })['generic']; | ||
var ports = _lodash2.default.compact(_lodash2.default.map(_lodash2.default.flatten(_lodash2.default.compact(_lodash2.default.concat(functions, generics))), function (v) { | ||
return '' + v; | ||
})); | ||
if (!graph.node(node).atomic && port) { | ||
ports = _lodash2.default.filter(ports, function (p) { | ||
return p === port; | ||
}); | ||
} | ||
if (graph.node(node).id === 'functional/partial' && port === 'value') { | ||
return ['value']; | ||
} | ||
if (lambdaPort) { | ||
return []; | ||
} | ||
if (ports.length === 0) { | ||
@@ -52,3 +67,3 @@ return null; | ||
return ports; | ||
}); | ||
}, { keepPorts: true }); | ||
} | ||
@@ -93,15 +108,34 @@ | ||
var findFunctionType = function findFunctionType(graph, meta) { | ||
if (meta.type === 'reference') { | ||
return meta; | ||
} | ||
var node = (0, _lodash2.default)(graph.nodes()).map(function (n) { | ||
return { v: n, value: graph.node(n) }; | ||
}).find(function (n) { | ||
return n.value.id === meta; | ||
return n.value.branchPath === meta; | ||
}); | ||
var rKeys = _lodash2.default.keys(node.value.outputPorts); | ||
var mapGenerics = function mapGenerics(type, key) { | ||
if (type === 'generic') { | ||
return { type: 'type-ref', node: meta, port: key }; | ||
} | ||
return type; | ||
}; | ||
var ins = _lodash2.default.mapValues(node.value.inputPorts, mapGenerics); | ||
var outs = _lodash2.default.mapValues(node.value.outputPorts, mapGenerics); | ||
var rKeys = _lodash2.default.keys(outs); | ||
return { | ||
arguments: node.value.inputPorts, | ||
return: rKeys.length === 1 ? node.value.outputPorts[rKeys[0]] : node.value.outputPorts | ||
type: 'function', | ||
arguments: ins, | ||
outputs: outs, | ||
return: rKeys.length === 1 ? outs[rKeys[0]] : outs | ||
}; | ||
}; | ||
function isFunctionType(type) { | ||
return (typeof type === 'undefined' ? 'undefined' : _typeof(type)) === 'object' && type.type === 'function'; | ||
} | ||
function portmapToEdges(graph, innerNode, portmap) { | ||
@@ -134,26 +168,159 @@ return _lodash2.default.flatten(_lodash2.default.map(portmap, function (pm) { | ||
var updatePorts = function updatePorts(node, ports, applys) { | ||
return _lodash2.default.mapValues(ports, function (p) { | ||
if (p === 'function' || p === 'generic') { | ||
return applys[node].type; | ||
} else if (p === 'function:return') { | ||
return applys[node].type.return; | ||
var updatePorts = function updatePorts(node, ports, apply) { | ||
return _lodash2.default.mapValues(ports, function (p, portName) { | ||
var srcType = apply.types[apply.index]; | ||
var type; | ||
if (p === 'function' || p === 'generic' || p === 'function|function:return' && _lodash2.default.keys(srcType.arguments).length > 1) { | ||
if (p === 'generic' && apply.lambda.port !== portName) { | ||
return 'generic'; | ||
} | ||
if (p === 'function|function:return') { | ||
type = _lodash2.default.merge({}, _lodash2.default.omit(srcType, ['arguments', 'newArguments']), { arguments: srcType.newArguments }); | ||
} else { | ||
type = srcType; | ||
} | ||
} else if (p === 'function:return' || p === 'function|function:return') { | ||
type = srcType.return; | ||
if (type === 'generic') { | ||
type = { type: 'type-ref', node: apply.implementation, port: _lodash2.default.keys(srcType.outputs)[0] }; | ||
} | ||
} else if (p === 'function:arg') { | ||
return applys[node].type.arguments[_lodash2.default.keys(applys[node].type.arguments)[0]]; | ||
var port = srcType.partialize && srcType.partialize.port ? srcType.partialize.port : _lodash2.default.keys(srcType.arguments)[0]; | ||
type = srcType.arguments[port]; | ||
if (type === 'generic') { | ||
type = { type: 'type-ref', node: apply.implementation, port: port }; | ||
} | ||
} | ||
return type; | ||
}); | ||
}; | ||
function partials(graph, apply) { | ||
return _lodash2.default.reduce(apply.path, function (type, p) { | ||
var pNode = graph.node(p.node); | ||
var lastType = _lodash2.default.cloneDeep(type.length > 0 ? _lodash2.default.last(type) : apply.type); | ||
if (lastType.newArguments) { | ||
lastType.arguments = lastType.newArguments; | ||
} | ||
lastType = _lodash2.default.omit(lastType, ['partialize', 'newArguments']); | ||
if (pNode.id !== 'functional/partial') { | ||
return type.concat(lastType); | ||
} else { | ||
var lambda = backtrackLambda(graph, { node: p.node, port: 'value' }); | ||
if (lambda.length !== 0) { | ||
var impl = lambdaImplementation(graph, createApplyRule([lambda, p.node])); | ||
lambda = findFunctionType(graph, impl); | ||
var lambdaLambda = backtrackLambda(graph, { node: p.node, port: 'fn' })[0][0]; | ||
} else { | ||
lambda = null; | ||
} | ||
return type.concat(_lodash2.default.merge({}, lastType, { newArguments: _lodash2.default.omit(lastType.arguments, _lodash2.default.keys(lastType.arguments)[pNode.params.partial]) }, { partialize: { | ||
partial: p.node, | ||
port: _lodash2.default.keys(lastType.arguments)[pNode.params.partial], | ||
lambda: lambda, | ||
implementation: impl, | ||
applyTo: lambdaLambda | ||
} })); | ||
} | ||
}, []); | ||
} | ||
function lambdaImplementation(graph, res) { | ||
if (graph.node(res.lambda.node).params && graph.node(res.lambda.node).params.implementation) { | ||
return graph.node(res.lambda.node).params.implementation; | ||
} else { | ||
return { type: 'reference', for: res.lambda, path: res.path }; | ||
} | ||
} | ||
function createApplyRule(arr) { | ||
return { apply: arr[1], lambda: arr[0][0][0], path: arr[0][0] }; | ||
} | ||
function partialFunctions(applys) { | ||
return (0, _lodash2.default)(applys).map(function (a) { | ||
return a.types; | ||
}).flatten().filter(function (t) { | ||
return t.partialize && t.partialize.lambda; | ||
}).value(); | ||
} | ||
function resolveReferences(graph, pFuns, applys) { | ||
var partials = _lodash2.default.keyBy(pFuns, 'partialize.applyTo.node'); | ||
return _lodash2.default.map(applys, function (a) { | ||
if (a.type.type === 'reference') { | ||
var pType = _lodash2.default.omit(partials[graph.parent(a.type.for.node)]); | ||
var type = pType.partialize.lambda; | ||
var impl = pType.partialize.implementation; | ||
return _lodash2.default.merge({}, _lodash2.default.omit(a, ['type', 'types', 'implementation']), { | ||
implementation: impl, | ||
type: type, | ||
types: _lodash2.default.map(a.types, function (t) { | ||
return type; | ||
}) | ||
}); | ||
} else { | ||
return a; | ||
} | ||
}); | ||
} | ||
function applyLambdaTypes(graph) { | ||
var gr = _graphtools.utils.finalize(graph); | ||
return _lodash2.default.merge({}, graph, { | ||
nodes: _lodash2.default.map(graph.nodes, function (n) { | ||
if (n.value.id === 'functional/lambda' && n.value.outputPorts.fn === 'function') { | ||
return _lodash2.default.merge({}, n, { value: { outputPorts: { fn: findFunctionType(gr, n.value.params.implementation) } } }); | ||
} | ||
return n; | ||
}) | ||
}); | ||
} | ||
function hasUnfinishedFunctionEdges(graph) { | ||
var gr = _graphtools.utils.finalize(graph); | ||
return _lodash2.default.filter(graph.edges, function (e) { | ||
var vPort = _graphtools.utils.portType(gr, e.v, e.value.outPort); | ||
var wPort = _graphtools.utils.portType(gr, e.w, e.value.inPort); | ||
return (vPort === 'generic' || vPort === 'function') && isFunctionType(wPort) || isFunctionType(vPort) && (wPort === 'function' || wPort === 'generic'); | ||
}).length !== 0; | ||
} | ||
function propagateFunctions(graph) { | ||
var gr = _graphtools.utils.finalize(graph); | ||
var changePorts = _lodash2.default.keyBy(_lodash2.default.compact(_lodash2.default.map(graph.edges, function (e) { | ||
var vPort = _graphtools.utils.portType(gr, e.v, e.value.outPort); | ||
var wPort = _graphtools.utils.portType(gr, e.w, e.value.inPort); | ||
if ((vPort === 'generic' || vPort === 'function') && isFunctionType(wPort)) { | ||
return { node: e.v, port: e.value.outPort, portType: 'outputPorts', type: wPort }; | ||
} else if (isFunctionType(vPort) && (wPort === 'function' || wPort === 'generic')) { | ||
return { node: e.w, port: e.value.inPort, portType: 'inputPorts', type: vPort }; | ||
} | ||
})), 'node'); | ||
return _lodash2.default.merge({}, graph, { | ||
nodes: _lodash2.default.map(graph.nodes, function (n) { | ||
if (_lodash2.default.has(changePorts, n.v)) { | ||
n.value[changePorts[n.v].portType][changePorts[n.v].port] = changePorts[n.v].type; | ||
} | ||
return n; | ||
}) | ||
}); | ||
} | ||
function resolveLambdaTypes(graph) { | ||
var anodes = applyNodes(graph); | ||
var types = (0, _lodash2.default)(anodes).map(_lodash2.default.partial(backtrackLambda, graph)).zip(anodes).map(function (arr) { | ||
return { apply: arr[1], lambda: arr[0][0][0], path: arr[0][0] }; | ||
return createApplyRule(arr); | ||
}).map(function (res) { | ||
return _lodash2.default.merge({}, res, { implementation: graph.node(res.lambda).params.implementation }); | ||
return _lodash2.default.merge({}, res, { implementation: lambdaImplementation(graph, res) }); | ||
}).map(function (res) { | ||
return _lodash2.default.merge({}, res, { type: findFunctionType(graph, res.implementation) }); | ||
}).map(function (res) { | ||
return _lodash2.default.merge({}, res, { types: partials(graph, res) }); | ||
}).value(); | ||
var pFuns = partialFunctions(types); | ||
types = resolveReferences(graph, pFuns, types); | ||
var args = _lodash2.default.concat([{}], _lodash2.default.map(types, function (t) { | ||
return _lodash2.default.fromPairs(_lodash2.default.map(t.path, function (p) { | ||
return [p, t]; | ||
return _lodash2.default.fromPairs(_lodash2.default.map(t.path, function (p, idx) { | ||
return [p.node, _lodash2.default.merge({}, t, { index: idx })]; | ||
})); | ||
@@ -169,4 +336,4 @@ })); | ||
return _lodash2.default.merge({}, n, { value: { | ||
inputPorts: updatePorts(n.v, n.value.inputPorts, applys), | ||
outputPorts: updatePorts(n.v, n.value.outputPorts, applys) | ||
inputPorts: updatePorts(n.v, n.value.inputPorts, applys[n.v]), | ||
outputPorts: updatePorts(n.v, n.value.outputPorts, applys[n.v]) | ||
} }); | ||
@@ -176,3 +343,14 @@ } | ||
}); | ||
editGraph = applyLambdaTypes(editGraph); | ||
var cnt = 0; | ||
while (hasUnfinishedFunctionEdges(editGraph)) { | ||
editGraph = propagateFunctions(editGraph); | ||
cnt++; | ||
if (cnt > 77) { | ||
console.error('maximum number of function propagations reached (77). Something is wrong.'); | ||
process.exit(1); | ||
} | ||
} | ||
// console.log(hasUnfinishedFunctionEdges(editGraph)) | ||
return _graphtools.utils.finalize(editGraph); | ||
} |
{ | ||
"name": "@buggyorg/functional", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"description": "Transformation of functional concepts.", | ||
@@ -19,3 +19,4 @@ "main": "lib/api.js", | ||
"dependencies": { | ||
"@buggyorg/graphtools": "^0.2.14", | ||
"@buggyorg/graphtools": "^0.2.18", | ||
"graphlib": "^2.1.0", | ||
"lodash": "^4.0.0" | ||
@@ -22,0 +23,0 @@ }, |
@@ -19,9 +19,19 @@ | ||
export function backtrackLambda (graph, node) { | ||
return walk.walkBack(graph, node, (graph, node) => { | ||
return walk.walkBack(graph, node, (graph, node, port) => { | ||
var lambdaPort = graph.parent(node) && graph.node(graph.parent(node)).isLambda | ||
if (graph.node(node).id === 'functional/lambda') { | ||
return [] | ||
} | ||
var functions = _.invert(graph.node(node).inputPorts || {function: []})['function'] | ||
var generics = _.invert(graph.node(node).inputPorts || {generic: []})['generic'] | ||
var ports = _.compact(_.map(_.flatten(_.concat(functions, generics)), (v) => '' + v)) | ||
var functions = (_.invertBy(graph.node(node).inputPorts) || {function: []})['function'] | ||
var generics = (_.invertBy(graph.node(node).inputPorts) || {generic: []})['generic'] | ||
var ports = _.compact(_.map(_.flatten(_.compact(_.concat(functions, generics))), (v) => '' + v)) | ||
if (!graph.node(node).atomic && port) { | ||
ports = _.filter(ports, (p) => p === port) | ||
} | ||
if (graph.node(node).id === 'functional/partial' && port === 'value') { | ||
return ['value'] | ||
} | ||
if (lambdaPort) { | ||
return [] | ||
} | ||
if (ports.length === 0) { | ||
@@ -31,3 +41,3 @@ return null | ||
return ports | ||
}) | ||
}, {keepPorts: true}) | ||
} | ||
@@ -67,13 +77,32 @@ | ||
var findFunctionType = (graph, meta) => { | ||
if (meta.type === 'reference') { | ||
return meta | ||
} | ||
var node = _(graph.nodes()) | ||
.map((n) => ({v: n, value: graph.node(n)})) | ||
.find((n) => n.value.id === meta) | ||
.find((n) => n.value.branchPath === meta) | ||
var rKeys = _.keys(node.value.outputPorts) | ||
var mapGenerics = (type, key) => { | ||
if (type === 'generic') { | ||
return {type: 'type-ref', node: meta, port: key} | ||
} | ||
return type | ||
} | ||
var ins = _.mapValues(node.value.inputPorts, mapGenerics) | ||
var outs = _.mapValues(node.value.outputPorts, mapGenerics) | ||
var rKeys = _.keys(outs) | ||
return { | ||
arguments: node.value.inputPorts, | ||
return: (rKeys.length === 1) ? node.value.outputPorts[rKeys[0]] : node.value.outputPorts | ||
type: 'function', | ||
arguments: ins, | ||
outputs: outs, | ||
return: (rKeys.length === 1) ? outs[rKeys[0]] : outs | ||
} | ||
} | ||
function isFunctionType (type) { | ||
return typeof (type) === 'object' && type.type === 'function' | ||
} | ||
export function portmapToEdges (graph, innerNode, portmap) { | ||
@@ -109,14 +138,148 @@ return _.flatten(_.map(portmap, (pm) => { | ||
var updatePorts = (node, ports, applys) => { | ||
return _.mapValues(ports, (p) => { | ||
if (p === 'function' || p === 'generic') { | ||
return applys[node].type | ||
} else if (p === 'function:return') { | ||
return applys[node].type.return | ||
var updatePorts = (node, ports, apply) => { | ||
return _.mapValues(ports, (p, portName) => { | ||
var srcType = apply.types[apply.index] | ||
var type | ||
if (p === 'function' || p === 'generic' || (p === 'function|function:return' && _.keys(srcType.arguments).length > 1)) { | ||
if (p === 'generic' && apply.lambda.port !== portName) { | ||
return 'generic' | ||
} | ||
if (p === 'function|function:return') { | ||
type = _.merge({}, _.omit(srcType, ['arguments', 'newArguments']), {arguments: srcType.newArguments}) | ||
} else { | ||
type = srcType | ||
} | ||
} else if (p === 'function:return' || p === 'function|function:return') { | ||
type = srcType.return | ||
if (type === 'generic') { | ||
type = {type: 'type-ref', node: apply.implementation, port: _.keys(srcType.outputs)[0]} | ||
} | ||
} else if (p === 'function:arg') { | ||
return applys[node].type.arguments[_.keys(applys[node].type.arguments)[0]] | ||
var port = (srcType.partialize && srcType.partialize.port) ? srcType.partialize.port : _.keys(srcType.arguments)[0] | ||
type = srcType.arguments[port] | ||
if (type === 'generic') { | ||
type = {type: 'type-ref', node: apply.implementation, port: port} | ||
} | ||
} | ||
return type | ||
}) | ||
} | ||
function partials (graph, apply) { | ||
return _.reduce(apply.path, (type, p) => { | ||
var pNode = graph.node(p.node) | ||
var lastType = _.cloneDeep((type.length > 0) ? _.last(type) : apply.type) | ||
if (lastType.newArguments) { | ||
lastType.arguments = lastType.newArguments | ||
} | ||
lastType = _.omit(lastType, ['partialize', 'newArguments']) | ||
if (pNode.id !== 'functional/partial') { | ||
return type.concat(lastType) | ||
} else { | ||
var lambda = backtrackLambda(graph, {node: p.node, port: 'value'}) | ||
if (lambda.length !== 0) { | ||
var impl = lambdaImplementation(graph, createApplyRule([lambda, p.node])) | ||
lambda = findFunctionType(graph, impl) | ||
var lambdaLambda = backtrackLambda(graph, {node: p.node, port: 'fn'})[0][0] | ||
} else { | ||
lambda = null | ||
} | ||
return type.concat(_.merge({}, | ||
lastType, | ||
{newArguments: _.omit(lastType.arguments, _.keys(lastType.arguments)[pNode.params.partial])}, | ||
{partialize: { | ||
partial: p.node, | ||
port: _.keys(lastType.arguments)[pNode.params.partial], | ||
lambda: lambda, | ||
implementation: impl, | ||
applyTo: lambdaLambda | ||
}})) | ||
} | ||
}, []) | ||
} | ||
function lambdaImplementation (graph, res) { | ||
if (graph.node(res.lambda.node).params && graph.node(res.lambda.node).params.implementation) { | ||
return graph.node(res.lambda.node).params.implementation | ||
} else { | ||
return { type: 'reference', for: res.lambda, path: res.path } | ||
} | ||
} | ||
function createApplyRule (arr) { | ||
return {apply: arr[1], lambda: arr[0][0][0], path: arr[0][0]} | ||
} | ||
function partialFunctions (applys) { | ||
return _(applys) | ||
.map((a) => a.types) | ||
.flatten() | ||
.filter((t) => t.partialize && t.partialize.lambda) | ||
.value() | ||
} | ||
function resolveReferences (graph, pFuns, applys) { | ||
var partials = _.keyBy(pFuns, 'partialize.applyTo.node') | ||
return _.map(applys, (a) => { | ||
if (a.type.type === 'reference') { | ||
var pType = _.omit(partials[graph.parent(a.type.for.node)]) | ||
var type = pType.partialize.lambda | ||
var impl = pType.partialize.implementation | ||
return _.merge({}, | ||
_.omit(a, ['type', 'types', 'implementation']), | ||
{ | ||
implementation: impl, | ||
type: type, | ||
types: _.map(a.types, (t) => type) | ||
}) | ||
} else { | ||
return a | ||
} | ||
}) | ||
} | ||
function applyLambdaTypes (graph) { | ||
var gr = utils.finalize(graph) | ||
return _.merge({}, graph, { | ||
nodes: _.map(graph.nodes, (n) => { | ||
if (n.value.id === 'functional/lambda' && n.value.outputPorts.fn === 'function') { | ||
return _.merge({}, n, {value: {outputPorts: {fn: findFunctionType(gr, n.value.params.implementation)}}}) | ||
} | ||
return n | ||
}) | ||
}) | ||
} | ||
function hasUnfinishedFunctionEdges (graph) { | ||
var gr = utils.finalize(graph) | ||
return _.filter(graph.edges, (e) => { | ||
var vPort = utils.portType(gr, e.v, e.value.outPort) | ||
var wPort = utils.portType(gr, e.w, e.value.inPort) | ||
return ((vPort === 'generic' || vPort === 'function') && isFunctionType(wPort)) || | ||
(isFunctionType(vPort) && (wPort === 'function' || wPort === 'generic')) | ||
}).length !== 0 | ||
} | ||
function propagateFunctions (graph) { | ||
var gr = utils.finalize(graph) | ||
var changePorts = _.keyBy(_.compact(_.map(graph.edges, (e) => { | ||
var vPort = utils.portType(gr, e.v, e.value.outPort) | ||
var wPort = utils.portType(gr, e.w, e.value.inPort) | ||
if ((vPort === 'generic' || vPort === 'function') && isFunctionType(wPort)) { | ||
return {node: e.v, port: e.value.outPort, portType: 'outputPorts', type: wPort} | ||
} else if (isFunctionType(vPort) && (wPort === 'function' || wPort === 'generic')) { | ||
return {node: e.w, port: e.value.inPort, portType: 'inputPorts', type: vPort} | ||
} | ||
})), 'node') | ||
return _.merge({}, graph, | ||
{ | ||
nodes: _.map(graph.nodes, (n) => { | ||
if (_.has(changePorts, n.v)) { | ||
n.value[changePorts[n.v].portType][changePorts[n.v].port] = changePorts[n.v].type | ||
} | ||
return n | ||
}) | ||
}) | ||
} | ||
export function resolveLambdaTypes (graph) { | ||
@@ -127,7 +290,10 @@ var anodes = applyNodes(graph) | ||
.zip(anodes) | ||
.map((arr) => ({apply: arr[1], lambda: arr[0][0][0], path: arr[0][0]})) | ||
.map((res) => _.merge({}, res, {implementation: graph.node(res.lambda).params.implementation})) | ||
.map((arr) => createApplyRule(arr)) | ||
.map((res) => _.merge({}, res, {implementation: lambdaImplementation(graph, res)})) | ||
.map((res) => _.merge({}, res, {type: findFunctionType(graph, res.implementation)})) | ||
.map((res) => _.merge({}, res, {types: partials(graph, res)})) | ||
.value() | ||
var args = _.concat([{}], _.map(types, (t) => _.fromPairs(_.map(t.path, (p) => [p, t])))) | ||
var pFuns = partialFunctions(types) | ||
types = resolveReferences(graph, pFuns, types) | ||
var args = _.concat([{}], _.map(types, (t) => _.fromPairs(_.map(t.path, (p, idx) => [p.node, _.merge({}, t, {index: idx})])))) | ||
var applys = _.merge.apply(null, args) | ||
@@ -142,4 +308,4 @@ var editGraph = utils.edit(graph) | ||
{ | ||
inputPorts: updatePorts(n.v, n.value.inputPorts, applys), | ||
outputPorts: updatePorts(n.v, n.value.outputPorts, applys) | ||
inputPorts: updatePorts(n.v, n.value.inputPorts, applys[n.v]), | ||
outputPorts: updatePorts(n.v, n.value.outputPorts, applys[n.v]) | ||
}}) | ||
@@ -149,3 +315,14 @@ } | ||
}) | ||
editGraph = applyLambdaTypes(editGraph) | ||
var cnt = 0 | ||
while (hasUnfinishedFunctionEdges(editGraph)) { | ||
editGraph = propagateFunctions(editGraph) | ||
cnt++ | ||
if (cnt > 77) { | ||
console.error('maximum number of function propagations reached (77). Something is wrong.') | ||
process.exit(1) | ||
} | ||
} | ||
// console.log(hasUnfinishedFunctionEdges(editGraph)) | ||
return utils.finalize(editGraph) | ||
} |
@@ -54,3 +54,3 @@ { | ||
"params": { | ||
"implementation": "math/inc" | ||
"implementation": "inc_lambda" | ||
}, | ||
@@ -57,0 +57,0 @@ "branchPath": "lambda_inc", |
@@ -38,3 +38,3 @@ { | ||
"params": { | ||
"implementation": "math/inc" | ||
"implementation": "inc_lambda" | ||
}, | ||
@@ -41,0 +41,0 @@ "branchPath": "lambda_inc", |
@@ -42,3 +42,3 @@ /* global describe, it */ | ||
expect(lambdaPath[0]).to.have.length(2) | ||
expect(lambdaPath[0][0]).to.equal('lambda_inc') | ||
expect(lambdaPath[0][0].node).to.equal('lambda_inc') | ||
}) | ||
@@ -96,3 +96,27 @@ | ||
}) | ||
/* | ||
it('`resolveLambdaTypes` can handle generic lambda input values', () => { | ||
var genGraph = lambda.resolveLambdaTypes(readFixture('apply_generic.json')) | ||
expect(genGraph.node('apply').inputPorts.value).to.equal('type-ref=math/inc@i') | ||
}) | ||
it('`resolveLambdaTypes` can handle generic lambda return values', () => { | ||
var genGraph = lambda.resolveLambdaTypes(readFixture('apply_generic.json')) | ||
expect(genGraph.node('apply').outputPorts.result).to.be.an('object') | ||
expect(genGraph.node('apply').outputPorts.result.type).to.equal('type-ref') | ||
}) | ||
it('`resolveLambdaTypes` can handle partial applications', () => { | ||
var genGraph = lambda.resolveLambdaTypes(readFixture('partial_generic.json')) | ||
expect(genGraph.node('apply').inputPorts.value).to.equal('int') | ||
expect(genGraph.node('partial').outputPorts.result).to.be.an('object') | ||
}) | ||
it('`resolveLambdaTypes` can handle multiple partial applications', () => { | ||
var genGraph = lambda.resolveLambdaTypes(readFixture('partial_generic_multi.json')) | ||
expect(genGraph.node('apply').inputPorts.value).to.equal('int32') | ||
expect(genGraph.node('partial').outputPorts.result).to.be.an('object') | ||
expect(genGraph.node('partial2').outputPorts.result).to.be.an('object') | ||
})*/ | ||
}) | ||
62249
30.42%2175
19.31%3
50%+ Added
Updated