@rcrsr/rill 0.1.0

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 (295) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -0
  3. package/dist/cli.d.ts +11 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +69 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/demo.d.ts +6 -0
  8. package/dist/demo.d.ts.map +1 -0
  9. package/dist/demo.js +121 -0
  10. package/dist/demo.js.map +1 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +9 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lexer/errors.d.ts +9 -0
  16. package/dist/lexer/errors.d.ts.map +1 -0
  17. package/dist/lexer/errors.js +12 -0
  18. package/dist/lexer/errors.js.map +1 -0
  19. package/dist/lexer/helpers.d.ts +14 -0
  20. package/dist/lexer/helpers.d.ts.map +1 -0
  21. package/dist/lexer/helpers.js +30 -0
  22. package/dist/lexer/helpers.js.map +1 -0
  23. package/dist/lexer/index.d.ts +8 -0
  24. package/dist/lexer/index.d.ts.map +1 -0
  25. package/dist/lexer/index.js +8 -0
  26. package/dist/lexer/index.js.map +1 -0
  27. package/dist/lexer/operators.d.ts +11 -0
  28. package/dist/lexer/operators.d.ts.map +1 -0
  29. package/dist/lexer/operators.js +58 -0
  30. package/dist/lexer/operators.js.map +1 -0
  31. package/dist/lexer/readers.d.ts +12 -0
  32. package/dist/lexer/readers.d.ts.map +1 -0
  33. package/dist/lexer/readers.js +144 -0
  34. package/dist/lexer/readers.js.map +1 -0
  35. package/dist/lexer/state.d.ts +18 -0
  36. package/dist/lexer/state.d.ts.map +1 -0
  37. package/dist/lexer/state.js +37 -0
  38. package/dist/lexer/state.js.map +1 -0
  39. package/dist/lexer/tokenizer.d.ts +9 -0
  40. package/dist/lexer/tokenizer.d.ts.map +1 -0
  41. package/dist/lexer/tokenizer.js +100 -0
  42. package/dist/lexer/tokenizer.js.map +1 -0
  43. package/dist/lexer.d.ts +19 -0
  44. package/dist/lexer.d.ts.map +1 -0
  45. package/dist/lexer.js +344 -0
  46. package/dist/lexer.js.map +1 -0
  47. package/dist/parser/arithmetic.d.ts +16 -0
  48. package/dist/parser/arithmetic.d.ts.map +1 -0
  49. package/dist/parser/arithmetic.js +128 -0
  50. package/dist/parser/arithmetic.js.map +1 -0
  51. package/dist/parser/boolean.d.ts +15 -0
  52. package/dist/parser/boolean.d.ts.map +1 -0
  53. package/dist/parser/boolean.js +20 -0
  54. package/dist/parser/boolean.js.map +1 -0
  55. package/dist/parser/control-flow.d.ts +56 -0
  56. package/dist/parser/control-flow.d.ts.map +1 -0
  57. package/dist/parser/control-flow.js +167 -0
  58. package/dist/parser/control-flow.js.map +1 -0
  59. package/dist/parser/expressions.d.ts +23 -0
  60. package/dist/parser/expressions.d.ts.map +1 -0
  61. package/dist/parser/expressions.js +950 -0
  62. package/dist/parser/expressions.js.map +1 -0
  63. package/dist/parser/extraction.d.ts +48 -0
  64. package/dist/parser/extraction.d.ts.map +1 -0
  65. package/dist/parser/extraction.js +279 -0
  66. package/dist/parser/extraction.js.map +1 -0
  67. package/dist/parser/functions.d.ts +20 -0
  68. package/dist/parser/functions.d.ts.map +1 -0
  69. package/dist/parser/functions.js +96 -0
  70. package/dist/parser/functions.js.map +1 -0
  71. package/dist/parser/helpers.d.ts +94 -0
  72. package/dist/parser/helpers.d.ts.map +1 -0
  73. package/dist/parser/helpers.js +225 -0
  74. package/dist/parser/helpers.js.map +1 -0
  75. package/dist/parser/index.d.ts +49 -0
  76. package/dist/parser/index.d.ts.map +1 -0
  77. package/dist/parser/index.js +73 -0
  78. package/dist/parser/index.js.map +1 -0
  79. package/dist/parser/literals.d.ts +37 -0
  80. package/dist/parser/literals.d.ts.map +1 -0
  81. package/dist/parser/literals.js +373 -0
  82. package/dist/parser/literals.js.map +1 -0
  83. package/dist/parser/parser-collect.d.ts +16 -0
  84. package/dist/parser/parser-collect.d.ts.map +1 -0
  85. package/dist/parser/parser-collect.js +125 -0
  86. package/dist/parser/parser-collect.js.map +1 -0
  87. package/dist/parser/parser-control.d.ts +20 -0
  88. package/dist/parser/parser-control.d.ts.map +1 -0
  89. package/dist/parser/parser-control.js +120 -0
  90. package/dist/parser/parser-control.js.map +1 -0
  91. package/dist/parser/parser-expr.d.ts +37 -0
  92. package/dist/parser/parser-expr.d.ts.map +1 -0
  93. package/dist/parser/parser-expr.js +639 -0
  94. package/dist/parser/parser-expr.js.map +1 -0
  95. package/dist/parser/parser-extract.d.ts +17 -0
  96. package/dist/parser/parser-extract.d.ts.map +1 -0
  97. package/dist/parser/parser-extract.js +222 -0
  98. package/dist/parser/parser-extract.js.map +1 -0
  99. package/dist/parser/parser-functions.d.ts +21 -0
  100. package/dist/parser/parser-functions.d.ts.map +1 -0
  101. package/dist/parser/parser-functions.js +155 -0
  102. package/dist/parser/parser-functions.js.map +1 -0
  103. package/dist/parser/parser-literals.d.ts +22 -0
  104. package/dist/parser/parser-literals.d.ts.map +1 -0
  105. package/dist/parser/parser-literals.js +288 -0
  106. package/dist/parser/parser-literals.js.map +1 -0
  107. package/dist/parser/parser-script.d.ts +21 -0
  108. package/dist/parser/parser-script.d.ts.map +1 -0
  109. package/dist/parser/parser-script.js +174 -0
  110. package/dist/parser/parser-script.js.map +1 -0
  111. package/dist/parser/parser-variables.d.ts +20 -0
  112. package/dist/parser/parser-variables.d.ts.map +1 -0
  113. package/dist/parser/parser-variables.js +146 -0
  114. package/dist/parser/parser-variables.js.map +1 -0
  115. package/dist/parser/parser.d.ts +49 -0
  116. package/dist/parser/parser.d.ts.map +1 -0
  117. package/dist/parser/parser.js +54 -0
  118. package/dist/parser/parser.js.map +1 -0
  119. package/dist/parser/script.d.ts +14 -0
  120. package/dist/parser/script.d.ts.map +1 -0
  121. package/dist/parser/script.js +196 -0
  122. package/dist/parser/script.js.map +1 -0
  123. package/dist/parser/state.d.ts +40 -0
  124. package/dist/parser/state.d.ts.map +1 -0
  125. package/dist/parser/state.js +129 -0
  126. package/dist/parser/state.js.map +1 -0
  127. package/dist/parser/variables.d.ts +10 -0
  128. package/dist/parser/variables.d.ts.map +1 -0
  129. package/dist/parser/variables.js +215 -0
  130. package/dist/parser/variables.js.map +1 -0
  131. package/dist/runtime/ast-equals.d.ts +13 -0
  132. package/dist/runtime/ast-equals.d.ts.map +1 -0
  133. package/dist/runtime/ast-equals.js +447 -0
  134. package/dist/runtime/ast-equals.js.map +1 -0
  135. package/dist/runtime/builtins.d.ts +13 -0
  136. package/dist/runtime/builtins.d.ts.map +1 -0
  137. package/dist/runtime/builtins.js +180 -0
  138. package/dist/runtime/builtins.js.map +1 -0
  139. package/dist/runtime/callable.d.ts +88 -0
  140. package/dist/runtime/callable.d.ts.map +1 -0
  141. package/dist/runtime/callable.js +98 -0
  142. package/dist/runtime/callable.js.map +1 -0
  143. package/dist/runtime/context.d.ts +13 -0
  144. package/dist/runtime/context.d.ts.map +1 -0
  145. package/dist/runtime/context.js +73 -0
  146. package/dist/runtime/context.js.map +1 -0
  147. package/dist/runtime/core/callable.d.ts +171 -0
  148. package/dist/runtime/core/callable.d.ts.map +1 -0
  149. package/dist/runtime/core/callable.js +246 -0
  150. package/dist/runtime/core/callable.js.map +1 -0
  151. package/dist/runtime/core/context.d.ts +29 -0
  152. package/dist/runtime/core/context.d.ts.map +1 -0
  153. package/dist/runtime/core/context.js +154 -0
  154. package/dist/runtime/core/context.js.map +1 -0
  155. package/dist/runtime/core/equals.d.ts +9 -0
  156. package/dist/runtime/core/equals.d.ts.map +1 -0
  157. package/dist/runtime/core/equals.js +381 -0
  158. package/dist/runtime/core/equals.js.map +1 -0
  159. package/dist/runtime/core/eval/base.d.ts +65 -0
  160. package/dist/runtime/core/eval/base.d.ts.map +1 -0
  161. package/dist/runtime/core/eval/base.js +112 -0
  162. package/dist/runtime/core/eval/base.js.map +1 -0
  163. package/dist/runtime/core/eval/evaluator.d.ts +47 -0
  164. package/dist/runtime/core/eval/evaluator.d.ts.map +1 -0
  165. package/dist/runtime/core/eval/evaluator.js +73 -0
  166. package/dist/runtime/core/eval/evaluator.js.map +1 -0
  167. package/dist/runtime/core/eval/index.d.ts +57 -0
  168. package/dist/runtime/core/eval/index.d.ts.map +1 -0
  169. package/dist/runtime/core/eval/index.js +95 -0
  170. package/dist/runtime/core/eval/index.js.map +1 -0
  171. package/dist/runtime/core/eval/mixins/annotations.d.ts +19 -0
  172. package/dist/runtime/core/eval/mixins/annotations.d.ts.map +1 -0
  173. package/dist/runtime/core/eval/mixins/annotations.js +146 -0
  174. package/dist/runtime/core/eval/mixins/annotations.js.map +1 -0
  175. package/dist/runtime/core/eval/mixins/closures.d.ts +49 -0
  176. package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -0
  177. package/dist/runtime/core/eval/mixins/closures.js +479 -0
  178. package/dist/runtime/core/eval/mixins/closures.js.map +1 -0
  179. package/dist/runtime/core/eval/mixins/collections.d.ts +24 -0
  180. package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -0
  181. package/dist/runtime/core/eval/mixins/collections.js +466 -0
  182. package/dist/runtime/core/eval/mixins/collections.js.map +1 -0
  183. package/dist/runtime/core/eval/mixins/control-flow.d.ts +27 -0
  184. package/dist/runtime/core/eval/mixins/control-flow.d.ts.map +1 -0
  185. package/dist/runtime/core/eval/mixins/control-flow.js +369 -0
  186. package/dist/runtime/core/eval/mixins/control-flow.js.map +1 -0
  187. package/dist/runtime/core/eval/mixins/core.d.ts +24 -0
  188. package/dist/runtime/core/eval/mixins/core.d.ts.map +1 -0
  189. package/dist/runtime/core/eval/mixins/core.js +335 -0
  190. package/dist/runtime/core/eval/mixins/core.js.map +1 -0
  191. package/dist/runtime/core/eval/mixins/expressions.d.ts +19 -0
  192. package/dist/runtime/core/eval/mixins/expressions.d.ts.map +1 -0
  193. package/dist/runtime/core/eval/mixins/expressions.js +202 -0
  194. package/dist/runtime/core/eval/mixins/expressions.js.map +1 -0
  195. package/dist/runtime/core/eval/mixins/extraction.d.ts +10 -0
  196. package/dist/runtime/core/eval/mixins/extraction.d.ts.map +1 -0
  197. package/dist/runtime/core/eval/mixins/extraction.js +250 -0
  198. package/dist/runtime/core/eval/mixins/extraction.js.map +1 -0
  199. package/dist/runtime/core/eval/mixins/literals.d.ts +23 -0
  200. package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -0
  201. package/dist/runtime/core/eval/mixins/literals.js +180 -0
  202. package/dist/runtime/core/eval/mixins/literals.js.map +1 -0
  203. package/dist/runtime/core/eval/mixins/types.d.ts +20 -0
  204. package/dist/runtime/core/eval/mixins/types.d.ts.map +1 -0
  205. package/dist/runtime/core/eval/mixins/types.js +109 -0
  206. package/dist/runtime/core/eval/mixins/types.js.map +1 -0
  207. package/dist/runtime/core/eval/mixins/variables.d.ts +34 -0
  208. package/dist/runtime/core/eval/mixins/variables.d.ts.map +1 -0
  209. package/dist/runtime/core/eval/mixins/variables.js +247 -0
  210. package/dist/runtime/core/eval/mixins/variables.js.map +1 -0
  211. package/dist/runtime/core/eval/types.d.ts +41 -0
  212. package/dist/runtime/core/eval/types.d.ts.map +1 -0
  213. package/dist/runtime/core/eval/types.js +10 -0
  214. package/dist/runtime/core/eval/types.js.map +1 -0
  215. package/dist/runtime/core/evaluate.d.ts +42 -0
  216. package/dist/runtime/core/evaluate.d.ts.map +1 -0
  217. package/dist/runtime/core/evaluate.debug.js +1251 -0
  218. package/dist/runtime/core/evaluate.js +1913 -0
  219. package/dist/runtime/core/evaluate.js.map +1 -0
  220. package/dist/runtime/core/execute.d.ts +26 -0
  221. package/dist/runtime/core/execute.d.ts.map +1 -0
  222. package/dist/runtime/core/execute.js +177 -0
  223. package/dist/runtime/core/execute.js.map +1 -0
  224. package/dist/runtime/core/signals.d.ts +19 -0
  225. package/dist/runtime/core/signals.d.ts.map +1 -0
  226. package/dist/runtime/core/signals.js +26 -0
  227. package/dist/runtime/core/signals.js.map +1 -0
  228. package/dist/runtime/core/types.d.ts +177 -0
  229. package/dist/runtime/core/types.d.ts.map +1 -0
  230. package/dist/runtime/core/types.js +50 -0
  231. package/dist/runtime/core/types.js.map +1 -0
  232. package/dist/runtime/core/values.d.ts +66 -0
  233. package/dist/runtime/core/values.d.ts.map +1 -0
  234. package/dist/runtime/core/values.js +240 -0
  235. package/dist/runtime/core/values.js.map +1 -0
  236. package/dist/runtime/evaluate.d.ts +32 -0
  237. package/dist/runtime/evaluate.d.ts.map +1 -0
  238. package/dist/runtime/evaluate.js +1111 -0
  239. package/dist/runtime/evaluate.js.map +1 -0
  240. package/dist/runtime/execute.d.ts +26 -0
  241. package/dist/runtime/execute.d.ts.map +1 -0
  242. package/dist/runtime/execute.js +121 -0
  243. package/dist/runtime/execute.js.map +1 -0
  244. package/dist/runtime/ext/builtins.d.ts +16 -0
  245. package/dist/runtime/ext/builtins.d.ts.map +1 -0
  246. package/dist/runtime/ext/builtins.js +528 -0
  247. package/dist/runtime/ext/builtins.js.map +1 -0
  248. package/dist/runtime/ext/content-parser.d.ts +83 -0
  249. package/dist/runtime/ext/content-parser.d.ts.map +1 -0
  250. package/dist/runtime/ext/content-parser.js +536 -0
  251. package/dist/runtime/ext/content-parser.js.map +1 -0
  252. package/dist/runtime/index.d.ts +28 -0
  253. package/dist/runtime/index.d.ts.map +1 -0
  254. package/dist/runtime/index.js +34 -0
  255. package/dist/runtime/index.js.map +1 -0
  256. package/dist/runtime/signals.d.ts +19 -0
  257. package/dist/runtime/signals.d.ts.map +1 -0
  258. package/dist/runtime/signals.js +26 -0
  259. package/dist/runtime/signals.js.map +1 -0
  260. package/dist/runtime/types.d.ts +169 -0
  261. package/dist/runtime/types.d.ts.map +1 -0
  262. package/dist/runtime/types.js +50 -0
  263. package/dist/runtime/types.js.map +1 -0
  264. package/dist/runtime/values.d.ts +50 -0
  265. package/dist/runtime/values.d.ts.map +1 -0
  266. package/dist/runtime/values.js +209 -0
  267. package/dist/runtime/values.js.map +1 -0
  268. package/dist/runtime.d.ts +254 -0
  269. package/dist/runtime.d.ts.map +1 -0
  270. package/dist/runtime.js +2014 -0
  271. package/dist/runtime.js.map +1 -0
  272. package/dist/types.d.ts +752 -0
  273. package/dist/types.d.ts.map +1 -0
  274. package/dist/types.js +189 -0
  275. package/dist/types.js.map +1 -0
  276. package/docs/00_INDEX.md +65 -0
  277. package/docs/01_guide.md +390 -0
  278. package/docs/02_types.md +399 -0
  279. package/docs/03_variables.md +314 -0
  280. package/docs/04_operators.md +551 -0
  281. package/docs/05_control-flow.md +350 -0
  282. package/docs/06_closures.md +353 -0
  283. package/docs/07_collections.md +686 -0
  284. package/docs/08_iterators.md +330 -0
  285. package/docs/09_strings.md +205 -0
  286. package/docs/10_parsing.md +366 -0
  287. package/docs/11_reference.md +350 -0
  288. package/docs/12_examples.md +771 -0
  289. package/docs/13_modules.md +519 -0
  290. package/docs/14_host-integration.md +826 -0
  291. package/docs/15_grammar.ebnf +693 -0
  292. package/docs/16_conventions.md +696 -0
  293. package/docs/99_llm-reference.txt +300 -0
  294. package/docs/assets/logo.png +0 -0
  295. package/package.json +70 -0
@@ -0,0 +1,551 @@
1
+ # rill Operators
2
+
3
+ *Pipe, arithmetic, comparison, logical, spread, and extraction operators*
4
+
5
+ ## Overview
6
+
7
+ | Category | Operators |
8
+ |----------|-----------|
9
+ | Pipe | `->` |
10
+ | Capture | `:>` |
11
+ | Arithmetic | `+`, `-`, `*`, `/`, `%` |
12
+ | Comparison | `==`, `!=`, `<`, `>`, `<=`, `>=` |
13
+ | Comparison Methods | `.eq`, `.ne`, `.lt`, `.gt`, `.le`, `.ge` |
14
+ | Logical | `!` (unary), `&&`, `||` |
15
+ | Spread | `@` (sequential), `*` (tuple) |
16
+ | Extraction | `*<>` (destructure), `/<>` (slice) |
17
+ | Type | `:type` (assert), `:?type` (check) |
18
+ | Member | `.field`, `[index]` |
19
+ | Default | `?? value` |
20
+ | Existence | `.?field`, `.?field&type` |
21
+
22
+ ---
23
+
24
+ ## Pipe Operator `->`
25
+
26
+ The pipe operator passes the left-hand value to the right-hand side:
27
+
28
+ ```rill
29
+ "hello" -> .upper # "HELLO"
30
+ 42 -> ($ + 8) # 50
31
+ [1, 2, 3] -> each { $ * 2 } # [2, 4, 6]
32
+ ```
33
+
34
+ ### Piped Value as `$`
35
+
36
+ The piped value is available as `$`:
37
+
38
+ ```rill
39
+ "world" -> "hello {$}" # "hello world"
40
+ 5 -> ($ * $ + $) # 30
41
+ ```
42
+
43
+ ### Method Syntax
44
+
45
+ Method calls are sugar for pipes:
46
+
47
+ ```rill
48
+ "hello".upper # equivalent: "hello" -> .upper
49
+ "hello".contains("ell") # equivalent: "hello" -> .contains("ell")
50
+ ```
51
+
52
+ ### Implicit `$`
53
+
54
+ Bare `.method()` implies `$` as receiver:
55
+
56
+ ```rill
57
+ "hello" -> {
58
+ .upper -> log # $."upper" -> log
59
+ .len # $.len
60
+ }
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Capture Operator `:>`
66
+
67
+ Captures a value into a variable:
68
+
69
+ ```rill
70
+ "hello" :> $greeting # store in $greeting
71
+ 42 :> $count # store in $count
72
+ ```
73
+
74
+ ### Capture and Continue
75
+
76
+ `:>` captures AND continues the chain:
77
+
78
+ ```rill
79
+ "hello" :> $a -> .upper :> $b -> .len
80
+ # $a is "hello", $b is "HELLO", result is 5
81
+ ```
82
+
83
+ See [Variables](03_variables.md) for detailed scoping rules.
84
+
85
+ ---
86
+
87
+ ## Arithmetic Operators
88
+
89
+ | Operator | Description |
90
+ |----------|-------------|
91
+ | `+` | Addition |
92
+ | `-` | Subtraction |
93
+ | `*` | Multiplication |
94
+ | `/` | Division |
95
+ | `%` | Modulo (remainder) |
96
+
97
+ ```rill
98
+ 5 + 3 # 8
99
+ 10 - 4 # 6
100
+ 3 * 4 # 12
101
+ 15 / 3 # 5
102
+ 17 % 5 # 2
103
+ ```
104
+
105
+ ### Precedence
106
+
107
+ Standard mathematical precedence (high to low):
108
+ 1. Unary: `-`, `!`
109
+ 2. Multiplicative: `*`, `/`, `%`
110
+ 3. Additive: `+`, `-`
111
+
112
+ ```rill
113
+ 2 + 3 * 4 # 14 (multiplication first)
114
+ (2 + 3) * 4 # 20 (parentheses override)
115
+ -5 + 3 # -2
116
+ ```
117
+
118
+ ### Type Constraint
119
+
120
+ All operands must be numbers. No implicit conversion:
121
+
122
+ ```rill
123
+ 5 + 3 # OK: 8
124
+ ```
125
+
126
+ ```text
127
+ "5" + 1 # ERROR: Arithmetic requires number, got string
128
+ ```
129
+
130
+ ### Error Handling
131
+
132
+ ```text
133
+ 10 / 0 # ERROR: Division by zero
134
+ 10 % 0 # ERROR: Modulo by zero
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Comparison Operators
140
+
141
+ | Operator | Description |
142
+ |----------|-------------|
143
+ | `==` | Equal |
144
+ | `!=` | Not equal |
145
+ | `<` | Less than |
146
+ | `>` | Greater than |
147
+ | `<=` | Less or equal |
148
+ | `>=` | Greater or equal |
149
+
150
+ ```rill
151
+ 5 == 5 # true
152
+ 5 != 3 # true
153
+ 3 < 5 # true
154
+ 5 > 3 # true
155
+ 5 <= 5 # true
156
+ 5 >= 3 # true
157
+ ```
158
+
159
+ ### Value Comparison
160
+
161
+ All comparisons are by value, not reference:
162
+
163
+ ```rill
164
+ [1, 2, 3] == [1, 2, 3] # true
165
+ [a: 1] == [a: 1] # true
166
+ "hello" == "hello" # true
167
+ ```
168
+
169
+ ### Comparison Methods
170
+
171
+ Methods provide readable alternatives in conditionals:
172
+
173
+ | Method | Equivalent |
174
+ |--------|------------|
175
+ | `.eq(val)` | `== val` |
176
+ | `.ne(val)` | `!= val` |
177
+ | `.lt(val)` | `< val` |
178
+ | `.gt(val)` | `> val` |
179
+ | `.le(val)` | `<= val` |
180
+ | `.ge(val)` | `>= val` |
181
+
182
+ ```rill
183
+ "A" :> $v
184
+ $v -> .eq("A") ? "match" ! "no" # "match"
185
+ 5 -> .gt(3) ? "big" ! "small" # "big"
186
+ 10 -> .le(10) ? "ok" ! "over" # "ok"
187
+ ```
188
+
189
+ ---
190
+
191
+ ## Logical Operators
192
+
193
+ | Operator | Description |
194
+ |----------|-------------|
195
+ | `&&` | Logical AND (short-circuit) |
196
+ | `\|\|` | Logical OR (short-circuit) |
197
+ | `!` | Logical NOT |
198
+
199
+ ```rill
200
+ (true && false) # false
201
+ (true || false) # true
202
+ !true # false
203
+ !false # true
204
+ ```
205
+
206
+ ### Short-Circuit Evaluation
207
+
208
+ ```rill
209
+ (false && undefined_var) # false (right side not evaluated)
210
+ (true || undefined_var) # true (right side not evaluated)
211
+ ```
212
+
213
+ ### With Comparisons
214
+
215
+ ```rill
216
+ (1 < 2 && 3 > 2) # true
217
+ (5 > 10 || 3 < 5) # true
218
+ ```
219
+
220
+ ### Grouping Required
221
+
222
+ Compound expressions require grouping in simple-body contexts:
223
+
224
+ ```rill
225
+ true -> ($ && true) ? "both" ! "not both" # "both"
226
+ ```
227
+
228
+ ### Negation in Pipes
229
+
230
+ In pipe targets, `!expr` binds tightly and returns a boolean:
231
+
232
+ ```rill
233
+ "hello" -> !.empty # true (not empty)
234
+ "" -> !.empty # false (is empty)
235
+ ```
236
+
237
+ This works naturally with conditionals and captures:
238
+
239
+ ```rill
240
+ "hello" -> !.empty ? "has content" ! "empty" # "has content"
241
+ "hello" -> !.empty :> $not_empty # $not_empty = true
242
+ ```
243
+
244
+ No grouping needed — `!.empty` is parsed as a unit before `?` or `:>`.
245
+
246
+ ---
247
+
248
+ ## Spread Operators
249
+
250
+ ### Sequential Spread `@`
251
+
252
+ Chain closures where each receives the previous result (fold pattern):
253
+
254
+ ```rill
255
+ |x|($x + 1) :> $inc
256
+ |x|($x * 2) :> $double
257
+ |x|($x + 10) :> $add10
258
+
259
+ # Chain: (5 + 1) = 6, (6 * 2) = 12, (12 + 10) = 22
260
+ 5 -> @[$inc, $double, $add10] # 22
261
+ ```
262
+
263
+ Single closure:
264
+
265
+ ```rill
266
+ |x|($x * 2) :> $dbl
267
+ 5 -> @$dbl # 10
268
+ ```
269
+
270
+ ### Tuple Spread `*`
271
+
272
+ Create tuples for argument unpacking:
273
+
274
+ ```rill
275
+ # From list (positional)
276
+ *[1, 2, 3] :> $args
277
+
278
+ # From dict (named)
279
+ *[x: 1, y: 2] :> $named
280
+
281
+ # Convert list to tuple via pipe
282
+ [1, 2, 3] -> * :> $tuple
283
+ ```
284
+
285
+ Using tuples at invocation:
286
+
287
+ ```rill
288
+ |a, b, c|"{$a}-{$b}-{$c}" :> $fmt
289
+ *[1, 2, 3] -> $fmt() # "1-2-3"
290
+ *[c: 3, a: 1, b: 2] -> $fmt() # "1-2-3" (named, order doesn't matter)
291
+ ```
292
+
293
+ See [Types](02_types.md) for full tuple documentation.
294
+
295
+ ---
296
+
297
+ ## Extraction Operators
298
+
299
+ ### Destructure `*<>`
300
+
301
+ Extract elements from lists or dicts into variables. Returns the original value unchanged.
302
+
303
+ **List destructuring** (pattern count must match list length):
304
+
305
+ ```rill
306
+ [1, 2, 3] -> *<$a, $b, $c>
307
+ # $a = 1, $b = 2, $c = 3
308
+ ```
309
+
310
+ **With type annotations:**
311
+
312
+ ```rill
313
+ [0, "ok"] -> *<$code:number, $msg:string>
314
+ # $code = 0, $msg = "ok"
315
+ ```
316
+
317
+ **Skip elements with `_`:**
318
+
319
+ ```rill
320
+ [1, 2, 3, 4] -> *<$first, _, _, $last>
321
+ # $first = 1, $last = 4
322
+ ```
323
+
324
+ **Dict destructuring** (explicit key mapping):
325
+
326
+ ```rill
327
+ [name: "test", count: 42] -> *<name: $n, count: $c>
328
+ # $n = "test", $c = 42
329
+ ```
330
+
331
+ **Nested destructuring:**
332
+
333
+ ```rill
334
+ [[1, 2], 3] -> *<*<$a, $b>, $c>
335
+ # $a = 1, $b = 2, $c = 3
336
+ ```
337
+
338
+ **Errors:**
339
+
340
+ ```text
341
+ [1, 2] -> *<$a, $b, $c> # Error: pattern has 3 elements, list has 2
342
+ [name: "x"] -> *<name: $n, age: $a> # Error: key 'age' not found
343
+ ```
344
+
345
+ ### Slice `/<>`
346
+
347
+ Extract a portion using Python-style `start:stop:step`. Works on lists and strings.
348
+
349
+ **Basic slicing:**
350
+
351
+ ```rill
352
+ [0, 1, 2, 3, 4] -> /<0:3> # [0, 1, 2]
353
+ [0, 1, 2, 3, 4] -> /<1:4> # [1, 2, 3]
354
+ ```
355
+
356
+ **Omitted bounds:**
357
+
358
+ ```rill
359
+ [0, 1, 2, 3, 4] -> /<:3> # [0, 1, 2] (first 3)
360
+ [0, 1, 2, 3, 4] -> /<2:> # [2, 3, 4] (from index 2)
361
+ ```
362
+
363
+ **Negative indices:**
364
+
365
+ ```rill
366
+ [0, 1, 2, 3, 4] -> /<-2:> # [3, 4] (last 2)
367
+ [0, 1, 2, 3, 4] -> /<:-1> # [0, 1, 2, 3] (all but last)
368
+ ```
369
+
370
+ **Step:**
371
+
372
+ ```rill
373
+ [0, 1, 2, 3, 4] -> /<::2> # [0, 2, 4] (every 2nd)
374
+ [0, 1, 2, 3, 4] -> /<::-1> # [4, 3, 2, 1, 0] (reversed)
375
+ ```
376
+
377
+ **String slicing:**
378
+
379
+ ```rill
380
+ "hello" -> /<1:4> # "ell"
381
+ "hello" -> /<::-1> # "olleh"
382
+ ```
383
+
384
+ **Edge cases:**
385
+
386
+ ```rill
387
+ [1, 2, 3] -> /<0:100> # [1, 2, 3] (clamped)
388
+ [1, 2, 3] -> /<2:1> # [] (empty when start >= stop)
389
+ ```
390
+
391
+ ```text
392
+ [1, 2, 3] -> /<::0> # Error: step cannot be zero
393
+ ```
394
+
395
+ ---
396
+
397
+ ## Member Access Operators
398
+
399
+ ### Field Access `.field`
400
+
401
+ Access dict fields:
402
+
403
+ ```rill
404
+ [name: "alice", age: 30] :> $person
405
+ $person.name # "alice"
406
+ $person.age # 30
407
+ ```
408
+
409
+ ### Index Access `[n]`
410
+
411
+ Access list elements (0-based, negative from end):
412
+
413
+ ```rill
414
+ ["a", "b", "c"] :> $list
415
+ $list[0] # "a"
416
+ $list[-1] # "c"
417
+ $list[1] # "b"
418
+ ```
419
+
420
+ ### Variable Key `.$key`
421
+
422
+ Use a variable as key:
423
+
424
+ ```rill
425
+ "name" :> $key
426
+ [name: "alice"] :> $data
427
+ $data.$key # "alice"
428
+ ```
429
+
430
+ ### Computed Key `.($expr)`
431
+
432
+ Use an expression as key:
433
+
434
+ ```rill
435
+ 0 :> $i
436
+ ["a", "b", "c"] :> $list
437
+ $list.($i + 1) # "b"
438
+ ```
439
+
440
+ ### Alternative Keys `.(a || b)`
441
+
442
+ Try keys left-to-right:
443
+
444
+ ```rill
445
+ [nickname: "Al"] :> $user
446
+ $user.(name || nickname) # "Al"
447
+ ```
448
+
449
+ ---
450
+
451
+ ## Default Operator `??`
452
+
453
+ Provide a default value if field is missing:
454
+
455
+ ```rill
456
+ [:] :> $empty
457
+ $empty.name ?? "unknown" # "unknown"
458
+
459
+ [name: "alice"] :> $user
460
+ $user.name ?? "unknown" # "alice"
461
+ $user.age ?? 0 # 0
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Existence Operators
467
+
468
+ ### Field Existence `.?field`
469
+
470
+ Returns boolean:
471
+
472
+ ```rill
473
+ [name: "alice"] :> $user
474
+ $user.?name # true
475
+ $user.?age # false
476
+ ```
477
+
478
+ ### Existence with Type `.?field&type`
479
+
480
+ Check existence AND type:
481
+
482
+ ```rill
483
+ [name: "alice", age: 30] :> $user
484
+ $user.?name&string # true
485
+ $user.?age&number # true
486
+ $user.?age&string # false
487
+ ```
488
+
489
+ ---
490
+
491
+ ## Type Operators
492
+
493
+ ### Type Assert `:type`
494
+
495
+ Error if type doesn't match, returns value unchanged:
496
+
497
+ ```rill
498
+ 42:number # 42
499
+ "hello" -> :string # "hello"
500
+ ```
501
+
502
+ ```text
503
+ "hello" -> :number # ERROR: expected number, got string
504
+ ```
505
+
506
+ ### Type Check `:?type`
507
+
508
+ Returns boolean:
509
+
510
+ ```rill
511
+ 42:?number # true
512
+ "hello":?number # false
513
+ "hello" -> :?string # true
514
+ ```
515
+
516
+ See [Types](02_types.md) for detailed type system documentation.
517
+
518
+ ---
519
+
520
+ ## Operator Precedence
521
+
522
+ From highest to lowest:
523
+
524
+ 1. Member access: `.field`, `[index]`
525
+ 2. Type operators: `:type`, `:?type`
526
+ 3. Unary: `-`, `!`
527
+ 4. Multiplicative: `*`, `/`, `%`
528
+ 5. Additive: `+`, `-`
529
+ 6. Comparison: `==`, `!=`, `<`, `>`, `<=`, `>=`
530
+ 7. Logical AND: `&&`
531
+ 8. Logical OR: `||`
532
+ 9. Default: `??`
533
+ 10. Pipe: `->`
534
+ 11. Capture: `:>`
535
+
536
+ Use parentheses to override precedence:
537
+
538
+ ```rill
539
+ (2 + 3) * 4 # 20
540
+ 5 -> ($ > 3) ? "big" ! "small" # "big"
541
+ ```
542
+
543
+ ---
544
+
545
+ ## See Also
546
+
547
+ - [Types](02_types.md) — Type system and assertions
548
+ - [Variables](03_variables.md) — Capture and scope
549
+ - [Control Flow](05_control-flow.md) — Conditionals and loops
550
+ - [Collections](07_collections.md) — Collection operators
551
+ - [Reference](11_reference.md) — Quick reference tables