rapydscript-ns 0.8.3 → 0.9.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/CHANGELOG.md +26 -0
- package/README.md +1351 -141
- package/TODO.md +12 -6
- package/language-service/index.js +184 -26
- package/package.json +1 -1
- package/release/baselib-plain-pretty.js +5895 -1928
- package/release/baselib-plain-ugly.js +140 -3
- package/release/compiler.js +16282 -5408
- package/release/signatures.json +25 -22
- package/src/ast.pyj +94 -1
- package/src/baselib-builtins.pyj +362 -3
- package/src/baselib-bytes.pyj +664 -0
- package/src/baselib-containers.pyj +99 -0
- package/src/baselib-errors.pyj +45 -1
- package/src/baselib-internal.pyj +346 -49
- package/src/baselib-itertools.pyj +17 -4
- package/src/baselib-str.pyj +46 -4
- package/src/lib/abc.pyj +317 -0
- package/src/lib/copy.pyj +120 -0
- package/src/lib/dataclasses.pyj +532 -0
- package/src/lib/enum.pyj +125 -0
- package/src/lib/pythonize.pyj +1 -1
- package/src/lib/re.pyj +35 -1
- package/src/lib/react.pyj +74 -0
- package/src/lib/typing.pyj +577 -0
- package/src/monaco-language-service/builtins.js +19 -4
- package/src/monaco-language-service/diagnostics.js +40 -19
- package/src/output/classes.pyj +161 -25
- package/src/output/codegen.pyj +16 -2
- package/src/output/exceptions.pyj +97 -1
- package/src/output/functions.pyj +87 -5
- package/src/output/jsx.pyj +164 -0
- package/src/output/literals.pyj +28 -2
- package/src/output/loops.pyj +5 -2
- package/src/output/modules.pyj +1 -1
- package/src/output/operators.pyj +108 -36
- package/src/output/statements.pyj +2 -2
- package/src/output/stream.pyj +1 -0
- package/src/parse.pyj +496 -128
- package/src/tokenizer.pyj +38 -4
- package/test/abc.pyj +291 -0
- package/test/arithmetic_nostrict.pyj +88 -0
- package/test/arithmetic_types.pyj +169 -0
- package/test/baselib.pyj +91 -0
- package/test/bytes.pyj +467 -0
- package/test/classes.pyj +1 -0
- package/test/comparison_ops.pyj +173 -0
- package/test/dataclasses.pyj +253 -0
- package/test/enum.pyj +134 -0
- package/test/eval_exec.pyj +56 -0
- package/test/format.pyj +148 -0
- package/test/object.pyj +64 -0
- package/test/python_compat.pyj +17 -15
- package/test/python_features.pyj +89 -21
- package/test/regexp.pyj +29 -1
- package/test/tuples.pyj +96 -0
- package/test/typing.pyj +469 -0
- package/test/unit/index.js +2292 -70
- package/test/unit/language-service.js +674 -4
- package/test/unit/web-repl.js +1106 -0
- package/test/vars_locals_globals.pyj +94 -0
- package/tools/cli.js +11 -0
- package/tools/compile.js +5 -0
- package/tools/embedded_compiler.js +15 -4
- package/tools/lint.js +16 -19
- package/tools/repl.js +1 -1
- package/web-repl/env.js +122 -0
- package/web-repl/main.js +1 -3
- package/web-repl/rapydscript.js +125 -3
- package/PYTHON_DIFFERENCES_REPORT.md +0 -291
- package/PYTHON_FEATURE_COVERAGE.md +0 -200
- package/hack_demo.pyj +0 -112
|
@@ -0,0 +1,164 @@
|
|
|
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 AST_String, AST_JSXText, AST_JSXSpread, AST_JSXExprContainer, is_node_type
|
|
6
|
+
|
|
7
|
+
def _is_component_tag(tag):
|
|
8
|
+
# Components start with uppercase or use dot notation (e.g. Router.Route)
|
|
9
|
+
first = tag[0]
|
|
10
|
+
return (first >= 'A' and first <= 'Z') or '.' in tag
|
|
11
|
+
|
|
12
|
+
def _needs_quoting(name):
|
|
13
|
+
# Attribute names containing non-identifier chars (e.g. aria-label) need quoting
|
|
14
|
+
return not v'/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)'
|
|
15
|
+
|
|
16
|
+
def _decode_html_entities(text):
|
|
17
|
+
# Decode HTML entities in a single pass to avoid double-decoding (e.g. &lt; -> <)
|
|
18
|
+
return text.replace(/&(?:#x([0-9a-fA-F]+)|#(\d+)|([a-zA-Z]+));/g, def(match, hex, dec, name):
|
|
19
|
+
if hex:
|
|
20
|
+
return String.fromCharCode(parseInt(hex, 16))
|
|
21
|
+
if dec:
|
|
22
|
+
return String.fromCharCode(parseInt(dec, 10))
|
|
23
|
+
if name is 'amp':
|
|
24
|
+
return '&'
|
|
25
|
+
if name is 'lt':
|
|
26
|
+
return '<'
|
|
27
|
+
if name is 'gt':
|
|
28
|
+
return '>'
|
|
29
|
+
if name is 'quot':
|
|
30
|
+
return '"'
|
|
31
|
+
if name is 'apos':
|
|
32
|
+
return "'"
|
|
33
|
+
if name is 'nbsp':
|
|
34
|
+
return '\u00a0'
|
|
35
|
+
return match
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def _normalize_jsx_whitespace(text):
|
|
39
|
+
# Implements the Babel JSX whitespace algorithm:
|
|
40
|
+
# - Split by newlines; trim leading whitespace from all lines except the first,
|
|
41
|
+
# trailing whitespace from all lines except the last.
|
|
42
|
+
# - Lines that are empty after trimming are dropped.
|
|
43
|
+
# - Remaining non-empty lines are joined; each line except the last non-empty
|
|
44
|
+
# gets a trailing space to separate it from the next.
|
|
45
|
+
lines = text.split('\n')
|
|
46
|
+
last_non_empty = -1
|
|
47
|
+
for i in range(lines.length):
|
|
48
|
+
if /[^ \t]/.test(lines[i]):
|
|
49
|
+
last_non_empty = i
|
|
50
|
+
result = ''
|
|
51
|
+
for i in range(lines.length):
|
|
52
|
+
line = lines[i].replace(/\t/g, ' ')
|
|
53
|
+
is_first = (i is 0)
|
|
54
|
+
is_last = (i is lines.length - 1)
|
|
55
|
+
if not is_first:
|
|
56
|
+
line = line.replace(/^[ ]+/, '')
|
|
57
|
+
if not is_last:
|
|
58
|
+
line = line.replace(/[ ]+$/, '')
|
|
59
|
+
if line:
|
|
60
|
+
if i is not last_non_empty:
|
|
61
|
+
line += ' '
|
|
62
|
+
result += line
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
def _process_jsx_text(text):
|
|
66
|
+
text = _normalize_jsx_whitespace(text)
|
|
67
|
+
if text:
|
|
68
|
+
text = _decode_html_entities(text)
|
|
69
|
+
return text
|
|
70
|
+
|
|
71
|
+
def _print_tag(tag, output):
|
|
72
|
+
if _is_component_tag(tag):
|
|
73
|
+
output.print(tag)
|
|
74
|
+
else:
|
|
75
|
+
output.print('"')
|
|
76
|
+
output.print(tag)
|
|
77
|
+
output.print('"')
|
|
78
|
+
|
|
79
|
+
def _print_props(props, output):
|
|
80
|
+
if not props or not props.length:
|
|
81
|
+
output.print('null')
|
|
82
|
+
return
|
|
83
|
+
output.print('{')
|
|
84
|
+
first = True
|
|
85
|
+
for prop in props:
|
|
86
|
+
if not first:
|
|
87
|
+
output.print(', ')
|
|
88
|
+
first = False
|
|
89
|
+
if is_node_type(prop, AST_JSXSpread):
|
|
90
|
+
output.print('...')
|
|
91
|
+
prop.expression.print(output)
|
|
92
|
+
else:
|
|
93
|
+
if _needs_quoting(prop.name):
|
|
94
|
+
output.print('"')
|
|
95
|
+
output.print(prop.name)
|
|
96
|
+
output.print('"')
|
|
97
|
+
else:
|
|
98
|
+
output.print(prop.name)
|
|
99
|
+
output.print(': ')
|
|
100
|
+
if prop.value is None:
|
|
101
|
+
output.print('true')
|
|
102
|
+
elif is_node_type(prop.value, AST_String):
|
|
103
|
+
output.print_string(prop.value.value)
|
|
104
|
+
else:
|
|
105
|
+
prop.value.print(output)
|
|
106
|
+
output.print('}')
|
|
107
|
+
|
|
108
|
+
def _print_children(children, output):
|
|
109
|
+
for child in children:
|
|
110
|
+
if is_node_type(child, AST_JSXText):
|
|
111
|
+
text = _process_jsx_text(child.value)
|
|
112
|
+
if text:
|
|
113
|
+
output.print(', ')
|
|
114
|
+
output.print_string(text)
|
|
115
|
+
elif is_node_type(child, AST_JSXExprContainer):
|
|
116
|
+
output.print(', ')
|
|
117
|
+
child.expression.print(output)
|
|
118
|
+
else:
|
|
119
|
+
output.print(', ')
|
|
120
|
+
child.print(output)
|
|
121
|
+
|
|
122
|
+
def print_jsx_element(self, output):
|
|
123
|
+
output.print('React.createElement(')
|
|
124
|
+
_print_tag(self.tag, output)
|
|
125
|
+
output.print(', ')
|
|
126
|
+
_print_props(self.props, output)
|
|
127
|
+
if not self.self_closing:
|
|
128
|
+
_print_children(self.children, output)
|
|
129
|
+
output.print(')')
|
|
130
|
+
|
|
131
|
+
def print_jsx_fragment(self, output):
|
|
132
|
+
output.print('React.createElement(React.Fragment, null')
|
|
133
|
+
_print_children(self.children, output)
|
|
134
|
+
output.print(')')
|
|
135
|
+
|
|
136
|
+
def print_jsx_attribute(self, output):
|
|
137
|
+
# Handled directly by _print_props; kept for completeness
|
|
138
|
+
if _needs_quoting(self.name):
|
|
139
|
+
output.print('"')
|
|
140
|
+
output.print(self.name)
|
|
141
|
+
output.print('"')
|
|
142
|
+
else:
|
|
143
|
+
output.print(self.name)
|
|
144
|
+
if self.value is not None:
|
|
145
|
+
output.print(': ')
|
|
146
|
+
if is_node_type(self.value, AST_String):
|
|
147
|
+
output.print_string(self.value.value)
|
|
148
|
+
else:
|
|
149
|
+
self.value.print(output)
|
|
150
|
+
|
|
151
|
+
def print_jsx_spread(self, output):
|
|
152
|
+
# Handled directly by _print_props; kept for completeness
|
|
153
|
+
output.print('...')
|
|
154
|
+
self.expression.print(output)
|
|
155
|
+
|
|
156
|
+
def print_jsx_text(self, output):
|
|
157
|
+
# Handled directly by _print_children; kept for completeness
|
|
158
|
+
text = _process_jsx_text(self.value)
|
|
159
|
+
if text:
|
|
160
|
+
output.print_string(text)
|
|
161
|
+
|
|
162
|
+
def print_jsx_expr_container(self, output):
|
|
163
|
+
# Handled directly by _print_children; kept for completeness
|
|
164
|
+
self.expression.print(output)
|
package/src/output/literals.pyj
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
|
3
3
|
from __python__ import hash_literals
|
|
4
4
|
|
|
5
|
-
from ast import AST_Binary, AST_ObjectSpread, is_node_type
|
|
5
|
+
from ast import AST_Binary, AST_ObjectSpread, AST_Spread, AST_SetItem, is_node_type
|
|
6
6
|
|
|
7
7
|
def print_array(self, output):
|
|
8
8
|
output.print('ρσ_list_decorate')
|
|
@@ -15,7 +15,11 @@ def print_array(self, output):
|
|
|
15
15
|
for i, exp in enumerate(a):
|
|
16
16
|
if i:
|
|
17
17
|
output.comma()
|
|
18
|
-
exp
|
|
18
|
+
if is_node_type(exp, AST_Spread):
|
|
19
|
+
output.print('...')
|
|
20
|
+
exp.expression.print(output)
|
|
21
|
+
else:
|
|
22
|
+
exp.print(output)
|
|
19
23
|
if len_ > 0:
|
|
20
24
|
output.space()
|
|
21
25
|
)
|
|
@@ -78,6 +82,28 @@ def print_object(self, output):
|
|
|
78
82
|
output.print("Object.create(null)" if self.is_jshash else '{}')
|
|
79
83
|
|
|
80
84
|
def print_set(self, output):
|
|
85
|
+
# Check for spread items: {*a, 1, 2, *b}
|
|
86
|
+
has_spread = False
|
|
87
|
+
for item in self.items:
|
|
88
|
+
if is_node_type(item, AST_Spread):
|
|
89
|
+
has_spread = True
|
|
90
|
+
break
|
|
91
|
+
if has_spread:
|
|
92
|
+
# Compile as ρσ_set([...a, 1, 2, ...b])
|
|
93
|
+
output.print('ρσ_set')
|
|
94
|
+
output.with_parens(def():
|
|
95
|
+
output.with_square(def():
|
|
96
|
+
for i, item in enumerate(self.items):
|
|
97
|
+
if i:
|
|
98
|
+
output.comma()
|
|
99
|
+
if is_node_type(item, AST_Spread):
|
|
100
|
+
output.print('...')
|
|
101
|
+
item.expression.print(output)
|
|
102
|
+
else:
|
|
103
|
+
item.value.print(output)
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
return
|
|
81
107
|
if self.items.length is 0:
|
|
82
108
|
output.print('ρσ_set()')
|
|
83
109
|
return
|
package/src/output/loops.pyj
CHANGED
|
@@ -456,10 +456,13 @@ def print_list_comprehension(self, output):
|
|
|
456
456
|
body_out.print(result_obj)
|
|
457
457
|
# Locally scope all loop variables (outer and inner clauses)
|
|
458
458
|
def decl_loop_vars(init_node):
|
|
459
|
+
# Recursively declare all leaf variable names from nested tuples/seqs
|
|
459
460
|
if is_node_type(init_node, AST_Array):
|
|
460
461
|
for i in init_node.elements:
|
|
461
|
-
|
|
462
|
-
|
|
462
|
+
decl_loop_vars(i)
|
|
463
|
+
elif is_node_type(init_node, AST_Seq):
|
|
464
|
+
for i in init_node.to_array():
|
|
465
|
+
decl_loop_vars(i)
|
|
463
466
|
else:
|
|
464
467
|
body_out.comma()
|
|
465
468
|
init_node.print(body_out)
|
package/src/output/modules.pyj
CHANGED
|
@@ -183,7 +183,7 @@ def print_top_level(self, output):
|
|
|
183
183
|
write_imports(self, output)
|
|
184
184
|
write_main_name(output)
|
|
185
185
|
|
|
186
|
-
declare_vars(self.localvars, output)
|
|
186
|
+
declare_vars(self.localvars, output, "var" if output.options.repl_mode else "let")
|
|
187
187
|
display_body(self.body, True, output)
|
|
188
188
|
if self.comments_after and self.comments_after.length:
|
|
189
189
|
output_comments(self.comments_after, output)
|
package/src/output/operators.pyj
CHANGED
|
@@ -5,7 +5,7 @@ from ast import (
|
|
|
5
5
|
AST_Array, AST_Assign, AST_BaseCall, AST_Binary, AST_Conditional,
|
|
6
6
|
AST_ItemAccess, AST_NamedExpr, AST_Number, AST_Object, AST_Return, AST_Seq, AST_Set,
|
|
7
7
|
AST_SimpleStatement, AST_Statement, AST_String, AST_Sub, AST_Symbol,
|
|
8
|
-
AST_SymbolRef, AST_Starred, AST_Unary, is_node_type
|
|
8
|
+
AST_SymbolRef, AST_Starred, AST_Unary, AST_AnnotatedAssign, is_node_type
|
|
9
9
|
)
|
|
10
10
|
from output.loops import unpack_tuple
|
|
11
11
|
|
|
@@ -13,6 +13,11 @@ from output.loops import unpack_tuple
|
|
|
13
13
|
def print_getattr(self, output, skip_expression): # AST_Dot
|
|
14
14
|
if not skip_expression:
|
|
15
15
|
expr = self.expression
|
|
16
|
+
# Redirect JSON.parse → ρσ_json_parse so RapydScript code gets dict-aware
|
|
17
|
+
# parsing without polluting the global JSON.parse for other JS on the page.
|
|
18
|
+
if is_node_type(expr, AST_SymbolRef) and expr.name == 'JSON' and self.property == 'parse':
|
|
19
|
+
output.print('ρσ_json_parse')
|
|
20
|
+
return
|
|
16
21
|
expr.print(output)
|
|
17
22
|
if is_node_type(expr, AST_Number) and expr.value >= 0:
|
|
18
23
|
if not /[xa-f.]/i.test(output.last()):
|
|
@@ -38,7 +43,7 @@ def print_getitem(self, output): # AST_Sub
|
|
|
38
43
|
expr.print(output)
|
|
39
44
|
output.print('['), prop.print(output), output.print(']')
|
|
40
45
|
return
|
|
41
|
-
is_negative_number = is_node_type(prop, AST_Unary) and prop.operator is "-" and is_node_type(prop.expression, AST_Number)
|
|
46
|
+
is_negative_number = is_node_type(prop, AST_Unary) and prop.operator is "-" and is_node_type(prop.expression, AST_Number) and not prop.overloaded
|
|
42
47
|
is_repeatable = is_node_type(expr, AST_SymbolRef)
|
|
43
48
|
if is_repeatable:
|
|
44
49
|
expr.print(output)
|
|
@@ -182,7 +187,7 @@ function_ops = {
|
|
|
182
187
|
'nin': '!ρσ_in',
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
# Maps binary operators to their overloading helper function names.
|
|
190
|
+
# Maps binary operators to their overloading helper function names (strict_arithmetic on).
|
|
186
191
|
overloaded_binary_ops = {
|
|
187
192
|
'+': 'ρσ_op_add',
|
|
188
193
|
'-': 'ρσ_op_sub',
|
|
@@ -196,9 +201,34 @@ overloaded_binary_ops = {
|
|
|
196
201
|
'^': 'ρσ_op_xor',
|
|
197
202
|
'<<': 'ρσ_op_lshift',
|
|
198
203
|
'>>': 'ρσ_op_rshift',
|
|
204
|
+
'<': 'ρσ_op_lt',
|
|
205
|
+
'>': 'ρσ_op_gt',
|
|
206
|
+
'<=': 'ρσ_op_le',
|
|
207
|
+
'>=': 'ρσ_op_ge',
|
|
199
208
|
}
|
|
200
209
|
|
|
201
|
-
# Maps
|
|
210
|
+
# Maps binary operators to no-strict helpers (overload_operators on, strict_arithmetic off).
|
|
211
|
+
# Operators that never threw TypeError reuse the same helper; others use _ns variants.
|
|
212
|
+
overloaded_binary_ops_ns = {
|
|
213
|
+
'+': 'ρσ_op_add_ns',
|
|
214
|
+
'-': 'ρσ_op_sub_ns',
|
|
215
|
+
'*': 'ρσ_op_mul_ns',
|
|
216
|
+
'/': 'ρσ_op_truediv_ns',
|
|
217
|
+
'//': 'ρσ_op_floordiv_ns',
|
|
218
|
+
'%': 'ρσ_op_mod_ns',
|
|
219
|
+
'**': 'ρσ_op_pow_ns',
|
|
220
|
+
'&': 'ρσ_op_and',
|
|
221
|
+
'|': 'ρσ_op_or',
|
|
222
|
+
'^': 'ρσ_op_xor',
|
|
223
|
+
'<<': 'ρσ_op_lshift',
|
|
224
|
+
'>>': 'ρσ_op_rshift',
|
|
225
|
+
'<': 'ρσ_op_lt_ns',
|
|
226
|
+
'>': 'ρσ_op_gt_ns',
|
|
227
|
+
'<=': 'ρσ_op_le_ns',
|
|
228
|
+
'>=': 'ρσ_op_ge_ns',
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
# Maps augmented-assignment operators to their overloading helper names (strict_arithmetic on).
|
|
202
232
|
overloaded_augmented_ops = {
|
|
203
233
|
'+=': 'ρσ_op_iadd',
|
|
204
234
|
'-=': 'ρσ_op_isub',
|
|
@@ -214,10 +244,78 @@ overloaded_augmented_ops = {
|
|
|
214
244
|
'>>=': 'ρσ_op_irshift',
|
|
215
245
|
}
|
|
216
246
|
|
|
247
|
+
# Maps augmented-assignment operators to no-strict helpers (strict_arithmetic off).
|
|
248
|
+
overloaded_augmented_ops_ns = {
|
|
249
|
+
'+=': 'ρσ_op_iadd_ns',
|
|
250
|
+
'-=': 'ρσ_op_isub_ns',
|
|
251
|
+
'*=': 'ρσ_op_imul_ns',
|
|
252
|
+
'/=': 'ρσ_op_itruediv_ns',
|
|
253
|
+
'//=': 'ρσ_op_ifloordiv_ns',
|
|
254
|
+
'%=': 'ρσ_op_imod_ns',
|
|
255
|
+
'**=': 'ρσ_op_ipow_ns',
|
|
256
|
+
'&=': 'ρσ_op_iand',
|
|
257
|
+
'|=': 'ρσ_op_ior',
|
|
258
|
+
'^=': 'ρσ_op_ixor',
|
|
259
|
+
'<<=': 'ρσ_op_ilshift',
|
|
260
|
+
'>>=': 'ρσ_op_irshift',
|
|
261
|
+
}
|
|
262
|
+
|
|
217
263
|
|
|
218
264
|
def print_binary_op(self, output):
|
|
219
|
-
if self.
|
|
220
|
-
|
|
265
|
+
if comparators[self.operator] and is_node_type(self.left, AST_Binary) and comparators[self.left.operator]:
|
|
266
|
+
# A chained comparison such as a < b < c
|
|
267
|
+
# With overload_operators: ρσ_op_lt(a, b) && ρσ_op_lt(b, c)
|
|
268
|
+
# Without: a < b && b < c
|
|
269
|
+
if is_node_type(self.left.right, AST_Symbol):
|
|
270
|
+
# Middle is a simple variable — no caching needed.
|
|
271
|
+
# self.left.print recurses into print_binary_op and handles overloaded case.
|
|
272
|
+
self.left.print(output)
|
|
273
|
+
leftvar = self.left.right.name
|
|
274
|
+
else:
|
|
275
|
+
# Middle is a complex expression — must cache to avoid double evaluation.
|
|
276
|
+
left_ops_map = overloaded_binary_ops if self.left.strict_arith else overloaded_binary_ops_ns
|
|
277
|
+
if self.left.overloaded and left_ops_map[self.left.operator]:
|
|
278
|
+
output.print(left_ops_map[self.left.operator] + '(')
|
|
279
|
+
self.left.left.print(output)
|
|
280
|
+
output.comma()
|
|
281
|
+
output.with_parens(def():
|
|
282
|
+
nonlocal leftvar
|
|
283
|
+
output.assign("ρσ_cond_temp")
|
|
284
|
+
self.left.right.print(output)
|
|
285
|
+
leftvar = "ρσ_cond_temp"
|
|
286
|
+
)
|
|
287
|
+
output.print(')')
|
|
288
|
+
else:
|
|
289
|
+
self.left.left.print(output)
|
|
290
|
+
output.space()
|
|
291
|
+
output.print(self.left.operator)
|
|
292
|
+
output.space()
|
|
293
|
+
output.with_parens(def():
|
|
294
|
+
nonlocal leftvar
|
|
295
|
+
output.assign("ρσ_cond_temp")
|
|
296
|
+
self.left.right.print(output)
|
|
297
|
+
leftvar = "ρσ_cond_temp"
|
|
298
|
+
)
|
|
299
|
+
ops_map = overloaded_binary_ops if self.strict_arith else overloaded_binary_ops_ns
|
|
300
|
+
output.space()
|
|
301
|
+
output.print("&&")
|
|
302
|
+
output.space()
|
|
303
|
+
if self.overloaded and ops_map[self.operator]:
|
|
304
|
+
output.print(ops_map[self.operator] + '(')
|
|
305
|
+
output.print(leftvar)
|
|
306
|
+
output.comma()
|
|
307
|
+
self.right.print(output)
|
|
308
|
+
output.print(')')
|
|
309
|
+
else:
|
|
310
|
+
output.print(leftvar)
|
|
311
|
+
output.space()
|
|
312
|
+
output.print(self.operator)
|
|
313
|
+
output.space()
|
|
314
|
+
self.right.print(output)
|
|
315
|
+
return
|
|
316
|
+
ops_map = overloaded_binary_ops if self.strict_arith else overloaded_binary_ops_ns
|
|
317
|
+
if self.overloaded and ops_map[self.operator]:
|
|
318
|
+
output.print(ops_map[self.operator] + '(')
|
|
221
319
|
self.left.print(output)
|
|
222
320
|
output.comma()
|
|
223
321
|
self.right.print(output)
|
|
@@ -230,34 +328,6 @@ def print_binary_op(self, output):
|
|
|
230
328
|
output.comma()
|
|
231
329
|
self.right.print(output)
|
|
232
330
|
)
|
|
233
|
-
elif comparators[self.operator] and is_node_type(self.left, AST_Binary) and comparators[self.left.operator]:
|
|
234
|
-
# A chained comparison such as a < b < c
|
|
235
|
-
if is_node_type(self.left.right, AST_Symbol):
|
|
236
|
-
# left side compares against a regular variable,
|
|
237
|
-
# no caching needed
|
|
238
|
-
self.left.print(output)
|
|
239
|
-
leftvar = self.left.right.name
|
|
240
|
-
else:
|
|
241
|
-
# some logic is being performed, let's cache it
|
|
242
|
-
self.left.left.print(output)
|
|
243
|
-
output.space()
|
|
244
|
-
output.print(self.left.operator)
|
|
245
|
-
output.space()
|
|
246
|
-
output.with_parens(def():
|
|
247
|
-
nonlocal leftvar
|
|
248
|
-
output.assign("ρσ_cond_temp")
|
|
249
|
-
self.left.right.print(output)
|
|
250
|
-
leftvar = "ρσ_cond_temp"
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
output.space()
|
|
254
|
-
output.print("&&")
|
|
255
|
-
output.space()
|
|
256
|
-
output.print(leftvar)
|
|
257
|
-
output.space()
|
|
258
|
-
output.print(self.operator)
|
|
259
|
-
output.space()
|
|
260
|
-
self.right.print(output)
|
|
261
331
|
elif self.operator is '//':
|
|
262
332
|
output.print('Math.floor')
|
|
263
333
|
output.with_parens(def():
|
|
@@ -395,7 +465,8 @@ def print_assignment(self, output):
|
|
|
395
465
|
|
|
396
466
|
def print_assign(self, output):
|
|
397
467
|
if self.overloaded and overloaded_augmented_ops[self.operator]:
|
|
398
|
-
|
|
468
|
+
aug_map = overloaded_augmented_ops if self.strict_arith else overloaded_augmented_ops_ns
|
|
469
|
+
helper = aug_map[self.operator]
|
|
399
470
|
output.assign(self.left)
|
|
400
471
|
output.print(helper + '(')
|
|
401
472
|
self.left.print(output)
|
|
@@ -482,7 +553,8 @@ def print_seq(output):
|
|
|
482
553
|
or is_node_type(p, AST_Return)
|
|
483
554
|
or is_node_type(p, AST_Array)
|
|
484
555
|
or is_node_type(p, AST_BaseCall)
|
|
485
|
-
or is_node_type(p, AST_SimpleStatement)
|
|
556
|
+
or is_node_type(p, AST_SimpleStatement)
|
|
557
|
+
or is_node_type(p, AST_AnnotatedAssign):
|
|
486
558
|
output.with_square(print_seq)
|
|
487
559
|
else:
|
|
488
560
|
print_seq()
|
|
@@ -54,11 +54,11 @@ def first_in_statement(output):
|
|
|
54
54
|
return False
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def declare_vars(vars, output):
|
|
57
|
+
def declare_vars(vars, output, kind="var"):
|
|
58
58
|
# declare all variables as local, unless explictly set otherwise
|
|
59
59
|
if vars.length:
|
|
60
60
|
output.indent()
|
|
61
|
-
output.print(
|
|
61
|
+
output.print(kind)
|
|
62
62
|
output.space()
|
|
63
63
|
for i, arg in enumerate(vars):
|
|
64
64
|
if i:
|