@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,692 +0,0 @@
1
- # rill Control Flow
2
-
3
- *Conditionals, loops, break, and return*
4
-
5
- ## Overview
6
-
7
- rill provides singular control flow—no exceptions, no try/catch. Errors halt execution. Recovery requires explicit conditionals.
8
-
9
- | Syntax | Description |
10
- |--------|-------------|
11
- | `cond ? then ! else` | Conditional (if-else) |
12
- | `$val -> ? then ! else` | Piped conditional (uses $ as cond) |
13
- | `(cond) @ body` | While loop (cond is bool) |
14
- | `@ body ? cond` | Do-while (body first) |
15
- | `break` / `$val -> break` | Exit loop |
16
- | `return` / `$val -> return` | Exit block |
17
- | `assert cond` / `assert cond "msg"` | Validate condition, halt on failure |
18
- | `error "msg"` / `$val -> error` | Halt execution with error message |
19
-
20
- ---
21
-
22
- ## Conditionals
23
-
24
- `?` is the conditional operator. The condition precedes `?`, and `!` introduces the else clause.
25
-
26
- ### Syntax Forms
27
-
28
- ```text
29
- condition ? then-body
30
- condition ? then-body ! else-body
31
- $val -> ? then-body ! else-body # piped form: $ is the condition
32
- ```
33
-
34
- ### Standalone Form
35
-
36
- Condition precedes `?`:
37
-
38
- ```rill
39
- true ? "yes" ! "no" # "yes"
40
- false ? "yes" ! "no" # "no"
41
- (5 > 3) ? "big" ! "small" # grouped comparison as condition
42
- ```
43
-
44
- ### Piped Form
45
-
46
- Use `$` as condition:
47
-
48
- ```rill
49
- true -> ? "yes" ! "no" # "yes" (pipe value must be bool)
50
- 5 -> ($ > 3) ? "big" ! "small" # "big"
51
- ```
52
-
53
- ### Method Conditions
54
-
55
- Methods that return booleans work directly as conditions:
56
-
57
- ```rill
58
- "hello" -> .contains("ell") ? "found" ! "missing" # "found"
59
- "abc" -> !.empty ? "has content" ! "empty" # "has content"
60
- ```
61
-
62
- ### Condition Forms
63
-
64
- ```rill
65
- "test" -> ($ == "test") ? "match" ! "no" # grouped comparison
66
- "test" -> .eq("test") ? "match" ! "no" # comparison method
67
- "xyz" -> .contains("x") ? "found" ! "no" # method as condition
68
- ```
69
-
70
- ### Optional Else
71
-
72
- The else branch (`! ...`) is optional:
73
-
74
- ```rill
75
- true ? "executed" # only runs if true
76
- false ? "skipped" # returns empty string
77
- ```
78
-
79
- ### Else-If Chains
80
-
81
- ```rill
82
- "B" :> $val
83
- $val -> .eq("A") ? "a" ! .eq("B") ? "b" ! "other" # "b"
84
- ```
85
-
86
- ### Return Value
87
-
88
- Conditionals return the last expression of the executed branch:
89
-
90
- ```rill
91
- true -> ? "yes" ! "no" :> $result # "yes"
92
- false -> ? "yes" ! "no" :> $result # "no"
93
- ```
94
-
95
- ### Block Bodies
96
-
97
- Use braces for multi-statement branches:
98
-
99
- ```rill
100
- true -> ? {
101
- "step 1" -> log
102
- "step 2" -> log
103
- "done"
104
- } ! {
105
- "skipped"
106
- }
107
- ```
108
-
109
- ---
110
-
111
- ## While Loop
112
-
113
- Pre-condition loop. Condition is evaluated before each iteration. The body result becomes the next iteration's `$`.
114
-
115
- > **Note:** There is no `while` keyword. Use `(condition) @ { body }` syntax. Loop bodies cannot modify outer-scope variables—use `$` to carry all state. For multiple values, pack them in a dict.
116
-
117
- ### Syntax
118
-
119
- ```text
120
- initial -> (condition) @ { body }
121
- ```
122
-
123
- ### Basic Usage
124
-
125
- ```rill
126
- # Count to 5
127
- 0 -> ($ < 5) @ { $ + 1 } # Result: 5
128
-
129
- # String accumulation
130
- "" -> (.len < 5) @ { "{$}x" } # Result: "xxxxx"
131
- ```
132
-
133
- ### Condition Forms
134
-
135
- ```rill
136
- 0 -> ($ < 10) @ { $ + 1 } # comparison condition
137
- "" -> (.len < 5) @ { "{$}x" } # method call condition
138
- ```
139
-
140
- ### Infinite Loop with Break
141
-
142
- ```rill
143
- 0 -> (true) @ {
144
- $ + 1 -> ($ > 5) ? break ! $
145
- } # Result: 6
146
- ```
147
-
148
- ### Loop Limits
149
-
150
- Use `^(limit: N)` annotation to set maximum iterations (default: 10,000):
151
-
152
- ```rill
153
- ^(limit: 100) 0 -> ($ < 10) @ { $ + 1 } # Runs 10 iterations, returns 10
154
- ```
155
-
156
- Exceeding the limit throws `RuntimeError` with code `RUNTIME_LIMIT_EXCEEDED`.
157
-
158
- ### Multiple State Values
159
-
160
- When you need to track multiple values across iterations, use `$` as a state dict:
161
-
162
- ```text
163
- # Track iteration count, text, and done flag
164
- [iter: 0, text: $input, done: false]
165
- -> (!$.done && $.iter < 3) @ {
166
- $.iter + 1 :> $i
167
- app::process($.text) :> $result
168
- $result.finished
169
- ? [iter: $i, text: $.text, done: true]
170
- ! [iter: $i, text: $result.text, done: false]
171
- }
172
- # Access final state: $.text, $.iter
173
- ```
174
-
175
- This pattern replaces the common (but invalid) approach of trying to modify outer variables from inside the loop.
176
-
177
- ---
178
-
179
- ## Do-While Loop
180
-
181
- Post-condition loop. Body executes first, then condition is checked. Use when you want at least one execution.
182
-
183
- ### Syntax
184
-
185
- ```text
186
- initial -> @ { body } ? (condition)
187
- ```
188
-
189
- ### Basic Usage
190
-
191
- ```rill
192
- # Execute at least once, continue while condition holds
193
- 0 -> @ { $ + 1 } ? ($ < 5) # Returns 5
194
-
195
- # String accumulation
196
- "" -> @ { "{$}x" } ? (.len < 3) # Returns "xxx"
197
- ```
198
-
199
- ### When to Use
200
-
201
- - **While** `(condition) @ { body }`: condition checked BEFORE body (may execute 0 times)
202
- - **Do-while** `@ { body } ? (condition)`: condition checked AFTER body (executes at least once)
203
-
204
- ### Retry Pattern
205
-
206
- Do-while is ideal for retry patterns:
207
-
208
- ```text
209
- ^(limit: 5) @ {
210
- app::prompt("Perform operation")
211
- } ? (.contains("RETRY"))
212
- # Loop exits when result doesn't contain RETRY
213
- ```
214
-
215
- ### Loop Limit
216
-
217
- ```rill
218
- ^(limit: 100) 0 -> @ { $ + 1 } ? ($ < 10) # Returns 10
219
- ```
220
-
221
- ---
222
-
223
- ## Break
224
-
225
- Exit a loop early. Returns the value piped to `break`, or current `$` if bare.
226
-
227
- ### Syntax
228
-
229
- ```text
230
- break # exit with current $
231
- $value -> break # exit with value
232
- ```
233
-
234
- ### In Each Loop
235
-
236
- ```rill
237
- [1, 2, 3, 4, 5] -> each {
238
- ($ > 3) ? ("found {$}" -> break)
239
- $
240
- }
241
- # Returns "found 4"
242
- ```
243
-
244
- ### In While Loop
245
-
246
- ```rill
247
- 0 -> (true) @ {
248
- ($ + 1) -> ($ > 3) ? break ! $
249
- }
250
- # Returns 4
251
- ```
252
-
253
- ### Break Value
254
-
255
- In `each`, break returns partial results collected before the break:
256
-
257
- ```rill
258
- ["a", "b", "STOP", "c"] -> each {
259
- ($ == "STOP") ? break
260
- $
261
- }
262
- # Returns ["a", "b"] (partial results before break)
263
- ```
264
-
265
- ### Break Not Allowed
266
-
267
- `break` is not supported in `map`, `filter`, or `fold` (parallel operations):
268
-
269
- ```text
270
- [1, 2, 3] -> map { break } # ERROR: break not supported in map
271
- ```
272
-
273
- ---
274
-
275
- ## Return
276
-
277
- Exit a block early. Returns the value piped to `return`, or current `$` if bare.
278
-
279
- ### Syntax
280
-
281
- ```text
282
- return # exit with current $
283
- $value -> return # exit with value
284
- ```
285
-
286
- ### In Blocks
287
-
288
- ```rill
289
- {
290
- 5 :> $x
291
- ($x > 3) ? ("big" -> return)
292
- "small"
293
- }
294
- # Returns "big"
295
- ```
296
-
297
- ### Multi-Phase Pipeline
298
-
299
- ```text
300
- {
301
- "content" :> $data
302
- $data -> .contains("ERROR") ? ("Read failed" -> return)
303
- "processed: {$data}"
304
- }
305
- # Returns "processed: content" or "Read failed"
306
- ```
307
-
308
- ---
309
-
310
- ## Assert
311
-
312
- Validate conditions during execution. Halts the script with a clear error if the assertion fails.
313
-
314
- ### Syntax
315
-
316
- ```text
317
- assert condition
318
- assert condition "error message"
319
- $value -> assert condition
320
- ```
321
-
322
- ### Basic Usage
323
-
324
- Assert halts execution when the condition evaluates to `false`. If the condition is `true`, the piped value passes through unchanged.
325
-
326
- ```rill
327
- 5 -> assert ($ > 0) # Returns 5 (condition true)
328
- -1 -> assert ($ > 0) # Error: Assertion failed
329
- ```
330
-
331
- ### Custom Error Messages
332
-
333
- Provide a descriptive message as the second argument:
334
-
335
- ```rill
336
- "" -> assert !.empty "Empty input not allowed"
337
- # Error: Empty input not allowed
338
-
339
- [1, 2, 3] -> assert (.len > 0) "List cannot be empty"
340
- # Returns [1, 2, 3] (assertion passes)
341
- ```
342
-
343
- ### Type Assertions
344
-
345
- Combine with type checks to validate input:
346
-
347
- ```rill
348
- "hello" -> assert $:?string # Returns "hello" (type check passes)
349
- 42 -> assert $:?string # Error: Assertion failed
350
- ```
351
-
352
- ### In Loops
353
-
354
- Assert validates each iteration. The loop halts on the first failing assertion:
355
-
356
- ```rill
357
- [1, 2, 3] -> each {
358
- assert ($ > 0) "Must be positive"
359
- }
360
- # Returns [1, 2, 3] (all elements valid)
361
-
362
- [1, 0, 3] -> each {
363
- assert ($ > 0) "Must be positive"
364
- }
365
- # Error: Must be positive
366
- ```
367
-
368
- ### Pipe Passthrough
369
-
370
- When the assertion passes, the piped value flows through unchanged:
371
-
372
- ```rill
373
- "data" :> $input
374
- $input
375
- -> assert !.empty "Input required"
376
- -> .upper
377
- -> assert (.len > 0) "Processed value required"
378
- # Returns "DATA"
379
- ```
380
-
381
- ### Error Behavior
382
-
383
- Assert throws `RuntimeError` when:
384
-
385
- | Condition | Error Code | Message |
386
- |-----------|-----------|---------|
387
- | Condition is `false` | `RUNTIME_ASSERTION_FAILED` | Custom message or "Assertion failed" |
388
- | Condition is not boolean | `RUNTIME_TYPE_ERROR` | "assert requires boolean condition, got {type}" |
389
-
390
- ```rill
391
- # Non-boolean condition
392
- "test" -> assert $ # Error: assert requires boolean condition, got string
393
-
394
- # Failed assertion with location
395
- -1 -> assert ($ > 0) # Error: Assertion failed
396
- ```
397
-
398
- ### Validation Patterns
399
-
400
- Guard clauses at function start:
401
-
402
- ```text
403
- |data| {
404
- assert $data:?list "Expected list"
405
- assert !$data.empty "List cannot be empty"
406
- $data -> each { $ * 2 }
407
- } :> $process
408
- ```
409
-
410
- Multi-step validation:
411
-
412
- ```text
413
- $input
414
- -> assert $:?string "Input must be string"
415
- -> .trim
416
- -> assert !.empty "Trimmed input cannot be empty"
417
- -> assert (.len >= 5) "Input too short (min 5 chars)"
418
- -> app::process()
419
- ```
420
-
421
- ---
422
-
423
- ## Error
424
-
425
- Halt execution immediately with a custom error message. Unlike `assert`, which validates a condition, `error` always halts.
426
-
427
- ### Syntax
428
-
429
- ```text
430
- error "message" # Direct form
431
- $value -> error # Piped form
432
- ```
433
-
434
- ### Basic Usage
435
-
436
- Use `error` with a string literal to halt with a message:
437
-
438
- ```text
439
- error "Something went wrong"
440
- # Halts execution with: Something went wrong
441
- ```
442
-
443
- The message argument accepts string literals or piped string values (see Piped Form below).
444
-
445
- ### Piped Form
446
-
447
- Pipe a string value to `error` to use dynamic error messages:
448
-
449
- ```text
450
- "Operation failed" -> error
451
- # Halts with: Operation failed
452
- ```
453
-
454
- The piped value must be a string:
455
-
456
- ```text
457
- "Error occurred" :> $msg
458
- $msg -> error
459
- # Halts with: Error occurred
460
-
461
- "Status: " :> $prefix
462
- 404 :> $code
463
- "{$prefix}{$code}" -> error
464
- # Halts with: Status: 404
465
- ```
466
-
467
- Piping non-string values throws a type error:
468
-
469
- ```text
470
- 42 -> error # Error: error requires string, got number
471
- ```
472
-
473
- ### String Interpolation
474
-
475
- Use interpolation for dynamic error messages:
476
-
477
- ```text
478
- 404 :> $code
479
- error "Unexpected status: {$code}"
480
- # Halts with: Unexpected status: 404
481
- ```
482
-
483
- ```text
484
- 3 :> $step
485
- "timeout" :> $reason
486
- error "Failed at step {$step}: {$reason}"
487
- # Halts with: Failed at step 3: timeout
488
- ```
489
-
490
- ### Conditional Usage
491
-
492
- Combine `error` with conditionals for guard clauses:
493
-
494
- ```rill
495
- 5 :> $x
496
- ($x < 0) ? { error "Number must be non-negative" } ! $x
497
- # Returns 5 (condition false, proceeds with else branch)
498
- ```
499
-
500
- ```text
501
- $data -> .empty ? { error "Data cannot be empty" } ! $data
502
- # Proceeds with $data if not empty
503
- ```
504
-
505
- ### In Blocks
506
-
507
- Use `error` in blocks for multi-step validation:
508
-
509
- ```text
510
- |age| {
511
- ($age < 0) ? { error "Age cannot be negative: {$age}" }
512
- ($age > 150) ? { error "Age out of range: {$age}" }
513
- "Valid age: {$age}"
514
- } :> $validate_age
515
- ```
516
-
517
- ### Error Behavior
518
-
519
- Error throws `RuntimeError` with code `RUNTIME_ERROR_RAISED`:
520
-
521
- | Pattern | Halts With | Message Source |
522
- |---------|-----------|----------------|
523
- | `error "msg"` | RUNTIME_ERROR_RAISED | String literal |
524
- | `$val -> error` | RUNTIME_ERROR_RAISED | Piped value (must be string) |
525
- | `error ""` | RUNTIME_ERROR_RAISED | Empty message |
526
- | `error 123` | Parse error | PARSE_INVALID_SYNTAX |
527
-
528
- All error responses include the source location from the error statement.
529
-
530
- ### Multiline Messages
531
-
532
- Use triple-quoted strings for formatted error messages:
533
-
534
- ```text
535
- error """
536
- Error occurred:
537
- - Line 1
538
- - Line 2
539
- """
540
- ```
541
-
542
- ### Comparison with Assert
543
-
544
- | Statement | Condition | Behavior |
545
- |-----------|-----------|----------|
546
- | `assert cond "msg"` | Validates condition | Halts if condition is false, passes through if true |
547
- | `error "msg"` | None | Always halts with message |
548
-
549
- Use `assert` when you need to validate a condition. Use `error` when you've already determined that execution cannot continue.
550
-
551
- ### In Loops
552
-
553
- Error halts the loop immediately:
554
-
555
- ```text
556
- [1, 2, 3] -> each {
557
- ($ == 2) ? { error "Halted at 2" }
558
- $ * 2
559
- }
560
- # Halts on second iteration with: Halted at 2
561
- ```
562
-
563
- ---
564
-
565
- ## Pass
566
-
567
- The `pass` keyword returns the current pipe value (`$`) unchanged. Use it for explicit identity pass-through in conditional branches and dict values.
568
-
569
- ### In Conditionals
570
-
571
- Use `pass` when one branch should preserve the piped value:
572
-
573
- ```rill
574
- "input" -> .contains("in") ? pass ! "fallback"
575
- # Returns "input" (condition true, pass preserves $)
576
- ```
577
-
578
- ```rill
579
- "data" -> .empty ? { error "Empty input" } ! pass
580
- # Returns "data" (condition false, pass preserves $)
581
- ```
582
-
583
- ### In Dict Values
584
-
585
- Use `pass` to include the piped value in dict construction:
586
-
587
- ```rill
588
- "success" -> { [status: pass, code: 0] }
589
- # Returns [status: "success", code: 0]
590
- ```
591
-
592
- ### In Collection Operators
593
-
594
- Preserve elements conditionally:
595
-
596
- ```rill
597
- [1, -2, 3, -4] -> map { ($ > 0) ? pass ! 0 }
598
- # Returns [1, 0, 3, 0]
599
- ```
600
-
601
- ### Why Use Pass?
602
-
603
- The `pass` keyword provides clearer intent than bare `$`:
604
-
605
- ```text
606
- # Less clear - what does $ mean here?
607
- $cond ? do_something() ! $
608
-
609
- # More explicit - reader knows this is intentional no-op
610
- $cond ? do_something() ! pass
611
- ```
612
-
613
- ### Pass Behavior
614
-
615
- | Pattern | Returns | Context |
616
- |---------|---------|---------|
617
- | `cond ? pass ! alt` | `$` if true, `alt` if false | Conditional branch |
618
- | `cond ? alt ! pass` | `alt` if true, `$` if false | Conditional branch |
619
- | `[key: pass]` | Dict with `$` as value | Dict construction |
620
- | `-> { pass }` | `$` | Block body |
621
-
622
- **Note:** `pass` requires pipe context. Using `pass` without `$` bound throws an error.
623
-
624
- ---
625
-
626
- ## Control Flow Summary
627
-
628
- | Statement | Scope | Effect |
629
- |-----------|-------|--------|
630
- | `break` | Loop | Exit loop with current `$` |
631
- | `$val -> break` | Loop | Exit loop with value |
632
- | `return` | Block/Script | Exit block or script with current `$` |
633
- | `$val -> return` | Block/Script | Exit block or script with value |
634
- | `pass` | Any | Returns current `$` unchanged |
635
- | `assert cond` | Any | Halt if condition false, pass through on success |
636
- | `assert cond "msg"` | Any | Halt with custom message if condition false |
637
- | `error "msg"` | Any | Always halt with error message |
638
- | `$val -> error` | Any | Always halt with piped error message (must be string) |
639
-
640
- ---
641
-
642
- ## Patterns
643
-
644
- ### Guard Clauses
645
-
646
- Exit early on invalid conditions (assumes host provides `error()`):
647
-
648
- ```text
649
- |data| {
650
- $data -> .empty ? app::error("Empty input")
651
- $data -> :?list ? $ ! app::error("Expected list")
652
- $data -> each { $ * 2 }
653
- } :> $process
654
- ```
655
-
656
- ### Retry with Limit
657
-
658
- ```text
659
- ^(limit: 3) @ {
660
- app::prompt("Try operation")
661
- } ? (.contains("RETRY"))
662
-
663
- .contains("SUCCESS") ? [0, "Done"] ! [1, "Failed"]
664
- ```
665
-
666
- ### State Machine
667
-
668
- ```rill
669
- "start" -> ($ != "done") @ {
670
- ($ == "start") ? "processing" ! ($ == "processing") ? "validating" ! ($ == "validating") ? "done" ! $
671
- }
672
- # Walks through states: start -> processing -> validating -> done
673
- ```
674
-
675
- ### Find First Match
676
-
677
- ```rill
678
- [1, 2, 3, 4, 5] -> each {
679
- ($ > 3) ? ($ -> break)
680
- $
681
- }
682
- # Returns 4 (first element > 3)
683
- ```
684
-
685
- ---
686
-
687
- ## See Also
688
-
689
- - [Variables](03_variables.md) — Scope rules and `$` binding
690
- - [Collections](07_collections.md) — `each`, `map`, `filter`, `fold` iteration
691
- - [Operators](04_operators.md) — Comparison and logical operators
692
- - [Reference](11_reference.md) — Quick reference tables