@informalsystems/quint
Version:
Core tool for the Quint specification language
116 lines • 4.11 kB
JavaScript
"use strict";
/* ----------------------------------------------------------------------------------
* Copyright 2022 Informal Systems
* Licensed under the Apache License, Version 2.0.
* See LICENSE in the project root for license information.
* --------------------------------------------------------------------------------- */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToEffectVisitor = void 0;
/**
* An ANTLR4 listener that constructs Effect objects out of the abstract
* syntax tree.
*/
class ToEffectVisitor {
constructor() {
// The resulting effect
this.effect = undefined;
// Stack of lists of effects, each list will hold the effects of an arrow effect
this.arrowEffectsStack = [];
this.entitiesStack = [];
this.stateVars = [];
this.idCounter = 0n;
}
pushEffect(effect) {
this.effect = effect;
// If inside an arrow effect, push it this effect to the arrow's effects list
if (this.arrowEffectsStack.length > 0) {
this.arrowEffectsStack[this.arrowEffectsStack.length - 1].push(effect);
}
}
exitReadOnly() {
const entity = this.entitiesStack.pop();
const effect = { kind: 'concrete', components: [{ kind: 'read', entity: entity }] };
this.pushEffect(effect);
}
exitUpdateOnly() {
const entity = this.entitiesStack.pop();
const effect = { kind: 'concrete', components: [{ kind: 'update', entity: entity }] };
this.pushEffect(effect);
}
exitTemporalOnly() {
const entity = this.entitiesStack.pop();
const effect = { kind: 'concrete', components: [{ kind: 'temporal', entity: entity }] };
this.pushEffect(effect);
}
exitReadAndUpdate() {
const update = this.entitiesStack.pop();
const read = this.entitiesStack.pop();
const effect = {
kind: 'concrete',
components: [
{ kind: 'read', entity: read },
{ kind: 'update', entity: update },
],
};
this.pushEffect(effect);
}
exitReadAndTemporal() {
const temporal = this.entitiesStack.pop();
const read = this.entitiesStack.pop();
const effect = {
kind: 'concrete',
components: [
{ kind: 'read', entity: read },
{ kind: 'temporal', entity: temporal },
],
};
this.pushEffect(effect);
}
exitPure() {
const effect = { kind: 'concrete', components: [] };
this.pushEffect(effect);
}
exitVariableEffect(ctx) {
const name = ctx.IDENTIFIER().text;
const effect = { kind: 'variable', name };
this.pushEffect(effect);
}
enterArrowEffect() {
this.arrowEffectsStack.push([]);
}
exitArrowEffect() {
const effects = this.arrowEffectsStack.pop();
const result = effects.pop();
const effect = { kind: 'arrow', params: effects, result };
this.pushEffect(effect);
}
exitEntity(ctx) {
const names = ctx.IDENTIFIER().map(i => i.text);
const entityUnion = names.map(name => ({ kind: 'variable', name }));
if (this.stateVars.length > 0) {
entityUnion.push({
kind: 'concrete',
stateVariables: this.stateVars.map(v => ({ name: v, reference: this.nextId() })),
});
}
if (entityUnion.length === 0) {
this.entitiesStack.push({ kind: 'concrete', stateVariables: [] });
}
else if (entityUnion.length === 1) {
this.entitiesStack.push(entityUnion[0]);
}
else {
this.entitiesStack.push({ kind: 'union', entities: entityUnion });
}
this.stateVars = [];
}
exitStateVarRef(ctx) {
const varRef = ctx.IDENTIFIER().text;
this.stateVars.push(varRef);
}
nextId() {
return ++this.idCounter;
}
}
exports.ToEffectVisitor = ToEffectVisitor;
//# sourceMappingURL=ToEffectVisitor.js.map