UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

163 lines 5.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PartialProductDomain = void 0; const abstract_domain_1 = require("./abstract-domain"); const lattice_1 = require("./lattice"); const record_1 = require("../../util/record"); /** * A partial product abstract domain as named Cartesian product of (optional) sub abstract domains. * The sub abstract domains are represented by a (partial) record mapping property names to abstract domains. * The Bottom element is defined as mapping every sub abstract domain to Bottom and the Top element is defined as having no sub abstract domain value. * @template Product - Type of the abstract product of the product domain mapping (optional) property names to abstract domains */ class PartialProductDomain extends abstract_domain_1.AbstractDomain { domain; constructor(value, domain) { super(record_1.Record.mapProperties(value, entry => entry?.create(entry.value))); this._value = this.reduce(this.value); this.domain = domain; } bottom() { const result = this.create(this.domain); for (const key in result.value) { result.value[key] = this.domain[key]?.bottom(); } return result; } top() { return this.create({}); } equals(other) { if (this.value === other.value) { return true; } for (const key in this.value) { if (this.value[key] == other.value[key]) { continue; } else if (this.value[key] === undefined || other.value[key] === undefined || !this.value[key].equals(other.value[key])) { return false; } } return true; } leq(other) { if (this.value === other.value) { return true; } for (const key in this.value) { if (this.value[key] === other.value[key] || other.value[key] === undefined) { continue; } else if (this.value[key] === undefined || !this.value[key].leq(other.value[key])) { return false; } } return true; } join(other) { const result = {}; for (const key in this.domain) { if (this.value[key] !== undefined && other.value[key] !== undefined) { result[key] = this.value[key].join(other.value[key]); } } return this.create(result); } meet(other) { const result = {}; for (const key in this.domain) { if (this.value[key] === undefined) { result[key] = other.value[key]; } else if (other.value[key] === undefined) { result[key] = this.value[key]; } else { result[key] = this.value[key].meet(other.value[key]); } } return this.create(result); } widen(other) { const result = {}; for (const key in this.domain) { if (this.value[key] !== undefined && other.value[key] !== undefined) { result[key] = this.value[key].widen(other.value[key]); } } return this.create(result); } narrow(other) { const result = {}; for (const key in this.domain) { if (this.value[key] === undefined) { result[key] = other.value[key]; } else if (other.value[key] === undefined) { result[key] = this.value[key]; } else { result[key] = this.value[key].narrow(other.value[key]); } } return this.create(result); } concretize(limit) { let result = new Set([{}]); for (const key in this.value) { if (this.value[key] === undefined) { continue; } const concrete = this.value[key].concretize(limit); if (concrete === lattice_1.Top) { return lattice_1.Top; } const newResult = new Set(); for (const value of concrete) { for (const entry of result) { if (newResult.size >= limit) { return lattice_1.Top; } newResult.add({ ...entry, [key]: value }); } } result = newResult; } return result; } abstract(concrete) { if (concrete === lattice_1.Top) { return this.top(); } const result = {}; for (const key in this.domain) { const concreteValues = new Set(concrete.values().map(value => value[key])); result[key] = this.domain[key]?.abstract(concreteValues); } return this.create(result); } toJson() { return record_1.Record.mapProperties(this.value, entry => entry?.toJson()); } toString() { return '(' + record_1.Record.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')'; } isTop() { return record_1.Record.values(this.value).length === 0; } isBottom() { return record_1.Record.values(this.value).every(value => value.isBottom()); } isValue() { return true; } /** * Optional reduction function for a reduced product domain. */ reduce(value) { return value; } } exports.PartialProductDomain = PartialProductDomain; //# sourceMappingURL=partial-product-domain.js.map