Skip to content

Unsigned Integer Types #1

@iso2t

Description

@iso2t

Summary

This proposal adds support for unsigned integer types (u8, u16, u32, u64, usize) to Loom. These types mirror their signed counterparts (i8, i16, i32, i64, isize) but represent only non-negative values and offer greater upper bounds. Unsigned integers are essential for bare-metal programming, allowing precise and safe manipulation of memory, indices, and binary data.


Motivation

Loom is designed for bare-metal targets with extreme fine control. Unsigned integers are critical for the following reasons:

  • Memory-mapped I/O and device registers rarely use negative values.
  • Bit manipulation is more predictable without sign-extension.
  • Network packets and protocol fields are commonly unsigned.
  • Sizes, lengths, and indexes are naturally non-negative.
  • Unsigned types allow a greater positive range with the same bit width.

Without unsigned support, developers are forced into workarounds or unsafe casts that violate Loom’s design principles of precision and control.


Guide-Level Explanation

Loom would support the following types:

Signed Unsigned Description
i8 u8 8-bit integer
i16 u16 16-bit integer
i32 u32 32-bit integer
i64 u64 64-bit integer
isize usize Pointer-width int

Example

pub func main(argc: []i64, argv: []string) -> i64 {
    var length -> u32 = 1024u32;
    var port -> u16 = 8080u16;
    var mask -> u8 = 0xFFu8;
    
    print("Length: %d\n", length);
    print("Port: %d\n", port);
    print("Mask: %d\n", mask);
    
    return 0;
}

Casting

All conversions between signed and unsigned integers must be explicit:

var x -> i32 = -42;
var y -> u32 = x as u32; // wraps or truncates explicitly

Overflow Semantics

Loom may introduce distinct operators for handling overflow:

a +% b; // wrapping add
a +! b; // checked add, traps on overflow
a +? b; // saturating add

Reference-Level Explanation

Grammar Changes

Extend the type grammar to include:

Type ::= "i8" | "i16" | "i32" | "i64"
       | "u8" | "u16" | "u32" | "u64"
       | "isize" | "usize"

Support typed literals using suffixes:

let maxByte -> u8 = 255u8;
let big -> u64 = 0xFFFF_FFFF_FFFF_FFFFu64;

Type System
• Add u8, u16, u32, u64, usize as primitive types.
• Ensure arithmetic, comparison, and bitwise operators support unsigned operands.
• Prevent implicit coercion between signed and unsigned types.

Codegen
• Use unsigned IR and machine instructions (e.g., movzx, unsigned div, cmp).
• For usize, emit pointer-width integer types depending on target (32-bit, 64-bit, etc.).

Diagnostics
• Warn on implicit conversions between signed/unsigned types.
• Provide clear errors for type mismatches and undefined overflow behavior.

Drawbacks
• Adds complexity to the language and the type system.
• Requires developers to understand the difference between signed and unsigned arithmetic.
• Increases the burden on tooling (type checker, codegen, etc.).

Alternatives
• Do not include unsigned types (rejected for low-level systems use).
• Emulate unsigned types through libraries or annotations (not viable for low-level performance).
• Rely only on usize for indexing (too limited and ambiguous for general use).

Prior Art
• C: Longtime support for unsigned types; implicit coercion leads to bugs.
• Rust: Strictly separates signed/unsigned, with explicit conversions and overflow operators.
• Zig: Heavy use of unsigned types with robust safety and performance semantics.
• Java: Lacks native unsigned types, causing issues in systems work.

Unresolved Questions
• Should usize always match pointer width or be configurable?
• Should Loom provide overflow operators (+%, +!, +?) as language features or compiler intrinsics?
• Should type inference prefer signed or unsigned when ambiguous?

Future Directions
• Add support for wider unsigned types (u128, u256) for crypto or VM applications.
• Define compile-time arithmetic evaluation with overflow semantics.
• Enable bitfield and register-mapped structs for embedded/firmware programming.
• Introduce trait-like interfaces for generic arithmetic over integer types.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions