Types, Data Structures & Gradual Soundness
Statically unboxed machine types, algebraic sum types, and zero-cost boundary gradual typing.
1. Primitive Types
| Type | Size | Description | Example |
|---|---|---|---|
int / i64 | 64-bit | Signed integer (standard register size) | 42 |
f64 / float | 64-bit | IEEE-754 double precision float | 3.14159 |
f32 | 32-bit | Single precision floating point (GPU/SIMD) | 1.0f |
bool | 8-bit | Boolean true/false | true |
string | 16-byte | UTF-8 pointer + length string slice | "hello, world" |
char | 32-bit | Unicode scalar value | 'A' |
2. Compound Types & Structs
struct Vector3 {
x: f32,
y: f32,
z: f32,
}
impl Vector3 {
pub fn dot(self: &Vector3, other: &Vector3) -> f32 {
(self.x * other.x) + (self.y * other.y) + (self.z * other.z)
}
}
3. Algebraic Enums & Pattern Matching
enum NetworkPacket {
Handshake { version: int },
Data { payload: string, seq: int },
Disconnect,
}
fn handle_packet(pkt: NetworkPacket) {
match pkt {
NetworkPacket.Handshake{ version } => println("Connecting with protocol v" + string(version)),
NetworkPacket.Data{ payload, seq } => println("Packet #" + string(seq) + ": " + payload),
NetworkPacket.Disconnect => println("Disconnected cleanly."),
}
}
4. Zero-Cost Gradual Typing & Hard Boundaries (@strict)
Nyx combines the developer velocity of dynamic prototyping with the raw execution speed of bare-metal C via sound gradual typing:
⚡ The Zero-Cost Hard-Boundary Guarantee:
Unlike languages that incur boxing/unboxing overhead on every type transition, Nyx strictly isolates dynamic types. When a function is annotated with @strict or @unboxed, the compiler guarantees:
- Zero Boxing Overhead: Types compile to raw register unboxed values with no heap wrapper.
- SIMD Loop Vectorization: Inner loops compile directly to AVX2/NEON instructions.
- Static Contract Verification: Dynamic inputs crossing into a
@strictboundary are checked once at the boundary gate with zero subsequent runtime checks.
import std.core.*;
// High-level dynamic handler (e.g. rapid JSON ingestion)
fn handle_request(raw_payload: any) {
// Dynamic boundary check happens ONCE here:
let tensor_data: [f32; 1024] = raw_payload.read_floats();
// Dispatches to 100% unboxed, pure SIMD kernel:
compute_heavy_simd(&tensor_data);
}
@strict
fn compute_heavy_simd(data: &[f32; 1024]) -> f32 {
let mut sum: f32 = 0.0;
for i in 0..1024 {
sum = sum + data[i]; // Compiles to pure AVX2 unboxed machine code
}
sum
}