UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

133 lines 4.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProductDomain = void 0; const abstract_domain_1 = require("./abstract-domain"); const lattice_1 = require("./lattice"); /** * A product abstract domain as named Cartesian product of sub abstract domains. * The sub abstract domains are represented a 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 mapping every sub abstract domain to Top. * @template Product - Type of the abstract product of the product domain mapping property names to abstract domains */ class ProductDomain { _value; constructor(value) { this._value = value; } get value() { return this._value; } bottom() { const result = this.create(this.value); for (const key in result.value) { result._value[key] = result.value[key].bottom(); } return result; } top() { const result = this.create(this.value); for (const key in result.value) { result._value[key] = result.value[key].top(); } return result; } equals(other) { if (this.value === other.value) { return true; } for (const key in this.value) { if (!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].leq(other.value[key])) { return false; } } return true; } join(...values) { const result = this.create(this.value); for (const value of values) { for (const key in result.value) { result._value[key] = result.value[key].join(value.value[key]); } } return result; } meet(...values) { const result = this.create(this.value); for (const value of values) { for (const key in result.value) { result._value[key] = result.value[key].meet(value.value[key]); } } return result; } widen(other) { const result = this.create(this.value); for (const key in result.value) { result._value[key] = result.value[key].widen(other.value[key]); } return result; } narrow(other) { const result = this.create(this.value); for (const key in result.value) { result._value[key] = result.value[key].narrow(other.value[key]); } return result; } concretize(limit = abstract_domain_1.DEFAULT_INFERENCE_LIMIT) { let result = new Set([{}]); for (const key in this.value) { 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 = this.create(this.value); for (const key in result.value) { const concreteValues = new Set(concrete.values().map(value => value[key])); result._value[key] = result.value[key].abstract(concreteValues); } return result; } toString() { return '(' + Object.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')'; } isTop() { return Object.values(this.value).every(value => value.isTop()); } isBottom() { return Object.values(this.value).every(value => value.isBottom()); } isValue() { return true; } } exports.ProductDomain = ProductDomain; //# sourceMappingURL=product-domain.js.map