New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@buggyorg/functional

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@buggyorg/functional - npm Package Compare versions

Comparing version

to
0.1.3

222

lib/lambda.js

@@ -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);
}

5

package.json
{
"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')
})*/
})