Forge

Type System

Forge has a static type system with explicit annotations and inference for literals.

Primitive Types

Integers

Type Aliases Size Range
int8 i8 8-bit signed -128 to 127
int16 i16 16-bit signed -32,768 to 32,767
int32 i32, int 32-bit signed -2^31 to 2^31-1
int64 i64 64-bit signed -2^63 to 2^63-1
uint8 u8, byte 8-bit unsigned 0 to 255
uint16 u16 16-bit unsigned 0 to 65,535
uint32 u32, uint 32-bit unsigned 0 to 2^32-1
uint64 u64 64-bit unsigned 0 to 2^64-1
usize — pointer-sized unsigned (maps to uint64) platform-dependent
isize — pointer-sized signed (maps to int64) platform-dependent

int128 / uint128 are accepted by the type checker but unsupported by all backends — compilation fails at codegen. See Known Issues.

Floats

Type Aliases Size Notes
float32 f32 32-bit IEEE 754 single; x86_64 only
float64 f64, float 64-bit IEEE 754 double; x86_64 only

Floats are not supported on the x86_32 target. On x86_64, float values are stored as 64-bit integer bit patterns in registers.

Other Primitives

Type Description
bool true or false
char 8-bit character (like a byte)
void No value (function return type only)

Pointer Types

ptr[T]       # Pointer to T
let x: int32 = 42
let p: ptr[int32] = &x        # Address of a local
let q = 0x1000 as ptr[int32]  # Integer literal as pointer

Pointers:

There is no separate mut ptr[T] spelling — mutability is expressed with var bindings and enforced by the unsafe rules.

Composite Types

Structs

struct Point:
    x: int32
    y: int32

Generic Structs

struct Pair[T]:
    first: T
    second: T

Generic structs are instantiated with a type application and monomorphized per instantiation:

var p: Pair[int64] = Pair[int64] { first: 3, second: 4 }
var q: Pair[Pair[int64]] = Pair[Pair[int64]] { first: p, second: p }

Arrays

let arr = [1, 2, 3]   # Array literal
let x = arr[0]

Array literals and indexing work. Fixed-size type annotations ([int32; 5]) and repeat literals ([0; 3]) are not supported yet.

Tuples

let t: (int64, int64) = (3, 4)
let a = t.0        # Field access by index
var (x, y) = t     # Destructuring

Tuples work end-to-end on x86_64 and x86_32: literals, type annotations, indexed field access (t.0, t.1), destructuring, and tuple return types (def pair() -> (int64, int64)).

Enums & Unions

enum Color:
    Red
    Green
    Blue

enum declarations are fully supported. Variants can be constructed (Color.Red, Option.Some(42)), matched on with match/case, and destructured to bind payload values (case Option.Some(x):). See Control Flow › Match Expression for details.

union declarations are accepted by the parser and type checker, but cannot be constructed — codegen support is not yet implemented. See Known Issues.

Type Inference

Types are inferred when possible:

let x = 42        # int32 (default integer)
let y = 3.14      # float64 (default float)
let z = true      # bool
let s = "hello"   # ptr[char] (string literal)

Explicit annotation is used when needed:

let x: int64 = 42
let f: float64 = 1.5

Casts

There are no implicit numeric conversions — explicit as casts are required:

let y = x as int64      # Integer widening/narrowing
let f = 42 as float64   # Integer to float
let i = 3.7 as int32    # Float to integer (truncating)
let p = 0x1000 as ptr[int32]  # Integer to pointer
let addr = p as int64   # Pointer to integer

sizeof / offsetof

let size = sizeof(u32)         # Size of a type in bytes
let size2 = sizeof(MyStruct)
let off = offsetof(Point, y)   # Byte offset of a field

Both return usize-typed values and work on primitives and struct types.

Unsupported Types

The following type forms parse but are not functional yet — see Known Issues: