Integer as Bit-Fields
Nothing here cannot be done via standard bit-manipulation (i.e. shifting and masking).
Built-in support is more elegant and performant since it usually replaces a sequence of multiple steps.
Since bit-wise operators are defined on integer numbers, individual bits can also be accessed and manipulated via an indexing syntax.
If a bit is set (i.e. 1
), the index access returns true
.
If a bit is not set (i.e. 0
), the index access returns false
.
When a range is used, the bits within the range are shifted and extracted as an integer value.
Bit-fields are very commonly used in embedded systems which must squeeze data into limited memory.
Built-in support makes handling them efficient.
Syntax
From Least-Significant Bit (LSB)
Bits in a bit-field are accessed with zero-based, non-negative integer indices:
integer
[
index from 0 to 63 or 31]
integer
[
index from 0 to 63 or 31] =
true
orfalse
;
[Ranges] can also be used:
integer
[
start..
end]
integer[
start..=
end]
integer
[
start..
end] =
new integer value ;
integer[
start..=
end] =
new integer value ;
The maximum bit number that can be accessed is one less than the number of bits for the system integer type (usually 63).
Bits outside of the range are ignored.
From Most-Significant Bit (MSB)
A negative index accesses a bit in the bit-field counting from the end, or from the most-significant bit, with −1 being the highest bit.
integer
[
index from −1 to −64 or −32]
integer
[
index from −1 to −64 or −32] =
true
orfalse
;
Ranges always count from the least-significant bit (LSB) and has no support for negative positions.
The maximum bit number that can be accessed is negative the number of bits for the system integer type (usually −64).
Bit-Field Functions
The following standard functions operate on bit-fields.
Function | Parameter(s) | Description |
---|---|---|
get_bit | bit number, counting from MSB if < 0 | returns the state of a bit: true if 1 , false if 0 |
set_bit |
| sets the state of a bit |
get_bits |
| extracts a number of bits, shifted towards LSB |
get_bits | range of bits | extracts a number of bits, shifted towards LSB |
set_bits |
| sets a number of bits from the new value |
set_bits |
| sets a number of bits from the new value |
bits method and property |
| allows iteration over the bits of a bit-field |
bits | range of bits | allows iteration over the bits of a bit-field |
Example
// Assume the following bits fields in a single 16-bit word:
// ┌─────────┬────────────┬──────┬─────────┐
// │ 15-12 │ 11-4 │ 3 │ 2-0 │
// ├─────────┼────────────┼──────┼─────────┤
// │ 0 │ 0-255 data │ flag │ command │
// └─────────┴────────────┴──────┴─────────┘
let value = read_start_hw_register(42);
let command = value.get_bits(0, 3); // Command = bits 0-2
let flag = value[3]; // Flag = bit 3
let data = value[4..=11]; // Data = bits 4-11
let data = value.get_bits(4..=11); // <- above is the same as this
let reserved = value.get_bits(-4); // Reserved = last 4 bits
if reserved != 0 {
throw reserved;
}
switch command {
0 => print(`Data = ${data}`),
1 => value[4..=11] = data / 2,
2 => value[3] = !flag,
_ => print(`Unknown: ${command}`)
}