update links

This commit is contained in:
james
2020-08-17 21:08:33 +01:00
parent 1d4978aa6e
commit b150c6497f
12 changed files with 49 additions and 55 deletions

View File

@@ -6,7 +6,7 @@ QL is the powerful query language that underlies CodeQL, which is used to analyz
About query languages and databases
-----------------------------------
This section is aimed at users with a background in general purpose programming as well as in databases. For a basic introduction and information on how to get started, see `Learning CodeQL <https://help.semmle.com/QL/learn-ql/index.html>`__.
This section is aimed at users with a background in general purpose programming as well as in databases. For a basic introduction and information on how to get started, see "`Learning CodeQL <https://help.semmle.com/QL/learn-ql/index.html>`__."
QL is a declarative, object-oriented query language that is optimized to enable efficient analysis of hierarchical data structures, in particular, databases representing software artifacts.
@@ -39,10 +39,10 @@ When you write this process in QL, it closely resembles the above structure. Not
result = count(getADescendant(p))
}
For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as :doc:`Expressions <expressions>` and :doc:`Recursion <recursion>`.
For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as ":doc:`Expressions <expressions>`" and ":doc:`Recursion <recursion>`."
The explanations and examples help you understand how the language works, and how to write more advanced QL code.
For formal specifications of the QL language and QLDoc comments, see the :doc:`QL language specification <language>` and :doc:`QLDoc comment specification <qldoc>`.
For formal specifications of the QL language and QLDoc comments, see the ":doc:`QL language specification <language>`" and ":doc:`QLDoc comment specification <qldoc>`."
QL and object orientation
-------------------------

View File

@@ -53,7 +53,7 @@ You can also find a summary table in the Annotations section of the
The ``abstract`` annotation is used to define an abstract entity.
For information about **abstract classes**, see :ref:`Classes <abstract-classes>`.
For information about **abstract classes**, see ":ref:`Classes <abstract-classes>`."
**Abstract predicates** are member predicates that have no body. They can be defined on any
class, and should be :ref:`overridden <overriding-member-predicates>` in non-abstract subtypes.
@@ -359,7 +359,7 @@ Language pragmas
This annotation allows you to use **monotonic aggregates** instead of the standard QL
:ref:`aggregates <aggregations>`.
For more information, see :ref:`monotonic-aggregates`.
For more information, see ":ref:`monotonic-aggregates`."
.. _bindingset:
@@ -380,7 +380,7 @@ The ``bindingset`` annotation takes a comma-separated list of variables. Each va
an argument of the predicate, possibly including ``this`` (for characteristic predicates and
member predicates) and ``result`` (for predicates that return a result).
See :ref:`predicate-binding` in the :ref:`predicates` topic for examples and more information.
For more information, see ":ref:`predicate-binding`."
.. Links to use in substitutions

View File

@@ -26,14 +26,14 @@ Each evaluation starts from these sets of tuples.
The remaining predicates and types in the program are organized into a number of layers, based
on the dependencies between them.
These layers are evaluated to produce their own sets of tuples, by finding the least fixed point
of each predicate. (For example, see :ref:`recursion`.)
of each predicate. (For example, see ":ref:`recursion`.")
The program's :ref:`queries <query>` determine which of these sets of tuples make up the final
results of the program. The results are sorted according to any ordering directives
(``order by``) in the queries.
For more details about each step of the evaluation process, see the `QL language specification
<https://help.semmle.com/QL/ql-spec/language.html#evaluation>`_.
For more details about each step of the evaluation process, see the "`QL language specification
<https://help.semmle.com/QL/ql-spec/language.html#evaluation>`_."
Validity of programs
********************
@@ -97,7 +97,7 @@ To do this, you can use the following mechanisms:
.. important:: If a predicate uses non-standard binding sets, then it does **not** always bind
all its arguments. In such a case, whether the predicate call binds a specific argument
depends on which other arguments are bound, and what the binding sets say about the
argument in question. See :ref:`binding-sets` for more information.
argument in question. For more information, see ":ref:`binding-sets`."
#. **Binding operators**: Most operators, such as the :ref:`arithmetic operators <binary-operations>`,
require that all their operands are bound. For example, you can't add two variables in QL

View File

@@ -160,8 +160,7 @@ Calls to predicates (with result)
Calls to :ref:`predicates with results <predicates-with-result>` are themselves expressions,
unlike calls to :ref:`predicates without results <predicates-without-result>` which are
formulas. See :ref:`calls` in the :ref:`formulas` topic for more general information about
calls.
formulas. For more information, see ":ref:`calls`."
A call to a predicate with result evaluates to the values of the ``result`` variable of the
called predicate.
@@ -350,7 +349,7 @@ Let us apply these steps to the ``sum`` aggregate in the following query:
#. Apply the aggregation function ``sum`` on the above values to get the final result ``60``.
If we change ``<expression>`` to ``i + j`` in the above query, the query result is ``135`` since
applying ``i + j`` on all tuples results in following values: 
applying ``i + j`` on all tuples results in following values:
\ ``0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 9``.
Next, consider the following query:

View File

@@ -148,14 +148,13 @@ A call to a predicate can also contain a closure operator, namely ``*`` or ``+``
``a.isChildOf+(b)`` is a call to the :ref:`transitive closure <transitive-closures>` of
``isChildOf()``, so it holds if ``a`` is a descendent of ``b``.
The predicate reference must resolve to exactly one predicate. See :ref:`name-resolution` for
more information about how a predicate reference is resolved.
The predicate reference must resolve to exactly one predicate. For more information about how a predicate
reference is resolved, see ":ref:`name-resolution`."
If the call resolves to a predicate without result, then the call is a formula.
It is also possible to call a predicate with result. This kind of call is an
expression in QL, instead of a formula. See :ref:`calls-with-result` for the corresponding
topic.
expression in QL, instead of a formula. For more information, see ":ref:`calls-with-result`."
.. _parenthesized-formulas:
@@ -251,7 +250,7 @@ Implicit quantifiers
Implicitly quantified variables can be introduced using "don't care expressions." These are used
when you need to introduce a variable to use as an argument to a predicate call, but don't care
about its value. For further information, see :ref:`Don't-care expressions <dont-care>`.
about its value. For further information, see ":ref:`Don't-care expressions <dont-care>`."
.. _connectives:
@@ -305,7 +304,7 @@ The following query selects files that are not HTML files.
.. note::
You should be careful when using ``not`` in a recursive definition, as this could lead to
non-monotonic recursion. For more information, see the section on :ref:`non-monotonic-recursion`.
non-monotonic recursion. For more information, ":ref:`non-monotonic-recursion`."
.. index:: if, then, else
.. _conditional:

View File

@@ -34,11 +34,11 @@ In the syntax itself, juxtaposition indicates sequencing. The vertical bar (``|`
Architecture
------------
A *QL program* consists of a query module defined in a QL file and a number of library modules defined in QLL files that it imports (see `Import directives <#import-directives>`__). The module in the QL file includes one or more queries (see `Queries <#queries>`__). A module may also include *import directives* (see `Import directives <#import-directives>`__), non-member predicates (see `Non-member predicates <#non-member-predicates>`__), class definitions (see `Classes <#classes>`__), and module definitions (see `Modules <#modules>`__).
A *QL program* consists of a query module defined in a QL file and a number of library modules defined in QLL files that it imports (see "`Import directives <#import-directives>`__"). The module in the QL file includes one or more queries (see "`Queries <#queries>`__"). A module may also include *import directives* (see "`Import directives <#import-directives>`__"), non-member predicates (see "`Non-member predicates <#non-member-predicates>`__"), class definitions (see "`Classes <#classes>`__"), and module definitions (see "`Modules <#modules>`__").
QL programs are interpreted in the context of a *database* and a *library path* . The database provides a number of definitions: database types (see `Types <#types>`__), entities (see `Values <#values>`__), built-in predicates (see `Built-ins <#built-ins>`__), and the *database content* of built-in predicates and external predicates (see `Evaluation <#evaluation>`__). The library path is a sequence of file-system directories that hold QLL files.
QL programs are interpreted in the context of a *database* and a *library path* . The database provides a number of definitions: database types (see "`Types <#types>`__"), entities (see "`Values <#values>`__"), built-in predicates (see "`Built-ins <#built-ins>`__"), and the *database content* of built-in predicates and external predicates (see "`Evaluation <#evaluation>`__"). The library path is a sequence of file-system directories that hold QLL files.
A QL program can be *evaluated* (see `Evaluation <#evaluation>`__) to produce a set of tuples of values (see `Values <#values>`__).
A QL program can be *evaluated* (see "`Evaluation <#evaluation>`__") to produce a set of tuples of values (see "`Values <#values>`__").
For a QL program to be *valid*, it must conform to a variety of conditions that are described throughout this specification; otherwise the program is said to be *invalid*. An implementation of QL must detect all invalid programs and refuse to evaluate them.
@@ -46,7 +46,7 @@ Library path
------------
The library path is an ordered list of directory locations. It is used
for resolving module imports (see `Module resolution <#module-resolution>`__). The library path is not strictly
for resolving module imports (see "`Module resolution <#module-resolution>`__"). The library path is not strictly
speaking a core part of the QL language, since different
implementations of QL construct it in slightly different ways. Most QL
tools also allow you to explicitly specify the library path on the command line for a
@@ -150,7 +150,7 @@ Module environments
For each of modules, types, and predicates, a module *imports*, *declares*, and *exports* an environment. These are defined as follows (with X denoting the type of entity we are currently considering):
- The *imported X environment* of a module is defined to be the union of the exported X environments of all the modules which the current module directly imports (see `Import directives <#import-directives>`__).
- The *imported X environment* of a module is defined to be the union of the exported X environments of all the modules which the current module directly imports (see "`Import directives <#import-directives>`__").
- The *declared X environment* of a module is the multimap of X declarations in the module itself.
@@ -232,10 +232,7 @@ For selection identifiers (``a::b``):
For qualified identifiers (``a.b``):
- Build up a list of *candidate search paths*, consisting of the
current file's directory, then the *query directory* of the current
file, and finally each of the directories on the
`library path <#library-path>`__ (in order).
- Build up a list of *candidate search paths*, consisting of the current file's directory, then the *query directory* of the current file, and finally each of the directories on the `library path <#library-path>`__ (in order).
- Determine the first candidate search path that has a *matching* QLL file for the import directive's qualified name. A QLL file in a candidate search path is said to match a qualified name if, starting from the candidate search path, there is a subdirectory for each successive qualifier in the qualified name, and the directory named by the final qualifier contains a file whose base name matches the qualified name's base name, with the addition of the file extension ``.qll``. The file and directory names are matched case-sensitively, regardless of whether the filesystem is case-sensitive or not.
@@ -268,7 +265,7 @@ The primitive types are ``boolean``, ``date``, ``float``, ``int``, and ``string`
Database types are supplied as part of the database. Each database type has a *name*, which is an identifier starting with an at sign (``@``, U+0040) followed by lower-case letter. Database types have some number of *base types*, which are other database types. In a valid database, the base types relation is non-cyclic.
Class types are defined in QL, in a way specified later in this document (see `Classes <#classes>`__). Each class type has a name that is an identifier starting with an upper-case letter. Each class type has one or more base types, which can be any kind of type except a class domain type. A class type may be declared *abstract*.
Class types are defined in QL, in a way specified later in this document (see "`Classes <#classes>`__"). Each class type has a name that is an identifier starting with an upper-case letter. Each class type has one or more base types, which can be any kind of type except a class domain type. A class type may be declared *abstract*.
Any class in QL has an associated class domain type and an associated character type.
@@ -287,7 +284,7 @@ With the exception of class domain types and character types (which cannot be re
A type reference is resolved to a type as follows:
- If it is a selection identifier (for example, ``a::B``), then the qualifier (``a``) is resolved as a module (see `Module resolution <#module-resolution>`__). The identifier (``B``) is then resolved in the exported type environment of the qualifier module.
- If it is a selection identifier (for example, ``a::B``), then the qualifier (``a``) is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier (``B``) is then resolved in the exported type environment of the qualifier module.
- Otherwise, the identifier is resolved in the current module's visible type environment.
@@ -383,7 +380,7 @@ A *variable declaration list* provides a sequence of variables and a type for ea
A valid variable declaration list must not include two declarations with the same variable name. Moreover, if the declaration has a typing environment that applies, it must not use a variable name that is already present in that typing environment.
An *extension* of a named tuple for a given variable declaration list is a named tuple that additionally maps each variable in the list to a value. The value mapped by each new variable must be in the type that is associated with that variable in the given list; see `The store <#the-store>`__ for the definition of a value being in a type.
An *extension* of a named tuple for a given variable declaration list is a named tuple that additionally maps each variable in the list to a value. The value mapped by each new variable must be in the type that is associated with that variable in the given list; see "`The store <#the-store>`__" for the definition of a value being in a type.
The store
---------
@@ -410,7 +407,7 @@ A value ``v`` is in a type ``t`` under any of the following conditions:
An ordered tuple *satisfies a predicate* ``p`` under the following circumstances. If ``p`` is not a member predicate, then the tuple satisfies the predicate whenever it directly satisfies the predicate.
Otherwise, the tuple must be the tuple of a fact in the store with predicate ``q``, where ``q`` shares a root definition with ``p``. The first element of the tuple must be in the type before the dot in ``q``, and there must be no other predicate that overrides ``q`` such that this is true (see `Classes <#classes>`__ for details on overriding and root definitions).
Otherwise, the tuple must be the tuple of a fact in the store with predicate ``q``, where ``q`` shares a root definition with ``p``. The first element of the tuple must be in the type before the dot in ``q``, and there must be no other predicate that overrides ``q`` such that this is true (see "`Classes <#classes>`__" for details on overriding and root definitions).
An ordered tuple ``(a0, an)`` satisfies the ``+`` closure of a predicate if there is a sequence of binary tuples ``(a0, a1)``, ``(a1, a2)``, ..., ``(an-1, an)`` that all satisfy the predicate. An ordered tuple ``(a, b)`` satisfies the ``*`` closure of a predicate if it either satisfies the ``+`` closure, or if ``a`` and ``b`` are the same, and if moreover they are in each argument type of the predicate.
@@ -419,7 +416,7 @@ Lexical syntax
QL and QLL files contain a sequence of *tokens* that are encoded as Unicode text. This section describes the tokenization algorithm, the kinds of available tokens, and their representation in Unicode.
Some kinds of tokens have an identifier given in parentheses in the section title. That identifier, if present, is a terminal used in grammar productions later in the specification. Additionally, the `Identifiers <#identifiers>`__ section gives several kinds of identifiers, each of which has its own grammar terminal.
Some kinds of tokens have an identifier given in parentheses in the section title. That identifier, if present, is a terminal used in grammar productions later in the specification. Additionally, the "`Identifiers <#identifiers>`__" section gives several kinds of identifiers, each of which has its own grammar terminal.
Tokenization
~~~~~~~~~~~~
@@ -719,7 +716,7 @@ The parameterized annotation ``language`` supplies language pragmas which change
A binding set for a predicate is a subset of the predicates arguments such that if those arguments are bound (restricted to a finite range of values), then all of the predicates arguments are bound.
The parameterized annotation ``bindingset`` can be applied to a predicate (see `Non-member predicates <#non-member-predicates>`__ and `Members <#members>`__) to specify a binding set.
The parameterized annotation ``bindingset`` can be applied to a predicate (see "`Non-member predicates <#non-member-predicates>`__" and "`Members <#members>`__") to specify a binding set.
This annotation accepts a (possibly empty) list of variable names as parameters. The named variables must all be arguments of the predicate, possibly including ``this`` for characteristic predicates and member predicates, and ``result`` for predicates that yield a result.
@@ -754,7 +751,7 @@ A *predicate* is declared as a sequence of annotations, a head, and an optional
A predicate definition adds a mapping from the predicate name and arity to the predicate declaration to the current module's declared predicate environment.
When a predicate is a top-level clause in a module, it is called a non-member predicate. See below for `member predicates <#member-predicates>`__.
When a predicate is a top-level clause in a module, it is called a non-member predicate. See below for "`Member predicates <#member-predicates>`__."
A valid non-member predicate can be annotated with ``cached``, ``deprecated``, ``external``, ``transient``, ``private``, and ``query``. Note, the ``transient`` annotation can only be applied if the non-member predicate is also annotated with ``external``.
@@ -772,7 +769,7 @@ The body of a predicate is of one of three forms:
| "{" formula "}"
| "=" literalId "(" (predicateRef "/" int ("," predicateRef "/" int)*)? ")" "(" (exprs)? ")"
In the first form, with just a semicolon, the predicate is said to not have a body. In the second form, the body of the predicate is the given formula (see `Formulas <#formulas>`__). In the third form, the body is a higher-order relation.
In the first form, with just a semicolon, the predicate is said to not have a body. In the second form, the body of the predicate is the given formula (see "`Formulas <#formulas>`__"). In the third form, the body is a higher-order relation.
A valid non-member predicate must have a body, either a formula or a higher-order relation, unless it is external, in which case it must not have a body.
@@ -903,7 +900,7 @@ The ``order`` keyword, if present, is followed by a number of *ordering directiv
Each identifier in an ordering directive must identify exactly one of the select expressions. It must either be the label of the expression, or it must be a variable expression that is equivalent to exactly one of the select expressions. The type of the designated select expression must be a subtype of a primitive type.
No select expression may be specified by more than one ordering directive. See `Ordering <#ordering>`__ for more information.
No select expression may be specified by more than one ordering directive. See "`Ordering <#ordering>`__" for more information.
Queries
~~~~~~~
@@ -1011,7 +1008,7 @@ The typing environment for the two environments is the same as for the operation
The type of the operation is ``string`` if either operand is a subtype of ``string``. Otherwise, the type of the operation is ``int`` if both operands are subtypes of ``int``. Otherwise, the type of the operation is ``float``.
If the result is of type ``string``, then the *left values* of the operation are the values of a "call with results" expression with the left operand as the receiver, ``toString`` as the predicate name, and no arguments (see `Calls with results <#calls-with-results>`__). Otherwise the left values are the values of the left operand. Likewise, the *right values* are either the values from calling ``toString`` on the right operand, or the values of the right operand as it is.
If the result is of type ``string``, then the *left values* of the operation are the values of a "call with results" expression with the left operand as the receiver, ``toString`` as the predicate name, and no arguments (see "`Calls with results <#calls-with-results>`__"). Otherwise the left values are the values of the left operand. Likewise, the *right values* are either the values from calling ``toString`` on the right operand, or the values of the right operand as it is.
The binary operation has one value for each combination of a left value and a right value. That value is determined as follows:
@@ -1098,7 +1095,7 @@ A valid call with results must *resolve* to exactly one predicate. The ways a ca
- If the call has no receiver, then it can resolve to a non-member predicate. If the predicate name is a simple identifier, then the predicate is resolved by looking up its name and arity in the visible predicate environment of the enclosing class or module.
If the predicate name is a selection identifier, then the qualifier is resolved as a module (see `Module resolution <#module-resolution>`__). The identifier is then resolved in the exported predicate environment of the qualifier module.
If the predicate name is a selection identifier, then the qualifier is resolved as a module (see "`Module resolution <#module-resolution>`__"). The identifier is then resolved in the exported predicate environment of the qualifier module.
- If the call has a super expression as the receiver, then it resolves to a member predicate in a class the enclosing class inherits from. If the super expression is unqualified, then the super-class is the single class that the current class inherits from. If there is not exactly one such class, then the program is invalid. Otherwise the super-class is the class named by the qualifier of the super expression. The predicate is resolved by looking up its name and arity in the exported predicate environment of the super-class. If there is more than one such predicate, then the predicate call is not valid.
@@ -1182,7 +1179,7 @@ The type of a ``count``, ``strictcount`` aggregation is ``int``. The type of an
An ordering directive may only be specified for a ``max``, ``min``, ``rank``, ``concat`` or ``strictconcat`` aggregation. The type of the expression in an ordering directive must be an orderable type.
The values of the aggregation expression are determined as follows. Firstly, the *range tuples* are extensions of the named tuple that the aggregation is being evaluated in with the variable declarations of the aggregation, and which *match* the formula (see `Formulas <#formulas>`__).
The values of the aggregation expression are determined as follows. Firstly, the *range tuples* are extensions of the named tuple that the aggregation is being evaluated in with the variable declarations of the aggregation, and which *match* the formula (see "`Formulas <#formulas>`__").
For each range tuple, the *aggregation tuples* are the extension of the range tuples to *aggregation variables* and *sort variables*.
@@ -1398,7 +1395,7 @@ A comparison formula is two expressions separated by a comparison operator:
comparison ::= expr compop expr
compop ::= "=" | "!=" | "<" | ">" | "<=" | ">="
A comparison formula matches if there is one value of the left expression that is in the given ordering with one of the values of the right expression. The ordering used is specified in `Ordering <#ordering>`__. If one of the values is an integer and the other is a float value, then the integer is converted to a float value before the comparison.
A comparison formula matches if there is one value of the left expression that is in the given ordering with one of the values of the right expression. The ordering used is specified in "`Ordering <#ordering>`__." If one of the values is an integer and the other is a float value, then the integer is converted to a float value before the comparison.
If the operator is ``=``, then at least one of the left and right expressions must have a type; if they both have a type, those types must be compatible.
@@ -1444,7 +1441,7 @@ A call has the following syntax:
The identifier is called the *predicate name* of the call.
A call must resolve to a predicate, using the same definition of resolve as for calls with results (see `Calls with results <#calls-with-results>`__).
A call must resolve to a predicate, using the same definition of resolve as for calls with results (see "`Calls with results <#calls-with-results>`__").
The resolved predicate must not have a result type.

View File

@@ -29,10 +29,9 @@ The name of a module can be any `identifier <https://help.semmle.com/QL/ql-spec/
that starts with an uppercase or lowercase letter.
``.ql`` or ``.qll`` files also implicitly define modules.
Read more about the different :ref:`kinds of modules <kinds-of-modules>` below.
For more information, see ":ref:`kinds-of-modules`."
You can also annotate a module. See the list of :ref:`annotations <annotations-overview>`
available for modules.
You can also annotate a module. For more information, see of ":ref:`annotations-overview`."
Note that you can only annotate :ref:`explicit modules <explicit-modules>`.
File modules cannot be annotated.
@@ -177,7 +176,7 @@ You can import a module under a different name using the ``as`` keyword,
for example ``import javascript as js``.
The ``<module_expression>`` itself can be a module name, a selection, or a qualified
reference. See :ref:`name-resolution` for more details.
reference. For more information, see ":ref:`name-resolution`."
For information about how import statements are looked up, see `Module resolution <https://help.semmle.com/QL/ql-spec/language.html#module-resolution>`__
For information about how import statements are looked up, see "`Module resolution <https://help.semmle.com/QL/ql-spec/language.html#module-resolution>`__"
in the QL language specification.

View File

@@ -74,7 +74,7 @@ statement as follows:
#. If the compiler can't find the library file using the above two checks, it looks up ``examples/security/MyLibrary.qll``
relative to each library path entry.
The library path is usually specified using the ``libraryPathDependencies`` of the ``qlpack.yml`` file, though it may also depend on the tools you use to run your query, and whether you have specified any extra settings.
For more information, see `Library path <https://help.semmle.com/QL/ql-spec/language.html#library-path>`__ in the QL language specification.
For more information, see "`Library path <https://help.semmle.com/QL/ql-spec/language.html#library-path>`__" in the QL language specification.
If the compiler cannot resolve an import statement, then it gives a compilation error.

View File

@@ -161,7 +161,7 @@ Non-member predicates are defined outside a class, that is, they are not members
For more information about the other kinds of predicates, see :ref:`characteristic predicates
<characteristic-predicates>` and :ref:`member predicates <member-predicates>` in the
:ref:`Classes <classes>` topic.
":ref:`Classes <classes>`" topic.
Here is an example showing a predicate of each kind::
@@ -198,7 +198,7 @@ It must be possible to evaluate a predicate in a finite amount of time, so the s
is not usually allowed to be infinite. In other words, a predicate can only contain a finite number of tuples.
The QL compiler reports an error when it can prove that a predicate contains variables that
aren't constrained to a finite number of values. See :ref:`binding` for more information.
aren't constrained to a finite number of values. For more information, see ":ref:`binding`."
Here are a few examples of infinite predicates::

View File

@@ -16,7 +16,7 @@ point and hence the result of the evaluation.
Similarly, the result of a QL query is the least fixed point of the predicates referenced in
the query.
In certain cases, you can also use aggregates recursively. For more information, see :ref:`monotonic-aggregates`.
In certain cases, you can also use aggregates recursively. For more information, see ":ref:`monotonic-aggregates`."
Examples of recursive predicates
********************************

View File

@@ -107,12 +107,12 @@ values of a class are contained within the intersection of the base types (that
the :ref:`class domain type <domain-types>`). A class inherits all member predicates from its
base types.
A class can extend multiple types. See :ref:`multiple-inheritance` below.
A class can extend multiple types. For more information, see ":ref:`multiple-inheritance`."
To be valid, a class:
- Must not extend itself.
- Must not extend a :ref:`final` class.
- Must not extend types that are incompatible. (See :ref:`type-compatibility`.)
- Must not extend types that are incompatible. For more information, see ":ref:`type-compatibility`."
You can also annotate a class. See the list of :ref:`annotations <annotations-overview>`
available for classes.

View File

@@ -50,7 +50,7 @@ As an aside, note that the following query leads to a compile-time error::
select i
In theory, it would have infinitely many results, as the variable ``i`` is not constrained to a
finite number of possible values. See :ref:`binding` for more information.
finite number of possible values. For more informaion, see ":ref:`binding`."
.. index:: variable; free, variable; bound
.. _free-variables:
@@ -116,7 +116,7 @@ a non-negative number, then the final formula holds. On the other hand, if ``x``
``-9`` for example, then the formula doesn't hold. The variable ``y`` doesn't affect whether
the formula holds or not.
For more information about how assignments to free variables are computed, see :ref:`evaluation`.
For more information about how assignments to free variables are computed, see ":ref:`evaluation`."
.. rubric:: Footnotes