UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

170 lines 6.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.expandOutputTemplate = exports.expandNamedOutputTemplate = exports.PLACEHOLDERS = exports.deriveVerbosity = exports.isMatchingTest = exports.loadApalacheConfig = exports.addItfHeader = exports.getInvariants = exports.guessMainModule = exports.toExpr = exports.mkErrorMessage = void 0; const path_1 = require("path"); const quintParserFrontend_1 = require("./parsing/quintParserFrontend"); const either_1 = require("@sweet-monads/either"); const quintError_1 = require("./quintError"); const IRVisitor_1 = require("./ir/IRVisitor"); const fs_1 = require("fs"); const cliReporting_1 = require("./cliReporting"); function mkErrorMessage(sourceMap) { return error => { const loc = error.reference ? sourceMap.get(error.reference) : undefined; return { explanation: (0, quintError_1.quintErrorToString)(error), locs: loc ? [loc] : [], }; }; } exports.mkErrorMessage = mkErrorMessage; function toExpr(prev, input) { const mainName = guessMainModule(prev); const parseResult = (0, quintParserFrontend_1.parseExpressionOrDeclaration)(input, '<input>', prev.idGen, prev.sourceMap); if (parseResult.kind !== 'expr') { return (0, either_1.left)({ code: 'QNT501', message: `Expected ${input} to be a valid expression` }); } prev.resolver.switchToModule(mainName); (0, IRVisitor_1.walkExpression)(prev.resolver, parseResult.expr); if (prev.resolver.errors.length > 0) { return (0, either_1.left)(prev.resolver.errors[0]); } return (0, either_1.right)(parseResult.expr); } exports.toExpr = toExpr; function guessMainModule(stage) { if (stage.args.main) { // the main module is specified via --main return stage.args.main; } if (stage.defaultModuleName.isJust()) { // there is only one module in the source file, make it main return stage.defaultModuleName.unwrap(); } // guess the name from the filename return (0, path_1.basename)(stage.args.input, '.qnt'); } exports.guessMainModule = guessMainModule; /** * Process invariants from arguments and return the combined invariant string * and individual invariants list. * * @param args The arguments containing invariant and invariants options. * @returns A tuple [invariantString, individualInvariants]. */ function getInvariants(args) { let invariantsList = []; // Add single invariant if specified and not 'true' if (args.invariant && args.invariant !== 'true') { invariantsList.push(args.invariant); } // Add multiple invariants if specified if (args.invariants && args.invariants.length > 0) { invariantsList = invariantsList.concat(args.invariants); } // Determine the combined invariant string and individual invariants const invariantString = invariantsList.length > 0 ? invariantsList.join(' and ') : 'true'; return [invariantString, invariantsList]; } exports.getInvariants = getInvariants; function addItfHeader(source, status, traceInJson) { return { '#meta': { format: 'ITF', 'format-description': 'https://apalache-mc.org/docs/adr/015adr-trace.html', source, status, description: 'Created by Quint on ' + new Date(), timestamp: Date.now(), }, ...traceInJson, }; } exports.addItfHeader = addItfHeader; function loadApalacheConfig(stage, apalacheConfig) { try { if (apalacheConfig) { return JSON.parse((0, fs_1.readFileSync)(apalacheConfig, 'utf-8')); } else { return {}; } } catch (err) { return (0, cliReporting_1.cliErr)(`failed to read Apalache config: ${err.message}`, { ...stage, errors: [], sourceCode: new Map() }); } } exports.loadApalacheConfig = loadApalacheConfig; /** * Does a definition name match the expected test criteria. * * @param tests an optional array of test names * @param name the name of a definition to match * @returns whether the name matches the tests, if tests are not undefined, * or name ends with 'Test' * */ function isMatchingTest(match, name) { if (match) { return new RegExp(match).exec(name) !== null; } else { return name.endsWith('Test'); } } exports.isMatchingTest = isMatchingTest; // Derive the verbosity for simulation and verification routines function deriveVerbosity(args) { return args.out ? 0 : args.verbosity; } exports.deriveVerbosity = deriveVerbosity; exports.PLACEHOLDERS = { test: '{test}', seq: '{seq}', }; /** * Expand the output template with the name of the test and the index of the trace. * * Possible placeholders: * - {test} is replaced with the name of the test * - {seq} is replaced with the index of the trace * * If {seq} is not present and `options.autoAppend` is true, * the index is appended to the filename, before the extension. * * @param template the output template * @param name the name of the test * @param index the index of the trace * @param options An object of the form `{ autoAppend: boolean }` * @returns the expanded output template */ function expandNamedOutputTemplate(template, name, index, options) { return expandOutputTemplate(template.replaceAll(exports.PLACEHOLDERS.test, name), index, options); } exports.expandNamedOutputTemplate = expandNamedOutputTemplate; /** * Expand the output template with the index of the trace. * * The {seq} placeholder is replaced with the index of the trace. * * If {seq} is not present and `options.autoAppend` is true, * the index is appended to the filename, before the extension. * * @param template the output template * @param index the index of the trace * @param options An object of the form `{ autoAppend: boolean }` * @returns the expanded output template */ function expandOutputTemplate(template, index, options) { if (template.includes(exports.PLACEHOLDERS.seq)) { return template.replaceAll(exports.PLACEHOLDERS.seq, index.toString()); } if (options.autoAppend) { const parts = template.split('.'); parts[0] += `${index}`; return parts.join('.'); } return template; } exports.expandOutputTemplate = expandOutputTemplate; //# sourceMappingURL=cliHelpers.js.map