Language Types & literals

Types & literals

Hover has two families of type. wire describes circuit topology and holds nothing; the numeric types hold logic values. Keeping them separate is what lets the compiler tell a net apart from a signal.

Structural types

Structural types describe topology only — they cannot hold a logic state or a numerical value.

wireAn electrical net. wire in, out;

Floating-point types

Floating-point values represent the continuous domains — time, voltage, current.

  • double — 64-bit. double x = 3.14;
  • float — 32-bit. float y = 1.0;

A note on precision. float variables really are 32-bit C++ floats inside digital module logic, but the MNA solver and the global state maps work exclusively in 64-bit. A float is therefore promoted to double the moment it crosses into an analog module, drives a physical source, or is logged by .save. For anything the solver touches, prefer double — mixed precision is a reliable way to destabilise Newton-Raphson.

Integer types

Integers are for discrete logic: state machines, loop counters, bitwise work.

  • int — signed 32-bit. int n = -4;
  • unsigned int — unsigned 32-bit. unsigned int k = 42;

Assigning a floating-point value to an integer truncates the fractional part. unsigned is reserved for integers — unsigned double is not a type.

Arrays

Append [size] to any type to get a fixed-size array:

wire arrays can't take a value initialiser — they hold no data.

Multidimensional arrays

Additional [size] suffixes add dimensions, read outer-to-inner exactly as in C:

Two initialisation forms, applied recursively at every level:

  • Nested brace literals{{...}, {...}}. The nesting depth must match the declared dimensions.
  • Scalar fill — one value broadcasts to every element across all dimensions, not just the outermost. int[2][2] grid = 0; zero-fills all four.

Each subscript peels off one dimension, left to right:

Passed to a function, only the outermost dimension may decay; every inner dimension has to stay a known fixed size.

Pointers

Append * to a numeric type. Stars stack one per level of indirection, and combine with array syntax:

A pointer with no initialiser defaults to null, the way a scalar defaults to 0.

Address-of and dereference

& takes an address; prefix * dereferences. These are the same symbols used for bitwise AND and multiplication, disambiguated purely by position exactly as C does it — unary in front of an operand with nothing to its left, binary between two operands.

Pointers as parameters and state

A pointer subscripts like an array — p[i] compiles to *(p + i), the usual C duality. Unlike a scalar parameter, which is copied, a pointer parameter is aliased: writes through it inside a function are visible to the caller.

Because a pointer is just an address-sized value, it can be declared state to persist across timesteps — the standard way to hold a handle from external C++ for the life of the simulation. See the opaque pointer pattern.

Pointer arithmetic (p + 1) isn't supported; use indexing to walk memory.

Number literals & suffixes

Engineering suffixes are part of the number token — no space between digits and suffix. Scientific notation (1e-6, 1e3) also works.

p 10⁻¹² 10p 10 pF / ps
n 10⁻⁹ 100n 100 nH / ns
u 10⁻⁶ 2u 2 µF / µs
m 10⁻³ 2m 2 mH / ms
(none) 1 400 400
k 10³ 20k 20 000
Meg 10⁶ 1Meg 1 000 000
G 10⁹ 2G 2 000 000 000

Suffixes are case-sensitive: the megohm suffix is Meg, and 1meg is a syntax error.