Skip to content

Commit f09c44f

Browse files
authored
Merge pull request github#13443 from github/ginsbach/SpecifyInstantiations
add QL specification section on module instantiations
2 parents 579c56c + 0c4eb68 commit f09c44f

File tree

1 file changed

+88
-6
lines changed

1 file changed

+88
-6
lines changed

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

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,24 +199,37 @@ Kinds of modules
199199

200200
A module may be:
201201

202+
- A *declared module*, if it is defined by the ``module`` or ``ql`` grammar rules.
203+
- A *non-declared module*, if it is not a *declared module*.
204+
205+
A *declared module* may be:
206+
202207
- A *file module*, if it is defined implicitly by a QL file or a QLL file.
203208
- A *query module*, if it is defined implicitly by a QL file.
204209
- A *library module*, if it is not a query module.
205210

211+
A *non-declared module* may be:
212+
213+
- A *built-in module*.
214+
- An *instantiated module* (see :ref:`Parameterized modules`).
215+
- An *instantiation-nested module* (see :ref:`Parameterized modules`).
216+
206217
A query module must contain one or more queries.
207218

208219
Import directives
209220
~~~~~~~~~~~~~~~~~
210221

211-
An import directive refers to a module identifier:
222+
An import directive refers to a module expression:
212223

213224
::
214225

215226
import ::= annotations "import" importModuleExpr ("as" modulename)?
216227

217-
qualId ::= simpleId | qualId "." simpleId
228+
importModuleExpr ::= importModuleId arguments?
218229

219-
importModuleExpr ::= qualId | importModuleExpr "::" modulename arguments?
230+
importModuleId ::= qualId | importModuleExpr "::" modulename
231+
232+
qualId ::= simpleId | qualId "." simpleId
220233

221234
arguments ::= "<" argument ("," argument)* ">"
222235

@@ -249,6 +262,73 @@ For qualified identifiers (``a.b``):
249262

250263
A qualified module identifier is only valid within an import.
251264

265+
Module expressions contain a module identifier and optional arguments. If arguments are present, the module expression instantiates the module that the identifier resolves to (see :ref:`Parameterized modules`).
266+
267+
Module expressions cannot refer to :ref:`Parameterized modules`. Instead, parameterized modules must always be fully instantiated when they are referenced.
268+
269+
.. _Parameterized modules:
270+
271+
Parameterized modules
272+
~~~~~~~~~~~~~~~~~~~~~
273+
274+
Modules with parameters are called *parameterized modules*. A *declared module* has parameters if and only if it is a *library module* and its declaration uses the ``parameters`` syntax.
275+
276+
*Parameterized modules* can be instantiated with arguments that match the signatures of the parameters:
277+
278+
- Given a type signature, the corresponding argument must be a type that transitively extends the specified ``extends`` types and is a transitive subtype of the specified ``instanceof`` types.
279+
- Given a predicate signature, the corresponding argument must be a predicate with exactly matching relational types.
280+
- Given a module signature, the corresponding argument must be a module that exports all the specified type and predicate members. Furthermore, the module must be declared as matching the module signature via the ``implements`` syntax.
281+
282+
The result of instantiating a *parameterized module* is an *instantiated module*. The parameterized module is called the *underlying module* of the *instantiated module*.
283+
284+
Instantiation-relative and instantiation-nested entities
285+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
286+
287+
Given an *instantiated module*, every entity has a corresponding entity called the *instantiation-relative* entity, which is determined as follows:
288+
289+
- If the entity is the *underlying module*, its *instantiation-relative* entity is the *instantiated module*.
290+
- If the entity is a parameter of the *underlying module*, its *instantiation-relative* entity is the corresponding argument.
291+
- If the entity is declared inside the *underlying module* or its nested modules, its *instantiation-relative* entity is an *instantiation-nested* entity that is generated by the module instantiation. Parameters of any modules that are nested inside the *underlying module* are considered declared inside the module for this purpose.
292+
- Otherwise, the entity's *instantiation-relative* entity is the initial entity itself.
293+
294+
When the *instantiation-relative* entity of an entity is an *instantiation-nested* entity, then the initial entity is called the *underlying nested* entity of the *instantiation-nested* entity*, the *instantiated module* is called the *instantiation root* of the *instantiation-nested* entity, and the *underlying module* is called the *underlying root* of the *instantiation-nested* entity.
295+
296+
The components of an *instantiation-nested* entity are the *instantiation-relative* entities of the components of its *underlying nested* entity. Among other things, this applies to:
297+
298+
- values in the exported environments of *instantiation-nested* modules,
299+
- relational types of *instantiation-nested* predicates and predicate signatures,
300+
- required signatures of *instantiation-nested* parameters,
301+
- parameters of an *instantiation-nested* *parameterized module*,
302+
- fields and member predicates of *instantiation-nested* dataclasses.
303+
304+
Given an *instantiated module*, any alias in the program has a corresponding alias called the *instantiation-relative* alias, which targets the *instantiation-relative* entity.
305+
306+
Applicative instantiation
307+
~~~~~~~~~~~~~~~~~~~~~~~~~
308+
309+
Every entity has an *underlying completely uninstantiated* entity that is determined as follows:
310+
311+
- If the entity is an *instantiated module*, its *underlying completely uninstantiated* entity is the *underlying completely uninstantiated* entity of the *underlying module*.
312+
- If the entity is an *instantiation-nested* entity, its *underlying completely uninstantiated* entity is the *underlying completely uninstantiated* entity of the *underlying nested* entity.
313+
- Otherwise, its *underlying completely uninstantiated* entity is the entity itself.
314+
315+
An entity is called *completely uninstantiated* entity if it is its own *underlying completely uninstantiated* entity.
316+
317+
Every *completely uninstantiated* entity has a *relevant set of parameters*, which is the set of all parameters of all the modules that the entity is transitively nested inside. For entities that are not nested inside any modules, the *relevant set of parameters* is empty.
318+
319+
Note that the *relevant set of parameters* by construction contains only *completely uninstantiated* parameters.
320+
321+
For a *completely uninstantiated* parameter, the *bottom-up instantiation-resolution* relative to an entity is defined as:
322+
323+
- If the entity is an *instantiated module* or an *instantiation-nested* entity, the *bottom-up instantiation-resolution* is the *instantiation-relative* entity of the *bottom-up instantiation-resolution* relative to the *underlying module*.
324+
- Otherwise, the *bottom-up instantiation-resolution* is the parameter itself.
325+
326+
An entity is called *fully instantiated* if none of the *bottom-up instantiation-resolutions* of the parameters in the *relevant set of parameters* of the entity's *underlying completely uninstantiated* entity are parameters.
327+
328+
Two *instantiated modules* or two *instantiation-nested* entities are considered *equivalent* if they have the same *underlying completely uninstantiated* entity and each parameter in its *relevant set of parameters* has the same *bottom-up instantiation-resolution* relative to either *instantiated module*.
329+
330+
Module instantiation is applicative, meaning that *equivalent* *instantiated modules* and *equivalent* *instantiation-nested* entities are indistinguishable.
331+
252332
Module references and active modules
253333
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
254334

@@ -268,7 +348,7 @@ QL is a typed language. This section specifies the kinds of types available, the
268348
Kinds of types
269349
~~~~~~~~~~~~~~
270350

271-
Types in QL are either *primitive* types, *database* types, *class* types, *character* types or *class domain* types.
351+
Types in QL are either *primitive* types, *database* types, *class* types, *character* types, *class domain* types, type *parameters*, or *instantiation-nested* types.
272352

273353
The primitive types are ``boolean``, ``date``, ``float``, ``int``, and ``string``.
274354

@@ -289,7 +369,9 @@ With the exception of class domain types and character types (which cannot be re
289369

290370
type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
291371

292-
moduleExpr ::= modulename arguments? | moduleExpr "::" modulename arguments?
372+
moduleExpr ::= moduleId arguments?
373+
374+
moduleId ::= modulename | moduleExpr "::" modulename
293375

294376
A type reference is resolved to a type as follows:
295377

@@ -1960,7 +2042,7 @@ Stratification
19602042

19612043
A QL program can be *stratified* to a sequence of *layers*. A layer is a set of predicates and types.
19622044

1963-
A valid stratification must include each predicate and type in the QL program. It must not include any other predicates or types.
2045+
A valid stratification must include each predicate and type in the QL program that is *fully instantiated*. It must not include any other predicates or types.
19642046

19652047
A valid stratification must not include the same predicate in multiple layers.
19662048

0 commit comments

Comments
 (0)