UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

150 lines 9.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const mocha_1 = require("mocha"); const chai_1 = require("chai"); const resolver_1 = require("../../src/names/resolver"); const ir_1 = require("../builders/ir"); const idGenerator_1 = require("../../src/idGenerator"); (0, mocha_1.describe)('resolveNames', () => { const baseDefs = [ 'const TEST_CONSTANT: int', 'val unscoped_def = val scoped_def = 10 scoped_def ', 'type MY_TYPE = int', ]; function resolveNamesForExprs(exprs, idGenerator) { const idGen = idGenerator ?? idGenerator_1.zerog; const module = (0, ir_1.buildModule)(baseDefs, exprs, undefined, idGen); return (0, resolver_1.resolveNames)([module]); } function resolveNamesForDefs(defs, idGenerator) { const idGen = idGenerator ?? idGenerator_1.zerog; const module = (0, ir_1.buildModuleWithDecls)(baseDefs.concat(defs), undefined, idGen); return (0, resolver_1.resolveNames)([module]); } (0, mocha_1.describe)('operator definitions', () => { (0, mocha_1.it)('finds top level definitions', () => { const result = resolveNamesForExprs(['TEST_CONSTANT.filter(a => unscoped_def > 0)']); chai_1.assert.isEmpty(result.errors); }); (0, mocha_1.it)('finds scoped definitions inside of scope', () => { const result = resolveNamesForExprs(['TEST_CONSTANT.filter(a => a > 0)']); chai_1.assert.isEmpty(result.errors); }); (0, mocha_1.it)('finds unused definitions', () => { const module = (0, ir_1.buildModule)(baseDefs, ['1 + TEST_CONSTANT'], undefined, idGenerator_1.zerog); const result = (0, resolver_1.resolveNames)([module]); chai_1.assert.isEmpty(result.errors); chai_1.assert.sameDeepMembers(Array.from(result.unusedDefinitions('wrapper')).map(d => d.name), ['unscoped_def', 'MY_TYPE', 'd0']); }); (0, mocha_1.it)('does not find scoped definitions outside of scope', () => { const result = resolveNamesForExprs(['TEST_CONSTANT', 'scoped_def']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Name 'scoped_def' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('find unresolved names inside application', () => { const result = resolveNamesForExprs(['head(x)', 'x(true)']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Name 'x' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Name 'x' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('find unresolved names inside lambdas', () => { const result = resolveNamesForExprs(['Nat.filter(a => x > 1)']); chai_1.assert.deepEqual(result.errors, [{ code: 'QNT404', message: "Name 'x' not found", reference: 0n, data: {} }]); }); (0, mocha_1.it)('find unresolved names inside lets', () => { const result = resolveNamesForExprs(['val a = x { true }', 'val b = true { x }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Name 'x' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Name 'x' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds a definition itself with depth information', () => { const result = resolveNamesForExprs([], (0, idGenerator_1.newIdGenerator)()); chai_1.assert.isEmpty(result.errors); const def = [...result.table.values()].find(def => def.name === 'unscoped_def' || def.kind === 'def'); chai_1.assert.isNotNull(def); chai_1.assert.deepEqual(result.table.get(def.id)?.depth, 0); }); }); (0, mocha_1.describe)('shadowing', () => { (0, mocha_1.it)('resolves shadowed names', () => { const result = resolveNamesForDefs(['val shadowing = def foo = (shadowing) => shadowing { foo(1) }', 'val a = shadowing'], (0, idGenerator_1.newIdGenerator)()); chai_1.assert.isEmpty(result.errors); chai_1.assert.isTrue([...result.table.values()].some(def => def.name === 'shadowing' && def.kind === 'def')); chai_1.assert.isTrue([...result.table.values()].some(def => def.name === 'shadowing' && def.kind === 'param')); }); (0, mocha_1.it)('collects depth and shadowing information properly', () => { const result = resolveNamesForDefs(['val shadowing = val a = 1 { val a = 2 { a } }'], (0, idGenerator_1.newIdGenerator)()); chai_1.assert.isEmpty(result.errors); chai_1.assert.isTrue([...result.table.values()].some(def => def.name === 'a' && def.depth === 2), 'Could not find first a'); chai_1.assert.isTrue([...result.table.values()].some(def => def.name === 'a' && def.depth === 3 && def.shadowing === true), 'Could not find second a'); }); }); (0, mocha_1.describe)('type aliases', () => { (0, mocha_1.it)('resolves defined aliases', () => { const result = resolveNamesForDefs(['const a: MY_TYPE', 'var b: a -> Set[a]']); chai_1.assert.isEmpty(result.errors); }); (0, mocha_1.it)('finds unresolved aliases under typed definitions', () => { const result = resolveNamesForDefs([ 'const a: UNKNOWN_TYPE_0', 'var b: UNKNOWN_TYPE_1', 'type C[t] = Set[t]', 'assume d = 1', ]); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE_0' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE_1' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under chained lets', () => { const result = resolveNamesForExprs(['val x = 1 { val y: Set[UNKNOWN_TYPE] = 1 { Set(0) } }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under Set', () => { const result = resolveNamesForExprs(['val x: Set[UNKNOWN_TYPE] = 1 { 0 }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under List', () => { const result = resolveNamesForExprs(['val x: List[UNKNOWN_TYPE] = 1 { 0 }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under functions', () => { const result = resolveNamesForExprs(['val x: UNKNOWN_TYPE -> OTHER_UNKNOWN_TYPE = 1 { 0 }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Type alias 'OTHER_UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under operators', () => { const result = resolveNamesForExprs(['val f(x): (UNKNOWN_TYPE) => OTHER_UNKNOWN_TYPE = { unscoped_def } { 0 }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Type alias 'OTHER_UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under tuples', () => { const result = resolveNamesForExprs(['val x: (UNKNOWN_TYPE, OTHER_UNKNOWN_TYPE) = (1, 2) { 0 }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Type alias 'OTHER_UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); (0, mocha_1.it)('finds unresolved aliases under records', () => { const result = resolveNamesForExprs(['val x: { a: UNKNOWN_TYPE, b: OTHER_UNKNOWN_TYPE } = { a: 1, b: 2 } { 0 }']); chai_1.assert.deepEqual(result.errors, [ { code: 'QNT404', message: "Type alias 'UNKNOWN_TYPE' not found", reference: 0n, data: {} }, { code: 'QNT404', message: "Type alias 'OTHER_UNKNOWN_TYPE' not found", reference: 0n, data: {} }, ]); }); }); }); //# sourceMappingURL=resolver.test.js.map