Skip to content

Instantly share code, notes, and snippets.

@amb26
Created March 9, 2021 19:03
Show Gist options
  • Select an option

  • Save amb26/6bd05ef2306b36529cb0517a183d5fd6 to your computer and use it in GitHub Desktop.

Select an option

Save amb26/6bd05ef2306b36529cb0517a183d5fd6 to your computer and use it in GitHub Desktop.
"use strict";
var fluid = require("infusion");
fluid.tangledMat = function (layersIn) {
var that = {
layers: layersIn || [ // Array of {
// layer: Object|Array
// name: String
],
// root: lazily initialised from fluid.tangledMat.getRoot
writeLayer: null,
writeLayerIndex: -1
};
Object.setPrototypeOf(that, fluid.tangledMat);
return that;
};
fluid.registerNamespace("fluid.flatObject");
fluid.flatObject.dispatch0 = function (func, target) {
return func(target);
};
fluid.flatObject.dispatch1 = function (func, target, args) {
return func(target, args[0]);
};
fluid.flatObject.dispatch2 = function (func, target, args) {
return func(target, args[0], args[1]);
};
fluid.flatObject.dispatch3 = function (func, target, args) {
return func(target, args[0], args[1], args[2]);
};
fluid.flatObject.dispatch4 = function (func, target, args) {
return func(target, args[0], args[1], args[2], args[3]);
};
fluid.flatObject.makeProperties = function (namespace) {
var methods = namespace.methods;
return fluid.transform(methods, function (func) {
var arity = func.length;
var dispatcher = fluid.getGlobalValue("fluid.flatObject.dispatch" + arity);
return {
value: function () {
return dispatcher(func, this, arguments);
}
};
});
};
fluid.flatObject.defineMethodProperties = function (namespace) {
Object.defineProperties(namespace, fluid.flatObject.makeProperties(namespace));
};
fluid.registerNamespace("fluid.tangledMat.methods");
fluid.tangledMat.methods.addLayer = function (mat, layer, layerName) {
console.log("addLayer with mat ", mat);
mat.layers.push({
layer: layer,
name: layerName
});
};
fluid.tangledMat.methods.getRoot = function (mat) {
if (!mat.root) {
var target = mat.topValue([]);
mat.root = mat.makeProxy([], target);
}
return mat.root;
};
fluid.tangledMat.methods.pathToRoot = function (mat, path) {
var root = mat.getRoot();
var togo = [root];
for (var i = 0; i < path.length - 1; ++i) {
togo[i] = togo[i - 1][path[i]];
};
return togo;
};
// Compute mat top value by searching from right to left at a given path, returns cell
fluid.tangledMat.methods.topValue = function (mat, path) {
for (var i = mat.layers.length - 1; i >= 0; --i) {
var value = fluid.getImmediate(mat.layers[i].layer, path);
if (value !== undefined) {
return {
value: value,
layerIndex: i,
layerName: mat.layers[i].name
};
}
}
return undefined;
};
/** Read what should be a member value of a "mat top" given the holder of the value, path to it and member name
* @param {fluid.tangledMat} mat - Mat structure containing the value to be read
* @param {String[]} path - Path to the value holding the member to be read
* @param {Any} holder - Object holding value to be read - expected to be an existing "mat top" member
* @param {String} member - Member name to be read
* @return {Any|undefined} The read value
*/
fluid.tangledMat.methods.readMember = function (mat, path, holder, member) {
var cached = holder[member];
if (cached) {
return cached;
} else {
var longPath = path.concat(member);
var cell = mat.topValue(longPath);
if (cell) {
if (!fluid.isPrimitive(cell.value)) {
cell.proxy = mat.makeProxy(longPath, cell);
}
// NOTE: This is a site at which something interesting might happen - we expect "free space" contents of the
// mat top to share references with underlying layer. If there is a mat update, we expect at that point that
// the top forks. Note that what this is is a differential implementation of "applyImmutable"
holder[member] = cell;
return cell;
} else {
return undefined;
}
}
};
fluid.tangledMat.ensureContainer = function (holder, seg, exemplar) {
if (fluid.typeCode(holder[seg]) !== fluid.typeCode(exemplar)) {
var newContainer = fluid.freshContainer(exemplar);
holder[seg] = newContainer;
}
return holder[seg];
};
fluid.tangledMat.methods.getLayerMap = function (mat) {
var root = fluid.tangledMat.getRoot(mat);
};
fluid.tangledMat.methods.evaluateFully = function (mat) {
};
fluid.tangledMat.methods.makeProxy = function (mat, path, target) {
var proxy = new Proxy(target, {
get: function (target, member) {
var cache = mat.readMember(path, target, member);
// TODO: eliminate conditional on every access
return cache ? cache.proxy || cache.value : undefined;
},
set: function (target, member, value) {
if (!mat.writeLayerIndex === -1) {
fluid.fail("Cannot write ", value, " to path ", path, " for mat without write layer set");
} else {
var layer = mat.layers[mat.writeLayerIndex];
var pathToRoot = mat.pathToRoot(path);
var move = layer;
for (var i = 0; i < path.length - 1; ++i) {
var seg = i === 0 ? "layer" : path[i - 1];
move = fluid.tangledMat.ensureContainer(move, seg, pathToRoot[i]);
}
move[member] = value;
}
}
// TODO: need to add ownKeys() so that object can be stringified
});
return proxy;
};
fluid.tangledMat.methods.getMembers = function (mat, path) {
return mat.layers.map(function (oneLayer) {
return fluid.getImmediate(oneLayer, path);
});
};
fluid.tangledMat.methods.findLayer = function (mat, layerName) {
return mat.layers.findIndex(function (entry) {
return entry.name === layerName;
});
};
fluid.tangledMat.methods.setWriteableLayer = function (mat, layerName) {
var index = mat.findLayer(layerName);
mat.writeLayer = layerName;
mat.writeLayerIndex = index;
};
fluid.flatObject.defineMethodProperties(fluid.tangledMat);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment