rip-lang 1.0.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/.cursor/rules/rip-agent-onboarding.md +681 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +98 -0
- package/.github/ISSUE_TEMPLATE/coffeescript_compatibility.yml +86 -0
- package/.github/ISSUE_TEMPLATE/config.yml +9 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +82 -0
- package/.github/ISSUE_TEMPLATE/question.yml +55 -0
- package/.github/pull_request_template.md +84 -0
- package/AGENT.md +623 -0
- package/CONTRIBUTING.md +331 -0
- package/LICENSE +21 -0
- package/README.md +1245 -0
- package/SETUP.md +144 -0
- package/bar.coffee +394 -0
- package/bin/rip +162 -0
- package/bunfig.toml +11 -0
- package/docs/BROWSER.md +983 -0
- package/docs/CODEGEN.md +1023 -0
- package/docs/COFFEESCRIPT-COMPARISON.md +740 -0
- package/docs/COMPREHENSIONS.md +572 -0
- package/docs/REGEX-PLUS.md +441 -0
- package/docs/SOLAR.md +846 -0
- package/docs/SPECIAL-OPERATORS.md +769 -0
- package/docs/STRING.md +363 -0
- package/docs/WHY-NOT-COFFEESCRIPT.md +184 -0
- package/docs/WHY-YES-RIP.md +690 -0
- package/docs/WORKFLOW.md +306 -0
- package/docs/dist/rip.browser.js +6798 -0
- package/docs/dist/rip.browser.min.js +242 -0
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/docs/example.html +177 -0
- package/docs/examples/README.md +154 -0
- package/docs/examples/arrows.rip +84 -0
- package/docs/examples/async-await.rip +59 -0
- package/docs/examples/existential.rip +86 -0
- package/docs/examples/fibonacci.rip +12 -0
- package/docs/examples/module.rip +38 -0
- package/docs/examples/object-syntax.rip +74 -0
- package/docs/examples/prototype.rip +30 -0
- package/docs/examples/ranges.rip +45 -0
- package/docs/examples/switch.rip +50 -0
- package/docs/examples/ternary.rip +36 -0
- package/docs/examples/use-loader.js +9 -0
- package/docs/examples/utils.rip +20 -0
- package/docs/index.html +65 -0
- package/docs/repl.html +914 -0
- package/docs/rip-1280w.png +0 -0
- package/docs/rip.svg +4 -0
- package/package.json +52 -0
- package/rip-loader.ts +27 -0
- package/scripts/build-browser.js +76 -0
- package/scripts/serve.js +71 -0
- package/src/browser.js +97 -0
- package/src/codegen.js +4808 -0
- package/src/compiler.js +270 -0
- package/src/grammar/grammar.rip +801 -0
- package/src/grammar/solar.rip +1056 -0
- package/src/lexer.js +3145 -0
- package/src/parser.js +352 -0
- package/src/repl.js +423 -0
- package/test/rip/assignment.rip +115 -0
- package/test/rip/async.rip +361 -0
- package/test/rip/basic.rip +171 -0
- package/test/rip/classes.rip +167 -0
- package/test/rip/compatibility.rip +338 -0
- package/test/rip/comprehensions.rip +104 -0
- package/test/rip/control.rip +177 -0
- package/test/rip/data.rip +215 -0
- package/test/rip/errors.rip +129 -0
- package/test/rip/functions.rip +443 -0
- package/test/rip/guards.rip +247 -0
- package/test/rip/literals.rip +131 -0
- package/test/rip/loops.rip +117 -0
- package/test/rip/modules.rip +87 -0
- package/test/rip/operators.rip +158 -0
- package/test/rip/optional.rip +184 -0
- package/test/rip/properties.rip +94 -0
- package/test/rip/regex.rip +301 -0
- package/test/rip/stabilization.rip +825 -0
- package/test/rip/strings.rip +483 -0
- package/test/runner.js +329 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
# Test: Function Definitions (1 node type)
|
|
2
|
+
# Tests "def" node type
|
|
3
|
+
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# Function Definitions: "def"
|
|
6
|
+
# ============================================================================
|
|
7
|
+
|
|
8
|
+
# Simple function
|
|
9
|
+
test "simple function", "def add(a, b)\n a + b\nadd(2, 3)", 5
|
|
10
|
+
test "function with no params", "def greet\n 'hello'\ngreet()", "hello"
|
|
11
|
+
|
|
12
|
+
# Function with body
|
|
13
|
+
test "function with multiple statements", "def fn\n x = 5\n y = 10\n x + y\nfn()", 15
|
|
14
|
+
|
|
15
|
+
# Code generation
|
|
16
|
+
code "simple def", "def add(a, b)\n a + b", "function add(a, b) { return (a + b); }"
|
|
17
|
+
|
|
18
|
+
# Implicit return
|
|
19
|
+
test "implicit return", "def getValue\n 42\ngetValue()", 42
|
|
20
|
+
test "implicit return last statement", "def fn\n x = 1\n x + 1\nfn()", 2
|
|
21
|
+
|
|
22
|
+
# Function calling other functions
|
|
23
|
+
test "function calling function", "def double(x)\n x * 2\ndef quad(x)\n double(double(x))\nquad(3)", 12
|
|
24
|
+
|
|
25
|
+
# Recursive functions
|
|
26
|
+
test "recursive factorial", "def factorial(n)\n if n <= 1\n 1\n else\n n * factorial(n - 1)\nfactorial(5)", 120
|
|
27
|
+
|
|
28
|
+
# ============================================================================
|
|
29
|
+
# Async Functions (auto-detection)
|
|
30
|
+
# ============================================================================
|
|
31
|
+
|
|
32
|
+
test "async function", "def fetchData\n await Promise.resolve(42)\nfetchData()", 42
|
|
33
|
+
|
|
34
|
+
# ============================================================================
|
|
35
|
+
# Stats for CODEGEN.md
|
|
36
|
+
# ============================================================================
|
|
37
|
+
# Function definitions implemented: 0/1 (0%)
|
|
38
|
+
# Tests passing: 0/10 (0%)
|
|
39
|
+
# Test: Arrow Functions (2 node types)
|
|
40
|
+
# Tests "->" (thin arrow) and "=>" (fat arrow) node types
|
|
41
|
+
|
|
42
|
+
# ============================================================================
|
|
43
|
+
# Thin Arrow: "->"
|
|
44
|
+
# ============================================================================
|
|
45
|
+
|
|
46
|
+
# Basic thin arrow
|
|
47
|
+
test "thin arrow simple", "add = (a, b) -> a + b\nadd(2, 3)", 5
|
|
48
|
+
test "thin arrow no params", "greet = -> 'hello'\ngreet()", "hello"
|
|
49
|
+
test "thin arrow one param", "double = (x) -> x * 2\ndouble(5)", 10
|
|
50
|
+
|
|
51
|
+
# Code generation
|
|
52
|
+
code "thin arrow", "(a, b) -> a + b", "function(a, b) { return (a + b); }"
|
|
53
|
+
|
|
54
|
+
# Thin arrow with block body
|
|
55
|
+
test "thin arrow block", "fn = ->\n x = 5\n x * 2\nfn()", 10
|
|
56
|
+
|
|
57
|
+
# Implicit return
|
|
58
|
+
test "thin arrow implicit return", "getValue = -> 42\ngetValue()", 42
|
|
59
|
+
|
|
60
|
+
# Thin arrow 'this' binding (call-site determined)
|
|
61
|
+
test "thin arrow this call-site", "obj = {x: 5, fn: -> this.x}\nobj.fn()", 5
|
|
62
|
+
|
|
63
|
+
# ============================================================================
|
|
64
|
+
# Fat Arrow: "=>"
|
|
65
|
+
# ============================================================================
|
|
66
|
+
|
|
67
|
+
# Basic fat arrow
|
|
68
|
+
test "fat arrow simple", "add = (a, b) => a + b\nadd(2, 3)", 5
|
|
69
|
+
test "fat arrow no params", "greet = => 'hello'\ngreet()", "hello"
|
|
70
|
+
test "fat arrow one param", "double = (x) => x * 2\ndouble(5)", 10
|
|
71
|
+
|
|
72
|
+
# Code generation
|
|
73
|
+
code "fat arrow", "(a, b) => a + b", "(a, b) => (a + b)"
|
|
74
|
+
|
|
75
|
+
# Fat arrow with block body
|
|
76
|
+
test "fat arrow block", "fn = =>\n x = 5\n x * 2\nfn()", 10
|
|
77
|
+
|
|
78
|
+
# Fat arrow 'this' binding (lexically bound to outer scope)
|
|
79
|
+
test "fat arrow this lexical", "obj = {x: 5, fn: => this?.x}\nobj.fn()", undefined
|
|
80
|
+
|
|
81
|
+
# ============================================================================
|
|
82
|
+
# Arrow Functions in Collections
|
|
83
|
+
# ============================================================================
|
|
84
|
+
|
|
85
|
+
# Arrow in array
|
|
86
|
+
test "arrow in array", "fns = [(x) -> x + 1, (x) -> x * 2]\nfns[0](5)", 6
|
|
87
|
+
|
|
88
|
+
# Arrow in object
|
|
89
|
+
test "arrow in object", "obj = {fn: (x) -> x * 2}\nobj.fn(5)", 10
|
|
90
|
+
|
|
91
|
+
# ============================================================================
|
|
92
|
+
# Stats for CODEGEN.md
|
|
93
|
+
# ============================================================================
|
|
94
|
+
# Arrow functions implemented: 0/2 (0%)
|
|
95
|
+
# Tests passing: 0/16 (0%)
|
|
96
|
+
# Test: Function Calls (1 node type)
|
|
97
|
+
# Tests function call pattern (array with non-string head)
|
|
98
|
+
|
|
99
|
+
# ============================================================================
|
|
100
|
+
# Function Calls
|
|
101
|
+
# ============================================================================
|
|
102
|
+
|
|
103
|
+
# Simple calls
|
|
104
|
+
test "call no args", "fn = -> 42\nfn()", 42
|
|
105
|
+
test "call with args", "add = (a, b) -> a + b\nadd(2, 3)", 5
|
|
106
|
+
test "call with multiple args", "sum = (a, b, c) -> a + b + c\nsum(1, 2, 3)", 6
|
|
107
|
+
|
|
108
|
+
# Code generation
|
|
109
|
+
code "simple call", "fn()", "fn()"
|
|
110
|
+
code "call with args", "fn(a, b)", "fn(a, b)"
|
|
111
|
+
|
|
112
|
+
# Nested calls
|
|
113
|
+
test "nested calls", "double = (x) -> x * 2\ntriple = (x) -> x * 3\ndouble(triple(2))", 12
|
|
114
|
+
|
|
115
|
+
# Calls with expressions
|
|
116
|
+
test "call with expression arg", "double = (x) -> x * 2\ndouble(2 + 3)", 10
|
|
117
|
+
|
|
118
|
+
# Method calls
|
|
119
|
+
test "method call", "obj = {fn: -> 42}\nobj.fn()", 42
|
|
120
|
+
|
|
121
|
+
# ============================================================================
|
|
122
|
+
# Spread in Calls: "..."
|
|
123
|
+
# ============================================================================
|
|
124
|
+
|
|
125
|
+
# Spread arguments
|
|
126
|
+
test "spread args", "add = (a, b, c) -> a + b + c\nargs = [1, 2, 3]\nadd(...args)", 6
|
|
127
|
+
test "spread with other args", "fn = (a, b, c) -> a + b + c\nfn(1, ...[2, 3])", 6
|
|
128
|
+
|
|
129
|
+
# ============================================================================
|
|
130
|
+
# Stats for CODEGEN.md
|
|
131
|
+
# ============================================================================
|
|
132
|
+
# Function calls implemented: 0/1 (0%)
|
|
133
|
+
# Tests passing: 0/10 (0%)
|
|
134
|
+
# Test: Function Parameters (3 node types)
|
|
135
|
+
# Tests "rest", "...", and "default" node types
|
|
136
|
+
|
|
137
|
+
# ============================================================================
|
|
138
|
+
# Rest Parameters: "rest"
|
|
139
|
+
# ============================================================================
|
|
140
|
+
|
|
141
|
+
# Basic rest parameters
|
|
142
|
+
test "rest params", "fn = (first, ...rest) -> rest.length\nfn(1, 2, 3, 4)", 3
|
|
143
|
+
test "rest params values", "fn = (first, ...rest) -> rest[0]\nfn(1, 2, 3)", 2
|
|
144
|
+
test "rest params empty", "fn = (...rest) -> rest.length\nfn()", 0
|
|
145
|
+
|
|
146
|
+
# Code generation
|
|
147
|
+
code "rest params", "(first, ...rest) -> rest", "function(first, ...rest) { return rest; }"
|
|
148
|
+
|
|
149
|
+
# Rest with no other params
|
|
150
|
+
test "rest only", "fn = (...all) -> all.length\nfn(1, 2, 3)", 3
|
|
151
|
+
|
|
152
|
+
# Rest in middle position (CoffeeScript expansion marker)
|
|
153
|
+
test "rest in middle", '''
|
|
154
|
+
fn = (first, middle..., last) ->
|
|
155
|
+
[first, middle.length, last]
|
|
156
|
+
fn(1, 2, 3, 4, 5)
|
|
157
|
+
''', [1, 3, 5]
|
|
158
|
+
|
|
159
|
+
test "rest in middle with two after", '''
|
|
160
|
+
fn = (a, mid..., b, c) ->
|
|
161
|
+
[a, mid, b, c]
|
|
162
|
+
fn(1, 2, 3, 4, 5)
|
|
163
|
+
''', [1, [2, 3], 4, 5]
|
|
164
|
+
|
|
165
|
+
# ============================================================================
|
|
166
|
+
# Default Parameters: "default"
|
|
167
|
+
# ============================================================================
|
|
168
|
+
|
|
169
|
+
# Basic default parameters
|
|
170
|
+
test "default param used", "fn = (x = 10) -> x\nfn()", 10
|
|
171
|
+
test "default param override", "fn = (x = 10) -> x\nfn(20)", 20
|
|
172
|
+
test "default param expression", "fn = (x = 5 + 5) -> x\nfn()", 10
|
|
173
|
+
|
|
174
|
+
# Code generation
|
|
175
|
+
code "default param", "(x = 10) -> x", "function(x = 10) { return x; }"
|
|
176
|
+
|
|
177
|
+
# Multiple default params
|
|
178
|
+
test "multiple defaults", "fn = (a = 1, b = 2) -> a + b\nfn()", 3
|
|
179
|
+
test "partial defaults", "fn = (a = 1, b = 2) -> a + b\nfn(5)", 7
|
|
180
|
+
|
|
181
|
+
# ============================================================================
|
|
182
|
+
# Expansion: "expansion"
|
|
183
|
+
# ============================================================================
|
|
184
|
+
|
|
185
|
+
# Expansion marker: (a, ..., b)
|
|
186
|
+
test "expansion marker", "fn = (a, ..., b) -> a + b\nfn(1, 2, 3, 4)", 5
|
|
187
|
+
|
|
188
|
+
# ============================================================================
|
|
189
|
+
# Stats for CODEGEN.md
|
|
190
|
+
# ============================================================================
|
|
191
|
+
# Parameter types implemented: 0/3 (0%)
|
|
192
|
+
# Tests passing: 0/15 (0%)
|
|
193
|
+
# Test: Return Statements (1 node type)
|
|
194
|
+
# Tests "return" node type
|
|
195
|
+
|
|
196
|
+
# ============================================================================
|
|
197
|
+
# Return Statements: "return"
|
|
198
|
+
# ============================================================================
|
|
199
|
+
|
|
200
|
+
# Explicit return
|
|
201
|
+
test "explicit return", "fn = -> return 42\nfn()", 42
|
|
202
|
+
test "early return", "fn = (x) ->\n return 1 if x < 0\n return 2\nfn(-5)", 1
|
|
203
|
+
test "return expression", "fn = -> return 5 + 10\nfn()", 15
|
|
204
|
+
|
|
205
|
+
# Code generation
|
|
206
|
+
code "simple return", "return 42", "return 42"
|
|
207
|
+
code "return expression", "return a + b", "return (a + b)"
|
|
208
|
+
|
|
209
|
+
# Return in different contexts
|
|
210
|
+
test "return in if", "fn = (x) ->\n if x > 0\n return 'positive'\n 'negative'\nfn(5)", "positive"
|
|
211
|
+
|
|
212
|
+
# Multiple returns
|
|
213
|
+
test "multiple returns", "fn = (x) ->\n return 1 if x == 1\n return 2 if x == 2\n return 3\nfn(2)", 2
|
|
214
|
+
|
|
215
|
+
# Return vs implicit return
|
|
216
|
+
test "explicit vs implicit", "fn = (x) ->\n if x > 0\n return x\n 0\nfn(5)", 5
|
|
217
|
+
|
|
218
|
+
# ============================================================================
|
|
219
|
+
# IIFE (Immediately Invoked Function Expression)
|
|
220
|
+
# ============================================================================
|
|
221
|
+
|
|
222
|
+
test "IIFE simple", "(-> 42)()", 42
|
|
223
|
+
test "IIFE with params", "((x) -> x * 2)(5)", 10
|
|
224
|
+
test "IIFE with block", "(-> \n x = 5\n x * 2)()", 10
|
|
225
|
+
|
|
226
|
+
# ============================================================================
|
|
227
|
+
# Closures
|
|
228
|
+
# ============================================================================
|
|
229
|
+
|
|
230
|
+
test "closure captures variable", '''
|
|
231
|
+
makeCounter = ->
|
|
232
|
+
count = 0
|
|
233
|
+
-> count++
|
|
234
|
+
counter = makeCounter()
|
|
235
|
+
counter()
|
|
236
|
+
counter()
|
|
237
|
+
counter()
|
|
238
|
+
''', 2
|
|
239
|
+
|
|
240
|
+
test "closure multiple instances", '''
|
|
241
|
+
makeAdder = (n) ->
|
|
242
|
+
(x) -> x + n
|
|
243
|
+
add5 = makeAdder(5)
|
|
244
|
+
add10 = makeAdder(10)
|
|
245
|
+
add5(3) + add10(3)
|
|
246
|
+
''', 21
|
|
247
|
+
|
|
248
|
+
# ============================================================================
|
|
249
|
+
# Higher-Order Functions
|
|
250
|
+
# ============================================================================
|
|
251
|
+
|
|
252
|
+
test "function returns function", '''
|
|
253
|
+
outer = (x) ->
|
|
254
|
+
(y) -> x + y
|
|
255
|
+
add5 = outer(5)
|
|
256
|
+
add5(3)
|
|
257
|
+
''', 8
|
|
258
|
+
|
|
259
|
+
test "function takes function", '''
|
|
260
|
+
apply = (fn, x) -> fn(x)
|
|
261
|
+
double = (x) -> x * 2
|
|
262
|
+
apply(double, 5)
|
|
263
|
+
''', 10
|
|
264
|
+
|
|
265
|
+
# ============================================================================
|
|
266
|
+
# Void Functions (! at definition - side-effect only)
|
|
267
|
+
# ============================================================================
|
|
268
|
+
|
|
269
|
+
test "void function no implicit return", '''
|
|
270
|
+
def process!
|
|
271
|
+
x = 42
|
|
272
|
+
x * 2
|
|
273
|
+
result = process()
|
|
274
|
+
result
|
|
275
|
+
''', undefined
|
|
276
|
+
|
|
277
|
+
test "void function with params", '''
|
|
278
|
+
def update!(arr, val)
|
|
279
|
+
arr.push val
|
|
280
|
+
val * 2
|
|
281
|
+
arr = []
|
|
282
|
+
update(arr, 5)
|
|
283
|
+
arr
|
|
284
|
+
''', [5]
|
|
285
|
+
|
|
286
|
+
test "void function with early return", '''
|
|
287
|
+
def validate!(x)
|
|
288
|
+
return if x < 0
|
|
289
|
+
console.log "valid"
|
|
290
|
+
x * 2
|
|
291
|
+
[validate(5), validate(-1)]
|
|
292
|
+
''', [undefined, undefined]
|
|
293
|
+
|
|
294
|
+
test "void function return strips value", '''
|
|
295
|
+
def compute!(x)
|
|
296
|
+
return x * 10
|
|
297
|
+
result = compute(5)
|
|
298
|
+
result
|
|
299
|
+
''', undefined
|
|
300
|
+
|
|
301
|
+
test "normal function for comparison", '''
|
|
302
|
+
def compute(x)
|
|
303
|
+
return x * 10
|
|
304
|
+
result = compute(5)
|
|
305
|
+
result
|
|
306
|
+
''', 50
|
|
307
|
+
|
|
308
|
+
test "void function in loop", '''
|
|
309
|
+
results = []
|
|
310
|
+
def append!(val)
|
|
311
|
+
results.push val
|
|
312
|
+
for x in [1, 2, 3]
|
|
313
|
+
append(x)
|
|
314
|
+
results
|
|
315
|
+
''', [1, 2, 3]
|
|
316
|
+
|
|
317
|
+
test "void function with comprehension", '''
|
|
318
|
+
def process!
|
|
319
|
+
for x in [1, 2, 3]
|
|
320
|
+
console.log x
|
|
321
|
+
result = process()
|
|
322
|
+
result
|
|
323
|
+
''', undefined
|
|
324
|
+
|
|
325
|
+
code "void function no implicit return in codegen", '''
|
|
326
|
+
def process!
|
|
327
|
+
x = 42
|
|
328
|
+
x * 2
|
|
329
|
+
''', '''
|
|
330
|
+
function process() {
|
|
331
|
+
let x;
|
|
332
|
+
x = 42;
|
|
333
|
+
(x * 2);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
'''
|
|
337
|
+
|
|
338
|
+
code "void function early return no value", '''
|
|
339
|
+
def validate!(x)
|
|
340
|
+
return if x < 0
|
|
341
|
+
console.log "ok"
|
|
342
|
+
''', '''
|
|
343
|
+
function validate(x) {
|
|
344
|
+
if ((x < 0)) return;
|
|
345
|
+
console.log("ok");
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
'''
|
|
349
|
+
|
|
350
|
+
code "void function strips return value", '''
|
|
351
|
+
def compute!(x)
|
|
352
|
+
return x * 2
|
|
353
|
+
''', '''
|
|
354
|
+
function compute(x) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
'''
|
|
358
|
+
|
|
359
|
+
# ============================================================================
|
|
360
|
+
# Void Arrow Functions (! with -> and =>)
|
|
361
|
+
# ============================================================================
|
|
362
|
+
|
|
363
|
+
test "void thin arrow no implicit return", '''
|
|
364
|
+
c! = ->
|
|
365
|
+
x = 42
|
|
366
|
+
x * 2
|
|
367
|
+
result = c()
|
|
368
|
+
result
|
|
369
|
+
''', undefined
|
|
370
|
+
|
|
371
|
+
test "void thin arrow with params", '''
|
|
372
|
+
add! = (a, b) ->
|
|
373
|
+
a + b
|
|
374
|
+
result = add(5, 10)
|
|
375
|
+
result
|
|
376
|
+
''', undefined
|
|
377
|
+
|
|
378
|
+
test "void thin arrow with return", '''
|
|
379
|
+
c! = ->
|
|
380
|
+
return "hello world"
|
|
381
|
+
result = c()
|
|
382
|
+
result
|
|
383
|
+
''', undefined
|
|
384
|
+
|
|
385
|
+
test "void fat arrow no implicit return", '''
|
|
386
|
+
d! = =>
|
|
387
|
+
x = 100
|
|
388
|
+
x * 2
|
|
389
|
+
result = d()
|
|
390
|
+
result
|
|
391
|
+
''', undefined
|
|
392
|
+
|
|
393
|
+
test "void fat arrow with params", '''
|
|
394
|
+
multiply! = (a, b) =>
|
|
395
|
+
a * b
|
|
396
|
+
result = multiply(3, 4)
|
|
397
|
+
result
|
|
398
|
+
''', undefined
|
|
399
|
+
|
|
400
|
+
test "void fat arrow with comprehension", '''
|
|
401
|
+
d! = (e, f, g) =>
|
|
402
|
+
h = for i in [3..6]
|
|
403
|
+
i + 4
|
|
404
|
+
result = d(1, 2, 3)
|
|
405
|
+
result
|
|
406
|
+
''', undefined
|
|
407
|
+
|
|
408
|
+
code "void thin arrow codegen", '''
|
|
409
|
+
c! = ->
|
|
410
|
+
return "hello world"
|
|
411
|
+
''', '''
|
|
412
|
+
let c;
|
|
413
|
+
c = (function() {
|
|
414
|
+
return;
|
|
415
|
+
});
|
|
416
|
+
'''
|
|
417
|
+
|
|
418
|
+
code "void fat arrow codegen", '''
|
|
419
|
+
process! = (x) =>
|
|
420
|
+
x * 2
|
|
421
|
+
''', '''
|
|
422
|
+
let process;
|
|
423
|
+
process = (x) => {
|
|
424
|
+
(x * 2);
|
|
425
|
+
return;
|
|
426
|
+
};
|
|
427
|
+
'''
|
|
428
|
+
|
|
429
|
+
# NOTE: Object method void syntax (fn!:) not yet supported by parser
|
|
430
|
+
# test "void arrow in object method", '''
|
|
431
|
+
# obj = {
|
|
432
|
+
# fn!: -> 42
|
|
433
|
+
# }
|
|
434
|
+
# result = obj.fn()
|
|
435
|
+
# result
|
|
436
|
+
# ''', undefined
|
|
437
|
+
|
|
438
|
+
# ============================================================================
|
|
439
|
+
# Stats for CODEGEN.md
|
|
440
|
+
# ============================================================================
|
|
441
|
+
# Node types: def, ->, =>, function calls, rest, ..., default, return, void functions (!)
|
|
442
|
+
# Tests: 81 total (81 passing, 0 failing)
|
|
443
|
+
# Coverage: Function definitions, arrows, calls, parameters, returns, IIFE, closures, higher-order functions, void functions (def and arrows)
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# Loop Guard Tests (when clause)
|
|
3
|
+
# ==============================================================================
|
|
4
|
+
#
|
|
5
|
+
# Tests for 'when' guards in for-in, for-of, while, and until loops.
|
|
6
|
+
# Guards filter iterations/executions based on a condition.
|
|
7
|
+
# ==============================================================================
|
|
8
|
+
|
|
9
|
+
# ==============================================================================
|
|
10
|
+
# FOR-IN GUARDS
|
|
11
|
+
# ==============================================================================
|
|
12
|
+
|
|
13
|
+
test 'for-in with simple guard', '''
|
|
14
|
+
result = []
|
|
15
|
+
for x in [1, 2, 3, 4, 5] when x > 2
|
|
16
|
+
result.push(x)
|
|
17
|
+
result
|
|
18
|
+
''', [3, 4, 5]
|
|
19
|
+
|
|
20
|
+
test 'for-in guard with not', '''
|
|
21
|
+
result = []
|
|
22
|
+
for x in [1, 2, 3, 4, 5] when not (x is 3)
|
|
23
|
+
result.push(x)
|
|
24
|
+
result
|
|
25
|
+
''', [1, 2, 4, 5]
|
|
26
|
+
|
|
27
|
+
test 'for-in guard with and', '''
|
|
28
|
+
result = []
|
|
29
|
+
for x in [1, 2, 3, 4, 5, 6] when x > 2 and x < 5
|
|
30
|
+
result.push(x)
|
|
31
|
+
result
|
|
32
|
+
''', [3, 4]
|
|
33
|
+
|
|
34
|
+
test 'for-in guard with modulo', '''
|
|
35
|
+
result = []
|
|
36
|
+
for x in [1, 2, 3, 4, 5, 6] when x % 2 is 0
|
|
37
|
+
result.push(x)
|
|
38
|
+
result
|
|
39
|
+
''', [2, 4, 6]
|
|
40
|
+
|
|
41
|
+
test 'for-in guard filtering strings', '''
|
|
42
|
+
result = []
|
|
43
|
+
for line in ["", "hello", "", "world", " "] when line and line.trim()
|
|
44
|
+
result.push(line)
|
|
45
|
+
result
|
|
46
|
+
''', ["hello", "world"]
|
|
47
|
+
|
|
48
|
+
# ==============================================================================
|
|
49
|
+
# FOR-OF GUARDS
|
|
50
|
+
# ==============================================================================
|
|
51
|
+
|
|
52
|
+
test 'for-of with guard (key only)', '''
|
|
53
|
+
result = []
|
|
54
|
+
for k of {a: 1, b: 2, c: 3} when k isnt 'b'
|
|
55
|
+
result.push(k)
|
|
56
|
+
result
|
|
57
|
+
''', ["a", "c"]
|
|
58
|
+
|
|
59
|
+
test 'for-of guard key only comprehension', '''
|
|
60
|
+
result = (k for k of {a: 1, b: 2, c: 3} when k isnt 'b')
|
|
61
|
+
result
|
|
62
|
+
''', ["a", "c"]
|
|
63
|
+
|
|
64
|
+
test 'for-of with guard single entry', '''
|
|
65
|
+
result = []
|
|
66
|
+
for k, v of {a: 1} when v > 0
|
|
67
|
+
result.push(k)
|
|
68
|
+
result
|
|
69
|
+
''', ["a"]
|
|
70
|
+
|
|
71
|
+
test 'for-of guard single entry comprehension', '''
|
|
72
|
+
result = (k for k, v of {a: 1} when v > 0)
|
|
73
|
+
result
|
|
74
|
+
''', ["a"]
|
|
75
|
+
|
|
76
|
+
test 'for-of with guard (key and value)', '''
|
|
77
|
+
result = []
|
|
78
|
+
for k, v of {a: 1, b: 2, c: 3, d: 4} when v > 2
|
|
79
|
+
result.push(k)
|
|
80
|
+
result
|
|
81
|
+
''', ["c", "d"]
|
|
82
|
+
|
|
83
|
+
test 'for-of guard complex condition', '''
|
|
84
|
+
obj = {x: 10, y: 20, z: 30}
|
|
85
|
+
sum = 0
|
|
86
|
+
for key, val of obj when val >= 20
|
|
87
|
+
sum += val
|
|
88
|
+
sum
|
|
89
|
+
''', 50
|
|
90
|
+
|
|
91
|
+
# ==============================================================================
|
|
92
|
+
# COMPREHENSIONS WITH GUARDS
|
|
93
|
+
# ==============================================================================
|
|
94
|
+
|
|
95
|
+
test 'comprehension with guard', '''
|
|
96
|
+
result = (x for x in [1, 2, 3, 4, 5] when x > 2)
|
|
97
|
+
result
|
|
98
|
+
''', [3, 4, 5]
|
|
99
|
+
|
|
100
|
+
test 'comprehension guard with not', '''
|
|
101
|
+
result = (x for x in [1, 2, 3, 4, 5] when not (x is 3))
|
|
102
|
+
result
|
|
103
|
+
''', [1, 2, 4, 5]
|
|
104
|
+
|
|
105
|
+
test 'comprehension guard complex', '''
|
|
106
|
+
result = (x * 2 for x in [1, 2, 3, 4, 5, 6] when x % 2 is 0 and x < 5)
|
|
107
|
+
result
|
|
108
|
+
''', [4, 8]
|
|
109
|
+
|
|
110
|
+
test 'object comprehension with guard', '''
|
|
111
|
+
result = {k: v for k, v of {a: 1, b: 2, c: 3} when v > 1}
|
|
112
|
+
result.b
|
|
113
|
+
''', 2
|
|
114
|
+
|
|
115
|
+
# ==============================================================================
|
|
116
|
+
# EDGE CASES
|
|
117
|
+
# ==============================================================================
|
|
118
|
+
|
|
119
|
+
test 'guard with method call', '''
|
|
120
|
+
items = ["hello", "", "world", " "]
|
|
121
|
+
result = []
|
|
122
|
+
for item in items when item.trim()
|
|
123
|
+
result.push(item)
|
|
124
|
+
result
|
|
125
|
+
''', ["hello", "world"]
|
|
126
|
+
|
|
127
|
+
test 'guard with property access', '''
|
|
128
|
+
objects = [{ok: true, val: 1}, {ok: false, val: 2}, {ok: true, val: 3}]
|
|
129
|
+
sum = 0
|
|
130
|
+
for obj in objects when obj.ok
|
|
131
|
+
sum += obj.val
|
|
132
|
+
sum
|
|
133
|
+
''', 4
|
|
134
|
+
|
|
135
|
+
test 'guard with negated method', '''
|
|
136
|
+
lines = ["# comment", "data", "# another", "more"]
|
|
137
|
+
result = []
|
|
138
|
+
for line in lines when not line.startsWith("#")
|
|
139
|
+
result.push(line)
|
|
140
|
+
result
|
|
141
|
+
''', ["data", "more"]
|
|
142
|
+
|
|
143
|
+
# ==============================================================================
|
|
144
|
+
# OWN KEYWORD (for-of only)
|
|
145
|
+
# ==============================================================================
|
|
146
|
+
|
|
147
|
+
test 'own filters inherited properties', '''
|
|
148
|
+
obj = Object.create({inherited: 'parent'})
|
|
149
|
+
obj.own1 = 'value1'
|
|
150
|
+
obj.own2 = 'value2'
|
|
151
|
+
result = []
|
|
152
|
+
for own k of obj
|
|
153
|
+
result.push(k)
|
|
154
|
+
result
|
|
155
|
+
''', ["own1", "own2"]
|
|
156
|
+
|
|
157
|
+
test 'own with key and value', '''
|
|
158
|
+
obj = Object.create({inherited: 99})
|
|
159
|
+
obj.a = 1
|
|
160
|
+
obj.b = 2
|
|
161
|
+
sum = 0
|
|
162
|
+
for own k, v of obj
|
|
163
|
+
sum += v
|
|
164
|
+
sum
|
|
165
|
+
''', 3
|
|
166
|
+
|
|
167
|
+
test 'own with guard', '''
|
|
168
|
+
obj = Object.create({inherited: 0})
|
|
169
|
+
obj.a = 1
|
|
170
|
+
obj.b = 2
|
|
171
|
+
obj.c = 3
|
|
172
|
+
result = []
|
|
173
|
+
for own k, v of obj when v > 1
|
|
174
|
+
result.push(k)
|
|
175
|
+
result
|
|
176
|
+
''', ["b", "c"]
|
|
177
|
+
|
|
178
|
+
test 'own in comprehension', '''
|
|
179
|
+
obj = Object.create({inherited: 'x'})
|
|
180
|
+
obj.a = 1
|
|
181
|
+
obj.b = 2
|
|
182
|
+
result = (k for own k of obj)
|
|
183
|
+
result
|
|
184
|
+
''', ["a", "b"]
|
|
185
|
+
|
|
186
|
+
test 'own in object comprehension', '''
|
|
187
|
+
obj = Object.create({inherited: 99})
|
|
188
|
+
obj.a = 1
|
|
189
|
+
obj.b = 2
|
|
190
|
+
result = {k: v for own k, v of obj}
|
|
191
|
+
Object.keys(result).sort()
|
|
192
|
+
''', ["a", "b"]
|
|
193
|
+
|
|
194
|
+
test 'own with guard in comprehension', '''
|
|
195
|
+
obj = Object.create({inherited: 0})
|
|
196
|
+
obj.a = 1
|
|
197
|
+
obj.b = 2
|
|
198
|
+
obj.c = 3
|
|
199
|
+
result = (k for own k, v of obj when v > 1)
|
|
200
|
+
result
|
|
201
|
+
''', ["b", "c"]
|
|
202
|
+
|
|
203
|
+
# ==============================================================================
|
|
204
|
+
# CODE GENERATION TESTS
|
|
205
|
+
# ==============================================================================
|
|
206
|
+
|
|
207
|
+
code 'for-in guard code', '''
|
|
208
|
+
for x in arr when x > 5
|
|
209
|
+
console.log x
|
|
210
|
+
''', '''
|
|
211
|
+
for (const x of arr) {
|
|
212
|
+
if (x > 5) {
|
|
213
|
+
console.log(x);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
'''
|
|
217
|
+
|
|
218
|
+
code 'for-of guard code', '''
|
|
219
|
+
for k, v of obj when v > 0
|
|
220
|
+
console.log k
|
|
221
|
+
''', '''
|
|
222
|
+
for (const k in obj) {
|
|
223
|
+
const v = obj[k];
|
|
224
|
+
if ((v > 0)) {
|
|
225
|
+
console.log(k);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
'''
|
|
229
|
+
|
|
230
|
+
code 'for-of with own code', '''
|
|
231
|
+
for own k, v of obj
|
|
232
|
+
console.log k
|
|
233
|
+
''', '''
|
|
234
|
+
for (const k in obj) {
|
|
235
|
+
if (obj.hasOwnProperty(k)) {
|
|
236
|
+
const v = obj[k];
|
|
237
|
+
console.log(k);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
'''
|
|
241
|
+
|
|
242
|
+
# ============================================================================
|
|
243
|
+
# Stats for CODEGEN.md
|
|
244
|
+
# ============================================================================
|
|
245
|
+
# Node types: for-in/for-of guards (when clause), own keyword (for-of only)
|
|
246
|
+
# Tests: 27 total (24 execution + 3 code generation, 27 passing, 0 failing)
|
|
247
|
+
# Coverage: Guards in all loop types, own keyword filtering inherited properties, combined own+guard
|