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
package/release/signatures.json
CHANGED
|
@@ -1,31 +1,34 @@
|
|
|
1
1
|
{
|
|
2
|
-
"ast": "
|
|
3
|
-
"baselib-builtins": "
|
|
4
|
-
"baselib-
|
|
5
|
-
"baselib-
|
|
6
|
-
"baselib-
|
|
7
|
-
"baselib-
|
|
8
|
-
"baselib-
|
|
9
|
-
"
|
|
2
|
+
"ast": "88027aa403dfe55fcf8d475115897d141717d17c",
|
|
3
|
+
"baselib-builtins": "284e14536cfdd0b497abeb6f110ae49a20f2a172",
|
|
4
|
+
"baselib-bytes": "057ab581c276ef03ce91fecdd4213e412198251c",
|
|
5
|
+
"baselib-containers": "d2f534e6530dfb309b074bf7fac082c65779e778",
|
|
6
|
+
"baselib-errors": "8efbb59deb88ede0995768f63f57103f2f0fd02d",
|
|
7
|
+
"baselib-internal": "bb1eff32c1c50d5d25ea3074a968e765a136108c",
|
|
8
|
+
"baselib-itertools": "268b7b7af79506e9a01023e8cd3b1741599bb6a5",
|
|
9
|
+
"baselib-str": "0e8d1ee658690412140cc138adf9681425de5084",
|
|
10
|
+
"compiler": "4c728d81b441b4b9c590f9330271f54b47cc11eb",
|
|
10
11
|
"errors": "d1b33848d19b141e19cc079cf78421f29b6d2c05",
|
|
11
12
|
"output/__init__": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
|
12
|
-
"output/classes": "
|
|
13
|
-
"output/codegen": "
|
|
13
|
+
"output/classes": "469c47511692e04eb1bc2b079af3f65b47165865",
|
|
14
|
+
"output/codegen": "69151b2cd53ff8b3270a122c65e1a0f56735150e",
|
|
14
15
|
"output/comments": "78ec38d8b34da96c078653e2d0d4049d7003906b",
|
|
15
|
-
"output/exceptions": "
|
|
16
|
-
"output/functions": "
|
|
17
|
-
"output/
|
|
18
|
-
"output/
|
|
19
|
-
"output/
|
|
20
|
-
"output/
|
|
21
|
-
"output/
|
|
22
|
-
"output/
|
|
16
|
+
"output/exceptions": "d45bc62bc6b011bae182ed7c8df8ea5e392f6fb8",
|
|
17
|
+
"output/functions": "5fe055661a45cf9de8ef024c758bb8214a87cd80",
|
|
18
|
+
"output/jsx": "0a174c39378155c19dfa669e833c14d63190127b",
|
|
19
|
+
"output/literals": "287ec4222c79f1ebfa2c6efae925e794cbb931ab",
|
|
20
|
+
"output/loops": "8a0dd93b95e1b9c2a29344e6b41cb5cec6b7afc5",
|
|
21
|
+
"output/modules": "15735b9b07260d11ba231fc3439818bd1a54947e",
|
|
22
|
+
"output/operators": "14b23f4a3ab3b1997411b8ec9f0f57d3e76a7da0",
|
|
23
|
+
"output/statements": "94ee0cd084f22aea451b96eb1a9a831084cc4267",
|
|
24
|
+
"output/stream": "2723d80bc398468e0828f50fb0837095c52f45dc",
|
|
25
|
+
"output/treeshake": "c1d65269ff21cfd046e947755a3489d0e670a74a",
|
|
23
26
|
"output/utils": "595968f96f6fdcc51eb41c34d64c92bb595e3cb1",
|
|
24
|
-
"parse": "
|
|
27
|
+
"parse": "0643834ed3c98d350ceb9ec71179f8923974c08c",
|
|
25
28
|
"string_interpolation": "bff1cc76d772d24d35707f6c794f38734ca08376",
|
|
26
|
-
"tokenizer": "
|
|
29
|
+
"tokenizer": "134f46d5a10576c6a27d4fe024c63f45e111fefe",
|
|
27
30
|
"unicode_aliases": "79ac6eaa5e6be44a5397d62c561f854a8fe7528e",
|
|
28
31
|
"utils": "c1666db819aa7c8db38697e34e18362e3cb45869",
|
|
29
|
-
"#compiler#": "
|
|
30
|
-
"#compiled_with#": "
|
|
32
|
+
"#compiler#": "d41c267ea92de4937495c7d35c8d50e1b48f550c",
|
|
33
|
+
"#compiled_with#": "d41c267ea92de4937495c7d35c8d50e1b48f550c"
|
|
31
34
|
}
|
package/src/ast.pyj
CHANGED
|
@@ -600,6 +600,9 @@ class AST_Class(AST_Scope):
|
|
|
600
600
|
'statements': "[AST_Node*] list of statements in the class scope (excluding method definitions)",
|
|
601
601
|
'dynamic_properties': '[dict] map of dynamic property names to property descriptors of the form {getter:AST_Method, setter:AST_Method',
|
|
602
602
|
'classvars': '[dict] map containing all class variables as keys, to be used to easily test for existence of a class variable',
|
|
603
|
+
'has_new': "[boolean] true if the class defines a __new__ method",
|
|
604
|
+
'has_attr_dunders': "[boolean] true if the class defines any of __getattr__/__setattr__/__delattr__/__getattribute__",
|
|
605
|
+
'class_kwargs': "[array] keyword arguments from class header (e.g. class C(Base, key=val):) as [[key_node, value_node], ...]",
|
|
603
606
|
}
|
|
604
607
|
|
|
605
608
|
def _walk(self, visitor):
|
|
@@ -610,6 +613,9 @@ class AST_Class(AST_Scope):
|
|
|
610
613
|
self.name._walk(visitor)
|
|
611
614
|
walk_body(self, visitor)
|
|
612
615
|
if (self.parent) self.parent._walk(visitor)
|
|
616
|
+
if self.class_kwargs:
|
|
617
|
+
for kw in self.class_kwargs:
|
|
618
|
+
kw[1]._walk(visitor)
|
|
613
619
|
)
|
|
614
620
|
|
|
615
621
|
class AST_Method(AST_Lambda):
|
|
@@ -725,7 +731,8 @@ class AST_Except(AST_Block):
|
|
|
725
731
|
"An `except` node for RapydScript, which resides inside the catch block"
|
|
726
732
|
properties = {
|
|
727
733
|
'argname': "[AST_SymbolCatch] symbol for the exception",
|
|
728
|
-
'errors': "[AST_SymbolVar*] error classes to catch in this block"
|
|
734
|
+
'errors': "[AST_SymbolVar*] error classes to catch in this block",
|
|
735
|
+
'is_star': '[bool] True for except* (exception group) clauses',
|
|
729
736
|
}
|
|
730
737
|
|
|
731
738
|
def _walk(self, visitor):
|
|
@@ -981,6 +988,7 @@ class AST_Binary(AST_Node):
|
|
|
981
988
|
'operator': "[string] the operator",
|
|
982
989
|
'right': "[AST_Node] right-hand side expression",
|
|
983
990
|
'overloaded': "[bool] Whether to use Python-style operator overloading dispatch",
|
|
991
|
+
'strict_arith': "[bool] Whether incompatible operand types raise TypeError (default True when overloaded; disable with no_strict_arithmetic)",
|
|
984
992
|
'python_truthiness': "[bool] Whether to use Python truthiness (from __python__ import truthiness)"
|
|
985
993
|
}
|
|
986
994
|
|
|
@@ -1161,6 +1169,17 @@ class AST_ObjectSpread(AST_Node):
|
|
|
1161
1169
|
self.value._walk(visitor)
|
|
1162
1170
|
)
|
|
1163
1171
|
|
|
1172
|
+
class AST_Spread(AST_Node):
|
|
1173
|
+
"A *expr spread item inside a list or set literal: [1, *a, 2]"
|
|
1174
|
+
properties = {
|
|
1175
|
+
'expression': "[AST_Node] the expression being spread",
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
def _walk(self, visitor):
|
|
1179
|
+
return visitor._visit(self, def():
|
|
1180
|
+
self.expression._walk(visitor)
|
|
1181
|
+
)
|
|
1182
|
+
|
|
1164
1183
|
class AST_Set(AST_Node):
|
|
1165
1184
|
"A set literal"
|
|
1166
1185
|
properties = {
|
|
@@ -1360,6 +1379,80 @@ class TreeWalker:
|
|
|
1360
1379
|
self = p
|
|
1361
1380
|
# }}}
|
|
1362
1381
|
|
|
1382
|
+
# JSX nodes {{{
|
|
1383
|
+
|
|
1384
|
+
class AST_JSXElement(AST_Node):
|
|
1385
|
+
"A JSX element like <div>...</div> or <Component />"
|
|
1386
|
+
properties = {
|
|
1387
|
+
'tag': "[string] The tag name (e.g. 'div', 'MyComponent')",
|
|
1388
|
+
'props': "[AST_JSXAttribute[]] The props/attributes",
|
|
1389
|
+
'children': "[AST_Node[]] The children",
|
|
1390
|
+
'self_closing': "[bool] Whether self-closing (no children)"
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
def _walk(self, visitor):
|
|
1394
|
+
return visitor._visit(self, def():
|
|
1395
|
+
for prop in self.props:
|
|
1396
|
+
prop._walk(visitor)
|
|
1397
|
+
for child in self.children:
|
|
1398
|
+
child._walk(visitor)
|
|
1399
|
+
)
|
|
1400
|
+
|
|
1401
|
+
class AST_JSXFragment(AST_Node):
|
|
1402
|
+
"A JSX fragment <>...</>"
|
|
1403
|
+
properties = {
|
|
1404
|
+
'children': "[AST_Node[]] The children"
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
def _walk(self, visitor):
|
|
1408
|
+
return visitor._visit(self, def():
|
|
1409
|
+
for child in self.children:
|
|
1410
|
+
child._walk(visitor)
|
|
1411
|
+
)
|
|
1412
|
+
|
|
1413
|
+
class AST_JSXAttribute(AST_Node):
|
|
1414
|
+
"A JSX attribute like prop='val', prop={expr}, or just prop (boolean)"
|
|
1415
|
+
properties = {
|
|
1416
|
+
'name': "[string] The attribute name",
|
|
1417
|
+
'value': "[AST_Node|null] The value (null for boolean attrs)"
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
def _walk(self, visitor):
|
|
1421
|
+
return visitor._visit(self, def():
|
|
1422
|
+
if self.value:
|
|
1423
|
+
self.value._walk(visitor)
|
|
1424
|
+
)
|
|
1425
|
+
|
|
1426
|
+
class AST_JSXSpread(AST_Node):
|
|
1427
|
+
"A JSX spread attribute {...expr}"
|
|
1428
|
+
properties = {
|
|
1429
|
+
'expression': "[AST_Node] The spread expression"
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
def _walk(self, visitor):
|
|
1433
|
+
return visitor._visit(self, def():
|
|
1434
|
+
self.expression._walk(visitor)
|
|
1435
|
+
)
|
|
1436
|
+
|
|
1437
|
+
class AST_JSXText(AST_Node):
|
|
1438
|
+
"Text content inside a JSX element"
|
|
1439
|
+
properties = {
|
|
1440
|
+
'value': "[string] The text content"
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
class AST_JSXExprContainer(AST_Node):
|
|
1444
|
+
"A JSX expression container {expr}"
|
|
1445
|
+
properties = {
|
|
1446
|
+
'expression': "[AST_Node] The expression"
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
def _walk(self, visitor):
|
|
1450
|
+
return visitor._visit(self, def():
|
|
1451
|
+
self.expression._walk(visitor)
|
|
1452
|
+
)
|
|
1453
|
+
|
|
1454
|
+
# }}}
|
|
1455
|
+
|
|
1363
1456
|
class Found(Exception):
|
|
1364
1457
|
pass
|
|
1365
1458
|
|
package/src/baselib-builtins.pyj
CHANGED
|
@@ -20,6 +20,7 @@ def ρσ_bool(val):
|
|
|
20
20
|
v'if ((typeof Set === "function" && val instanceof Set) || (typeof Map === "function" && val instanceof Map)) return val.size > 0'
|
|
21
21
|
v'if (!val.constructor || val.constructor === Object) return Object.keys(val).length > 0'
|
|
22
22
|
return True
|
|
23
|
+
ρσ_bool.__name__ = 'bool'
|
|
23
24
|
|
|
24
25
|
def ρσ_print(*args, **kwargs):
|
|
25
26
|
if v'typeof console' is 'object':
|
|
@@ -35,6 +36,7 @@ def ρσ_int(val, base):
|
|
|
35
36
|
if isNaN(ans):
|
|
36
37
|
raise ValueError('Invalid literal for int with base ' + (base or 10) + ': ' + val)
|
|
37
38
|
return ans
|
|
39
|
+
ρσ_int.__name__ = 'int'
|
|
38
40
|
|
|
39
41
|
def ρσ_float(val):
|
|
40
42
|
if jstype(val) is "number":
|
|
@@ -44,6 +46,7 @@ def ρσ_float(val):
|
|
|
44
46
|
if isNaN(ans):
|
|
45
47
|
raise ValueError('Could not convert string to float: ' + arguments[0])
|
|
46
48
|
return ans
|
|
49
|
+
ρσ_float.__name__ = 'float'
|
|
47
50
|
|
|
48
51
|
def ρσ_arraylike_creator():
|
|
49
52
|
names = 'Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array'.split(' ')
|
|
@@ -282,6 +285,23 @@ def ρσ_hasattr(obj, name):
|
|
|
282
285
|
def ρσ_get_module(name):
|
|
283
286
|
return ρσ_modules[name]
|
|
284
287
|
|
|
288
|
+
def ρσ__import__(name, globals, locals, fromlist, level):
|
|
289
|
+
# Return the module from the already-compiled ρσ_modules registry.
|
|
290
|
+
# Like Python: without fromlist (or empty fromlist) returns the top-level
|
|
291
|
+
# package; with a non-empty fromlist returns the named (possibly dotted) module.
|
|
292
|
+
# NOTE: the module must have been statically imported elsewhere in the source;
|
|
293
|
+
# __import__ only provides a runtime reference to an already-compiled module.
|
|
294
|
+
if v'typeof ρσ_modules' is 'undefined':
|
|
295
|
+
raise ImportError('No module named \'' + name + '\'')
|
|
296
|
+
if fromlist is not undefined and fromlist is not None and fromlist.length:
|
|
297
|
+
lookup = name
|
|
298
|
+
else:
|
|
299
|
+
lookup = name.split('.')[0]
|
|
300
|
+
module = ρσ_modules[lookup]
|
|
301
|
+
if module is undefined:
|
|
302
|
+
raise ModuleNotFoundError('No module named \'' + lookup + '\'')
|
|
303
|
+
return module
|
|
304
|
+
|
|
285
305
|
def ρσ_pow(x, y, z):
|
|
286
306
|
ans = Math.pow(x, y)
|
|
287
307
|
if z is not undefined:
|
|
@@ -322,6 +342,7 @@ def ρσ_hash(obj):
|
|
|
322
342
|
}
|
|
323
343
|
return ρσ_h;
|
|
324
344
|
}'''
|
|
345
|
+
v'if (obj.__hash__ === null) throw new TypeError("unhashable type: \'" + (obj.constructor && obj.constructor.name ? obj.constructor.name : "object") + "\'")'
|
|
325
346
|
v'if (typeof obj.__hash__ === "function") return obj.__hash__()'
|
|
326
347
|
v'if (Array.isArray(obj)) throw new TypeError("unhashable type: \'list\'")'
|
|
327
348
|
v'if (typeof ρσ_set === "function" && obj instanceof ρσ_set) throw new TypeError("unhashable type: \'set\'")'
|
|
@@ -438,12 +459,350 @@ class ρσ_slice:
|
|
|
438
459
|
raise TypeError("unhashable type: 'slice'")
|
|
439
460
|
|
|
440
461
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
462
|
+
class ρσ_object:
|
|
463
|
+
def __init__(self):
|
|
464
|
+
pass
|
|
465
|
+
|
|
466
|
+
def __repr__(self):
|
|
467
|
+
v'if (this.ρσ_object_id === undefined) this.ρσ_object_id = ++ρσ_hash_id_counter'
|
|
468
|
+
return '<object object at 0x' + v'this.ρσ_object_id.toString(16)'+ '>'
|
|
469
|
+
|
|
470
|
+
def __str__(self):
|
|
471
|
+
return self.__repr__()
|
|
472
|
+
|
|
473
|
+
def __eq__(self, other):
|
|
474
|
+
return self is other
|
|
475
|
+
|
|
476
|
+
def __hash__(self):
|
|
477
|
+
v'if (this.ρσ_object_id === undefined) this.ρσ_object_id = ++ρσ_hash_id_counter'
|
|
478
|
+
return self.ρσ_object_id
|
|
479
|
+
|
|
480
|
+
ρσ_object.__name__ = 'object'
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def ρσ_exec(code, globals, locals):
|
|
484
|
+
# Execute a string of JavaScript/RapydScript-compiled code, like Python's exec.
|
|
485
|
+
# Always returns None. Without globals/locals uses indirect eval (global scope).
|
|
486
|
+
# With globals/locals uses the Function constructor so the code can reference the
|
|
487
|
+
# supplied variables; mutable object arguments (lists, dicts) are passed by
|
|
488
|
+
# reference so side-effects (e.g. array.push) are visible in the caller.
|
|
489
|
+
# Handles both plain JS objects and Python ρσ_dict instances (jsmap-backed Map).
|
|
490
|
+
# ρσ_ helpers referenced in compiled strings are injected from the current scope.
|
|
491
|
+
if globals is undefined:
|
|
492
|
+
v'eval(code)'
|
|
493
|
+
return None
|
|
494
|
+
v'''
|
|
495
|
+
function _ρσ_to_obj(d) {
|
|
496
|
+
if (d == null) return {};
|
|
497
|
+
if (typeof ρσ_dict === "function" && d instanceof ρσ_dict) {
|
|
498
|
+
var _r = {}; d.jsmap.forEach(function(v, k) { _r[k] = v; }); return _r;
|
|
499
|
+
}
|
|
500
|
+
return Object.assign({}, d);
|
|
501
|
+
}
|
|
502
|
+
var _ctx = _ρσ_to_obj(globals);
|
|
503
|
+
if (locals !== undefined) Object.assign(_ctx, _ρσ_to_obj(locals));
|
|
504
|
+
var _rσ_refs = code.match(/ρσ_\w+/g) || [];
|
|
505
|
+
_rσ_refs.forEach(function(name) {
|
|
506
|
+
if (!Object.prototype.hasOwnProperty.call(_ctx, name)) {
|
|
507
|
+
try { var _v = eval(name); if (_v !== undefined) _ctx[name] = _v; } catch(e) {}
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
var _keys = Object.keys(_ctx);
|
|
511
|
+
var _vals = _keys.map(function(k) { return _ctx[k]; });
|
|
512
|
+
Function.apply(null, _keys.concat([code])).apply(null, _vals);
|
|
513
|
+
'''
|
|
514
|
+
return None
|
|
515
|
+
ρσ_exec.__name__ = 'exec'
|
|
516
|
+
|
|
517
|
+
def ρσ_eval(expr, globals, locals):
|
|
518
|
+
# Called only when 2 or 3 args are provided (scoped eval via Function constructor).
|
|
519
|
+
# The compiler emits ρσ_eval() only when globals/locals are supplied; the
|
|
520
|
+
# plain 1-arg eval(expr) stays as a native direct JS eval call.
|
|
521
|
+
# Handles both plain JS objects and Python ρσ_dict instances (jsmap-backed Map).
|
|
522
|
+
# ρσ_ helpers referenced in compiled strings are injected from the current scope.
|
|
523
|
+
v'''
|
|
524
|
+
function _ρσ_to_obj(d) {
|
|
525
|
+
if (d == null) return {};
|
|
526
|
+
if (typeof ρσ_dict === "function" && d instanceof ρσ_dict) {
|
|
527
|
+
var _r = {}; d.jsmap.forEach(function(v, k) { _r[k] = v; }); return _r;
|
|
528
|
+
}
|
|
529
|
+
return Object.assign({}, d);
|
|
530
|
+
}
|
|
531
|
+
var _ctx = (globals !== undefined) ? _ρσ_to_obj(globals) : {};
|
|
532
|
+
if (locals !== undefined) Object.assign(_ctx, _ρσ_to_obj(locals));
|
|
533
|
+
var _rσ_refs = expr.match(/ρσ_\w+/g) || [];
|
|
534
|
+
_rσ_refs.forEach(function(name) {
|
|
535
|
+
if (!Object.prototype.hasOwnProperty.call(_ctx, name)) {
|
|
536
|
+
try { var _v = eval(name); if (_v !== undefined) _ctx[name] = _v; } catch(e) {}
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
var _keys = Object.keys(_ctx);
|
|
540
|
+
var _vals = _keys.map(function(k) { return _ctx[k]; });
|
|
541
|
+
return Function.apply(null, _keys.concat(['return (' + expr + ')'])).apply(null, _vals);
|
|
542
|
+
'''
|
|
543
|
+
ρσ_eval.__name__ = 'eval'
|
|
544
|
+
|
|
545
|
+
def ρσ_vars(obj):
|
|
546
|
+
# vars(obj) -> dict of obj's own instance attributes (like Python's obj.__dict__)
|
|
547
|
+
# vars() -> compiler rewrites to vars(this) — see output/functions.pyj
|
|
548
|
+
v'''
|
|
549
|
+
var _d;
|
|
550
|
+
if (typeof ρσ_dict === "function") {
|
|
551
|
+
_d = new ρσ_dict();
|
|
552
|
+
if (obj !== undefined && obj !== null) {
|
|
553
|
+
Object.keys(obj).forEach(function(k) {
|
|
554
|
+
if (k.charCodeAt(0) !== 0x03c1) { _d.jsmap.set(k, obj[k]); }
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
} else {
|
|
558
|
+
_d = Object.create(null);
|
|
559
|
+
if (obj !== undefined && obj !== null) {
|
|
560
|
+
Object.keys(obj).forEach(function(k) {
|
|
561
|
+
if (k.charCodeAt(0) !== 0x03c1) { _d[k] = obj[k]; }
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
'''
|
|
566
|
+
return v'_d'
|
|
567
|
+
ρσ_vars.__name__ = 'vars'
|
|
568
|
+
|
|
569
|
+
def ρσ_locals():
|
|
570
|
+
# In JavaScript, local scope cannot be introspected at runtime.
|
|
571
|
+
# Returns an empty dict as an approximation.
|
|
572
|
+
v'''
|
|
573
|
+
var _d;
|
|
574
|
+
if (typeof ρσ_dict === "function") { _d = new ρσ_dict(); } else { _d = Object.create(null); }
|
|
575
|
+
'''
|
|
576
|
+
return v'_d'
|
|
577
|
+
ρσ_locals.__name__ = 'locals'
|
|
578
|
+
|
|
579
|
+
def ρσ_globals():
|
|
580
|
+
# Returns a snapshot dict of the JS global object's own enumerable properties.
|
|
581
|
+
# In a browser this covers window.*; in Node.js this covers globalThis/global.*.
|
|
582
|
+
# Note: module-level RapydScript variables compiled inside an IIFE/module
|
|
583
|
+
# wrapper will NOT appear here — use a plain dict to share state instead.
|
|
584
|
+
v'''
|
|
585
|
+
var _g = (typeof globalThis !== "undefined") ? globalThis : (typeof window !== "undefined" ? window : (typeof global !== "undefined" ? global : {}));
|
|
586
|
+
var _d;
|
|
587
|
+
if (typeof ρσ_dict === "function") {
|
|
588
|
+
_d = new ρσ_dict();
|
|
589
|
+
Object.getOwnPropertyNames(_g).forEach(function(k) { _d.jsmap.set(k, _g[k]); });
|
|
590
|
+
} else {
|
|
591
|
+
_d = Object.create(null);
|
|
592
|
+
Object.getOwnPropertyNames(_g).forEach(function(k) { _d[k] = _g[k]; });
|
|
593
|
+
}
|
|
594
|
+
'''
|
|
595
|
+
return v'_d'
|
|
596
|
+
ρσ_globals.__name__ = 'globals'
|
|
597
|
+
|
|
598
|
+
def ρσ_abs(x):
|
|
599
|
+
if x is not None and jstype(x.__abs__) is 'function':
|
|
600
|
+
return x.__abs__()
|
|
601
|
+
return Math.abs(x)
|
|
602
|
+
ρσ_abs.__name__ = 'abs'
|
|
603
|
+
|
|
604
|
+
class ρσ_complex:
|
|
605
|
+
def __init__(self, real, imag):
|
|
606
|
+
nargs = arguments.length
|
|
607
|
+
if nargs is 0:
|
|
608
|
+
self.real = 0.0
|
|
609
|
+
self.imag = 0.0
|
|
610
|
+
elif nargs >= 2:
|
|
611
|
+
if jstype(real) is not 'number' and jstype(real) is not 'boolean':
|
|
612
|
+
raise TypeError("complex() first argument must be a number, not '" + jstype(real) + "'")
|
|
613
|
+
if jstype(imag) is not 'number' and jstype(imag) is not 'boolean':
|
|
614
|
+
raise TypeError("complex() second argument must be a number, not '" + jstype(imag) + "'")
|
|
615
|
+
self.real = +real
|
|
616
|
+
self.imag = +imag
|
|
617
|
+
else:
|
|
618
|
+
x = real
|
|
619
|
+
if v'x instanceof ρσ_complex':
|
|
620
|
+
self.real = x.real
|
|
621
|
+
self.imag = x.imag
|
|
622
|
+
elif jstype(x) is 'number' or jstype(x) is 'boolean':
|
|
623
|
+
self.real = +x
|
|
624
|
+
self.imag = 0.0
|
|
625
|
+
elif jstype(x) is 'string' or v'x instanceof String':
|
|
626
|
+
s = String(x).trim()
|
|
627
|
+
m_mixed = v'/^([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)([+-](?:(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)?)[jJ]$/.exec(s)'
|
|
628
|
+
m_imag = v'/^([+-]?(?:(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)?)[jJ]$/.exec(s)'
|
|
629
|
+
m_real = v'/^([+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?)$/.exec(s)'
|
|
630
|
+
if m_mixed:
|
|
631
|
+
self.real = parseFloat(m_mixed[1])
|
|
632
|
+
ims = m_mixed[2]
|
|
633
|
+
if ims is '+': self.imag = 1.0
|
|
634
|
+
elif ims is '-': self.imag = -1.0
|
|
635
|
+
else: self.imag = parseFloat(ims)
|
|
636
|
+
elif m_imag:
|
|
637
|
+
self.real = 0.0
|
|
638
|
+
ims = m_imag[1]
|
|
639
|
+
if not ims or ims is '+': self.imag = 1.0
|
|
640
|
+
elif ims is '-': self.imag = -1.0
|
|
641
|
+
else: self.imag = parseFloat(ims)
|
|
642
|
+
elif m_real:
|
|
643
|
+
self.real = parseFloat(m_real[1])
|
|
644
|
+
self.imag = 0.0
|
|
645
|
+
else:
|
|
646
|
+
raise ValueError("complex() arg is a malformed string")
|
|
647
|
+
else:
|
|
648
|
+
raise TypeError("complex() argument must be a string or a number")
|
|
649
|
+
|
|
650
|
+
def __add__(self, other):
|
|
651
|
+
if v'other instanceof ρσ_complex':
|
|
652
|
+
return new ρσ_complex(self.real + other.real, self.imag + other.imag)
|
|
653
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
654
|
+
return new ρσ_complex(self.real + other, self.imag)
|
|
655
|
+
raise TypeError("unsupported operand type(s) for +: 'complex' and '" + jstype(other) + "'")
|
|
656
|
+
|
|
657
|
+
def __radd__(self, other):
|
|
658
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
659
|
+
return new ρσ_complex(other + self.real, self.imag)
|
|
660
|
+
if v'other instanceof ρσ_complex':
|
|
661
|
+
return new ρσ_complex(other.real + self.real, other.imag + self.imag)
|
|
662
|
+
raise TypeError("unsupported operand type(s) for +: '" + jstype(other) + "' and 'complex'")
|
|
663
|
+
|
|
664
|
+
def __sub__(self, other):
|
|
665
|
+
if v'other instanceof ρσ_complex':
|
|
666
|
+
return new ρσ_complex(self.real - other.real, self.imag - other.imag)
|
|
667
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
668
|
+
return new ρσ_complex(self.real - other, self.imag)
|
|
669
|
+
raise TypeError("unsupported operand type(s) for -: 'complex' and '" + jstype(other) + "'")
|
|
670
|
+
|
|
671
|
+
def __rsub__(self, other):
|
|
672
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
673
|
+
return new ρσ_complex(other - self.real, -self.imag)
|
|
674
|
+
if v'other instanceof ρσ_complex':
|
|
675
|
+
return new ρσ_complex(other.real - self.real, other.imag - self.imag)
|
|
676
|
+
raise TypeError("unsupported operand type(s) for -: '" + jstype(other) + "' and 'complex'")
|
|
677
|
+
|
|
678
|
+
def __mul__(self, other):
|
|
679
|
+
if v'other instanceof ρσ_complex':
|
|
680
|
+
return new ρσ_complex(
|
|
681
|
+
self.real * other.real - self.imag * other.imag,
|
|
682
|
+
self.real * other.imag + self.imag * other.real
|
|
683
|
+
)
|
|
684
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
685
|
+
return new ρσ_complex(self.real * other, self.imag * other)
|
|
686
|
+
raise TypeError("unsupported operand type(s) for *: 'complex' and '" + jstype(other) + "'")
|
|
687
|
+
|
|
688
|
+
def __rmul__(self, other):
|
|
689
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
690
|
+
return new ρσ_complex(other * self.real, other * self.imag)
|
|
691
|
+
if v'other instanceof ρσ_complex':
|
|
692
|
+
return new ρσ_complex(
|
|
693
|
+
other.real * self.real - other.imag * self.imag,
|
|
694
|
+
other.real * self.imag + other.imag * self.real
|
|
695
|
+
)
|
|
696
|
+
raise TypeError("unsupported operand type(s) for *: '" + jstype(other) + "' and 'complex'")
|
|
697
|
+
|
|
698
|
+
def __truediv__(self, other):
|
|
699
|
+
if v'other instanceof ρσ_complex':
|
|
700
|
+
denom = other.real * other.real + other.imag * other.imag
|
|
701
|
+
if denom is 0: raise ZeroDivisionError('complex division by zero')
|
|
702
|
+
return new ρσ_complex(
|
|
703
|
+
(self.real * other.real + self.imag * other.imag) / denom,
|
|
704
|
+
(self.imag * other.real - self.real * other.imag) / denom
|
|
705
|
+
)
|
|
706
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
707
|
+
if other is 0: raise ZeroDivisionError('complex division by zero')
|
|
708
|
+
return new ρσ_complex(self.real / other, self.imag / other)
|
|
709
|
+
raise TypeError("unsupported operand type(s) for /: 'complex' and '" + jstype(other) + "'")
|
|
710
|
+
|
|
711
|
+
def __rtruediv__(self, other):
|
|
712
|
+
denom = self.real * self.real + self.imag * self.imag
|
|
713
|
+
if denom is 0: raise ZeroDivisionError('complex division by zero')
|
|
714
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
715
|
+
return new ρσ_complex(other * self.real / denom, -other * self.imag / denom)
|
|
716
|
+
if v'other instanceof ρσ_complex':
|
|
717
|
+
return new ρσ_complex(
|
|
718
|
+
(other.real * self.real + other.imag * self.imag) / denom,
|
|
719
|
+
(other.imag * self.real - other.real * self.imag) / denom
|
|
720
|
+
)
|
|
721
|
+
raise TypeError("unsupported operand type(s) for /: '" + jstype(other) + "' and 'complex'")
|
|
722
|
+
|
|
723
|
+
def __pow__(self, other):
|
|
724
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
725
|
+
r = Math.sqrt(self.real * self.real + self.imag * self.imag)
|
|
726
|
+
if r is 0: return new ρσ_complex(0, 0)
|
|
727
|
+
theta = Math.atan2(self.imag, self.real)
|
|
728
|
+
rn = Math.pow(r, other)
|
|
729
|
+
return new ρσ_complex(rn * Math.cos(other * theta), rn * Math.sin(other * theta))
|
|
730
|
+
if v'other instanceof ρσ_complex':
|
|
731
|
+
r = Math.sqrt(self.real * self.real + self.imag * self.imag)
|
|
732
|
+
if r is 0: return new ρσ_complex(0, 0)
|
|
733
|
+
theta = Math.atan2(self.imag, self.real)
|
|
734
|
+
log_r = Math.log(r)
|
|
735
|
+
c = other.real
|
|
736
|
+
d = other.imag
|
|
737
|
+
re_prod = c * log_r - d * theta
|
|
738
|
+
im_prod = d * log_r + c * theta
|
|
739
|
+
exp_re = Math.exp(re_prod)
|
|
740
|
+
return new ρσ_complex(exp_re * Math.cos(im_prod), exp_re * Math.sin(im_prod))
|
|
741
|
+
raise TypeError("unsupported operand type(s) for **: 'complex' and '" + jstype(other) + "'")
|
|
742
|
+
|
|
743
|
+
def __rpow__(self, other):
|
|
744
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
745
|
+
base = new ρσ_complex(other, 0)
|
|
746
|
+
return base.__pow__(self)
|
|
747
|
+
if v'other instanceof ρσ_complex':
|
|
748
|
+
return other.__pow__(self)
|
|
749
|
+
raise TypeError("unsupported operand type(s) for **: '" + jstype(other) + "' and 'complex'")
|
|
750
|
+
|
|
751
|
+
def __neg__(self):
|
|
752
|
+
return new ρσ_complex(-self.real, -self.imag)
|
|
753
|
+
|
|
754
|
+
def __pos__(self):
|
|
755
|
+
return new ρσ_complex(self.real, self.imag)
|
|
756
|
+
|
|
757
|
+
def __abs__(self):
|
|
758
|
+
return Math.sqrt(self.real * self.real + self.imag * self.imag)
|
|
759
|
+
|
|
760
|
+
def __bool__(self):
|
|
761
|
+
return self.real is not 0 or self.imag is not 0
|
|
762
|
+
|
|
763
|
+
def __eq__(self, other):
|
|
764
|
+
if v'other instanceof ρσ_complex':
|
|
765
|
+
return self.real is other.real and self.imag is other.imag
|
|
766
|
+
if jstype(other) is 'number' or jstype(other) is 'boolean':
|
|
767
|
+
return self.imag is 0 and self.real is other
|
|
768
|
+
return False
|
|
769
|
+
|
|
770
|
+
def __hash__(self):
|
|
771
|
+
if self.imag is 0:
|
|
772
|
+
return self.real | 0
|
|
773
|
+
return v'(self.real * 1000003 ^ self.imag) | 0'
|
|
774
|
+
|
|
775
|
+
def conjugate(self):
|
|
776
|
+
return new ρσ_complex(self.real, -self.imag)
|
|
777
|
+
|
|
778
|
+
def __repr__(self):
|
|
779
|
+
r = self.real
|
|
780
|
+
i = self.imag
|
|
781
|
+
if r is 0 and i is 0: return '0j'
|
|
782
|
+
r_str = String(r)
|
|
783
|
+
i_str = String(i)
|
|
784
|
+
if r is 0:
|
|
785
|
+
return i_str + 'j'
|
|
786
|
+
if i >= 0 or isNaN(i):
|
|
787
|
+
return '(' + r_str + '+' + i_str + 'j)'
|
|
788
|
+
return '(' + r_str + i_str + 'j)'
|
|
789
|
+
|
|
790
|
+
def __str__(self):
|
|
791
|
+
return self.__repr__()
|
|
792
|
+
|
|
793
|
+
ρσ_complex.__name__ = 'complex'
|
|
794
|
+
|
|
795
|
+
v'var abs = ρσ_abs, max = ρσ_max.bind(Math.max), min = ρσ_max.bind(Math.min), bool = ρσ_bool, type = ρσ_type'
|
|
796
|
+
v'var float = ρσ_float, int = ρσ_int, complex = ρσ_complex, arraylike = ρσ_arraylike_creator(), ρσ_arraylike = arraylike'
|
|
797
|
+
v'var id = ρσ_id, get_module = ρσ_get_module, pow = ρσ_pow, divmod = ρσ_divmod, __import__ = ρσ__import__'
|
|
444
798
|
v'var dir = ρσ_dir, ord = ρσ_ord, chr = ρσ_chr, bin = ρσ_bin, hex = ρσ_hex, callable = ρσ_callable, round = ρσ_round'
|
|
445
799
|
v'var enumerate = ρσ_enumerate, iter = ρσ_iter, reversed = ρσ_reversed, len = ρσ_len'
|
|
446
800
|
v'var range = ρσ_range, getattr = ρσ_getattr, setattr = ρσ_setattr, hasattr = ρσ_hasattr, issubclass = ρσ_issubclass, hash = ρσ_hash, next = ρσ_next'
|
|
801
|
+
v'var exec = ρσ_exec'
|
|
802
|
+
v'var vars = ρσ_vars, locals = ρσ_locals, globals = ρσ_globals'
|
|
447
803
|
v'var ρσ_Ellipsis = Object.freeze({toString: function(){return "Ellipsis";}, __repr__: function(){return "Ellipsis";}})'
|
|
448
804
|
v'var Ellipsis = ρσ_Ellipsis'
|
|
449
805
|
v'var slice = ρσ_slice'
|
|
806
|
+
v'var object = ρσ_object'
|
|
807
|
+
v'Number.prototype.is_integer = function() { return isFinite(+this) && (+this) % 1 === 0; }'
|
|
808
|
+
v'Number.prototype.bit_length = function() { var n = Math.abs(Math.trunc(+this)); if (n === 0) return 0; return Math.floor(Math.log2(n)) + 1; }'
|