plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


plum-std/ByteSlice.plum
module std
import std/Byte
import std/Str
import std/Bool
import std/Number

# ByteSlice is `[]Byte` — Plum's counterpart to Go's byte slice: a
# fixed-length, mutable sequence of raw bytes backed directly by a wasm-gc
# `array<i8>` (see `plum-wasm-codegen`'s `PlumType::TByteSlice`) — the same
# raw array type `Buffer`'s own `data` field uses underneath (`Str` itself is
# now a real two-level struct wrapping a `Buffer`, not this array directly;
# see `str.plum`'s header comment). Every method here, and `makeBytes`/
# `copyBytes` below, is a compiler intrinsic (see `compileIntrinsicFnBody`)
# — there's no way to express raw array length/indexing/construction/copying
# in Plum source itself; `copyStrToBytes`/`bytesToStr` build on top of them
# instead of needing intrinsics of their own.
enum ByteSlice =
  | ByteSlice

  # Number of bytes in the slice.
  fun length(self) -> Int =
    todo

  # The raw byte at index `i`. Traps if `i` is out of range.
  fun get(self, i: Int) -> Byte =
    todo

  # Overwrites the byte at index `i` with `b`. Traps if `i` is out of range.
  fun set(self, i: Int, b: Byte) -> Unit =
    todo

# A new zero-filled `[]Byte` of length `n`.
fun makeBytes(n: Int) -> []Byte =
  todo

# Copies `n` bytes from `src` (starting at `srcStart`) into `dst` (starting at
# `dstStart`). `dst` and `src` may be the same slice — overlapping ranges are
# handled correctly, matching wasm's `array.copy`.
fun copyBytes(dst: []Byte, dstStart: Int, src: []Byte, srcStart: Int, n: Int) -> Unit =
  todo

# Like `copyBytes`, but the source is a `Str` — ordinary Plum glue over
# `copyBytes` itself, reaching through `Str`'s real `data: Buffer` field to
# its own `data: []Byte` (see `str.plum`'s header comment on `Str`'s shape).
fun copyStrToBytes(dst: []Byte, dstStart: Int, src: Str, srcStart: Int, n: Int) -> Unit =
  copyBytes(dst, dstStart, src.data.data, srcStart, n)

# Copies out `n` bytes of `src` starting at `start` into a fresh, independent
# `Str` — never aliases `src`, so mutating `src` afterwards can't
# retroactively change an already-returned `Str`. Ordinary Plum: allocate a
# right-sized `[]Byte`, copy into it, wrap it in a fresh `Buffer`/`Str` pair.
fun bytesToStr(src: []Byte, start: Int, n: Int) -> Str =
  data := makeBytes(n)
  copyBytes(data, 0, src, start, n)
  return Str(data: Buffer(data: data, len: n))