@rcrsr/rill 0.7.1 → 0.8.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.
- package/README.md +1 -1
- package/dist/ast-nodes.d.ts +635 -0
- package/dist/ast-nodes.d.ts.map +1 -0
- package/dist/ast-nodes.js +2 -0
- package/dist/ast-nodes.js.map +1 -0
- package/dist/ast-unions.d.ts +6 -0
- package/dist/ast-unions.d.ts.map +1 -0
- package/dist/ast-unions.js +6 -0
- package/dist/ast-unions.js.map +1 -0
- package/dist/error-classes.d.ts +90 -0
- package/dist/error-classes.d.ts.map +1 -0
- package/dist/error-classes.js +185 -0
- package/dist/error-classes.js.map +1 -0
- package/dist/error-registry.d.ts +93 -0
- package/dist/error-registry.d.ts.map +1 -0
- package/dist/error-registry.js +712 -0
- package/dist/error-registry.js.map +1 -0
- package/dist/generated/introspection-data.d.ts +1 -1
- package/dist/generated/introspection-data.d.ts.map +1 -1
- package/dist/generated/introspection-data.js +509 -481
- package/dist/generated/introspection-data.js.map +1 -1
- package/dist/generated/version-data.d.ts +1 -1
- package/dist/generated/version-data.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parser/parser-expr.js +9 -6
- package/dist/parser/parser-expr.js.map +1 -1
- package/dist/runtime/core/callable.d.ts +5 -5
- package/dist/runtime/core/callable.d.ts.map +1 -1
- package/dist/runtime/core/callable.js +2 -1
- package/dist/runtime/core/callable.js.map +1 -1
- package/dist/runtime/core/eval/mixins/collections.d.ts.map +1 -1
- package/dist/runtime/core/eval/mixins/collections.js +5 -1
- package/dist/runtime/core/eval/mixins/collections.js.map +1 -1
- package/dist/runtime/core/eval/mixins/literals.d.ts.map +1 -1
- package/dist/runtime/core/eval/mixins/literals.js +5 -1
- package/dist/runtime/core/eval/mixins/literals.js.map +1 -1
- package/dist/runtime/core/eval/mixins/variables.js +12 -12
- package/dist/runtime/core/eval/mixins/variables.js.map +1 -1
- package/dist/runtime/core/values.d.ts +31 -3
- package/dist/runtime/core/values.d.ts.map +1 -1
- package/dist/runtime/core/values.js +47 -1
- package/dist/runtime/core/values.js.map +1 -1
- package/dist/runtime/ext/builtins.d.ts.map +1 -1
- package/dist/runtime/ext/builtins.js +202 -1
- package/dist/runtime/ext/builtins.js.map +1 -1
- package/dist/runtime/ext/extensions.d.ts +39 -3
- package/dist/runtime/ext/extensions.d.ts.map +1 -1
- package/dist/runtime/ext/extensions.js +77 -12
- package/dist/runtime/ext/extensions.js.map +1 -1
- package/dist/runtime/index.d.ts +5 -5
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/index.js.map +1 -1
- package/dist/source-location.d.ts +10 -0
- package/dist/source-location.d.ts.map +1 -0
- package/dist/source-location.js +5 -0
- package/dist/source-location.js.map +1 -0
- package/dist/token-types.d.ts +68 -0
- package/dist/token-types.d.ts.map +1 -0
- package/dist/token-types.js +79 -0
- package/dist/token-types.js.map +1 -0
- package/dist/types.d.ts +9 -882
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -958
- package/dist/types.js.map +1 -1
- package/dist/value-types.d.ts +3 -0
- package/dist/value-types.d.ts.map +1 -0
- package/dist/value-types.js +2 -0
- package/dist/value-types.js.map +1 -0
- package/package.json +15 -2
|
@@ -1,538 +1,566 @@
|
|
|
1
1
|
// AUTO-GENERATED - DO NOT EDIT
|
|
2
2
|
// Generated by packages/core/scripts/generate-docs-bundle.ts from docs/ref-llm.txt
|
|
3
|
-
export const LANGUAGE_REFERENCE =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
export const LANGUAGE_REFERENCE = `# rill
|
|
4
|
+
|
|
5
|
+
> Scripting language designed for machine-generated code. LLMs generate rill scripts; humans review and debug. Data flows through pipes (\`->\`), not assignment. Variables use \`\$\` prefix. No null, no exceptions, no truthiness.
|
|
6
|
+
|
|
7
|
+
## Documentation
|
|
8
|
+
|
|
9
|
+
- [Getting Started](https://rill.run/docs/guide/getting-started/): Beginner-friendly introduction to rill
|
|
10
|
+
- [Language Reference](https://rill.run/docs/reference/language/): Core language specification
|
|
11
|
+
- [Examples](https://rill.run/docs/guide/examples/): Workflow patterns and use cases
|
|
12
|
+
- [Cookbook](https://rill.run/docs/guide/cookbook/): Advanced agent scripting patterns
|
|
13
|
+
- [Types](https://rill.run/docs/language/types/): Primitives, tuples, dicts, type assertions
|
|
14
|
+
- [Variables](https://rill.run/docs/language/variables/): Declaration, scope rules, \`\$\` binding
|
|
15
|
+
- [Control Flow](https://rill.run/docs/language/control-flow/): Conditionals, loops, break/return
|
|
16
|
+
- [Operators](https://rill.run/docs/language/operators/): Arithmetic, comparison, spread, extraction
|
|
17
|
+
- [Closures](https://rill.run/docs/language/closures/): Late binding, dict-bound closures
|
|
18
|
+
- [Collections](https://rill.run/docs/data/collections/): \`each\`, \`map\`, \`filter\`, \`fold\` operators
|
|
19
|
+
- [Iterators](https://rill.run/docs/data/iterators/): Lazy sequences with \`range\`, \`repeat\`, \`.first()\`
|
|
20
|
+
- [Strings](https://rill.run/docs/data/strings/): String methods for text manipulation
|
|
21
|
+
- [Host Integration](https://rill.run/docs/integration/host/): Embedding rill in applications
|
|
22
|
+
- [Host API Reference](https://rill.run/docs/reference/host-api/): Complete TypeScript API exports
|
|
23
|
+
- [Developing Extensions](https://rill.run/docs/integration/extensions/): Writing reusable host function packages
|
|
24
|
+
- [Modules](https://rill.run/docs/integration/modules/): Convention for host-provided module systems
|
|
25
|
+
- [CLI Tools](https://rill.run/docs/integration/cli/): \`rill-exec\`, \`rill-eval\`, \`rill-check\` commands
|
|
26
|
+
- [Error Reference](https://rill.run/docs/reference/errors/): Error codes and resolution
|
|
27
|
+
|
|
28
|
+
## Essentials
|
|
29
|
+
|
|
30
|
+
1. Variables use \`\$\` prefix ALWAYS: \`5 => \$x\` (no assignment operator \`=\`)
|
|
31
|
+
2. Pipe with \`->\`, capture with \`=>\`: \`"hello" => \$x -> .upper => \$y\`
|
|
13
32
|
3. No null/undefined, no try/catch, no truthiness (conditions must be boolean)
|
|
14
|
-
4. Variables lock to first type:
|
|
15
|
-
5. Loops cannot modify outer vars: use fold
|
|
33
|
+
4. Variables lock to first type: \`"hi" => \$x; 42 => \$x\` is an ERROR
|
|
34
|
+
5. Loops cannot modify outer vars: use \`fold\`, \`each(init)\`, or \`\$\` as state dict
|
|
35
|
+
|
|
36
|
+
## Strengths and Use Cases
|
|
16
37
|
|
|
17
|
-
STRENGTHS AND USE CASES
|
|
18
|
-
-----------------------
|
|
19
38
|
Strengths:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
39
|
+
- Unambiguous syntax: \`\$\` prefix, explicit operators, no implicit coercion
|
|
40
|
+
- Single-pass parseable: LLMs generate correct code without symbol tables
|
|
41
|
+
- Readable by humans: pipe chains show data flow left-to-right
|
|
42
|
+
- Safe defaults: immutable values, type locking, no null/undefined
|
|
24
43
|
|
|
25
44
|
Use cases:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
State machine pattern (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
\$.state
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
- Workflow orchestration: chain LLM calls, API requests, transformations
|
|
46
|
+
- State machines: \`(cond) @ { }\` loops with \`\$\` as state dict
|
|
47
|
+
- Data pipelines: \`each\`/\`map\`/\`filter\`/\`fold\` process collections declaratively
|
|
48
|
+
|
|
49
|
+
State machine pattern (\`\$\` carries state through iterations):
|
|
50
|
+
|
|
51
|
+
[state: "init", data: \$input]
|
|
52
|
+
-> (\$.state != "done") @ {
|
|
53
|
+
\$.state -> [
|
|
54
|
+
init: { [state: "process", data: transform(\$.data)] },
|
|
55
|
+
process: { [state: "done", data: finalize(\$.data)] }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
## Naming Convention: snake_case
|
|
60
|
+
|
|
41
61
|
Use snake_case for all identifiers:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
closure? Is data a variable or key? This would require tracking all declarations.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Operators:
|
|
61
|
-
Parentheses:
|
|
62
|
-
Braces:
|
|
63
|
-
Brackets:
|
|
64
|
-
Literals:
|
|
65
|
-
Closures:
|
|
66
|
-
Methods:
|
|
67
|
-
Pipes:
|
|
68
|
-
Continuations: indent 2 spaces
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
\$.method() -> .method "x" -> .upper (not \$.upper())
|
|
75
|
-
func(\$) -> func "x" -> log (not log(\$))
|
|
76
|
-
\$fn(\$) -> \$fn 5 -> \$double (not \$double(\$))
|
|
77
|
-
|
|
78
|
-
Don't capture just to continue
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
|
|
63
|
+
\$user_name, \$item_list, \$is_valid # variables
|
|
64
|
+
\$double_value, \$cleanup_text # closures
|
|
65
|
+
[first_name: "x", last_name: "y"] # dict keys
|
|
66
|
+
|
|
67
|
+
## Why Variables Use \$ Prefix
|
|
68
|
+
|
|
69
|
+
The \`\$\` prefix enables single-pass parsing without a symbol table:
|
|
70
|
+
|
|
71
|
+
name() -> host function call
|
|
72
|
+
\$name() -> closure invocation
|
|
73
|
+
\$name -> variable reference
|
|
74
|
+
name -> dict key literal
|
|
75
|
+
|
|
76
|
+
Without \`\$\`, \`process(data)\` is ambiguous: is \`process\` a host function or stored closure? Is \`data\` a variable or key? This would require tracking all declarations.
|
|
77
|
+
|
|
78
|
+
## Spacing Rules
|
|
79
|
+
|
|
80
|
+
Operators: space both sides 5 + 3, \$x -> .upper, "a" => \$b
|
|
81
|
+
Parentheses: no inner space (\$x + 1), (\$ > 3) ? "yes"
|
|
82
|
+
Braces: space inside { \$x + 1 }, each { \$ * 2 }
|
|
83
|
+
Brackets: no inner space \$list[0], \$dict.items[1]
|
|
84
|
+
Literals: space after , and : [1, 2, 3], [name: "x", age: 30]
|
|
85
|
+
Closures: space after params |x| (\$x * 2), |a, b| { \$a + \$b }
|
|
86
|
+
Methods: no space before . or ( \$str.upper(), \$list.join(", ")
|
|
87
|
+
Pipes: space both sides "x" -> .upper -> .len
|
|
88
|
+
Continuations: indent 2 spaces \$data
|
|
89
|
+
-> .filter { \$.active }
|
|
90
|
+
-> map { \$.name }
|
|
91
|
+
|
|
92
|
+
## Implicit \$ Shorthand (Always Prefer)
|
|
93
|
+
|
|
94
|
+
\$.method() -> .method "x" -> .upper (not \$.upper())
|
|
95
|
+
func(\$) -> func "x" -> log (not log(\$))
|
|
96
|
+
\$fn(\$) -> \$fn 5 -> \$double (not \$double(\$))
|
|
97
|
+
|
|
98
|
+
Don't capture just to continue — use line continuation instead:
|
|
99
|
+
|
|
100
|
+
# avoid # good
|
|
101
|
+
"x" => \$a "x"
|
|
102
|
+
\$a -> .upper => \$b -> .upper
|
|
103
|
+
\$b -> .len -> .len
|
|
83
104
|
|
|
84
105
|
Only capture when the variable is reused later in the code.
|
|
85
106
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
2.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
3.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
196
|
-
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
199
|
-
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
107
|
+
## Critical Differences from Mainstream Languages
|
|
108
|
+
|
|
109
|
+
### 1. No Assignment Operator
|
|
110
|
+
|
|
111
|
+
Wrong: x = 5 Mainstream: x = value
|
|
112
|
+
Right: 5 => \$x rill: value => \$x
|
|
113
|
+
|
|
114
|
+
Pipe (\`->\`): passes value to next operation.
|
|
115
|
+
Capture (\`=>\`): stores value AND continues chain.
|
|
116
|
+
Example: \`"hello" => \$x -> .upper => \$y\` — \`\$x="hello"\`, \`\$y="HELLO"\`.
|
|
117
|
+
|
|
118
|
+
### 2. No Null/Undefined
|
|
119
|
+
|
|
120
|
+
Empty values (\`""\`, \`[]\`, \`[:]\`) exist. "No value" cannot be represented.
|
|
121
|
+
Use \`??\` for defaults: \`\$dict.field ?? "default"\`.
|
|
122
|
+
Use \`.empty\` to check: \`\$str -> .empty ? "was empty"\`.
|
|
123
|
+
|
|
124
|
+
### 3. No Truthiness
|
|
125
|
+
|
|
126
|
+
Conditions MUST be boolean. No implicit coercion.
|
|
127
|
+
|
|
128
|
+
Wrong: "" ? "yes" ! "no" Right: "" -> .empty ? "yes" ! "no"
|
|
129
|
+
Wrong: 0 ? "yes" ! "no" Right: (0 == 0) ? "yes" ! "no"
|
|
130
|
+
|
|
131
|
+
Negation (\`!\`) also requires boolean:
|
|
132
|
+
|
|
133
|
+
!true # false
|
|
134
|
+
"hello" -> .empty -> (!\$) # true (negates boolean from .empty)
|
|
135
|
+
!"hello" # ERROR: Negation requires boolean
|
|
136
|
+
|
|
137
|
+
### 4. Variables Lock to First Type
|
|
138
|
+
|
|
139
|
+
"hello" => \$x
|
|
140
|
+
42 => \$x # ERROR: cannot assign number to string variable
|
|
141
|
+
|
|
142
|
+
### 5. No Variable Shadowing (Critical for Loops)
|
|
143
|
+
|
|
144
|
+
Child scopes can READ parent variables but cannot WRITE or redeclare them.
|
|
145
|
+
Variables created inside blocks/loops do NOT leak out.
|
|
146
|
+
|
|
147
|
+
WRONG — outer variable modification (NEVER works):
|
|
148
|
+
|
|
149
|
+
0 => \$count
|
|
150
|
+
[1, 2, 3] -> each { \$count + 1 => \$count } # creates LOCAL \$count
|
|
151
|
+
\$count # still 0!
|
|
152
|
+
|
|
153
|
+
RIGHT — use \`fold\` for reduction:
|
|
154
|
+
|
|
155
|
+
[1, 2, 3] -> fold(0) { \$@ + \$ } # 6 (\$@ is accumulator)
|
|
156
|
+
|
|
157
|
+
RIGHT — use \`each(init)\` for results AND accumulator:
|
|
158
|
+
|
|
159
|
+
[1, 2, 3] -> each(0) { \$@ + \$ } # [1, 3, 6] (running totals)
|
|
160
|
+
|
|
161
|
+
RIGHT — use \`(cond) @ { }\` with \`\$\` as state dict for multiple values:
|
|
162
|
+
|
|
163
|
+
[iter: 0, max: 3, text: \$input, done: false]
|
|
164
|
+
-> (!\$.done && \$.iter < \$.max) @ {
|
|
165
|
+
\$.iter + 1 => \$i
|
|
166
|
+
process(\$.text) => \$result
|
|
167
|
+
\$result.finished ? [iter: \$i, max: \$.max, text: \$.text, done: true]
|
|
168
|
+
! [iter: \$i, max: \$.max, text: \$result.text, done: false]
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
Pattern summary:
|
|
172
|
+
|
|
173
|
+
Single value accumulation -> fold(init) { \$@ + \$ }
|
|
174
|
+
Per-item results + running -> each(init) { ... \$@ ... }
|
|
175
|
+
Multiple state values / while -> (cond) @ { } with \$ as state dict
|
|
176
|
+
"while" and "for" keywords -> DO NOT EXIST
|
|
177
|
+
|
|
178
|
+
### 6. No Exceptions
|
|
179
|
+
|
|
180
|
+
Errors halt execution. No try/catch. Use conditionals for error handling.
|
|
181
|
+
Built-in: \`assert\` (validate condition), \`error\` (halt with message).
|
|
182
|
+
|
|
183
|
+
### 7. Value Semantics (No References)
|
|
184
|
+
|
|
185
|
+
All copies are deep. All comparisons are by value. No object identity.
|
|
186
|
+
|
|
187
|
+
[1, 2, 3] == [1, 2, 3] # true (content equality)
|
|
188
|
+
[1, 2] => \$a
|
|
189
|
+
\$a => \$b # \$b is an independent deep copy
|
|
190
|
+
|
|
191
|
+
## Syntax Quick Reference
|
|
192
|
+
|
|
193
|
+
Variables: \$name (always prefixed with \$)
|
|
194
|
+
Strings: "hello {\$var}" # interpolation with {}
|
|
195
|
+
"""...""" # multiline (also interpolates)
|
|
196
|
+
Numbers: 42, 3.14, -7
|
|
197
|
+
Booleans: true, false
|
|
198
|
+
Lists: [1, 2, 3]
|
|
199
|
+
[...\$list, 4] # spread: inline list elements
|
|
200
|
+
Dicts: [name: "alice", age: 30] # identifier keys
|
|
201
|
+
[1: "one", 2: "two"] # number keys (incl. negative: [-1: "neg"])
|
|
202
|
+
[true: "yes", false: "no"] # boolean keys
|
|
203
|
+
[["a", "b"]: 1] # multi-key: [a: 1, b: 1]
|
|
204
|
+
[\$keyVar: value] # variable key (must eval to string)
|
|
205
|
+
[(\$expr): value] # computed key (must eval to string)
|
|
206
|
+
Tuples: *[1, 2, 3] # for argument unpacking
|
|
207
|
+
Closures: |x|(\$x + 1) # like lambda/arrow functions
|
|
208
|
+
Type annot: "hi" => \$x:string # lock type on capture
|
|
209
|
+
Comments: # single line only
|
|
210
|
+
|
|
211
|
+
## Pipes and \$ Binding
|
|
212
|
+
|
|
213
|
+
\`\$\` is the current piped value. Its meaning depends on context:
|
|
214
|
+
|
|
215
|
+
| Context | \`\$\` contains |
|
|
216
|
+
|---|---|
|
|
217
|
+
| \`-> { body }\` | piped value |
|
|
218
|
+
| \`-> each { }\` | current item |
|
|
219
|
+
| \`(cond) @ { }\` | accumulated value |
|
|
220
|
+
| \`@ { } ? cond\` | accumulated value |
|
|
221
|
+
| \`cond ? { } ! { }\` | tested value |
|
|
222
|
+
| \`-> ? { } ! { }\` | piped value |
|
|
223
|
+
| \`\\|\\|{ \$.field }\` in dict | the containing dict |
|
|
224
|
+
| \`\\|x\\|{ }\` stored closure | N/A — use parameters |
|
|
225
|
+
|
|
226
|
+
Implied \`\$\`: bare \`.method()\` means \`\$ -> .method()\`.
|
|
227
|
+
Example: \`"hello" -> .upper\` is the same as \`"hello" -> \$.upper()\`.
|
|
228
|
+
|
|
229
|
+
## Control Flow
|
|
206
230
|
|
|
207
231
|
Conditional (if-else):
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
232
|
+
|
|
233
|
+
cond ? then_expr ! else_expr
|
|
234
|
+
cond ? then_expr # else returns ""
|
|
235
|
+
|
|
236
|
+
Piped conditional (\`\$\` becomes condition):
|
|
237
|
+
|
|
238
|
+
value -> ? then_expr ! else_expr
|
|
239
|
+
|
|
240
|
+
Multi-line conditionals (\`?\` and \`!\` work as line continuations):
|
|
241
|
+
|
|
242
|
+
condition
|
|
243
|
+
? "yes"
|
|
244
|
+
! "no"
|
|
245
|
+
value -> is_valid
|
|
246
|
+
? "ok"
|
|
247
|
+
! "error"
|
|
248
|
+
\$val -> .eq("A") ? "a"
|
|
249
|
+
! .eq("B") ? "b"
|
|
250
|
+
! "c"
|
|
251
|
+
|
|
252
|
+
Condition loop (NO \`while\` keyword — use \`@\` operator):
|
|
253
|
+
|
|
254
|
+
init_value -> (\$ < 10) @ { \$ + 1 } # \$ is accumulator
|
|
227
255
|
|
|
228
256
|
Do-condition loop (body runs at least once):
|
|
229
|
-
|
|
257
|
+
|
|
258
|
+
init_value -> @ { \$ + 1 } ? (\$ < 10)
|
|
230
259
|
|
|
231
260
|
Break (exits loop, returns collected results before break):
|
|
232
|
-
|
|
261
|
+
|
|
262
|
+
[1,2,3,4,5] -> each { (\$ == 3) ? break; \$ } # returns [1, 2]
|
|
233
263
|
|
|
234
264
|
Return (exits block or script with value):
|
|
235
|
-
|
|
236
|
-
|
|
265
|
+
|
|
266
|
+
{ 5 => \$x; (\$x > 3) ? ("big" -> return); "small" } # returns "big"
|
|
267
|
+
"done" -> return # exits script with "done"
|
|
237
268
|
|
|
238
269
|
Assert (validate condition, halt if false, pass through if true):
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
270
|
+
|
|
271
|
+
5 -> assert (\$ > 0) # returns 5
|
|
272
|
+
-1 -> assert (\$ > 0) # ERROR: Assertion failed
|
|
273
|
+
"" -> assert !.empty "Input required" # ERROR: Input required
|
|
274
|
+
\$val -> assert \$:?list "Expected list" # type validation
|
|
243
275
|
|
|
244
276
|
Error (halt execution immediately with message):
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
|
262
|
-
|
|
263
|
-
|
|
|
264
|
-
|
|
|
265
|
-
|
|
|
266
|
-
|
|
267
|
-
\$@
|
|
277
|
+
|
|
278
|
+
error "Something went wrong" # halt with message
|
|
279
|
+
"Operation failed" -> error # piped form (must be string)
|
|
280
|
+
error "Status: {\$code}" # interpolation works
|
|
281
|
+
|
|
282
|
+
Pass (returns \`\$\` unchanged, explicit no-op):
|
|
283
|
+
|
|
284
|
+
cond ? pass ! "fallback" # preserve \$ when condition true
|
|
285
|
+
cond ? "value" ! pass # preserve \$ when condition false
|
|
286
|
+
"data" -> { [status: pass] } # include \$ in dict: [status: "data"]
|
|
287
|
+
[1, -2, 3] -> map { (\$ > 0) ? pass ! 0 } # [1, 0, 3]
|
|
288
|
+
|
|
289
|
+
Note: \`pass\` requires pipe context. Using \`pass\` without \`\$\` throws error.
|
|
290
|
+
|
|
291
|
+
## Collection Operators
|
|
292
|
+
|
|
293
|
+
| Operator | Execution | Returns | Break? |
|
|
294
|
+
|---|---|---|---|
|
|
295
|
+
| \`-> each { }\` | sequential | all body results | yes |
|
|
296
|
+
| \`-> each(i) { \$@ + \$ }\` | sequential | all with accumulator | yes |
|
|
297
|
+
| \`-> map { }\` | parallel | all body results | NO |
|
|
298
|
+
| \`-> filter { }\` | parallel | matching elements | NO |
|
|
299
|
+
| \`-> fold(i) { \$@ + \$ }\` | sequential | final result only | yes |
|
|
300
|
+
|
|
301
|
+
\`\$@\` is the accumulator in \`each(init)\` and \`fold(init)\`.
|
|
268
302
|
|
|
269
303
|
Method shorthand in collection operators:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
304
|
+
|
|
305
|
+
["a", "b"] -> map .upper # ["A", "B"]
|
|
306
|
+
["", "x"] -> filter (!.empty) # ["x"]
|
|
307
|
+
["a", "b"] -> map .pad_start(3, "0") # ["00a", "00b"] (with args)
|
|
308
|
+
[" HI "] -> map .trim.lower # ["hi"] (chained methods)
|
|
274
309
|
|
|
275
310
|
Body forms (all operators accept these):
|
|
276
|
-
-> each { \$ * 2 } # block (\$ is current element)
|
|
277
|
-
-> each (\$ + 10) # grouped expression
|
|
278
|
-
-> each |x| (\$x * 2) # inline closure
|
|
279
|
-
-> each \$double # variable closure
|
|
280
|
-
-> each .upper # method shorthand
|
|
281
|
-
-> each log # host function
|
|
282
311
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
312
|
+
-> each { \$ * 2 } # block (\$ is current element)
|
|
313
|
+
-> each (\$ + 10) # grouped expression
|
|
314
|
+
-> each |x| (\$x * 2) # inline closure
|
|
315
|
+
-> each \$double # variable closure
|
|
316
|
+
-> each .upper # method shorthand
|
|
317
|
+
-> each log # host function
|
|
318
|
+
|
|
319
|
+
Dict iteration (\`\$\` contains \`key\` and \`value\` fields):
|
|
320
|
+
|
|
321
|
+
[a: 1, b: 2] -> each { "{\$.key}={\$.value}" } # ["a=1", "b=2"]
|
|
322
|
+
[a: 1, b: 5] -> filter { \$.value > 2 } # entries where value > 2
|
|
286
323
|
|
|
287
324
|
String iteration (iterates over characters):
|
|
288
|
-
"abc" -> each { "{\$}!" } # ["a!", "b!", "c!"]
|
|
289
|
-
"hello" -> filter { \$ != "l" } # ["h", "e", "o"]
|
|
290
325
|
|
|
291
|
-
|
|
292
|
-
|
|
326
|
+
"abc" -> each { "{\$}!" } # ["a!", "b!", "c!"]
|
|
327
|
+
"hello" -> filter { \$ != "l" } # ["h", "e", "o"]
|
|
293
328
|
|
|
294
|
-
|
|
329
|
+
## Closures
|
|
295
330
|
|
|
296
331
|
Two ways to create closures:
|
|
297
332
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
{ body } => \$fn # store closure for later use
|
|
320
|
-
( expr ) => \$x # store result value immediately
|
|
321
|
-
|
|
322
|
-
PIPE TARGET: { } creates closure then immediately invokes it:
|
|
323
|
-
5 -> { \$ + 1 } # 6 (create closure, invoke with 5)
|
|
324
|
-
5 -> (\$ + 1) # 6 (evaluate expression with \$=5)
|
|
325
|
-
Same observable result, different mechanism. Error messages differ.
|
|
326
|
-
|
|
327
|
-
Block-closure invocation:
|
|
328
|
-
{ \$ + 1 } => \$inc
|
|
329
|
-
\$inc(5) # direct call: 6
|
|
330
|
-
5 -> \$inc # pipe call: 6
|
|
331
|
-
[1,2,3] -> map \$inc # in collection op
|
|
333
|
+
**Block-closures:** \`{ body }\` in expression position
|
|
334
|
+
|
|
335
|
+
{ \$ + 1 } => \$inc # implicit \$ parameter
|
|
336
|
+
\$inc(5) # 6
|
|
337
|
+
5 -> \$inc # 6 (pipe invocation)
|
|
338
|
+
[x: { \$ * 2 }] # dict value is closure
|
|
339
|
+
type({ "hi" }) # "closure"
|
|
340
|
+
|
|
341
|
+
**Explicit closures:** \`|params| body\`
|
|
342
|
+
|
|
343
|
+
|x|(\$x + 1) => \$inc # named parameter
|
|
344
|
+
|a, b|(\$a + \$b) => \$add # multiple params
|
|
345
|
+
|x = 0|(\$x + 1) => \$inc_or_one # default value
|
|
346
|
+
|x: number|(\$x + 1) => \$typed # type annotation
|
|
347
|
+
|
|
348
|
+
\`{ body }\` vs \`( expr )\` distinction:
|
|
349
|
+
|
|
350
|
+
| Syntax | Semantics | Example |
|
|
351
|
+
|---|---|---|
|
|
352
|
+
| \`{ body }\` | Deferred (closure) | \`{ \$ + 1 } => \$fn\` |
|
|
353
|
+
| \`( expr )\` | Eager (immediate eval) | \`( 5 + 1 ) => \$x\` gives 6 |
|
|
332
354
|
|
|
333
355
|
LATE BINDING: closures capture scope, not values. Variables resolve at call time.
|
|
334
356
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
357
|
+
\`\$\` vs named params:
|
|
358
|
+
- Use \`\$\` in inline pipes and loops: \`"hello" -> { .upper }\`
|
|
359
|
+
- Use named params in stored closures: \`|x| (\$x * 2) => \$double\`
|
|
360
|
+
- \`\$\` is undefined when a stored closure is called later — always use params.
|
|
339
361
|
|
|
340
362
|
Zero-param dict closures (methods):
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
\$data.field # dict field
|
|
348
|
-
\$data[0], \$data[-1] # list index (negative from end)
|
|
349
|
-
\$data.\$key # variable as key
|
|
350
|
-
\$data.(\$i + 1) # computed key
|
|
351
|
-
\$data.(a || b) # try keys left-to-right
|
|
352
|
-
\$data.field ?? "default" # default if missing
|
|
353
|
-
\$data.?field # existence check (boolean)
|
|
354
|
-
\$data.?\$keyVar # variable existence check
|
|
355
|
-
\$data.?(\$expr) # computed existence check
|
|
356
|
-
\$data.?field&string # existence AND type check
|
|
357
|
-
\$data.?\$key&number # variable existence + type check
|
|
358
|
-
\$data.?(\$a -> "{\$}_b")&list # computed existence + type check
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
\$method -> [["GET", "HEAD"]: "safe", ["POST", "PUT"]: "unsafe"] # multi-key dispatch
|
|
363
|
+
|
|
364
|
+
[count: 3, double: ||{ \$.count * 2 }] => \$obj
|
|
365
|
+
\$obj.double # 6 (\$ is bound to dict)
|
|
366
|
+
|
|
367
|
+
## Property Access
|
|
368
|
+
|
|
369
|
+
\$data.field # dict field
|
|
370
|
+
\$data[0], \$data[-1] # list index (negative from end)
|
|
371
|
+
\$data.\$key # variable as key
|
|
372
|
+
\$data.(\$i + 1) # computed key
|
|
373
|
+
\$data.(a || b) # try keys left-to-right
|
|
374
|
+
\$data.field ?? "default" # default if missing
|
|
375
|
+
\$data.?field # existence check (boolean)
|
|
376
|
+
\$data.?\$keyVar # variable existence check
|
|
377
|
+
\$data.?(\$expr) # computed existence check
|
|
378
|
+
\$data.?field&string # existence AND type check
|
|
379
|
+
\$data.?\$key&number # variable existence + type check
|
|
380
|
+
\$data.?(\$a -> "{\$}_b")&list # computed existence + type check
|
|
381
|
+
|
|
382
|
+
## Dispatch Operators
|
|
383
|
+
|
|
384
|
+
**Dict dispatch** (single key) — pipe a value to a dict to match keys:
|
|
385
|
+
|
|
386
|
+
\$val -> [apple: "fruit", carrot: "veg"] # "fruit" if \$val is "apple"
|
|
387
|
+
\$val -> [apple: "fruit"] ?? "not found" # default if no match
|
|
388
|
+
\$method -> [["GET", "HEAD"]: "safe", ["POST", "PUT"]: "unsafe"] # multi-key
|
|
368
389
|
|
|
369
390
|
Type-aware matching (keys matched by value AND type):
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
Types: string
|
|
395
|
-
|
|
396
|
-
Comparison methods
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
1.
|
|
404
|
-
2.
|
|
405
|
-
3.
|
|
406
|
-
4.
|
|
407
|
-
5.
|
|
408
|
-
6.
|
|
409
|
-
7.
|
|
410
|
-
8.
|
|
411
|
-
9.
|
|
412
|
-
10. Pipe:
|
|
413
|
-
11. Capture:
|
|
414
|
-
|
|
415
|
-
Use parentheses to override: (2 + 3) * 4
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
Slice (
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
Inline list elements into a new list using
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
TUPLES FOR ARGUMENT UNPACKING
|
|
449
|
-
-----------------------------
|
|
450
|
-
|
|
451
|
-
*[1, 2, 3] -> \$fn() # positional: \$fn(1, 2, 3)
|
|
452
|
-
*[b: 2, a: 1] -> \$fn() # named: \$fn(a=1, b=2)
|
|
453
|
-
*[...\$list, 3] -> \$fn() # spread in tuple: combines elements
|
|
454
|
-
|
|
455
|
-
CLOSURE CHAIN (@)
|
|
456
|
-
-----------------
|
|
391
|
+
|
|
392
|
+
1 -> [1: "number", "1": "string"] # "number"
|
|
393
|
+
"1" -> [1: "number", "1": "string"] # "string"
|
|
394
|
+
true -> [true: "bool", "true": "str"] # "bool"
|
|
395
|
+
|
|
396
|
+
**List dispatch** (index) — pipe a number to a list:
|
|
397
|
+
|
|
398
|
+
0 -> ["first", "second"] # "first"
|
|
399
|
+
-1 -> ["first", "second"] # "second" (last)
|
|
400
|
+
5 -> ["a", "b"] ?? "not found" # default if out of bounds
|
|
401
|
+
|
|
402
|
+
**Hierarchical dispatch** (path navigation) — pipe a list of keys/indexes:
|
|
403
|
+
|
|
404
|
+
["name", "first"] -> [name: [first: "Alice"]] # "Alice"
|
|
405
|
+
[0, 1] -> [[1, 2, 3], [4, 5, 6]] # 2
|
|
406
|
+
["users", 0, "name"] -> [users: [[name: "Alice"]]] # "Alice"
|
|
407
|
+
[] -> [a: 1] # [a: 1] (empty path = unchanged)
|
|
408
|
+
["a", "missing"] -> [a: [x: 1]] ?? "default" # "default"
|
|
409
|
+
|
|
410
|
+
## Type Operations
|
|
411
|
+
|
|
412
|
+
\`:type\` — assert type (error if wrong): \`42:number\` passes; \`"x":number\` errors.
|
|
413
|
+
\`:?type\` — check type (boolean): \`42:?number\` is true; \`"x":?number\` is false.
|
|
414
|
+
|
|
415
|
+
Types: \`string\`, \`number\`, \`boolean\`, \`list\`, \`dict\`, \`tuple\`, \`closure\`.
|
|
416
|
+
|
|
417
|
+
Comparison methods:
|
|
418
|
+
|
|
419
|
+
.eq(val) == .ne(val) != .lt(val) < .gt(val) > .le(val) <= .ge(val) >=
|
|
420
|
+
Example: \$age -> .ge(18) ? "adult" ! "minor"
|
|
421
|
+
|
|
422
|
+
## Operator Precedence (Highest to Lowest)
|
|
423
|
+
|
|
424
|
+
1. Member access: \`.field\`, \`[index]\`
|
|
425
|
+
2. Type operators: \`:type\`, \`:?type\`
|
|
426
|
+
3. Unary: \`-\`, \`!\`
|
|
427
|
+
4. Multiplicative: \`*\`, \`/\`, \`%\`
|
|
428
|
+
5. Additive: \`+\`, \`-\`
|
|
429
|
+
6. Comparison: \`==\`, \`!=\`, \`<\`, \`>\`, \`<=\`, \`>=\`
|
|
430
|
+
7. Logical AND: \`&&\`
|
|
431
|
+
8. Logical OR: \`||\`
|
|
432
|
+
9. Default: \`??\`
|
|
433
|
+
10. Pipe: \`->\`
|
|
434
|
+
11. Capture: \`=>\`
|
|
435
|
+
|
|
436
|
+
Use parentheses to override: \`(2 + 3) * 4\`
|
|
437
|
+
|
|
438
|
+
## Extraction Operators
|
|
439
|
+
|
|
440
|
+
Destructure (\`*<>\`):
|
|
441
|
+
|
|
442
|
+
[1, 2, 3] -> *<\$a, \$b, \$c> # \$a=1, \$b=2, \$c=3
|
|
443
|
+
[x: 1, y: 2] -> *<x: \$a, y: \$b> # \$a=1, \$b=2
|
|
444
|
+
[1, 2, 3] -> *<\$first, _, \$third> # _ skips element
|
|
445
|
+
|
|
446
|
+
Slice (\`/<start:stop:step>\`):
|
|
447
|
+
|
|
448
|
+
[0,1,2,3,4] -> /<1:3> # [1, 2]
|
|
449
|
+
[0,1,2,3,4] -> /<-2:> # [3, 4]
|
|
450
|
+
[0,1,2,3,4] -> /<::-1> # [4,3,2,1,0] (reverse)
|
|
451
|
+
"hello" -> /<1:4> # "ell"
|
|
452
|
+
|
|
453
|
+
## List Spread in Literals
|
|
454
|
+
|
|
455
|
+
Inline list elements into a new list using \`...\` (spread operator):
|
|
456
|
+
|
|
457
|
+
[1, 2] => \$a
|
|
458
|
+
[...\$a, 3] # [1, 2, 3]
|
|
459
|
+
[...\$a, ...\$b] # concatenate lists
|
|
460
|
+
[...(\$nums -> map {\$ * 2})] # spread expression result
|
|
461
|
+
|
|
462
|
+
## Tuples for Argument Unpacking
|
|
463
|
+
|
|
464
|
+
*[1, 2, 3] -> \$fn() # positional: \$fn(1, 2, 3)
|
|
465
|
+
*[b: 2, a: 1] -> \$fn() # named: \$fn(a=1, b=2)
|
|
466
|
+
*[...\$list, 3] -> \$fn() # spread in tuple: combines elements
|
|
467
|
+
|
|
468
|
+
## Closure Chain (@)
|
|
457
469
|
|
|
458
470
|
Chains closures sequentially (each receives previous result):
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
471
|
+
|
|
472
|
+
5 -> @[\$inc, \$double, \$add10] # (5+1)*2+10 = 22
|
|
473
|
+
|
|
474
|
+
## String Methods
|
|
475
|
+
|
|
476
|
+
| Method | Description |
|
|
477
|
+
|---|---|
|
|
478
|
+
| \`.len\` | length |
|
|
479
|
+
| \`.empty\` | is empty string |
|
|
480
|
+
| \`.trim\` | remove whitespace |
|
|
481
|
+
| \`.upper\` | uppercase |
|
|
482
|
+
| \`.lower\` | lowercase |
|
|
483
|
+
| \`.str\` | convert to string |
|
|
484
|
+
| \`.num\` | parse to number |
|
|
485
|
+
| \`.head\` | first character |
|
|
486
|
+
| \`.tail\` | last character |
|
|
487
|
+
| \`.at(i)\` | character at index |
|
|
488
|
+
| \`.split(sep)\` | split into list (default: newline) |
|
|
489
|
+
| \`.lines\` | split on newlines |
|
|
490
|
+
| \`.join(sep)\` | join list with separator |
|
|
491
|
+
| \`.contains(s)\` | substring check |
|
|
492
|
+
| \`.starts_with(s)\` | prefix check |
|
|
493
|
+
| \`.ends_with(s)\` | suffix check |
|
|
494
|
+
| \`.index_of(s)\` | first match position (-1 if none) |
|
|
495
|
+
| \`.replace(p, r)\` | replace first regex match |
|
|
496
|
+
| \`.replace_all(p, r)\` | replace all regex matches |
|
|
497
|
+
| \`.match(regex)\` | first match info (dict with matched, index, groups) |
|
|
498
|
+
| \`.is_match(regex)\` | boolean regex check |
|
|
499
|
+
| \`.repeat(n)\` | repeat n times |
|
|
500
|
+
| \`.pad_start(n, f)\` | pad start |
|
|
501
|
+
| \`.pad_end(n, f)\` | pad end |
|
|
502
|
+
|
|
503
|
+
## List/Dict Methods
|
|
504
|
+
|
|
505
|
+
| Method | Description |
|
|
506
|
+
|---|---|
|
|
507
|
+
| \`.len\` | length |
|
|
508
|
+
| \`.empty\` | is empty |
|
|
509
|
+
| \`.head\` | first element |
|
|
510
|
+
| \`.tail\` | last element |
|
|
511
|
+
| \`.at(i)\` | element at index |
|
|
512
|
+
| \`.keys\` | dict keys as list |
|
|
513
|
+
| \`.values\` | dict values as list |
|
|
514
|
+
| \`.entries\` | dict as list of [k, v] tuples |
|
|
515
|
+
| \`.has(val)\` | list contains value (deep equality) |
|
|
516
|
+
| \`.has_any(list)\` | list contains any value from candidates |
|
|
517
|
+
| \`.has_all(list)\` | list contains all values from candidates |
|
|
518
|
+
|
|
519
|
+
## Global Functions
|
|
520
|
+
|
|
521
|
+
| Function | Description |
|
|
522
|
+
|---|---|
|
|
523
|
+
| \`type(val)\` | returns type name |
|
|
524
|
+
| \`log(val)\` | print and pass through |
|
|
525
|
+
| \`json(val)\` | convert to JSON string |
|
|
526
|
+
| \`identity(val)\` | returns input unchanged |
|
|
527
|
+
| \`range(start, end, step?)\` | number sequence (iterator) |
|
|
528
|
+
| \`repeat(val, count)\` | repeat value n times (iterator) |
|
|
529
|
+
| \`enumerate(coll)\` | lists: [index, value]; dicts: [index, key, value] |
|
|
530
|
+
|
|
531
|
+
## Iterators
|
|
505
532
|
|
|
506
533
|
Lazy sequence generation. Collection operators auto-expand iterators.
|
|
507
534
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
535
|
+
range(0, 5) -> each { \$ * 2 } # [0, 2, 4, 6, 8]
|
|
536
|
+
repeat("x", 3) -> each { \$ } # ["x", "x", "x"]
|
|
537
|
+
|
|
538
|
+
\`.first()\` method (returns iterator for any collection):
|
|
539
|
+
|
|
540
|
+
[1, 2, 3] -> .first() # iterator at 1
|
|
541
|
+
"abc" -> .first() # iterator at "a"
|
|
511
542
|
|
|
512
|
-
|
|
513
|
-
[1, 2, 3] -> .first() # iterator at 1
|
|
514
|
-
"abc" -> .first() # iterator at "a"
|
|
543
|
+
Iterator protocol (dict with \`value\`, \`done\`, \`next\`):
|
|
515
544
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
\$it.next() # returns new iterator at next position
|
|
545
|
+
\$it.done # bool: is exhausted?
|
|
546
|
+
\$it.value # current element
|
|
547
|
+
\$it.next() # returns new iterator at next position
|
|
520
548
|
|
|
521
|
-
|
|
522
|
-
----------------
|
|
549
|
+
## Iteration Limits
|
|
523
550
|
|
|
524
551
|
Default: 10,000 iterations max for loops.
|
|
525
|
-
Override:
|
|
552
|
+
Override: \`^(limit: N)\` statement.
|
|
526
553
|
|
|
527
|
-
|
|
528
|
-
|
|
554
|
+
^(limit: 100) 0 -> (\$ < 50) @ { \$ + 1 }
|
|
555
|
+
^(limit: 3) \$items -> map { slow_process(\$) } # concurrency limit
|
|
529
556
|
|
|
530
|
-
|
|
531
|
-
--------------------
|
|
557
|
+
## Script Return Values
|
|
532
558
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
559
|
+
| Return value | Exit code |
|
|
560
|
+
|---|---|
|
|
561
|
+
| \`true\` / non-empty string | 0 |
|
|
562
|
+
| \`false\` / empty string | 1 |
|
|
563
|
+
| \`[0, "message"]\` | 0 with message |
|
|
564
|
+
| \`[1, "message"]\` | 1 with message |
|
|
537
565
|
`;
|
|
538
566
|
//# sourceMappingURL=introspection-data.js.map
|