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,429 @@
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
+ from __python__ import hash_literals
4
+ from ast import (
5
+ AST_Array, AST_Assign, AST_BaseCall, AST_Binary, AST_Conditional,
6
+ AST_ItemAccess, AST_NamedExpr, AST_Number, AST_Object, AST_Return, AST_Seq, AST_Set,
7
+ AST_SimpleStatement, AST_Statement, AST_String, AST_Sub, AST_Symbol,
8
+ AST_SymbolRef, AST_Starred, AST_Unary, is_node_type
9
+ )
10
+ from output.loops import unpack_tuple
11
+
12
+
13
+ def print_getattr(self, output, skip_expression): # AST_Dot
14
+ if not skip_expression:
15
+ expr = self.expression
16
+ expr.print(output)
17
+ if is_node_type(expr, AST_Number) and expr.value >= 0:
18
+ if not /[xa-f.]/i.test(output.last()):
19
+ output.print(".")
20
+ output.print(".")
21
+ # the name after dot would be mapped about here.
22
+ output.print_name(self.property)
23
+
24
+ def print_getitem(self, output): # AST_Sub
25
+ expr = self.expression
26
+ prop = self.property
27
+ # Tuple-style subscript: a[1, 2] → a[[1, 2]]
28
+ if is_node_type(prop, AST_Array) and prop.is_subscript_tuple:
29
+ expr.print(output)
30
+ output.print('[[')
31
+ for i, elem in enumerate(prop.elements):
32
+ if i:
33
+ output.comma()
34
+ elem.print(output)
35
+ output.print(']]')
36
+ return
37
+ if (is_node_type(prop, AST_Number) or is_node_type(prop, AST_String)) or (is_node_type(prop, AST_SymbolRef) and prop.name and prop.name.startsWith('ρσ_')):
38
+ expr.print(output)
39
+ output.print('['), prop.print(output), output.print(']')
40
+ return
41
+ is_negative_number = is_node_type(prop, AST_Unary) and prop.operator is "-" and is_node_type(prop.expression, AST_Number)
42
+ is_repeatable = is_node_type(expr, AST_SymbolRef)
43
+ if is_repeatable:
44
+ expr.print(output)
45
+ else:
46
+ output.spaced('(ρσ_expr_temp', '=', expr), output.print(')')
47
+ expr = {'print': def(): output.print('ρσ_expr_temp');}
48
+
49
+ if is_negative_number:
50
+ output.print('['), expr.print(output), output.print('.length'), prop.print(output), output.print(']')
51
+ return
52
+ is_repeatable = is_node_type(prop, AST_SymbolRef)
53
+ # We have to check the type of the property because if it is a Symbol, it
54
+ # will raise a TypeError with the < operator.
55
+ if is_repeatable:
56
+ output.spaced('[(typeof', prop, '===', '"number"', '&&', prop)
57
+ output.spaced('', '<', '0)', '?', expr), output.spaced('.length', '+', prop, ':', prop)
58
+ output.print("]")
59
+ else:
60
+ output.print('[ρσ_bound_index('), prop.print(output), output.comma(), expr.print(output), output.print(')]')
61
+
62
+
63
+ def print_rich_getitem(self, output): # AST_ItemAccess
64
+ func = 'ρσ_' + ('setitem' if self.assignment else 'getitem')
65
+ output.print(func + '(')
66
+ self.expression.print(output), output.comma(), self.property.print(output)
67
+ if self.assignment:
68
+ output.comma()
69
+ asg = self.assignment
70
+ as_op = self.assign_operator
71
+ if as_op.length > 0:
72
+ self.assignment = None
73
+ print_rich_getitem(self, output)
74
+ self.assignment = asg
75
+ output.space()
76
+ output.print(as_op)
77
+ output.space()
78
+ self.assignment.print(output)
79
+ output.print(')')
80
+
81
+ def print_splice_assignment(self, output): # AST_Splice
82
+ # splice assignment via pythonic array[start:end]
83
+ output.print('ρσ_splice(')
84
+ self.expression.print(output), output.comma(), self.assignment.print(output), output.comma()
85
+ self.property.print(output) if self.property else output.print('0')
86
+ if self.property2:
87
+ output.comma()
88
+ self.property2.print(output)
89
+ output.print(')')
90
+
91
+ def print_delete(self, output):
92
+ if is_node_type(self, AST_Symbol):
93
+ output.assign(self), output.print('undefined')
94
+ elif is_node_type(self, AST_Sub) or is_node_type(self, AST_ItemAccess):
95
+ output.print('ρσ_delitem('), self.expression.print(output), output.comma(), self.property.print(output), output.print(')')
96
+ else:
97
+ output.spaced('delete', self)
98
+
99
+ def print_unary_prefix(self, output):
100
+ op = self.operator
101
+ if op is 'delete':
102
+ return print_delete(self.expression, output)
103
+ if self.overloaded:
104
+ if op is '-':
105
+ output.print('ρσ_op_neg('), self.expression.print(output), output.print(')')
106
+ return
107
+ if op is '+':
108
+ output.print('ρσ_op_pos('), self.expression.print(output), output.print(')')
109
+ return
110
+ if op is '~':
111
+ output.print('ρσ_op_invert('), self.expression.print(output), output.print(')')
112
+ return
113
+ output.print(op)
114
+ if /^[a-z]/i.test(op):
115
+ output.space()
116
+ if self.parenthesized:
117
+ output.with_parens(def():
118
+ self.expression.print(output)
119
+ )
120
+ else:
121
+ self.expression.print(output)
122
+
123
+ def write_instanceof(left, right, output):
124
+
125
+ def do_many(vals):
126
+ output.print('ρσ_instanceof.apply(null,'), output.space()
127
+ output.print('['), left.print(output), output.comma()
128
+ for v'var i = 0; i < vals.length; i++':
129
+ vals[i].print(output)
130
+ if i is not vals.length - 1:
131
+ output.comma()
132
+ output.print('])')
133
+
134
+ if is_node_type(right, AST_Seq):
135
+ do_many(right.to_array())
136
+ elif is_node_type(right, AST_Array):
137
+ do_many(right.elements)
138
+ else:
139
+ output.print('ρσ_instanceof(')
140
+ left.print(output), output.comma(), right.print(output), output.print(')')
141
+
142
+ def write_smart_equality(self, output):
143
+ def is_ok(x):
144
+ return not (
145
+ is_node_type(x, AST_Array) or is_node_type(x, AST_Set) or is_node_type(x, AST_Object) or
146
+ is_node_type(x, AST_Statement) or is_node_type(x, AST_Binary) or is_node_type(x, AST_Conditional)
147
+ or is_node_type(x, AST_BaseCall)
148
+ )
149
+ if is_ok(self.left) and is_ok(self.right):
150
+ if self.operator is '==':
151
+ output.print('(')
152
+ output.spaced(self.left, '===', self.right, '||', 'typeof', self.left, '===', '"object"', '&&', 'ρσ_equals(')
153
+ self.left.print(output), output.print(','), output.space(), self.right.print(output), output.print('))')
154
+ else:
155
+ output.print('(')
156
+ output.spaced(self.left, '!==', self.right, '&&', '(typeof', self.left, '!==', '"object"', '||', 'ρσ_not_equals(')
157
+ self.left.print(output), output.print(','), output.space(), self.right.print(output), output.print(')))')
158
+ else:
159
+ output.print('ρσ_' + ('equals(' if self.operator is '==' else 'not_equals('))
160
+ self.left.print(output), output.print(','), output.space(), self.right.print(output), output.print(')')
161
+
162
+
163
+ comparators = {
164
+ "<": True,
165
+ ">": True,
166
+ "<=": True,
167
+ ">=": True,
168
+ }
169
+
170
+ function_ops = {
171
+ "in": "ρσ_in",
172
+ 'nin': '!ρσ_in',
173
+ }
174
+
175
+ # Maps binary operators to their overloading helper function names.
176
+ overloaded_binary_ops = {
177
+ '+': 'ρσ_op_add',
178
+ '-': 'ρσ_op_sub',
179
+ '*': 'ρσ_op_mul',
180
+ '/': 'ρσ_op_truediv',
181
+ '//': 'ρσ_op_floordiv',
182
+ '%': 'ρσ_op_mod',
183
+ '**': 'ρσ_op_pow',
184
+ '&': 'ρσ_op_and',
185
+ '|': 'ρσ_op_or',
186
+ '^': 'ρσ_op_xor',
187
+ '<<': 'ρσ_op_lshift',
188
+ '>>': 'ρσ_op_rshift',
189
+ }
190
+
191
+ # Maps augmented-assignment operators to their overloading helper names.
192
+ overloaded_augmented_ops = {
193
+ '+=': 'ρσ_op_iadd',
194
+ '-=': 'ρσ_op_isub',
195
+ '*=': 'ρσ_op_imul',
196
+ '/=': 'ρσ_op_itruediv',
197
+ '//=': 'ρσ_op_ifloordiv',
198
+ '%=': 'ρσ_op_imod',
199
+ '**=': 'ρσ_op_ipow',
200
+ '&=': 'ρσ_op_iand',
201
+ '|=': 'ρσ_op_ior',
202
+ '^=': 'ρσ_op_ixor',
203
+ '<<=': 'ρσ_op_ilshift',
204
+ '>>=': 'ρσ_op_irshift',
205
+ }
206
+
207
+
208
+ def print_binary_op(self, output):
209
+ if self.overloaded and overloaded_binary_ops[self.operator]:
210
+ output.print(overloaded_binary_ops[self.operator] + '(')
211
+ self.left.print(output)
212
+ output.comma()
213
+ self.right.print(output)
214
+ output.print(')')
215
+ return
216
+ if function_ops[self.operator]:
217
+ output.print(function_ops[self.operator])
218
+ output.with_parens(def():
219
+ self.left.print(output)
220
+ output.comma()
221
+ self.right.print(output)
222
+ )
223
+ elif comparators[self.operator] and is_node_type(self.left, AST_Binary) and comparators[self.left.operator]:
224
+ # A chained comparison such as a < b < c
225
+ if is_node_type(self.left.right, AST_Symbol):
226
+ # left side compares against a regular variable,
227
+ # no caching needed
228
+ self.left.print(output)
229
+ leftvar = self.left.right.name
230
+ else:
231
+ # some logic is being performed, let's cache it
232
+ self.left.left.print(output)
233
+ output.space()
234
+ output.print(self.left.operator)
235
+ output.space()
236
+ output.with_parens(def():
237
+ nonlocal leftvar
238
+ output.assign("ρσ_cond_temp")
239
+ self.left.right.print(output)
240
+ leftvar = "ρσ_cond_temp"
241
+ )
242
+
243
+ output.space()
244
+ output.print("&&")
245
+ output.space()
246
+ output.print(leftvar)
247
+ output.space()
248
+ output.print(self.operator)
249
+ output.space()
250
+ self.right.print(output)
251
+ elif self.operator is '//':
252
+ output.print('Math.floor')
253
+ output.with_parens(def():
254
+ self.left.print(output)
255
+ output.space()
256
+ output.print('/')
257
+ output.space()
258
+ self.right.print(output)
259
+ )
260
+ elif self.operator is '**':
261
+ left = self.left
262
+ if is_node_type(self.left, AST_Unary) and not self.left.parenthesized:
263
+ left = self.left.expression
264
+ output.print(self.left.operator)
265
+ if output.options.js_version > 6:
266
+ output.print('(('), left.print(output), output.spaced(')', '**', '('), self.right.print(output), output.print('))')
267
+ else:
268
+ output.print('Math.pow('), left.print(output), output.comma(), self.right.print(output), output.print(')')
269
+ elif self.operator is '==' or self.operator is '!=':
270
+ write_smart_equality(self, output)
271
+ elif self.operator is 'instanceof':
272
+ write_instanceof(self.left, self.right, output)
273
+ elif self.operator is '*' and is_node_type(self.left, AST_String):
274
+ self.left.print(output), output.print('.repeat('), self.right.print(output), output.print(')')
275
+ elif self.operator is '===' or self.operator is '!==':
276
+ nan_check = None
277
+ if is_node_type(self.right, AST_Symbol) and self.right.name is 'NaN':
278
+ nan_check = self.left
279
+ if is_node_type(self.left, AST_Symbol) and self.left.name is 'NaN':
280
+ nan_check = self.right
281
+ if nan_check is not None:
282
+ # We use the fact that NaN is the only object that is not equal to
283
+ # itself
284
+ output.spaced(nan_check, '!==' if self.operator is '===' else '===', nan_check)
285
+ else:
286
+ output.spaced(self.left, self.operator, self.right)
287
+ else:
288
+ output.spaced(self.left, self.operator, self.right)
289
+
290
+ after_map = {'.':'d', '(':'c', '[':'d', 'g':'g', 'null':'n'}
291
+
292
+ def print_existential(self, output):
293
+ key = after_map[self.after] if self.after is None or jstype(self.after) is 'string' else 'e'
294
+ if is_node_type(self.expression, AST_SymbolRef):
295
+ if key is 'n':
296
+ output.spaced('(typeof', self.expression, '!==', '"undefined"', '&&', self.expression, '!==', 'null)')
297
+ return
298
+ if key is 'c':
299
+ output.spaced('(typeof', self.expression, '===', '"function"', '?', self.expression, ':', '(function(){return undefined;}))')
300
+ return
301
+ after = self.after
302
+ if key is 'd':
303
+ after = 'Object.create(null)'
304
+ elif key is 'g':
305
+ after = '{__getitem__:function(){return undefined;}}'
306
+ output.spaced('(typeof', self.expression, '!==', '"undefined"', '&&', self.expression, '!==', 'null', '?', self.expression, ':', after)
307
+ output.print(')')
308
+ return
309
+ output.print('ρσ_exists.' + key + '(')
310
+ self.expression.print(output)
311
+ if key is 'e':
312
+ output.comma(), self.after.print(output)
313
+ output.print(')')
314
+
315
+ def print_assignment(self, output):
316
+ flattened = False
317
+ left = self.left
318
+ if is_node_type(left, AST_Seq):
319
+ left = new AST_Array({'elements':v'[left.car, left.cdr]'})
320
+ if is_node_type(left, AST_Array):
321
+ flat = left.flatten()
322
+ flattened = flat.length > left.elements.length
323
+ has_starred = False
324
+ for elem in flat:
325
+ if is_node_type(elem, AST_Starred):
326
+ has_starred = True
327
+ break
328
+ output.print("ρσ_unpack")
329
+ else:
330
+ left.print(output)
331
+ output.space()
332
+ output.print(self.operator)
333
+ output.space()
334
+ if flattened:
335
+ output.print('ρσ_flatten')
336
+ output.with_parens(def():self.right.print(output);)
337
+ else:
338
+ self.right.print(output)
339
+ if is_node_type(left, AST_Array):
340
+ output.end_statement()
341
+ if not is_node_type(self.right, AST_Seq) and not is_node_type(self.right, AST_Array):
342
+ output.assign('ρσ_unpack')
343
+ if has_starred:
344
+ output.print('ρσ_unpack_starred_asarray('), output.print('ρσ_unpack)')
345
+ else:
346
+ output.print('ρσ_unpack_asarray(' + flat.length), output.comma(), output.print('ρσ_unpack)')
347
+ output.end_statement()
348
+ unpack_tuple(flat, output, True)
349
+
350
+ def print_assign(self, output):
351
+ if self.overloaded and overloaded_augmented_ops[self.operator]:
352
+ helper = overloaded_augmented_ops[self.operator]
353
+ output.assign(self.left)
354
+ output.print(helper + '(')
355
+ self.left.print(output)
356
+ output.comma()
357
+ self.right.print(output)
358
+ output.print(')')
359
+ return
360
+ if self.operator is '//=':
361
+ output.assign(self.left)
362
+ output.print('Math.floor')
363
+ output.with_parens(def():
364
+ self.left.print(output)
365
+ output.space()
366
+ output.print('/')
367
+ output.space()
368
+ self.right.print(output)
369
+ )
370
+ return
371
+ if self.operator is '=' and self.is_chained():
372
+ left_hand_sides, rhs = self.traverse_chain()
373
+ is_compound_assign = False
374
+ for lhs in left_hand_sides:
375
+ if is_node_type(lhs, AST_Seq) or is_node_type(lhs, AST_Array) or is_node_type(lhs, AST_ItemAccess):
376
+ is_compound_assign = True
377
+ break
378
+ if is_compound_assign:
379
+ temp_rhs = new AST_SymbolRef({'name':'ρσ_chain_assign_temp'})
380
+ print_assignment(new AST_Assign({'left':temp_rhs, 'operator':'=', 'right':rhs}), output)
381
+ for lhs in left_hand_sides:
382
+ output.end_statement(), output.indent()
383
+ print_assignment(new AST_Assign({'left':lhs, 'right':temp_rhs, 'operator':self.operator}), output)
384
+ else:
385
+ for lhs in left_hand_sides:
386
+ output.spaced(lhs, '=', '')
387
+ rhs.print(output)
388
+ else:
389
+ print_assignment(self, output)
390
+
391
+ def print_conditional(self, output, condition, consequent, alternative):
392
+ condition, consequent, alternative = self.condition, self.consequent, self.alternative
393
+ output.with_parens(def():condition.print(output);)
394
+ output.space()
395
+ output.print("?")
396
+ output.space()
397
+ consequent.print(output)
398
+ output.space()
399
+ output.colon()
400
+ alternative.print(output)
401
+
402
+ def print_seq(output):
403
+ self = this
404
+ p = output.parent()
405
+ print_seq = def():
406
+ self.car.print(output)
407
+ if self.cdr:
408
+ output.comma()
409
+ if output.should_break():
410
+ output.newline()
411
+ output.indent()
412
+ self.cdr.print(output)
413
+
414
+ # this will effectively convert tuples to arrays
415
+ if is_node_type(p, AST_Binary)
416
+ or is_node_type(p, AST_Return)
417
+ or is_node_type(p, AST_Array)
418
+ or is_node_type(p, AST_BaseCall)
419
+ or is_node_type(p, AST_SimpleStatement):
420
+ output.with_square(print_seq)
421
+ else:
422
+ print_seq()
423
+
424
+ def print_named_expr(self, output):
425
+ # Walrus operator: name := value → (name = value)
426
+ output.with_parens(def():
427
+ output.assign(self.name)
428
+ self.value.print(output)
429
+ )