UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

229 lines 14.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const mocha_1 = require("mocha"); const chai_1 = require("chai"); const ir_1 = require("../builders/ir"); const collector_1 = require("../../src/names/collector"); const IRVisitor_1 = require("../../src/ir/IRVisitor"); const base_1 = require("../../src/names/base"); const idGenerator_1 = require("../../src/idGenerator"); (0, mocha_1.describe)('NameCollector', () => { const baseModule = (0, ir_1.buildModuleWithDecls)(['def a = 1', 'def b = 2', 'def c = 3', 'const c1: int', 'const c2: int', 'type T = int', 'type R'], 'test_module', idGenerator_1.zerog); function collect(module) { const collector = new collector_1.NameCollector(); (0, IRVisitor_1.walkModule)(collector, baseModule); (0, IRVisitor_1.walkModule)(collector, module); return [collector.errors, collector.definitionsByName]; } (0, mocha_1.describe)('existing modules', () => { (0, mocha_1.it)('imports named definitions', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.a'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.deepInclude([...definitions.keys()], 'a'); chai_1.assert.notDeepInclude([...definitions.keys()], 'b'); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'a')?.importedFrom?.kind, 'import'); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'a')?.namespaces ?? [], []); }); (0, mocha_1.it)('imports all definitions', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.*'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.includeDeepMembers([...definitions.keys()], ['a', 'b', 'T']); }); (0, mocha_1.it)('imports definitions with namespace', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); const def = (0, base_1.getTopLevelDef)(definitions, 'test_module::a'); chai_1.assert.isTrue(def.hidden); chai_1.assert.deepEqual(def?.kind, 'def'); }); (0, mocha_1.it)('imports definitions with qualifier', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module as my_import'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); const def = (0, base_1.getTopLevelDef)(definitions, 'my_import::a'); chai_1.assert.isTrue(def.hidden); chai_1.assert.deepEqual(def?.kind, 'def'); }); (0, mocha_1.it)('instantiates modules', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module(c1 = 3, c2 = 4) as test_module_instance'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.includeDeepMembers([...definitions.keys()], ['test_module_instance::c1', 'test_module_instance::c2']); chai_1.assert.includeDeepMembers([...definitions.keys()], ['test_module_instance::T']); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'test_module_instance::a')?.importedFrom?.kind, 'instance'); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'test_module_instance::a')?.namespaces ?? [], [ 'test_module_instance', 'wrapper', ]); }); (0, mocha_1.it)('fails instantiating when a param does not exists', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module(c1 = 3, c2 = 4, other = 5) as test_module_instance'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT406', message: "Instantiation error: 'other' not found in 'test_module'", reference: 0n, data: {}, }, ]); }); (0, mocha_1.it)('fails instantiating when a param is not a constant', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module(c1 = 3, c2 = 4, a = 5) as test_module_instance'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT406', message: "Instantiation error: 'a' is not a constant in 'test_module'", reference: 0n, data: {}, }, ]); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'test_module_instance::a')?.kind, 'def'); }); (0, mocha_1.it)('fails importing itself', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import wrapper.*', 'import wrapper(c1 = 1) as w', 'export wrapper.*'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT407', message: "Cannot import 'wrapper' inside 'wrapper'", reference: 0n, data: {} }, { code: 'QNT407', message: "Cannot instantiate 'wrapper' inside 'wrapper'", reference: 0n, data: {} }, { code: 'QNT407', message: "Cannot export 'wrapper' inside 'wrapper'", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('exports all definitions', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['export test_module.*'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'a').hidden); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'T').hidden); }); (0, mocha_1.it)('exports previously imported definitions', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.*', 'export test_module.*'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'a').hidden); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'T').hidden); }); (0, mocha_1.it)('exports imported definitions that were previously qualified', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module as T1', 'export T1.*'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'a').hidden); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'T').hidden); }); (0, mocha_1.it)('exports specific definitions', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.*', 'export test_module.a'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); // a is not hidden anymore chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'a').hidden); // T is still hidden chai_1.assert.isTrue((0, base_1.getTopLevelDef)(definitions, 'T').hidden); }); (0, mocha_1.it)('exports definitions with qualifier', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.*', 'export test_module as my_export'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isTrue((0, base_1.getTopLevelDef)(definitions, 'a').hidden); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'my_export::a').hidden); }); (0, mocha_1.it)('exports definitions with namespace', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.*', 'export test_module'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isTrue((0, base_1.getTopLevelDef)(definitions, 'a').hidden); chai_1.assert.isNotTrue((0, base_1.getTopLevelDef)(definitions, 'test_module::a').hidden); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'a')?.importedFrom?.kind, 'import'); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'test_module::a')?.importedFrom?.kind, 'export'); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'a')?.namespaces ?? [], []); chai_1.assert.deepEqual((0, base_1.getTopLevelDef)(definitions, 'test_module::a')?.namespaces ?? [], ['test_module']); }); (0, mocha_1.it)('fails exporting unexisting definition', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module.*', 'export test_module.other'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT404', message: "Name 'test_module::other' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('does not collect nested defs inside assume', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['assume _ = val foo = 1 { foo }'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isFalse(definitions.has('foo')); }); (0, mocha_1.it)('does not collect nested defs inside instances', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import test_module(c1 = (val foo = 1 { foo })).*'], undefined, idGenerator_1.zerog); const [errors, definitions] = collect(quintModule); chai_1.assert.isEmpty(errors); chai_1.assert.isFalse(definitions.has('foo')); }); }); (0, mocha_1.describe)('conflicts', () => { (0, mocha_1.it)('reports conflicts with builtin names', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['def size(x) = 10'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT101', message: "Built-in name 'size' is redefined in module 'wrapper'", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('reports conflicts with user defined names', () => { // Use the real id generator to have different references for each def const quintModule = (0, ir_1.buildModuleWithDecls)(['def a = 10', 'import test_module.*']); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT101', message: "Conflicting definitions found for name 'a' in module 'wrapper'", reference: 2n, data: {}, }, { code: 'QNT101', message: "Conflicting definitions found for name 'a' in module 'wrapper'", reference: 0n, data: {}, }, ]); }); (0, mocha_1.it)('reports conflicts with module names', () => { // Setup already defines a module named 'test_module', see `baseDefs` const quintModule = (0, ir_1.buildModuleWithDecls)(['def a = 10'], 'test_module'); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT102', message: "Module with name 'test_module' was already defined", reference: 3n, data: {}, }, ]); }); }); (0, mocha_1.describe)('unexisting modules', () => { (0, mocha_1.it)('fails importing', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import unexisting_module.*'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT405', message: "Module 'unexisting_module' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('fails instantiating', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['import unexisting_module(c1 = c1, c2 = c2) as test_module_instance'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT405', message: "Module 'unexisting_module' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('fails exporting', () => { const quintModule = (0, ir_1.buildModuleWithDecls)(['export unexisting_module.*'], undefined, idGenerator_1.zerog); const [errors, _definitions] = collect(quintModule); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT405', message: "Module 'unexisting_module' not found", reference: 0n, data: {} }, ]); }); }); }); //# sourceMappingURL=collector.test.js.map