xref: /aosp_15_r20/external/emboss/doc/language-reference.md (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
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