Skip to main content

8  Type System, Scalars and Unit

Edva is statically typed with zero runtime type information (RTTI). All types are checked and unified at compile time and lowered directly to machine registers or arena-backed layouts.

8.1 Complete type taxonomy and ABI layout

Category Edva Syntax Size & Alignment (64-bit) LLVM Lowering Reference Chapter
Signed integers Int (i64), i8, i16, i32 8B, 1B, 2B, 4B i64, i8, i16, i32 Below
Unsigned integers u8, u16, u32, u64 1B, 2B, 4B, 8B i8, i16, i32, i64 Below
Floating-point Float (f64), f32 8B (align 8), 4B (align 4) double, float Below
Unicode scalar Rune 4B (align 4) i32 Below
Zero-sized unit () (Unit) 0B void Below
Byte string String 16B (align 8) { i64 len, ptr data } String & Builder
Byte buffer Builder ({cap}) 24B (align 8) { i64 len, ptr data, i64 cap } String & Builder
Flag (RamNN) <> 1 bit / 1B i1 Flags, Ramifications & Error
Option / Fallible < T | >, < | E > 8B (ptr niche) or { i1, T } ptr / { i1, T } Flags, Ramifications & Error
Result (RamPP) < T | E > 16B unboxed register pair { i1, i64 } Flags, Ramifications & Error
Structured error Error Pointer to 6-field struct ptr Flags, Ramifications & Error
Record / Tuple (a: T1, b: T2), (T * N) C ABI / #packed / #align N { T1, T2, ... } Records, Tuples, Bitfields & Enums
Nominal enum < V1, V2(T) > 16B (align 8) { i64 tag, ptr payload } Records, Tuples, Bitfields & Enums
Growable array T{} / T{cap} 24B (align 8) { i64 len, ptr data, i64 cap } Arrays, Slices & Maps
Slice view T[] 16B (align 8) { i64 len, ptr data } Arrays, Slices & Maps
Hash map K ^ V 8B handle (ptr) ptr (arena hash table) Arrays, Slices & Maps
Function / closure A, B => R 16B (align 8) { ptr fn_ptr, ptr env_ptr } Functions & Closures
Compile-time type Type (#!) 0B (erased before codegen) Erased Compile-Time (#!) & Type Reflection
Raw pointer Addr (ptr) 8B on 64-bit, 4B on 32-bit ptr Memory, Arenas, Addr & FFI

8.2 Integer scalars (Int, i8..i64, u8..u64)

Int is strictly 64-bit signed (i64) on all target architectures (including 32-bit wasm32). Fixed-width integers provide exact C-ABI and hardware register widths.

Type Bits Signed Minimum Value Maximum Value Literal Suffix
i8 8 Yes \(-128\) \(127\) 127i8
u8 8 No \(0\) \(255\) 255u8
i16 16 Yes \(-32,768\) \(32,767\) 1000i16
u16 16 No \(0\) \(65,535\) 8080u16
i32 32 Yes \(-2,147,483,648\) \(2,147,483,647\) 42i32
u32 32 No \(0\) \(4,294,967,295\) 0x80000000u32
Int / i64 64 Yes \(-9,223,372,036,854,775,808\) \(9,223,372,036,854,775,807\) 42 or 42i64
u64 64 No \(0\) \(18,446,744,073,709,551,615\) 42u64

8.2.1 Integer operations and conversions

Operation Syntax Semantics
Arithmetic + - * / % Same-width integer arithmetic (/ truncates toward zero; mixing Int with Float promotes to Float)
Bitwise .&. .|. .^. .!. Bitwise AND, OR, XOR, and unary one’s-complement NOT (.!.x)
Shifts .<. .>. Left shift and right shift
Comparisons == != < > !< !> Returns <> (!< is \(\ge\), !> is \(\le\))
Explicit width cast i16(x), u8(x), Int(x) Explicit truncation, zero-extension, or sign-extension (no implicit integer widening)
#use io

mask = 0b1{8}
port = 8080u16
io::out $ (mask .&. 0xFF, Int(port), 20 / 6, 20 % 6)

8.3 Floating-point scalars (Float, f32)

Type Bits Significand Bits Decimal Precision Exponent Range Literal Example
f32 32 24 ~7 digits \(10^{-38} \dots 10^{38}\) 1.25f32
Float / f64 64 53 ~15–17 digits \(10^{-308} \dots 10^{308}\) 3.141592653589793, 1.0e-9

8.3.1 Floating-point semantics and NaN ordering

Rule Expression Result when Operand is NaN Explanation
Ordered relational a < b, a > b, a !< b, a !> b <-> (false) LLVM OLT / OGT / OGE / OLE
Logical negation !(a < b) <+> (true) Negates the <-> result of a < b (distinct from a !< b)
Equality / inequality a == b / a != b <-> / <+> LLVM OEQ / UNE (nan != nan is <+>)
Explicit conversion Float(n), Int(f), f32(f) — Int(f) truncates toward zero
#use io

nan = 0.0 / 0.0
io::out $ (nan !< 1.0, !(nan < 1.0), Int(3.99), Float(42))

8.4 Unicode characters (Rune)

Rune represents a 32-bit Unicode scalar value (U+0000..U+D7FF, U+E000..U+10FFFF), lowered as i32 (#size Rune == 4).

Operation Syntax Result Type Behavior
Rune literal 'a', 'λ', '🦀', '\n', '\x1b', '\u{1F600}' Rune Single Unicode codepoint
Offset arithmetic 'a' + 1, ch - 'a' Rune / Int Direct codepoint arithmetic with Int
Comparison ch !< 'a' && ch !> 'z' <> Codepoint order comparison
Builder UTF-8 append b += '🦀' () Encodes 1–4 UTF-8 bytes directly into Builder b
Explicit cast Rune(0x1F680), Int('λ') Rune / Int Zero-cost identity conversion
String length vs runes ?str vs ??str Int ?str returns UTF-8 byte count; ??str counts Unicode runes
#use io

b = {16}
b += 'A'
b += 'λ'
b += '🦀'
s = +b
io::out $ (?s, ??s, Int('λ'))   // (7, 3, 955)

8.5 Zero-sized Unit type (())

() represents the zero-sized type (lowered to LLVM void).

Context Syntax Validity & Semantics Diagnostic
Type signature log: String => ()
cb: (Int => ()) => ()
Valid: declares void return or void callback parameter —
Type-shape guard (#!) T [()] "unit" | "other" Valid: matches Unit at compile time —
Value expression x = () or f(()) Forbidden: () is strictly a type, never a value literal E2104
Implicit unit producers x = 10, cond | side_effect(), --| expr, empty ram slots Evaluate to () at the expression site with 0 runtime bytes —