UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

433 lines 13.9 kB
"use strict"; /* ---------------------------------------------------------------------------------- * Copyright 2022 Informal Systems * Licensed under the Apache License, Version 2.0. * See LICENSE in the project root for license information. * --------------------------------------------------------------------------------- */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.walkExpression = exports.walkDefinition = exports.walkDeclaration = exports.walkType = exports.walkModule = void 0; /** * Visitor pattern implementation for Quint IR components. Use this to navigate the IR instead * of implementing a recursion over it yourself. * * @author Gabriela Moreira * * @module */ const ir = __importStar(require("./quintIr")); const util_1 = require("../util"); /** * Navigates a Quint module with a visitor, invoking the correspondent function for each * found IR component. * * @param visitor: the IRVisitor instance with the functions to be invoked * @param quintModule: the Quint module to be navigated * * @returns nothing, any collected information has to be a state inside the IRVisitor instance. */ function walkModule(visitor, quintModule) { if (visitor.enterModule) { visitor.enterModule(quintModule); } quintModule.declarations.forEach(decl => walkDeclaration(visitor, decl)); if (visitor.exitModule) { visitor.exitModule(quintModule); } } exports.walkModule = walkModule; /** * Navigates a Quint type with a visitor, invoking the correspondent function for each * inner type. * * @param visitor: the IRVisitor instance with the functions to be invoked * @param type: the Quint type to be navigated * * @returns nothing, any collected information has to be a state inside the IRVisitor instance. */ function walkType(visitor, type) { if (visitor.enterType) { visitor.enterType(type); } switch (type.kind) { case 'bool': case 'int': case 'str': if (visitor.enterLiteralType) { visitor.enterLiteralType(type); } if (visitor.exitLiteralType) { visitor.exitLiteralType(type); } break; case 'const': if (visitor.enterConstType) { visitor.enterConstType(type); } if (visitor.exitConstType) { visitor.exitConstType(type); } break; case 'var': if (visitor.enterVarType) { visitor.enterVarType(type); } if (visitor.exitVarType) { visitor.exitVarType(type); } break; case 'set': if (visitor.enterSetType) { visitor.enterSetType(type); } walkType(visitor, type.elem); if (visitor.exitSetType) { visitor.exitSetType(type); } break; case 'list': if (visitor.enterSeqType) { visitor.enterSeqType(type); } walkType(visitor, type.elem); if (visitor.exitSeqType) { visitor.exitSeqType(type); } break; case 'fun': if (visitor.enterFunType) { visitor.enterFunType(type); } // Functions, walk both argument and result walkType(visitor, type.arg); walkType(visitor, type.res); if (visitor.exitFunType) { visitor.exitFunType(type); } break; case 'oper': if (visitor.enterOperType) { visitor.enterOperType(type); } // Operators, walk all arguments and result type.args.forEach(arg => walkType(visitor, arg)); walkType(visitor, type.res); if (visitor.exitOperType) { visitor.exitOperType(type); } break; case 'tup': if (visitor.enterTupleType) { visitor.enterTupleType(type); } // Tuples, walk all elements walkRow(visitor, type.fields); if (visitor.exitTupleType) { visitor.exitTupleType(type); } break; case 'rec': if (visitor.enterRecordType) { visitor.enterRecordType(type); } // Records, walk all fields walkRow(visitor, type.fields); if (visitor.exitRecordType) { visitor.exitRecordType(type); } break; case 'sum': visitor.enterSumType?.(type); walkRow(visitor, type.fields); visitor.exitSumType?.(type); break; case 'app': visitor.enterAppType?.(type); walkType(visitor, type.ctor); type.args.map(t => walkType(visitor, t)); visitor.exitAppType?.(type); break; default: (0, util_1.unreachable)(type); } if (visitor.exitType) { visitor.exitType(type); } } exports.walkType = walkType; /** * Navigates a Quint declaration with a visitor, invoking the correspondent function for each * inner component. * * @param visitor: the IRVisitor instance with the functions to be invoked * @param decl: the Quint declaration to be navigated * * @returns nothing, any collected information has to be a state inside the IRVisitor instance. */ function walkDeclaration(visitor, decl) { if (visitor.enterDecl) { visitor.enterDecl(decl); } // The standard depth starts at 0, so definitions inside delclarations (i.e. // assume and instance overrides) are not considered top-level visitor.definitionDepth = 0; switch (decl.kind) { case 'const': case 'var': case 'typedef': case 'assume': walkDefinition(visitor, decl); break; case 'def': // depth will be increased inside `walkDefinition`, so we set it to -1 in // order for it to be 0 there visitor.definitionDepth = -1; walkDefinition(visitor, decl); break; case 'instance': if (visitor.enterInstance) { visitor.enterInstance(decl); } decl.overrides.forEach(([_, e]) => walkExpression(visitor, e)); if (visitor.exitInstance) { visitor.exitInstance(decl); } break; case 'import': if (visitor.enterImport) { visitor.enterImport(decl); } if (visitor.exitImport) { visitor.exitImport(decl); } break; case 'export': if (visitor.enterExport) { visitor.enterExport(decl); } if (visitor.exitExport) { visitor.exitExport(decl); } break; default: (0, util_1.unreachable)(decl); } if (visitor.exitDecl) { visitor.exitDecl(decl); } } exports.walkDeclaration = walkDeclaration; /** * Navigates a Quint definition with a visitor, invoking the correspondent function for each * inner component. * * @param visitor: the IRVisitor instance with the functions to be invoked * @param def: the Quint definition to be navigated * * @returns nothing, any collected information has to be a state inside the IRVisitor instance. */ function walkDefinition(visitor, def) { if (visitor.definitionDepth !== undefined) { visitor.definitionDepth++; } if (visitor.enterDef) { visitor.enterDef(def); } if (ir.isAnnotatedDef(def)) { walkType(visitor, def.typeAnnotation); } else if (ir.isTypeAlias(def)) { walkType(visitor, def.type); } switch (def.kind) { case 'const': if (visitor.enterConst) { visitor.enterConst(def); } if (visitor.exitConst) { visitor.exitConst(def); } break; case 'var': if (visitor.enterVar) { visitor.enterVar(def); } if (visitor.exitVar) { visitor.exitVar(def); } break; case 'def': if (visitor.enterOpDef) { visitor.enterOpDef(def); } walkExpression(visitor, def.expr); if (visitor.exitOpDef) { visitor.exitOpDef(def); } break; case 'typedef': if (visitor.enterTypeDef) { visitor.enterTypeDef(def); } if (visitor.exitTypeDef) { visitor.exitTypeDef(def); } break; case 'assume': if (visitor.enterAssume) { visitor.enterAssume(def); } walkExpression(visitor, def.assumption); if (visitor.exitAssume) { visitor.exitAssume(def); } break; default: (0, util_1.unreachable)(def); } if (visitor.exitDef) { visitor.exitDef(def); } if (visitor.definitionDepth !== undefined) { visitor.definitionDepth--; } } exports.walkDefinition = walkDefinition; function walkExpression(visitor, expr) { if (visitor.enterExpr) { visitor.enterExpr(expr); } switch (expr.kind) { case 'name': if (visitor.enterName) { visitor.enterName(expr); } if (visitor.exitName) { visitor.exitName(expr); } break; case 'bool': case 'int': case 'str': if (visitor.enterLiteral) { visitor.enterLiteral(expr); } if (visitor.exitLiteral) { visitor.exitLiteral(expr); } break; case 'app': { if (visitor.enterApp) { visitor.enterApp(expr); } expr.args.forEach(arg => walkExpression(visitor, arg)); if (visitor.exitApp) { visitor.exitApp(expr); } break; } case 'lambda': if (visitor.definitionDepth !== undefined) { visitor.definitionDepth++; } if (visitor.enterLambda) { visitor.enterLambda(expr); } expr.params.forEach(p => { if (p.typeAnnotation) { walkType(visitor, p.typeAnnotation); } }); walkExpression(visitor, expr.expr); if (visitor.exitLambda) { visitor.exitLambda(expr); } if (visitor.definitionDepth !== undefined) { visitor.definitionDepth--; } break; case 'let': if (visitor.definitionDepth !== undefined) { visitor.definitionDepth++; } if (visitor.enterLet) { visitor.enterLet(expr); } walkDefinition(visitor, expr.opdef); walkExpression(visitor, expr.expr); if (visitor.exitLet) { visitor.exitLet(expr); } if (visitor.definitionDepth !== undefined) { visitor.definitionDepth--; } break; default: (0, util_1.unreachable)(expr); } if (visitor.exitExpr) { visitor.exitExpr(expr); } } exports.walkExpression = walkExpression; function walkRow(visitor, r) { if (visitor.enterRow) { visitor.enterRow(r); } switch (r.kind) { case 'row': if (visitor.enterConcreteRow) { visitor.enterConcreteRow(r); } r.fields.forEach(field => walkType(visitor, field.fieldType)); walkRow(visitor, r.other); if (visitor.exitConcreteRow) { visitor.exitConcreteRow(r); } break; case 'var': if (visitor.enterVarRow) { visitor.enterVarRow(r); } if (visitor.exitVarRow) { visitor.exitVarRow(r); } break; case 'empty': if (visitor.enterEmptyRow) { visitor.enterEmptyRow(r); } if (visitor.exitEmptyRow) { visitor.exitEmptyRow(r); } break; default: (0, util_1.unreachable)(r); } if (visitor.exitRow) { visitor.exitRow(r); } } //# sourceMappingURL=IRVisitor.js.map