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,463 @@
|
|
|
1
|
+
# vim:fileencoding=utf-8
|
|
2
|
+
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
|
+
from __python__ import hash_literals
|
|
4
|
+
|
|
5
|
+
from ast import (
|
|
6
|
+
AST_Definitions, AST_Scope, AST_Method, AST_Except, AST_EmptyStatement,
|
|
7
|
+
AST_Statement, AST_Seq, AST_BaseCall, AST_Dot, AST_Sub, AST_ItemAccess,
|
|
8
|
+
AST_Conditional, AST_Binary, AST_BlockStatement, is_node_type,
|
|
9
|
+
AST_Match, AST_MatchCase,
|
|
10
|
+
AST_MatchWildcard, AST_MatchCapture, AST_MatchLiteral, AST_MatchOr,
|
|
11
|
+
AST_MatchAs, AST_MatchStar, AST_MatchSequence, AST_MatchMapping, AST_MatchClass,
|
|
12
|
+
AST_AnnotatedAssign
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
def force_statement(stat, output):
|
|
16
|
+
if output.options.bracketize:
|
|
17
|
+
if not stat or is_node_type(stat, AST_EmptyStatement):
|
|
18
|
+
output.print("{}")
|
|
19
|
+
elif is_node_type(stat, AST_BlockStatement):
|
|
20
|
+
stat.print(output)
|
|
21
|
+
else:
|
|
22
|
+
output.with_block(def():
|
|
23
|
+
output.indent()
|
|
24
|
+
stat.print(output)
|
|
25
|
+
output.newline()
|
|
26
|
+
)
|
|
27
|
+
else:
|
|
28
|
+
if not stat or is_node_type(stat, AST_EmptyStatement):
|
|
29
|
+
output.force_semicolon()
|
|
30
|
+
else:
|
|
31
|
+
stat.print(output)
|
|
32
|
+
|
|
33
|
+
# return true if the node at the top of the stack (that means the
|
|
34
|
+
# innermost node in the current output) is lexically the first in
|
|
35
|
+
# a statement.
|
|
36
|
+
def first_in_statement(output):
|
|
37
|
+
a = output.stack()
|
|
38
|
+
i = a.length
|
|
39
|
+
node = a[i -= 1]
|
|
40
|
+
p = a[i -= 1]
|
|
41
|
+
while i > 0:
|
|
42
|
+
if is_node_type(p, AST_Statement) and p.body is node:
|
|
43
|
+
return True
|
|
44
|
+
if is_node_type(p, AST_Seq) and p.car is node
|
|
45
|
+
or is_node_type(p, AST_BaseCall) and p.expression is node
|
|
46
|
+
or is_node_type(p, AST_Dot) and p.expression is node
|
|
47
|
+
or is_node_type(p, AST_Sub) and p.expression is node
|
|
48
|
+
or is_node_type(p, AST_ItemAccess) and p.expression is node
|
|
49
|
+
or is_node_type(p, AST_Conditional) and p.condition is node
|
|
50
|
+
or is_node_type(p, AST_Binary) and p.left is node:
|
|
51
|
+
node = p
|
|
52
|
+
p = a[i -= 1]
|
|
53
|
+
else:
|
|
54
|
+
return False
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def declare_vars(vars, output):
|
|
58
|
+
# declare all variables as local, unless explictly set otherwise
|
|
59
|
+
if vars.length:
|
|
60
|
+
output.indent()
|
|
61
|
+
output.print("var")
|
|
62
|
+
output.space()
|
|
63
|
+
for i, arg in enumerate(vars):
|
|
64
|
+
if i:
|
|
65
|
+
output.comma()
|
|
66
|
+
|
|
67
|
+
arg.print(output)
|
|
68
|
+
output.semicolon()
|
|
69
|
+
output.newline()
|
|
70
|
+
|
|
71
|
+
def display_body(body, is_toplevel, output):
|
|
72
|
+
last = body.length - 1
|
|
73
|
+
for i, stmt in enumerate(body):
|
|
74
|
+
if not (is_node_type(stmt, AST_EmptyStatement)) and not (is_node_type(stmt, AST_Definitions)):
|
|
75
|
+
output.indent()
|
|
76
|
+
stmt.print(output)
|
|
77
|
+
if not (i is last and is_toplevel):
|
|
78
|
+
output.newline()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def display_complex_body(node, is_toplevel, output, function_preamble):
|
|
82
|
+
offset = 0
|
|
83
|
+
# argument offset
|
|
84
|
+
# this is a method, add 'var self = this'
|
|
85
|
+
if is_node_type(node, AST_Method) and not node.static:
|
|
86
|
+
output.indent()
|
|
87
|
+
output.print("var")
|
|
88
|
+
output.space()
|
|
89
|
+
output.assign(node.argnames[0])
|
|
90
|
+
output.print("this")
|
|
91
|
+
output.semicolon()
|
|
92
|
+
output.newline()
|
|
93
|
+
offset += 1
|
|
94
|
+
|
|
95
|
+
if is_node_type(node, AST_Scope):
|
|
96
|
+
function_preamble(node, output, offset)
|
|
97
|
+
declare_vars(node.localvars, output)
|
|
98
|
+
|
|
99
|
+
elif is_node_type(node, AST_Except):
|
|
100
|
+
if node.argname:
|
|
101
|
+
output.indent()
|
|
102
|
+
output.print("var")
|
|
103
|
+
output.space()
|
|
104
|
+
output.assign(node.argname)
|
|
105
|
+
output.print("ρσ_Exception")
|
|
106
|
+
output.semicolon()
|
|
107
|
+
output.newline()
|
|
108
|
+
|
|
109
|
+
display_body(node.body, is_toplevel, output)
|
|
110
|
+
|
|
111
|
+
def print_bracketed(node, output, complex, function_preamble, before, after):
|
|
112
|
+
if node.body.length > 0:
|
|
113
|
+
output.with_block(def():
|
|
114
|
+
if before:
|
|
115
|
+
before(output)
|
|
116
|
+
if complex:
|
|
117
|
+
display_complex_body(node, False, output, function_preamble)
|
|
118
|
+
else:
|
|
119
|
+
display_body(node.body, False, output)
|
|
120
|
+
if after:
|
|
121
|
+
after(output)
|
|
122
|
+
)
|
|
123
|
+
else:
|
|
124
|
+
if before or after:
|
|
125
|
+
output.with_block(def():
|
|
126
|
+
if before:
|
|
127
|
+
before(output)
|
|
128
|
+
if after:
|
|
129
|
+
after(output)
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
output.print("{}")
|
|
133
|
+
|
|
134
|
+
def print_with(self, output):
|
|
135
|
+
exits = v'[]'
|
|
136
|
+
output.assign('ρσ_with_exception'), output.print('undefined'), output.end_statement()
|
|
137
|
+
for clause in self.clauses:
|
|
138
|
+
output.with_counter += 1
|
|
139
|
+
clause_name = 'ρσ_with_clause_' + output.with_counter
|
|
140
|
+
exits.push(clause_name)
|
|
141
|
+
output.indent(), output.print('var '), output.assign(clause_name)
|
|
142
|
+
clause.expression.print(output)
|
|
143
|
+
output.end_statement()
|
|
144
|
+
output.indent()
|
|
145
|
+
if clause.alias:
|
|
146
|
+
output.assign(clause.alias.name)
|
|
147
|
+
output.print(clause_name + '.__enter__()')
|
|
148
|
+
output.end_statement()
|
|
149
|
+
output.indent(), output.print('try'), output.space()
|
|
150
|
+
output.with_block(def():
|
|
151
|
+
output.indent()
|
|
152
|
+
self._do_print_body(output)
|
|
153
|
+
output.newline()
|
|
154
|
+
)
|
|
155
|
+
output.space(), output.print('catch(e)')
|
|
156
|
+
output.with_block(def():
|
|
157
|
+
output.indent(), output.assign('ρσ_with_exception'), output.print('e'), output.end_statement()
|
|
158
|
+
)
|
|
159
|
+
output.newline(), output.indent(), output.spaced('if', '(ρσ_with_exception', '===', 'undefined)')
|
|
160
|
+
output.with_block(def():
|
|
161
|
+
for clause in exits:
|
|
162
|
+
output.indent(), output.print(clause + '.__exit__()'), output.end_statement()
|
|
163
|
+
)
|
|
164
|
+
output.space(), output.print('else'), output.space()
|
|
165
|
+
output.with_block(def():
|
|
166
|
+
output.indent(), output.assign('ρσ_with_suppress'), output.print('false'), output.end_statement()
|
|
167
|
+
for clause in exits:
|
|
168
|
+
output.indent()
|
|
169
|
+
output.spaced('ρσ_with_suppress', '|=', 'ρσ_bool(' + clause + '.__exit__(ρσ_with_exception.constructor,',
|
|
170
|
+
'ρσ_with_exception,', 'ρσ_with_exception.stack))')
|
|
171
|
+
output.end_statement()
|
|
172
|
+
output.indent(), output.spaced('if', '(!ρσ_with_suppress)', 'throw ρσ_with_exception'), output.end_statement()
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
def print_assert(self, output):
|
|
176
|
+
if output.options.discard_asserts:
|
|
177
|
+
return
|
|
178
|
+
output.spaced('if', '(!('), self.condition.print(output), output.spaced('))', 'throw new AssertionError')
|
|
179
|
+
if self.message:
|
|
180
|
+
output.print('(')
|
|
181
|
+
self.message.print(output)
|
|
182
|
+
output.print(')')
|
|
183
|
+
output.end_statement()
|
|
184
|
+
|
|
185
|
+
# ---- Match/case code generation ----
|
|
186
|
+
|
|
187
|
+
def _match_is_always_true(pattern):
|
|
188
|
+
"""Return True if this pattern always succeeds (no structural check needed)."""
|
|
189
|
+
return (is_node_type(pattern, AST_MatchWildcard) or
|
|
190
|
+
is_node_type(pattern, AST_MatchCapture) or
|
|
191
|
+
(is_node_type(pattern, AST_MatchAs) and not pattern.pattern))
|
|
192
|
+
|
|
193
|
+
def _match_write_cond(pattern, subj, output):
|
|
194
|
+
"""Write the JS condition expression for a pattern to the output stream."""
|
|
195
|
+
if is_node_type(pattern, AST_MatchWildcard) or is_node_type(pattern, AST_MatchCapture):
|
|
196
|
+
output.print('true')
|
|
197
|
+
|
|
198
|
+
elif is_node_type(pattern, AST_MatchLiteral):
|
|
199
|
+
output.print(subj + ' === ')
|
|
200
|
+
pattern.value.print(output)
|
|
201
|
+
|
|
202
|
+
elif is_node_type(pattern, AST_MatchOr):
|
|
203
|
+
for i, p in enumerate(pattern.patterns):
|
|
204
|
+
if i > 0:
|
|
205
|
+
output.print(' || ')
|
|
206
|
+
if not _match_is_always_true(p):
|
|
207
|
+
output.print('(')
|
|
208
|
+
_match_write_cond(p, subj, output)
|
|
209
|
+
output.print(')')
|
|
210
|
+
else:
|
|
211
|
+
output.print('true')
|
|
212
|
+
|
|
213
|
+
elif is_node_type(pattern, AST_MatchAs):
|
|
214
|
+
if pattern.pattern and not is_node_type(pattern.pattern, AST_MatchWildcard):
|
|
215
|
+
_match_write_cond(pattern.pattern, subj, output)
|
|
216
|
+
else:
|
|
217
|
+
output.print('true')
|
|
218
|
+
|
|
219
|
+
elif is_node_type(pattern, AST_MatchSequence):
|
|
220
|
+
_match_write_seq_cond(pattern, subj, output)
|
|
221
|
+
|
|
222
|
+
elif is_node_type(pattern, AST_MatchMapping):
|
|
223
|
+
_match_write_map_cond(pattern, subj, output)
|
|
224
|
+
|
|
225
|
+
elif is_node_type(pattern, AST_MatchClass):
|
|
226
|
+
_match_write_class_cond(pattern, subj, output)
|
|
227
|
+
|
|
228
|
+
else:
|
|
229
|
+
output.print('true')
|
|
230
|
+
|
|
231
|
+
def _match_write_seq_cond(pattern, subj, output):
|
|
232
|
+
has_star = False
|
|
233
|
+
for e in pattern.elements:
|
|
234
|
+
if is_node_type(e, AST_MatchStar):
|
|
235
|
+
has_star = True
|
|
236
|
+
break
|
|
237
|
+
n = pattern.elements.length
|
|
238
|
+
n_non_star = n - (1 if has_star else 0)
|
|
239
|
+
|
|
240
|
+
output.print('Array.isArray(' + subj + ')')
|
|
241
|
+
if has_star:
|
|
242
|
+
output.print(' && ' + subj + '.length >= ' + str(n_non_star))
|
|
243
|
+
else:
|
|
244
|
+
output.print(' && ' + subj + '.length === ' + str(n))
|
|
245
|
+
|
|
246
|
+
# Add sub-conditions for complex element patterns
|
|
247
|
+
star_idx = -1
|
|
248
|
+
for i, e in enumerate(pattern.elements):
|
|
249
|
+
if is_node_type(e, AST_MatchStar):
|
|
250
|
+
star_idx = i
|
|
251
|
+
continue
|
|
252
|
+
if not _match_is_always_true(e):
|
|
253
|
+
if star_idx >= 0 and i > star_idx:
|
|
254
|
+
elem_var = subj + '[' + subj + '.length - ' + str(n - i) + ']'
|
|
255
|
+
else:
|
|
256
|
+
elem_var = subj + '[' + str(i) + ']'
|
|
257
|
+
output.print(' && (')
|
|
258
|
+
_match_write_cond(e, elem_var, output)
|
|
259
|
+
output.print(')')
|
|
260
|
+
|
|
261
|
+
def _match_write_map_cond(pattern, subj, output):
|
|
262
|
+
output.print('(' + subj + ' !== null && ' + subj + ' !== undefined && typeof ' + subj + ' === \'object\')')
|
|
263
|
+
for i, key in enumerate(pattern.keys):
|
|
264
|
+
output.print(' && (')
|
|
265
|
+
key.print(output)
|
|
266
|
+
output.print(' in ' + subj + ')')
|
|
267
|
+
# Sub-condition for non-trivial value patterns
|
|
268
|
+
if not _match_is_always_true(pattern.values[i]):
|
|
269
|
+
val_var = subj + '[' + _key_to_js_str(key) + ']'
|
|
270
|
+
output.print(' && (')
|
|
271
|
+
_match_write_cond(pattern.values[i], val_var, output)
|
|
272
|
+
output.print(')')
|
|
273
|
+
|
|
274
|
+
def _key_to_js_str(key_node):
|
|
275
|
+
"""Return a JS expression string for a mapping key AST node."""
|
|
276
|
+
# For simple string and number literals we can produce the literal inline
|
|
277
|
+
from ast import AST_String, AST_Number, AST_True, AST_False, AST_Null
|
|
278
|
+
if is_node_type(key_node, AST_String):
|
|
279
|
+
return JSON.stringify(key_node.value)
|
|
280
|
+
elif is_node_type(key_node, AST_Number):
|
|
281
|
+
return str(key_node.value)
|
|
282
|
+
elif is_node_type(key_node, AST_True):
|
|
283
|
+
return 'true'
|
|
284
|
+
elif is_node_type(key_node, AST_False):
|
|
285
|
+
return 'false'
|
|
286
|
+
elif is_node_type(key_node, AST_Null):
|
|
287
|
+
return 'null'
|
|
288
|
+
return '"__key__"'
|
|
289
|
+
|
|
290
|
+
def _match_write_class_cond(pattern, subj, output):
|
|
291
|
+
output.print('(' + subj + ' instanceof ')
|
|
292
|
+
pattern.cls.print(output)
|
|
293
|
+
output.print(')')
|
|
294
|
+
# Keyword patterns: check literal sub-patterns
|
|
295
|
+
for i, kname in enumerate(pattern.keys):
|
|
296
|
+
vpat = pattern.values[i]
|
|
297
|
+
if is_node_type(vpat, AST_MatchLiteral):
|
|
298
|
+
output.print(' && ' + subj + '.' + kname + ' === ')
|
|
299
|
+
vpat.value.print(output)
|
|
300
|
+
elif not _match_is_always_true(vpat):
|
|
301
|
+
attr_var = subj + '.' + kname
|
|
302
|
+
output.print(' && (')
|
|
303
|
+
_match_write_cond(vpat, attr_var, output)
|
|
304
|
+
output.print(')')
|
|
305
|
+
# Positional patterns: check literal sub-patterns via __match_args__
|
|
306
|
+
for i, ppat in enumerate(pattern.positional):
|
|
307
|
+
if is_node_type(ppat, AST_MatchLiteral):
|
|
308
|
+
output.print(' && ' + subj + '[' + subj + '.constructor.__match_args__[' + str(i) + ']] === ')
|
|
309
|
+
ppat.value.print(output)
|
|
310
|
+
elif not _match_is_always_true(ppat):
|
|
311
|
+
pos_var = subj + '[' + subj + '.constructor.__match_args__[' + str(i) + ']]'
|
|
312
|
+
output.print(' && (')
|
|
313
|
+
_match_write_cond(ppat, pos_var, output)
|
|
314
|
+
output.print(')')
|
|
315
|
+
|
|
316
|
+
def _match_write_bindings(pattern, subj, output):
|
|
317
|
+
"""Write JS assignment statements for all captures in a pattern."""
|
|
318
|
+
if is_node_type(pattern, AST_MatchCapture):
|
|
319
|
+
output.indent()
|
|
320
|
+
output.print(pattern.name + ' = ' + subj)
|
|
321
|
+
output.end_statement()
|
|
322
|
+
|
|
323
|
+
elif is_node_type(pattern, AST_MatchAs):
|
|
324
|
+
if pattern.pattern and not is_node_type(pattern.pattern, AST_MatchWildcard):
|
|
325
|
+
_match_write_bindings(pattern.pattern, subj, output)
|
|
326
|
+
if pattern.name:
|
|
327
|
+
output.indent()
|
|
328
|
+
output.print(pattern.name + ' = ' + subj)
|
|
329
|
+
output.end_statement()
|
|
330
|
+
|
|
331
|
+
elif is_node_type(pattern, AST_MatchOr):
|
|
332
|
+
# Bindings from first alternative (all must bind the same names per Python spec)
|
|
333
|
+
if pattern.patterns.length:
|
|
334
|
+
_match_write_bindings(pattern.patterns[0], subj, output)
|
|
335
|
+
|
|
336
|
+
elif is_node_type(pattern, AST_MatchSequence):
|
|
337
|
+
star_idx = -1
|
|
338
|
+
n = pattern.elements.length
|
|
339
|
+
for i, e in enumerate(pattern.elements):
|
|
340
|
+
if is_node_type(e, AST_MatchStar):
|
|
341
|
+
star_idx = i
|
|
342
|
+
break
|
|
343
|
+
for i, e in enumerate(pattern.elements):
|
|
344
|
+
if is_node_type(e, AST_MatchStar):
|
|
345
|
+
if e.name:
|
|
346
|
+
before = i
|
|
347
|
+
after = n - i - 1
|
|
348
|
+
output.indent()
|
|
349
|
+
if after > 0:
|
|
350
|
+
output.print(e.name + ' = ' + subj + '.slice(' + str(before) + ', ' + subj + '.length - ' + str(after) + ')')
|
|
351
|
+
else:
|
|
352
|
+
output.print(e.name + ' = ' + subj + '.slice(' + str(before) + ')')
|
|
353
|
+
output.end_statement()
|
|
354
|
+
else:
|
|
355
|
+
if star_idx >= 0 and i > star_idx:
|
|
356
|
+
elem_var = subj + '[' + subj + '.length - ' + str(n - i) + ']'
|
|
357
|
+
else:
|
|
358
|
+
elem_var = subj + '[' + str(i) + ']'
|
|
359
|
+
_match_write_bindings(e, elem_var, output)
|
|
360
|
+
|
|
361
|
+
elif is_node_type(pattern, AST_MatchMapping):
|
|
362
|
+
for i, key in enumerate(pattern.keys):
|
|
363
|
+
val_var = subj + '[' + _key_to_js_str(key) + ']'
|
|
364
|
+
_match_write_bindings(pattern.values[i], val_var, output)
|
|
365
|
+
if pattern.rest_name:
|
|
366
|
+
# Build rest object excluding matched keys
|
|
367
|
+
key_strs = [_key_to_js_str(k) for k in pattern.keys]
|
|
368
|
+
output.indent()
|
|
369
|
+
output.print(pattern.rest_name + ' = (function() { var ρσ_rest = {}; for (var ρσ_k in ' + subj + ') { if ([' + key_strs.join(', ') + '].indexOf(ρσ_k) < 0) ρσ_rest[ρσ_k] = ' + subj + '[ρσ_k]; } return ρσ_rest; })()')
|
|
370
|
+
output.end_statement()
|
|
371
|
+
|
|
372
|
+
elif is_node_type(pattern, AST_MatchClass):
|
|
373
|
+
# Positional patterns via __match_args__
|
|
374
|
+
for i, ppat in enumerate(pattern.positional):
|
|
375
|
+
pos_var = subj + '[' + subj + '.constructor.__match_args__[' + str(i) + ']]'
|
|
376
|
+
_match_write_bindings(ppat, pos_var, output)
|
|
377
|
+
# Keyword patterns
|
|
378
|
+
for i, kname in enumerate(pattern.keys):
|
|
379
|
+
attr_var = subj + '.' + kname
|
|
380
|
+
_match_write_bindings(pattern.values[i], attr_var, output)
|
|
381
|
+
|
|
382
|
+
def print_match(self, output):
|
|
383
|
+
output.match_counter += 1
|
|
384
|
+
n = output.match_counter
|
|
385
|
+
subj_var = 'ρσ_match_subject_' + n
|
|
386
|
+
label = 'ρσ_match_' + n
|
|
387
|
+
|
|
388
|
+
# var ρσ_match_subject_N = <subject>;
|
|
389
|
+
output.indent()
|
|
390
|
+
output.print('var ' + subj_var + ' = ')
|
|
391
|
+
self.subject.print(output)
|
|
392
|
+
output.end_statement()
|
|
393
|
+
|
|
394
|
+
# ρσ_match_N: do { ... } while (false);
|
|
395
|
+
output.newline()
|
|
396
|
+
output.indent()
|
|
397
|
+
output.print(label + ': do')
|
|
398
|
+
output.space()
|
|
399
|
+
output.with_block(def():
|
|
400
|
+
for mcase in self.cases:
|
|
401
|
+
always = _match_is_always_true(mcase.pattern)
|
|
402
|
+
|
|
403
|
+
if always:
|
|
404
|
+
# No structural if-check needed
|
|
405
|
+
output.indent()
|
|
406
|
+
_match_write_bindings(mcase.pattern, subj_var, output)
|
|
407
|
+
if mcase.guard:
|
|
408
|
+
output.indent()
|
|
409
|
+
output.print('if (')
|
|
410
|
+
mcase.guard.print(output)
|
|
411
|
+
output.print(')')
|
|
412
|
+
output.space()
|
|
413
|
+
output.with_block(def():
|
|
414
|
+
_match_print_body(mcase.body, label, output)
|
|
415
|
+
)
|
|
416
|
+
output.newline()
|
|
417
|
+
else:
|
|
418
|
+
_match_print_body(mcase.body, label, output)
|
|
419
|
+
else:
|
|
420
|
+
output.indent()
|
|
421
|
+
output.print('if (')
|
|
422
|
+
_match_write_cond(mcase.pattern, subj_var, output)
|
|
423
|
+
output.print(')')
|
|
424
|
+
output.space()
|
|
425
|
+
output.with_block(def():
|
|
426
|
+
_match_write_bindings(mcase.pattern, subj_var, output)
|
|
427
|
+
if mcase.guard:
|
|
428
|
+
output.indent()
|
|
429
|
+
output.print('if (')
|
|
430
|
+
mcase.guard.print(output)
|
|
431
|
+
output.print(')')
|
|
432
|
+
output.space()
|
|
433
|
+
output.with_block(def():
|
|
434
|
+
_match_print_body(mcase.body, label, output)
|
|
435
|
+
)
|
|
436
|
+
output.newline()
|
|
437
|
+
else:
|
|
438
|
+
_match_print_body(mcase.body, label, output)
|
|
439
|
+
)
|
|
440
|
+
output.newline()
|
|
441
|
+
)
|
|
442
|
+
output.spaced('while', '(false)')
|
|
443
|
+
output.end_statement()
|
|
444
|
+
|
|
445
|
+
def _match_print_body(body, label, output):
|
|
446
|
+
"""Print the statements of a case body, followed by break <label>."""
|
|
447
|
+
stmts = body.body if is_node_type(body, AST_BlockStatement) else [body]
|
|
448
|
+
display_body(stmts, False, output)
|
|
449
|
+
output.indent()
|
|
450
|
+
output.print('break ' + label)
|
|
451
|
+
output.end_statement()
|
|
452
|
+
|
|
453
|
+
def print_annotated_assign(self, output):
|
|
454
|
+
# Variable type annotation: `x: int = value` or `x: int` (annotation only).
|
|
455
|
+
# The annotation is erased in the JavaScript output; only the assignment is emitted.
|
|
456
|
+
if self.value is not None:
|
|
457
|
+
self.target.print(output)
|
|
458
|
+
output.space()
|
|
459
|
+
output.print('=')
|
|
460
|
+
output.space()
|
|
461
|
+
self.value.print(output)
|
|
462
|
+
output.semicolon()
|
|
463
|
+
# annotation-only (no value) emits nothing
|