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