Skip to main content

harn_parser/builtin_methods/
table.rs

1//! The builtin value-method table. Every consumer (VM dispatch drift checks,
2//! the portable kernel, the typechecker, the linter, the language server, and
3//! the generated reference in `docs/src/builtins.md`) reads these rows.
4//!
5//! Signature conventions: `T` is the element type of a list, set, iter, or
6//! generator receiver; `K`/`V` are a dict receiver's key and value types.
7//! Those parameters are bound from the receiver, so each signature declares
8//! them alongside any it binds from arguments.
9
10use harn_builtin_macros::harn_method_sig as sig;
11use harn_builtin_meta::MethodReceiver::{Dict, Generator, Iter, List, Range, Set, String};
12use harn_builtin_meta::{MethodDescriptor as M, RemovedMethod as R};
13
14pub static BUILTIN_METHODS: &[M] = &[
15    // ---- string ----
16    M::pure(String, sig!("len() -> int"), "Number of characters."),
17    M::pure(
18        String,
19        sig!("empty() -> bool"),
20        "True when the string has no characters.",
21    ),
22    M::pure(
23        String,
24        sig!("contains(needle: string) -> bool"),
25        "True when `needle` occurs in the string.",
26    ),
27    M::pure(
28        String,
29        sig!("replace(old: string, new: string) -> string"),
30        "Replace every occurrence of `old` with `new`.",
31    ),
32    M::pure(
33        String,
34        sig!("split(separator: string) -> list<string>"),
35        "Split on every occurrence of `separator`.",
36    ),
37    M::pure(
38        String,
39        sig!("trim() -> string"),
40        "Remove leading and trailing whitespace.",
41    ),
42    M::pure(
43        String,
44        sig!("trim_start() -> string"),
45        "Remove leading whitespace.",
46    ),
47    M::pure(
48        String,
49        sig!("trim_end() -> string"),
50        "Remove trailing whitespace.",
51    ),
52    M::pure(
53        String,
54        sig!("starts_with(prefix: string) -> bool"),
55        "True when the string begins with `prefix`.",
56    ),
57    M::pure(
58        String,
59        sig!("ends_with(suffix: string) -> bool"),
60        "True when the string ends with `suffix`.",
61    ),
62    M::pure(String, sig!("lower() -> string"), "Lowercase copy."),
63    M::pure(String, sig!("upper() -> string"), "Uppercase copy."),
64    M::pure(
65        String,
66        sig!("substring(start: int, end?: int) -> string"),
67        "Characters from `start` up to `end` (default: the end).",
68    ),
69    M::pure(
70        String,
71        sig!("slice(start: int, end?: int) -> string"),
72        "Characters from `start` up to `end`; negative indices count from the end.",
73    ),
74    M::pure(
75        String,
76        sig!("index_of(needle: string) -> int"),
77        "Character offset of the first `needle`, or -1.",
78    ),
79    M::pure(
80        String,
81        sig!("last_index_of(needle: string) -> int"),
82        "Character offset of the last `needle`, or -1.",
83    ),
84    M::pure(
85        String,
86        sig!("chars() -> list<string>"),
87        "List of single-character strings.",
88    ),
89    M::pure(
90        String,
91        sig!("repeat(count: int) -> string"),
92        "The string repeated `count` times.",
93    ),
94    M::pure(
95        String,
96        sig!("reversed() -> string"),
97        "Characters in reverse order.",
98    ),
99    M::pure(
100        String,
101        sig!("pad_left(width: int, fill?: string) -> string"),
102        "Pad on the left to `width` characters with `fill` (default: space).",
103    ),
104    M::pure(
105        String,
106        sig!("pad_right(width: int, fill?: string) -> string"),
107        "Pad on the right to `width` characters with `fill` (default: space).",
108    ),
109    M::pure(String, sig!("lines() -> list<string>"), "Split into lines."),
110    M::pure(
111        String,
112        sig!("char_at(index: int) -> string?"),
113        "Character at `index`, or nil when out of range.",
114    ),
115    M::pure(
116        String,
117        sig!("iter() -> iter<string>"),
118        "Lazy iterator over the characters.",
119    ),
120    // ---- list ----
121    M::pure(List, sig!("len() -> int"), "Number of elements."),
122    M::pure(
123        List,
124        sig!("empty() -> bool"),
125        "True when the list has no elements.",
126    ),
127    M::pure(
128        List,
129        sig!("<T> first() -> T?"),
130        "First element, or nil when empty.",
131    ),
132    M::pure(
133        List,
134        sig!("<T> last() -> T?"),
135        "Last element, or nil when empty.",
136    ),
137    M::pure(
138        List,
139        sig!("<T, U> map(f: (T) -> U) -> list<U>"),
140        "Apply `f` to each element.",
141    ),
142    M::pure(
143        List,
144        sig!("<T> filter(predicate: (T) -> bool) -> list<T>"),
145        "Elements for which `predicate` is truthy.",
146    ),
147    M::pure(
148        List,
149        sig!("<T, U> flat_map(f: (T) -> list<U>) -> list<U>"),
150        "Apply `f` and flatten one level.",
151    ),
152    M::pure(
153        List,
154        sig!("<T, U> reduce(initial: U, f: (U, T) -> U) -> U"),
155        "Fold the elements into an accumulator.",
156    ),
157    M::pure(
158        List,
159        sig!("<T> find(predicate: (T) -> bool) -> T?"),
160        "First element matching `predicate`, or nil.",
161    ),
162    M::pure(
163        List,
164        sig!("<T> find_index(predicate: (T) -> bool) -> int"),
165        "Index of the first match, or -1.",
166    ),
167    M::pure(
168        List,
169        sig!("<T> any(predicate: (T) -> bool) -> bool"),
170        "True when any element matches.",
171    ),
172    M::pure(
173        List,
174        sig!("<T> all(predicate: (T) -> bool) -> bool"),
175        "True when every element matches.",
176    ),
177    M::pure(
178        List,
179        sig!("<T> none(predicate?: (T) -> bool) -> bool"),
180        "True when no element matches; with no argument, true when empty.",
181    ),
182    M::pure(
183        List,
184        sig!("<T> partition(predicate: (T) -> bool) -> list<list<T>>"),
185        "Split into `[matching, rest]`.",
186    ),
187    M::pure(
188        List,
189        sig!("<T, U> group_by(key: (T) -> U) -> dict<string, list<T>>"),
190        "Group elements by `key`.",
191    ),
192    M::pure(
193        List,
194        sig!("<T, U> count_by(key: (T) -> U) -> dict<string, int>"),
195        "Count elements per `key`.",
196    ),
197    M::pure(
198        List,
199        sig!("<T> sorted() -> list<T>"),
200        "Sorted copy (stable, natural order).",
201    ),
202    M::pure(
203        List,
204        sig!("<T, U> sorted_by(key: (T) -> U) -> list<T>"),
205        "Sorted copy ordered by `key`; list keys order lexicographically.",
206    ),
207    M::pure(
208        List,
209        sig!("<T> reversed() -> list<T>"),
210        "Copy in reverse order.",
211    ),
212    M::pure(
213        List,
214        sig!("join(separator?: string) -> string"),
215        "Join the elements' display text with `separator`.",
216    ),
217    M::pure(
218        List,
219        sig!("<T> contains(item: T) -> bool"),
220        "True when an element equals `item`.",
221    ),
222    M::pure(
223        List,
224        sig!("<T> index_of(item: T) -> int"),
225        "Index of the first element equal to `item`, or -1.",
226    ),
227    M::pure(
228        List,
229        sig!("<T> enumerate() -> list<{index: int, value: T}>"),
230        "Pair each element with its index.",
231    ),
232    M::pure(
233        List,
234        sig!("<T, U> zip(other: list<U>) -> list<list<T | U>>"),
235        "Pair elements with `other`, stopping at the shorter list.",
236    ),
237    M::pure(
238        List,
239        sig!("<T> slice(start: int, end?: int) -> list<T>"),
240        "Elements from `start` up to `end`; negative indices count from the end.",
241    ),
242    M::pure(
243        List,
244        sig!("<T> take(count: int) -> list<T>"),
245        "The first `count` elements.",
246    ),
247    M::pure(
248        List,
249        sig!("<T> skip(count: int) -> list<T>"),
250        "All but the first `count` elements.",
251    ),
252    M::pure(
253        List,
254        sig!("<T> take_while(predicate: (T) -> bool) -> list<T>"),
255        "Leading elements while `predicate` holds.",
256    ),
257    M::pure(
258        List,
259        sig!("<T> drop_while(predicate: (T) -> bool) -> list<T>"),
260        "Elements after the leading run where `predicate` holds.",
261    ),
262    M::pure(
263        List,
264        sig!("<T> unique() -> list<T>"),
265        "Copy without duplicates, keeping first occurrences.",
266    ),
267    M::pure(
268        List,
269        sig!("<T> compact() -> list<T>"),
270        "Copy without nil elements.",
271    ),
272    M::pure(
273        List,
274        sig!("flatten() -> list<any>"),
275        "Flatten one level of nesting.",
276    ),
277    M::pure(
278        List,
279        sig!("<T> chunks(size: int) -> list<list<T>>"),
280        "Consecutive non-overlapping chunks of `size`.",
281    ),
282    M::pure(
283        List,
284        sig!("<T> windows(size: int, step?: int) -> list<list<T>>"),
285        "Sliding windows of `size`, advancing by `step` (default 1).",
286    ),
287    M::pure(List, sig!("sum() -> any"), "Sum of the numeric elements."),
288    M::pure(
289        List,
290        sig!("<T> min() -> T?"),
291        "Smallest element, or nil when empty.",
292    ),
293    M::pure(
294        List,
295        sig!("<T> max() -> T?"),
296        "Largest element, or nil when empty.",
297    ),
298    M::pure(
299        List,
300        sig!("<T, U> min_by(key: (T) -> U) -> T?"),
301        "Element with the smallest `key`, or nil when empty.",
302    ),
303    M::pure(
304        List,
305        sig!("<T, U> max_by(key: (T) -> U) -> T?"),
306        "Element with the largest `key`, or nil when empty.",
307    ),
308    M::pure(
309        List,
310        sig!("tally() -> dict<string, int>"),
311        "Count occurrences of each string element.",
312    ),
313    M::pure(List, sig!("<T> to_list() -> list<T>"), "The list itself."),
314    M::pure(List, sig!("<T> to_set() -> set<T>"), "Set of the elements."),
315    M::pure(
316        List,
317        sig!("<T> iter() -> iter<T>"),
318        "Lazy iterator over the elements.",
319    ),
320    M::mutating(
321        List,
322        sig!("<T> push(item: T) -> nil"),
323        "Append `item` to the end.",
324    ),
325    M::mutating(
326        List,
327        sig!("<T> pop() -> T?"),
328        "Remove and return the last element, or nil when empty.",
329    ),
330    M::mutating(
331        List,
332        sig!("<T> insert(index: int, item: T) -> nil"),
333        "Insert `item` before `index`; out-of-range indices clamp to the ends.",
334    ),
335    M::mutating(
336        List,
337        sig!("<T> extend(items: list<T>) -> nil"),
338        "Append every element of `items`.",
339    ),
340    M::mutating(List, sig!("clear() -> nil"), "Remove every element."),
341    M::mutating(
342        List,
343        sig!("sort() -> nil"),
344        "Sort in place (stable, natural order).",
345    ),
346    M::mutating(
347        List,
348        sig!("<T, U> sort_by(key: (T) -> U) -> nil"),
349        "Sort in place ordered by `key`.",
350    ),
351    M::mutating(List, sig!("reverse() -> nil"), "Reverse in place."),
352    // ---- set ----
353    M::pure(Set, sig!("len() -> int"), "Number of members."),
354    M::pure(
355        Set,
356        sig!("empty() -> bool"),
357        "True when the set has no members.",
358    ),
359    M::pure(
360        Set,
361        sig!("<T> contains(item: T) -> bool"),
362        "True when `item` is a member.",
363    ),
364    M::pure(
365        Set,
366        sig!("<T> union(other: set<T>) -> set<T>"),
367        "Members of either set.",
368    ),
369    M::pure(
370        Set,
371        sig!("<T> intersection(other: set<T>) -> set<T>"),
372        "Members of both sets.",
373    ),
374    M::pure(
375        Set,
376        sig!("<T> difference(other: set<T>) -> set<T>"),
377        "Members not in `other`.",
378    ),
379    M::pure(
380        Set,
381        sig!("<T> symmetric_difference(other: set<T>) -> set<T>"),
382        "Members of exactly one set.",
383    ),
384    M::pure(
385        Set,
386        sig!("<T> is_subset(other: set<T>) -> bool"),
387        "True when every member is in `other`.",
388    ),
389    M::pure(
390        Set,
391        sig!("<T> is_superset(other: set<T>) -> bool"),
392        "True when every member of `other` is a member.",
393    ),
394    M::pure(
395        Set,
396        sig!("<T> is_disjoint(other: set<T>) -> bool"),
397        "True when the sets share no member.",
398    ),
399    M::pure(
400        Set,
401        sig!("<T, U> map(f: (T) -> U) -> set<U>"),
402        "Apply `f` to each member.",
403    ),
404    M::pure(
405        Set,
406        sig!("<T> filter(predicate: (T) -> bool) -> set<T>"),
407        "Members for which `predicate` is truthy.",
408    ),
409    M::pure(
410        Set,
411        sig!("<T> any(predicate: (T) -> bool) -> bool"),
412        "True when any member matches.",
413    ),
414    M::pure(
415        Set,
416        sig!("<T> all(predicate: (T) -> bool) -> bool"),
417        "True when every member matches.",
418    ),
419    M::pure(
420        Set,
421        sig!("<T> to_list() -> list<T>"),
422        "Members in insertion order.",
423    ),
424    M::pure(Set, sig!("<T> to_set() -> set<T>"), "The set itself."),
425    M::pure(
426        Set,
427        sig!("<T> iter() -> iter<T>"),
428        "Lazy iterator over the members.",
429    ),
430    M::mutating(Set, sig!("<T> add(item: T) -> nil"), "Add `item`."),
431    M::mutating(
432        Set,
433        sig!("<T> remove(item: T) -> bool"),
434        "Remove `item`; true when it was a member.",
435    ),
436    M::mutating(Set, sig!("clear() -> nil"), "Remove every member."),
437    // ---- dict ----
438    M::pure(Dict, sig!("len() -> int"), "Number of entries."),
439    M::pure(Dict, sig!("<K> keys() -> list<K>"), "Keys in sorted order."),
440    M::pure(
441        Dict,
442        sig!("<V> values() -> list<V>"),
443        "Values in key order.",
444    ),
445    M::pure(
446        Dict,
447        sig!("<K, V> entries() -> list<{key: K, value: V}>"),
448        "`{key, value}` records in key order.",
449    ),
450    M::pure(
451        Dict,
452        sig!("has(key: string) -> bool"),
453        "True when `key` is present.",
454    ),
455    // The result is `V` with a default and `V?` without one; a signature
456    // cannot say both, so it stays gradual.
457    M::pure(
458        Dict,
459        sig!("get(key: string, default?: any) -> any"),
460        "Value at `key`, else `default` (nil when omitted).",
461    ),
462    M::pure(
463        Dict,
464        sig!("<K, V> merge(other: dict<K, V>) -> dict<K, V>"),
465        "Copy with `other`'s entries added; `other` wins on conflicts.",
466    ),
467    M::pure(
468        Dict,
469        sig!("<K, V, U> map_values(f: (V) -> U) -> dict<K, U>"),
470        "Apply `f` to each value.",
471    ),
472    M::pure(
473        Dict,
474        sig!("<K, V> map_keys(f: (K) -> string) -> dict<string, V>"),
475        "Rename each key to `f(key)`.",
476    ),
477    M::pure(
478        Dict,
479        sig!("<K, V> filter(predicate: (V) -> bool) -> dict<K, V>"),
480        "Entries whose value satisfies `predicate`.",
481    ),
482    M::pure(
483        Dict,
484        sig!("<K, V> to_dict() -> dict<K, V>"),
485        "The dict itself.",
486    ),
487    M::pure(
488        Dict,
489        sig!("<K, V> to_list() -> list<{key: K, value: V}>"),
490        "Same as `entries()`.",
491    ),
492    M::pure(
493        Dict,
494        sig!("<K, V> iter() -> iter<Pair<K, V>>"),
495        "Lazy iterator over `Pair(key, value)`.",
496    ),
497    M::mutating(
498        Dict,
499        sig!("<V> remove(key: string) -> V?"),
500        "Remove `key` and return its value, or nil when absent.",
501    ),
502    M::mutating(Dict, sig!("clear() -> nil"), "Remove every entry."),
503    // ---- range ----
504    M::pure(
505        Range,
506        sig!("len() -> int"),
507        "Number of integers in the range.",
508    ),
509    M::pure(
510        Range,
511        sig!("empty() -> bool"),
512        "True when the range is empty.",
513    ),
514    M::pure(
515        Range,
516        sig!("contains(value: int) -> bool"),
517        "True when `value` is in the range.",
518    ),
519    M::pure(
520        Range,
521        sig!("first() -> int?"),
522        "First integer, or nil when empty.",
523    ),
524    M::pure(
525        Range,
526        sig!("last() -> int?"),
527        "Last integer, or nil when empty.",
528    ),
529    M::pure(
530        Range,
531        sig!("to_string() -> string"),
532        "Source form such as `1..=5`.",
533    ),
534    M::pure(
535        Range,
536        sig!("iter() -> iter<int>"),
537        "Lazy iterator; other iterator methods lift the range automatically.",
538    ),
539    // ---- iter ----
540    M::pure(Iter, sig!("<T> iter() -> iter<T>"), "The iterator itself."),
541    M::pure(
542        Iter,
543        sig!("<T, U> map(f: (T) -> U) -> iter<U>"),
544        "Lazily apply `f` to each item.",
545    ),
546    M::pure(
547        Iter,
548        sig!("<T, U> flat_map(f: (T) -> list<U>) -> iter<U>"),
549        "Lazily apply `f` and flatten.",
550    ),
551    M::pure(
552        Iter,
553        sig!("<T> filter(predicate: (T) -> bool) -> iter<T>"),
554        "Lazily keep items matching `predicate`.",
555    ),
556    M::pure(
557        Iter,
558        sig!("<T> take(count: int) -> iter<T>"),
559        "The first `count` items.",
560    ),
561    M::pure(
562        Iter,
563        sig!("<T> skip(count: int) -> iter<T>"),
564        "Drop the first `count` items.",
565    ),
566    M::pure(
567        Iter,
568        sig!("<T> take_while(predicate: (T) -> bool) -> iter<T>"),
569        "Items until `predicate` first fails.",
570    ),
571    M::pure(
572        Iter,
573        sig!("<T> skip_while(predicate: (T) -> bool) -> iter<T>"),
574        "Drop items while `predicate` holds.",
575    ),
576    M::pure(
577        Iter,
578        sig!("<T, U> zip(other: iter<U>) -> iter<Pair<T, U>>"),
579        "Pair items with `other`, stopping at the shorter.",
580    ),
581    M::pure(
582        Iter,
583        sig!("<T> enumerate() -> iter<Pair<int, T>>"),
584        "Pair each item with a 0-based index.",
585    ),
586    M::pure(
587        Iter,
588        sig!("<T> chain(other: iter<T>) -> iter<T>"),
589        "Items of this iterator, then of `other`.",
590    ),
591    M::pure(
592        Iter,
593        sig!("<T> chunks(size: int) -> iter<list<T>>"),
594        "Non-overlapping chunks of `size`.",
595    ),
596    M::pure(
597        Iter,
598        sig!("<T> windows(size: int) -> iter<list<T>>"),
599        "Sliding windows of `size`.",
600    ),
601    M::pure(Iter, sig!("<T> to_list() -> list<T>"), "Drain into a list."),
602    M::pure(Iter, sig!("<T> to_set() -> set<T>"), "Drain into a set."),
603    M::pure(
604        Iter,
605        sig!("to_dict() -> dict<string, any>"),
606        "Drain `Pair(key, value)` items into a dict.",
607    ),
608    M::pure(Iter, sig!("count() -> int"), "Drain and count the items."),
609    M::pure(
610        Iter,
611        sig!("sum() -> number"),
612        "Drain and sum numeric items.",
613    ),
614    M::pure(
615        Iter,
616        sig!("<T> min() -> T?"),
617        "Drain and return the smallest item.",
618    ),
619    M::pure(
620        Iter,
621        sig!("<T> max() -> T?"),
622        "Drain and return the largest item.",
623    ),
624    M::pure(
625        Iter,
626        sig!("<T> first() -> T?"),
627        "The next item, or nil when exhausted.",
628    ),
629    M::pure(
630        Iter,
631        sig!("<T> last() -> T?"),
632        "Drain and return the final item.",
633    ),
634    M::pure(
635        Iter,
636        sig!("<T> find(predicate: (T) -> bool) -> T?"),
637        "First item matching `predicate`.",
638    ),
639    M::pure(
640        Iter,
641        sig!("<T> any(predicate: (T) -> bool) -> bool"),
642        "True when any item matches.",
643    ),
644    M::pure(
645        Iter,
646        sig!("<T> all(predicate: (T) -> bool) -> bool"),
647        "True when every item matches.",
648    ),
649    M::pure(
650        Iter,
651        sig!("<T> for_each(f: (T) -> any) -> nil"),
652        "Drain, calling `f` on each item.",
653    ),
654    M::pure(
655        Iter,
656        sig!("<T, U> reduce(initial: U, f: (U, T) -> U) -> U"),
657        "Drain into an accumulator.",
658    ),
659    // ---- generator ----
660    M::pure(
661        Generator,
662        sig!("<T> iter() -> iter<T>"),
663        "Lazy iterator over the yielded values.",
664    ),
665    M::pure(
666        Generator,
667        sig!("<T> next() -> {done: bool, value: T?}"),
668        "Resume and return the next yielded value.",
669    ),
670];
671
672pub static REMOVED_METHODS: &[R] = &[
673    R::renamed(String, "count", "len"),
674    R::renamed(String, "includes", "contains"),
675    R::renamed(String, "lowercase", "lower"),
676    R::renamed(String, "to_lower", "lower"),
677    R::renamed(String, "uppercase", "upper"),
678    R::renamed(String, "to_upper", "upper"),
679    R::renamed(String, "reverse", "reversed"),
680    R::renamed(String, "rfind", "last_index_of"),
681    R::renamed(List, "count", "len"),
682    R::renamed(List, "includes", "contains"),
683    R::renamed(List, "every", "all"),
684    R::renamed(List, "chunk", "chunks"),
685    R::renamed(List, "each_slice", "chunks"),
686    R::renamed(List, "window", "windows"),
687    R::renamed(List, "each_cons", "windows"),
688    R::renamed(List, "sliding_window", "windows"),
689    R {
690        receiver: List,
691        name: "appending",
692        migration: harn_builtin_meta::MethodMigration::AppendingToPush,
693    },
694    R::mutating_when_self_assigned(
695        List,
696        "dropping_last",
697        "pop",
698        "use `xs.pop()` to remove the last element in place, or `xs.slice(0, -1)` for a new list",
699    ),
700    R::renamed(Set, "count", "len"),
701    R::renamed(Set, "includes", "contains"),
702    R::renamed(Set, "every", "all"),
703    R::renamed(Set, "intersect", "intersection"),
704    R::mutating_when_self_assigned(
705        Set,
706        "adding",
707        "add",
708        "use `s.add(v)` on a `let` binding, or `s.union(set([v]))` for a new set",
709    ),
710    R::mutating_when_self_assigned(
711        Set,
712        "removing",
713        "remove",
714        "use `s.remove(v)` on a `let` binding, or `s.difference(set([v]))` for a new set",
715    ),
716    R::mutating_when_self_assigned(
717        Set,
718        "delete",
719        "remove",
720        "use `s.remove(v)` on a `let` binding, or `s.difference(set([v]))` for a new set",
721    ),
722    R::renamed(Dict, "count", "len"),
723    R::renamed(Dict, "merging", "merge"),
724    R::renamed(Dict, "rekeyed", "map_keys"),
725    R::renamed(Dict, "rekey", "map_keys"),
726    R::mutating_when_self_assigned(
727        Dict,
728        "removing",
729        "remove",
730        "use `d.remove(key)` on a `let` binding, or `omit(d, [key])` from `std/json` for a new dict",
731    ),
732    R::renamed(Range, "count", "len"),
733    R::renamed(Range, "includes", "contains"),
734];