From 14c4550aff926f53f256e831a7d99bffffd21dfd Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Sat, 31 Oct 2020 22:38:29 -0600 Subject: settle on a tagged union plan (for now) --- language/type-definition.rst | 52 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'language/type-definition.rst') 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 -- cgit v1.2.3