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.
- package/.agignore +1 -0
- package/.gitattributes +4 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/web-repl-page-deploy.yml +42 -0
- package/=template.pyj +5 -0
- package/CHANGELOG.md +456 -0
- package/CONTRIBUTORS +13 -0
- package/HACKING.md +103 -0
- package/LICENSE +24 -0
- package/README.md +2512 -0
- package/TODO.md +327 -0
- package/add-toc-to-readme +2 -0
- package/bin/export +75 -0
- package/bin/rapydscript +70 -0
- package/bin/web-repl-export +102 -0
- package/build +3 -0
- package/package.json +46 -0
- package/publish.py +37 -0
- package/release/baselib-plain-pretty.js +4370 -0
- package/release/baselib-plain-ugly.js +3 -0
- package/release/compiler.js +18394 -0
- package/release/signatures.json +31 -0
- package/session.vim +4 -0
- package/setup.cfg +2 -0
- package/src/ast.pyj +1356 -0
- package/src/baselib-builtins.pyj +279 -0
- package/src/baselib-containers.pyj +723 -0
- package/src/baselib-errors.pyj +37 -0
- package/src/baselib-internal.pyj +421 -0
- package/src/baselib-itertools.pyj +97 -0
- package/src/baselib-str.pyj +798 -0
- package/src/compiler.pyj +36 -0
- package/src/errors.pyj +30 -0
- package/src/lib/aes.pyj +646 -0
- package/src/lib/collections.pyj +695 -0
- package/src/lib/elementmaker.pyj +83 -0
- package/src/lib/encodings.pyj +126 -0
- package/src/lib/functools.pyj +148 -0
- package/src/lib/gettext.pyj +569 -0
- package/src/lib/itertools.pyj +580 -0
- package/src/lib/math.pyj +193 -0
- package/src/lib/numpy.pyj +2101 -0
- package/src/lib/operator.pyj +11 -0
- package/src/lib/pythonize.pyj +20 -0
- package/src/lib/random.pyj +118 -0
- package/src/lib/re.pyj +470 -0
- package/src/lib/traceback.pyj +63 -0
- package/src/lib/uuid.pyj +77 -0
- package/src/monaco-language-service/analyzer.js +526 -0
- package/src/monaco-language-service/builtins.js +543 -0
- package/src/monaco-language-service/completions.js +498 -0
- package/src/monaco-language-service/diagnostics.js +643 -0
- package/src/monaco-language-service/dts.js +550 -0
- package/src/monaco-language-service/hover.js +121 -0
- package/src/monaco-language-service/index.js +386 -0
- package/src/monaco-language-service/scope.js +162 -0
- package/src/monaco-language-service/signature.js +144 -0
- package/src/output/__init__.pyj +0 -0
- package/src/output/classes.pyj +296 -0
- package/src/output/codegen.pyj +492 -0
- package/src/output/comments.pyj +45 -0
- package/src/output/exceptions.pyj +105 -0
- package/src/output/functions.pyj +491 -0
- package/src/output/literals.pyj +109 -0
- package/src/output/loops.pyj +444 -0
- package/src/output/modules.pyj +329 -0
- package/src/output/operators.pyj +429 -0
- package/src/output/statements.pyj +463 -0
- package/src/output/stream.pyj +309 -0
- package/src/output/treeshake.pyj +182 -0
- package/src/output/utils.pyj +72 -0
- package/src/parse.pyj +3106 -0
- package/src/string_interpolation.pyj +72 -0
- package/src/tokenizer.pyj +702 -0
- package/src/unicode_aliases.pyj +576 -0
- package/src/utils.pyj +192 -0
- package/test/_import_one.pyj +37 -0
- package/test/_import_two/__init__.pyj +11 -0
- package/test/_import_two/level2/__init__.pyj +0 -0
- package/test/_import_two/level2/deep.pyj +4 -0
- package/test/_import_two/other.pyj +6 -0
- package/test/_import_two/sub.pyj +13 -0
- package/test/aes_vectors.pyj +421 -0
- package/test/annotations.pyj +80 -0
- package/test/baselib.pyj +319 -0
- package/test/classes.pyj +452 -0
- package/test/collections.pyj +152 -0
- package/test/decorators.pyj +77 -0
- package/test/dict_spread.pyj +76 -0
- package/test/docstrings.pyj +39 -0
- package/test/elementmaker_test.pyj +45 -0
- package/test/ellipsis.pyj +49 -0
- package/test/functions.pyj +151 -0
- package/test/generators.pyj +41 -0
- package/test/generic.pyj +370 -0
- package/test/imports.pyj +72 -0
- package/test/internationalization.pyj +73 -0
- package/test/lint.pyj +164 -0
- package/test/loops.pyj +85 -0
- package/test/numpy.pyj +734 -0
- package/test/omit_function_metadata.pyj +20 -0
- package/test/regexp.pyj +55 -0
- package/test/repl.pyj +121 -0
- package/test/scoped_flags.pyj +76 -0
- package/test/starargs.pyj +506 -0
- package/test/starred_assign.pyj +104 -0
- package/test/str.pyj +198 -0
- package/test/subscript_tuple.pyj +53 -0
- package/test/unit/fixtures/fibonacci_expected.js +46 -0
- package/test/unit/index.js +2989 -0
- package/test/unit/language-service-builtins.js +815 -0
- package/test/unit/language-service-completions.js +1067 -0
- package/test/unit/language-service-dts.js +543 -0
- package/test/unit/language-service-hover.js +455 -0
- package/test/unit/language-service-scope.js +833 -0
- package/test/unit/language-service-signature.js +458 -0
- package/test/unit/language-service.js +705 -0
- package/test/unit/run-language-service.js +41 -0
- package/test/unit/web-repl.js +484 -0
- package/tools/build-language-service.js +190 -0
- package/tools/cli.js +547 -0
- package/tools/compile.js +219 -0
- package/tools/compiler.js +108 -0
- package/tools/completer.js +131 -0
- package/tools/embedded_compiler.js +251 -0
- package/tools/export.js +316 -0
- package/tools/gettext.js +185 -0
- package/tools/ini.js +65 -0
- package/tools/lint.js +705 -0
- package/tools/msgfmt.js +187 -0
- package/tools/repl.js +223 -0
- package/tools/self.js +162 -0
- package/tools/test.js +118 -0
- package/tools/utils.js +128 -0
- package/tools/web_repl.js +95 -0
- package/try +41 -0
- package/web-repl/env.js +74 -0
- package/web-repl/index.html +163 -0
- package/web-repl/language-service.js +4084 -0
- package/web-repl/main.js +254 -0
- package/web-repl/prism.css +139 -0
- package/web-repl/prism.js +113 -0
- package/web-repl/rapydscript.js +435 -0
- 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]')
|