@informalsystems/quint
Version:
Core tool for the Quint specification language
111 lines • 3.82 kB
JavaScript
;
/* ----------------------------------------------------------------------------------
* Copyright 2022 Informal Systems
* Licensed under the Apache License, Version 2.0.
* See LICENSE in the project root for license information.
* --------------------------------------------------------------------------------- */
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.flattenUnions = exports.simplify = void 0;
/**
* Simplification for effects, including a check on multiple updates of the same entity
*
* @author Gabriela Moreira
*
* @module
*/
const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
const util_1 = require("../util");
/**
* Simplifies a concrete effect by:
* 1. Removing repeated entities (except for updates)
* 2. Flattening nested unions
*
* @param e the concrete effect to be simplified
*
* @returns the simplified effect
*/
function simplifyConcreteEffect(e) {
const components = e.components.map(c => {
const flatEntity = flattenUnions(c.entity);
const entity = c.kind === 'update' ? flatEntity : deduplicateEntity(flatEntity);
return { kind: c.kind, entity };
});
return { kind: 'concrete', components };
}
function simplify(e) {
switch (e.kind) {
case 'concrete':
return simplifyConcreteEffect(e);
case 'variable':
return e;
case 'arrow': {
const params = e.params.map(simplify);
const result = simplify(e.result);
return { kind: 'arrow', params, result };
}
}
}
exports.simplify = simplify;
/**
* Transforms entities of form [x, [y, z]] into [x, y, z]
*
* @param entity the entity to be transformed
*
* @returns the flattened form of union if a union.
* Otherwise, the entity without change.
*/
function flattenUnions(entity) {
if (entity.kind == 'union') {
const unionEntities = [];
const vars = [];
const flattenEntities = entity.entities.map(v => flattenUnions(v));
flattenEntities.map(v => {
switch (v.kind) {
case 'variable':
unionEntities.push(v);
break;
case 'concrete':
vars.push(...v.stateVariables);
break;
case 'union':
unionEntities.push(...v.entities);
break;
default:
(0, util_1.unreachable)(v);
}
});
if (unionEntities.length > 0) {
const entities = vars.length > 0 ? unionEntities.concat({ kind: 'concrete', stateVariables: vars }) : unionEntities;
return entities.length > 1 ? { kind: 'union', entities: entities } : entities[0];
}
else {
return { kind: 'concrete', stateVariables: vars };
}
}
else {
return entity;
}
}
exports.flattenUnions = flattenUnions;
function deduplicateEntity(entity) {
switch (entity.kind) {
case 'variable':
return entity;
case 'concrete':
return { kind: 'concrete', stateVariables: Array.from(new Set(entity.stateVariables)) };
case 'union': {
const nestedEntities = entity.entities.map(v => deduplicateEntity(v));
const unique = [];
nestedEntities.forEach(entity => {
if (!unique.some(v => (0, lodash_isequal_1.default)(v, entity))) {
unique.push(entity);
}
});
return { kind: 'union', entities: unique };
}
}
}
//# sourceMappingURL=simplification.js.map