@rcrsr/rill 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +88 -162
  2. package/dist/generated/introspection-data.d.ts +1 -1
  3. package/dist/generated/introspection-data.d.ts.map +1 -1
  4. package/dist/generated/introspection-data.js +107 -186
  5. package/dist/generated/introspection-data.js.map +1 -1
  6. package/dist/generated/version-data.d.ts +1 -1
  7. package/dist/generated/version-data.js +4 -4
  8. package/dist/generated/version-data.js.map +1 -1
  9. package/dist/highlight-map.d.ts +4 -0
  10. package/dist/highlight-map.d.ts.map +1 -0
  11. package/dist/highlight-map.js +71 -0
  12. package/dist/highlight-map.js.map +1 -0
  13. package/dist/index.d.ts +2 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +5 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/lexer/errors.d.ts.map +1 -1
  18. package/dist/lexer/errors.js +9 -3
  19. package/dist/lexer/errors.js.map +1 -1
  20. package/dist/lexer/operators.js +1 -1
  21. package/dist/lexer/tokenizer.d.ts.map +1 -1
  22. package/dist/lexer/tokenizer.js +0 -14
  23. package/dist/lexer/tokenizer.js.map +1 -1
  24. package/dist/parser/helpers.d.ts +8 -0
  25. package/dist/parser/helpers.d.ts.map +1 -1
  26. package/dist/parser/helpers.js +4 -4
  27. package/dist/parser/helpers.js.map +1 -1
  28. package/dist/parser/index.d.ts.map +1 -1
  29. package/dist/parser/index.js +1 -1
  30. package/dist/parser/index.js.map +1 -1
  31. package/dist/parser/parser-collect.js +1 -1
  32. package/dist/parser/parser-collect.js.map +1 -1
  33. package/dist/parser/parser-control.js +4 -4
  34. package/dist/parser/parser-control.js.map +1 -1
  35. package/dist/parser/parser-expr.js +32 -10
  36. package/dist/parser/parser-expr.js.map +1 -1
  37. package/dist/parser/parser-extract.js +7 -3
  38. package/dist/parser/parser-extract.js.map +1 -1
  39. package/dist/parser/parser-functions.d.ts.map +1 -1
  40. package/dist/parser/parser-functions.js +7 -18
  41. package/dist/parser/parser-functions.js.map +1 -1
  42. package/dist/parser/parser-literals.js +15 -15
  43. package/dist/parser/parser-literals.js.map +1 -1
  44. package/dist/parser/parser-script.js +3 -3
  45. package/dist/parser/parser-script.js.map +1 -1
  46. package/dist/parser/parser-variables.js +4 -4
  47. package/dist/parser/parser-variables.js.map +1 -1
  48. package/dist/parser/state.d.ts +1 -1
  49. package/dist/parser/state.d.ts.map +1 -1
  50. package/dist/parser/state.js +2 -2
  51. package/dist/parser/state.js.map +1 -1
  52. package/dist/runtime/core/callable.d.ts +20 -0
  53. package/dist/runtime/core/callable.d.ts.map +1 -1
  54. package/dist/runtime/core/callable.js +30 -7
  55. package/dist/runtime/core/callable.js.map +1 -1
  56. package/dist/runtime/core/context.d.ts +21 -0
  57. package/dist/runtime/core/context.d.ts.map +1 -1
  58. package/dist/runtime/core/context.js +75 -4
  59. package/dist/runtime/core/context.js.map +1 -1
  60. package/dist/runtime/core/eval/base.d.ts.map +1 -1
  61. package/dist/runtime/core/eval/base.js +3 -3
  62. package/dist/runtime/core/eval/base.js.map +1 -1
  63. package/dist/runtime/core/eval/index.d.ts.map +1 -1
  64. package/dist/runtime/core/eval/index.js +2 -0
  65. package/dist/runtime/core/eval/index.js.map +1 -1
  66. package/dist/runtime/core/eval/mixins/annotations.js +3 -3
  67. package/dist/runtime/core/eval/mixins/annotations.js.map +1 -1
  68. package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -1
  69. package/dist/runtime/core/eval/mixins/closures.js +69 -40
  70. package/dist/runtime/core/eval/mixins/closures.js.map +1 -1
  71. package/dist/runtime/core/eval/mixins/collections.js +15 -15
  72. package/dist/runtime/core/eval/mixins/collections.js.map +1 -1
  73. package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +1 -1
  74. package/dist/runtime/core/eval/mixins/control-flow.js +12 -12
  75. package/dist/runtime/core/eval/mixins/control-flow.js.map +1 -1
  76. package/dist/runtime/core/eval/mixins/core.d.ts.map +1 -1
  77. package/dist/runtime/core/eval/mixins/core.js +12 -13
  78. package/dist/runtime/core/eval/mixins/core.js.map +1 -1
  79. package/dist/runtime/core/eval/mixins/expressions.js +9 -9
  80. package/dist/runtime/core/eval/mixins/expressions.js.map +1 -1
  81. package/dist/runtime/core/eval/mixins/extraction.d.ts.map +1 -1
  82. package/dist/runtime/core/eval/mixins/extraction.js +15 -15
  83. package/dist/runtime/core/eval/mixins/extraction.js.map +1 -1
  84. package/dist/runtime/core/eval/mixins/literals.js +22 -22
  85. package/dist/runtime/core/eval/mixins/literals.js.map +1 -1
  86. package/dist/runtime/core/eval/mixins/types.js +4 -4
  87. package/dist/runtime/core/eval/mixins/types.js.map +1 -1
  88. package/dist/runtime/core/eval/mixins/variables.js +34 -34
  89. package/dist/runtime/core/eval/mixins/variables.js.map +1 -1
  90. package/dist/runtime/core/execute.js +3 -3
  91. package/dist/runtime/core/execute.js.map +1 -1
  92. package/dist/runtime/core/introspection.d.ts +30 -1
  93. package/dist/runtime/core/introspection.d.ts.map +1 -1
  94. package/dist/runtime/core/introspection.js +47 -1
  95. package/dist/runtime/core/introspection.js.map +1 -1
  96. package/dist/runtime/core/types.d.ts +11 -0
  97. package/dist/runtime/core/types.d.ts.map +1 -1
  98. package/dist/runtime/core/types.js.map +1 -1
  99. package/dist/runtime/ext/builtins.js +22 -22
  100. package/dist/runtime/ext/builtins.js.map +1 -1
  101. package/dist/runtime/ext/extensions.d.ts +1 -1
  102. package/dist/runtime/ext/extensions.d.ts.map +1 -1
  103. package/dist/runtime/ext/extensions.js +4 -5
  104. package/dist/runtime/ext/extensions.js.map +1 -1
  105. package/dist/runtime/index.d.ts +6 -4
  106. package/dist/runtime/index.d.ts.map +1 -1
  107. package/dist/runtime/index.js +3 -2
  108. package/dist/runtime/index.js.map +1 -1
  109. package/dist/types.d.ts +36 -37
  110. package/dist/types.d.ts.map +1 -1
  111. package/dist/types.js +440 -120
  112. package/dist/types.js.map +1 -1
  113. package/package.json +7 -66
  114. package/dist/check/config.d.ts +0 -20
  115. package/dist/check/config.d.ts.map +0 -1
  116. package/dist/check/config.js +0 -151
  117. package/dist/check/config.js.map +0 -1
  118. package/dist/check/fixer.d.ts +0 -39
  119. package/dist/check/fixer.d.ts.map +0 -1
  120. package/dist/check/fixer.js +0 -119
  121. package/dist/check/fixer.js.map +0 -1
  122. package/dist/check/index.d.ts +0 -10
  123. package/dist/check/index.d.ts.map +0 -1
  124. package/dist/check/index.js +0 -21
  125. package/dist/check/index.js.map +0 -1
  126. package/dist/check/rules/anti-patterns.d.ts +0 -65
  127. package/dist/check/rules/anti-patterns.d.ts.map +0 -1
  128. package/dist/check/rules/anti-patterns.js +0 -481
  129. package/dist/check/rules/anti-patterns.js.map +0 -1
  130. package/dist/check/rules/closures.d.ts +0 -66
  131. package/dist/check/rules/closures.d.ts.map +0 -1
  132. package/dist/check/rules/closures.js +0 -370
  133. package/dist/check/rules/closures.js.map +0 -1
  134. package/dist/check/rules/collections.d.ts +0 -90
  135. package/dist/check/rules/collections.d.ts.map +0 -1
  136. package/dist/check/rules/collections.js +0 -373
  137. package/dist/check/rules/collections.js.map +0 -1
  138. package/dist/check/rules/conditionals.d.ts +0 -41
  139. package/dist/check/rules/conditionals.d.ts.map +0 -1
  140. package/dist/check/rules/conditionals.js +0 -134
  141. package/dist/check/rules/conditionals.js.map +0 -1
  142. package/dist/check/rules/flow.d.ts +0 -46
  143. package/dist/check/rules/flow.d.ts.map +0 -1
  144. package/dist/check/rules/flow.js +0 -206
  145. package/dist/check/rules/flow.js.map +0 -1
  146. package/dist/check/rules/formatting.d.ts +0 -133
  147. package/dist/check/rules/formatting.d.ts.map +0 -1
  148. package/dist/check/rules/formatting.js +0 -648
  149. package/dist/check/rules/formatting.js.map +0 -1
  150. package/dist/check/rules/helpers.d.ts +0 -26
  151. package/dist/check/rules/helpers.d.ts.map +0 -1
  152. package/dist/check/rules/helpers.js +0 -66
  153. package/dist/check/rules/helpers.js.map +0 -1
  154. package/dist/check/rules/index.d.ts +0 -21
  155. package/dist/check/rules/index.d.ts.map +0 -1
  156. package/dist/check/rules/index.js +0 -78
  157. package/dist/check/rules/index.js.map +0 -1
  158. package/dist/check/rules/loops.d.ts +0 -77
  159. package/dist/check/rules/loops.d.ts.map +0 -1
  160. package/dist/check/rules/loops.js +0 -310
  161. package/dist/check/rules/loops.js.map +0 -1
  162. package/dist/check/rules/naming.d.ts +0 -21
  163. package/dist/check/rules/naming.d.ts.map +0 -1
  164. package/dist/check/rules/naming.js +0 -174
  165. package/dist/check/rules/naming.js.map +0 -1
  166. package/dist/check/rules/strings.d.ts +0 -28
  167. package/dist/check/rules/strings.d.ts.map +0 -1
  168. package/dist/check/rules/strings.js +0 -79
  169. package/dist/check/rules/strings.js.map +0 -1
  170. package/dist/check/rules/types.d.ts +0 -41
  171. package/dist/check/rules/types.d.ts.map +0 -1
  172. package/dist/check/rules/types.js +0 -167
  173. package/dist/check/rules/types.js.map +0 -1
  174. package/dist/check/types.d.ts +0 -112
  175. package/dist/check/types.d.ts.map +0 -1
  176. package/dist/check/types.js +0 -6
  177. package/dist/check/types.js.map +0 -1
  178. package/dist/check/validator.d.ts +0 -18
  179. package/dist/check/validator.d.ts.map +0 -1
  180. package/dist/check/validator.js +0 -110
  181. package/dist/check/validator.js.map +0 -1
  182. package/dist/check/visitor.d.ts +0 -33
  183. package/dist/check/visitor.d.ts.map +0 -1
  184. package/dist/check/visitor.js +0 -259
  185. package/dist/check/visitor.js.map +0 -1
  186. package/dist/cli-check.d.ts +0 -43
  187. package/dist/cli-check.d.ts.map +0 -1
  188. package/dist/cli-check.js +0 -368
  189. package/dist/cli-check.js.map +0 -1
  190. package/dist/cli-eval.d.ts +0 -15
  191. package/dist/cli-eval.d.ts.map +0 -1
  192. package/dist/cli-eval.js +0 -116
  193. package/dist/cli-eval.js.map +0 -1
  194. package/dist/cli-exec.d.ts +0 -49
  195. package/dist/cli-exec.d.ts.map +0 -1
  196. package/dist/cli-exec.js +0 -183
  197. package/dist/cli-exec.js.map +0 -1
  198. package/dist/cli-module-loader.d.ts +0 -19
  199. package/dist/cli-module-loader.d.ts.map +0 -1
  200. package/dist/cli-module-loader.js +0 -83
  201. package/dist/cli-module-loader.js.map +0 -1
  202. package/dist/cli-shared.d.ts +0 -44
  203. package/dist/cli-shared.d.ts.map +0 -1
  204. package/dist/cli-shared.js +0 -108
  205. package/dist/cli-shared.js.map +0 -1
  206. package/dist/cli.d.ts +0 -13
  207. package/dist/cli.d.ts.map +0 -1
  208. package/dist/cli.js +0 -62
  209. package/dist/cli.js.map +0 -1
  210. package/dist/runtime/core/introspection-data.d.ts +0 -2
  211. package/dist/runtime/core/introspection-data.d.ts.map +0 -1
  212. package/dist/runtime/core/introspection-data.js +0 -618
  213. package/dist/runtime/core/introspection-data.js.map +0 -1
  214. package/dist/runtime/core/version-data.d.ts +0 -18
  215. package/dist/runtime/core/version-data.d.ts.map +0 -1
  216. package/dist/runtime/core/version-data.js +0 -16
  217. package/dist/runtime/core/version-data.js.map +0 -1
  218. package/docs/00_INDEX.md +0 -67
  219. package/docs/01_guide.md +0 -390
  220. package/docs/02_types.md +0 -504
  221. package/docs/03_variables.md +0 -324
  222. package/docs/04_operators.md +0 -629
  223. package/docs/05_control-flow.md +0 -692
  224. package/docs/06_closures.md +0 -787
  225. package/docs/07_collections.md +0 -688
  226. package/docs/08_iterators.md +0 -330
  227. package/docs/09_strings.md +0 -205
  228. package/docs/10_parsing.md +0 -366
  229. package/docs/11_reference.md +0 -600
  230. package/docs/12_examples.md +0 -748
  231. package/docs/13_modules.md +0 -519
  232. package/docs/14_host-integration.md +0 -985
  233. package/docs/15_grammar.ebnf +0 -773
  234. package/docs/16_conventions.md +0 -695
  235. package/docs/17_cli-tools.md +0 -184
  236. package/docs/18_design-principles.md +0 -247
  237. package/docs/19_cookbook.md +0 -628
  238. package/docs/88_errors.md +0 -902
  239. package/docs/99_llm-reference.txt +0 -614
  240. package/docs/assets/logo.png +0 -0
@@ -1,600 +0,0 @@
1
- # rill Core Language Specification v0.5.0
2
-
3
- *From prompts to workflows*
4
-
5
- rill is a pipe-based scripting language for orchestrating workflows.
6
-
7
- > **Experimental (v0.5.0).** Active development. Breaking changes until v1.0.
8
-
9
- ## Overview
10
-
11
- rill is an imperative scripting language that is dynamically typed and type-safe. Types are checked at runtime, but type errors are always caught—there are no implicit conversions. Type annotations are optional, but variables lock their type on first assignment. The language is value-based: no references, all copies are deep, all comparisons are by value. Empty values are valid (empty strings, lists, dicts), but null and undefined do not exist. Control flow is singular: no exceptions, no try/catch. Data flows through pipes (`->`), not assignment.
12
-
13
- ## Design Principles
14
-
15
- 1. **Pipes over assignment** — Data flows via `->`. No `=` operator exists.
16
- 2. **Pattern-driven decisions** — Check response patterns, branch accordingly.
17
- 3. **Singular control flow** — No try/catch. Errors halt execution. Recovery requires explicit conditionals.
18
- 4. **Value-based** — All values compare by content. No references, no object identity.
19
- 5. **No null/undefined** — Empty values are valid, but "no value" cannot be represented.
20
- 6. **No magic** — No truthiness, no automatic type conversions. Explicit behavior only.
21
- 7. **Expressive and consistent** — Small syntax, coherent semantics. Every construct composes predictably.
22
-
23
- ---
24
-
25
- ## Quick Reference Tables
26
-
27
- ### Expression Delimiters
28
-
29
- | Delimiter | Semantics | Produces |
30
- |-----------|-----------|----------|
31
- | `{ body }` | Deferred (closure creation) | `ScriptCallable` |
32
- | `( expr )` | Eager (immediate evaluation) | Result value |
33
-
34
- ### Operators
35
-
36
- | Category | Operators |
37
- |----------|-----------|
38
- | Arithmetic | `+`, `-`, `*`, `/`, `%` |
39
- | Comparison | `==`, `!=`, `<`, `>`, `<=`, `>=` |
40
- | Comparison | `.eq`, `.ne`, `.lt`, `.gt`, `.le`, `.ge` methods |
41
- | Logical | `!` (unary), `&&`, `\|\|` |
42
- | Pipe | `->` |
43
- | Capture | `:>` |
44
- | Spread | `@` (sequential), `*` (tuple) |
45
- | Extraction | `*<>` (destructure), `/<>` (slice) |
46
- | Type | `:type` (assert), `:?type` (check) |
47
- | Member | `.field`, `[index]` |
48
- | Default | `?? value` |
49
- | Existence | `.?field`, `.?$var`, `.?($expr)`, `.?field&type` |
50
-
51
- See [Operators](04_operators.md) for detailed documentation.
52
-
53
- ### Control Flow
54
-
55
- | Syntax | Description |
56
- |--------|-------------|
57
- | `cond ? then ! else` | Conditional (if-else) |
58
- | `$val -> ? then ! else` | Piped conditional ($ as condition) |
59
- | `(cond) @ body` | While loop |
60
- | `@ body ? cond` | Do-while |
61
- | `break` / `$val -> break` | Exit loop |
62
- | `return` / `$val -> return` | Exit block or script |
63
- | `pass` | Returns current `$` unchanged (use in conditionals, dicts) |
64
- | `assert cond` / `assert cond "msg"` | Validate condition, halt on failure |
65
- | `error "msg"` / `$val -> error` | Halt execution with error message |
66
-
67
- See [Control Flow](05_control-flow.md) for detailed documentation. Script-level exit functions must be host-provided.
68
-
69
- ### Collection Operators
70
-
71
- | Syntax | Description |
72
- |--------|-------------|
73
- | `-> each { body }` | Sequential iteration, all results |
74
- | `-> each(init) { body }` | Sequential with accumulator (`$@`) |
75
- | `-> map { body }` | Parallel iteration, all results |
76
- | `-> filter { cond }` | Parallel filter, matching elements |
77
- | `-> fold(init) { body }` | Sequential reduction, final result |
78
-
79
- See [Collections](07_collections.md) for detailed documentation.
80
-
81
- ### Types
82
-
83
- | Type | Syntax | Example | Produces |
84
- |------|--------|---------|----------|
85
- | String | `"text"`, `"""text"""` | `"hello"`, `"""line 1\nline 2"""` | String value |
86
- | Number | `123`, `0.5` | `42`, `0.9` | Number value |
87
- | Bool | `true`, `false` | `true` | Boolean value |
88
- | List | `[a, b]`, `[...$list]` | `["file.ts", 42]`, `[...$a, 3]` | List value |
89
- | Dict | `[k: v]`, `[$k: v]`, `[($e): v]` | `[output: "text"]`, `[$key: 1]` | Dict value |
90
- | Tuple | `*[...]` | `*[1, 2]`, `*[x: 1, y: 2]` | Tuple value |
91
- | Closure | `\|\|{ }` | `\|x\|($x * 2)` | `ScriptCallable` |
92
- | Block | `{ body }` | `{ $ + 1 }` | `ScriptCallable` |
93
-
94
- See [Types](02_types.md) for detailed documentation.
95
-
96
- ### Functions
97
-
98
- | Syntax | Description |
99
- |--------|-------------|
100
- | `\|p: type\|{ } :> $fn` | Define and capture function |
101
- | `\|p = default\|{ }` | Parameter with default |
102
- | `\|p ^(min: 0)\|{ }` | Parameter with annotation |
103
- | `$fn(arg)` | Call function directly |
104
- | `arg -> $fn()` | Call function with pipe value |
105
- | `arg -> $fn` | Pipe-style invoke |
106
-
107
- See [Closures](06_closures.md) for detailed documentation.
108
-
109
- ### Special Variables
110
-
111
- | Variable | Contains | Source |
112
- |----------|----------|--------|
113
- | `$` | Piped value (current scope) | Grammar |
114
- | `$ARGS` | CLI positional args (list) | Runtime |
115
- | `$ENV.NAME` | Environment variable | Runtime |
116
- | `$name` | Named variable | Runtime |
117
-
118
- See [Variables](03_variables.md) for detailed documentation.
119
-
120
- ### `$` Binding by Context
121
-
122
- | Context | `$` contains |
123
- |---------|--------------|
124
- | Inline block `-> { }` | Piped value |
125
- | Each loop `-> each { }` | Current item |
126
- | While-loop `(cond) @ { }` | Accumulated value |
127
- | Do-while `@ { } ? cond` | Accumulated value |
128
- | Conditional `cond ? { }` | Tested value |
129
- | Piped conditional `-> ? { }` | Piped value |
130
- | Stored closure `\|x\|{ }` | N/A — use params |
131
- | Dict closure `\|\|{ $.x }` | Dict self |
132
-
133
- ### Property Access
134
-
135
- | Syntax | Description |
136
- |--------|-------------|
137
- | `$data.field` | Literal field access |
138
- | `$data[0]`, `$data[-1]` | Index access |
139
- | `$data.$key` | Variable as key |
140
- | `$data.($i + 1)` | Computed key |
141
- | `$data.(a \|\| b)` | Alternative keys |
142
- | `$data.field ?? default` | Default if missing |
143
- | `$data.?field` | Existence check (literal) |
144
- | `$data.?$key` | Existence check (variable) |
145
- | `$data.?($expr)` | Existence check (computed) |
146
- | `$data.?field&type` | Existence + type check |
147
- | `$data.^key` | Annotation reflection |
148
-
149
- ### Dispatch
150
-
151
- Pipe a value to a collection (dict or list) to retrieve the corresponding element.
152
-
153
- **Dict Dispatch:** Match keys and return associated values.
154
-
155
- | Syntax | Description |
156
- |--------|-------------|
157
- | `$val -> [k1: v1, k2: v2]` | Returns value for matching key |
158
- | `$val -> [k1: v1, k2: v2] ?? default` | Returns matched value or default |
159
- | `$val -> [["k1", "k2"]: shared]` | Multi-key dispatch (same value) |
160
-
161
- ```text
162
- $value -> [apple: "fruit", carrot: "vegetable"] # Returns "fruit" if $value is "apple"
163
- $value -> [apple: "fruit"] ?? "not found" # Returns "not found" if no match
164
- $method -> [["GET", "HEAD"]: "safe", ["POST", "PUT"]: "unsafe"] # Multi-key dispatch
165
- ```
166
-
167
- **Type-Aware Dispatch:** Keys match by both value and type.
168
-
169
- | Input | Dict | Result |
170
- |-------|------|--------|
171
- | `1` | `[1: "one", 2: "two"]` | `"one"` |
172
- | `"1"` | `[1: "one", "1": "string"]` | `"string"` |
173
- | `true` | `[true: "yes", false: "no"]` | `"yes"` |
174
- | `"true"` | `[true: "bool", "true": "string"]` | `"string"` |
175
- | `1` | `[[1, "one"]: "match"]` | `"match"` |
176
- | `"one"` | `[[1, "one"]: "match"]` | `"match"` |
177
-
178
- Dict keys can be identifiers, numbers, or booleans. Multi-key syntax `[k1, k2]: value` maps multiple keys to the same value.
179
-
180
- **Hierarchical Dispatch:** Navigate nested structures using a path list.
181
-
182
- | Syntax | Description |
183
- |--------|-------------|
184
- | `[path] -> $target` | Navigate nested dict/list using path of keys/indexes |
185
- | `[] -> $target` | Empty path returns target unchanged |
186
- | `[k1, k2, ...] -> $dict` | Sequential navigation through nested dicts |
187
- | `[0, 1, ...] -> $list` | Sequential navigation through nested lists |
188
- | `[k, 0, k2] -> $mixed` | Mixed dict keys and list indexes |
189
-
190
- Path element types: string keys for dict lookup, number indexes for list access (negative indexes supported). Type mismatch throws `RUNTIME_TYPE_ERROR`.
191
-
192
- Terminal closures receive `$` bound to the final path key.
193
-
194
- ```text
195
- ["name", "first"] -> [name: [first: "Alice"]] # "Alice" (dict path)
196
- [0, 1] -> [[1, 2, 3], [4, 5, 6]] # 2 (list path)
197
- ["users", 0, "name"] -> [users: [[name: "Alice"]]] # "Alice" (mixed path)
198
- ["req", "draft"] -> [req: [draft: { "key={$}" }]] # "key=draft" (terminal closure)
199
- ```
200
-
201
- **List Dispatch:** Index into a list using a number.
202
-
203
- | Syntax | Description |
204
- |--------|-------------|
205
- | `$idx -> [a, b, c]` | Returns element at index (0-based) |
206
- | `$idx -> [a, b, c] ?? default` | Returns element or default if out of bounds |
207
-
208
- ```text
209
- 0 -> ["first", "second", "third"] # "first"
210
- 1 -> ["first", "second", "third"] # "second"
211
- -1 -> ["first", "second", "third"] # "third" (last element)
212
- 5 -> ["a", "b"] ?? "not found" # "not found" (out of bounds)
213
- ```
214
-
215
- **Variable Dispatch:** Use stored collections.
216
-
217
- ```rill
218
- [apple: "fruit", carrot: "vegetable"] :> $lookup
219
- "apple" -> $lookup # "fruit"
220
-
221
- ["a", "b", "c"] :> $items
222
- 1 -> $items # "b"
223
- ```
224
-
225
- **Error Messages:**
226
-
227
- | Scenario | Error |
228
- |----------|-------|
229
- | Dict dispatch key not found | `Dict dispatch: key '{key}' not found` |
230
- | List dispatch index not found | `List dispatch: index '{index}' not found` |
231
- | List dispatch with non-number | `List dispatch requires number index, got {type}` |
232
- | Dispatch to non-collection | `Cannot dispatch to {type}` |
233
-
234
- ### Parsing Functions
235
-
236
- | Function | Description |
237
- |----------|-------------|
238
- | `parse_auto` | Auto-detect and extract structured content |
239
- | `parse_json` | Parse JSON with error repair |
240
- | `parse_xml(tag?)` | Extract content between XML tags |
241
- | `parse_fence(lang?)` | Extract fenced code block content |
242
- | `parse_fences` | Extract all fenced blocks as list |
243
- | `parse_frontmatter` | Parse `---` delimited YAML frontmatter |
244
- | `parse_checklist` | Parse `- [ ]` and `- [x]` items |
245
-
246
- See [Parsing](10_parsing.md) for detailed documentation.
247
-
248
- ### Core Methods
249
-
250
- | Method | Input | Output | Description |
251
- |--------|-------|--------|-------------|
252
- | `.str` | Any | String | Convert to string |
253
- | `.num` | Any | Number | Convert to number |
254
- | `.len` | Any | Number | Length |
255
- | `.trim` | String | String | Remove whitespace |
256
- | `.head` | String/List | Any | First element |
257
- | `.tail` | String/List | Any | Last element |
258
- | `.at(idx)` | String/List | Any | Element at index |
259
- | `.split(sep)` | String | List | Split by separator |
260
- | `.join(sep)` | List | String | Join with separator |
261
- | `.lines` | String | List | Split on newlines |
262
- | `.lower` | String | String | Lowercase |
263
- | `.upper` | String | String | Uppercase |
264
- | `.replace(pat, repl)` | String | String | Replace first match |
265
- | `.replace_all(pat, repl)` | String | String | Replace all matches |
266
- | `.contains(text)` | String | Bool | Contains substring |
267
- | `.starts_with(pre)` | String | Bool | Starts with prefix |
268
- | `.ends_with(suf)` | String | Bool | Ends with suffix |
269
- | `.match(regex)` | String | Dict | First match info |
270
- | `.is_match(regex)` | String | Bool | Regex matches |
271
- | `.empty` | Any | Bool | Is empty |
272
- | `.has(value)` | List | Bool | Check if list contains value (deep equality) |
273
- | `.has_any([values])` | List | Bool | Check if list contains any value from candidates |
274
- | `.has_all([values])` | List | Bool | Check if list contains all values from candidates |
275
- | `.keys` | Dict | List | All keys |
276
- | `.values` | Dict | List | All values |
277
- | `.entries` | Dict | List | Key-value pairs |
278
- | `.params` | Closure | Dict | Parameter metadata (type, __annotations) |
279
-
280
- See [Strings](09_strings.md) for detailed string method documentation.
281
-
282
- ### Global Functions
283
-
284
- | Function | Description |
285
- |----------|-------------|
286
- | `type` | Returns type name of value |
287
- | `log` | Print to console, pass through |
288
- | `json` | Convert to JSON string |
289
- | `identity` | Returns input unchanged |
290
- | `range(start, end, step?)` | Generate number sequence |
291
- | `repeat(value, count)` | Repeat value n times |
292
- | `enumerate(collection)` | Add index to elements |
293
-
294
- See [Iterators](08_iterators.md) for `range` and `repeat` documentation.
295
-
296
- ---
297
-
298
- ## Implied `$`
299
-
300
- When constructs appear without explicit input, `$` is used implicitly:
301
-
302
- | Written | Equivalent to |
303
- |---------|---------------|
304
- | `? { }` | `$ -> ? { }` |
305
- | `.method()` | `$ -> .method()` |
306
- | `$fn()` | `$fn($)` (when no args, no default) |
307
-
308
- ---
309
-
310
- ## Extraction Operators
311
-
312
- ### Destructure `*<>`
313
-
314
- Extract elements from lists or dicts into variables:
315
-
316
- ```rill
317
- [1, 2, 3] -> *<$a, $b, $c>
318
- # $a = 1, $b = 2, $c = 3
319
-
320
- [name: "test", count: 42] -> *<name: $n, count: $c>
321
- # $n = "test", $c = 42
322
- ```
323
-
324
- ### Slice `/<>`
325
-
326
- Extract portions using Python-style `start:stop:step`:
327
-
328
- ```rill
329
- [0, 1, 2, 3, 4] -> /<0:3> # [0, 1, 2]
330
- [0, 1, 2, 3, 4] -> /<-2:> # [3, 4]
331
- [0, 1, 2, 3, 4] -> /<::-1> # [4, 3, 2, 1, 0]
332
- "hello" -> /<1:4> # "ell"
333
- ```
334
-
335
- See [Operators](04_operators.md) for detailed extraction operator documentation.
336
-
337
- ---
338
-
339
- ## Annotation Reflection
340
-
341
- Access annotation values on closures using `.^key` syntax.
342
-
343
- **Type Restriction:** Annotations attach to closures only. Accessing `.^key` on primitives (string, number, boolean, list, dict) throws `RUNTIME_TYPE_ERROR`.
344
-
345
- ```rill
346
- ^(min: 0, max: 100) |x|($x) :> $fn
347
-
348
- $fn.^min # 0
349
- $fn.^max # 100
350
- $fn.^missing # Error: RUNTIME_UNDEFINED_ANNOTATION
351
- ```
352
-
353
- Annotations are metadata attached to closures during creation. They enable runtime configuration and introspection.
354
-
355
- ### Common Use Cases
356
-
357
- **Function Metadata:**
358
-
359
- ```rill
360
- ^(doc: "validates user input", version: 2) |input|($input) :> $validate
361
-
362
- $validate.^doc # "validates user input"
363
- $validate.^version # 2
364
- ```
365
-
366
- **Configuration Annotations:**
367
-
368
- ```rill
369
- ^(timeout: 30000, retry: 3) |url|($url) :> $fetch
370
-
371
- $fetch.^timeout # 30000
372
- $fetch.^retry # 3
373
- ```
374
-
375
- **Complex Annotation Values:**
376
-
377
- ```rill
378
- ^(config: [timeout: 30, endpoints: ["a", "b"]]) |x|($x) :> $fn
379
-
380
- $fn.^config.timeout # 30
381
- $fn.^config.endpoints[0] # "a"
382
- ```
383
-
384
- ### Error Handling
385
-
386
- Accessing undefined annotation keys throws `RUNTIME_UNDEFINED_ANNOTATION`:
387
-
388
- ```rill
389
- |x|($x) :> $fn
390
- $fn.^missing # Error: Annotation 'missing' not defined
391
- ```
392
-
393
- Use default value operator for optional annotations:
394
-
395
- ```rill
396
- |x|($x) :> $fn
397
- $fn.^timeout ?? 30 # 30 (uses default since annotation missing)
398
- ```
399
-
400
- Accessing `.^key` on non-closure values throws `RUNTIME_TYPE_ERROR`:
401
-
402
- ```text
403
- "hello" :> $str
404
- $str.^key # Error: Cannot access annotation on string
405
- ```
406
-
407
- ### Parameter Annotations
408
-
409
- Parameters can have their own annotations using `^(key: value)` syntax. These attach metadata to individual parameters.
410
-
411
- **Syntax:** `|paramName ^(annotation: value)| body`
412
-
413
- **Order:** Parameter annotations appear after the type annotation (if present) and before the default value (if present).
414
-
415
- ```rill
416
- |x: number ^(min: 0, max: 100)|($x) :> $validate
417
- |name: string ^(required: true) = "guest"|($name) :> $greet
418
- |count ^(cache: true) = 0|($count) :> $process
419
- ```
420
-
421
- **Access via `.params`:**
422
-
423
- The `.params` property returns a dict keyed by parameter name. Each entry is a dict containing:
424
-
425
- - `type` — Type annotation (string) if present
426
- - `__annotations` — Dict of parameter-level annotations if present
427
-
428
- ```rill
429
- |x: number ^(min: 0, max: 100), y: string|($x + $y) :> $fn
430
-
431
- $fn.params
432
- # Returns:
433
- # [
434
- # x: [type: "number", __annotations: [min: 0, max: 100]],
435
- # y: [type: "string"]
436
- # ]
437
-
438
- $fn.params.x.__annotations.min # 0
439
- $fn.params.y.?__annotations # false (no annotations on y)
440
- ```
441
-
442
- **Use Cases:**
443
-
444
- ```rill
445
- # Validation metadata
446
- |value ^(min: 0, max: 100)|($value) :> $bounded
447
-
448
- # Caching hints
449
- |key ^(cache: true)|($key) :> $fetch
450
-
451
- # Format specifications
452
- |timestamp ^(format: "ISO8601")|($timestamp) :> $formatDate
453
- ```
454
-
455
- See [Closures](06_closures.md) for parameter annotation examples and patterns.
456
-
457
- ---
458
-
459
- ## Tuples
460
-
461
- Tuples package values for argument unpacking:
462
-
463
- ```rill
464
- |a, b, c|"{$a}-{$b}-{$c}" :> $fmt
465
- *[1, 2, 3] -> $fmt() # "1-2-3"
466
- *[c: 3, a: 1, b: 2] -> $fmt() # "1-2-3" (named)
467
- ```
468
-
469
- See [Types](02_types.md) for detailed tuple documentation.
470
-
471
- ---
472
-
473
- ## Runtime Limits
474
-
475
- ### Iteration Limits
476
-
477
- Loops have a default maximum of **10,000 iterations**. Override with `^(limit: N)`:
478
-
479
- ```rill
480
- ^(limit: 100) 0 -> ($ < 50) @ { $ + 1 }
481
- ```
482
-
483
- ### Concurrency Limits
484
-
485
- The `^(limit: N)` annotation also controls parallel concurrency in `map`:
486
-
487
- ```text
488
- ^(limit: 3) $items -> map { slow_process($) }
489
- ```
490
-
491
- See [Host Integration](14_host-integration.md) for timeout and cancellation configuration.
492
-
493
- ---
494
-
495
- ## Host-Provided Functions
496
-
497
- rill is a vanilla language. The host application registers domain-specific functions via `RuntimeContext`:
498
-
499
- ```typescript
500
- const ctx = createRuntimeContext({
501
- functions: {
502
- prompt: async (args) => await callLLM(args[0]),
503
- 'io::read': async (args) => fs.readFile(String(args[0]), 'utf-8'),
504
- },
505
- variables: {
506
- config: { apiUrl: 'https://api.example.com' },
507
- },
508
- });
509
- ```
510
-
511
- Scripts call these as `prompt("text")` or `io::read("file.txt")`.
512
-
513
- See [Host Integration](14_host-integration.md) for complete API documentation.
514
-
515
- ---
516
-
517
- ## Script Frontmatter
518
-
519
- Optional YAML frontmatter between `---` markers. **Frontmatter is opaque to rill**—the host interprets it:
520
-
521
- ```text
522
- ---
523
- timeout: 00:10:00
524
- args: file: string
525
- ---
526
-
527
- process($file)
528
- ```
529
-
530
- ---
531
-
532
- ## Script Return Values
533
-
534
- Scripts return their last expression:
535
-
536
- | Return | Exit Code |
537
- |--------|-----------|
538
- | `true` / non-empty string | 0 |
539
- | `false` / empty string | 1 |
540
- | `[0, "message"]` | 0 with message |
541
- | `[1, "message"]` | 1 with message |
542
-
543
- ---
544
-
545
- ## Comments
546
-
547
- Single-line comments start with `#`:
548
-
549
- ```rill
550
- # This is a comment
551
- "hello" # inline comment
552
- ```
553
-
554
- ---
555
-
556
- ## Grammar
557
-
558
- The complete formal grammar is in [grammar.ebnf](15_grammar.ebnf).
559
-
560
- ---
561
-
562
- ## Error Codes
563
-
564
- Runtime and parse errors include structured error codes for programmatic handling.
565
-
566
- | Code | Description |
567
- |------|-------------|
568
- | `PARSE_UNEXPECTED_TOKEN` | Unexpected token in source |
569
- | `PARSE_INVALID_SYNTAX` | Invalid syntax |
570
- | `PARSE_INVALID_TYPE` | Invalid type annotation |
571
- | `RUNTIME_UNDEFINED_VARIABLE` | Variable not defined |
572
- | `RUNTIME_UNDEFINED_FUNCTION` | Function not defined |
573
- | `RUNTIME_UNDEFINED_METHOD` | Method not defined (built-in only) |
574
- | `RUNTIME_UNDEFINED_ANNOTATION` | Annotation key not defined |
575
- | `RUNTIME_TYPE_ERROR` | Type mismatch |
576
- | `RUNTIME_TIMEOUT` | Operation timed out |
577
- | `RUNTIME_ABORTED` | Execution cancelled |
578
- | `RUNTIME_INVALID_PATTERN` | Invalid regex pattern |
579
- | `RUNTIME_AUTO_EXCEPTION` | Auto-exception triggered |
580
- | `RUNTIME_ASSERTION_FAILED` | Assertion failed (condition false) |
581
- | `RUNTIME_ERROR_RAISED` | Error statement executed |
582
-
583
- See [Host Integration](14_host-integration.md) for error handling details.
584
-
585
- ---
586
-
587
- ## Topic Guides
588
-
589
- For detailed documentation on specific topics:
590
-
591
- - [Types](02_types.md) — Type system, type assertions
592
- - [Variables](03_variables.md) — Declaration, scope, `$` binding
593
- - [Control Flow](05_control-flow.md) — Conditionals, loops
594
- - [Operators](04_operators.md) — All operators
595
- - [Closures](06_closures.md) — Late binding, dict closures
596
- - [Collections](07_collections.md) — `each`, `map`, `filter`, `fold`
597
- - [Iterators](08_iterators.md) — `range`, `repeat`, `.first()`
598
- - [Strings](09_strings.md) — String methods
599
- - [Parsing](10_parsing.md) — Content parsing
600
- - [Host Integration](14_host-integration.md) — Embedding API