Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/codegen_deno.ml
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,19 @@ let () =
(* Recursive file walk — depth-first, returns every file path under
`root`. Filtering by extension is the caller's responsibility. *)
b "walkRecursive" (fun a -> Printf.sprintf "__as_walkRecursive(%s)" (arg 0 a));
(* Bytes I/O — construction + LE getters/setters (campaign #239 STEP
4-A / standards#326). Setters return 0 so they compose in an
expression-statement position. All multi-byte ints are LE. *)
b "bytes_new" (fun a -> Printf.sprintf "new Uint8Array(%s)" (arg 0 a));
b "bytes_fill" (fun a -> Printf.sprintf "(new Uint8Array(%s)).fill((%s) & 0xFF)" (arg 0 a) (arg 1 a));
b "bytes_set_u8" (fun a -> Printf.sprintf "((new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).setUint8(%s, (%s) & 0xFF), 0)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a) (arg 2 a));
b "bytes_set_u16_le" (fun a -> Printf.sprintf "((new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).setUint16(%s, (%s) & 0xFFFF, true), 0)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a) (arg 2 a));
b "bytes_set_u32_le" (fun a -> Printf.sprintf "((new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).setUint32(%s, (%s) >>> 0, true), 0)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a) (arg 2 a));
b "bytes_set_i32_le" (fun a -> Printf.sprintf "((new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).setInt32(%s, (%s) | 0, true), 0)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a) (arg 2 a));
b "bytes_get_u8" (fun a -> Printf.sprintf "(new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).getUint8(%s)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a));
b "bytes_get_u16_le" (fun a -> Printf.sprintf "(new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).getUint16(%s, true)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a));
b "bytes_get_u32_le" (fun a -> Printf.sprintf "(new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).getUint32(%s, true)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a));
b "bytes_get_i32_le" (fun a -> Printf.sprintf "(new DataView((%s).buffer, (%s).byteOffset, (%s).byteLength)).getInt32(%s, true)" (arg 0 a) (arg 0 a) (arg 0 a) (arg 1 a));
(* `new RegExp(pat).test(s)` — minimal regex surface. Invalid `pat`
throws at call time (RegExp constructor error). *)
b "regexMatch" (fun a -> Printf.sprintf "__as_regexMatch(%s, %s)" (arg 0 a) (arg 1 a));
Expand Down
43 changes: 43 additions & 0 deletions stdlib/Deno.affine
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,49 @@ pub extern fn statSize(path: String) -> Int;
/// filter by extension). Throws on a missing root via `Deno.readDirSync`.
pub extern fn walkRecursive(root: String) -> [String];

// ── Bytes I/O (construction + LE getters/setters) ──────────────────
//
// Construction + per-field read/write at byte offsets. Companion to
// the read-only `bytesLength` / `bytesByteAt` / `bytesAsciiSlice`
// accessors (campaign #239 STEP 3 / standards#242). All multi-byte
// integer variants are little-endian — the estate's C ABI contracts
// (raze-tui `raze-events.ads`, Idris2 `Events.idr`) are LE-pinned.
//
// Setters return `Int = 0` so they compose in expression-statement
// position; the caller is responsible for the buffer-bounds invariant
// (an out-of-range offset throws `RangeError` at the host boundary).
// Bounds-check via `bytesLength` from STEP 3.

/// `new Uint8Array(n)` — zeroed buffer of `n` bytes.
pub extern fn bytes_new(n: Int) -> Bytes;

/// `new Uint8Array(n).fill(byte & 0xFF)` — all-`byte` buffer.
pub extern fn bytes_fill(n: Int, byte: Int) -> Bytes;

/// Write `v & 0xFF` to byte `offset`.
pub extern fn bytes_set_u8(b: Bytes, offset: Int, v: Int) -> Int;

/// Write `v & 0xFFFF` to bytes `[offset, offset+2)` as little-endian u16.
pub extern fn bytes_set_u16_le(b: Bytes, offset: Int, v: Int) -> Int;

/// Write `v >>> 0` to bytes `[offset, offset+4)` as little-endian u32.
pub extern fn bytes_set_u32_le(b: Bytes, offset: Int, v: Int) -> Int;

/// Write `v | 0` to bytes `[offset, offset+4)` as little-endian i32.
pub extern fn bytes_set_i32_le(b: Bytes, offset: Int, v: Int) -> Int;

/// Read byte at `offset` (0..255).
pub extern fn bytes_get_u8(b: Bytes, offset: Int) -> Int;

/// Read bytes `[offset, offset+2)` as little-endian u16 (0..65535).
pub extern fn bytes_get_u16_le(b: Bytes, offset: Int) -> Int;

/// Read bytes `[offset, offset+4)` as little-endian u32 (0..4294967295).
pub extern fn bytes_get_u32_le(b: Bytes, offset: Int) -> Int;

/// Read bytes `[offset, offset+4)` as little-endian i32 (-2147483648..2147483647).
pub extern fn bytes_get_i32_le(b: Bytes, offset: Int) -> Int;

// ── Path ───────────────────────────────────────────────────────────

/// Single-segment join with a `/` separator (idempotent on a trailing
Expand Down
43 changes: 43 additions & 0 deletions tests/codegen-deno/bytes_binary_io.affine
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: MPL-2.0
// campaign #239 STEP 4-A — binary I/O smoke (raze-tui RazeEvent shape).
//
// Round-trips the 16-byte event record that estate ABI tests build and
// parse byte-by-byte:
//
// offset 0 size 4 i32_le kind
// offset 4 size 4 u32_le key_code
// offset 8 size 1 u8 modifiers
// offset 9 size 1 pad
// offset 10 size 2 u16_le mouse_x
// offset 12 size 2 u16_le mouse_y
// offset 14 size 2 pad
// Total: 16 bytes

use Deno::{ Bytes, bytes_new, bytes_fill,
bytes_set_u8, bytes_set_u16_le, bytes_set_u32_le, bytes_set_i32_le,
bytes_get_u8, bytes_get_u16_le, bytes_get_u32_le, bytes_get_i32_le };

pub fn build_event(kind: Int, key_code: Int, modifiers: Int, mouse_x: Int, mouse_y: Int) -> Bytes {
// Uniquely-named `let` discards keep the codegen pre-#504-compatible
// (the `PatWildcard` fix from #504 also works, but isn't required).
let b = bytes_new(16);
let _r0 = bytes_set_i32_le(b, 0, kind);
let _r4 = bytes_set_u32_le(b, 4, key_code);
let _r8 = bytes_set_u8(b, 8, modifiers);
let _ra = bytes_set_u16_le(b, 10, mouse_x);
let _rc = bytes_set_u16_le(b, 12, mouse_y);
b
}

pub fn read_kind(b: Bytes) -> Int { bytes_get_i32_le(b, 0) }
pub fn read_key_code(b: Bytes) -> Int { bytes_get_u32_le(b, 4) }
pub fn read_modifiers(b: Bytes) -> Int { bytes_get_u8(b, 8) }
pub fn read_mouse_x(b: Bytes) -> Int { bytes_get_u16_le(b, 10) }
pub fn read_mouse_y(b: Bytes) -> Int { bytes_get_u16_le(b, 12) }

pub fn fill_byte(n: Int, byte: Int) -> Bytes { bytes_fill(n, byte) }

pub fn fill_first(n: Int, byte: Int) -> Int {
let b = bytes_fill(n, byte);
bytes_get_u8(b, 0)
}
Loading