A tiny GCC front end – Part 9
Today we will do something relatively easy: let's add a way to declare boolean variables and express boolean literals.
Syntax
Since tiny already has a boolean type (for instance when doing a comparison like a > b
) it is just a matter of making it explicit in the language. First let's extend the syntax of types. Some programming languages call this type logical, but we will call it bool
.
〈type〉 → int
| float
| bool
| 〈type〉[
〈expression〉]
| 〈type〉(
〈expression〉:
〈expression〉)
Booleans only have two values: true and false. Technically speaking we already can express these two values in many different ways. For instance a way to express a true value is 1 = 1 and a false value is 1 != 1. So technically, nothing else is mandatory at this point. That said, this would be a poor language design choice, as it would make our programs look a bit weird. So we will add two boolean literals true
and false
that express a true boolean value and a false boolean value respectively.
We will have to extend our primary syntax.
〈primary〉 → (
expression )
| 〈identifier〉
| 〈integer-literal〉
| 〈bool-literal〉
| 〈float-literal〉
| 〈string-literal〉
| 〈array-element〉
〈bool-literal〉 → true
| false
Semantics
bool
designates the boolean type of tiny.
A 〈bool-literal〉 of the form true
is an expression with boolean type and true boolean value. Similarly, a 〈bool-literal〉 of the form false
is an expression with boolean type and false boolean value.
Note that in contrast to some programming languages (like C/C++), boolean and integer are different types in tiny and there are no implicit conversions between them.
Implementation
Given that much of the required infrastructure is already there, adding boolean types and literals is quite straightforward.
Lexer
We only have to define three new tokens bool, true and false. Since they are keywords, nothing else is required in the lexer.
Parser
Member function Parser::parse_type
will have to recognize the bool token. The GENERIC tree type used will be boolean_type_node
(we already use this one in relational operators).
Finally, member function Parser::null_denotation has to handle the two new literals.
Note that GCC function build_int_cst_type
constructs a GENERIC tree with code INTEGER_CST
. This does not mean that he node must have integer type. In our case a true boolean value will be represented using the integer 1 (and 0 for the false value), but note that the tree itself has boolean_type_node
.
Nothing else is required. Compared to arrays this was easy-peasy.
Smoke test
Now we can use boolean variables and use them as operators of logical operators.
Yay!
Now we can rewrite our bubble.tiny
program from part 8 in a nicer way.
That's all for today