Skip to content

Commit 7a8c9e7

Browse files
authored
Merge pull request #10919 from kaspersv/kaspersv/document-equiv-rel-module
QL language spec: Document built-in equivalence relation module
2 parents 2e6d6e1 + b29ed3b commit 7a8c9e7

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

docs/codeql/ql-language-reference/modules.rst

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,71 @@ The ``<module_expression>`` itself can be a module name, a selection, or a quali
273273
reference. For more information, see ":ref:`name-resolution`."
274274

275275
For information about how import statements are looked up, see "`Module resolution <https://codeql.github.com/docs/ql-language-reference/ql-language-specification/#module-resolution>`__"
276-
in the QL language specification.
276+
in the QL language specification.
277+
278+
Built-in modules
279+
****************
280+
281+
QL defines a ``QlBuiltins`` module that is always in scope.
282+
Currently, it defines a single parameterized sub-module
283+
``EquivalenceRelation``, that provides an efficient abstraction for working with
284+
(partial) equivalence relations in QL.
285+
286+
Equivalence relations
287+
=====================
288+
289+
The built-in ``EquivalenceRelation`` module is parameterized by a type ``T`` and a
290+
binary base relation ``base`` on ``T``. The symmetric and transitive closure of ``base``
291+
induces a partial equivalence relation on ``T``. If every value of ``T`` appears in
292+
``base``, then the induced relation is an equivalence relation on ``T``.
293+
294+
The ``EquivalenceRelation`` module exports a ``getEquivalenceClass`` predicate that
295+
gets the equivalence class, if any, associated with a given ``T`` element by the
296+
(partial) equivalence relation induced by ``base``.
297+
298+
The following example illustrates an application of the ``EquivalenceRelation``
299+
module to generate a custom equivalence relation:
300+
301+
.. code-block:: ql
302+
303+
class Node extends int {
304+
Node() { this in [1 .. 6] }
305+
}
306+
307+
predicate base(Node x, Node y) {
308+
x = 1 and y = 2
309+
or
310+
x = 3 and y = 4
311+
}
312+
313+
module Equiv = QlBuiltins::EquivalenceRelation<Node, base/2>;
314+
315+
from int x, int y
316+
where Equiv::getEquivalenceClass(x) = Equiv::getEquivalenceClass(y)
317+
select x, y
318+
319+
Since ``base`` does not relate ``5`` or ``6`` to any nodes, the induced
320+
relation is a partial equivalence relation on ``Node`` and does not relate ``5``
321+
or ``6`` to any nodes either.
322+
323+
The above select clause returns the following partial equivalence relation:
324+
325+
+---+---+
326+
| x | y |
327+
+===+===+
328+
| 1 | 1 |
329+
+---+---+
330+
| 1 | 2 |
331+
+---+---+
332+
| 2 | 1 |
333+
+---+---+
334+
| 2 | 2 |
335+
+---+---+
336+
| 3 | 3 |
337+
+---+---+
338+
| 3 | 4 |
339+
+---+---+
340+
| 4 | 3 |
341+
+---+---+
342+
| 4 | 4 |
343+
+---+---+

0 commit comments

Comments
 (0)