aboutsummaryrefslogtreecommitdiff
path: root/language
diff options
context:
space:
mode:
Diffstat (limited to 'language')
-rw-r--r--language/scanning.rst2
-rw-r--r--language/source-file.rst2
-rw-r--r--language/type-definition.rst52
3 files changed, 52 insertions, 4 deletions
diff --git a/language/scanning.rst b/language/scanning.rst
index ed85ead..c45e6b8 100644
--- a/language/scanning.rst
+++ b/language/scanning.rst
@@ -15,7 +15,7 @@ Scanning
``char``, ``const``, ``continue``, ``default``, ``do``, ``double``,
``else``, ``enum``, ``extern``, ``float``, ``for``, ``fragile``,
``function``, ``if``, :crowbar:ref:`include <IncludeStatement>`, ``int``, ``long``, ``return``,
- ``short``, ``signed``, ``sizeof``, ``struct``, ``switch``,
+ ``short``, ``signed``, ``sizeof``, ``struct``, ``switch``, ``union``,
``unsigned``, ``void``, or ``while``.
identifier
diff --git a/language/source-file.rst b/language/source-file.rst
index 6522ea8..2fc3ba0 100644
--- a/language/source-file.rst
+++ b/language/source-file.rst
@@ -2,7 +2,7 @@ Source Files
------------
.. crowbar:element:: HeaderFile <- IncludeStatement* HeaderFileElement+
-.. crowbar:element:: HeaderFileElement <- TypeDefinition / FunctionDeclaration / ConstantDefinition / UninitializedVariableDeclaration
+.. crowbar:element:: HeaderFileElement <- TypeDefinition / FunctionDeclaration / ConstantDefinition / VariableDeclaration
A Crowbar header file defines an API boundary, either at the surface of a library or between pieces of a library or application.
:crowbar:ref:`IncludeStatement`\ s can only appear at the beginning of the header file, and header files cannot define behavior directly.
diff --git a/language/type-definition.rst b/language/type-definition.rst
index 02616b8..88c4a04 100644
--- a/language/type-definition.rst
+++ b/language/type-definition.rst
@@ -5,7 +5,7 @@ Defining Types
Crowbar has three different kinds of user-defined types.
-.. crowbar:element:: StructDefinition <- 'struct' identifier '{' VariableDeclaration+ '}' ';'
+.. crowbar:element:: StructDefinition <- 'struct' identifier '{' VariableDeclaration+ '}'
A ``struct`` defines a composite type with several members.
@@ -13,7 +13,7 @@ Defining Types
define struct layout in memory
-.. crowbar:element:: EnumDefinition <- 'enum' identifier '{' EnumMember (',' EnumMember)* ','? '}' ';'
+.. crowbar:element:: EnumDefinition <- 'enum' identifier '{' EnumMember (',' EnumMember)* ','? '}'
EnumMember <- identifier ('=' Expression)?
An ``enum`` defines a type which can take one of several specified values.
@@ -21,3 +21,51 @@ Defining Types
.. 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