1*99e0aae7SDavid Rees# Emboss Language Reference 2*99e0aae7SDavid Rees 3*99e0aae7SDavid Rees## Top Level Structure 4*99e0aae7SDavid Rees 5*99e0aae7SDavid ReesAn `.emb` file contains four sections: a documentation block, imports, an 6*99e0aae7SDavid Reesattribute block, containing attributes which apply to the whole module, followed 7*99e0aae7SDavid Reesby a list of type definitions: 8*99e0aae7SDavid Rees 9*99e0aae7SDavid Rees``` 10*99e0aae7SDavid Rees# Documentation block (optional) 11*99e0aae7SDavid Rees-- This is an example of an .emb file, with every section. 12*99e0aae7SDavid Rees 13*99e0aae7SDavid Rees# Imports (optional) 14*99e0aae7SDavid Reesimport "other.emb" as other 15*99e0aae7SDavid Reesimport "project/more.emb" as project_more 16*99e0aae7SDavid Rees 17*99e0aae7SDavid Rees# Attribute block (optional) 18*99e0aae7SDavid Rees[$default byte_order: "LittleEndian"] 19*99e0aae7SDavid Rees[(cpp) namespace: "foo::bar::baz"] 20*99e0aae7SDavid Rees[(java) namespace: "com.example.foo.bar.baz"] 21*99e0aae7SDavid Rees 22*99e0aae7SDavid Rees# Type definitions 23*99e0aae7SDavid Reesenum Foo: 24*99e0aae7SDavid Rees ONE = 1 25*99e0aae7SDavid Rees TEN = 10 26*99e0aae7SDavid Rees PURPLE = 12 27*99e0aae7SDavid Rees 28*99e0aae7SDavid Reesstruct Bar: 29*99e0aae7SDavid Rees 0 [+4] Foo purple 30*99e0aae7SDavid Rees 4 [+4] UInt payload_size (s) 31*99e0aae7SDavid Rees 8 [+s] UInt:8[] payload 32*99e0aae7SDavid Rees``` 33*99e0aae7SDavid Rees 34*99e0aae7SDavid ReesThe documentation and/or attribute blocks may be omitted if they are not 35*99e0aae7SDavid Reesnecessary. 36*99e0aae7SDavid Rees 37*99e0aae7SDavid Rees 38*99e0aae7SDavid Rees### Comments 39*99e0aae7SDavid Rees 40*99e0aae7SDavid ReesComments start with `#` and extend to the end of the line: 41*99e0aae7SDavid Rees 42*99e0aae7SDavid Rees``` 43*99e0aae7SDavid Reesstruct Foo: # This is a comment 44*99e0aae7SDavid Rees # This is a comment 45*99e0aae7SDavid Rees 0 [+1] UInt field # This is a comment 46*99e0aae7SDavid Rees``` 47*99e0aae7SDavid Rees 48*99e0aae7SDavid ReesComments are ignored. They should not be confused with 49*99e0aae7SDavid Rees[*documentation*](#documentation), which is intended to be used by some back 50*99e0aae7SDavid Reesends. 51*99e0aae7SDavid Rees 52*99e0aae7SDavid Rees 53*99e0aae7SDavid Rees## Documentation 54*99e0aae7SDavid Rees 55*99e0aae7SDavid ReesDocumentation blocks may be attached to modules, types, fields, or enum values. 56*99e0aae7SDavid ReesThey are different from comments in that they will be used by the 57*99e0aae7SDavid Rees(not-yet-ready) documentation generator back-end. 58*99e0aae7SDavid Rees 59*99e0aae7SDavid ReesDocumentation blocks take the form of any number of lines starting with `-- `: 60*99e0aae7SDavid Rees 61*99e0aae7SDavid Rees``` 62*99e0aae7SDavid Rees-- This is a module documentation block. Text in this block will be attached to 63*99e0aae7SDavid Rees-- the module as documentation. 64*99e0aae7SDavid Rees-- 65*99e0aae7SDavid Rees-- This is a new paragraph in the same module documentation block. 66*99e0aae7SDavid Rees-- 67*99e0aae7SDavid Rees-- Module-level documentation should describe the purpose of the module, and may 68*99e0aae7SDavid Rees-- point out the most salient features of the module. 69*99e0aae7SDavid Rees 70*99e0aae7SDavid Reesstruct Message: 71*99e0aae7SDavid Rees -- This is a documentation block attached to the Message structure. It should 72*99e0aae7SDavid Rees -- describe the purpose of Message, and how it should be used. 73*99e0aae7SDavid Rees 0 [+4] UInt header_length 74*99e0aae7SDavid Rees -- This is documentation for the header_length field. Again, it should 75*99e0aae7SDavid Rees -- describe this specific field. 76*99e0aae7SDavid Rees 4 [+4] MessageType message_type -- Short docs can go on the same line. 77*99e0aae7SDavid Rees``` 78*99e0aae7SDavid Rees 79*99e0aae7SDavid ReesDocumentation should be written in CommonMark format, ignoring the leading 80*99e0aae7SDavid Rees`-- `. 81*99e0aae7SDavid Rees 82*99e0aae7SDavid Rees 83*99e0aae7SDavid Rees## Imports 84*99e0aae7SDavid Rees 85*99e0aae7SDavid ReesAn `import` line tells Emboss to read another `.emb` file and make its types 86*99e0aae7SDavid Reesavailable to the current file under the given name. For example, given the 87*99e0aae7SDavid Reesimport line: 88*99e0aae7SDavid Rees 89*99e0aae7SDavid Rees``` 90*99e0aae7SDavid Reesimport "other.emb" as helper 91*99e0aae7SDavid Rees``` 92*99e0aae7SDavid Rees 93*99e0aae7SDavid Reesthen the type `Type` from `other.emb` may be referenced as `helper.Type`. 94*99e0aae7SDavid Rees 95*99e0aae7SDavid ReesThe `--import-dir` command-line flag tells Emboss which directories to search 96*99e0aae7SDavid Reesfor imported files; it may be specified multiple times. If no `--import-dir` is 97*99e0aae7SDavid Reesspecified, Emboss will search the current working directory. 98*99e0aae7SDavid Rees 99*99e0aae7SDavid Rees 100*99e0aae7SDavid Rees## Attributes 101*99e0aae7SDavid Rees 102*99e0aae7SDavid ReesAttributes are an extensible way of adding arbitrary information to a module, 103*99e0aae7SDavid Reestype, field, or enum value. Currently, only whitelisted attributes are allowed 104*99e0aae7SDavid Reesby the Emboss compiler, but this may change in the future. 105*99e0aae7SDavid Rees 106*99e0aae7SDavid ReesAttributes take a form like: 107*99e0aae7SDavid Rees 108*99e0aae7SDavid Rees``` 109*99e0aae7SDavid Rees[name: value] # name has value for the current entity. 110*99e0aae7SDavid Rees[$default name: value] # Default name to value for all sub-entities. 111*99e0aae7SDavid Rees[(backend) name: value] # Attribute for a specific back end. 112*99e0aae7SDavid Rees``` 113*99e0aae7SDavid Rees 114*99e0aae7SDavid Rees 115*99e0aae7SDavid Rees### `byte_order` 116*99e0aae7SDavid Rees 117*99e0aae7SDavid ReesThe `byte_order` attribute is used to specify the byte order of `bits` fields 118*99e0aae7SDavid Reesand of field with an atomic type, such as `UInt`. 119*99e0aae7SDavid Rees 120*99e0aae7SDavid Rees`byte_order` takes a string value, which must be either `"BigEndian"`, 121*99e0aae7SDavid Rees`"LittleEndian"`, or `"Null"`: 122*99e0aae7SDavid Rees 123*99e0aae7SDavid Rees``` 124*99e0aae7SDavid Rees[$default byte_order: "LittleEndian"] 125*99e0aae7SDavid Rees 126*99e0aae7SDavid Reesstruct Foo: 127*99e0aae7SDavid Rees [$default byte_order: "Null"] 128*99e0aae7SDavid Rees 129*99e0aae7SDavid Rees 0 [+4] UInt bar 130*99e0aae7SDavid Rees [byte_order: "BigEndian"] 131*99e0aae7SDavid Rees 132*99e0aae7SDavid Rees 4 [+4] bits: 133*99e0aae7SDavid Rees [byte_order: "LittleEndian"] 134*99e0aae7SDavid Rees 135*99e0aae7SDavid Rees 0 [+23] UInt baz 136*99e0aae7SDavid Rees 23 [+9] UInt qux 137*99e0aae7SDavid Rees 138*99e0aae7SDavid Rees 8 [+1] UInt froble 139*99e0aae7SDavid Rees``` 140*99e0aae7SDavid Rees 141*99e0aae7SDavid ReesA `$default` byte order may be set on a module or structure. 142*99e0aae7SDavid Rees 143*99e0aae7SDavid ReesThe `"BigEndian"` and `"LittleEndian"` byte orders set the byte order to big or 144*99e0aae7SDavid Reeslittle endian, respectively. That is, for little endian: 145*99e0aae7SDavid Rees 146*99e0aae7SDavid Rees``` 147*99e0aae7SDavid Rees byte 0 byte 1 byte 2 byte 3 148*99e0aae7SDavid Rees+--------+--------+--------+--------+ 149*99e0aae7SDavid Rees|76543210|76543210|76543210|76543210| 150*99e0aae7SDavid Rees+--------+--------+--------+--------+ 151*99e0aae7SDavid Rees ^ ^ ^ ^ ^ ^ ^ ^ 152*99e0aae7SDavid Rees 07 00 15 08 23 16 31 24 153*99e0aae7SDavid Rees ^^^^^^^^^^^^^^^ bit ^^^^^^^^^^^^^^^ 154*99e0aae7SDavid Rees``` 155*99e0aae7SDavid Rees 156*99e0aae7SDavid ReesAnd for big endian: 157*99e0aae7SDavid Rees 158*99e0aae7SDavid Rees``` 159*99e0aae7SDavid Rees byte 0 byte 1 byte 2 byte 3 160*99e0aae7SDavid Rees+--------+--------+--------+--------+ 161*99e0aae7SDavid Rees|76543210|76543210|76543210|76543210| 162*99e0aae7SDavid Rees+--------+--------+--------+--------+ 163*99e0aae7SDavid Rees ^ ^ ^ ^ ^ ^ ^ ^ 164*99e0aae7SDavid Rees 31 24 23 16 15 08 07 00 165*99e0aae7SDavid Rees ^^^^^^^^^^^^^^^ bit ^^^^^^^^^^^^^^^ 166*99e0aae7SDavid Rees``` 167*99e0aae7SDavid Rees 168*99e0aae7SDavid ReesThe `"Null"` byte order is used if no `byte_order` attribute is specified. 169*99e0aae7SDavid Rees`"Null"` indicates that the byte order is unknown; it is an error if a 170*99e0aae7SDavid Reesbyte-order-dependent field that is not exactly 8 bits has the `"Null"` byte 171*99e0aae7SDavid Reesorder. 172*99e0aae7SDavid Rees 173*99e0aae7SDavid Rees 174*99e0aae7SDavid Rees### `requires` 175*99e0aae7SDavid Rees 176*99e0aae7SDavid ReesThe `requires` attribute may be placed on an atomic field (e.g., type `UInt`, 177*99e0aae7SDavid Rees`Int`, `Flag`, etc.) to specify a predicate that values of that field must 178*99e0aae7SDavid Reessatisfy, or on a `struct` or `bits` to specify relationships between fields that 179*99e0aae7SDavid Reesmust be satisfied. 180*99e0aae7SDavid Rees 181*99e0aae7SDavid Rees``` 182*99e0aae7SDavid Reesstruct Foo: 183*99e0aae7SDavid Rees [requires: bar < qux] 184*99e0aae7SDavid Rees 185*99e0aae7SDavid Rees 0 [+4] UInt bar 186*99e0aae7SDavid Rees [requires: this <= 999_999_999] 187*99e0aae7SDavid Rees 188*99e0aae7SDavid Rees 4 [+4] UInt qux 189*99e0aae7SDavid Rees [requires: 100 <= this <= 1_000_000_000] 190*99e0aae7SDavid Rees 191*99e0aae7SDavid Rees let bar_plus_qux = bar + qux 192*99e0aae7SDavid Rees [requires: this >= 199] 193*99e0aae7SDavid Rees``` 194*99e0aae7SDavid Rees 195*99e0aae7SDavid ReesFor `[requires]` on a field, other fields may not be referenced, and the value 196*99e0aae7SDavid Reesof the current field must be referred to as `this`. 197*99e0aae7SDavid Rees 198*99e0aae7SDavid ReesFor `[requires]` on a `struct` or `bits`, any atomic field in the structure may 199*99e0aae7SDavid Reesbe referenced. 200*99e0aae7SDavid Rees 201*99e0aae7SDavid Rees 202*99e0aae7SDavid Rees### `(cpp) namespace` 203*99e0aae7SDavid Rees 204*99e0aae7SDavid ReesThe `namespace` attribute is used by the C++ back end to determine which 205*99e0aae7SDavid Reesnamespace to place the generated code in: 206*99e0aae7SDavid Rees 207*99e0aae7SDavid Rees``` 208*99e0aae7SDavid Rees[(cpp) namespace: "foo::bar::baz"] 209*99e0aae7SDavid Rees``` 210*99e0aae7SDavid Rees 211*99e0aae7SDavid ReesA leading `::` is allowed, but not required; the previous example could also be 212*99e0aae7SDavid Reeswritten as: 213*99e0aae7SDavid Rees 214*99e0aae7SDavid Rees``` 215*99e0aae7SDavid Rees[(cpp) namespace: "::foo::bar::baz"] 216*99e0aae7SDavid Rees``` 217*99e0aae7SDavid Rees 218*99e0aae7SDavid ReesInternally, Emboss will translate either of these into a nested `namespace foo { 219*99e0aae7SDavid Reesnamespace bar { namespace baz { ... } } }` wrapping the generated C++ code for 220*99e0aae7SDavid Reesthis module. 221*99e0aae7SDavid Rees 222*99e0aae7SDavid ReesThe `namespace` attribute may only be used at the module level; all structures 223*99e0aae7SDavid Reesand enums within a module will be placed in the same namespace. 224*99e0aae7SDavid Rees 225*99e0aae7SDavid Rees### `(cpp) enum_case` 226*99e0aae7SDavid Rees 227*99e0aae7SDavid ReesThe `enum_case` attribute can be specified for the C++ backend to specify 228*99e0aae7SDavid Reesin which case the enum values should be emitted to generated source. It does 229*99e0aae7SDavid Reesnot change the text representation, which always uses the original emboss 230*99e0aae7SDavid Reesdefinition name as the canonical name. 231*99e0aae7SDavid Rees 232*99e0aae7SDavid ReesCurrently, the supported cases are`SHOUTY_CASE` and `kCamelCase`. 233*99e0aae7SDavid Rees 234*99e0aae7SDavid ReesA `$default` enum case can be set on a module, struct, bits, or enum and 235*99e0aae7SDavid Reesapplies to all enum values within that module, struct, bits, or enum 236*99e0aae7SDavid Reesdefinition. 237*99e0aae7SDavid Rees 238*99e0aae7SDavid ReesFor example, to use `kCamelCase` by default for all enum values in a module: 239*99e0aae7SDavid Rees 240*99e0aae7SDavid Rees``` 241*99e0aae7SDavid Rees[$default enum_case: "kCamelCase"] 242*99e0aae7SDavid Rees``` 243*99e0aae7SDavid Rees 244*99e0aae7SDavid ReesThis will change enum names like `UPPER_CHANNEL_RANGE_LIMIT` to 245*99e0aae7SDavid Rees`kUpperChannelRangeLimit` in the C++ source for all enum values in the module. 246*99e0aae7SDavid ReesMultiple case names can be specified, which is especially useful when 247*99e0aae7SDavid Reestransitioning between two cases: 248*99e0aae7SDavid Rees 249*99e0aae7SDavid Rees``` 250*99e0aae7SDavid Rees[enum_case: "SHOUTY_CASE, kCamelCase"] 251*99e0aae7SDavid Rees``` 252*99e0aae7SDavid Rees 253*99e0aae7SDavid Rees### `text_output` 254*99e0aae7SDavid Rees 255*99e0aae7SDavid ReesThe `text_output` attribute may be attached to a `struct` or `bits` field to 256*99e0aae7SDavid Reescontrol whether or not the field is included when emitting the text format 257*99e0aae7SDavid Reesversion of the structure. For example: 258*99e0aae7SDavid Rees 259*99e0aae7SDavid Rees``` 260*99e0aae7SDavid Reesstruct SuppressedField: 261*99e0aae7SDavid Rees 0 [+1] UInt a 262*99e0aae7SDavid Rees 1 [+1] UInt b 263*99e0aae7SDavid Rees [text_output: "Skip"] 264*99e0aae7SDavid Rees``` 265*99e0aae7SDavid Rees 266*99e0aae7SDavid ReesThe text format output (as from `emboss::WriteToString()` in C++) would be of 267*99e0aae7SDavid Reesthe form: 268*99e0aae7SDavid Rees 269*99e0aae7SDavid Rees``` 270*99e0aae7SDavid Rees{ a: 1 } 271*99e0aae7SDavid Rees``` 272*99e0aae7SDavid Rees 273*99e0aae7SDavid Reesinstead of the default: 274*99e0aae7SDavid Rees 275*99e0aae7SDavid Rees``` 276*99e0aae7SDavid Rees{ a: 1, b: 2 } 277*99e0aae7SDavid Rees``` 278*99e0aae7SDavid Rees 279*99e0aae7SDavid ReesFor completeness, `[text_output: "Emit"]` may be used to explicitly specify that 280*99e0aae7SDavid Reesa field should be included in text output. 281*99e0aae7SDavid Rees 282*99e0aae7SDavid Rees 283*99e0aae7SDavid Rees### `external` specifier attributes 284*99e0aae7SDavid Rees 285*99e0aae7SDavid ReesThe `addressable_unit_size`, `type_requires`, `fixed_size_in_bits`, and 286*99e0aae7SDavid Rees`is_integer` attributes are used on `external` types to tell the compiler what 287*99e0aae7SDavid Reesit needs to know about the `external` types. They are currently 288*99e0aae7SDavid Reesunstable, and should only be used internally. 289*99e0aae7SDavid Rees 290*99e0aae7SDavid Rees 291*99e0aae7SDavid Rees## Type Definitions 292*99e0aae7SDavid Rees 293*99e0aae7SDavid ReesEmboss allows you to define structs, unions, bits, and enums, and uses externals 294*99e0aae7SDavid Reesto define "basic types." Types may be defined in any order, and may freely 295*99e0aae7SDavid Reesreference other types in the same module or any imported modules (including the 296*99e0aae7SDavid Reesimplicitly-imported prelude). 297*99e0aae7SDavid Rees 298*99e0aae7SDavid Rees### `struct` 299*99e0aae7SDavid Rees 300*99e0aae7SDavid ReesA `struct` defines a view of a sequence of bytes. Each field of a `struct` is a 301*99e0aae7SDavid Reesview of some particular subsequence of the `struct`'s bytes, whose 302*99e0aae7SDavid Reesinterpretation is determined by the field's type. 303*99e0aae7SDavid Rees 304*99e0aae7SDavid ReesFor example: 305*99e0aae7SDavid Rees 306*99e0aae7SDavid Rees``` 307*99e0aae7SDavid Reesstruct FramedMessage: 308*99e0aae7SDavid Rees -- A FramedMessage wraps a Message with magic bytes, lengths, and CRC. 309*99e0aae7SDavid Rees [$default byte_order: "LittleEndian"] 310*99e0aae7SDavid Rees 0 [+4] UInt magic_value 311*99e0aae7SDavid Rees 4 [+4] UInt header_length (h) 312*99e0aae7SDavid Rees 8 [+4] UInt message_length (m) 313*99e0aae7SDavid Rees h [+m] Message message 314*99e0aae7SDavid Rees h+m [+4] UInt crc32 315*99e0aae7SDavid Rees [byte_order: "BigEndian"] 316*99e0aae7SDavid Rees``` 317*99e0aae7SDavid Rees 318*99e0aae7SDavid ReesThe first line introduces the `struct` and gives it a name. This name may be 319*99e0aae7SDavid Reesused in field definitions to specify that the field has a structured type, and 320*99e0aae7SDavid Reesis used in the generated code. For example, to read the `message_length` from a 321*99e0aae7SDavid Reessequence of bytes in C++, you would construct a `FramedMessageView` over the 322*99e0aae7SDavid Reesbytes: 323*99e0aae7SDavid Rees 324*99e0aae7SDavid Rees```c++ 325*99e0aae7SDavid Rees// vector<uint8_t> bytes; 326*99e0aae7SDavid Reesauto framed_message_view = FramedMessageView(&bytes[0], bytes.size()); 327*99e0aae7SDavid Reesuint32_t message_length = framed_message_view.message_length().Read(); 328*99e0aae7SDavid Rees``` 329*99e0aae7SDavid Rees 330*99e0aae7SDavid Rees(Note that the `FramedMessageView` does not take ownership of the bytes: it only 331*99e0aae7SDavid Reesprovides a view of them.) 332*99e0aae7SDavid Rees 333*99e0aae7SDavid ReesEach field starts with a byte range (`0 [+4]`) that indicates *where* the field 334*99e0aae7SDavid Reessits in the struct. For example, the `magic_value` field covers the first four 335*99e0aae7SDavid Reesbytes of the struct. 336*99e0aae7SDavid Rees 337*99e0aae7SDavid ReesField locations *do not have to be constants*. In the example above, the 338*99e0aae7SDavid Rees`message` field starts at the end of the header (as determined by the 339*99e0aae7SDavid Rees`header_length` field) and covers `message_length` bytes. 340*99e0aae7SDavid Rees 341*99e0aae7SDavid ReesAfter the field's location is the field's *type*. The type determines how the 342*99e0aae7SDavid Reesfield's bytes are interpreted: the `header_length` field will be interpreted as 343*99e0aae7SDavid Reesan unsigned integer (`UInt`), while the `message` field is interpreted as a 344*99e0aae7SDavid Rees`Message` -- another `struct` type defined elsewhere. 345*99e0aae7SDavid Rees 346*99e0aae7SDavid ReesAfter the type is the field's *name*: this is a name used in the generated code 347*99e0aae7SDavid Reesto access that field, as in `framed_message_view.message_length()`. The name 348*99e0aae7SDavid Reesmay be followed by an optional *abbreviation*, like the `(h)` after 349*99e0aae7SDavid Rees`header_length`. The abbreviation can be used elsewhere in the `struct`, but is 350*99e0aae7SDavid Reesnot available in the generated code: `framed_message_view.h()` wouldn't compile. 351*99e0aae7SDavid Rees 352*99e0aae7SDavid ReesFinally, fields may have attributes and documentation, just like any other 353*99e0aae7SDavid ReesEmboss construct. 354*99e0aae7SDavid Rees 355*99e0aae7SDavid Rees 356*99e0aae7SDavid Rees#### `$next` 357*99e0aae7SDavid Rees 358*99e0aae7SDavid ReesThe keyword `$next` may be used in the offset expression of a physical field: 359*99e0aae7SDavid Rees 360*99e0aae7SDavid Rees``` 361*99e0aae7SDavid Reesstruct Foo: 362*99e0aae7SDavid Rees 0 [+4] UInt x 363*99e0aae7SDavid Rees $next [+2] UInt y 364*99e0aae7SDavid Rees $next [+1] UInt z 365*99e0aae7SDavid Rees $next [+4] UInt q 366*99e0aae7SDavid Rees``` 367*99e0aae7SDavid Rees 368*99e0aae7SDavid Rees`$next` translates to a built-in constant meaning "the end of the previous 369*99e0aae7SDavid Reesphysical field." In the example above, `y` will start at offset 4 (0 + 4), `z` 370*99e0aae7SDavid Reesstarts at offset 6 (4 + 2), and `q` at 7 (6 + 1). 371*99e0aae7SDavid Rees 372*99e0aae7SDavid Rees`$next` may be used in `bits` as well as `struct`s: 373*99e0aae7SDavid Rees 374*99e0aae7SDavid Rees``` 375*99e0aae7SDavid Reesbits Bar: 376*99e0aae7SDavid Rees 0 [+4] UInt x 377*99e0aae7SDavid Rees $next [+2] UInt y 378*99e0aae7SDavid Rees $next [+1] UInt z 379*99e0aae7SDavid Rees $next [+4] UInt q 380*99e0aae7SDavid Rees``` 381*99e0aae7SDavid Rees 382*99e0aae7SDavid ReesYou may use `$next` like a regular variable. For example, if you want to leave 383*99e0aae7SDavid Reesa two-byte gap between `z` and `q` (so that `q` starts at offset 9): 384*99e0aae7SDavid Rees 385*99e0aae7SDavid Rees``` 386*99e0aae7SDavid Reesstruct Foo: 387*99e0aae7SDavid Rees 0 [+4] UInt x 388*99e0aae7SDavid Rees $next [+2] UInt y 389*99e0aae7SDavid Rees $next [+1] UInt z 390*99e0aae7SDavid Rees $next+2 [+4] UInt q 391*99e0aae7SDavid Rees``` 392*99e0aae7SDavid Rees 393*99e0aae7SDavid Rees`$next` is particularly useful if your datasheet defines structures as lists of 394*99e0aae7SDavid Reesfields without offsets, or if you are translating from a C or C++ packed 395*99e0aae7SDavid Rees`struct`. 396*99e0aae7SDavid Rees 397*99e0aae7SDavid Rees 398*99e0aae7SDavid Rees#### Parameters 399*99e0aae7SDavid Rees 400*99e0aae7SDavid Rees`struct`s and `bits` can take runtime parameters: 401*99e0aae7SDavid Rees 402*99e0aae7SDavid Rees``` 403*99e0aae7SDavid Reesstruct Foo(x: Int:8, y: Int:8): 404*99e0aae7SDavid Rees 0 [+x] UInt:8[] xs 405*99e0aae7SDavid Rees x [+y] UInt:8[] ys 406*99e0aae7SDavid Rees 407*99e0aae7SDavid Reesenum Version: 408*99e0aae7SDavid Rees VERSION_1 = 10 409*99e0aae7SDavid Rees VERSION_2 = 20 410*99e0aae7SDavid Rees 411*99e0aae7SDavid Reesstruct Bar(version: Version): 412*99e0aae7SDavid Rees 0 [+1] UInt payload 413*99e0aae7SDavid Rees if payload == 1 && version == Version.VERSION_1: 414*99e0aae7SDavid Rees 1 [+10] OldPayload1 old_payload_1 415*99e0aae7SDavid Rees if payload == 1 && version == Version.VERSION_2: 416*99e0aae7SDavid Rees 1 [+12] NewPayload1 new_payload_1 417*99e0aae7SDavid Rees``` 418*99e0aae7SDavid Rees 419*99e0aae7SDavid ReesEach parameter must have the form *name`:` type*. Currently, the *type* can 420*99e0aae7SDavid Reesbe: 421*99e0aae7SDavid Rees 422*99e0aae7SDavid Rees* <code>UInt:*n*</code>, where *`n`* is a number from 1 to 64, inclusive. 423*99e0aae7SDavid Rees* <code>Int:*n*</code>, where *`n`* is a number from 1 to 64, inclusive. 424*99e0aae7SDavid Rees* The name of an Emboss `enum` type. 425*99e0aae7SDavid Rees 426*99e0aae7SDavid Rees`UInt`- and `Int`-typed parameters are integers with the corresponding range: 427*99e0aae7SDavid Reesfor example, an `Int:4` parameter can have any integer value from -8 to +7. 428*99e0aae7SDavid Rees 429*99e0aae7SDavid Rees`enum`-typed parameters can take any value in the `enum`'s native range. Note 430*99e0aae7SDavid Reesthat Emboss `enum`s are *open*, so unnamed values are allowed. 431*99e0aae7SDavid Rees 432*99e0aae7SDavid ReesParameterized structures can be included in other structures by passing their 433*99e0aae7SDavid Reesparameters: 434*99e0aae7SDavid Rees 435*99e0aae7SDavid Rees``` 436*99e0aae7SDavid Reesstruct Baz: 437*99e0aae7SDavid Rees 0 [+1] Version version 438*99e0aae7SDavid Rees 1 [+1] UInt:8 size 439*99e0aae7SDavid Rees 2 [+size] Bar(version) bar 440*99e0aae7SDavid Rees``` 441*99e0aae7SDavid Rees 442*99e0aae7SDavid Rees 443*99e0aae7SDavid Rees#### Virtual "Fields" 444*99e0aae7SDavid Rees 445*99e0aae7SDavid ReesIt is possible to define a non-physical "field" whose value is an expression: 446*99e0aae7SDavid Rees 447*99e0aae7SDavid Rees``` 448*99e0aae7SDavid Reesstruct Foo: 449*99e0aae7SDavid Rees 0 [+4] UInt bar 450*99e0aae7SDavid Rees let two_bar = 2 * bar 451*99e0aae7SDavid Rees``` 452*99e0aae7SDavid Rees 453*99e0aae7SDavid ReesThese virtual "fields" may be used like any other field in most circumstances: 454*99e0aae7SDavid Rees 455*99e0aae7SDavid Rees``` 456*99e0aae7SDavid Reesstruct Bar: 457*99e0aae7SDavid Rees 0 [+4] Foo foo 458*99e0aae7SDavid Rees if foo.two_bar < 100: 459*99e0aae7SDavid Rees foo.two_bar [+4] UInt uint_at_offset_two_bar 460*99e0aae7SDavid Rees``` 461*99e0aae7SDavid Rees 462*99e0aae7SDavid ReesVirtual fields may be integers, booleans, or an enum: 463*99e0aae7SDavid Rees 464*99e0aae7SDavid Rees``` 465*99e0aae7SDavid Reesenum Size: 466*99e0aae7SDavid Rees SMALL = 1 467*99e0aae7SDavid Rees LARGE = 2 468*99e0aae7SDavid Rees 469*99e0aae7SDavid Reesstruct Qux: 470*99e0aae7SDavid Rees 0 [+4] UInt x 471*99e0aae7SDavid Rees let x_is_big = x > 100 472*99e0aae7SDavid Rees let x_size = x_is_big ? Size.LARGE : Size.SMALL 473*99e0aae7SDavid Rees``` 474*99e0aae7SDavid Rees 475*99e0aae7SDavid ReesWhen a virtual field has a constant value, you may refer to it using its type: 476*99e0aae7SDavid Rees 477*99e0aae7SDavid Rees``` 478*99e0aae7SDavid Reesstruct Foo: 479*99e0aae7SDavid Rees let foo_offset = 0x120 480*99e0aae7SDavid Rees 0 [+4] UInt foo 481*99e0aae7SDavid Rees 482*99e0aae7SDavid Reesstruct Bar: 483*99e0aae7SDavid Rees Foo.foo_offset [+4] Foo foo 484*99e0aae7SDavid Rees``` 485*99e0aae7SDavid Rees 486*99e0aae7SDavid ReesThis does not work for non-constant virtual fields: 487*99e0aae7SDavid Rees 488*99e0aae7SDavid Rees``` 489*99e0aae7SDavid Reesstruct Foo: 490*99e0aae7SDavid Rees 0 [+4] UInt foo 491*99e0aae7SDavid Rees let foo_offset = foo + 10 492*99e0aae7SDavid Rees 493*99e0aae7SDavid Reesstruct Bar: 494*99e0aae7SDavid Rees Foo.foo_offset [+4] Foo foo # Won't compile. 495*99e0aae7SDavid Rees``` 496*99e0aae7SDavid Rees 497*99e0aae7SDavid ReesNote that, in some cases, you *must* use Type.field, and not field.field: 498*99e0aae7SDavid Rees 499*99e0aae7SDavid Rees``` 500*99e0aae7SDavid Reesstruct Foo: 501*99e0aae7SDavid Rees 0 [+4] UInt foo 502*99e0aae7SDavid Rees let foo_offset = 10 503*99e0aae7SDavid Rees 504*99e0aae7SDavid Reesstruct Bar: 505*99e0aae7SDavid Rees # Won't compile: foo.foo_offset depends on foo, which depends on 506*99e0aae7SDavid Rees # foo.foo_offset. 507*99e0aae7SDavid Rees foo.foo_offset [+4] Foo foo 508*99e0aae7SDavid Rees 509*99e0aae7SDavid Rees # Will compile: Foo.foo_offset is a static constant. 510*99e0aae7SDavid Rees Foo.foo_offset [+4] Foo foo 511*99e0aae7SDavid Rees``` 512*99e0aae7SDavid Rees 513*99e0aae7SDavid ReesThis limitation may be lifted in the future, but it has no practical effect. 514*99e0aae7SDavid Rees 515*99e0aae7SDavid Rees 516*99e0aae7SDavid Rees##### Aliases 517*99e0aae7SDavid Rees 518*99e0aae7SDavid ReesVirtual fields of the form `let x = y` or `let x = y.z.q` are allowed even when 519*99e0aae7SDavid Rees`y` or `q` are composite fields. Virtuals of this form are considered to be 520*99e0aae7SDavid Rees*aliases* of the referred field; in generated code, they may be written as well 521*99e0aae7SDavid Reesas read, and writing through them is equivalent to writing to the aliased field. 522*99e0aae7SDavid Rees 523*99e0aae7SDavid Rees 524*99e0aae7SDavid Rees##### Simple Transforms 525*99e0aae7SDavid Rees 526*99e0aae7SDavid ReesVirtual fields of the forms `let x1 = y + 1`, `let x2 = 2 + y`, `let x3 = y - 527*99e0aae7SDavid Rees3`, and `let x4 = 4 - y`, where `y` is a writeable field, will be writeable in 528*99e0aae7SDavid Reesthe generated code. When writing through these fields, the transformed field 529*99e0aae7SDavid Reeswill be set to an appropriate value. For example, writing `5` to `x1` will 530*99e0aae7SDavid Reesactually write `4` to `y`, and writing `6` to `x4` will write `-2` to `y`. This 531*99e0aae7SDavid Reescan be used to model fields whose raw values should be adjusted by some constant 532*99e0aae7SDavid Reesvalue, e.g.: 533*99e0aae7SDavid Rees 534*99e0aae7SDavid Rees``` 535*99e0aae7SDavid Reesstruct PosixDate: 536*99e0aae7SDavid Rees 0 [+1] Int raw_year 537*99e0aae7SDavid Rees -- Number of years since 1900. 538*99e0aae7SDavid Rees 539*99e0aae7SDavid Rees let year = raw_year + 1900 540*99e0aae7SDavid Rees -- Gregorian year number. 541*99e0aae7SDavid Rees 542*99e0aae7SDavid Rees 1 [+1] Int zero_based_month 543*99e0aae7SDavid Rees -- Month number, from 0-11. Good for looking up a month name in a table. 544*99e0aae7SDavid Rees 545*99e0aae7SDavid Rees let month = zero_based_month + 1 546*99e0aae7SDavid Rees -- Month number, from 1-12. Good for printing directly. 547*99e0aae7SDavid Rees 548*99e0aae7SDavid Rees 2 [+1] Int day 549*99e0aae7SDavid Rees -- Day number, one-based. 550*99e0aae7SDavid Rees``` 551*99e0aae7SDavid Rees 552*99e0aae7SDavid Rees 553*99e0aae7SDavid Rees#### Subtypes 554*99e0aae7SDavid Rees 555*99e0aae7SDavid ReesA `struct` definition may contain other type definitions: 556*99e0aae7SDavid Rees 557*99e0aae7SDavid Rees``` 558*99e0aae7SDavid Reesstruct Foo: 559*99e0aae7SDavid Rees struct Bar: 560*99e0aae7SDavid Rees 0 [+2] UInt baz 561*99e0aae7SDavid Rees 2 [+2] UInt qux 562*99e0aae7SDavid Rees 563*99e0aae7SDavid Rees 0 [+4] Bar bar 564*99e0aae7SDavid Rees 4 [+4] Bar bar2 565*99e0aae7SDavid Rees``` 566*99e0aae7SDavid Rees 567*99e0aae7SDavid Rees 568*99e0aae7SDavid Rees#### Conditional fields 569*99e0aae7SDavid Rees 570*99e0aae7SDavid ReesA `struct` field may have fields which are only present under some 571*99e0aae7SDavid Reescircumstances. For example: 572*99e0aae7SDavid Rees 573*99e0aae7SDavid Rees``` 574*99e0aae7SDavid Reesstruct FramedMessage: 575*99e0aae7SDavid Rees 0 [+4] enum message_id: 576*99e0aae7SDavid Rees TYPE1 = 1 577*99e0aae7SDavid Rees TYPE2 = 2 578*99e0aae7SDavid Rees 579*99e0aae7SDavid Rees if message_id == MessageId.TYPE1: 580*99e0aae7SDavid Rees 4 [+16] Type1Message type_1_message 581*99e0aae7SDavid Rees 582*99e0aae7SDavid Rees if message_id == MessageId.TYPE2: 583*99e0aae7SDavid Rees 4 [+8] Type2Message type_2_message 584*99e0aae7SDavid Rees``` 585*99e0aae7SDavid Rees 586*99e0aae7SDavid ReesThe `type_1_message` field will only be available if `message_id` is `TYPE1`, 587*99e0aae7SDavid Reesand similarly the `type_2_message` field will only be available if `message_id` 588*99e0aae7SDavid Reesis `TYPE2`. If `message_id` is some other value, then neither field will be 589*99e0aae7SDavid Reesavailable. 590*99e0aae7SDavid Rees 591*99e0aae7SDavid Rees 592*99e0aae7SDavid Rees#### Inline `struct` 593*99e0aae7SDavid Rees 594*99e0aae7SDavid ReesIt is possible to define a `struct` inline in a `struct` field. For example: 595*99e0aae7SDavid Rees 596*99e0aae7SDavid Rees``` 597*99e0aae7SDavid Reesstruct Message: 598*99e0aae7SDavid Rees [$default byte_order: "BigEndian"] 599*99e0aae7SDavid Rees 0 [+4] UInt message_length 600*99e0aae7SDavid Rees 4 [+4] struct payload: 601*99e0aae7SDavid Rees 0 [+1] UInt incoming 602*99e0aae7SDavid Rees 2 [+2] UInt scale_factor 603*99e0aae7SDavid Rees``` 604*99e0aae7SDavid Rees 605*99e0aae7SDavid ReesThis is equivalent to: 606*99e0aae7SDavid Rees 607*99e0aae7SDavid Rees``` 608*99e0aae7SDavid Reesstruct Message: 609*99e0aae7SDavid Rees [$default byte_order: "BigEndian"] 610*99e0aae7SDavid Rees 611*99e0aae7SDavid Rees struct Payload: 612*99e0aae7SDavid Rees 0 [+1] UInt incoming 613*99e0aae7SDavid Rees 2 [+2] UInt scale_factor 614*99e0aae7SDavid Rees 615*99e0aae7SDavid Rees 0 [+4] UInt message_length 616*99e0aae7SDavid Rees 4 [+4] Payload payload 617*99e0aae7SDavid Rees``` 618*99e0aae7SDavid Rees 619*99e0aae7SDavid ReesThis can be useful as a way to group related fields together. 620*99e0aae7SDavid Rees 621*99e0aae7SDavid Rees 622*99e0aae7SDavid Rees#### Using `struct` to define a C-like `union` 623*99e0aae7SDavid Rees 624*99e0aae7SDavid ReesEmboss doesn't support C-like `union`s directly via built in type 625*99e0aae7SDavid Reesdefinitions. However, you can use Emboss's overlapping fields feature to 626*99e0aae7SDavid Reeseffectively create a `union`: 627*99e0aae7SDavid Rees 628*99e0aae7SDavid Rees``` 629*99e0aae7SDavid Reesstruct Foo: 630*99e0aae7SDavid Rees 0 [+1] UInt a 631*99e0aae7SDavid Rees 0 [+2] UInt b 632*99e0aae7SDavid Rees 0 [+4] UInt c 633*99e0aae7SDavid Rees``` 634*99e0aae7SDavid Rees 635*99e0aae7SDavid Rees 636*99e0aae7SDavid Rees#### Automatically-Generated Fields 637*99e0aae7SDavid Rees 638*99e0aae7SDavid ReesA `struct` will have `$size_in_bytes`, `$max_size_in_bytes`, and 639*99e0aae7SDavid Rees`$min_size_in_bytes` virtual field automatically generated. These virtual field 640*99e0aae7SDavid Reescan be referenced inside the Emboss language just like any other virtual field: 641*99e0aae7SDavid Rees 642*99e0aae7SDavid Rees``` 643*99e0aae7SDavid Reesstruct Inner: 644*99e0aae7SDavid Rees 0 [+4] UInt field_a 645*99e0aae7SDavid Rees 4 [+4] UInt field_b 646*99e0aae7SDavid Rees 647*99e0aae7SDavid Reesstruct Outer: 648*99e0aae7SDavid Rees 0 [+1] UInt message_type 649*99e0aae7SDavid Rees if message_type == 4: 650*99e0aae7SDavid Rees 4 [+Inner.$size_in_bytes] Inner payload 651*99e0aae7SDavid Rees``` 652*99e0aae7SDavid Rees 653*99e0aae7SDavid Rees 654*99e0aae7SDavid Rees##### `$size_in_bytes` {#size-in-bytes} 655*99e0aae7SDavid Rees 656*99e0aae7SDavid ReesAn Emboss `struct` has an *intrinsic* size, which is the size required to hold 657*99e0aae7SDavid Reesevery field in the `struct`, regardless of how many bytes are in the buffer that 658*99e0aae7SDavid Reesbacks the `struct`. For example: 659*99e0aae7SDavid Rees 660*99e0aae7SDavid Rees``` 661*99e0aae7SDavid Reesstruct FixedSize: 662*99e0aae7SDavid Rees 0 [+4] UInt long_field 663*99e0aae7SDavid Rees 4 [+2] UInt short_field 664*99e0aae7SDavid Rees``` 665*99e0aae7SDavid Rees 666*99e0aae7SDavid ReesIn this case, `FixedSize.$size_in_bytes` will always be `6`, even if a 667*99e0aae7SDavid Rees`FixedSize` is placed in a larger field: 668*99e0aae7SDavid Rees 669*99e0aae7SDavid Rees``` 670*99e0aae7SDavid Reesstruct Envelope: 671*99e0aae7SDavid Rees # padded_payload.$size_in_bytes == FixedSize.$size_in_bytes == 6 672*99e0aae7SDavid Rees 0 [+8] FixedSize padded_payload 673*99e0aae7SDavid Rees``` 674*99e0aae7SDavid Rees 675*99e0aae7SDavid ReesThe intrinsic size of a `struct` might not be constant: 676*99e0aae7SDavid Rees 677*99e0aae7SDavid Rees``` 678*99e0aae7SDavid Reesstruct DynamicallySizedField: 679*99e0aae7SDavid Rees 0 [+1] UInt length 680*99e0aae7SDavid Rees 1 [+length] UInt:8[] payload 681*99e0aae7SDavid Rees # $size_in_bytes == 1 + length 682*99e0aae7SDavid Rees 683*99e0aae7SDavid Reesstruct DynamicallyPlacedField: 684*99e0aae7SDavid Rees 0 [+1] UInt offset 685*99e0aae7SDavid Rees offset [+1] UInt payload 686*99e0aae7SDavid Rees # $size_in_bytes == offset + 1 687*99e0aae7SDavid Rees 688*99e0aae7SDavid Reesstruct OptionalField: 689*99e0aae7SDavid Rees 0 [+1] UInt version 690*99e0aae7SDavid Rees if version > 3: 691*99e0aae7SDavid Rees 1 [+1] UInt optional_field 692*99e0aae7SDavid Rees # $size_in_bytes == (version > 3 ? 2 : 1) 693*99e0aae7SDavid Rees``` 694*99e0aae7SDavid Rees 695*99e0aae7SDavid ReesIf the intrinsic size is dynamic, it can still be read dynamically from a field: 696*99e0aae7SDavid Rees 697*99e0aae7SDavid Rees``` 698*99e0aae7SDavid Reesstruct Envelope2: 699*99e0aae7SDavid Rees 0 [+1] UInt payload_size 700*99e0aae7SDavid Rees 1 [+payload_size] DynamicallySizedField payload 701*99e0aae7SDavid Rees let padding_bytes = payload_size - payload.$size_in_bytes 702*99e0aae7SDavid Rees``` 703*99e0aae7SDavid Rees 704*99e0aae7SDavid Rees 705*99e0aae7SDavid Rees##### `$max_size_in_bytes` {#max-size-in-bytes} 706*99e0aae7SDavid Rees 707*99e0aae7SDavid ReesThe `$max_size_in_bytes` virtual field is a constant value that is at least as 708*99e0aae7SDavid Reeslarge as the largest possible value for `$size_in_bytes`. In most cases, it 709*99e0aae7SDavid Reeswill exactly equal the largest possible message size, but it is possible to 710*99e0aae7SDavid Reesoutsmart Emboss's bounds checker. 711*99e0aae7SDavid Rees 712*99e0aae7SDavid Rees``` 713*99e0aae7SDavid Reesstruct DynamicallySizedStruct: 714*99e0aae7SDavid Rees 0 [+1] UInt length 715*99e0aae7SDavid Rees 1 [+length] UInt:8[] payload 716*99e0aae7SDavid Rees 717*99e0aae7SDavid Reesstruct PaddedContainer: 718*99e0aae7SDavid Rees 0 [+DynamicallySizedStruct.$max_size_in_bytes] DynamicallySizedStruct s 719*99e0aae7SDavid Rees # s will be 256 bytes long. 720*99e0aae7SDavid Rees``` 721*99e0aae7SDavid Rees 722*99e0aae7SDavid Rees 723*99e0aae7SDavid Rees##### `$min_size_in_bytes` {#min-size-in-bytes} 724*99e0aae7SDavid Rees 725*99e0aae7SDavid ReesThe `$min_size_in_bytes` virtual field is a constant value that is no larger 726*99e0aae7SDavid Reesthan the smallest possible value for `$size_in_bytes`. In most cases, it will 727*99e0aae7SDavid Reesexactly equal the smallest possible message size, but it is possible to 728*99e0aae7SDavid Reesoutsmart Emboss's bounds checker. 729*99e0aae7SDavid Rees 730*99e0aae7SDavid Rees``` 731*99e0aae7SDavid Reesstruct DynamicallySizedStruct: 732*99e0aae7SDavid Rees 0 [+1] UInt length 733*99e0aae7SDavid Rees 1 [+length] UInt:8[] payload 734*99e0aae7SDavid Rees 735*99e0aae7SDavid Reesstruct PaddedContainer: 736*99e0aae7SDavid Rees 0 [+DynamicallySizedStruct.$min_size_in_bytes] DynamicallySizedStruct s 737*99e0aae7SDavid Rees # s will be 1 byte long. 738*99e0aae7SDavid Rees``` 739*99e0aae7SDavid Rees 740*99e0aae7SDavid Rees 741*99e0aae7SDavid Rees### `enum` 742*99e0aae7SDavid Rees 743*99e0aae7SDavid ReesAn `enum` defines a set of named integers. 744*99e0aae7SDavid Rees 745*99e0aae7SDavid Rees``` 746*99e0aae7SDavid Reesenum Color: 747*99e0aae7SDavid Rees BLACK = 0 748*99e0aae7SDavid Rees RED = 1 749*99e0aae7SDavid Rees GREEN = 2 750*99e0aae7SDavid Rees YELLOW = 3 751*99e0aae7SDavid Rees BLUE = 4 752*99e0aae7SDavid Rees MAGENTA = 5 753*99e0aae7SDavid Rees CYAN = 6 754*99e0aae7SDavid Rees WHITE = 7 755*99e0aae7SDavid Rees 756*99e0aae7SDavid Reesstruct PaletteEntry: 757*99e0aae7SDavid Rees 0 [+1] UInt id 758*99e0aae7SDavid Rees 1 [+1] Color color 759*99e0aae7SDavid Rees``` 760*99e0aae7SDavid Rees 761*99e0aae7SDavid ReesEnum values are always read the same way as `Int` or `UInt` -- that is, as an 762*99e0aae7SDavid Reesunsigned integer or as a 2's-complement signed integer, depending on whether the 763*99e0aae7SDavid Rees`enum` contains any negative values or not. 764*99e0aae7SDavid Rees 765*99e0aae7SDavid ReesEnum values do not have to be contiguous, and may repeat: 766*99e0aae7SDavid Rees 767*99e0aae7SDavid Rees``` 768*99e0aae7SDavid Reesenum Baud: 769*99e0aae7SDavid Rees B300 = 300 770*99e0aae7SDavid Rees B600 = 600 771*99e0aae7SDavid Rees B1200 = 1200 772*99e0aae7SDavid Rees STANDARD = 1200 773*99e0aae7SDavid Rees``` 774*99e0aae7SDavid Rees 775*99e0aae7SDavid ReesAll values in a single `enum` must either be between -9223372036854775808 776*99e0aae7SDavid Rees(-2^63) and 9223372036854775807 (2^(63)-1), inclusive, or between 0 and 777*99e0aae7SDavid Rees18446744073709551615 (2^(64)-1), inclusive. 778*99e0aae7SDavid Rees 779*99e0aae7SDavid ReesIt is valid to have an `enum` field that is too small to contain some values in 780*99e0aae7SDavid Reesthe `enum`: 781*99e0aae7SDavid Rees 782*99e0aae7SDavid Rees``` 783*99e0aae7SDavid Reesenum LittleAndBig: 784*99e0aae7SDavid Rees LITTLE = 1 785*99e0aae7SDavid Rees BIG = 0x1_0000_0000 786*99e0aae7SDavid Rees 787*99e0aae7SDavid Reesstruct LittleOnly: 788*99e0aae7SDavid Rees 0 [+1] LittleAndBig:8 little_only # Too small to hold LittleAndBig.BIG 789*99e0aae7SDavid Rees``` 790*99e0aae7SDavid Rees 791*99e0aae7SDavid ReesEmboss `enum`s are *open*: they may take values that are not defined in the 792*99e0aae7SDavid Rees`.emb`, as long as those values are in range. The `is_signed` and 793*99e0aae7SDavid Rees`maximum_bits` attributes, below, may be used to control the allowed range of 794*99e0aae7SDavid Reesvalues. 795*99e0aae7SDavid Rees 796*99e0aae7SDavid Rees 797*99e0aae7SDavid Rees#### `is_signed` Attribute 798*99e0aae7SDavid Rees 799*99e0aae7SDavid ReesThe attribute `is_signed` may be used to explicitly specify whether an `enum` 800*99e0aae7SDavid Reesis signed or unsigned. Normally, an `enum` is signed if there is at least one 801*99e0aae7SDavid Reesnegative value, and unsigned otherwise, but this behavior can be overridden: 802*99e0aae7SDavid Rees 803*99e0aae7SDavid Rees``` 804*99e0aae7SDavid Reesenum ExplicitlySigned: 805*99e0aae7SDavid Rees [is_signed: true] 806*99e0aae7SDavid Rees POSITIVE = 10 807*99e0aae7SDavid Rees``` 808*99e0aae7SDavid Rees 809*99e0aae7SDavid Rees 810*99e0aae7SDavid Rees#### `maximum_bits` Attribute 811*99e0aae7SDavid Rees 812*99e0aae7SDavid ReesThe attribute `maximum_bits` may be used to specify the *maximum* width of an 813*99e0aae7SDavid Rees`enum`: fields of `enum` type may be smaller than `maximum_bits`, but never 814*99e0aae7SDavid Reeslarger: 815*99e0aae7SDavid Rees 816*99e0aae7SDavid Rees``` 817*99e0aae7SDavid Reesenum ExplicitlySized: 818*99e0aae7SDavid Rees [maximum_bits: 32] 819*99e0aae7SDavid Rees MAX_VALUE = 0xffff_ffff 820*99e0aae7SDavid Rees 821*99e0aae7SDavid Reesstruct Foo: 822*99e0aae7SDavid Rees 0 [+4] ExplicitlySized four_bytes # 32-bit is fine 823*99e0aae7SDavid Rees #4 [+8] ExplicitlySized eight_bytes # 64-bit field would be an error 824*99e0aae7SDavid Rees``` 825*99e0aae7SDavid Rees 826*99e0aae7SDavid ReesIf not specified, `maximum_bits` defaults to `64`. 827*99e0aae7SDavid Rees 828*99e0aae7SDavid ReesThis also allows back end code generators to use smaller types for `enum`s, in 829*99e0aae7SDavid Reessome cases. 830*99e0aae7SDavid Rees 831*99e0aae7SDavid Rees 832*99e0aae7SDavid Rees#### Inline `enum` 833*99e0aae7SDavid Rees 834*99e0aae7SDavid ReesIt is possible to provide an enum definition directly in a field definition in a 835*99e0aae7SDavid Rees`struct` or `bits`: 836*99e0aae7SDavid Rees 837*99e0aae7SDavid Rees``` 838*99e0aae7SDavid Reesstruct TurnSpecification: 839*99e0aae7SDavid Rees 0 [+1] UInt degrees 840*99e0aae7SDavid Rees 1 [+1] enum direction: 841*99e0aae7SDavid Rees LEFT = 0 842*99e0aae7SDavid Rees RIGHT = 1 843*99e0aae7SDavid Rees``` 844*99e0aae7SDavid Rees 845*99e0aae7SDavid ReesThis example creates a nested `enum` `TurnSpecification.Direction`, exactly as 846*99e0aae7SDavid Reesif it were written: 847*99e0aae7SDavid Rees 848*99e0aae7SDavid Rees``` 849*99e0aae7SDavid Reesstruct TurnSpecification: 850*99e0aae7SDavid Rees enum Direction: 851*99e0aae7SDavid Rees LEFT = 0 852*99e0aae7SDavid Rees RIGHT = 1 853*99e0aae7SDavid Rees 854*99e0aae7SDavid Rees 0 [+1] UInt degrees 855*99e0aae7SDavid Rees 1 [+1] Direction direction 856*99e0aae7SDavid Rees``` 857*99e0aae7SDavid Rees 858*99e0aae7SDavid ReesThis can be useful when a particular `enum` is short and only used in one place. 859*99e0aae7SDavid Rees 860*99e0aae7SDavid ReesNote that `maximum_bits` and `is_signed` cannot be used on an inline `enum`. 861*99e0aae7SDavid ReesIf you need to use either of these attributes, make a separate `enum`. 862*99e0aae7SDavid Rees 863*99e0aae7SDavid Rees 864*99e0aae7SDavid Rees### `bits` 865*99e0aae7SDavid Rees 866*99e0aae7SDavid ReesA `bits` defines a view of an ordered sequence of bits. Each field is a view of 867*99e0aae7SDavid Reessome particular subsequence of the `bits`'s bits, whose interpretation is 868*99e0aae7SDavid Reesdetermined by the field's type. 869*99e0aae7SDavid Rees 870*99e0aae7SDavid ReesThe structure of a `bits` definition is very similar to a `struct`, except that 871*99e0aae7SDavid Reesa `struct` provides a structured view of bytes, where a `bits` provides a 872*99e0aae7SDavid Reesstructured view of bits. Fields in a `bits` must have bit-oriented types (such 873*99e0aae7SDavid Reesas other `bits`, `UInt`, `Bcd`, `Flag`). Byte-oriented types, such as 874*99e0aae7SDavid Rees`struct`s, may not be embedded in a `bits`. 875*99e0aae7SDavid Rees 876*99e0aae7SDavid ReesFor example: 877*99e0aae7SDavid Rees 878*99e0aae7SDavid Rees``` 879*99e0aae7SDavid Reesbits ControlRegister: 880*99e0aae7SDavid Rees -- The `ControlRegister` holds basic control values. 881*99e0aae7SDavid Rees 882*99e0aae7SDavid Rees 4 [+12] UInt horizontal_start_offset 883*99e0aae7SDavid Rees -- The number of pixel clock ticks to wait after the start of a line 884*99e0aae7SDavid Rees -- before starting to draw pixel data. 885*99e0aae7SDavid Rees 886*99e0aae7SDavid Rees 3 [+1] Flag horizontal_overscan_disable 887*99e0aae7SDavid Rees -- If set, the electron gun will be disabled during the overscan period, 888*99e0aae7SDavid Rees -- otherwise the overscan color will be used. 889*99e0aae7SDavid Rees 890*99e0aae7SDavid Rees 0 [+3] UInt horizontal_overscan_color 891*99e0aae7SDavid Rees -- The palette index of the overscan color to use. 892*99e0aae7SDavid Rees 893*99e0aae7SDavid Reesstruct RegisterPage: 894*99e0aae7SDavid Rees -- The registers of the BGA (Bogus Graphics Array) card. 895*99e0aae7SDavid Rees 896*99e0aae7SDavid Rees 0 [+2] ControlRegister control_register 897*99e0aae7SDavid Rees [byte_order: "LittleEndian"] 898*99e0aae7SDavid Rees``` 899*99e0aae7SDavid Rees 900*99e0aae7SDavid ReesThe first line introduces the `bits` and gives it a name. This name may be 901*99e0aae7SDavid Reesused in field definitions to specify that the field has a structured type, and 902*99e0aae7SDavid Reesis used in the generated code. 903*99e0aae7SDavid Rees 904*99e0aae7SDavid ReesFor example, to write a `horizontal_overscan_color` of 7 to a pair of bytes in 905*99e0aae7SDavid ReesC++, you would use: 906*99e0aae7SDavid Rees 907*99e0aae7SDavid Rees```c++ 908*99e0aae7SDavid Rees// vector<uint8_t> bytes; 909*99e0aae7SDavid Reesauto register_page_view = RegisterPageWriter(&bytes[0], bytes.size()); 910*99e0aae7SDavid Reesregister_page_view.control_register().horizontal_overscan_color().Write(7); 911*99e0aae7SDavid Rees``` 912*99e0aae7SDavid Rees 913*99e0aae7SDavid ReesSimilar to `struct`, each field starts with a *bit* range (`4 [+12]`) that 914*99e0aae7SDavid Reesindicates which bits it covers. For example, the `horizontal_overscan_disable` 915*99e0aae7SDavid Reesfield only covers bit 3. Bit 0 always corresponds to the lowest-order bit the 916*99e0aae7SDavid Reesbitfield; that is, if a `UInt` covers the same bits as the `bits` construct, 917*99e0aae7SDavid Reesthen bit 0 in the `bits` will be the same as the `UInt` mod 2. This is often, 918*99e0aae7SDavid Reesbut not always, how bits are numbered in protocol specifications. 919*99e0aae7SDavid Rees 920*99e0aae7SDavid ReesAfter the field's location is the field's *type*. The type determines how the 921*99e0aae7SDavid Reesfield's bits are interpreted: typical choices are `UInt` (for unsigned 922*99e0aae7SDavid Reesintegers), `Flag` (for boolean flags), and `enum`s. Other `bits` may also be 923*99e0aae7SDavid Reesused, as well as any `external` types declared with `[addressable_unit_size: 924*99e0aae7SDavid Rees1]`. 925*99e0aae7SDavid Rees 926*99e0aae7SDavid ReesFields may have attributes and documentation, just like any other Emboss 927*99e0aae7SDavid Reesconstruct. 928*99e0aae7SDavid Rees 929*99e0aae7SDavid ReesIn generated code, reading or writing any field of a `bits` construct will cause 930*99e0aae7SDavid Reesthe entire field to be read or written -- something to keep in mind when reading 931*99e0aae7SDavid Reesor writing a memory-mapped register space. 932*99e0aae7SDavid Rees 933*99e0aae7SDavid Rees 934*99e0aae7SDavid Rees#### Anonymous `bits` 935*99e0aae7SDavid Rees 936*99e0aae7SDavid ReesIt is possible to use an anonymous `bits` definition directly in a `struct`; 937*99e0aae7SDavid Reesfor example: 938*99e0aae7SDavid Rees 939*99e0aae7SDavid Rees``` 940*99e0aae7SDavid Reesstruct Message: 941*99e0aae7SDavid Rees [$default byte_order: "BigEndian"] 942*99e0aae7SDavid Rees 0 [+4] UInt message_length 943*99e0aae7SDavid Rees 4 [+4] bits: 944*99e0aae7SDavid Rees 0 [+1] Flag incoming 945*99e0aae7SDavid Rees 1 [+1] Flag last_fragment 946*99e0aae7SDavid Rees 2 [+4] UInt scale_factor 947*99e0aae7SDavid Rees 31 [+1] Flag error 948*99e0aae7SDavid Rees``` 949*99e0aae7SDavid Rees 950*99e0aae7SDavid ReesIn this case, the fields of the `bits` will be treated as though they are fields 951*99e0aae7SDavid Reesof the outer struct. 952*99e0aae7SDavid Rees 953*99e0aae7SDavid Rees 954*99e0aae7SDavid Rees#### Inline `bits` 955*99e0aae7SDavid Rees 956*99e0aae7SDavid ReesLike `enum`s, it is also possible to define a named `bits` inline in a `struct` 957*99e0aae7SDavid Reesor `bits`. For example: 958*99e0aae7SDavid Rees 959*99e0aae7SDavid Rees``` 960*99e0aae7SDavid Reesstruct Message: 961*99e0aae7SDavid Rees [$default byte_order: "BigEndian"] 962*99e0aae7SDavid Rees 0 [+4] UInt message_length 963*99e0aae7SDavid Rees 4 [+4] bits payload: 964*99e0aae7SDavid Rees 0 [+1] Flag incoming 965*99e0aae7SDavid Rees 1 [+1] Flag last_fragment 966*99e0aae7SDavid Rees 2 [+4] UInt scale_factor 967*99e0aae7SDavid Rees 31 [+1] Flag error 968*99e0aae7SDavid Rees``` 969*99e0aae7SDavid Rees 970*99e0aae7SDavid ReesThis is equivalent to: 971*99e0aae7SDavid Rees 972*99e0aae7SDavid Rees``` 973*99e0aae7SDavid Reesstruct Message: 974*99e0aae7SDavid Rees [$default byte_order: "BigEndian"] 975*99e0aae7SDavid Rees 976*99e0aae7SDavid Rees bits Payload: 977*99e0aae7SDavid Rees 0 [+1] Flag incoming 978*99e0aae7SDavid Rees 1 [+1] Flag last_fragment 979*99e0aae7SDavid Rees 2 [+4] UInt scale_factor 980*99e0aae7SDavid Rees 31 [+1] Flag error 981*99e0aae7SDavid Rees 982*99e0aae7SDavid Rees 0 [+4] UInt message_length 983*99e0aae7SDavid Rees 4 [+4] Payload payload 984*99e0aae7SDavid Rees``` 985*99e0aae7SDavid Rees 986*99e0aae7SDavid ReesThis can be useful as a way to group related fields together. 987*99e0aae7SDavid Rees 988*99e0aae7SDavid Rees 989*99e0aae7SDavid Rees#### Automatically-Generated Fields 990*99e0aae7SDavid Rees 991*99e0aae7SDavid ReesA `bits` will have `$size_in_bits`, `$max_size_in_bits`, and `$min_size_in_bits` 992*99e0aae7SDavid Reesvirtual fields automatically generated. These virtual fields can be referenced 993*99e0aae7SDavid Reesinside the Emboss language just like any other virtual field: 994*99e0aae7SDavid Rees 995*99e0aae7SDavid Rees``` 996*99e0aae7SDavid Reesbits Inner: 997*99e0aae7SDavid Rees 0 [+4] UInt field_a 998*99e0aae7SDavid Rees 4 [+4] UInt field_b 999*99e0aae7SDavid Rees 1000*99e0aae7SDavid Reesstruct Outer: 1001*99e0aae7SDavid Rees 0 [+1] UInt message_type 1002*99e0aae7SDavid Rees if message_type == 4: 1003*99e0aae7SDavid Rees 4 [+Inner.$size_in_bits] Inner payload 1004*99e0aae7SDavid Rees``` 1005*99e0aae7SDavid Rees 1006*99e0aae7SDavid Rees 1007*99e0aae7SDavid Rees##### `$size_in_bits` {#size-in-bits} 1008*99e0aae7SDavid Rees 1009*99e0aae7SDavid ReesLike a `struct`, an Emboss `bits` has an *intrinsic* size, which is the size 1010*99e0aae7SDavid Reesrequired to hold every field in the `bits`, regardless of how many bits are 1011*99e0aae7SDavid Reesin the buffer that backs the `bits`. For example: 1012*99e0aae7SDavid Rees 1013*99e0aae7SDavid Rees``` 1014*99e0aae7SDavid Reesbits FixedSize: 1015*99e0aae7SDavid Rees 0 [+3] UInt long_field 1016*99e0aae7SDavid Rees 3 [+1] Flag short_field 1017*99e0aae7SDavid Rees``` 1018*99e0aae7SDavid Rees 1019*99e0aae7SDavid ReesIn this case, `FixedSize.$size_in_bits` will always be `4`, even if a 1020*99e0aae7SDavid Rees`FixedSize` is placed in a larger field: 1021*99e0aae7SDavid Rees 1022*99e0aae7SDavid Rees``` 1023*99e0aae7SDavid Reesstruct Envelope: 1024*99e0aae7SDavid Rees # padded_payload.$size_in_bits == FixedSize.$size_in_bits == 4 1025*99e0aae7SDavid Rees 0 [+8] FixedSize padded_payload 1026*99e0aae7SDavid Rees``` 1027*99e0aae7SDavid Rees 1028*99e0aae7SDavid ReesUnlike `struct`s, the size of `bits` must known at compile time; there are no 1029*99e0aae7SDavid Reesdynamic `$size_in_bits` fields. 1030*99e0aae7SDavid Rees 1031*99e0aae7SDavid Rees 1032*99e0aae7SDavid Rees##### `$max_size_in_bits` {#max-size-in-bits} 1033*99e0aae7SDavid Rees 1034*99e0aae7SDavid ReesSince `bits` must be fixed size, the `$max_size_in_bits` field has the same 1035*99e0aae7SDavid Reesvalue as `$size_in_bits`. It is provided for consistency with 1036*99e0aae7SDavid Rees`$max_size_in_bytes`. 1037*99e0aae7SDavid Rees 1038*99e0aae7SDavid Rees 1039*99e0aae7SDavid Rees##### `$min_size_in_bits` {#min-size-in-bits} 1040*99e0aae7SDavid Rees 1041*99e0aae7SDavid ReesSince `bits` must be fixed size, the `$min_size_in_bits` field has the same 1042*99e0aae7SDavid Reesvalue as `$size_in_bits`. It is provided for consistency with 1043*99e0aae7SDavid Rees`$min_size_in_bytes`. 1044*99e0aae7SDavid Rees 1045*99e0aae7SDavid Rees 1046*99e0aae7SDavid Rees### `external` 1047*99e0aae7SDavid Rees 1048*99e0aae7SDavid ReesAn `external` type is used when a type cannot be defined in Emboss itself; 1049*99e0aae7SDavid Reesinstead, external code must be provided to manipulate the type. 1050*99e0aae7SDavid Rees 1051*99e0aae7SDavid ReesEmboss's built-in types, such as `UInt`, `Bcd`, and `Flag`, are defined this way 1052*99e0aae7SDavid Reesin a special file called the *prelude*. For example, `UInt` is defined as: 1053*99e0aae7SDavid Rees 1054*99e0aae7SDavid Rees``` 1055*99e0aae7SDavid Reesexternal UInt: 1056*99e0aae7SDavid Rees -- UInt is an automatically-sized unsigned integer. 1057*99e0aae7SDavid Rees [type_requires: $is_statically_sized && 1 <= $static_size_in_bits <= 64] 1058*99e0aae7SDavid Rees [is_integer: true] 1059*99e0aae7SDavid Rees [addressable_unit_size: 1] 1060*99e0aae7SDavid Rees``` 1061*99e0aae7SDavid Rees 1062*99e0aae7SDavid Rees`external` types are an unstable feature. Contact `emboss-dev` if you would 1063*99e0aae7SDavid Reeslike to add your own `external`s. 1064*99e0aae7SDavid Rees 1065*99e0aae7SDavid Rees 1066*99e0aae7SDavid Rees## Builtin Types and the Prelude 1067*99e0aae7SDavid Rees 1068*99e0aae7SDavid ReesEmboss has a built-in module called the *Prelude*, which contains types that are 1069*99e0aae7SDavid Reesautomatically usable from any module. In particular, types like `Int` and 1070*99e0aae7SDavid Rees`UInt` are defined in the Prelude. 1071*99e0aae7SDavid Rees 1072*99e0aae7SDavid ReesThe Prelude is (more or less) a standard Emboss file, called `prelude.emb`, that 1073*99e0aae7SDavid Reesis embedded in the Emboss compiler. 1074*99e0aae7SDavid Rees 1075*99e0aae7SDavid Rees<!-- TODO(bolms): When the documentation generator backend is built, generate 1076*99e0aae7SDavid Reesthe Prelude documentation from prelude.emb. --> 1077*99e0aae7SDavid Rees 1078*99e0aae7SDavid Rees 1079*99e0aae7SDavid Rees### `UInt` 1080*99e0aae7SDavid Rees 1081*99e0aae7SDavid ReesA `UInt` is an unsigned integer. `UInt` can be anywhere from 1 to 64 bits in 1082*99e0aae7SDavid Reessize, and may be used both in `struct`s and in `bits`. `UInt` fields may be 1083*99e0aae7SDavid Reesreferenced in integer expressions. 1084*99e0aae7SDavid Rees 1085*99e0aae7SDavid Rees 1086*99e0aae7SDavid Rees### `Int` 1087*99e0aae7SDavid Rees 1088*99e0aae7SDavid ReesAn `Int` is a signed two's-complement integer. `Int` can be anywhere from 1 to 1089*99e0aae7SDavid Rees64 bits in size, and may be used both in `struct`s and in `bits`. `Int` fields 1090*99e0aae7SDavid Reesmay be referenced in integer expressions. 1091*99e0aae7SDavid Rees 1092*99e0aae7SDavid Rees 1093*99e0aae7SDavid Rees### `Bcd` 1094*99e0aae7SDavid Rees 1095*99e0aae7SDavid Rees(Note: `Bcd` is subject to change.) 1096*99e0aae7SDavid Rees 1097*99e0aae7SDavid ReesA `Bcd` is an unsigned binary-coded decimal integer. `Bcd` can be anywhere from 1098*99e0aae7SDavid Rees1 to 64 bits in size, and may be used both in `struct`s and in `bits`. `Bcd` 1099*99e0aae7SDavid Reesfields may be referenced in integer expressions. 1100*99e0aae7SDavid Rees 1101*99e0aae7SDavid ReesWhen a `Bcd`'s size is not a multiple of 4 bits, the high-order "digit" is 1102*99e0aae7SDavid Reestreated as if it were zero-extended to a multiple of 4 bits. For example, a 1103*99e0aae7SDavid Rees7-bit `Bcd` value can store any number from 0 to 79. 1104*99e0aae7SDavid Rees 1105*99e0aae7SDavid Rees 1106*99e0aae7SDavid Rees### `Flag` 1107*99e0aae7SDavid Rees 1108*99e0aae7SDavid ReesA `Flag` is a 1-bit boolean value. A stored value of `0` means `false`, and a 1109*99e0aae7SDavid Reesstored value of `1` means `true`. 1110*99e0aae7SDavid Rees 1111*99e0aae7SDavid Rees 1112*99e0aae7SDavid Rees### `Float` 1113*99e0aae7SDavid Rees 1114*99e0aae7SDavid ReesA `Float` is a floating-point value in an IEEE 754 binaryNN format, where NN is 1115*99e0aae7SDavid Reesthe bit width. 1116*99e0aae7SDavid Rees 1117*99e0aae7SDavid ReesOnly 32- and 64-bit `Float`s are supported. There are no current plans to 1118*99e0aae7SDavid Reessupport 16- or 128-bit `Float`s, nor the nonstandard x86 80-bit `Float`s. 1119*99e0aae7SDavid Rees 1120*99e0aae7SDavid ReesIEEE 754 does not specify which NaN bit patterns are signalling NaNs and which 1121*99e0aae7SDavid Reesare quiet NaNs, and thus Emboss also does not specify which NaNs are which. 1122*99e0aae7SDavid ReesThis means that a quiet NaN written through an Emboss view one system could be 1123*99e0aae7SDavid Reesread out as a signalling NaN through an Emboss view on a different system. If 1124*99e0aae7SDavid Reesthis is a concern, the application must explicitly check for NaN before doing 1125*99e0aae7SDavid Reesarithmetic on any floating-point value read from a `Float` field. 1126*99e0aae7SDavid Rees 1127*99e0aae7SDavid Rees 1128*99e0aae7SDavid Rees## General Syntax 1129*99e0aae7SDavid Rees 1130*99e0aae7SDavid Rees### Names 1131*99e0aae7SDavid Rees 1132*99e0aae7SDavid ReesAll names in Emboss must be ASCII, for compatibility with languages such as C 1133*99e0aae7SDavid Reesand C++ that do not support Unicode identifiers. 1134*99e0aae7SDavid Rees 1135*99e0aae7SDavid ReesType names in Emboss are always `CamelCase`. They must start with a capital 1136*99e0aae7SDavid Reesletter, contain at least one lower-case letter, and contain only letters and 1137*99e0aae7SDavid Reesdigits. They are required to match the regex 1138*99e0aae7SDavid Rees`[A-Z][a-zA-Z0-9]*[a-z][a-zA-Z0-9]*` 1139*99e0aae7SDavid Rees 1140*99e0aae7SDavid ReesImported module names and field names are always `snake_case`. They must start 1141*99e0aae7SDavid Reeswith a lower-case letter, and may only contain lower-case letters, numbers, and 1142*99e0aae7SDavid Reesunderscore. They must match the regex `[a-z][a-z_0-9]*`. 1143*99e0aae7SDavid Rees 1144*99e0aae7SDavid ReesEnum value names are always `SHOUTY_CASE`. They must start with a capital 1145*99e0aae7SDavid Reesletter, may only contain capital letters, numbers, and underscore, and must be 1146*99e0aae7SDavid Reesat least two characters long. They must match the regex 1147*99e0aae7SDavid Rees`[A-Z][A-Z_0-9]*[A-Z_][A-Z_0-9]*`. 1148*99e0aae7SDavid Rees 1149*99e0aae7SDavid ReesAdditionally, names that are used as keywords in common programming languages 1150*99e0aae7SDavid Reesare disallowed. A complete list can be found in the [Grammar 1151*99e0aae7SDavid ReesReference](grammar.md). 1152*99e0aae7SDavid Rees 1153*99e0aae7SDavid Rees 1154*99e0aae7SDavid Rees### Expressions 1155*99e0aae7SDavid Rees 1156*99e0aae7SDavid Rees#### Primary expressions 1157*99e0aae7SDavid Rees 1158*99e0aae7SDavid ReesEmboss primary expressions are field names (like `field` or `field.subfield`), 1159*99e0aae7SDavid Reesnumeric constants (like `9` or `0x1_0000_0000`), enum value names (like 1160*99e0aae7SDavid Rees`Enum.VALUE`), and the boolean constants `true` and `false`. 1161*99e0aae7SDavid Rees 1162*99e0aae7SDavid ReesSubfields may be specified using `.`; e.g., `foo.bar` references the `bar` 1163*99e0aae7SDavid Reessubfield of the `foo` field. Emboss parses `.` before any expressions: unlike 1164*99e0aae7SDavid Reesmany languages, something like `(foo).bar` is a syntax error in Emboss. 1165*99e0aae7SDavid Rees 1166*99e0aae7SDavid ReesEnum values generally must be qualified by their type; e.g., `Color.RED` rather 1167*99e0aae7SDavid Reesthan just `RED`. Enums defined in other modules must use the imported module 1168*99e0aae7SDavid Reesname, as in `styles.Color.RED`. 1169*99e0aae7SDavid Rees 1170*99e0aae7SDavid Rees 1171*99e0aae7SDavid Rees#### Operators and Functions 1172*99e0aae7SDavid Rees 1173*99e0aae7SDavid ReesNote: Emboss currently has a relatively limited set of operators because 1174*99e0aae7SDavid Reesoperators have been implemented as needed. If you could use an operator that is 1175*99e0aae7SDavid Reesnot on the list, email `emboss-dev@`, and we'll see about adding it. 1176*99e0aae7SDavid Rees 1177*99e0aae7SDavid ReesEmboss operators have the following precedence (tightest binding to loosest 1178*99e0aae7SDavid Reesbinding): 1179*99e0aae7SDavid Rees 1180*99e0aae7SDavid Rees1. `()` `$max()` `$present()` `$upper_bound()` `$lower_bound()` 1181*99e0aae7SDavid Rees2. unary `+` and `-` ([see note 1](#precedence-note-unary-plus-minus)) 1182*99e0aae7SDavid Rees3. `*` 1183*99e0aae7SDavid Rees4. `+` `-` 1184*99e0aae7SDavid Rees5. `<` `>` `==` `!=` `>=` `<=` ([see note 2](#precedence-note-comparisons)) 1185*99e0aae7SDavid Rees6. `&&` `||` ([see note 3](#precedence-note-and-or)) 1186*99e0aae7SDavid Rees7. `?:` ([see note 4](#precedence-note-choice)) 1187*99e0aae7SDavid Rees 1188*99e0aae7SDavid Rees 1189*99e0aae7SDavid Rees###### Note 1 {#precedence-note-unary-plus-minus} 1190*99e0aae7SDavid Rees 1191*99e0aae7SDavid ReesOnly one unary `+` or `-` may be applied to an expression without parentheses. 1192*99e0aae7SDavid ReesThese expressions are valid: 1193*99e0aae7SDavid Rees 1194*99e0aae7SDavid Rees``` 1195*99e0aae7SDavid Rees-5 1196*99e0aae7SDavid Rees+6 1197*99e0aae7SDavid Rees-(-x) 1198*99e0aae7SDavid Rees``` 1199*99e0aae7SDavid Rees 1200*99e0aae7SDavid ReesThese are not: 1201*99e0aae7SDavid Rees 1202*99e0aae7SDavid Rees``` 1203*99e0aae7SDavid Rees- -5 1204*99e0aae7SDavid Rees-+5 1205*99e0aae7SDavid Rees+ +5 1206*99e0aae7SDavid Rees+-5 1207*99e0aae7SDavid Rees``` 1208*99e0aae7SDavid Rees 1209*99e0aae7SDavid Rees 1210*99e0aae7SDavid Rees###### Note 2 {#precedence-note-comparisons} 1211*99e0aae7SDavid Rees 1212*99e0aae7SDavid ReesThe relational operators may be chained like so: 1213*99e0aae7SDavid Rees 1214*99e0aae7SDavid Rees``` 1215*99e0aae7SDavid Rees10 <= x < 50 # 10 <= x && x < 50 1216*99e0aae7SDavid Rees10 <= x == y < 50 # 10 <= x && x == y && y < 50 1217*99e0aae7SDavid Rees100 > y >= 2 # 100 > y && y >= 2 1218*99e0aae7SDavid Reesx == y == 15 # x == y && y == 15 1219*99e0aae7SDavid Rees``` 1220*99e0aae7SDavid Rees 1221*99e0aae7SDavid ReesThese are not: 1222*99e0aae7SDavid Rees 1223*99e0aae7SDavid Rees``` 1224*99e0aae7SDavid Rees10 < x > 50 1225*99e0aae7SDavid Rees10 < x == y >= z 1226*99e0aae7SDavid Reesx == y >= z <= 50 1227*99e0aae7SDavid Rees``` 1228*99e0aae7SDavid Rees 1229*99e0aae7SDavid ReesIf one specifically wants to compare the result of a comparison, parentheses 1230*99e0aae7SDavid Reesmust be used: 1231*99e0aae7SDavid Rees 1232*99e0aae7SDavid Rees``` 1233*99e0aae7SDavid Rees(x > 15) == (y > 15) 1234*99e0aae7SDavid Rees(x > 15) == true 1235*99e0aae7SDavid Rees``` 1236*99e0aae7SDavid Rees 1237*99e0aae7SDavid ReesThe `!=` operator may not be chained. 1238*99e0aae7SDavid Rees 1239*99e0aae7SDavid ReesA chain may contain either `<`, `<=`, and/or `==`, or `>`, `>=`, and/or `==`. 1240*99e0aae7SDavid ReesGreater-than comparisons may not be mixed with less-than comparisons. 1241*99e0aae7SDavid Rees 1242*99e0aae7SDavid Rees 1243*99e0aae7SDavid Rees###### Note 3 {#precedence-note-and-or} 1244*99e0aae7SDavid Rees 1245*99e0aae7SDavid ReesThe boolean logical operators have the same precedence, but may not be mixed 1246*99e0aae7SDavid Reeswithout parentheses. The following are allowed: 1247*99e0aae7SDavid Rees 1248*99e0aae7SDavid Rees``` 1249*99e0aae7SDavid Reesx && y && z 1250*99e0aae7SDavid Reesx || y || z 1251*99e0aae7SDavid Rees(x || y) && z 1252*99e0aae7SDavid Reesx || (y && z) 1253*99e0aae7SDavid Rees``` 1254*99e0aae7SDavid Rees 1255*99e0aae7SDavid ReesThe following are not allowed: 1256*99e0aae7SDavid Rees 1257*99e0aae7SDavid Rees``` 1258*99e0aae7SDavid Reesx || y && z 1259*99e0aae7SDavid Reesx && y || z 1260*99e0aae7SDavid Rees``` 1261*99e0aae7SDavid Rees 1262*99e0aae7SDavid Rees 1263*99e0aae7SDavid Rees###### Note 4 {#precedence-note-choice} 1264*99e0aae7SDavid Rees 1265*99e0aae7SDavid ReesThe choice operator `?:` may not be chained without parentheses. These are OK: 1266*99e0aae7SDavid Rees 1267*99e0aae7SDavid Rees``` 1268*99e0aae7SDavid Reesq ? x : (r ? y : z) 1269*99e0aae7SDavid Reesq ? (r ? x : y) : z 1270*99e0aae7SDavid Rees``` 1271*99e0aae7SDavid Rees 1272*99e0aae7SDavid ReesThis is not: 1273*99e0aae7SDavid Rees 1274*99e0aae7SDavid Rees``` 1275*99e0aae7SDavid Reesq ? x : r ? y : z # Is this `(q?x:r)?y:z` or `q?x:(r?y:z)`? 1276*99e0aae7SDavid Reesq ? r ? x : y : z # Technically unambiguous, but visually confusing 1277*99e0aae7SDavid Rees``` 1278*99e0aae7SDavid Rees 1279*99e0aae7SDavid Rees 1280*99e0aae7SDavid Rees##### `()` 1281*99e0aae7SDavid Rees 1282*99e0aae7SDavid ReesParentheses are used to override precedence. The subexpression inside the 1283*99e0aae7SDavid Reesparentheses will be evaluated as a unit: 1284*99e0aae7SDavid Rees 1285*99e0aae7SDavid Rees``` 1286*99e0aae7SDavid Rees3 * 4 + 5 == 17 1287*99e0aae7SDavid Rees3 * (4 + 5) == 27 1288*99e0aae7SDavid Rees``` 1289*99e0aae7SDavid Rees 1290*99e0aae7SDavid ReesThe value inside the parentheses can have any type; the value of the resulting 1291*99e0aae7SDavid Reesexpression will have the same type. 1292*99e0aae7SDavid Rees 1293*99e0aae7SDavid Rees 1294*99e0aae7SDavid Rees##### `$present()` 1295*99e0aae7SDavid Rees 1296*99e0aae7SDavid ReesThe `$present()` function takes a field as an argument, and returns `true` if 1297*99e0aae7SDavid Reesthe field is present in its structure. 1298*99e0aae7SDavid Rees 1299*99e0aae7SDavid Rees``` 1300*99e0aae7SDavid Reesstruct PresentExample: 1301*99e0aae7SDavid Rees 0 [+1] UInt x 1302*99e0aae7SDavid Rees if false: 1303*99e0aae7SDavid Rees 1 [+1] UInt y 1304*99e0aae7SDavid Rees if x > 10: 1305*99e0aae7SDavid Rees 2 [+1] UInt z 1306*99e0aae7SDavid Rees if $present(x): # Always true 1307*99e0aae7SDavid Rees 0 [+1] Int x2 1308*99e0aae7SDavid Rees if $present(y): # Always false 1309*99e0aae7SDavid Rees 1 [+1] Int y2 1310*99e0aae7SDavid Rees if $present(z): # Equivalent to `if x > 10` 1311*99e0aae7SDavid Rees 2 [+1] Int z2 1312*99e0aae7SDavid Rees``` 1313*99e0aae7SDavid Rees 1314*99e0aae7SDavid Rees`$present()` takes exactly one argument. 1315*99e0aae7SDavid Rees 1316*99e0aae7SDavid ReesThe argument to `$present()` must be a reference to a field. It can be a nested 1317*99e0aae7SDavid Reesreference, like `$present(x.y.z.q.r)`. The type of the field does not matter. 1318*99e0aae7SDavid Rees 1319*99e0aae7SDavid Rees`$present()` returns a boolean. 1320*99e0aae7SDavid Rees 1321*99e0aae7SDavid Rees 1322*99e0aae7SDavid Rees##### `$max()` 1323*99e0aae7SDavid Rees 1324*99e0aae7SDavid ReesThe `$max()` function returns the maximum value out of its arguments: 1325*99e0aae7SDavid Rees 1326*99e0aae7SDavid Rees``` 1327*99e0aae7SDavid Rees$max(1) == 1 1328*99e0aae7SDavid Rees$max(-10, -5) == -5 1329*99e0aae7SDavid Rees$max(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 10 1330*99e0aae7SDavid Rees``` 1331*99e0aae7SDavid Rees 1332*99e0aae7SDavid Rees`$max()` requires at least one argument. There is no explicit limit on the 1333*99e0aae7SDavid Reesnumber of arguments, but at some point the Emboss compiler will run out of 1334*99e0aae7SDavid Reesmemory. 1335*99e0aae7SDavid Rees 1336*99e0aae7SDavid ReesAll arguments to `$max()` must be integers, and it returns an integer. 1337*99e0aae7SDavid Rees 1338*99e0aae7SDavid Rees 1339*99e0aae7SDavid Rees##### `$upper_bound()` 1340*99e0aae7SDavid Rees 1341*99e0aae7SDavid ReesThe `$upper_bound()` function returns a value that is at least as high as the 1342*99e0aae7SDavid Reesmaximum possible value of its argument: 1343*99e0aae7SDavid Rees 1344*99e0aae7SDavid Rees``` 1345*99e0aae7SDavid Rees$upper_bound(1) == 1 1346*99e0aae7SDavid Rees$upper_bound(-10) == -10 1347*99e0aae7SDavid Rees$upper_bound(foo) == 255 # If foo is UInt:8 1348*99e0aae7SDavid Rees$upper_bound($max(foo, 500)) == 500 # If foo is UInt:8 1349*99e0aae7SDavid Rees``` 1350*99e0aae7SDavid Rees 1351*99e0aae7SDavid ReesGenerally, `$upper_bound()` will return a tight bound, but it is possible to 1352*99e0aae7SDavid Reesoutsmart Emboss's bounds checker. 1353*99e0aae7SDavid Rees 1354*99e0aae7SDavid Rees`$upper_bound()` takes a single integer argument, and returns a single integer 1355*99e0aae7SDavid Reesargument. 1356*99e0aae7SDavid Rees 1357*99e0aae7SDavid Rees 1358*99e0aae7SDavid Rees##### `$lower_bound()` 1359*99e0aae7SDavid Rees 1360*99e0aae7SDavid ReesThe `$lower_bound()` function returns a value that is no greater than the 1361*99e0aae7SDavid Reesminimum possible value of its argument: 1362*99e0aae7SDavid Rees 1363*99e0aae7SDavid Rees``` 1364*99e0aae7SDavid Rees$lower_bound(1) == 1 1365*99e0aae7SDavid Rees$lower_bound(-10) == -10 1366*99e0aae7SDavid Rees$lower_bound(foo) == -127 # If foo is Int:8 1367*99e0aae7SDavid Rees$lower_bound($min(foo, -500)) == -500 # If foo is Int:8 1368*99e0aae7SDavid Rees``` 1369*99e0aae7SDavid Rees 1370*99e0aae7SDavid ReesGenerally, `$lower_bound()` will return a tight bound, but it is possible to 1371*99e0aae7SDavid Reesoutsmart Emboss's bounds checker. 1372*99e0aae7SDavid Rees 1373*99e0aae7SDavid Rees`$lower_bound()` takes a single integer argument, and returns a single integer 1374*99e0aae7SDavid Reesargument. 1375*99e0aae7SDavid Rees 1376*99e0aae7SDavid Rees 1377*99e0aae7SDavid Rees##### Unary `+` and `-` 1378*99e0aae7SDavid Rees 1379*99e0aae7SDavid ReesThe unary `+` operator returns its argument unchanged. 1380*99e0aae7SDavid Rees 1381*99e0aae7SDavid ReesThe unary `-` operator subtracts its argument from 0: 1382*99e0aae7SDavid Rees 1383*99e0aae7SDavid Rees``` 1384*99e0aae7SDavid Rees3 * -4 == 0 - 12 1385*99e0aae7SDavid Rees-(3 * 4) == -12 1386*99e0aae7SDavid Rees``` 1387*99e0aae7SDavid Rees 1388*99e0aae7SDavid ReesUnary `+` and `-` require an integer argument, and return an integer result. 1389*99e0aae7SDavid Rees 1390*99e0aae7SDavid Rees 1391*99e0aae7SDavid Rees##### `*` 1392*99e0aae7SDavid Rees 1393*99e0aae7SDavid Rees`*` is the multiplication operator: 1394*99e0aae7SDavid Rees 1395*99e0aae7SDavid Rees``` 1396*99e0aae7SDavid Rees3 * 4 == 12 1397*99e0aae7SDavid Rees10 * 10 == 100 1398*99e0aae7SDavid Rees``` 1399*99e0aae7SDavid Rees 1400*99e0aae7SDavid ReesThe `*` operator requires two integer arguments, and returns an integer. 1401*99e0aae7SDavid Rees 1402*99e0aae7SDavid Rees 1403*99e0aae7SDavid Rees##### `+` and `-` 1404*99e0aae7SDavid Rees 1405*99e0aae7SDavid Rees`+` and `-` are the addition and subtraction operators, respectively: 1406*99e0aae7SDavid Rees 1407*99e0aae7SDavid Rees``` 1408*99e0aae7SDavid Rees3 + 4 == 7 1409*99e0aae7SDavid Rees3 - 4 == -1 1410*99e0aae7SDavid Rees``` 1411*99e0aae7SDavid Rees 1412*99e0aae7SDavid ReesThe `+` and `-` operators require two integer arguments, and return an integer 1413*99e0aae7SDavid Reesresult. 1414*99e0aae7SDavid Rees 1415*99e0aae7SDavid Rees 1416*99e0aae7SDavid Rees##### `==` and `!=` 1417*99e0aae7SDavid Rees 1418*99e0aae7SDavid ReesThe `==` operator returns `true` if its arguments are equal, and `false` if not. 1419*99e0aae7SDavid Rees 1420*99e0aae7SDavid ReesThe `!=` operator returns `false` if its arguments are equal, and `true` if not. 1421*99e0aae7SDavid Rees 1422*99e0aae7SDavid ReesBoth operators take two boolean arguments, two integer arguments, or two 1423*99e0aae7SDavid Reesarguments of the same enum type, and return a boolean result. 1424*99e0aae7SDavid Rees 1425*99e0aae7SDavid Rees 1426*99e0aae7SDavid Rees##### `<`, `<=`, `>`, and `>=` 1427*99e0aae7SDavid Rees 1428*99e0aae7SDavid ReesThe `<` operator returns `true` if its first argument is numerically less than 1429*99e0aae7SDavid Reesits second argument. 1430*99e0aae7SDavid Rees 1431*99e0aae7SDavid ReesThe `>` operator returns `true` if its first argument is numerically greater 1432*99e0aae7SDavid Reesthan its second argument. 1433*99e0aae7SDavid Rees 1434*99e0aae7SDavid ReesThe `<=` operator returns `true` if its first argument is numerically less than 1435*99e0aae7SDavid Reesor equal to its second argument. 1436*99e0aae7SDavid Rees 1437*99e0aae7SDavid ReesThe `>=` operator returns `true` if its first argument is numerically greater 1438*99e0aae7SDavid Reesthan or equal to its second argument. 1439*99e0aae7SDavid Rees 1440*99e0aae7SDavid ReesAll of these operators take two integer arguments, and return a boolean value. 1441*99e0aae7SDavid Rees 1442*99e0aae7SDavid Rees 1443*99e0aae7SDavid Rees##### `&&` and `||` 1444*99e0aae7SDavid Rees 1445*99e0aae7SDavid ReesThe `&&` operator returns `false` if either of its arguments are `false`, even 1446*99e0aae7SDavid Reesif the other argument cannot be computed. `&&` returns `true` if both arguments 1447*99e0aae7SDavid Reesare `true`. 1448*99e0aae7SDavid Rees 1449*99e0aae7SDavid ReesThe `||` operator returns `true` if either of its arguments are `true`, even if 1450*99e0aae7SDavid Reesthe other argument cannot be computed. `||` returns `false` if both arguments 1451*99e0aae7SDavid Reesare `false`. 1452*99e0aae7SDavid Rees 1453*99e0aae7SDavid ReesThe `&&` and `||` operators require two boolean arguments, and return a boolean 1454*99e0aae7SDavid Reesresult. 1455*99e0aae7SDavid Rees 1456*99e0aae7SDavid Rees 1457*99e0aae7SDavid Rees##### `?:` 1458*99e0aae7SDavid Rees 1459*99e0aae7SDavid ReesThe `?:` operator, used like <code>*condition* ? *if\_true* : 1460*99e0aae7SDavid Rees*if\_false*</code>, returns *`if_true`* if *`condition`* is `true`, otherwise 1461*99e0aae7SDavid Rees*`if_false`*. 1462*99e0aae7SDavid Rees 1463*99e0aae7SDavid ReesOther than having stricter type requirements for its arguments, it behaves like 1464*99e0aae7SDavid Reesthe C, C++, Java, JavaScript, C#, etc. conditional operator `?:` (sometimes 1465*99e0aae7SDavid Reescalled the "ternary operator"). 1466*99e0aae7SDavid Rees 1467*99e0aae7SDavid ReesThe `?:` operator's *`condition`* argument must be a boolean, and the 1468*99e0aae7SDavid Rees*`if_true`* and *`if_false`* arguments must have the same type. It returns the 1469*99e0aae7SDavid Reessame type as *`if_true`* and *`if_false`*. 1470*99e0aae7SDavid Rees 1471*99e0aae7SDavid Rees 1472*99e0aae7SDavid Rees### Numeric Constant Formats 1473*99e0aae7SDavid Rees 1474*99e0aae7SDavid ReesNumeric constants in Emboss may be written in decimal, hexadecimal, or binary 1475*99e0aae7SDavid Reesformat: 1476*99e0aae7SDavid Rees 1477*99e0aae7SDavid Rees``` 1478*99e0aae7SDavid Rees12 # The decimal value of 6 + 6. 1479*99e0aae7SDavid Rees012 # The same value; NOT interpreted as octal. 1480*99e0aae7SDavid Rees0xc # The same value, written in hexadecimal. 1481*99e0aae7SDavid Rees0xC # Hex digits may be written in capital letters. 1482*99e0aae7SDavid Rees # Note that the 'x' must be lower-case: 0XC is not allowed. 1483*99e0aae7SDavid Rees0b1100 # The same value, in binary. 1484*99e0aae7SDavid Rees``` 1485*99e0aae7SDavid Rees 1486*99e0aae7SDavid ReesDecimal numbers may use `_` as a thousands separator: 1487*99e0aae7SDavid Rees 1488*99e0aae7SDavid Rees``` 1489*99e0aae7SDavid Rees1_000_000 # 1e6 1490*99e0aae7SDavid Rees123_456_789 1491*99e0aae7SDavid Rees``` 1492*99e0aae7SDavid Rees 1493*99e0aae7SDavid ReesHexadecimal and binary numbers may use `_` as a separator every 4 or 8 digits: 1494*99e0aae7SDavid Rees 1495*99e0aae7SDavid Rees``` 1496*99e0aae7SDavid Rees0x1234_5678_9abc_def0 1497*99e0aae7SDavid Rees0x12345678_9abcdef0 1498*99e0aae7SDavid Rees0b1010_0101_1010_0101 1499*99e0aae7SDavid Rees0b10100101_10100101 1500*99e0aae7SDavid Rees``` 1501*99e0aae7SDavid Rees 1502*99e0aae7SDavid ReesIf separators are used, they *must* be thousands separators (for decimal 1503*99e0aae7SDavid Reesnumbers) or 4- or 8-digit separators (for binary or hexadecimal numbers); `_` 1504*99e0aae7SDavid Reesmay *not* be placed arbitrarily. Binary and hexadecimal numbers must be 1505*99e0aae7SDavid Reesconsistent about whether they use 4- or 8-digit separators; they cannot be 1506*99e0aae7SDavid Reesmixed in the same constant: 1507*99e0aae7SDavid Rees 1508*99e0aae7SDavid Rees``` 1509*99e0aae7SDavid Rees1000_000 # Not allowed: missing the separator after 1. 1510*99e0aae7SDavid Rees1_000_00 # Not allowed: separators must be followed by a multiple 1511*99e0aae7SDavid Rees # of 3 digits. 1512*99e0aae7SDavid Rees0x1234_567 # Not allowed: separators must be followed by a multiple 1513*99e0aae7SDavid Rees # of 4 or 8 digits. 1514*99e0aae7SDavid Rees0x1234_5678_9abcdef0 # Not allowed: cannot mix 4- and 8-digit separators. 1515*99e0aae7SDavid Rees``` 1516