UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

141 lines 4.65 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StateAbstractDomain = void 0; const abstract_domain_1 = require("./abstract-domain"); const lattice_1 = require("./lattice"); /** * A state abstract domain that maps AST node IDs of a program to abstract values of an abstract domain. * The Bottom element is defined as {@link Bottom} symbol and the Top element as empty mapping. * @template Domain - Type of the value abstract domain to map the AST node IDs to * @see {@link NodeId} for the node IDs of the AST nodes */ class StateAbstractDomain extends abstract_domain_1.AbstractDomain { domain; constructor(value, domain) { if (value === lattice_1.Bottom || value.values().some(entry => entry.isBottom())) { super(lattice_1.Bottom); } else { super(new Map(value)); } this.domain = domain; } create(value) { return new StateAbstractDomain(value, this.domain); } static top(domain) { return new this(new Map(), domain); } static bottom(domain) { return new this(lattice_1.Bottom, domain); } get(node) { return this.value === lattice_1.Bottom ? this.domain.bottom() : this.value.get(node); } has(node) { return this.value !== lattice_1.Bottom && this.value.has(node); } set(node, value) { if (this.value !== lattice_1.Bottom) { this._value.set(node, value); } } remove(node) { if (this.value !== lattice_1.Bottom) { this._value.delete(node); } } top() { return this.create(new Map()); } bottom() { return this.create(lattice_1.Bottom); } equalsValue(other) { if (this.value.size !== other.value.size) { return false; } for (const [key, currValue] of this.value.entries()) { const otherValue = other.get(key); if (otherValue === undefined || !currValue.equals(otherValue)) { return false; } } return true; } leqValue(other) { if (this.value.size > other.value.size) { return false; } for (const [key, currValue] of this.value.entries()) { const otherValue = other.get(key); if (otherValue === undefined || !currValue.leq(otherValue)) { return false; } } return true; } joinValue(other) { const result = new Map(this.value); for (const [key, otherValue] of other.value.entries()) { const currValue = result.get(key); if (currValue === undefined) { result.set(key, otherValue); } else { result.set(key, currValue.join(otherValue)); } } return this.create(result); } meetValue(other) { const result = new Map(); for (const [key, currValue] of this.value.entries()) { const otherValue = other.value.get(key); if (otherValue !== undefined) { result.set(key, currValue.meet(otherValue)); } } return this.create(result); } widenValue(other) { const result = new Map(this.value); for (const [key, otherValue] of other.value.entries()) { const currValue = result.get(key); if (currValue === undefined) { result.set(key, otherValue); } else { result.set(key, currValue.widen(otherValue)); } } return this.create(result); } narrowValue(other) { const result = new Map(); for (const [key, currValue] of this.value.entries()) { const otherValue = other.value.get(key); if (otherValue !== undefined) { result.set(key, currValue.narrow(otherValue)); } } return this.create(result); } jsonify() { return Object.fromEntries(this.value.entries().map(([key, value]) => [key, value.toJSON()])); } stringify() { return '(' + this.value.entries().toArray().map(([key, value]) => `${key} -> ${value.toString()}`).join(', ') + ')'; } isTop() { return this.value !== lattice_1.Bottom && this.value.size === 0; } isBottom() { return this.value === lattice_1.Bottom; } isValue() { return this.value !== lattice_1.Bottom; } } exports.StateAbstractDomain = StateAbstractDomain; //# sourceMappingURL=state-abstract-domain.js.map