rapydscript-ns 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.
Files changed (144) hide show
  1. package/.agignore +1 -0
  2. package/.gitattributes +4 -0
  3. package/.github/workflows/ci.yml +38 -0
  4. package/.github/workflows/web-repl-page-deploy.yml +42 -0
  5. package/=template.pyj +5 -0
  6. package/CHANGELOG.md +456 -0
  7. package/CONTRIBUTORS +13 -0
  8. package/HACKING.md +103 -0
  9. package/LICENSE +24 -0
  10. package/README.md +2512 -0
  11. package/TODO.md +327 -0
  12. package/add-toc-to-readme +2 -0
  13. package/bin/export +75 -0
  14. package/bin/rapydscript +70 -0
  15. package/bin/web-repl-export +102 -0
  16. package/build +3 -0
  17. package/package.json +46 -0
  18. package/publish.py +37 -0
  19. package/release/baselib-plain-pretty.js +4370 -0
  20. package/release/baselib-plain-ugly.js +3 -0
  21. package/release/compiler.js +18394 -0
  22. package/release/signatures.json +31 -0
  23. package/session.vim +4 -0
  24. package/setup.cfg +2 -0
  25. package/src/ast.pyj +1356 -0
  26. package/src/baselib-builtins.pyj +279 -0
  27. package/src/baselib-containers.pyj +723 -0
  28. package/src/baselib-errors.pyj +37 -0
  29. package/src/baselib-internal.pyj +421 -0
  30. package/src/baselib-itertools.pyj +97 -0
  31. package/src/baselib-str.pyj +798 -0
  32. package/src/compiler.pyj +36 -0
  33. package/src/errors.pyj +30 -0
  34. package/src/lib/aes.pyj +646 -0
  35. package/src/lib/collections.pyj +695 -0
  36. package/src/lib/elementmaker.pyj +83 -0
  37. package/src/lib/encodings.pyj +126 -0
  38. package/src/lib/functools.pyj +148 -0
  39. package/src/lib/gettext.pyj +569 -0
  40. package/src/lib/itertools.pyj +580 -0
  41. package/src/lib/math.pyj +193 -0
  42. package/src/lib/numpy.pyj +2101 -0
  43. package/src/lib/operator.pyj +11 -0
  44. package/src/lib/pythonize.pyj +20 -0
  45. package/src/lib/random.pyj +118 -0
  46. package/src/lib/re.pyj +470 -0
  47. package/src/lib/traceback.pyj +63 -0
  48. package/src/lib/uuid.pyj +77 -0
  49. package/src/monaco-language-service/analyzer.js +526 -0
  50. package/src/monaco-language-service/builtins.js +543 -0
  51. package/src/monaco-language-service/completions.js +498 -0
  52. package/src/monaco-language-service/diagnostics.js +643 -0
  53. package/src/monaco-language-service/dts.js +550 -0
  54. package/src/monaco-language-service/hover.js +121 -0
  55. package/src/monaco-language-service/index.js +386 -0
  56. package/src/monaco-language-service/scope.js +162 -0
  57. package/src/monaco-language-service/signature.js +144 -0
  58. package/src/output/__init__.pyj +0 -0
  59. package/src/output/classes.pyj +296 -0
  60. package/src/output/codegen.pyj +492 -0
  61. package/src/output/comments.pyj +45 -0
  62. package/src/output/exceptions.pyj +105 -0
  63. package/src/output/functions.pyj +491 -0
  64. package/src/output/literals.pyj +109 -0
  65. package/src/output/loops.pyj +444 -0
  66. package/src/output/modules.pyj +329 -0
  67. package/src/output/operators.pyj +429 -0
  68. package/src/output/statements.pyj +463 -0
  69. package/src/output/stream.pyj +309 -0
  70. package/src/output/treeshake.pyj +182 -0
  71. package/src/output/utils.pyj +72 -0
  72. package/src/parse.pyj +3106 -0
  73. package/src/string_interpolation.pyj +72 -0
  74. package/src/tokenizer.pyj +702 -0
  75. package/src/unicode_aliases.pyj +576 -0
  76. package/src/utils.pyj +192 -0
  77. package/test/_import_one.pyj +37 -0
  78. package/test/_import_two/__init__.pyj +11 -0
  79. package/test/_import_two/level2/__init__.pyj +0 -0
  80. package/test/_import_two/level2/deep.pyj +4 -0
  81. package/test/_import_two/other.pyj +6 -0
  82. package/test/_import_two/sub.pyj +13 -0
  83. package/test/aes_vectors.pyj +421 -0
  84. package/test/annotations.pyj +80 -0
  85. package/test/baselib.pyj +319 -0
  86. package/test/classes.pyj +452 -0
  87. package/test/collections.pyj +152 -0
  88. package/test/decorators.pyj +77 -0
  89. package/test/dict_spread.pyj +76 -0
  90. package/test/docstrings.pyj +39 -0
  91. package/test/elementmaker_test.pyj +45 -0
  92. package/test/ellipsis.pyj +49 -0
  93. package/test/functions.pyj +151 -0
  94. package/test/generators.pyj +41 -0
  95. package/test/generic.pyj +370 -0
  96. package/test/imports.pyj +72 -0
  97. package/test/internationalization.pyj +73 -0
  98. package/test/lint.pyj +164 -0
  99. package/test/loops.pyj +85 -0
  100. package/test/numpy.pyj +734 -0
  101. package/test/omit_function_metadata.pyj +20 -0
  102. package/test/regexp.pyj +55 -0
  103. package/test/repl.pyj +121 -0
  104. package/test/scoped_flags.pyj +76 -0
  105. package/test/starargs.pyj +506 -0
  106. package/test/starred_assign.pyj +104 -0
  107. package/test/str.pyj +198 -0
  108. package/test/subscript_tuple.pyj +53 -0
  109. package/test/unit/fixtures/fibonacci_expected.js +46 -0
  110. package/test/unit/index.js +2989 -0
  111. package/test/unit/language-service-builtins.js +815 -0
  112. package/test/unit/language-service-completions.js +1067 -0
  113. package/test/unit/language-service-dts.js +543 -0
  114. package/test/unit/language-service-hover.js +455 -0
  115. package/test/unit/language-service-scope.js +833 -0
  116. package/test/unit/language-service-signature.js +458 -0
  117. package/test/unit/language-service.js +705 -0
  118. package/test/unit/run-language-service.js +41 -0
  119. package/test/unit/web-repl.js +484 -0
  120. package/tools/build-language-service.js +190 -0
  121. package/tools/cli.js +547 -0
  122. package/tools/compile.js +219 -0
  123. package/tools/compiler.js +108 -0
  124. package/tools/completer.js +131 -0
  125. package/tools/embedded_compiler.js +251 -0
  126. package/tools/export.js +316 -0
  127. package/tools/gettext.js +185 -0
  128. package/tools/ini.js +65 -0
  129. package/tools/lint.js +705 -0
  130. package/tools/msgfmt.js +187 -0
  131. package/tools/repl.js +223 -0
  132. package/tools/self.js +162 -0
  133. package/tools/test.js +118 -0
  134. package/tools/utils.js +128 -0
  135. package/tools/web_repl.js +95 -0
  136. package/try +41 -0
  137. package/web-repl/env.js +74 -0
  138. package/web-repl/index.html +163 -0
  139. package/web-repl/language-service.js +4084 -0
  140. package/web-repl/main.js +254 -0
  141. package/web-repl/prism.css +139 -0
  142. package/web-repl/prism.js +113 -0
  143. package/web-repl/rapydscript.js +435 -0
  144. package/web-repl/sha1.js +25 -0
@@ -0,0 +1,506 @@
1
+ # vim:fileencoding=utf-8
2
+ # globals: assrt
3
+
4
+ eq = assrt.equal
5
+ de = assrt.deepEqual
6
+
7
+ def get(obj, name):
8
+ return obj[name] if obj else undefined
9
+
10
+ # Test the parsing of function definitions {{{
11
+
12
+ def basic_test(code, arglen, starargs, kwargs, defaults):
13
+ func = RapydScript.parse('def func(' + code + '): pass\n', {'filename':code}).body[0]
14
+ eq(func.argnames.length, arglen)
15
+ eq(get(func.argnames.starargs, 'name'), starargs)
16
+ eq(get(func.argnames.kwargs, 'name'), kwargs)
17
+ eq(func.argnames.is_simple_func, bool(not starargs and not kwargs and not defaults))
18
+ if defaults:
19
+ fd = {}
20
+ for key in Object.keys(func.argnames.defaults):
21
+ fd[key] = func.argnames.defaults[key].value
22
+ de(fd, defaults)
23
+ return func
24
+
25
+ def throw_test(code):
26
+ assrt.throws(def():
27
+ RapydScript.parse('def func(' + code + '): pass\n', {'filename':code}).body[0]
28
+ , RapydScript.SyntaxError)
29
+
30
+ basic_test('a, b, c', 3)
31
+ basic_test('*args', 0, 'args')
32
+ basic_test('a, b, *args', 2, 'args')
33
+ throw_test('*args, a')
34
+ throw_test('*args, *a')
35
+ basic_test('**kwargs', 0, undefined, 'kwargs')
36
+ basic_test('*args, **kwargs', 0, 'args', 'kwargs')
37
+ basic_test('a, b, *args, **kwargs', 2, 'args', 'kwargs')
38
+ throw_test('**kw, *a')
39
+ throw_test('**kw, **a')
40
+ basic_test('a=1, b="2"', 2, None, None, {'a':1, 'b':"2"})
41
+ basic_test('x, a=1, b="2", *args, **kw', 3, 'args', 'kw', {'a':1, 'b':"2"})
42
+ throw_test('a=1, b')
43
+ throw_test('**k, a=1')
44
+ throw_test('a, a')
45
+ throw_test('a, a=1')
46
+ throw_test('*a, **a')
47
+ # }}}
48
+
49
+ # Test parsing of function calls {{{
50
+
51
+ def parse_call_test(code, arglen, opts):
52
+ func = RapydScript.parse('f(' + code + ')', {'filename':code}).body[0].body
53
+ opts = opts or {}
54
+ eq(func.args.length, arglen, 'Incorrect len for: ' + code)
55
+ if (opts.starargs != undefined):
56
+ si = [[i, x.name] for i, x in enumerate(func.args) if x.is_array]
57
+ de(opts.starargs, si, 'starargs wrong for: ' + code + ': ' + si + ' != ' + opts.starargs)
58
+ if (opts.kwargs != undefined):
59
+ de(opts.kwargs, [x[0].name for x in func.args.kwargs])
60
+
61
+
62
+ parse_call_test('a, b, c', 3)
63
+ parse_call_test('*args', 1, {'starargs':[[0, 'args']]})
64
+ parse_call_test('a, b, *args', 3, {'starargs':[[2, 'args']]})
65
+ parse_call_test('a, *args, b, *a2', 4, {'starargs':[[1, 'args'], [3, 'a2']]})
66
+ parse_call_test('a=1', 0, {'kwargs':['a']})
67
+ parse_call_test('a=1, b', 1, {'kwargs':['a']})
68
+ parse_call_test('a=1, b, **kwargs, *args, **k2', 2, {'kwargs':['a'], 'kw':['kwargs', 'k2'], 'starargs':[[1,'args']]})
69
+ # }}}
70
+
71
+ # Test calling {{{
72
+
73
+ def f():
74
+ return Array.prototype.slice.call(arguments)
75
+
76
+
77
+ de(f(1, 2, 3), [1, 2, 3])
78
+ args1, args2 = [4, 5, 6], [7, 8, 9]
79
+ kw1, kw2 = {'a':4, 'b':5, 'c':6}, {'a':7, 'x':8, 'y':9}
80
+
81
+ de(f(*args1), [4, 5, 6])
82
+ de(f(1, *args1), [1, 4, 5, 6])
83
+ de(f(*args1, 2), [4, 5, 6, 2])
84
+ de(f(1, *args1, 2), [1, 4, 5, 6, 2])
85
+ de(f(*args1, *args2), args1.concat(args2))
86
+ de(f(*args1, 1, 2, *args2, 3), [4, 5, 6, 1, 2, 7, 8, 9, 3])
87
+
88
+ de(f(1, a=2), [1, {'a':2}])
89
+ de(f(1, a=2, 3), [1, 3, {'a':2}])
90
+ de(f(**kw1), [kw1])
91
+ de(f(1, a=2, 3, **kw1), [1, 3, {'a':2, 'b':5, 'c':6}])
92
+ de(f(**kw2, 1, 3, **kw1, 2), [1, 3, 2, {'a':4, 'b':5, 'c':6, 'x':8, 'y':9}])
93
+
94
+ # }}}
95
+
96
+ # Test calling with definitions {{{
97
+
98
+ def f1(a, b, c):
99
+ return a, b, c
100
+ de(f1(1, 2, 3), [1, 2, 3])
101
+ de(f1(), [undefined, undefined, undefined])
102
+
103
+ def f2(a, b=1):
104
+ return a, b
105
+
106
+ de(f2(), [undefined, 1])
107
+ de(f2(1), [1, 1])
108
+ de(f2(1, 2), [1, 2])
109
+ de(f2(b=2), [undefined, 2])
110
+ de(f2(1, b=2), [1, 2])
111
+ de(f2({'b':3}), [{'b':3}, 1], 'a normal object is being treated as an options object')
112
+
113
+ def f3(*args):
114
+ return args
115
+
116
+ de(f3(), [])
117
+ de(f3(1, 2), [1, 2])
118
+
119
+ def f4(**kwargs):
120
+ return kwargs
121
+
122
+ de(f4(), {})
123
+ de(f4(a=1, b=2), {'a':1, 'b':2})
124
+
125
+ def f5(*args, **kwargs):
126
+ return [args, kwargs]
127
+
128
+ de(f5(), [[], {}])
129
+ de(f5(1, 2, a=1, b=2), [[1,2], {'a':1, 'b':2}])
130
+
131
+ def f6(a, *args):
132
+ return [a, args]
133
+
134
+ de(f6(), [undefined, []])
135
+ de(f6(1), [1, []])
136
+ de(f6(1, 2, 3), [1, [2, 3]])
137
+
138
+ def f7(a=1, **kw):
139
+ return [a, kw]
140
+
141
+ de(f7(), [1, {}])
142
+ de(f7(a=3, b=4), [3, {'b':4}])
143
+
144
+ def f8(a, b=2, *args, **kwargs):
145
+ return [a, b, args, kwargs]
146
+
147
+ de(f8(), [undefined, 2, [], {}])
148
+ de(f8(1), [1, 2, [], {}])
149
+ de(f8(1, 3, 4, 5, b=8, c=9), [1, 8, [4, 5], {'c':9}])
150
+
151
+ def f9(*args, **kwargs):
152
+ return [args, kwargs]
153
+
154
+ de(f9(), [[], {}])
155
+ de(f9(1, 2, a=1, b=2), [[1,2], {'a':1, 'b':2}])
156
+
157
+ def f10(a, b=2, c=3):
158
+ return [a, b, c]
159
+
160
+ de(f10(1, c=6), [1, 2, 6])
161
+
162
+ def f11(a, b, x=1):
163
+ return [a, b, x]
164
+
165
+ de(f11(x=3), [undefined, undefined, 3])
166
+ # }}}
167
+
168
+ acc = []
169
+ def mutable_defaults(a=acc):
170
+ a.append(1)
171
+
172
+ mutable_defaults(), mutable_defaults()
173
+ de([1, 1], acc)
174
+
175
+ def identity(f):
176
+ return def():
177
+ return f()
178
+
179
+ @identity
180
+ def wrapped(x=1):
181
+ return x
182
+
183
+ eq(wrapped(), 1)
184
+
185
+ class W:
186
+ @identity
187
+ def wrapped(self, x=1):
188
+ return x
189
+ eq(W().wrapped(), 1)
190
+ eq(1, (def(x=1): return x;)())
191
+
192
+ class Simple:
193
+
194
+ def __init__(self, a, b):
195
+ self.q = [a, b]
196
+ de(Simple(b=2, a=1).q, [1, 2])
197
+
198
+ class Other:
199
+ def func(self, **kw):
200
+ if self:
201
+ return kw
202
+
203
+ class Test:
204
+
205
+ def __init__(self, a, b=2, *args, **kwargs):
206
+ self.q = [a, b, args, kwargs]
207
+ self.other = Other()
208
+
209
+ def forwarded(self, **kw):
210
+ return self.other.func(**kw)
211
+
212
+ def simple(self, a, b):
213
+ return [a, b]
214
+
215
+ de(Test().q, [undefined, 2, [], {}])
216
+ de(Test(a=1).q, [1, 2, [], {}])
217
+ de(Test(1, 3, 4, 5, b=8, c=9).q, [1, 8, [4, 5], {'c':9}])
218
+ args = [1, 2]
219
+ de(Test(*args).q, [1, 2, [], {}])
220
+ t = Test()
221
+ de(t.simple(b=2, a=1), [1, 2])
222
+
223
+ @options_object
224
+ def callback(a, b=1, c=2):
225
+ return [a, b, c]
226
+
227
+ de(callback(0, {'c':4}), [0, 1, 4])
228
+
229
+ def afunc(a=1):
230
+ return a
231
+
232
+ def a2func(*args):
233
+ return args[0]
234
+
235
+ eq(afunc(None), None)
236
+ eq(a2func(None), None)
237
+ de(Test().forwarded(a=1), {'a':1})
238
+
239
+ def norm(a, b):
240
+ return [a, b]
241
+
242
+ de(norm(b=2, a=1), [1, 2])
243
+
244
+ call_counter = 0
245
+
246
+ def cc():
247
+ nonlocal call_counter
248
+ call_counter += 1
249
+ return def():
250
+ pass
251
+
252
+ cc()(a=1)
253
+ eq(call_counter, 1)
254
+ cc(o=1)(a=1)
255
+ eq(call_counter, 2)
256
+ call_counter = 0
257
+
258
+ def cc2():
259
+ nonlocal call_counter
260
+ call_counter += 1
261
+ return {'val':3, 'x':def():return this.val;}
262
+ eq(3, cc2().x(a=1))
263
+ eq(call_counter, 1)
264
+ call_counter = 0
265
+
266
+ def cc3():
267
+ nonlocal call_counter
268
+ call_counter += 1
269
+ this.num = call_counter
270
+ this.c = def():
271
+ return call_counter
272
+ eq(new cc3(a=1).num, 1)
273
+ eq(new cc3(a=1).c(b=9), 2)
274
+
275
+ class Pr:
276
+ def __init__(self, a=1):
277
+ self.a = a
278
+
279
+ def add(self, val=0):
280
+ self.a += val
281
+
282
+ class Pr2(Pr):
283
+
284
+ def __init__(self):
285
+ Pr.__init__(self, a=2)
286
+
287
+ def add(self):
288
+ Pr.add(self, val=1)
289
+
290
+ p = Pr(a=2)
291
+ p.add(val=3)
292
+ eq(p.a, 5)
293
+ p = Pr2()
294
+ p.add()
295
+ eq(p.a, 3)
296
+ p1, p2 = Pr(), Pr(a=1)
297
+ eq(p1.prototype, p2.prototype)
298
+ de(dir(p1), dir(p2))
299
+
300
+ class Prn:
301
+
302
+ def __init__(self, x):
303
+ self.x = x
304
+
305
+ class Prn1(Prn):
306
+
307
+ def __init__(self, x, *a):
308
+ Prn.__init__(self, [x, a])
309
+
310
+ class Prn2(Prn):
311
+
312
+ def __init__(self, *a):
313
+ Prn.__init__(self, a)
314
+
315
+
316
+ class Prn3(Prn):
317
+
318
+ def __init__(self, *a):
319
+ Prn.__init__(self, *a)
320
+
321
+ p = Prn1(1, 2, 3)
322
+ eq(p.x[0], 1)
323
+ de(p.x[1], [2, 3])
324
+ p = Prn2(1, 2)
325
+ de(p.x, [1, 2])
326
+ p = Prn3(1, 2)
327
+ eq(p.x, 1)
328
+
329
+
330
+ class Prnb:
331
+
332
+ def __init__(self, a, k):
333
+ self.a, self.k = a, k
334
+
335
+ class Prnb1(Prnb):
336
+
337
+ def __init__(self, *a, **kw):
338
+ Prnb.__init__(self, a, kw)
339
+
340
+ p = Prnb1(1, 2, x=1, y=2)
341
+ de(p.a, [1, 2])
342
+ de(p.k, {'x': 1, 'y':2})
343
+
344
+ # Test positional-only (/) and keyword-only (*) parameter separators {{{
345
+
346
+ # --- Parse tests ---
347
+
348
+ def parse_posonly_test(code, arglen, posonly_count, bare_star):
349
+ func = RapydScript.parse('def func(' + code + '): pass\n', {'filename':code}).body[0]
350
+ eq(func.argnames.length, arglen, 'arglen for: ' + code)
351
+ eq(func.argnames.posonly_count or 0, posonly_count, 'posonly_count for: ' + code)
352
+ eq(bool(func.argnames.bare_star), bool(bare_star), 'bare_star for: ' + code)
353
+ eq(func.argnames.is_simple_func, False, 'is_simple_func should be False for: ' + code)
354
+ return func
355
+
356
+ # Positional-only: all params before /
357
+ f = parse_posonly_test('a, b, /', 2, 2, False)
358
+ eq(f.argnames[0].posonly, True)
359
+ eq(f.argnames[1].posonly, True)
360
+
361
+ # Positional-only: only first param is posonly
362
+ f = parse_posonly_test('a, /, b', 2, 1, False)
363
+ eq(f.argnames[0].posonly, True)
364
+ eq(bool(f.argnames[1].posonly), False)
365
+
366
+ # Keyword-only: bare * separator
367
+ f = parse_posonly_test('a, *, b', 2, 0, True)
368
+ eq(bool(f.argnames[0].kwonly), False)
369
+ eq(f.argnames[1].kwonly, True)
370
+
371
+ # Combined: positional-only and keyword-only
372
+ f = parse_posonly_test('a, /, *, b', 2, 1, True)
373
+ eq(f.argnames[0].posonly, True)
374
+ eq(f.argnames[1].kwonly, True)
375
+
376
+ # Posonly + regular + kwonly
377
+ f = parse_posonly_test('a, b, /, c, *, d, e', 5, 2, True)
378
+ eq(f.argnames[0].posonly, True)
379
+ eq(f.argnames[1].posonly, True)
380
+ eq(bool(f.argnames[2].posonly), False)
381
+ eq(bool(f.argnames[2].kwonly), False)
382
+ eq(f.argnames[3].kwonly, True)
383
+ eq(f.argnames[4].kwonly, True)
384
+
385
+ # Defaults in posonly and kwonly sections
386
+ f = parse_posonly_test('a=1, /, *, b=2', 2, 1, True)
387
+ eq(f.argnames.defaults.a.value, 1)
388
+ eq(f.argnames.defaults.b.value, 2)
389
+
390
+ # Posonly with *args and **kwargs
391
+ parse_posonly_test('a, /, *args', 1, 1, False)
392
+ parse_posonly_test('a, /, **kw', 1, 1, False)
393
+ parse_posonly_test('a, /, *args, **kw', 1, 1, False)
394
+
395
+ # Keyword-only with **kwargs
396
+ parse_posonly_test('a, *, b, **kw', 2, 0, True)
397
+
398
+ # Error: / before any argument
399
+ throw_test('/')
400
+ throw_test('/, a')
401
+
402
+ # Error: / after *
403
+ throw_test('*args, /')
404
+ throw_test('*, a, /')
405
+
406
+ # Error: / after **kwargs
407
+ throw_test('**kw, /')
408
+
409
+ # Error: duplicate /
410
+ throw_test('a, /, b, /')
411
+
412
+ # Error: bare * without following keyword-only param
413
+ throw_test('a, *')
414
+ throw_test('*')
415
+
416
+ # Error: required kwonly after optional kwonly
417
+ throw_test('*, a=1, b')
418
+
419
+ # --- Runtime tests ---
420
+
421
+ # Positional-only: basic
422
+ def po1(a, b, /):
423
+ return [a, b]
424
+
425
+ de(po1(1, 2), [1, 2])
426
+ de(po1(10, 20), [10, 20])
427
+
428
+ # Positional-only with default
429
+ def po2(a, b=99, /):
430
+ return [a, b]
431
+
432
+ de(po2(1), [1, 99])
433
+ de(po2(1, 2), [1, 2])
434
+
435
+ # Positional-only + regular
436
+ def po3(a, /, b):
437
+ return [a, b]
438
+
439
+ de(po3(1, 2), [1, 2])
440
+ de(po3(1, b=2), [1, 2])
441
+
442
+ # Positional-only + regular with default
443
+ def po4(a, /, b=5):
444
+ return [a, b]
445
+
446
+ de(po4(1), [1, 5])
447
+ de(po4(1, 10), [1, 10])
448
+ de(po4(1, b=10), [1, 10])
449
+
450
+ # Keyword-only: basic
451
+ def ko1(a, *, b):
452
+ return [a, b]
453
+
454
+ de(ko1(1, b=2), [1, 2])
455
+ de(ko1(b=2, a=1), [1, 2])
456
+
457
+ # Keyword-only with default
458
+ def ko2(a, *, b=7):
459
+ return [a, b]
460
+
461
+ de(ko2(1), [1, 7])
462
+ de(ko2(1, b=3), [1, 3])
463
+ de(ko2(a=1, b=3), [1, 3])
464
+
465
+ # Multiple keyword-only params
466
+ def ko3(*, x, y, z=0):
467
+ return [x, y, z]
468
+
469
+ de(ko3(x=1, y=2), [1, 2, 0])
470
+ de(ko3(x=1, y=2, z=3), [1, 2, 3])
471
+
472
+ # Combined posonly + kwonly
473
+ def poko1(a, b, /, *, c, d=4):
474
+ return [a, b, c, d]
475
+
476
+ de(poko1(1, 2, c=3), [1, 2, 3, 4])
477
+ de(poko1(1, 2, c=3, d=5), [1, 2, 3, 5])
478
+
479
+ # Combined posonly + regular + kwonly
480
+ def poko2(a, /, b, *, c):
481
+ return [a, b, c]
482
+
483
+ de(poko2(1, 2, c=3), [1, 2, 3])
484
+ de(poko2(1, b=2, c=3), [1, 2, 3])
485
+
486
+ # Posonly with *args
487
+ def po_star(a, /, *args):
488
+ return [a, args]
489
+
490
+ de(po_star(1, 2, 3), [1, [2, 3]])
491
+
492
+ # Kwonly with **kwargs
493
+ def ko_kw(a, *, b, **rest):
494
+ return [a, b, rest]
495
+
496
+ de(ko_kw(1, b=2, c=3), [1, 2, {'c':3}])
497
+
498
+ # Class method with posonly and kwonly
499
+ class PoKoClass:
500
+ def method(self, a, /, *, b):
501
+ return [a, b]
502
+
503
+ obj = PoKoClass()
504
+ de(obj.method(10, b=20), [10, 20])
505
+
506
+ # }}}
@@ -0,0 +1,104 @@
1
+ # vim:fileencoding=utf-8
2
+ # globals: assrt
3
+
4
+ eq = assrt.equal
5
+ de = assrt.deepEqual
6
+ ok = assrt.ok
7
+
8
+ # ----[ Transpilation tests (parse + codegen) ]----
9
+
10
+ def compile_test(code):
11
+ # Returns the JS output as a string (main code section only)
12
+ ast = RapydScript.parse(code + '\n', {'filename': code})
13
+ opts = RapydScript.OutputStream({'beautify': True, 'js_version': 7})
14
+ ast.print(opts)
15
+ return opts.get()
16
+
17
+ def throw_parse_test(code):
18
+ assrt.throws(def():
19
+ RapydScript.parse(code + '\n', {'filename': code})
20
+ , RapydScript.SyntaxError)
21
+
22
+ # ----[ Basic runtime correctness tests ]----
23
+
24
+ # a, *b, c = list — middle starred
25
+ a, *b, c = [1, 2, 3, 4, 5]
26
+ eq(a, 1)
27
+ de(b, [2, 3, 4])
28
+ eq(c, 5)
29
+
30
+ # *a, b = list — starred at front
31
+ *a, b = [1, 2, 3]
32
+ de(a, [1, 2])
33
+ eq(b, 3)
34
+
35
+ # x, *y = list — starred at end
36
+ x, *y = [1, 2, 3, 4]
37
+ eq(x, 1)
38
+ de(y, [2, 3, 4])
39
+
40
+ # first, *rest, last — first and last are scalars
41
+ first, *rest, last = [10, 20, 30, 40, 50]
42
+ eq(first, 10)
43
+ de(rest, [20, 30, 40])
44
+ eq(last, 50)
45
+
46
+ # Minimal: only two elements on rhs, starred in front
47
+ *p, q = [7, 8]
48
+ de(p, [7])
49
+ eq(q, 8)
50
+
51
+ # Minimal: only two elements on rhs, starred at end
52
+ m, *n = [7, 8]
53
+ eq(m, 7)
54
+ de(n, [8])
55
+
56
+ # Starred gets empty list when nothing to absorb
57
+ a2, *b2, c2 = [1, 2]
58
+ eq(a2, 1)
59
+ de(b2, [])
60
+ eq(c2, 2)
61
+
62
+ # Works with tuple packing on rhs
63
+ i, *j, k = 1, 2, 3, 4
64
+ eq(i, 1)
65
+ de(j, [2, 3])
66
+ eq(k, 4)
67
+
68
+ # Works with string (iterable)
69
+ head, *tail = "hello"
70
+ eq(head, "h")
71
+ de(tail, ["e", "l", "l", "o"])
72
+
73
+ # Works with generator
74
+ def make_gen():
75
+ yield 10
76
+ yield 20
77
+ yield 30
78
+ yield 40
79
+
80
+ g1, *g2, g3 = make_gen()
81
+ eq(g1, 10)
82
+ de(g2, [20, 30])
83
+ eq(g3, 40)
84
+
85
+ # Starred result is a list (not raw js array)
86
+ *s1, s2 = [1, 2, 3]
87
+ ok(Array.isArray(s1))
88
+ eq(s1.length, 2)
89
+
90
+ # ----[ Language service parse tests ]----
91
+
92
+ # Parsing: starred assignment produces an AST_SimpleStatement containing AST_Assign
93
+ parsed = RapydScript.parse('a, *b, c = [1,2,3]\n', {'filename': 'test'}).body[0]
94
+ ok(v'parsed instanceof RapydScript.AST_SimpleStatement')
95
+ ok(v'parsed.body instanceof RapydScript.AST_Assign')
96
+ ok(v'parsed.body.left instanceof RapydScript.AST_Array')
97
+
98
+ # ----[ Error detection ]----
99
+
100
+ # Multiple starred expressions should throw
101
+ throw_parse_test('*a, *b = [1, 2]')
102
+
103
+ # Starred in augmented assignment should throw
104
+ throw_parse_test('a, *b += [1, 2]')