plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
plum-std/Array.plum
| ea9b8c1 | 1 | module std |
| 73b5e55 | 2 | import std/Bool |
| ca5fd6f | 3 | import std/Number |
| ea9b8c1 | 4 | |
| ea9b8c1 | 5 | # A fixed-length, O(1)-indexable array of `T`, backed directly by a wasm-gc |
| ea9b8c1 | 6 | # `array<anyref>` — every `Array[T]` specialization (`Array$Int`, `Array$Str`, |
| ea9b8c1 | 7 | # ...) shares the SAME underlying wasm array type (see |
| ea9b8c1 | 8 | # `plum-wasm-codegen::GcTypeRegistry::array_type_idx`), exactly like `[]Byte` |
| ea9b8c1 | 9 | # reuses `Str`'s own array type. `init`/`get`/`set`/`length` are compiler |
| ea9b8c1 | 10 | # intrinsics (see `compileIntrinsicFnBody`) — there's no way to express raw |
| ea9b8c1 | 11 | # array allocation/indexing in Plum source itself. |
| ea9b8c1 | 12 | # |
| ea9b8c1 | 13 | # LIMITATION: `T` must be a reference type (a `type`/`enum` value, `Str`, |
| ea9b8c1 | 14 | # `List`, etc.) — every element is stored as a boxed `anyref` and `get` |
| ea9b8c1 | 15 | # narrows it back to `T` via `ref.cast`. A primitive `T` (`Int`/`Float`/`Bool`/ |
| ea9b8c1 | 16 | # `Byte`) is NOT supported (no boxing/unboxing exists yet) and will not |
| ea9b8c1 | 17 | # codegen correctly. Nothing in `libs/std` instantiates `Array` with a |
| ea9b8c1 | 18 | # primitive `T` today — the only user is `Map[K, V]`'s bucket array, |
| ea9b8c1 | 19 | # `Array[List[Pair[K, V]]]`. |
| ea9b8c1 | 20 | # |
| ea9b8c1 | 21 | # `init()` is deliberately zero-arg (no `Array[T](n)` constructor exists) — |
| ea9b8c1 | 22 | # `class_call`'s grammar (`Type[Generics](...)`) only ever accepts `name: |
| ea9b8c1 | 23 | # value` field arguments or an empty arg list, never bare positional ones |
| ea9b8c1 | 24 | # (see `tooling/tree-sitter-plum/grammar.js`'s `class_argument_list`), and |
| ea9b8c1 | 25 | # `Array` has no real fields for a keyword arg to bind to. Building a |
| ea9b8c1 | 26 | # specific-length array is `push`ing onto an empty one `n` times instead |
| ea9b8c1 | 27 | # (`Map`'s bucket array does exactly this at construction) — `push` itself |
| ea9b8c1 | 28 | # has no in-place "grow" to fall back on either (a wasm-gc `array` is a |
| ea9b8c1 | 29 | # fixed-length allocation once made), so it allocates a new, one-longer array |
| ea9b8c1 | 30 | # and copies, same amortized-growth idea as `Buffer`'s own `write`. |
| ea9b8c1 | 31 | # |
| ea9b8c1 | 32 | # New elements start out `None`-shaped — really a null `anyref` under the |
| ea9b8c1 | 33 | # hood — so `get` on an index that was never `set` traps rather than |
| ea9b8c1 | 34 | # returning some default `T` value (there is no way to conjure a default `T` |
| ea9b8c1 | 35 | # generically). |
| 5f2f962 | 36 | enum Array[T] = |
| 5f2f962 | 37 | | Array |
| 5f2f962 | 38 | |
| ea9b8c1 | 39 | # A new, empty array. |
| ea9b8c1 | 40 | fun init() -> Array[T] = |
| ea9b8c1 | 41 | todo |
| ea9b8c1 | 42 | |
| ea9b8c1 | 43 | # The element at index `i`. Traps if `i` is out of range or was never `set`. |
| ea9b8c1 | 44 | fun get(self, i: Int) -> T = |
| ea9b8c1 | 45 | todo |
| ea9b8c1 | 46 | |
| ea9b8c1 | 47 | # Overwrites the element at index `i` with `v`. Traps if `i` is out of range. |
| ea9b8c1 | 48 | fun set(self, i: Int, v: T) -> Unit = |
| ea9b8c1 | 49 | todo |
| ea9b8c1 | 50 | |
| ea9b8c1 | 51 | # Number of slots in the array. |
| ea9b8c1 | 52 | fun length(self) -> Int = |
| ea9b8c1 | 53 | todo |
| ea9b8c1 | 54 | |
| ea9b8c1 | 55 | # Returns a NEW array, one longer than `self`, with `v` appended at the end |
| ea9b8c1 | 56 | # — `self` itself is left untouched (this allocates and copies, it does not |
| ea9b8c1 | 57 | # mutate in place). Callers grow in a loop by reassigning: `arr = |
| ea9b8c1 | 58 | # arr.push(v)`. |
| ea9b8c1 | 59 | fun push(self, v: T) -> Array[T] = |
| ea9b8c1 | 60 | todo |