UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

134 lines 4.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PartialProductDomain = void 0; const assert_1 = require("../../util/assert"); const record_1 = require("../../util/record"); const abstract_domain_1 = require("./abstract-domain"); /** * 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; reductions; constructor(value, domain, reductions = [], reduce = true) { super(record_1.Record.mapProperties(value, entry => entry?.create(entry.value))); this.reductions = reductions; this.domain = domain; if (reduce) { this._value = this.reduce(this.value); } } bottom() { const result = {}; for (const key in this.domain) { result[key] = this.domain[key]?.bottom(); } return this.create(result); } top() { return this.create({}); } equalsValue(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; } leqValue(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; } joinValue(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); } meetValue(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); } widenValue(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); } narrowValue(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); } jsonify() { return record_1.Record.mapProperties(this.value, entry => entry?.toJSON()); } stringify() { return '(' + record_1.Record.entries(this.value).map(([key, value]) => `${key}: ${value.toString()}`).join(', ') + ')'; } isTop() { return record_1.Record.values(this.value).filter(assert_1.isNotUndefined).length === 0; } isBottom() { return record_1.Record.values(this.value).some(value => value.isBottom()); } isValue() { return true; } /** * Applies the {@link reductions} of the (reduced) product domain to refine the abstract value based on its components. * Subclasses may override this to implement a fixed reduction instead of (or in addition to) the configurable reductions. */ reduce(value) { return this.reductions.reduce((current, reduction) => reduction(current), value); } } exports.PartialProductDomain = PartialProductDomain; //# sourceMappingURL=partial-product-domain.js.map