aboutsummaryrefslogtreecommitdiff
path: root/language/type-definition.rst
blob: 88c4a04026ab7131f019749c823216b84f101a25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Defining Types
--------------

.. crowbar:element:: TypeDefinition <- StructDefinition / EnumDefinition / UnionDefinition

    Crowbar has three different kinds of user-defined types.

.. crowbar:element:: StructDefinition <- 'struct' identifier '{' VariableDeclaration+ '}'

    A ``struct`` defines a composite type with several members.

    .. todo::

        define struct layout in memory

.. crowbar:element:: EnumDefinition <- 'enum' identifier '{' EnumMember (',' EnumMember)* ','? '}'
                     EnumMember <- identifier ('=' Expression)?

    An ``enum`` defines a type which can take one of several specified values.

    .. todo::
        
        define enum value assignment, type-related behavior

.. crowbar:element:: UnionDefinition <- RobustUnionDefinition / FragileUnionDefinition

    Unions as implemented in C are not robust by default, and care must be taken to ensure that they are only used robustly.
    However, for the purpose of interoperability with C, Crowbar unions may be defined as robust or as fragile.

.. crowbar:element:: RobustUnionDefinition <- 'union' identifier '{' VariableDeclaration UnionBody '}'
                     UnionBody <- 'switch' '(' identifier ')' '{' UnionBodySet+ '}'
                     UnionBodySet <- CaseSpecifier+ (VariableDeclaration / ';')

    A robust union, or simply union, in Crowbar is what is known more broadly as a tagged union.
    The top-level variable declaration must have a type which is some ``enum``, and its name must be the same as the identifier in the ``switch``.

    For example::

        enum TokenType {
            Identifier,
            Constant,
            Operator,
            Whitespace,
        }

        union Token {
            enum TokenType type;

            switch (type) {
                case Identifier: (const char) * name;
                case Constant: int value;
                case Operator: char op;
                case Whitespace: ;
            }
        }
    
    defines a ``union Token`` type, where the ``type`` field controls which of the other fields in the union is valid.

    .. todo::

        go into more depth about how tagged unions work

.. crowbar:element:: FragileUnionDefinition <- 'fragile' 'union' identifier '{' VariableDeclaration+ '}'

    A fragile union, like a struct, is a simple bag of fields.
    However, unlike a struct, only the most recently assigned field is valid at any given time.
    As such, in non-trivial cases no compiler can predict which field is or is not valid, and any statement which reads a field of a fragile union must itself be a :crowbar:ref:`FragileStatement`.

    .. todo::

        explain memory layout of fragile unions