@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
146 lines • 4.31 kB
JavaScript
"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