ql language ref: change code blocks

This commit is contained in:
james
2020-11-11 10:51:48 +00:00
parent 28c7c42e34
commit bab6d04139
14 changed files with 265 additions and 127 deletions

View File

@@ -35,7 +35,9 @@ Use the following syntax to define an alias for a :ref:`module <modules>`::
module ModAlias = ModuleName;
For example, if you create a new module ``NewVersion`` that is an updated version
of ``OldVersion``, you could deprecate the name ``OldVersion`` as follows::
of ``OldVersion``, you could deprecate the name ``OldVersion`` as follows:
.. code-block:: ql
deprecated module OldVersion = NewVersion;
@@ -59,7 +61,9 @@ For example, you can use an alias to abbreviate the name of the primitive type `
class bool = boolean;
Or, to use a class ``OneTwo`` defined in a :ref:`module <explicit-modules>` ``M`` in
``OneTwoThreeLib.qll``, you could create an alias to use the shorter name ``OT`` instead::
``OneTwoThreeLib.qll``, you could create an alias to use the shorter name ``OT`` instead:
.. code-block:: ql
import OneTwoThreeLib
@@ -92,12 +96,16 @@ You can use an alias to abbreviate the name to ``succ``::
predicate succ = getSuccessor/1;
As an example of a predicate without result, suppose you have a predicate that holds
for any positive integer less than ten::
for any positive integer less than ten:
.. code-block:: ql
predicate isSmall(int i) {
i in [1 .. 9]
}
You could give the predicate a more descriptive name as follows::
You could give the predicate a more descriptive name as follows:
.. code-block:: ql
predicate lessThanTen = isSmall/1;

View File

@@ -5,7 +5,9 @@ Annotations
An annotation is a string that you can place directly before the declaration of a QL entity or name.
For example, to declare a module ``M`` as private, you could use::
For example, to declare a module ``M`` as private, you could use:
.. code-block:: ql
private module M {
...
@@ -20,7 +22,9 @@ For example, if you annotate an entity with ``private``, then only that particul
private. You could still access that entity under a different name (using an :ref:`alias <aliases>`).
On the other hand, if you annotate an entity with ``cached``, then the entity itself is cached.
Here is an explicit example::
Here is an explicit example:
.. code-block:: ql
module M {
private int foo() { result = 1 }
@@ -61,7 +65,9 @@ class, and should be :ref:`overridden <overriding-member-predicates>` in non-abs
Here is an example that uses abstract predicates. A common pattern when writing data flow
analysis in QL is to define a configuration class. Such a configuration must describe, among
other things, the sources of data that it tracks. A supertype of all such configurations might
look like this::
look like this:
.. code-block:: ql
abstract class Configuration extends string {
...
@@ -125,7 +131,9 @@ alternatives.
Typically, deprecated names have a QLDoc comment that tells users which updated element they
should use instead.
For example, the name ``DataFlowNode`` is deprecated and has the following QLDoc comment::
For example, the name ``DataFlowNode`` is deprecated and has the following QLDoc comment:
.. code-block:: ql
/**
* DEPRECATED: Use `DataFlow::Node` instead.
@@ -177,7 +185,9 @@ This is useful if you don't want subclasses to change the meaning of a particula
For example, the predicate ``hasName(string name)`` holds if an element has the name ``name``.
It uses the predicate ``getName()`` to check this, and it wouldn't make sense for a subclass to
change this definition. In this case, ``hasName`` should be final::
change this definition. In this case, ``hasName`` should be final:
.. code-block:: ql
class Element ... {
string getName() { result = ... }

View File

@@ -163,7 +163,9 @@ being "bound" or "unbound" is a global concept—a single binding occurrence is
variable bound.
Therefore, you could fix the "infinite" examples above by providing a binding occurrence. For
example, instead of ``int timesTwo(int n) { result = n * 2 }``, you could write::
example, instead of ``int timesTwo(int n) { result = n * 2 }``, you could write:
.. code-block:: ql
int timesTwo(int n) {
n in [0 .. 10] and

View File

@@ -33,7 +33,9 @@ You can express certain values directly in QL, such as numbers, booleans, and st
- :ref:`Integer <int>` literals: These are sequences of decimal digits (``0`` through ``9``),
possibly starting with a minus sign (``-``).
For example::
For example:
.. code-block:: ql
0
42
@@ -50,7 +52,9 @@ You can express certain values directly in QL, such as numbers, booleans, and st
- :ref:`String <string>` literals: These are finite strings of 16-bit characters. You can
define a string literal by enclosing characters in quotation marks (``"..."``). Most
characters represent themselves, but there are a few characters that you need to "escape"
with a backslash. The following are examples of string literals::
with a backslash. The following are examples of string literals:
.. code-block:: ql
"hello"
"They said, \"Please escape quotation marks!\""
@@ -177,7 +181,9 @@ Aggregations
An aggregation is a mapping that computes a result value from a set of input values that are
specified by a formula.
The general syntax is::
The general syntax is:
.. code-block:: ql
<aggregate>(<variable declarations> | <formula> | <expression>)
@@ -203,7 +209,9 @@ The following aggregates are available in QL:
each possible assignment of the aggregation variables.
For example, the following aggregation returns the number of files that have more than
``500`` lines::
``500`` lines:
.. code-block:: ql
count(File f | f.getTotalNumberOfLines() > 500 | f)
@@ -217,7 +225,9 @@ The following aggregates are available in QL:
In this case, ``<expression>`` must be of numeric type or of type ``string``.
For example, the following aggregation returns the name of the ``.js`` file (or files) with the
largest number of lines::
largest number of lines:
.. code-block:: ql
max(File f | f.getExtension() = "js" | f.getBaseName() order by f.getTotalNumberOfLines())
@@ -260,7 +270,9 @@ The following aggregates are available in QL:
the formula, then ``concat`` defaults to the empty string.
For example, the following aggregation returns the string ``"3210"``, that is, the
concatenation of the strings ``"0"``, ``"1"``, ``"2"``, and ``"3"`` in descending order::
concatenation of the strings ``"0"``, ``"1"``, ``"2"``, and ``"3"`` in descending order:
.. code-block:: ql
concat(int i | i = [0 .. 3] | i.toString() order by i desc)
@@ -378,7 +390,9 @@ aggregation in a simpler form:
#. If you want to write an aggregation of the form ``<aggregate>(<type> v | <expression> = v | v)``,
then you can omit the ``<variable declarations>`` and ``<formula>`` parts and write it
as follows::
as follows:
.. code-block:: ql
<aggregate>(<expression>)
@@ -403,17 +417,23 @@ aggregation in a simpler form:
count(int i, int j | i in [1 .. 3] and j in [1 .. 3] | 1)
count(int i, int j | i in [1 .. 3] and j in [1 .. 3])
#. You can omit the ``<formula>`` part, but in that case you should include two vertical bars::
#. You can omit the ``<formula>`` part, but in that case you should include two vertical bars:
.. code-block:: ql
<aggregate>(<variable declarations> | | <expression>)
This is useful if you don't want to restrict the aggregation variables any further.
For example, the following aggregation returns the maximum number of lines across all files::
For example, the following aggregation returns the maximum number of lines across all files:
.. code-block:: ql
max(File f | | f.getTotalNumberOfLines())
#. Finally, you can also omit both the ``<formula>`` and ``<expression>`` parts. For example,
the following aggregations are equivalent ways to count the number of files in a database::
the following aggregations are equivalent ways to count the number of files in a database:
.. code-block:: ql
count(File f | any() | 1)
count(File f | | 1)
@@ -498,7 +518,9 @@ Any
***
The general syntax of an ``any`` expression is similar to the syntax of an
:ref:`aggregation <aggregations>`, namely::
:ref:`aggregation <aggregations>`, namely:
.. code-block:: ql
any(<variable declarations> | <formula> | <expression>)
@@ -536,7 +558,9 @@ Unary operations
****************
A unary operation is a minus sign (``-``) or a plus sign (``+``) followed by an expression of type
``int`` or ``float``. For example::
``int`` or ``float``. For example:
.. code-block:: ql
-6.28
+(10 - 4)
@@ -552,7 +576,9 @@ Binary operations
*****************
A binary operation consists of an expression, followed by a binary operator, followed by
another expression. For example::
another expression. For example:
.. code-block:: ql
5 % 2
(9 + 1) / (-2)
@@ -621,7 +647,9 @@ Since the predicate ``getASupertype()`` is defined for ``Class``, but not for ``
can't call ``t.getASupertype()`` directly. The cast ``t.(Class)`` ensures that ``t`` is
of type ``Class``, so it has access to the desired predicate.
If you prefer to use a prefix cast, you can rewrite the ``where`` part as::
If you prefer to use a prefix cast, you can rewrite the ``where`` part as:
.. code-block:: ql
where ((Class)t).getASupertype().hasName("List")

View File

@@ -22,7 +22,9 @@ The following sections describe the kinds of formulas that are available in QL.
Comparisons
***********
A comparison formula is of the form::
A comparison formula is of the form:
.. code-block:: ql
<expression> <operator> <expression>
@@ -109,7 +111,9 @@ As a consequence, ``A != B`` has a very different meaning to the :ref:`negation
Type checks
***********
A type check is a formula that looks like::
A type check is a formula that looks like:
.. code-block:: ql
<expression> instanceof <type>
@@ -121,7 +125,9 @@ example, ``x instanceof Person`` holds if the variable ``x`` has type ``Person``
Range checks
************
A range check is a formula that looks like::
A range check is a formula that looks like:
.. code-block:: ql
<expression> in <range>
@@ -186,7 +192,9 @@ mathematical logic.
``exists``
----------
This quantifier has the following syntax::
This quantifier has the following syntax:
.. code-block:: ql
exists(<variable declarations> | <formula>)
@@ -204,7 +212,9 @@ type ``int`` and holds if any value of that variable has type ``OneTwoThree``.
``forall``
----------
This quantifier has the following syntax::
This quantifier has the following syntax:
.. code-block:: ql
forall(<variable declarations> | <formula 1> | <formula 2>)
@@ -224,11 +234,15 @@ logically the same as ``not exists(<vars> | <formula 1> | not <formula 2>)``.
``forex``
---------
This quantifier has the following syntax::
This quantifier has the following syntax:
.. code-block:: ql
forex(<variable declarations> | <formula 1> | <formula 2>)
This quantifier exists as a shorthand for::
This quantifier exists as a shorthand for:
.. code-block:: ql
forall(<vars> | <formula 1> | <formula 2>) and
exists(<vars> | <formula 1> | <formula 2>)
@@ -296,7 +310,7 @@ You can use the keyword ``not`` before a formula. The resulting formula is calle
The following query selects files that are not HTML files.
::
.. code-block:: ql
from File f
where not f.getFileType().isHtml()
@@ -318,7 +332,9 @@ notation: ``if A then B else C`` is the same as writing ``(A and B) or ((not A)
**Example**
With the following definition, ``visibility(c)`` returns ``"public"`` if ``x`` is
a public class and returns ``"private"`` otherwise::
a public class and returns ``"private"`` otherwise:
.. code-block:: ql
string visibility(Class c){
if c.isPublic()
@@ -340,7 +356,9 @@ conjunction.
**Example**
The following query selects files that have the ``js`` extension and contain fewer
than 200 lines of code::
than 200 lines of code:
.. code-block:: ql
from File f
where f.getExtension() = "js" and
@@ -383,7 +401,7 @@ implication. This is just a simplified notation: ``A implies B`` is the same as
The following query selects any ``SmallInt`` that is odd, or a multiple of ``4``.
::
.. code-block:: ql
class SmallInt extends int {
SmallInt() { this = [1 .. 10] }
@@ -396,11 +414,15 @@ The following query selects any ``SmallInt`` that is odd, or a multiple of ``4``
.. rubric:: Footnotes
.. [#] The difference between ``A != B`` and ``not A = B`` is due to the underlying quantifiers.
If you think of ``A`` and ``B`` as sets of values, then ``A != B`` means::
If you think of ``A`` and ``B`` as sets of values, then ``A != B`` means:
.. code-block:: ql
exists( a, b | a in A and b in B | a != b )
On the other hand, ``not A = B`` means::
On the other hand, ``not A = B`` means:
.. code-block:: ql
not exists( a, b | a in A and b in B | a = b )

View File

@@ -21,7 +21,9 @@ You can also write another kind of comment, namely **QLDoc comments**. These com
QL entities and are displayed as pop-up information in QL editors. For information about QLDoc
comments, see the ":doc:`QLDoc comment specification <qldoc-comment-specification>`."
The following example uses these three different kinds of comments::
The following example uses these three different kinds of comments:
.. code-block:: ql
/**
* A QLDoc comment that describes the class `Digit`.

View File

@@ -60,7 +60,7 @@ For example, consider the following QL library:
**OneTwoThreeLib.qll**
::
.. code-block:: ql
class OneTwoThree extends int {
OneTwoThree() {
@@ -90,7 +90,7 @@ For example:
**OneTwoQuery.ql**
::
.. code-block:: ql
import OneTwoThreeLib
@@ -162,7 +162,9 @@ into the :ref:`namespace <namespaces>` of the current module.
Import statements
=================
Import statements are used for importing modules. They are of the form::
Import statements are used for importing modules. They are of the form:
.. code-block:: ql
import <module_expression1> as <name>
import <module_expression2>

View File

@@ -38,7 +38,9 @@ in the :ref:`namespaces <namespaces>` of the current module.
In an :ref:`import statement <import-statements>`, name resolution is slightly more complicated.
For example, suppose you define a :ref:`query module <query-modules>` ``Example.ql`` with the
following import statement::
following import statement:
.. code-block:: ql
import javascript
@@ -57,7 +59,9 @@ only use such an expression in :ref:`import statements <import-statements>`, to
library module defined by a relative path.
For example, suppose you define a :ref:`query module <query-modules>` ``Example.ql`` with the
following import statement::
following import statement:
.. code-block:: ql
import examples.security.MyLibrary
@@ -84,7 +88,9 @@ Selections
**********
You can use a selection to refer to a module, type, or predicate inside a particular
module. A selection is of the form::
module. A selection is of the form:
.. code-block:: ql
<module_expression>::<name>
@@ -200,7 +206,7 @@ This is easiest to understand in an example:
**OneTwoThreeLib.qll**
::
.. code-block:: ql
import MyFavoriteNumbers

View File

@@ -65,7 +65,9 @@ Predicates without result
These predicate definitions start with the keyword ``predicate``. If a value satisfies the
logical property in the body, then the predicate holds for that value.
For example::
For example:
.. code-block:: ql
predicate isSmall(int i) {
i in [1 .. 9]
@@ -84,7 +86,9 @@ Predicates with result
You can define a predicate with result by replacing the keyword ``predicate`` with the type
of the result. This introduces the special variable ``result``.
For example::
For example:
.. code-block:: ql
int getSuccessor(int i) {
result = i + 1 and
@@ -97,7 +101,9 @@ is the successor of ``i``.
Note that you can use ``result`` in the same way as any other argument to the predicate.
You can express the relation between ``result`` and other variables in any way you like.
For example, given a predicate ``getAParentOf(Person x)`` that returns parents of ``x``, you can
define a "reverse" predicate as follows::
define a "reverse" predicate as follows:
.. code-block:: ql
Person getAChildOf(Person p) {
p = getAParentOf(result)
@@ -105,7 +111,9 @@ define a "reverse" predicate as follows::
It is also possible for a predicate to have multiple results (or none at all) for each value
of its arguments. For example::
of its arguments. For example:
.. code-block:: ql
string getANeighbor(string country) {
country = "France" and result = "Belgium"
@@ -164,7 +172,9 @@ For more information about the other kinds of predicates, see :ref:`characterist
<characteristic-predicates>` and :ref:`member predicates <member-predicates>` in the
":ref:`Classes <classes>`" topic.
Here is an example showing a predicate of each kind::
Here is an example showing a predicate of each kind:
.. code-block:: ql
int getSuccessor(int i) { // 1. Non-member predicate
result = i + 1 and
@@ -201,7 +211,9 @@ is not usually allowed to be infinite. In other words, a predicate can only cont
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. For more information, see ":ref:`binding`."
Here are a few examples of infinite predicates::
Here are a few examples of infinite predicates:
.. code-block:: ql
/*
Compilation errors:
@@ -239,7 +251,9 @@ use it on a restricted set of arguments. In that case, you can specify an explic
set using the ``bindingset`` :ref:`annotation <bindingset>`. This annotation is valid for any
kind of predicate.
For example::
For example:
.. code-block:: ql
bindingset[i]
int multiplyBy4(int i) {
@@ -256,7 +270,9 @@ finite provided that ``i`` is bound to a finite number of values. Then it uses t
a context where ``i`` is restricted to to the range ``[1 .. 10]``.
It is also possible to state multiple binding sets for a predicate. This can be done by adding
multiple binding set annotations, for example::
multiple binding set annotations, for example:
.. code-block:: ql
bindingset[x] bindingset[y]
predicate plusOne(int x, int y) {
@@ -276,7 +292,9 @@ be bound, is different from ``bindingset[x, y]``, which states that both ``x`` a
bound.
The latter can be useful when you want to declare a :ref:`predicate with result <predicates-with-result>` that takes multiple input arguments.
For example, the following predicate takes a string ``str`` and truncates it to a maximum length of ``len`` characters::
For example, the following predicate takes a string ``str`` and truncates it to a maximum length of ``len`` characters:
.. code-block:: ql
bindingset[str, len]
string truncate(string str, int len) {
@@ -285,7 +303,9 @@ For example, the following predicate takes a string ``str`` and truncates it to
else result = str
}
You can then use this in a :ref:`select clause <select-clauses>`, for example::
You can then use this in a :ref:`select clause <select-clauses>`, for example:
.. code-block:: ql
select truncate("hello world", 5)

View File

@@ -172,7 +172,7 @@ Module definitions
A QL module definition has the following syntax:
::
.. code-block:: ql
module ::= annotation* "module" modulename "{" moduleBody "}"
@@ -182,7 +182,7 @@ A module definition extends the current module's declared module environment wit
QL files consist of simply a module body without a name and surrounding braces:
::
.. code-block:: ql
ql ::= moduleBody
@@ -204,7 +204,7 @@ Import directives
An import directive refers to a module identifier:
::
.. code-block:: ql
import ::= annotations "import" importModuleId ("as" modulename)?
@@ -276,7 +276,7 @@ Type references
With the exception of class domain types and character types (which cannot be referenced explicitly in QL source), a reference to a type is written as the name of the type. In the case of database types, the name includes the at sign (``@``, U+0040).
::
.. code-block:: ql
type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
@@ -373,7 +373,7 @@ A *named tuple* is a finite map of variables to values. Each variable in a named
A *variable declaration list* provides a sequence of variables and a type for each one:
::
.. code-block:: ql
var_decls ::= var_decl ("," var_decl)*
var_decl ::= type simpleId
@@ -389,7 +389,7 @@ QL programs evaluate in the context of a *store*. This section specifies several
A *fact* is a predicate or type along with an ordered tuple. A fact is written as the predicate name or type name followed immediately by the tuple. Here are some examples of facts:
::
.. code-block:: ql
successor(0, 1)
Tree.toString(@method_tree(12), "def println")
@@ -439,13 +439,13 @@ There are two kinds of comments in QL: one-line and multiline.
A one-line comment is two slash characters (``/``, U+002F) followed by any sequence of characters other than line feeds (U+000A) and carriage returns (U+000D). Here is an example of a one-line comment:
::
.. code-block:: ql
// This is a comment
A multiline comment is a *comment start*, followed by a *comment body*, followed by a *comment end*. A comment start is a slash (``/``, U+002F) followed by an asterisk (``*``, U+002A), and a comment end is an asterisk followed by a slash. A comment body is any sequence of characters that does not include a comment end. Here is an example multiline comment:
::
.. code-block:: ql
/*
It was the best of code.
@@ -458,7 +458,7 @@ Keywords
The following sequences of characters are keyword tokens:
::
.. code-block:: ql
and
any
@@ -513,7 +513,7 @@ Operators
The following sequences of characters are operator tokens:
::
.. code-block:: ql
<
<=
@@ -548,7 +548,7 @@ An identifier cannot have the same sequence of characters as a keyword, nor can
Here are some examples of identifiers:
::
.. code-block:: ql
width
Window_width
@@ -567,7 +567,7 @@ There are several kinds of identifiers:
Identifiers are used in following syntactic constructs:
::
.. code-block:: ql
simpleId ::= lowerId | upperId
modulename ::= simpleId
@@ -583,7 +583,7 @@ Integer literals (int)
An integer literal is a possibly negated sequence of decimal digits (``0`` through ``9``, U+0030 through U+0039). Here are some examples of integer literals:
::
.. code-block:: ql
0
42
@@ -595,7 +595,7 @@ Float literals (float)
A floating-point literals is a possibly negated two non-negative integers literals separated by a dot (``.``, U+002E). Here are some examples of float literals:
::
.. code-block:: ql
0.5
2.0
@@ -619,7 +619,7 @@ A string literal denotes a sequence of characters. It begins and ends with a dou
Here are some examples of string literals:
::
.. code-block:: ql
"hello"
"He said, \"Logic clearly dictates that the needs of the many...\""
@@ -629,7 +629,7 @@ Annotations
Various kinds of syntax can have *annotations* applied to them. Annotations are as follows:
::
.. code-block:: ql
annotations ::= annotation*
@@ -745,7 +745,7 @@ Non-member predicates
A *predicate* is declared as a sequence of annotations, a head, and an optional body:
::
.. code-block:: ql
predicate ::= annotations head optbody
@@ -757,13 +757,13 @@ A valid non-member predicate can be annotated with ``cached``, ``deprecated``, `
The head of the predicate gives a name, an optional *result type*, and a sequence of variables declarations that are *arguments*:
::
.. code-block:: ql
head ::= ("predicate" | type) predicateName "(" (var_decls)? ")"
The body of a predicate is of one of three forms:
::
.. code-block:: ql
optbody ::= ";"
| "{" formula "}"
@@ -780,7 +780,7 @@ Classes
A class definition has the following syntax:
::
.. code-block:: ql
class ::= annotations "class" classname "extends" type ("," type)* "{" member* "}"
@@ -818,7 +818,7 @@ Members
Each member of a class is either a *character*, a predicate, or a field:
::
.. code-block:: ql
member ::= character | predicate | field
character ::= annotations classname "(" ")" "{" formula "}"
@@ -870,7 +870,7 @@ Select clauses
A QL file may include at most one *select clause*. That select clause has the following syntax:
::
.. code-block:: ql
select ::= ("from" var_decls)? ("where" formula)? "select" select_exprs ("order" "by" orderbys)?
@@ -884,7 +884,7 @@ The ``where`` keyword, if present, is followed by the *formula* of the select cl
The ``select`` keyword is followed by a number of *select expressions*. Select expressions have the following syntax:
::
.. code-block:: ql
as_exprs ::= as_expr ("," as_expr)*
as_expr ::= expr ("as" simpleId)?
@@ -893,7 +893,7 @@ The keyword ``as`` gives a *label* to the select expression it is part of. No tw
The ``order`` keyword, if present, is followed by a number of *ordering directives*. Ordering directives have the following syntax:
::
.. code-block:: ql
orderbys ::= orderby ("," orderby)*
orderby ::= simpleId ("asc" | "desc")?
@@ -923,7 +923,7 @@ Given a named tuple and a store, each expression has one or more *values*. This
There are several kinds of expressions:
::
.. code-block:: ql
exprs ::= expr ("," expr)*
@@ -947,7 +947,7 @@ Parenthesized expressions
A parenthesized expression is an expression surrounded by parentheses:
::
.. code-block:: ql
eparen ::= "(" expr ")"
@@ -958,7 +958,7 @@ Don't-care expressions
A don't-care expression is written as a single underscore:
::
.. code-block:: ql
dontcare ::= "_"
@@ -969,7 +969,7 @@ Literals
A literal expression is as follows:
::
.. code-block:: ql
literal ::= "false" | "true" | int | float | string
@@ -980,7 +980,7 @@ Unary operations
A unary operation is the application of ``+`` or ``-`` to another expression:
::
.. code-block:: ql
unop ::= "+" expr
| "-" expr
@@ -996,7 +996,7 @@ Binary operations
A binary operation is written as a *left operand* followed by a *binary operator*, followed by a *right operand*:
::
.. code-block:: ql
binop ::= expr "+" expr
| expr "-" expr
@@ -1023,7 +1023,7 @@ Variables
A variable has the following syntax:
::
.. code-block:: ql
variable ::= varname | "this" | "result"
@@ -1036,7 +1036,7 @@ Super
A super expression has the following syntax:
::
.. code-block:: ql
super_expr ::= "super" | type "." "super"
@@ -1055,7 +1055,7 @@ Casts
A cast expression is a type in parentheses followed by another expression:
::
.. code-block:: ql
cast ::= "(" type ")" expr
@@ -1070,7 +1070,7 @@ Postfix casts
A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses:
::
.. code-block:: ql
postfix_cast ::= primary "." "(" type ")"
@@ -1081,7 +1081,7 @@ Calls with results
An expression for a call with results is of one of two forms:
::
.. code-block:: ql
callwithresult ::= predicateRef (closure)? "(" (exprs)? ")"
| primary "." predicateName (closure)? "(" (exprs)? ")"
@@ -1124,7 +1124,7 @@ Aggregations
An aggregation can be written in one of two forms:
::
.. code-block:: ql
aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")"
| aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")"
@@ -1218,7 +1218,7 @@ Any
The ``any`` expression is a special kind of quantified expression.
::
.. code-block:: ql
any ::= "any" "(" var_decls ("|" (formula)? ("|" expr)?)? ")"
@@ -1231,7 +1231,7 @@ Ranges
Range expressions denote a range of values.
::
.. code-block:: ql
range ::= "[" expr ".." expr "]"
@@ -1246,7 +1246,7 @@ Set literals
Set literals denote a choice from a collection of values.
::
.. code-block:: ql
setliteral ::= "[" expr ("," expr)* "]"
@@ -1275,7 +1275,7 @@ A formula is a form of syntax used to *match* a named tuple given a store.
There are several kinds of formulas:
::
.. code-block:: ql
formula ::= fparen
| disjunction
@@ -1296,7 +1296,7 @@ Parenthesized formulas
A parenthesized formula is a formula enclosed by a pair of parentheses:
::
.. code-block:: ql
fparen ::= "(" formula ")"
@@ -1307,7 +1307,7 @@ Disjunctions
A disjunction is two formulas separated by the ``or`` keyword:
::
.. code-block:: ql
disjunction ::= formula "or" formula
@@ -1318,7 +1318,7 @@ Conjunctions
A conjunction is two formulas separated by the ``and`` keyword:
::
.. code-block:: ql
conjunction ::= formula "and" formula
@@ -1329,7 +1329,7 @@ Implications
An implication formula is two formulas separated by the ``implies`` keyword:
::
.. code-block:: ql
implies ::= formula "implies" formula
@@ -1342,7 +1342,7 @@ Conditional formulas
A conditional formula has the following syntax:
::
.. code-block:: ql
ifthen ::= "if" formula "then" formula "else" formula
@@ -1355,7 +1355,7 @@ Negations
A negation formula is a formula preceded by the ``not`` keyword:
::
.. code-block:: ql
negated ::= "not" formula
@@ -1366,7 +1366,7 @@ Quantified formulas
A quantified formula has several syntaxes:
::
.. code-block:: ql
quantified ::= "exists" "(" expr ")"
| "exists" "(" var_decls ("|" formula)? ("|" formula)? ")"
@@ -1390,7 +1390,7 @@ Comparisons
A comparison formula is two expressions separated by a comparison operator:
::
.. code-block:: ql
comparison ::= expr compop expr
compop ::= "=" | "!=" | "<" | ">" | "<=" | ">="
@@ -1408,7 +1408,7 @@ Type checks
A type check formula has the following syntax:
::
.. code-block:: ql
instanceof ::= expr "instanceof" type
@@ -1423,7 +1423,7 @@ Range checks
A range check has the following syntax:
::
.. code-block:: ql
inrange ::= expr "in" range
@@ -1434,7 +1434,7 @@ Calls
A call has the following syntax:
::
.. code-block:: ql
call ::= predicateRef (closure)? "(" (exprs)? ")"
| primary "." predicateName (closure)? "(" (exprs)? ")"
@@ -1471,7 +1471,7 @@ Aliases
Aliases define new names for existing QL entities.
::
.. code-block:: ql
alias ::= annotations "predicate" literalId "=" predicateRef "/" int ";"
| annotations "class" classname "=" type ";"
@@ -1891,7 +1891,7 @@ Summary of syntax
The complete grammar for QL is as follows:
::
.. code-block:: ql
ql ::= moduleBody

View File

@@ -37,7 +37,9 @@ Apart from the expressions described in ":ref:`expressions`," you can also inclu
.. TODO: link to topics on formulas and expressions in QL
For example::
For example:
.. code-block:: ql
from int x, int y
where x = 3 and y in [0 .. 2]
@@ -76,7 +78,9 @@ Query predicates
A query predicate is a :ref:`non-member predicate <non-member-predicates>` with a ``query``
annotation. It returns all the tuples that the predicate evaluates to.
For example::
For example:
.. code-block:: ql
query int getProduct(int x, int y) {
x = 3 and

View File

@@ -132,7 +132,9 @@ If a recursive predicate evaluates to the empty set of values, there is usually
wrong.
For example, you might try to define the predicate ``getAnAncestor()`` (from the
:ref:`above <transitive-closures>` example) as follows::
:ref:`above <transitive-closures>` example) as follows:
.. code-block:: ql
Person getAnAncestor() {
result = this.getAParent().getAnAncestor()
@@ -141,7 +143,9 @@ For example, you might try to define the predicate ``getAnAncestor()`` (from the
In this case, the QL compiler gives an error stating that this is an empty recursive call.
Since ``getAnAncestor()`` is initially assumed to be empty, there is no way for new values to
be added. The predicate needs a starting point for the recursion, for example::
be added. The predicate needs a starting point for the recursion, for example:
.. code-block:: ql
Person getAnAncestor() {
result = this.getAParent()
@@ -158,7 +162,9 @@ A valid recursive predicate must also be `monotonic <https://en.wikipedia.org/wi
This means that (mutual) recursion is only allowed under an even number of :ref:`negations <negation>`.
Intuitively, this prevents "`liar's paradox <https://en.wikipedia.org/wiki/Liar_paradox>`_"
situations, where there is no solution to the recursion. For example::
situations, where there is no solution to the recursion. For example:
.. code-block:: ql
predicate isParadox() {
not isParadox()
@@ -181,7 +187,9 @@ For example, consider the following (slightly macabre) member predicate of class
The recursive call to ``isExtinct()`` is nested in an even number of negations, so this is a
valid definition.
In fact, you could rewrite the second part of the definition as follows::
In fact, you could rewrite the second part of the definition as follows:
.. code-block:: ql
forall(Person descendant | descendant.getAParent+() = this |
descendant.isExtinct()

View File

@@ -79,7 +79,9 @@ To define a class, you write:
#. The types to extend.
#. The :ref:`body of the class <class-bodies>`, enclosed in braces.
For example::
For example:
.. code-block:: ql
class OneTwoThree extends int {
OneTwoThree() { // characteristic predicate
@@ -146,7 +148,9 @@ Member predicates
These are :ref:`predicates <predicates>` that only apply to members of a particular class.
You can :ref:`call <calls>` a member predicate on a value. For example, you can use the member
predicate from the :ref:`above <defining-a-class>` class::
predicate from the :ref:`above <defining-a-class>` class:
.. code-block:: ql
1.(OneTwoThree).getAString()
@@ -166,7 +170,9 @@ This call returns ``"ONE, TWO OR THREE: 1"``.
.. index:: this
.. _this:
.. note::
.. note:
.. code-block:: ql
Characteristic predicates and member predicates often use the variable ``this``.
This variable always refers to a member of the class—in this case a value belonging to the
@@ -240,7 +246,9 @@ abstract class, you can add more subclasses to it.
If you are writing a security query, you may be interested in identifying
all expressions that can be interpreted as SQL queries.
You can use the following abstract class to describe these expressions::
You can use the following abstract class to describe these expressions:
.. code-block:: ql
abstract class SqlExpr extends Expr {
...
@@ -343,7 +351,9 @@ Multiple inheritance
A class can extend multiple types. In that case, it inherits from all those types.
For example, using the definitions from the above section::
For example, using the definitions from the above section:
.. code-block:: ql
class Two extends OneTwo, TwoThree {}
@@ -401,7 +411,9 @@ of values that satisfy the argument types and the body.
A benefit of this is that each branch can have a different structure. For example, if you want
to define an "option type" that either holds a value (such as a ``Call``) or is empty, you
could write this as follows::
could write this as follows:
.. code-block:: ql
newtype OptionCall = SomeCall(Call c) or NoCall()
@@ -415,7 +427,9 @@ To define an algebraic datatype, use the following general syntax::
newtype <TypeName> = <branches>
The branch definitions have the following form::
The branch definitions have the following form:
.. code-block:: ql
<BranchName>(<arguments>) { <body> }
@@ -429,7 +443,9 @@ The branch definitions have the following form::
Note that branch bodies are evaluated fully, so they must be finite. They should be kept small
for good performance.
For example, the following algebraic datatype has three branches::
For example, the following algebraic datatype has three branches:
.. code-block:: ql
newtype T =
Type1(A a, B b) { body(a, b) }
@@ -495,7 +511,9 @@ Type unions of :ref:`database types <database-types>` are also supported.
You can use a type union to give a name to a subset of the branches from an algebraic datatype.
In some cases, using the type union over the whole algebraic datatype can avoid spurious
:ref:`recursion <recursion>` in predicates.
For example, the following construction is legal::
For example, the following construction is legal:
.. code-block:: ql
newtype InitialValueSource =
ExplicitInitialization(VarDecl v) { exists(v.getInitializer()) } or

View File

@@ -34,7 +34,9 @@ and many more.
Conceptually, you can think of a variable as holding all the values that its type allows, subject
to any further constraints.
For example, consider the following select clause::
For example, consider the following select clause:
.. code-block:: ql
from int i
where i in [0 .. 9]
@@ -44,7 +46,9 @@ Just based on its type, the variable ``i`` could contain all integers. However,
constrained by the formula ``i in [0 .. 9]``. Consequently, the result of the select clause is
the ten numbers between ``0`` and ``9`` inclusive.
As an aside, note that the following query leads to a compile-time error::
As an aside, note that the following query leads to a compile-time error:
.. code-block:: ql
from int i
select i
@@ -64,7 +68,9 @@ affect the value of an :ref:`expression <expressions>` that uses them, or whethe
Other variables, called **bound** variables, are restricted to specific sets of values.
It might be easiest to understand this distinction in an example. Take a look at the following
expressions::
expressions:
.. code-block:: ql
"hello".indexOf("l")
@@ -90,7 +96,9 @@ variables ``i`` and ``x`` respectively. In other words, the value of the variabl
on the value of the expression. These are examples of **free variables**.
Similarly, if a formula contains free variables, then the formula can hold or not hold
depending on the values assigned to those variables [#]_. For example::
depending on the values assigned to those variables [#]_. For example:
.. code-block:: ql
"hello".indexOf("l") = 1