@informalsystems/quint
Version:
Core tool for the Quint specification language
95 lines • 5.2 kB
JavaScript
;
/* ----------------------------------------------------------------------------------
* Copyright 2023 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.flattenModules = void 0;
/**
* Flattening for modules, replacing instances, imports and exports with definitions referred by the module.
*
* @author Gabriela Moreira
*
* @module
*/
const assert_1 = __importDefault(require("assert"));
const IRprinting_1 = require("../ir/IRprinting");
const quintIr_1 = require("../ir/quintIr");
const quintParserFrontend_1 = require("../parsing/quintParserFrontend");
const aliasInliner_1 = require("../types/aliasInliner");
const flattener_1 = require("./flattener");
const instanceFlattener_1 = require("./instanceFlattener");
const unshadower_1 = require("../names/unshadower");
const quintError_1 = require("../quintError");
/**
* Flatten an array of modules, replacing instances, imports and exports with
* their definitions and inlining type aliases.
*
* @param modules The modules to flatten
* @param table The lookup table to for all referred names
* @param idGenerator The id generator to use for new definitions; should be the same as used for parsing
* @param sourceMap The source map for all modules involved
* @param analysisOutput The analysis output for all modules involved
*
* @returns An object containing the flattened modules, flattened lookup table and flattened analysis output
*/
function flattenModules(modules, table, idGenerator, sourceMap, analysisOutput) {
// FIXME: use copies of parameters so the original objects are not mutated.
// This is not a problem atm, but might be in the future.
// Use unique names when there is shadowing
const modulesWithUniqueNames = modules.map(m => (0, unshadower_1.unshadowNames)(m, table));
// Inline type aliases
const inlined = (0, aliasInliner_1.inlineTypeAliases)(modulesWithUniqueNames, table, analysisOutput);
const modulesByName = new Map(inlined.modules.map(m => [m.name, m]));
// Mutable values, updated on every iteration
const flattenedAnalysis = inlined.analysisOutput;
const modulesQueue = inlined.modules;
// Mutable references, updated on every iteration
let flattenedModules = [];
let flattenedTable = inlined.table;
while (modulesQueue.length > 0) {
const module = modulesQueue.shift();
// First, flatten imports and exports
const moduleAfterFirstFlattening = (0, flattener_1.flattenModule)(module, modulesByName, flattenedTable);
// Then, flatten instances, replacing them with imports
const instancedModules = (0, instanceFlattener_1.flattenInstances)(moduleAfterFirstFlattening, modulesByName, flattenedTable, idGenerator, sourceMap, flattenedAnalysis);
// Get an updated lookup table including references for the instanced modules. For that, use all the modules that
// were flattened so far, plus the instanced modules.
const intermediateTable = resolveNamesOrThrow(flattenedModules.concat(instancedModules), sourceMap).table;
// Flatten the instanced modules, removing the added imports.
instancedModules.forEach(m => {
const flat = (0, flattener_1.flattenModule)(m, modulesByName, intermediateTable);
flattenedModules.push(flat);
// Update the index that is going to be used in next iterations
modulesByName.set(m.name, flat);
});
// Finally, get an updated lookup table and a toposorted version of the definitions. For that, we combine the
// modules that were flattened so far, plus the modules that still have to be flattened (queue). We need to do this
// for the modules in the queue as well since they might also refer to definitions that had their ids changed by the
// instance flattener.
const result = resolveNamesOrThrow(flattenedModules.concat(modulesQueue), sourceMap);
flattenedModules = result.modules.slice(0, flattenedModules.length);
flattenedTable = result.table;
}
// FIXME: Ideally we should do this via the type system
(0, assert_1.default)(flattenedModules.every(m => m.declarations.every(quintIr_1.isDef)));
return {
flattenedModules: flattenedModules,
flattenedTable,
flattenedAnalysis,
};
}
exports.flattenModules = flattenModules;
function resolveNamesOrThrow(modules, sourceMap) {
const result = (0, quintParserFrontend_1.parsePhase3importAndNameResolution)({ modules, sourceMap, errors: [] });
if (result.errors.length > 0) {
modules.forEach(m => console.log((0, IRprinting_1.moduleToString)(m)));
throw new Error('Internal error while flattening ' + result.errors.map(quintError_1.quintErrorToString));
}
return result;
}
//# sourceMappingURL=fullFlattener.js.map