rapydscript-ns 0.9.3 → 0.9.5

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 (111) hide show
  1. package/.agignore +1 -1
  2. package/.github/workflows/ci.yml +38 -38
  3. package/=template.pyj +5 -5
  4. package/CHANGELOG.md +18 -0
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/PYTHON_GAPS.md +52 -142
  8. package/README.md +51 -21
  9. package/TODO.md +1 -26
  10. package/add-toc-to-readme +2 -2
  11. package/bin/export +75 -75
  12. package/bin/rapydscript +0 -0
  13. package/bin/web-repl-export +102 -102
  14. package/build +2 -2
  15. package/language-service/index.js +88 -36
  16. package/package.json +1 -1
  17. package/publish.py +37 -37
  18. package/release/baselib-plain-pretty.js +157 -31
  19. package/release/baselib-plain-ugly.js +5 -5
  20. package/release/compiler.js +724 -426
  21. package/release/signatures.json +29 -29
  22. package/session.vim +4 -4
  23. package/setup.cfg +2 -2
  24. package/src/ast.pyj +7 -0
  25. package/src/baselib-containers.pyj +41 -4
  26. package/src/baselib-errors.pyj +4 -3
  27. package/src/baselib-internal.pyj +47 -18
  28. package/src/baselib-str.pyj +16 -3
  29. package/src/compiler.pyj +36 -36
  30. package/src/errors.pyj +30 -30
  31. package/src/lib/aes.pyj +646 -646
  32. package/src/lib/collections.pyj +227 -3
  33. package/src/lib/copy.pyj +120 -120
  34. package/src/lib/elementmaker.pyj +83 -83
  35. package/src/lib/encodings.pyj +126 -126
  36. package/src/lib/gettext.pyj +569 -569
  37. package/src/lib/itertools.pyj +580 -580
  38. package/src/lib/math.pyj +193 -193
  39. package/src/lib/operator.pyj +11 -11
  40. package/src/lib/pprint.pyj +455 -0
  41. package/src/lib/random.pyj +118 -118
  42. package/src/lib/react.pyj +74 -74
  43. package/src/lib/statistics.pyj +0 -0
  44. package/src/lib/traceback.pyj +63 -63
  45. package/src/lib/uuid.pyj +77 -77
  46. package/src/monaco-language-service/completions.js +21 -14
  47. package/src/monaco-language-service/diagnostics.js +2 -2
  48. package/src/monaco-language-service/dts.js +58 -15
  49. package/src/monaco-language-service/package.json +3 -0
  50. package/src/output/classes.pyj +25 -2
  51. package/src/output/codegen.pyj +4 -1
  52. package/src/output/comments.pyj +45 -45
  53. package/src/output/exceptions.pyj +201 -201
  54. package/src/output/jsx.pyj +164 -164
  55. package/src/output/treeshake.pyj +182 -182
  56. package/src/output/utils.pyj +72 -72
  57. package/src/parse.pyj +42 -7
  58. package/src/string_interpolation.pyj +72 -72
  59. package/src/tokenizer.pyj +18 -2
  60. package/src/unicode_aliases.pyj +576 -576
  61. package/src/utils.pyj +192 -192
  62. package/test/_import_one.pyj +37 -37
  63. package/test/_import_two/__init__.pyj +11 -11
  64. package/test/_import_two/level2/deep.pyj +4 -4
  65. package/test/_import_two/other.pyj +6 -6
  66. package/test/_import_two/sub.pyj +13 -13
  67. package/test/aes_vectors.pyj +421 -421
  68. package/test/annotations.pyj +80 -80
  69. package/test/baselib.pyj +23 -0
  70. package/test/chainmap.pyj +185 -0
  71. package/test/dataclasses.pyj +3 -4
  72. package/test/decorators.pyj +77 -77
  73. package/test/docstrings.pyj +39 -39
  74. package/test/elementmaker_test.pyj +45 -45
  75. package/test/enum.pyj +1 -1
  76. package/test/functions.pyj +151 -151
  77. package/test/generators.pyj +41 -41
  78. package/test/generic.pyj +370 -370
  79. package/test/internationalization.pyj +73 -73
  80. package/test/lint.pyj +164 -164
  81. package/test/loops.pyj +85 -85
  82. package/test/numpy.pyj +734 -734
  83. package/test/pprint.pyj +232 -0
  84. package/test/python_features.pyj +1 -1
  85. package/test/repl.pyj +121 -121
  86. package/test/scoped_flags.pyj +76 -76
  87. package/test/statistics.pyj +224 -0
  88. package/test/str.pyj +4 -4
  89. package/test/unit/index.js +455 -0
  90. package/test/unit/language-service-completions.js +2 -0
  91. package/test/unit/language-service-dts.js +113 -0
  92. package/test/unit/language-service-hover.js +455 -455
  93. package/test/unit/language-service.js +135 -2
  94. package/test/unit/web-repl.js +349 -1
  95. package/tools/compiler.d.ts +367 -367
  96. package/tools/completer.js +131 -131
  97. package/tools/export.js +4 -2
  98. package/tools/gettext.js +185 -185
  99. package/tools/ini.js +65 -65
  100. package/tools/msgfmt.js +187 -187
  101. package/tools/repl.js +223 -223
  102. package/tools/test.js +118 -118
  103. package/tools/utils.js +141 -128
  104. package/tools/web_repl.js +95 -95
  105. package/try +41 -41
  106. package/web-repl/env.js +196 -196
  107. package/web-repl/index.html +163 -163
  108. package/web-repl/prism.css +139 -139
  109. package/web-repl/prism.js +113 -113
  110. package/web-repl/rapydscript.js +228 -226
  111. package/web-repl/sha1.js +25 -25
@@ -1,34 +1,34 @@
1
1
  {
2
- "ast": "1f915bd707f37c2eca90633cbe291b6c030e68a3",
2
+ "ast": "9c7c4c0132da3d1e4af19a00c1c0387423484a82",
3
3
  "baselib-builtins": "1be74e1e78642c5cbf448f8f2a94aae0f1a3d59c",
4
4
  "baselib-bytes": "057ab581c276ef03ce91fecdd4213e412198251c",
5
- "baselib-containers": "6c480319b9d2ba5d2ee9376e02b67fcd45375912",
6
- "baselib-errors": "c7e514d89ad79f2da41fe924f5ad93fc6f2cdf8e",
7
- "baselib-internal": "19a95012b2bc1d18c47262ac908a6017e5092f49",
5
+ "baselib-containers": "b25e5a999657f3195573679b9eb544cba48c52ba",
6
+ "baselib-errors": "b4c055341bca1943ede820c5d179cfa7e08bb3fe",
7
+ "baselib-internal": "11fb673a8eef58fad100c43e83ef5274e4b6694e",
8
8
  "baselib-itertools": "268b7b7af79506e9a01023e8cd3b1741599bb6a5",
9
- "baselib-str": "3fa63a0bf3bcf91cba4666093c3960633c6eed2e",
10
- "compiler": "4c728d81b441b4b9c590f9330271f54b47cc11eb",
11
- "errors": "d1b33848d19b141e19cc079cf78421f29b6d2c05",
12
- "output/__init__": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
13
- "output/classes": "469c47511692e04eb1bc2b079af3f65b47165865",
14
- "output/codegen": "69151b2cd53ff8b3270a122c65e1a0f56735150e",
15
- "output/comments": "78ec38d8b34da96c078653e2d0d4049d7003906b",
16
- "output/exceptions": "d45bc62bc6b011bae182ed7c8df8ea5e392f6fb8",
17
- "output/functions": "263416b49c60c78abee42fef83ec460e886fb243",
18
- "output/jsx": "0a174c39378155c19dfa669e833c14d63190127b",
19
- "output/literals": "287ec4222c79f1ebfa2c6efae925e794cbb931ab",
20
- "output/loops": "1c9bbd6a2772dd2fc287c0b1aebfac7f5426eb27",
21
- "output/modules": "8383da8f58a79921d24e4e0261360a7d0708c4db",
22
- "output/operators": "8f7b1cf4f8a91102fc04104f8a799dcd8849963e",
23
- "output/statements": "94ee0cd084f22aea451b96eb1a9a831084cc4267",
24
- "output/stream": "9bd250ebb7ee43374d69c24357f8c985f95397d4",
25
- "output/treeshake": "c1d65269ff21cfd046e947755a3489d0e670a74a",
26
- "output/utils": "595968f96f6fdcc51eb41c34d64c92bb595e3cb1",
27
- "parse": "d4ad97b80e3cbf810c55285bd47281bedfe027f9",
28
- "string_interpolation": "bff1cc76d772d24d35707f6c794f38734ca08376",
29
- "tokenizer": "7b8fb7855dc09aeeb16f6a513ae664951dd070e1",
30
- "unicode_aliases": "79ac6eaa5e6be44a5397d62c561f854a8fe7528e",
31
- "utils": "c1666db819aa7c8db38697e34e18362e3cb45869",
32
- "#compiler#": "ce0d8d902910ca87ffa150b4d56775144ed6ec25",
33
- "#compiled_with#": "ce0d8d902910ca87ffa150b4d56775144ed6ec25"
9
+ "baselib-str": "0183cdb36d8bee149e6bd50f03017e5baa1c49e6",
10
+ "compiler": "bb16e915c60dc4ffb5bfe98bef411736d19fa297",
11
+ "errors": "257eca38b6de987e5fd80672bec9b9981847e1bd",
12
+ "output\\classes": "fd465d02dc11e532be40d3d45d14bf57bc668ed0",
13
+ "output\\codegen": "aaf15f93f7ab0de23d9076cc5b1a9a415ffe5690",
14
+ "output\\comments": "63b39620f9d6f407aa2d4ddb557d1c60ef296b05",
15
+ "output\\exceptions": "e7d9119550403e6c5730d40b9bc9c923a23d6eb7",
16
+ "output\\functions": "263416b49c60c78abee42fef83ec460e886fb243",
17
+ "output\\jsx": "14f32c048301965de7764c5b74b651bc279de937",
18
+ "output\\literals": "287ec4222c79f1ebfa2c6efae925e794cbb931ab",
19
+ "output\\loops": "1c9bbd6a2772dd2fc287c0b1aebfac7f5426eb27",
20
+ "output\\modules": "8383da8f58a79921d24e4e0261360a7d0708c4db",
21
+ "output\\operators": "8f7b1cf4f8a91102fc04104f8a799dcd8849963e",
22
+ "output\\statements": "94ee0cd084f22aea451b96eb1a9a831084cc4267",
23
+ "output\\stream": "9bd250ebb7ee43374d69c24357f8c985f95397d4",
24
+ "output\\treeshake": "4a490ba097739d924db9e3cd9eb7718db5e24cae",
25
+ "output\\utils": "e957919bfccb9a3ab510d824a8f2ee3fc2689795",
26
+ "output\\__init__": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
27
+ "parse": "d3f79e2e958219ddea28d483e8b337abd16793f1",
28
+ "string_interpolation": "88dce6c2c5ee75126a6838a1506841c6531a0d15",
29
+ "tokenizer": "4a043b2805688a59a21eb99e57567c52ee7b3952",
30
+ "unicode_aliases": "7fbcbc9c24adcb2e33fac8d69aaafe5047fcc2c2",
31
+ "utils": "35a2a707c841da851e18c64edac54e7c20b7dfc9",
32
+ "#compiler#": "a8443467a8034f2a29d201a7264eb0cdbe61ff4e",
33
+ "#compiled_with#": "a8443467a8034f2a29d201a7264eb0cdbe61ff4e"
34
34
  }
package/session.vim CHANGED
@@ -1,4 +1,4 @@
1
- set wildignore+=*.pyj-cached
2
- set wildignore+=node_modules
3
- imap <F4> ρσ_
4
- cmap <F4> ρσ_
1
+ set wildignore+=*.pyj-cached
2
+ set wildignore+=node_modules
3
+ imap <F4> ρσ_
4
+ cmap <F4> ρσ_
package/setup.cfg CHANGED
@@ -1,2 +1,2 @@
1
- [rapydscript]
2
- globals=assert,RapydScript
1
+ [rapydscript]
2
+ globals=assert,RapydScript
package/src/ast.pyj CHANGED
@@ -605,6 +605,7 @@ class AST_Class(AST_Scope):
605
605
  'has_new': "[boolean] true if the class defines a __new__ method",
606
606
  'has_attr_dunders': "[boolean] true if the class defines any of __getattr__/__setattr__/__delattr__/__getattribute__",
607
607
  'class_kwargs': "[array] keyword arguments from class header (e.g. class C(Base, key=val):) as [[key_node, value_node], ...]",
608
+ 'slots': "[array|null] list of __slots__ attribute names, null if not defined",
608
609
  }
609
610
 
610
611
  def _walk(self, visitor):
@@ -1280,6 +1281,12 @@ class AST_Number(AST_Constant):
1280
1281
  'value': "[number] the numeric value"
1281
1282
  }
1282
1283
 
1284
+ class AST_BigInt(AST_Constant):
1285
+ "A BigInt literal (e.g. 42n)"
1286
+ properties = {
1287
+ 'value': "[string] the raw numeric string (without n suffix)"
1288
+ }
1289
+
1283
1290
  class AST_RegExp(AST_Constant):
1284
1291
  "A regexp literal"
1285
1292
  properties = {
@@ -93,7 +93,10 @@ def ρσ_list_remove(value):
93
93
  raise ValueError(value + ' not in list')
94
94
 
95
95
  def ρσ_list_to_string():
96
- return '[' + this.join(', ') + ']'
96
+ ans = v'[]'
97
+ for v'var i = 0; i < this.length; i++':
98
+ ans.push(ρσ_repr(this[i]))
99
+ return '[' + ans.join(', ') + ']'
97
100
 
98
101
  def ρσ_list_insert(index, val):
99
102
  if index < 0:
@@ -122,9 +125,22 @@ def ρσ_list_sort_key(value):
122
125
  t = jstype(value)
123
126
  if t is 'string' or t is 'number':
124
127
  return value
128
+ # Keep objects that define __lt__ unchanged so ρσ_list_sort_cmp can
129
+ # dispatch the dunder; everything else falls back to a string key.
130
+ if value is not None and value is not undefined and jstype(value.__lt__) is 'function':
131
+ return value
125
132
  return value.toString()
126
133
 
127
134
  def ρσ_list_sort_cmp(a, b, ap, bp):
135
+ # When the elements define __lt__, order them the Pythonic way via
136
+ # ρσ_op_lt (which also handles a reflected __gt__); otherwise compare
137
+ # the precomputed primitive keys directly.
138
+ if a is not None and a is not undefined and jstype(a.__lt__) is 'function':
139
+ if ρσ_op_lt(a, b):
140
+ return -1
141
+ if ρσ_op_lt(b, a):
142
+ return 1
143
+ return ap - bp
128
144
  if a < b:
129
145
  return -1
130
146
  if a > b:
@@ -132,8 +148,17 @@ def ρσ_list_sort_cmp(a, b, ap, bp):
132
148
  return ap - bp
133
149
 
134
150
  def ρσ_list_sort(key=None, reverse=False):
135
- key = key or ρσ_list_sort_key
136
151
  mult = -1 if reverse else 1
152
+ if key is not None and key is not undefined and jstype(key) is 'function' and key.length is 2:
153
+ # A two-argument function is treated as a comparator (à la
154
+ # functools.cmp_to_key) rather than a key function, so a JS-style
155
+ # `.sort((a, b) => ...)` callback works as expected.
156
+ cmpposmap = dict()
157
+ for v'var i=0; i < this.length; i++':
158
+ cmpposmap.set(this[i], i) # noqa:undef
159
+ Array.prototype.sort.call(this, def (a, b): return (mult * key(a, b)) or (cmpposmap.get(a) - cmpposmap.get(b));)
160
+ return
161
+ key = key or ρσ_list_sort_key
137
162
  keymap = dict()
138
163
  posmap = dict()
139
164
  for v'var i=0; i < this.length; i++':
@@ -489,7 +514,13 @@ Object.defineProperties(ρσ_set.prototype, {
489
514
  r = iterator.next()
490
515
 
491
516
  ρσ_set.prototype.toString = ρσ_set.prototype.__repr__ = ρσ_set.prototype.__str__ = ρσ_set.prototype.inspect = def():
492
- return '{' + list(this).join(', ') + '}'
517
+ ans = v'[]'
518
+ iterator = this.jsset.values()
519
+ r = iterator.next()
520
+ while not r.done:
521
+ ans.push(ρσ_repr(r.value))
522
+ r = iterator.next()
523
+ return '{' + ans.join(', ') + '}'
493
524
 
494
525
  ρσ_set.prototype.__eq__ = def(other):
495
526
  if v'!other || !other.jsset':
@@ -631,7 +662,13 @@ Object.defineProperties(ρσ_frozenset.prototype, {
631
662
  return ans
632
663
 
633
664
  ρσ_frozenset.prototype.toString = ρσ_frozenset.prototype.__repr__ = ρσ_frozenset.prototype.__str__ = ρσ_frozenset.prototype.inspect = def():
634
- return 'frozenset({' + list(this).join(', ') + '})'
665
+ ans = v'[]'
666
+ iterator = this.jsset.values()
667
+ r = iterator.next()
668
+ while not r.done:
669
+ ans.push(ρσ_repr(r.value))
670
+ r = iterator.next()
671
+ return 'frozenset({' + ans.join(', ') + '})'
635
672
 
636
673
  ρσ_frozenset.prototype.__eq__ = def(other):
637
674
  if v'!other || !other.jsset':
@@ -8,8 +8,9 @@ v'var _ρσ_NativeError = Error'
8
8
 
9
9
  class Exception(Error):
10
10
 
11
- def __init__(self, message):
12
- self.message = message
11
+ def __init__(self):
12
+ self.args = v'Array.prototype.slice.call(arguments)'
13
+ self.message = self.args[0] if self.args.length > 0 else ''
13
14
  self.stack = v'_ρσ_NativeError'().stack
14
15
  self.name = self.constructor.name
15
16
 
@@ -57,7 +58,7 @@ def _is_exc_class(obj):
57
58
  class ExceptionGroup(Exception):
58
59
 
59
60
  def __init__(self, message, exceptions):
60
- Exception.__init__(self, message)
61
+ Exception.__init__(self, message, exceptions)
61
62
  self.exceptions = exceptions if exceptions else []
62
63
 
63
64
  def subgroup(self, condition):
@@ -385,37 +385,49 @@ def ρσ_op_pow(a, b):
385
385
  def ρσ_op_and(a, b):
386
386
  if a is not None and jstype(a.__and__) is 'function': return a.__and__(b)
387
387
  if b is not None and jstype(b.__rand__) is 'function': return b.__rand__(a)
388
- if (jstype(a) is 'bigint') is not (jstype(b) is 'bigint'):
389
- raise TypeError("unsupported operand type(s) for &: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
390
- return v'a & b'
388
+ ta = jstype(a)
389
+ tb = jstype(b)
390
+ if (ta is 'number' or ta is 'boolean') and (tb is 'number' or tb is 'boolean'): return v'a & b'
391
+ if ta is 'bigint' and tb is 'bigint': return v'a & b'
392
+ raise TypeError("unsupported operand type(s) for &: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
391
393
 
392
394
  def ρσ_op_or(a, b):
393
395
  if a is not None and jstype(a.__or__) is 'function': return a.__or__(b)
394
396
  if b is not None and jstype(b.__ror__) is 'function': return b.__ror__(a)
395
- if (jstype(a) is 'bigint') is not (jstype(b) is 'bigint'):
396
- raise TypeError("unsupported operand type(s) for |: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
397
- return v'a | b'
397
+ ta = jstype(a)
398
+ tb = jstype(b)
399
+ if ta is 'object' and tb is 'object' and a is not None and b is not None and not Array.isArray(a) and not Array.isArray(b) and v'a.constructor === Object' and v'b.constructor === Object':
400
+ return Object.assign({}, a, b)
401
+ if (ta is 'number' or ta is 'boolean') and (tb is 'number' or tb is 'boolean'): return v'a | b'
402
+ if ta is 'bigint' and tb is 'bigint': return v'a | b'
403
+ raise TypeError("unsupported operand type(s) for |: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
398
404
 
399
405
  def ρσ_op_xor(a, b):
400
406
  if a is not None and jstype(a.__xor__) is 'function': return a.__xor__(b)
401
407
  if b is not None and jstype(b.__rxor__) is 'function': return b.__rxor__(a)
402
- if (jstype(a) is 'bigint') is not (jstype(b) is 'bigint'):
403
- raise TypeError("unsupported operand type(s) for ^: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
404
- return v'a ^ b'
408
+ ta = jstype(a)
409
+ tb = jstype(b)
410
+ if (ta is 'number' or ta is 'boolean') and (tb is 'number' or tb is 'boolean'): return v'a ^ b'
411
+ if ta is 'bigint' and tb is 'bigint': return v'a ^ b'
412
+ raise TypeError("unsupported operand type(s) for ^: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
405
413
 
406
414
  def ρσ_op_lshift(a, b):
407
415
  if a is not None and jstype(a.__lshift__) is 'function': return a.__lshift__(b)
408
416
  if b is not None and jstype(b.__rlshift__) is 'function': return b.__rlshift__(a)
409
- if (jstype(a) is 'bigint') is not (jstype(b) is 'bigint'):
410
- raise TypeError("unsupported operand type(s) for <<: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
411
- return v'a << b'
417
+ ta = jstype(a)
418
+ tb = jstype(b)
419
+ if (ta is 'number' or ta is 'boolean') and (tb is 'number' or tb is 'boolean'): return v'a << b'
420
+ if ta is 'bigint' and tb is 'bigint': return v'a << b'
421
+ raise TypeError("unsupported operand type(s) for <<: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
412
422
 
413
423
  def ρσ_op_rshift(a, b):
414
424
  if a is not None and jstype(a.__rshift__) is 'function': return a.__rshift__(b)
415
425
  if b is not None and jstype(b.__rrshift__) is 'function': return b.__rrshift__(a)
416
- if (jstype(a) is 'bigint') is not (jstype(b) is 'bigint'):
417
- raise TypeError("unsupported operand type(s) for >>: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
418
- return v'a >> b'
426
+ ta = jstype(a)
427
+ tb = jstype(b)
428
+ if (ta is 'number' or ta is 'boolean') and (tb is 'number' or tb is 'boolean'): return v'a >> b'
429
+ if ta is 'bigint' and tb is 'bigint': return v'a >> b'
430
+ raise TypeError("unsupported operand type(s) for >>: '" + ρσ_arith_type_name(a) + "' and '" + ρσ_arith_type_name(b) + "'")
419
431
 
420
432
  # Ordered-comparison operator overloading helpers.
421
433
  # ρσ_op_lt dispatches __lt__ (forward) then __gt__ (reflected), handles lists
@@ -505,15 +517,22 @@ def ρσ_list_iadd(a, b):
505
517
  # Unary operator overloading helpers
506
518
  def ρσ_op_neg(a):
507
519
  if a is not None and jstype(a.__neg__) is 'function': return a.__neg__()
508
- return -a
520
+ ta = jstype(a)
521
+ if ta is 'number' or ta is 'boolean' or ta is 'bigint': return -a
522
+ raise TypeError("bad operand type for unary -: '" + ρσ_arith_type_name(a) + "'")
509
523
 
510
524
  def ρσ_op_pos(a):
511
525
  if a is not None and jstype(a.__pos__) is 'function': return a.__pos__()
512
- return +a
526
+ ta = jstype(a)
527
+ if ta is 'number' or ta is 'boolean': return +a
528
+ if ta is 'bigint': return a
529
+ raise TypeError("bad operand type for unary +: '" + ρσ_arith_type_name(a) + "'")
513
530
 
514
531
  def ρσ_op_invert(a):
515
532
  if a is not None and jstype(a.__invert__) is 'function': return a.__invert__()
516
- return ~a
533
+ ta = jstype(a)
534
+ if ta is 'number' or ta is 'boolean' or ta is 'bigint': return ~a
535
+ raise TypeError("bad operand type for unary ~: '" + ρσ_arith_type_name(a) + "'")
517
536
 
518
537
  # Augmented-assignment helpers: try __i<op>__ first, fall back to binary op
519
538
  def ρσ_op_iadd(a, b):
@@ -550,6 +569,11 @@ def ρσ_op_iand(a, b):
550
569
 
551
570
  def ρσ_op_ior(a, b):
552
571
  if a is not None and jstype(a.__ior__) is 'function': return a.__ior__(b)
572
+ ta = jstype(a)
573
+ tb = jstype(b)
574
+ if ta is 'object' and tb is 'object' and a is not None and b is not None and not Array.isArray(a) and not Array.isArray(b) and v'a.constructor === Object' and v'b.constructor === Object':
575
+ Object.assign(a, b)
576
+ return a
553
577
  return ρσ_op_or(a, b)
554
578
 
555
579
  def ρσ_op_ixor(a, b):
@@ -766,6 +790,11 @@ v'var ρσ_proxy_target_symbol = typeof Symbol === "function" ? Symbol("ρσ_pro
766
790
  if jstype(target.__setattr__) is 'function':
767
791
  target.__setattr__.call(receiver, prop, value)
768
792
  return True
793
+ # __slots__ enforcement: check if the class restricts instance attributes.
794
+ if jstype(prop) is 'string' and prop[0] is not 'ρ':
795
+ slots = v'target.constructor && target.constructor.prototype.__ρσ_slots__'
796
+ if slots and not v'slots.hasOwnProperty(prop)':
797
+ raise AttributeError("'" + (target.constructor.__name__ or 'object') + "' object has no attribute '" + prop + "'")
769
798
  # Pass 'target' as receiver (not proxy) to avoid infinite recursion through the Proxy set trap.
770
799
  return v'Reflect.set(target, prop, value, target)'
771
800
  ,
@@ -23,7 +23,7 @@ def ρσ_repr_js_builtin(x, as_array):
23
23
  keys = Object.keys(x)
24
24
  for v'var k = 0; k < keys.length; k++':
25
25
  key = keys[k]
26
- ans.push(JSON.stringify(key) + ':' + ρσ_repr(x[key]))
26
+ ans.push(ρσ_repr(key) + ': ' + ρσ_repr(x[key]))
27
27
  return b[0] + ans.join(', ') + b[1]
28
28
 
29
29
  def ρσ_html_element_to_string(elem):
@@ -49,6 +49,8 @@ def ρσ_repr(x):
49
49
  ans = x.__repr__()
50
50
  elif x is True or x is False:
51
51
  ans = 'True' if x else 'False'
52
+ elif jstype(x) is 'string':
53
+ ans = "'" + x.replace("\\", "\\\\").replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t") + "'"
52
54
  elif Array.isArray(x):
53
55
  ans = ρσ_repr_js_builtin(x, True)
54
56
  elif jstype(x) is 'function':
@@ -111,8 +113,19 @@ define_str_func = def(name, func):
111
113
  if func.__argnames__:
112
114
  Object.defineProperty(f, '__argnames__', {'value':v"['string']".concat(func.__argnames__)})
113
115
 
114
- ρσ_orig_split = String.prototype.split.call.bind(String.prototype.split)
115
- ρσ_orig_replace = String.prototype.replace.call.bind(String.prototype.replace)
116
+ # Guard against multiple evaluations of the baselib in the same JS context
117
+ # (e.g. web_repl()/create_compiler() being called repeatedly). Without this,
118
+ # each eval captures the PREVIOUS patched String.prototype.split as ρσ_orig_split,
119
+ # creating a chain that eventually overflows the call stack.
120
+ if v'typeof globalThis !== "undefined" && globalThis._ρσ_orig_split':
121
+ ρσ_orig_split = v'globalThis._ρσ_orig_split'
122
+ ρσ_orig_replace = v'globalThis._ρσ_orig_replace'
123
+ else:
124
+ ρσ_orig_split = String.prototype.split.call.bind(String.prototype.split)
125
+ ρσ_orig_replace = String.prototype.replace.call.bind(String.prototype.replace)
126
+ if v'typeof globalThis !== "undefined"':
127
+ v'globalThis._ρσ_orig_split = ρσ_orig_split'
128
+ v'globalThis._ρσ_orig_replace = ρσ_orig_replace'
116
129
 
117
130
  # format() {{{
118
131
  define_str_func('format', def ():
package/src/compiler.pyj CHANGED
@@ -1,36 +1,36 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD
3
- # Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
4
- # globals: console
5
-
6
- from utils import DefaultsError, string_template
7
- from errors import ImportError, SyntaxError
8
- from tokenizer import ALL_KEYWORDS, IDENTIFIER_PAT, tokenizer
9
- from parse import parse, NATIVE_CLASSES, compile_time_decorators
10
- from output.stream import OutputStream
11
- from output.codegen import generate_code
12
- from output.treeshake import tree_shake
13
-
14
- generate_code() # create the print methods on the AST nodes
15
-
16
- # The following allows this module to be used from a pure javascript, require()
17
- # based environment like Node.js
18
- if jstype(exports) is 'object':
19
- exports.DefaultsError = DefaultsError
20
- exports.parse = parse
21
- exports.compile_time_decorators = compile_time_decorators
22
- exports.OutputStream = OutputStream
23
- exports.string_template = string_template # noqa:undef
24
- # Needed for REPL and linter
25
- exports.ALL_KEYWORDS = ALL_KEYWORDS
26
- exports.IDENTIFIER_PAT = IDENTIFIER_PAT
27
- exports.NATIVE_CLASSES = NATIVE_CLASSES
28
- exports.ImportError = ImportError
29
- exports.SyntaxError = SyntaxError
30
- exports.tokenizer = tokenizer
31
- exports.tree_shake = tree_shake
32
- # Magic! Export all the AST_* nodes
33
- ast = ρσ_modules['ast']
34
- for ast_node in ast:
35
- if ast_node.substr(0, 4) is 'AST_':
36
- exports[ast_node] = ast[ast_node] # noqa:undef
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD
3
+ # Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
4
+ # globals: console
5
+
6
+ from utils import DefaultsError, string_template
7
+ from errors import ImportError, SyntaxError
8
+ from tokenizer import ALL_KEYWORDS, IDENTIFIER_PAT, tokenizer
9
+ from parse import parse, NATIVE_CLASSES, compile_time_decorators
10
+ from output.stream import OutputStream
11
+ from output.codegen import generate_code
12
+ from output.treeshake import tree_shake
13
+
14
+ generate_code() # create the print methods on the AST nodes
15
+
16
+ # The following allows this module to be used from a pure javascript, require()
17
+ # based environment like Node.js
18
+ if jstype(exports) is 'object':
19
+ exports.DefaultsError = DefaultsError
20
+ exports.parse = parse
21
+ exports.compile_time_decorators = compile_time_decorators
22
+ exports.OutputStream = OutputStream
23
+ exports.string_template = string_template # noqa:undef
24
+ # Needed for REPL and linter
25
+ exports.ALL_KEYWORDS = ALL_KEYWORDS
26
+ exports.IDENTIFIER_PAT = IDENTIFIER_PAT
27
+ exports.NATIVE_CLASSES = NATIVE_CLASSES
28
+ exports.ImportError = ImportError
29
+ exports.SyntaxError = SyntaxError
30
+ exports.tokenizer = tokenizer
31
+ exports.tree_shake = tree_shake
32
+ # Magic! Export all the AST_* nodes
33
+ ast = ρσ_modules['ast']
34
+ for ast_node in ast:
35
+ if ast_node.substr(0, 4) is 'AST_':
36
+ exports[ast_node] = ast[ast_node] # noqa:undef
package/src/errors.pyj CHANGED
@@ -1,30 +1,30 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
- from __python__ import hash_literals
4
-
5
- class SyntaxError(Error):
6
-
7
- def __init__(self, message, filename, line, col, pos, is_eof):
8
- self.stack = Error().stack
9
- self.message = message
10
- self.line = line
11
- self.col = col
12
- self.pos = pos
13
- self.is_eof = is_eof
14
- self.filename = filename
15
- # The "standard" form for these error attributes
16
- self.lineNumber = line
17
- self.fileName = filename
18
-
19
- def toString(self):
20
- ans = self.message + " (line: " + self.line + ", col: " + self.col + ", pos: " + self.pos + ")"
21
- if self.filename:
22
- ans = self.filename + ':' + ans
23
- if self.stack:
24
- ans += "\n\n" + self.stack
25
- return ans
26
-
27
-
28
- class ImportError(SyntaxError):
29
- pass
30
-
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
+ from __python__ import hash_literals
4
+
5
+ class SyntaxError(Error):
6
+
7
+ def __init__(self, message, filename, line, col, pos, is_eof):
8
+ self.stack = Error().stack
9
+ self.message = message
10
+ self.line = line
11
+ self.col = col
12
+ self.pos = pos
13
+ self.is_eof = is_eof
14
+ self.filename = filename
15
+ # The "standard" form for these error attributes
16
+ self.lineNumber = line
17
+ self.fileName = filename
18
+
19
+ def toString(self):
20
+ ans = self.message + " (line: " + self.line + ", col: " + self.col + ", pos: " + self.pos + ")"
21
+ if self.filename:
22
+ ans = self.filename + ':' + ans
23
+ if self.stack:
24
+ ans += "\n\n" + self.stack
25
+ return ans
26
+
27
+
28
+ class ImportError(SyntaxError):
29
+ pass
30
+