UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

146 lines 4.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MutableStateAbstractDomain = exports.StateAbstractDomain = void 0; const lattice_1 = require("./lattice"); const mapped_abstract_domain_1 = require("./mapped-abstract-domain"); /** * A state abstract domain as mapping of AST node IDs of a program to abstract values of an abstract domain. * The Bottom element is defined as empty mapping and the Top element is defined as mapping every existing mapped AST node ID to Top. * @template Domain - Type of the abstract domain to map the AST node IDs to * @see {@link NodeId} for the node IDs of the AST nodes */ class StateAbstractDomain extends mapped_abstract_domain_1.MappedAbstractDomain { _isBottom; constructor(value, bottom) { super(value); if (bottom || value.values().some(entry => entry.isBottom())) { this._isBottom = true; } } create(value, bottom) { return new StateAbstractDomain(value, bottom ?? this._isBottom); } static top() { return new StateAbstractDomain(new Map()); } get(key, ignoreBottom) { return this._isBottom && !ignoreBottom ? super.get(key)?.bottom() : super.get(key); } set(key, value) { if (value.isBottom()) { this._isBottom = true; } super.set(key, value); } bottom() { return this.create(this.value, true); } top() { return this.create(new Map()); } equals(other) { if (this._isBottom !== other._isBottom) { return false; } return super.equals(other); } leq(other) { if (this._isBottom) { return true; } else if (other._isBottom) { return false; } return super.leq(other); } join(other) { if (this._isBottom) { return other.create(other.value); } else if (other._isBottom) { return this.create(this.value); } return super.join(other); } meet(other) { const result = super.meet(other); result._isBottom = this._isBottom || other._isBottom; return result; } widen(other) { if (this._isBottom) { return other.create(other.value); } else if (other._isBottom) { return this.create(this.value); } return super.widen(other); } narrow(other) { const result = super.narrow(other); result._isBottom = this._isBottom || other._isBottom; return result; } concretize(limit) { if (this._isBottom) { return new Set(); } else if (this.value.size === 0) { return lattice_1.Top; } return super.concretize(limit); } abstract(concrete) { if (concrete === lattice_1.Top) { return this.top(); } else if (concrete.size === 0) { return this.create(new Map(), true); } return super.abstract(concrete); } toJson() { if (this._isBottom) { return lattice_1.BottomSymbol; } else if (this.value.size === 0) { return lattice_1.TopSymbol; } return super.toJson(); } toString() { if (this._isBottom) { return lattice_1.BottomSymbol; } else if (this.value.size === 0) { return lattice_1.TopSymbol; } return super.toString(); } isTop() { return this.value.size === 0; } isBottom() { return this._isBottom ?? false; } isValue() { return !this._isBottom; } } exports.StateAbstractDomain = StateAbstractDomain; /** * A mutable version of the {@link StateAbstractDomain} with {@link MutableStateAbstractDomain#set|`set`} and {@link MutableStateAbstractDomain#remove|`remove`}. */ class MutableStateAbstractDomain extends StateAbstractDomain { create(value) { return new MutableStateAbstractDomain(value); } set(key, value) { super.set(key, value); } remove(key) { super.remove(key); } } exports.MutableStateAbstractDomain = MutableStateAbstractDomain; //# sourceMappingURL=state-abstract-domain.js.map