Types
The powerful type system is one of the features that make Spade stand out the most compared to contemporary HDLs. For software developers already familiar with Rust, the Spade type system is very similar to that of Rust, to the point where you can skim this section and assume that you're writing Rust.
Structs
Like most languages, Spade supports struct
s to encapsulate related values. For example, a struct containing a field named a
with type int<8>
and b
with type bool
can be written as
struct IntAndBool {
a: int<8>,
b: bool,
}
Like many languages, accessing struct fields is done with .
let x = instance.a;
let y = instance.b;
Structs are initialized as if they are functions. This means you can either do so with positional arguments:
let instance = IntAndBool(0, true);
or with named arguments:
let instance = IntAndBool$(a: 0, b: true);
Tuples
Sometimes, defining a named struct just to group values is overkill, which makes tuples
a useful alternative. Tuple types are written as (type1, type1, ...)
and values are written
as (a, b, ...)
. As an example, a function that wraps a bool
and int<8>
in a tuple can
be written as
fn example(a: int<8>, b: bool) -> (int<8>, bool) {
// ^^^^^^^^^^^^^^ Return a tuple
(a, b)
// ^^^^^^ Construct the return value
}
Tuple elements can be accessed using the #
operator, i.e.
let a = tup#0;
let b = tup#1;
though in most cases it is better to use destructuring
Destructuring
Tuples, structs, and most other types can be destructured to gain access to the inner values. For example, the tuple indexing above can be replaced with
let (a, b) = tup;
The big advantage of destructuring over indexing is that you cannot forget to
account for all fields. If someone adds another field to tup
, you will get a
compilation error saying that field also needs to be taken into account.
Structs can also be destructured, and like instantiation it can be done with both positional and named arguments
let IntAndBool(x, y) = instance;
let IntAndBool$(a: x, b: y) = instance;
Like named arguments, you can also use shorthand notation, to bind a field name to a variable of the same name:
let IntAndBool$(a, b) = instance;
// Is the same as
let a = instance.a;
let b = instance.b;
Destructuring can also be done recursively, for example:
let (IntAndBool(x, y), z) = instance_and_bool;
Arrays
Arrays too work like most other languages. They are a collection of a fixed
number of identical values. Array types are written as [T; N]
where T
is
the contained type and N
is the number of elements. For example, an array
of ten 8-bit integers is written as [int<8>; 10]
. For more details on initializing and accessing arrays, see the previous Basic Expressions chapter
More fancy types
Beyond these types which are similar to those found in many languages, Spade has some more powerful type system features that are discussed in the next section.