Skip to content

Add u8 type, i8 comparisons, and byte casts - #76

Merged
wtholliday merged 1 commit into
mainfrom
u8-and-i8-comparisons
Oct 19, 2026
Merged

wtholliday merged 1 commit into
mainfrom
u8-and-i8-comparisons

Conversation

@wtholliday

Copy link
Copy Markdown
Collaborator

Summary

  • u8 is now a source-level type. The internal UInt8 type already existed; this adds the u8 keyword, parsing, and casts between u8 and i32/u32 on the Cranelift JIT, LLVM JIT, register VM, and stack VM. Like i8, u8 has casts and equality but no arithmetic, and plain integer literals still infer as i32, so values are made with as u8.
  • i8 gains ordered comparisons (<, >, <=, >=) and casts to and from u8 and u32. i8 to u32 sign-extends to 32 bits, so -1 as i8 becomes the maximum u32.
  • Register VM byte fix. Load8 zero-extends while the i32 to i8 cast sign-extends, so a negative i8 read from memory never compared equal to a cast one, and would have ordered wrongly. Loads of i8 now sign-extend afterwards. The register VM holds i8 sign-extended and u8 zero-extended. The stack VM's Load8 sign-extends, so it keeps both byte types sign-extended and masks u8 when widening.
  • Docs: u8 added to the grammar and both type tables in the language guide, which now also say that i8 and u8 have no arithmetic.

Notes

  • u8 is now a reserved word, so a program that used u8 as an identifier will stop parsing.
  • u8 has no ordered comparisons yet. The stack VM would need to switch u8 to a zero-extended form first.
  • Not addressed: the register VM lays out aggregates without alignment, so a 1-byte field followed by an i32 aborts on the VM. This predates the change but is easier to hit with u8.

Test plan

  • New golden tests tests/cases/int_types_u8.lyte and tests/cases/int_types_i8_compare.lyte. The latter checks that a negative i8 loaded from an array compares equal to and orders against cast values, which fails on main for the VM.
  • tests/cases/slices/empty_string_bytecode.lyte regenerated for the extra sign-extension instruction after i8 loads.
  • cargo test --workspace --features llvm passes on all five backends: jit, vm, asm, stack, llvm (built with LLVM_SYS_191_PREFIX=/opt/homebrew/opt/llvm@19).

🤖 Generated with Claude Code

Add `u8` as a source-level type. The internal `UInt8` type already
existed, so this wires it through the lexer and parser and adds casts
between u8 and i32/u32 on every backend. Like i8, u8 has no arithmetic
and plain integer literals still infer as i32, so values are made with
`as u8`.

Add ordered comparisons for i8 and casts between i8 and u8/u32.

Fix a register VM bug this exposed: Load8 zero-extends but the i32->i8
cast sign-extends, so a negative i8 read from memory never compared
equal to a cast one. Loads of i8 now sign-extend afterwards. i8 is held
sign-extended and u8 zero-extended on the register VM. The stack VM's
Load8 sign-extends, so it keeps both byte types sign-extended and masks
u8 when widening.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@wtholliday
wtholliday merged commit cd2511b into main Oct 19, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant