@informalsystems/quint
Version:
Core tool for the Quint specification language
170 lines • 6.39 kB
JavaScript
;
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