@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
75 lines • 2.96 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.envFingerprint = envFingerprint;
exports.fingerprint = fingerprint;
const object_hash_1 = __importDefault(require("object-hash"));
const environment_1 = require("../../dataflow/environments/environment");
const HashOptions = {
algorithm: 'md5',
excludeKeys: (key) => key === 'id' || key === 'value',
respectFunctionProperties: false,
respectFunctionNames: false,
ignoreUnknown: true,
replacer: (v) => (0, environment_1.isDefaultBuiltInEnvironment)(v) ? undefined : v
};
/* definitions, definition maps and frames are shared across the environments a slice builds, and a definition may
* hold a whole environment of its own (`envState`), so each is hashed once instead of on every fingerprint. The
* map is keyed separately from the frame because cloning a frame shares its definitions until one side writes
* (see {@link Environment#clone}): the graph holds many frames per distinct set of definitions, and hashing that
* set is what costs. */
const definitionHashes = new WeakMap();
const memoryHashes = new WeakMap();
const frameHashes = new WeakMap();
function definitionHash(definition) {
let hash = definitionHashes.get(definition);
if (hash === undefined) {
hash = (0, object_hash_1.default)(definition, HashOptions);
definitionHashes.set(definition, hash);
}
return hash;
}
function memoryHash(memory) {
let hash = memoryHashes.get(memory);
if (hash === undefined) {
const entries = [];
for (const [name, definitions] of memory) {
entries.push(`${String(name)}=${definitions.map(definitionHash).join(',')}`);
}
entries.sort();
hash = (0, object_hash_1.default)(entries, HashOptions);
memoryHashes.set(memory, hash);
}
return hash;
}
function frameHash(frame) {
let hash = frameHashes.get(frame);
if (hash === undefined) {
hash = (0, object_hash_1.default)([frame.n, frame.t, frame.closure, frame.globalEnv === true, memoryHash(frame.memory)], HashOptions);
frameHashes.set(frame, hash);
}
return hash;
}
/**
* Calculate a fingerprint for the given R environment information
* @see {@link fingerprint}
*/
function envFingerprint(env) {
const parts = [String(env.level)];
let frame = env.current;
while (frame !== undefined && !frame.builtInEnv) {
parts.push(frameHash(frame));
frame = frame.parent;
}
return parts.join('|');
}
/**
* Calculate a fingerprint for the given node id and environment fingerprint
* @see {@link envFingerprint}
*/
function fingerprint(id, envFingerprint, onlyForSideEffects) {
return `${id}-${envFingerprint}-${onlyForSideEffects ? '0' : '1'}`;
}
//# sourceMappingURL=fingerprint.js.map