]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | / Copyright (c) 2015 Boost.Test contributors | |
3 | / | |
4 | / Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | /] | |
7 | ||
8 | ||
9 | [section:internal_details `BOOST_TEST`: details on expressions] | |
10 | Let's consider the following example: | |
11 | ||
12 | [bt_example boost_test_macro3..BOOST_TEST reporting..run-fail] | |
13 | ||
14 | It was already mentioned that the reporting is not symmetrical (see [link boost_test.testing_tools.reports here]). | |
15 | An expression is constructed from the `statement` appearing in the `BOOST_TEST` macro. This expression allows evaluation and reporting such | |
16 | as `"13 - 1 >= 12" failed` along with a copy of the `statement`, which contains more details than `"a - 1 < b" failed`. | |
17 | In details, what happens is the following: | |
18 | ||
19 | # a special object, the `seed` of the expression, is composed from the left side of `statement`. | |
20 | This initial composition has highest precedence over the supported operations. The expression below: | |
21 | ||
22 | a op1 b op2 c op3 d | |
23 | ||
24 | is actually seen as | |
25 | ||
26 | ( seed a ) op1 b op2 c op3 d | |
27 | ||
28 | # The "`seed a`" returns an `expression` object that keep tracks of the type of `a`. This expression | |
29 | has overloads for left-to-right associativity, and the | |
30 | operations `op1`, `op2` ... are /chained/ to the right of this expression object: | |
31 | ||
32 | a op1 b | |
33 | ||
34 | yields to the pseudo-code | |
35 | ||
36 | expression1 = create-expression(a) | |
37 | expression2 = create-expression(expression1, op1, b) | |
38 | ||
39 | `expression1` and `expression2` keep track of their left and right operands, and the operation on those operands. The | |
40 | expressions keep also track of the result type of the associated sub-expression. In the above example, `expression1` and `expression2` | |
41 | have result type `decltype(a)` and `decltype(a op1 b)` respectively. The result type allows for chaining | |
42 | sub-expressions. | |
43 | ||
44 | # The C++ operators precedence rules apply in any case. What is seen by the expression is what is reachable with left-to-right | |
45 | composition. Any other operation that happens before it reaches the expression's right operand is not parsed as a sub-expression | |
46 | and is seen as a single operand: the right operand is not developed further by the framework. | |
47 | Let's suppose `op2` below has higher precedence than `op1`, then | |
48 | ||
49 | a op1 b op2 c | |
50 | ||
51 | is equivalent to: | |
52 | ||
53 | create-expression(create-expression(a), op1, (b op2 c)) | |
54 | ||
55 | In the above statement, the final expression can only see the result of `(b op2 c)` to its right, for which no further detail | |
56 | can be provided in the logs. This is also the case for /right-to-left/ associative operators, such as `!`, `~`, `-` (unary negation) | |
57 | etc. | |
58 | ||
59 | [caution Since the `expression` object is composed from left-to-right, it actually observes a chain of operations and | |
60 | not the full expression tree.] | |
61 | ||
62 | # Once the full expression chain is built, it is evaluated as a chain of sub-expressions from left-to-right, exactly as the | |
63 | composition rule above. The evaluated elements are the ones of the expression itself. The expression | |
64 | ||
65 | a op1 b | |
66 | ||
67 | yields to the following evaluation chain: | |
68 | ||
69 | expression2.result = expression1.result op1 b | |
70 | expression1.result = a | |
71 | ||
72 | The final expression of the statement is cast to a boolean, which is in turn evaluated by the __UTF__. | |
73 | ||
74 | ||
75 | The example below illustrates the construction of the left-to-right /chained/ expression. | |
76 | ||
77 | [bt_example boost_test_macro2..BOOST_TEST compound statements..run-fail] | |
78 | [endsect] |