UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

101 lines 3.7 kB
"use strict"; /* ---------------------------------------------------------------------------------- * Copyright 2024 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.NondetChecker = void 0; /** * Checking for the misuse of 'nondet', 'oneOf', and 'apalache::generate'. * Necessary to ensure they are compatible with the exists operator from TLA+. * * @author Gabriela Moreira * * @module */ const IRVisitor_1 = require("../ir/IRVisitor"); const printing_1 = require("../types/printing"); class NondetChecker { constructor(table) { this.types = new Map(); this.lastDefQualifier = 'def'; this.errors = []; this.table = table; } /** * Checks declarations for misuse of 'nondet', 'oneOf', and 'apalache::generate'. * * @param types - the types of the declarations * @param declarations - the declarations to check * * @returns a list of errors (empty if no errors are found) */ checkNondets(types, declarations) { this.types = types; declarations.forEach(d => (0, IRVisitor_1.walkDeclaration)(this, d)); return this.errors; } enterOpDef(def) { this.lastDefQualifier = def.qualifier; const entry = this.table.get(def.id); if (!entry) { // A name resolution error should have been reported already return; } if (def.qualifier === 'nondet' && entry.depth === 0) { this.errors.push({ code: 'QNT206', message: `'nondet' can only be used inside actions, not at the top level`, reference: def.id, data: {}, }); } } enterApp(app) { if (app.opcode !== 'oneOf' && app.opcode !== 'apalache::generate') { // nothing to check return; } if (this.lastDefQualifier !== 'nondet') { this.errors.push({ code: 'QNT203', message: `'${app.opcode}' must be used inside a nondet definition`, reference: app.id, data: {}, }); return; } } enterLet(expr) { if (expr.opdef.qualifier !== 'nondet') { return; } // body of nondet must be an application of oneOf or apalache::generate const body = expr.opdef.expr; if (body.kind !== 'app' || (body.opcode !== 'oneOf' && body.opcode !== 'apalache::generate')) { this.errors.push({ code: 'QNT204', message: `the outermost expression in a nondet definition must be either 'oneOf' or 'apalache::generate'`, reference: body.id, data: {}, }); } // if the opdef is nondet, the return type must be bool const expressionType = this.types.get(expr.expr.id); if (!expressionType) { // A type error should have been reported already return; } if (expressionType.type.kind !== 'bool') { this.errors.push({ code: 'QNT205', message: `nondet bindings can only be used with boolean expressions, but expression has type: ${(0, printing_1.typeSchemeToString)(expressionType)}`, reference: expr.id, data: {}, }); } } } exports.NondetChecker = NondetChecker; //# sourceMappingURL=NondetChecker.js.map