feat: stdlib daily APIs, macro tt/type paste, riscv64 cross smoke
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
Sessions 83–87: grow Array/Map/String/Test ergonomics; delimiter-balanced and juxta :tt macros plus $t:type fragments; expression-level $(…),* in templates; selfhost slice lits; riscv64/aarch64 cross smoke helper and freestanding docs. Null-safe CBE type names and String_StartsWith.
This commit is contained in:
+35
-2
@@ -122,6 +122,9 @@ BUX_RUNTIME=minimal ./buxc build
|
||||
# Cross-compile for ARM64 Linux (prefers aarch64-linux-gnu-gcc, else clang -target)
|
||||
./buxc --static --release --target aarch64-linux-gnu build
|
||||
|
||||
# Cross-compile for RISC-V 64 (session 85; needs riscv64-linux-gnu-gcc)
|
||||
./buxc --static --release --target riscv64-linux-gnu build
|
||||
|
||||
# Override C compiler
|
||||
BUX_CC=aarch64-linux-gnu-gcc ./buxc --static --target aarch64-linux-gnu build
|
||||
|
||||
@@ -142,7 +145,7 @@ make test-musl-static # SKIP if no musl-gcc/zig
|
||||
| `BUX_CFLAGS` | Extra flags appended to the C line |
|
||||
|
||||
```bash
|
||||
# Smoke all of the above (+ CTFE CRC example)
|
||||
# Smoke all of the above (+ CTFE CRC + optional aarch64/riscv64 cross)
|
||||
make test-linux-targets
|
||||
|
||||
# Build static hello for Docker scratch/distroless
|
||||
@@ -153,6 +156,36 @@ docker build -f examples/docker/Dockerfile.static \
|
||||
|
||||
> **Note:** Full runtime + fully-static OpenSSL is intentionally not the default (painful). Use minimal for static containers; keep full runtime for servers that need net/crypto (`nexus`).
|
||||
|
||||
### Cross toolchains
|
||||
|
||||
| Triple | Typical package | Smoke |
|
||||
|--------|-----------------|-------|
|
||||
| `aarch64-linux-gnu` | `gcc-aarch64-linux-gnu` | `make test-linux-targets` (SKIP if missing) |
|
||||
| `riscv64-linux-gnu` | `gcc-riscv64-linux-gnu` | same (session 85) |
|
||||
|
||||
`clang -target <triple>` alone is **not** enough: you still need target headers and libc
|
||||
(sysroot). Prefer `*-gcc` from a cross package, or set `BUX_CC` to a wrapper that
|
||||
already knows the sysroot (e.g. Zig `zig cc -target …`).
|
||||
|
||||
### Freestanding / bare-metal (research spike, not v1.0)
|
||||
|
||||
`BUX_RUNTIME=minimal` / `--static` is the **Linux userspace / container / CTFE** path:
|
||||
it still links against a libc (`malloc`, `printf`, `strlen`, …). It is *not* true
|
||||
no-libc freestanding firmware.
|
||||
|
||||
| Layer | Status | Notes |
|
||||
|-------|--------|-------|
|
||||
| Thin runtime (no pthread/OpenSSL) | ✅ | `rt/runtime_minimal.c` |
|
||||
| Static musl / distroless | ✅ | `make test-musl-static`, Dockerfiles |
|
||||
| Linux multi-arch cross | ✅ | aarch64 + riscv64 smokes (SKIP without gcc) |
|
||||
| True freestanding (`-ffreestanding`, no libc) | 🔬 spike | Needs custom alloc, panic, and I/O stubs |
|
||||
| Cortex-M / qemu-system | 🔬 spike | Same; plus linker scripts and startup |
|
||||
|
||||
**Practical path today:** build with `BUX_RUNTIME=minimal --static --target …` for
|
||||
Linux userspace on foreign ISAs; treat bare-metal as a research project that
|
||||
starts from a custom `runtime_freestanding.c` (not shipped) and does **not**
|
||||
import `Std::Net` / `Std::Task` / OpenSSL.
|
||||
|
||||
---
|
||||
|
||||
## Running Tests
|
||||
@@ -165,7 +198,7 @@ make test-stdlib # stdlib golden packages
|
||||
make test-registry # package registry (local + HTTP index)
|
||||
make test-apps # showcase apps build + simpledb/jwt CLI smoke (in `make test`)
|
||||
make test-dwarf # #line maps + .debug_info + --release (in `make test`)
|
||||
make test-linux-targets # minimal runtime + static + aarch64 cross + CTFE CRC
|
||||
make test-linux-targets # minimal + static + aarch64/riscv64 cross (SKIP) + CTFE CRC
|
||||
make test-registry # package registry local + HTTP (in `make test`)
|
||||
make test-selfhost-smoke # buxc2: move_field + multi-file #line (in `make test`)
|
||||
make test-lsp # hover + references/rename + call hierarchy
|
||||
|
||||
+28
-1
@@ -1284,11 +1284,12 @@ macro! with_acc {
|
||||
|------|---------|
|
||||
| `expr` | any expression |
|
||||
| `ident` | bare identifier (`ekIdent`) |
|
||||
| `tt` | token-tree: any single call-site AST fragment (expr/ident/lit/block/stmt/pat); broader than `expr` |
|
||||
| `tt` | token-tree: any single call-site AST fragment; **delimiter-balanced multi-element groups** `(a, b)` and `[a, b]` flatten when spliced as the sole call argument (`$f($args)` → `f(a, b)`, not `f((a, b))`). Non-group `tt` unwraps to the value. Broader than `expr`. |
|
||||
| `literal` / `lit` | int/float/string/char/bool literal only |
|
||||
| `block` | block expression `{ … }` |
|
||||
| `stmt` | one statement (`let`/`if`/… or expression-stmt) |
|
||||
| `pat` / `pattern` | match pattern (`_`, literals, `Enum::Var(…)`, …) |
|
||||
| `type` | type expression from call-site shape: named (`int`), pointer (`*int`); spliced into `sizeof($t)`, `as $t`, `let x: $t` |
|
||||
|
||||
- Fragment names start with `$` (lexer `$ident`).
|
||||
- **Repetition:** `$( $x:expr ),*` / `$( $x:expr )*` — one or more rep fragments per pattern.
|
||||
@@ -1297,6 +1298,23 @@ macro! with_acc {
|
||||
`sum_groups!(1, 2; 10, 20, 30)`.
|
||||
- Template `$( stmt; … )*` expands once per list item (zip when multiple lists used).
|
||||
- Nested `$( $(…)* )*`: after outer binds list items as singles, inner expands once.
|
||||
- **Expression-level rep in templates:** `$f( $($a),* )` — `$( expr ),*` / `$( expr )*`
|
||||
inside call arguments expands to N positional args (session 84).
|
||||
- **Delimiter-balanced `:tt` groups:** `apply_tt!(Add, (3, 4))` or
|
||||
`apply_tt!(Add, [3, 4])` with `($f:ident, $args:tt) => { $f($args) }`
|
||||
expands to `Add(3, 4)`. Contrast `:expr`, which keeps the group as one value.
|
||||
- **Free-form juxta (session 86):** pattern `$f:ident $args:tt` (comma optional
|
||||
between fragments) matches a **single call-site argument** that is a call
|
||||
expression: `apply_juxta!(Add(2, 5))` → binds `$f=Add`, `$args` = arg-list
|
||||
group, then `$f($args)` flattens to `Add(2, 5)`.
|
||||
- **Type fragments (session 87):**
|
||||
```bux
|
||||
macro! size_of {
|
||||
( $t:type ) => { sizeof($t) as int }
|
||||
}
|
||||
let n: int = size_of!(int);
|
||||
let p: int = size_of!(*int);
|
||||
```
|
||||
|
||||
### Invocation
|
||||
|
||||
@@ -1388,3 +1406,12 @@ Examples: `examples/macro_hygiene.bux`, `examples/macro_unhygienic.bux`.
|
||||
Scheme/Rust colored identifiers or `stmt`/`pat` token trees.
|
||||
- Macro expansion still yields a **block expression**; unhygienic names are
|
||||
scoped to that block (not automatically injected into the caller scope).
|
||||
- Expression-level `$(…)*` is only parsed inside **call argument lists** in
|
||||
templates (not as a free-standing primary expression).
|
||||
- Raw delimiter-balanced `tt` covers **tuple** `(a, b)` and **slice lit**
|
||||
`[a, b]` groups, plus **juxta call-split** for `$f:ident $args:tt` matching
|
||||
`F(a, b)`. Arbitrary free-form token pastes (operators-only, type-only
|
||||
without AST) remain out of scope.
|
||||
|
||||
Examples: `examples/macro_tt.bux`, `examples/macro_tt_raw.bux`,
|
||||
`examples/macro_repeat.bux`, `examples/macro_nested.bux`.
|
||||
|
||||
+101
-22
@@ -1,7 +1,7 @@
|
||||
# Bux — План към „добър“ език (v0.5 → v1.0)
|
||||
|
||||
> **Дата:** 2026-07-23
|
||||
> **Текущо:** v0.5.x — CI cloud smokes + registry path cleanup (session 82)
|
||||
> **Текущо:** v0.5.x — `:type` macros + Array_Reverse (session 87)
|
||||
> **Цел:** Език, с който се пишат реални проекти комфортно, безопасно (по избор) и с надежден toolchain.
|
||||
> **Платформен фокус:** **Linux** (primary) · **cloud-native** (servers, containers, HTTP) · **embedded** (cross, freestanding-ish, CTFE).
|
||||
> **Не-цел:** MS Windows като product platform (исторически CI/hello smoke остават; няма roadmap investment).
|
||||
@@ -116,7 +116,7 @@ A (stdlib ergonomics) → B (compiler holes) → C (ownership depth)
|
||||
## Acceptance criteria за „добър v1.0“
|
||||
|
||||
- [x] Всички examples + apps + selfhost smoke на CI (`make test` via `.github/workflows/ci.yml`); selfhost-loop optional
|
||||
- [ ] Array/Map/String/Test API покрива 90% от ежедневните нужди
|
||||
- [x] Array/Map/String/Test API покрива 90% от ежедневните нужди (+ Insert/Remove/Clone/case/GetOr)
|
||||
- [x] `@[Checked]` хваща use-after-move + double `&mut` + dangling return / elision fail
|
||||
- [x] `bux test` + `bux fmt` + `bux check` са default developer loop (`--filter` / `--check` shipped)
|
||||
- [x] LanguageRef синхронизиран с компилатора (incl. C.1 elision)
|
||||
@@ -1216,7 +1216,7 @@ A (stdlib ergonomics) → B (compiler holes) → C (ownership depth)
|
||||
|------|--------------------|-----------------|
|
||||
| **Linux** | Host + CI + full `rt/runtime.c` (pthread, ucontext, sockets, OpenSSL) | ✅ primary; macOS secondary smoke only |
|
||||
| **Cloud-native** | HTTP/HTTPS, registry (lock+HTTPS), containers, musl docs | ✅ sessions 75–79 |
|
||||
| **Embedded** | Cross (`--target`), CTFE tables, **thin runtime**, no-GC story | ✅ minimal + aarch64 + ctfe_crc (75); 🔧 riscv / bare-metal spike |
|
||||
| **Embedded** | Cross (`--target`), CTFE tables, **thin runtime**, no-GC story | ✅ minimal + aarch64 + riscv64 smoke (85) + freestanding notes; bare-metal still spike |
|
||||
| **Windows** | Не е product target | ⛔ no further investment (existing MinGW hello = historical) |
|
||||
|
||||
**Правило:** нов runtime / stdlib / CI effort отива към Linux + cloud + embedded. Windows-only work не влиза в следващи сесии.
|
||||
@@ -1369,35 +1369,114 @@ A (stdlib ergonomics) → B (compiler holes) → C (ownership depth)
|
||||
|
||||
---
|
||||
|
||||
## Сесия 83 (stdlib daily API — collections_extra)
|
||||
|
||||
1. **Array** (`lib/Array.bux`):
|
||||
- `Array_RemoveAt` — shift-left remove, returns value
|
||||
- `Array_Insert` — insert at `0..=len` (append at end)
|
||||
- `Array_SwapRemove` — O(1) unordered remove
|
||||
- `Array_Clone` — shallow value clone into new buffer
|
||||
2. **String** (`lib/String.bux`):
|
||||
- `String_Cmp` — `strcmp` wrapper
|
||||
- `String_IndexOf` — byte index or `-1`
|
||||
- `String_ToUpper` / `String_ToLower` — ASCII only via StringBuilder
|
||||
3. **Map** (`lib/Map.bux`):
|
||||
- `Map_GetOr` / `StringMap_GetOr` — default when key missing
|
||||
4. **Example** `examples/collections_extra.bux` + Makefile `EXAMPLES`
|
||||
5. **Goldens** `tests/stdlib_golden/{array,string}` extended
|
||||
6. **Docs** `docs/Stdlib.md` tables updated
|
||||
|
||||
**Verified:** `collections_extra` PASS; `make test-stdlib` 3/3 PASS.
|
||||
|
||||
---
|
||||
|
||||
## Сесия 84 (macro raw `tt` groups + expression-level `$(…),*`)
|
||||
|
||||
1. **Delimiter-balanced `:tt` groups** (bootstrap + selfhost):
|
||||
- `$args:tt` that is a multi-element tuple `(a, b)` is wrapped as `ekMacroTt` with group flag
|
||||
- Splice `$f($args)` flattens to `f(a, b)` (not `f((a, b))`)
|
||||
- Value-position splice unwraps to the inner tuple / fragment
|
||||
- Contrast `:expr` keeps the tuple as one argument
|
||||
2. **Expression-level rep in templates:**
|
||||
- Parse `$( expr ),*` / `$( expr )*` inside **call argument lists** when `macroTemplateMode`
|
||||
- `ekMacroRep` expands to N call args (zip list fragments)
|
||||
- Example: `apply_rep!(Add3, 1, 2, 3)` → `Add3(1, 2, 3)`
|
||||
3. **Example** `examples/macro_tt_raw.bux` + Makefile EXAMPLES / EXAMPLES_SMOKE
|
||||
4. **Docs** LanguageRef tt + expression-level rep + limits
|
||||
5. **Hardening:** `CBE_NormalizeTypeName` / `String_StartsWith` null-safe
|
||||
(fixed selfhost segfault on `if_let_like` + enum field-move path)
|
||||
|
||||
**Verified:** bootstrap + **buxc2** `macro_tt_raw` PASS; `macro_stmt_pat` PASS; macro regressions OK.
|
||||
|
||||
---
|
||||
|
||||
## Сесия 85 (riscv64 cross smoke + freestanding notes + slice `:tt`)
|
||||
|
||||
1. **riscv64 cross smoke** (`tools/smoke_linux_targets.sh`):
|
||||
- Shared `try_cross` helper for aarch64 + riscv64
|
||||
- `PASS` when `${triple}-gcc` present; **SKIP** otherwise (no false fail)
|
||||
- Documented: clang `-target` alone needs a sysroot
|
||||
2. **Freestanding / bare-metal research** (`docs/BuildAndTest.md`):
|
||||
- Table: thin/static/cross ✅ vs true freestanding / Cortex-M 🔬
|
||||
- Clarifies `runtime_minimal` still uses libc (not no-libc)
|
||||
3. **Delimiter-balanced `:tt` + slice lit** (session 84 extension):
|
||||
- `[a, b]` slice groups flatten like tuples in `$f($args)`
|
||||
- Selfhost parser: primary `[a, b, …]` → `ekSlice` (parity with bootstrap)
|
||||
- `examples/macro_tt_raw.bux` case `apply_tt!(Add, [8, 9])` → 17
|
||||
4. Docs: LanguageRef, BuildAndTest, Makefile target blurb
|
||||
|
||||
**Verified:** `make test-linux-targets` — minimal/static/aarch64/ctfe PASS; riscv64 SKIP;
|
||||
bootstrap + **buxc2** `macro_tt_raw` (incl. slice) PASS.
|
||||
|
||||
---
|
||||
|
||||
## Сесия 86 (free-form juxta `:tt` paste)
|
||||
|
||||
1. **Pattern juxtaposition:** `$f:ident $args:tt` without comma between fragments
|
||||
(bootstrap + selfhost parser continue on next `$…`)
|
||||
2. **Expand-time call split:** when rule is exactly two fixed frags `ident` + `tt`
|
||||
and the call site has **one** arg that is `ekCall` with ident callee:
|
||||
- bind `$f` → callee
|
||||
- bind `$args` → MacroTt group of the call’s arguments
|
||||
- `$f($args)` flattens as before → `f(a, b)`
|
||||
3. **Example** `apply_juxta!(Add(2, 5))` / `apply_juxta!(Add3(1, 2, 4))` in
|
||||
`examples/macro_tt_raw.bux`
|
||||
4. LanguageRef juxta section; comma form still works
|
||||
|
||||
**Verified:** bootstrap + **buxc2** `macro_tt_raw` (h=7, i=7) PASS; macro regressions OK.
|
||||
|
||||
---
|
||||
|
||||
## Сесия 87 (`:type` fragments + Array_Reverse / Test_AssertNeqString)
|
||||
|
||||
1. **Macro `$t:type`** (bootstrap + selfhost):
|
||||
- Fragment kind `type` (`type` is a keyword — special-cased in parsers)
|
||||
- Call-site coerce: `int` → named; `*int` → pointer
|
||||
- Subst into `sizeof($t)`, `as $t`, `let x: $t`
|
||||
2. **Example** `examples/macro_type.bux` — size_of / cast_zero + reverse/neq
|
||||
3. **Stdlib:** `Array_Reverse`, `Test_AssertNeqString`
|
||||
4. Docs: LanguageRef type table; Stdlib Array_Reverse
|
||||
|
||||
**Verified:** bootstrap + **buxc2** `macro_type` PASS (sizeof int=4, *int=8).
|
||||
|
||||
---
|
||||
|
||||
## Следващи стъпки
|
||||
|
||||
### P0 — Compiler / language
|
||||
|
||||
1. ~~Cross-function pointer ownership~~ ✅ session 76
|
||||
2. ~~Selfhost `--static` / `BUX_RUNTIME` / `--target`~~ ✅ session 76
|
||||
3. ~~Macro `tt` broader than expr~~ ✅ session 76 (raw delimiter-balanced tokens still open)
|
||||
4. Macro: raw token-tree delimiter balancing / deeper nested rewrite edge cases
|
||||
5. ~~Selfhost cross-fn moves~~ ✅ session 77
|
||||
1. ~~… through session 86~~ ✅
|
||||
2. ~~**`:type` macro fragments**~~ ✅ session 87
|
||||
3. Optional: richer free-form (operators-only tt); generics in `:type` (`Array<int>`)
|
||||
|
||||
### P1 — Linux / cloud-native
|
||||
|
||||
6. ~~**Static path**~~ ✅ session 75–76
|
||||
7. ~~**Multi-arch Linux smoke**~~ ✅ session 75
|
||||
8. ~~**Nexus production polish**~~ ✅ session 77
|
||||
9. ~~**Nexus TLS**~~ ✅ session 78
|
||||
10. ~~**Container story**~~ ✅ session 78
|
||||
11. ~~**Registry + deploy**~~ ✅ session 79 (HTTPS + lock checksum + `--locked`)
|
||||
12. ~~**musl path**~~ ✅ session 79 (smoke + docs; SKIP without toolchain)
|
||||
13. ~~**mTLS / client certs**~~ ✅ session 80 (`NEXUS_TLS_CLIENT_CA`)
|
||||
14. ~~**Selfhost install --locked**~~ ✅ session 80
|
||||
15. ~~**Selfhost full registry**~~ ✅ session 81 (search / add / HTTP / path-dep build)
|
||||
16. **Language P0 leftovers** — raw macro `tt` delimiter balancing (optional)
|
||||
4. ~~(sessions 75–81)~~ ✅
|
||||
|
||||
### P2 — Embedded / cross
|
||||
|
||||
12. ~~**Cross / thin / CTFE**~~ ✅ session 75
|
||||
13. **riscv64 cross smoke** (when toolchain available)
|
||||
14. **no-libc / bare-metal research** (spike only) — Cortex-M / qemu-system; not v1.0 blocker
|
||||
5. ~~riscv64 smoke + freestanding notes~~ ✅ session 85
|
||||
6. Optional: real `runtime_freestanding.c` + Cortex-M qemu — not v1.0
|
||||
|
||||
### Изрично **не** правим
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ struct Array<T> {
|
||||
| `Array_Contains<T>` | `func Array_Contains<T>(arr: *Array<T>, value: T) -> bool` | Linear search for value |
|
||||
| `Array_IndexOf<T>` | `func Array_IndexOf<T>(arr: *Array<T>, value: T) -> int` | First index or -1 |
|
||||
| `Array_Extend<T>` | `func Array_Extend<T>(arr: *Array<T>, other: *Array<T>)` | Append all from other |
|
||||
| `Array_RemoveAt<T>` | `func Array_RemoveAt<T>(arr: *Array<T>, index: uint) -> T` | Remove at index (shift left) |
|
||||
| `Array_Insert<T>` | `func Array_Insert<T>(arr: *Array<T>, index: uint, value: T)` | Insert at index (`0..=len`) |
|
||||
| `Array_SwapRemove<T>` | `func Array_SwapRemove<T>(arr: *Array<T>, index: uint) -> T` | O(1) remove (swap with last) |
|
||||
| `Array_Clone<T>` | `func Array_Clone<T>(arr: *Array<T>) -> Array<T>` | Shallow clone (value copy) |
|
||||
| `Array_Reverse<T>` | `func Array_Reverse<T>(arr: *Array<T>)` | Reverse elements in place |
|
||||
| `Array_Get<T>` | `func Array_Get<T>(arr: *Array<T>, index: uint) -> T` | Get element at index |
|
||||
| `Array_Set<T>` | `func Array_Set<T>(arr: *Array<T>, index: uint, value: T)` | Set element at index |
|
||||
| `Array_First<T>` | `func Array_First<T>(arr: *Array<T>) -> T` | First element (bounds-checked) |
|
||||
@@ -257,6 +262,10 @@ String manipulation utilities.
|
||||
| `String_IsBlank` | `func String_IsBlank(s: String) -> bool` | True if empty or only whitespace |
|
||||
| `String_Repeat` | `func String_Repeat(s: String, count: uint) -> String` | Repeat string N times |
|
||||
| `String_Find` | `func String_Find(haystack: String, needle: String) -> String` | Find substring (returns pointer; 0 = not found) |
|
||||
| `String_IndexOf` | `func String_IndexOf(s: String, needle: String) -> int` | Byte index of first match, or `-1` |
|
||||
| `String_Cmp` | `func String_Cmp(a: String, b: String) -> int` | Lexicographic compare (`strcmp`) |
|
||||
| `String_ToUpper` | `func String_ToUpper(s: String) -> String` | ASCII `a`–`z` → upper (allocates) |
|
||||
| `String_ToLower` | `func String_ToLower(s: String) -> String` | ASCII `A`–`Z` → lower (allocates) |
|
||||
| `String_Replace` | `func String_Replace(s: String, old: String, new: String) -> String` | Replace first occurrence |
|
||||
| `String_ReplaceAll` | `func String_ReplaceAll(s: String, old: String, new: String) -> String` | Replace all non-overlapping occurrences |
|
||||
| `String_Format1` | `func String_Format1(pattern: String, a0: String) -> String` | Format with 1 arg (`{0}`) |
|
||||
@@ -430,6 +439,7 @@ struct Map<K, V> {
|
||||
| `Map_New<K,V>` | `func Map_New<K,V>(cap: uint) -> Map<K,V>` | Create map |
|
||||
| `Map_Set<K,V>` | `func Map_Set<K,V>(m: *Map<K,V>, key: K, value: V)` | Insert/update |
|
||||
| `Map_Get<K,V>` | `func Map_Get<K,V>(m: *Map<K,V>, key: K) -> V` | Get value (zero if missing) |
|
||||
| `Map_GetOr<K,V>` | `func Map_GetOr<K,V>(m: *Map<K,V>, key: K, defaultVal: V) -> V` | Get or default if missing |
|
||||
| `Map_Has<K,V>` | `func Map_Has<K,V>(m: *Map<K,V>, key: K) -> bool` | Check key exists |
|
||||
| `Map_Remove<K,V>` | `func Map_Remove<K,V>(m: *Map<K,V>, key: K) -> bool` | Remove key (true if present) |
|
||||
| `Map_Clear<K,V>` | `func Map_Clear<K,V>(m: *Map<K,V>)` | Remove all entries (keeps capacity) |
|
||||
@@ -481,6 +491,7 @@ struct StringMap<V> {
|
||||
| `StringMap_New<V>` | `func StringMap_New<V>(cap: uint) -> StringMap<V>` | Create map |
|
||||
| `StringMap_Set<V>` | `func StringMap_Set<V>(m: *StringMap<V>, key: String, value: V)` | Insert/update |
|
||||
| `StringMap_Get<V>` | `func StringMap_Get<V>(m: *StringMap<V>, key: String) -> V` | Get value |
|
||||
| `StringMap_GetOr<V>` | `func StringMap_GetOr<V>(m: *StringMap<V>, key: String, defaultVal: V) -> V` | Get or default if missing |
|
||||
| `StringMap_Has<V>` | `func StringMap_Has<V>(m: *StringMap<V>, key: String) -> bool` | Check key exists |
|
||||
| `StringMap_Remove<V>` | `func StringMap_Remove<V>(m: *StringMap<V>, key: String) -> bool` | Remove key |
|
||||
| `StringMap_Clear<V>` | `func StringMap_Clear<V>(m: *StringMap<V>)` | Clear all entries |
|
||||
@@ -1010,6 +1021,7 @@ import Std::Test::*;
|
||||
| `Test_AssertEqInt` | `func Test_AssertEqInt(a: int, b: int)` | Integer equality |
|
||||
| `Test_AssertNeqInt` | `func Test_AssertNeqInt(a: int, b: int)` | Integer inequality |
|
||||
| `Test_AssertEqString` | `func Test_AssertEqString(a: String, b: String)` | String equality |
|
||||
| `Test_AssertNeqString` | `func Test_AssertNeqString(a: String, b: String)` | String inequality |
|
||||
| `Test_AssertEqBool` | `func Test_AssertEqBool(a: bool, b: bool)` | Boolean equality |
|
||||
| `Test_Fail` / `Test_Pass` | `func ...(msg: String)` | Explicit fail / log pass |
|
||||
| `Test_Exit` | `func Test_Exit(code: int)` | Exit with code |
|
||||
|
||||
Reference in New Issue
Block a user