Skip to content

Commit 6a1d0b0

Browse files
author
Shati Patel
committed
QL tutorials: Update formatting and style
1 parent 9193a81 commit 6a1d0b0

File tree

6 files changed

+48
-49
lines changed

6 files changed

+48
-49
lines changed

docs/language/learn-ql/beginner/find-thief-1.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Find the thief: Introduction
22
============================
33

4-
There is a small village hidden away in the mountains. The village is divided into four parts - north, south, east, and west - and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown!
4+
There is a small village hidden away in the mountains. The village is divided into four partsnorth, south, east, and westand in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown!
55

66
You know that the thief must live in the village, since nobody else knew about the crown. After some expert detective work, you obtain a list of all the people in the village and some of their personal details.
77

docs/language/learn-ql/beginner/find-thief-2.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Notice that we have only temporarily introduced the variable ``c`` and we didn't
8282

8383
Note
8484

85-
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-handbook/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not(exists(vars | formula 1 | not formula 2))``.
85+
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-handbook/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``.
8686

8787
The real investigation
8888
----------------------
@@ -124,8 +124,8 @@ Hints
124124
125125
from Person t
126126
where <condition 1> and
127-
not <condition 2> and
128-
...
127+
not <condition 2> and
128+
...
129129
select t
130130
131131
Once you have finished, you will have a list of possible suspects. One of those people must be the thief!

docs/language/learn-ql/beginner/fire-1.rst

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,50 @@ Read the examples below to learn how to define predicates and classes in QL. The
1212
Select the southerners
1313
----------------------
1414

15-
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ ``southern``:
15+
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ ``isSouthern``:
1616

1717
.. code-block:: ql
1818
19-
predicate southern(Person p) {
20-
p.getLocation() = "south"
19+
predicate isSouthern(Person p) {
20+
p.getLocation() = "south"
2121
}
2222
23-
The predicate ``southern(p)`` takes a single parameter ``p`` and checks if ``p`` satisfies the property ``p.getLocation() = "south"``.
23+
The predicate ``isSouthern(p)`` takes a single parameter ``p`` and checks if ``p`` satisfies the property ``p.getLocation() = "south"``.
2424

2525
.. pull-quote::
2626

2727
Note
2828

2929
- The name of a predicate always starts with a lowercase letter.
30-
- You can also define predicates with a result. In that case, the keyword ``predicate`` is replaced with the type of the result. This is like introducing a new argument, the special variable ``result``. For example, ``int getAge() {result = ...}`` returns an ``int``.
30+
- You can also define predicates with a result. In that case, the keyword ``predicate`` is replaced with the type of the result. This is like introducing a new argument, the special variable ``result``. For example, ``int getAge() { result = ... }`` returns an ``int``.
3131

3232
You can now list all southerners using:
3333

3434
.. code-block:: ql
3535
36-
/* define predicate `southern` as above */
36+
/* define predicate `isSouthern` as above */
3737
3838
from Person p
39-
where southern(p)
39+
where isSouthern(p)
4040
select p
4141
42-
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``southern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
42+
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``isSouthern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
4343

4444
.. code-block:: ql
4545
4646
class Southerner extends Person {
47-
Southerner() { southern(this) }
47+
Southerner() { isSouthern(this) }
4848
}
4949
50-
A class in QL represents a logical property: when a value satisfies that property, it is a member of the class. This means that a value can be in many classes - being in a particular class doesn't stop it from being in other classes too.
50+
A class in QL represents a logical property: when a value satisfies that property, it is a member of the class. This means that a value can be in many classesbeing in a particular class doesn't stop it from being in other classes too.
5151

52-
The expression ``southern(this)`` defines the logical property represented by the class, called its *characteristic predicate*. It uses a special variable ``this`` and indicates that a ``Person`` "``this``" is a ``Southerner`` if the property ``southern(this)`` holds.
52+
The expression ``isSouthern(this)`` defines the logical property represented by the class, called its *characteristic predicate*. It uses a special variable ``this`` and indicates that a ``Person`` "``this``" is a ``Southerner`` if the property ``isSouthern(this)`` holds.
5353

5454
.. pull-quote::
5555

5656
Note
5757

58-
If you are familiar with object-oriented programming languages, you might be tempted to think of the characteristic predicate as a *constructor*. However, this is **not** the case - it is a logical property which does not create any objects.
58+
If you are familiar with object-oriented programming languages, you might be tempted to think of the characteristic predicate as a *constructor*. However, this is **not** the caseit is a logical property which does not create any objects.
5959

6060
You always need to define a class in QL in terms of an existing (larger) class. In our example, a ``Southerner`` is a special kind of ``Person``, so we say that ``Southerner`` *extends* ("is a subset of") ``Person``.
6161

@@ -66,7 +66,7 @@ Using this class you can now list all people living in the south simply as:
6666
from Southerner s
6767
select s
6868
69-
You may have noticed that some predicates are appended, for example ``p.getAge()``, while others are not, for example ``southern(p)``. This is because ``getAge()`` is a member predicate, that is, a predicate that only applies to members of a class. You define such a member predicate inside a class. In this case, ``getAge()`` is defined inside the class ``Person``. In contrast, ``southern`` is defined separately and is not inside any classes. Member predicates are especially useful because you can chain them together easily. For example, ``p.getAge().sqrt()`` first gets the age of ``p`` and then calculates the square root of that number.
69+
You may have noticed that some predicates are appended, for example ``p.getAge()``, while others are not, for example ``isSouthern(p)``. This is because ``getAge()`` is a member predicate, that is, a predicate that only applies to members of a class. You define such a member predicate inside a class. In this case, ``getAge()`` is defined inside the class ``Person``. In contrast, ``isSouthern`` is defined separately and is not inside any classes. Member predicates are especially useful because you can chain them together easily. For example, ``p.getAge().sqrt()`` first gets the age of ``p`` and then calculates the square root of that number.
7070

7171
Travel restrictions
7272
-------------------
@@ -88,20 +88,19 @@ Start by defining a class ``Child`` containing all villagers under 10 years old.
8888
.. code-block:: ql
8989
9090
class Child extends Person {
91+
/* the characteristic predicate */
92+
Child() { this.getAge() < 10 }
9193
92-
/* the characteristic predicate */
93-
Child() { this.getAge() < 10 }
94-
95-
/* a member predicate */
96-
override predicate isAllowedIn(string region) {
97-
region = this.getLocation()
98-
}
94+
/* a member predicate */
95+
override predicate isAllowedIn(string region) {
96+
region = this.getLocation()
97+
}
9998
}
10099
101100
Now try applying ``isAllowedIn(string region)`` to a person ``p``. If ``p`` is not a child, the original definition is used, but if ``p`` is a child, the new predicate definition overrides the original.
102101

103102
You know that the fire starters live in the south *and* that they must have been able to travel to the north. Write a query to find the possible suspects. You could also extend the ``select`` clause to list the age of the suspects. That way you can clearly see that all the children have been excluded from the list.
104103

105-
➤ `See the answer in the query console <https://lgtm.com/query/2164870087/>`__
104+
➤ `See the answer in the query console <https://lgtm.com/query/2551838470440192723/>`__
106105

107106
Continue to the :doc:`next page <fire-2>` to gather more clues and find out which of your suspects started the fire...

docs/language/learn-ql/beginner/fire-2.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,27 @@ This is a very helpful clue. Remember that you wrote a QL query to select all ba
1111
where not exists (string c | p.getHairColor() = c)
1212
select p
1313
14-
To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``bald``.
14+
To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``isBald``.
1515

1616
.. code-block:: ql
1717
18-
predicate bald(Person p) {
19-
not exists (string c | p.getHairColor() = c)
18+
predicate isBald(Person p) {
19+
not exists (string c | p.getHairColor() = c)
2020
}
2121
22-
The property ``bald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with:
22+
The property ``isBald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with:
2323

2424
.. code-block:: ql
2525
2626
from Person p
27-
where bald(p)
27+
where isBald(p)
2828
select p
2929
30-
The predicate ``bald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example - that would cause an error.
30+
The predicate ``isBald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for examplethat would cause an error.
3131

3232
You can now write a query to select the bald southerners who are allowed into the north.
3333

34-
➤ `See the answer in the query console <https://lgtm.com/query/1505746995987/>`__
34+
➤ `See the answer in the query console <https://lgtm.com/query/2572701606358725253/>`__
3535

3636
You have found the two fire starters! They are arrested and the villagers are once again impressed with your work.
3737

docs/language/learn-ql/beginner/heir.rst

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Crown the rightful heir
22
=======================
33

4-
Phew! No more crimes in the village - you can finally leave the village and go home.
4+
Phew! No more crimes in the villageyou can finally leave the village and go home.
55

6-
But then... During your last night in the village, the old king - the great King Basil - dies in his sleep and there is chaos everywhere!
6+
But then... During your last night in the village, the old kingthe great King Basildies in his sleep and there is chaos everywhere!
77

88
The king never married and he had no children, so nobody knows who should inherit the king's castle and fortune. Immediately, lots of villagers claim that they are somehow descended from the king's family and that they are the true heir. People argue and fight and the situation seems hopeless.
99

@@ -38,8 +38,8 @@ We know that the king has no children himself, but perhaps he has siblings. Writ
3838
.. code-block:: ql
3939
4040
from Person p
41-
where parentOf(p) = parentOf("King Basil") and
42-
not p = "King Basil"
41+
where parentOf(p) = parentOf("King Basil") and
42+
not p = "King Basil"
4343
select p
4444
4545
He does indeed have siblings! But you need to check if any of them are alive... Here is one more predicate you might need:
@@ -56,16 +56,16 @@ Use this predicate to see if the any of the king's siblings are alive.
5656
5757
from Person p
5858
where parentOf(p) = parentOf("King Basil") and
59-
not p = "King Basil"
60-
and not p.isDeceased()
59+
not p = "King Basil"
60+
and not p.isDeceased()
6161
select p
6262
6363
Unfortunately, none of King Basil's siblings are alive. Time to investigate further. It might be helpful to define a predicate ``childOf()`` which returns a child of the person. To do this, the ``parentOf()`` predicate can be used inside the definition of ``childOf()``. Remember that someone is a child of ``p`` if and only if ``p`` is their parent:
6464

6565
.. code-block:: ql
6666
6767
Person childOf(Person p) {
68-
p = parentOf(result)
68+
p = parentOf(result)
6969
}
7070
7171
.. pull-quote::
@@ -80,7 +80,7 @@ Try to write a query to find out if any of the king's siblings have children:
8080
8181
from Person p
8282
where parentOf(p) = parentOf("King Basil") and
83-
not p = "King Basil"
83+
not p = "King Basil"
8484
select childOf(p)
8585
8686
The query returns no results, so they have no children. But perhaps King Basil has a cousin who is alive or has children, or a second cousin, or...
@@ -100,8 +100,8 @@ You can translate this into QL as follows:
100100
.. code-block:: ql
101101
102102
Person ancestorOf(Person p) {
103-
result = parentOf(p) or
104-
result = parentOf(ancestorOf(p))
103+
result = parentOf(p) or
104+
result = parentOf(ancestorOf(p))
105105
}
106106
107107
As you can see, you have used the predicate ``ancestorOf()`` inside its own definition. This is an example of `recursion <https://help.semmle.com/QL/ql-handbook/recursion.html>`__.
@@ -120,12 +120,12 @@ Here is one way to define ``relativeOf()``:
120120
.. code-block:: ql
121121
122122
Person relativeOf(Person p) {
123-
parentOf*(result) = parentOf*(p)
123+
parentOf*(result) = parentOf*(p)
124124
}
125125
126126
Don't forget to use the predicate ``isDeceased()`` to find relatives that are still alive.
127127

128-
➤ `See the answer in the query console <https://lgtm.com/query/2164460071/>`__
128+
➤ `See the answer in the query console <https://lgtm.com/query/6710025057257064639/>`__
129129

130130
Select the true heir
131131
--------------------
@@ -136,9 +136,9 @@ To decide who should inherit the king's fortune, the villagers carefully read th
136136

137137
*"The heir to the throne is the closest living relative of the king. Any person with a criminal record will not be considered. If there are multiple candidates, the oldest person is the heir."*
138138

139-
As your final challenge, define a predicate ``criminalRecord`` so that ``criminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief <find-thief-1>` and :doc:`Catch the fire starter <fire-1>` tutorials).
139+
As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief <find-thief-1>` and :doc:`Catch the fire starter <fire-1>` tutorials).
140140

141-
➤ `See the answer in the query console <https://lgtm.com/query/1505745996002/>`__
141+
➤ `See the answer in the query console <https://lgtm.com/query/1820692755164273290/>`__
142142

143143
Experimental explorations
144144
-------------------------

docs/language/learn-ql/beginner/ql-tutorials.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ some simple examples.
1616

1717
Currently the following detective tutorials are available:
1818

19-
- :doc:`Find the thief <find-thief-1>` - a three part mystery that introduces logical connectives, quantifiers, and aggregates
20-
- :doc:`Catch the fire starter <fire-1>` - an intriguing search that introduces predicates and classes
21-
- :doc:`Crown the rightful heir <heir>` - a detective puzzle that introduces recursion
19+
- :doc:`Find the thief <find-thief-1>`a three part mystery that introduces logical connectives, quantifiers, and aggregates
20+
- :doc:`Catch the fire starter <fire-1>`an intriguing search that introduces predicates and classes
21+
- :doc:`Crown the rightful heir <heir>`a detective puzzle that introduces recursion
2222

2323
Further resources
2424
-----------------

0 commit comments

Comments
 (0)