Skip to main content

bynk_check/
kernel_methods.rs

1//! v0.30.2 (ADR 0063): the enumerable kernel-method registry.
2//!
3//! The value methods of the built-in kernels (`List`/`Map`/`Option`/`Result`/
4//! `String`/`Int`/`Float`) are dispatched by the checker in
5//! [`crate::checker`]'s `check_*_kernel_method` functions, where the method
6//! names live in `match` arms — authoritative for *typing*, but not
7//! enumerable. This module is the enumerable view the LSP reads for `.`-member
8//! completion: per-kernel `(name, signature)` tables and a [`methods_for`]
9//! mapping from a receiver [`Ty`] to its methods.
10//!
11//! The signatures are human-readable Bynk-surface display strings (generic in
12//! the element/key/value type), for completion `detail` — not the checker's
13//! `Ty`-typed signatures. A drift test (`kernel_registry_pins_dispatch`)
14//! drives every listed method through the real checker and asserts none is
15//! rejected as `method_not_found`, so the table can't list a phantom method.
16
17use crate::checker::Ty;
18use bynk_syntax::ast::BaseType;
19
20/// One built-in kernel method: its name and a display signature.
21#[derive(Debug, Clone, Copy)]
22pub struct KernelMethod {
23    pub name: &'static str,
24    pub signature: &'static str,
25}
26
27const fn m(name: &'static str, signature: &'static str) -> KernelMethod {
28    KernelMethod { name, signature }
29}
30
31/// `List[T]` (v0.20b; v0.88 adds the ADR 0116 query/collection vocabulary).
32pub const LIST_METHODS: &[KernelMethod] = &[
33    m("length", "length() -> Int"),
34    m("get", "get(index: Int) -> Option[T]"),
35    m("prepend", "prepend(item: T) -> List[T]"),
36    m("fold", "fold(init: U, step: (U, T) -> U) -> U"),
37    m(
38        "foldEff",
39        "foldEff(init: U, step: (U, T) -> Effect[U]) -> Effect[U]",
40    ),
41    // v0.88 (ADR 0116): eager in-memory builders + terminals.
42    m("map", "map(f: T -> U) -> List[U]"),
43    m("filter", "filter(p: T -> Bool) -> List[T]"),
44    m("flatMap", "flatMap(f: T -> List[U]) -> List[U]"),
45    m("sortBy", "sortBy(key: T -> K) -> List[T]"),
46    m("take", "take(n: Int) -> List[T]"),
47    m("skip", "skip(n: Int) -> List[T]"),
48    m("distinct", "distinct() -> List[T]"),
49    m("distinctBy", "distinctBy(key: T -> K) -> List[T]"),
50    m("count", "count() -> Int"),
51    m("any", "any(p: T -> Bool) -> Bool"),
52    m("all", "all(p: T -> Bool) -> Bool"),
53    m("first", "first() -> Option[T]"),
54    m("firstOrElse", "firstOrElse(default: T) -> T"),
55    m("sum", "sum(key: T -> K) -> K"),
56    m("min", "min(key: T -> K) -> Option[K]"),
57    m("max", "max(key: T -> K) -> Option[K]"),
58    m("average", "average(key: T -> K) -> Option[Float]"),
59];
60
61/// `Map[K, V]` (v0.20b).
62pub const MAP_METHODS: &[KernelMethod] = &[
63    m("length", "length() -> Int"),
64    m("keys", "keys() -> List[K]"),
65    m("get", "get(key: K) -> Option[V]"),
66    m("insert", "insert(key: K, value: V) -> Map[K, V]"),
67];
68
69/// `Option[T]` combinators (v0.22a).
70pub const OPTION_METHODS: &[KernelMethod] = &[
71    m("map", "map(f: T -> U) -> Option[U]"),
72    m("andThen", "andThen(f: T -> Option[U]) -> Option[U]"),
73    m("getOrElse", "getOrElse(default: T) -> T"),
74    m("isSome", "isSome() -> Bool"),
75    m("okOr", "okOr(err: E) -> Result[T, E]"),
76];
77
78/// `Result[T, E]` combinators (v0.22a).
79pub const RESULT_METHODS: &[KernelMethod] = &[
80    m("map", "map(f: T -> U) -> Result[U, E]"),
81    m("andThen", "andThen(f: T -> Result[U, E]) -> Result[U, E]"),
82    m("mapErr", "mapErr(f: E -> F) -> Result[T, F]"),
83    m("getOrElse", "getOrElse(default: T) -> T"),
84    m("isOk", "isOk() -> Bool"),
85];
86
87/// The `String` kernel (v0.22a; UTF-16 code units, except `chars`).
88pub const STRING_METHODS: &[KernelMethod] = &[
89    m("length", "length() -> Int"),
90    m("split", "split(sep: String) -> List[String]"),
91    m("trim", "trim() -> String"),
92    m("toUpper", "toUpper() -> String"),
93    m("toLower", "toLower() -> String"),
94    m("contains", "contains(s: String) -> Bool"),
95    m("startsWith", "startsWith(s: String) -> Bool"),
96    m("endsWith", "endsWith(s: String) -> Bool"),
97    m("replace", "replace(from: String, to: String) -> String"),
98    m("slice", "slice(start: Int, end: Int) -> String"),
99    m("indexOf", "indexOf(s: String) -> Option[Int]"),
100    m("chars", "chars() -> List[String]"),
101    m("concat", "concat(s: String) -> String"),
102];
103
104/// The `Int` numeric kernel (v0.21).
105pub const INT_METHODS: &[KernelMethod] = &[
106    m("toFloat", "toFloat() -> Float"),
107    m("toString", "toString() -> String"),
108    m("abs", "abs() -> Int"),
109    m("min", "min(other: Int) -> Int"),
110    m("max", "max(other: Int) -> Int"),
111    m("clamp", "clamp(lo: Int, hi: Int) -> Int"),
112];
113
114/// The `Float` numeric kernel (v0.21).
115pub const FLOAT_METHODS: &[KernelMethod] = &[
116    m("round", "round() -> Int"),
117    m("floor", "floor() -> Int"),
118    m("ceil", "ceil() -> Int"),
119    m("truncate", "truncate() -> Int"),
120    m("toString", "toString() -> String"),
121    m("abs", "abs() -> Float"),
122    m("min", "min(other: Float) -> Float"),
123    m("max", "max(other: Float) -> Float"),
124    m("clamp", "clamp(lo: Float, hi: Float) -> Float"),
125    m("isNaN", "isNaN() -> Bool"),
126    m("isFinite", "isFinite() -> Bool"),
127];
128
129/// The `Duration` kernel (v0.86, ADR 0112). Comparison/arithmetic are operators
130/// (D3/D4); the kernel is the explicit escape to raw milliseconds (D5).
131pub const DURATION_METHODS: &[KernelMethod] = &[
132    m("toMillis", "toMillis() -> Int"),
133    m("toString", "toString() -> String"),
134];
135
136/// The `Instant` kernel (v0.90, ADR 0114). Comparison/arithmetic are operators
137/// (D3); the kernel is the explicit escape to raw epoch milliseconds (D6).
138pub const INSTANT_METHODS: &[KernelMethod] = &[
139    m("toEpochMillis", "toEpochMillis() -> Int"),
140    m("toString", "toString() -> String"),
141];
142
143/// The `Bytes` kernel (v0.110, ADR 0142). Equality is an operator (D4, content
144/// compare); the kernel is length plus the String-interop bridge (D3). No
145/// ordering/arithmetic/concat/slice in v1 (deferred follow-ons).
146pub const BYTES_METHODS: &[KernelMethod] = &[
147    m("length", "length() -> Int"),
148    m("toBase64", "toBase64() -> String"),
149    m("decodeUtf8", "decodeUtf8() -> Option[String]"),
150];
151
152/// The value methods of a receiver type, or `&[]` for a type with no kernel
153/// methods (record/sum named types, `Bool`, `Effect`, …). Record *fields* are
154/// resolved separately by the LSP (they need the type declaration).
155pub fn methods_for(ty: &Ty) -> &'static [KernelMethod] {
156    match ty {
157        Ty::Base(BaseType::Int) => INT_METHODS,
158        Ty::Base(BaseType::Float) => FLOAT_METHODS,
159        Ty::Base(BaseType::Duration) => DURATION_METHODS,
160        Ty::Base(BaseType::Instant) => INSTANT_METHODS,
161        Ty::Base(BaseType::Bytes) => BYTES_METHODS,
162        Ty::Base(BaseType::String) => STRING_METHODS,
163        Ty::List(_) => LIST_METHODS,
164        Ty::Map(_, _) => MAP_METHODS,
165        Ty::Option(_) => OPTION_METHODS,
166        Ty::Result(_, _) => RESULT_METHODS,
167        _ => &[],
168    }
169}