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.
Files changed (72) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1351 -141
  3. package/TODO.md +12 -6
  4. package/language-service/index.js +184 -26
  5. package/package.json +1 -1
  6. package/release/baselib-plain-pretty.js +5895 -1928
  7. package/release/baselib-plain-ugly.js +140 -3
  8. package/release/compiler.js +16282 -5408
  9. package/release/signatures.json +25 -22
  10. package/src/ast.pyj +94 -1
  11. package/src/baselib-builtins.pyj +362 -3
  12. package/src/baselib-bytes.pyj +664 -0
  13. package/src/baselib-containers.pyj +99 -0
  14. package/src/baselib-errors.pyj +45 -1
  15. package/src/baselib-internal.pyj +346 -49
  16. package/src/baselib-itertools.pyj +17 -4
  17. package/src/baselib-str.pyj +46 -4
  18. package/src/lib/abc.pyj +317 -0
  19. package/src/lib/copy.pyj +120 -0
  20. package/src/lib/dataclasses.pyj +532 -0
  21. package/src/lib/enum.pyj +125 -0
  22. package/src/lib/pythonize.pyj +1 -1
  23. package/src/lib/re.pyj +35 -1
  24. package/src/lib/react.pyj +74 -0
  25. package/src/lib/typing.pyj +577 -0
  26. package/src/monaco-language-service/builtins.js +19 -4
  27. package/src/monaco-language-service/diagnostics.js +40 -19
  28. package/src/output/classes.pyj +161 -25
  29. package/src/output/codegen.pyj +16 -2
  30. package/src/output/exceptions.pyj +97 -1
  31. package/src/output/functions.pyj +87 -5
  32. package/src/output/jsx.pyj +164 -0
  33. package/src/output/literals.pyj +28 -2
  34. package/src/output/loops.pyj +5 -2
  35. package/src/output/modules.pyj +1 -1
  36. package/src/output/operators.pyj +108 -36
  37. package/src/output/statements.pyj +2 -2
  38. package/src/output/stream.pyj +1 -0
  39. package/src/parse.pyj +496 -128
  40. package/src/tokenizer.pyj +38 -4
  41. package/test/abc.pyj +291 -0
  42. package/test/arithmetic_nostrict.pyj +88 -0
  43. package/test/arithmetic_types.pyj +169 -0
  44. package/test/baselib.pyj +91 -0
  45. package/test/bytes.pyj +467 -0
  46. package/test/classes.pyj +1 -0
  47. package/test/comparison_ops.pyj +173 -0
  48. package/test/dataclasses.pyj +253 -0
  49. package/test/enum.pyj +134 -0
  50. package/test/eval_exec.pyj +56 -0
  51. package/test/format.pyj +148 -0
  52. package/test/object.pyj +64 -0
  53. package/test/python_compat.pyj +17 -15
  54. package/test/python_features.pyj +89 -21
  55. package/test/regexp.pyj +29 -1
  56. package/test/tuples.pyj +96 -0
  57. package/test/typing.pyj +469 -0
  58. package/test/unit/index.js +2292 -70
  59. package/test/unit/language-service.js +674 -4
  60. package/test/unit/web-repl.js +1106 -0
  61. package/test/vars_locals_globals.pyj +94 -0
  62. package/tools/cli.js +11 -0
  63. package/tools/compile.js +5 -0
  64. package/tools/embedded_compiler.js +15 -4
  65. package/tools/lint.js +16 -19
  66. package/tools/repl.js +1 -1
  67. package/web-repl/env.js +122 -0
  68. package/web-repl/main.js +1 -3
  69. package/web-repl/rapydscript.js +125 -3
  70. package/PYTHON_DIFFERENCES_REPORT.md +0 -291
  71. package/PYTHON_FEATURE_COVERAGE.md +0 -200
  72. package/hack_demo.pyj +0 -112
@@ -0,0 +1,317 @@
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD
3
+ # RapydScript implementation of Python's abc standard library.
4
+ #
5
+ # Supported:
6
+ # ABC — base class for abstract base classes
7
+ # @abstractmethod — decorator marking a method as abstract
8
+ # Protocol — base class for structural subtyping (PEP 544)
9
+ # @runtime_checkable — allow isinstance() structural checks on Protocol
10
+ # ABCMeta — informational placeholder (not a real metaclass)
11
+ # get_cache_token() — returns 0
12
+ #
13
+ # Usage:
14
+ # from abc import ABC, abstractmethod
15
+ #
16
+ # class Shape(ABC):
17
+ # @abstractmethod
18
+ # def area(self): pass
19
+ #
20
+ # class Circle(Shape):
21
+ # def __init__(self, r):
22
+ # self.r = r
23
+ # def area(self):
24
+ # return 3.14159 * self.r * self.r
25
+ #
26
+ # c = Circle(5) # OK
27
+ # Shape() # TypeError: Can't instantiate abstract class Shape
28
+ # # with abstract method area
29
+ #
30
+ # Protocol usage:
31
+ # from abc import Protocol, runtime_checkable
32
+ #
33
+ # @runtime_checkable
34
+ # class Drawable(Protocol):
35
+ # def draw(self): ...
36
+ #
37
+ # class Canvas:
38
+ # def draw(self): pass
39
+ #
40
+ # isinstance(Canvas(), Drawable) # True (structural check)
41
+ # isinstance(42, Drawable) # False
42
+ #
43
+ # Implementation notes:
44
+ # - @abstractmethod sets func.__isabstractmethod__ = True.
45
+ # - ABC.__init_subclass__ is called for every subclass (directly or transitively)
46
+ # because ρσ_extends calls Object.setPrototypeOf(child, parent), making
47
+ # constructor-chain lookup find the parent's __init_subclass__.
48
+ # - A __init__ guard is installed on cls.prototype when abstract methods remain;
49
+ # the guard checks this.__class__.__abstractmethods__ at runtime so concrete
50
+ # subclasses that inherit the guard pass cleanly.
51
+ # - ABC.register() stores class constructors in a native JS Set; Symbol.hasInstance
52
+ # is installed to make isinstance(obj, SomeABC) respect the registry.
53
+ # - Protocol collects __protocol_attrs__ (non-dunder callable own-properties).
54
+ # @runtime_checkable installs Symbol.hasInstance for structural isinstance().
55
+
56
+
57
+ def abstractmethod(func):
58
+ """Decorator to declare a method as abstract."""
59
+ func.__isabstractmethod__ = True
60
+ return func
61
+
62
+
63
+ def _collect_abstract_methods(cls):
64
+ """
65
+ Return a Python set of still-abstract method names in cls.
66
+
67
+ Merges base classes' __abstractmethods__ sets, then walks cls.prototype's
68
+ own properties: methods with __isabstractmethod__ are added; concrete
69
+ implementations remove the name from the set.
70
+ """
71
+ abstract = set()
72
+
73
+ v"""
74
+ var ρσ_bases = (cls.prototype && cls.prototype.__bases__) || [];
75
+ for (var ρσ_bi = 0; ρσ_bi < ρσ_bases.length; ρσ_bi++) {
76
+ var ρσ_base = ρσ_bases[ρσ_bi];
77
+ if (ρσ_base && ρσ_base.__abstractmethods__) {
78
+ for (var ρσ_n of ρσ_base.__abstractmethods__) {
79
+ abstract.add(ρσ_n);
80
+ }
81
+ }
82
+ }
83
+ var ρσ_proto = cls.prototype;
84
+ var ρσ_keys = Object.getOwnPropertyNames(ρσ_proto);
85
+ for (var ρσ_ki = 0; ρσ_ki < ρσ_keys.length; ρσ_ki++) {
86
+ var ρσ_k = ρσ_keys[ρσ_ki];
87
+ if (ρσ_k.startsWith('ρσ') || ρσ_k === '__class__') continue;
88
+ var ρσ_desc = Object.getOwnPropertyDescriptor(ρσ_proto, ρσ_k);
89
+ if (!ρσ_desc) continue;
90
+ if (typeof ρσ_desc.value === 'function') {
91
+ if (ρσ_desc.value.__isabstractmethod__) {
92
+ abstract.add(ρσ_k);
93
+ } else {
94
+ abstract.discard(ρσ_k);
95
+ }
96
+ } else if (ρσ_desc.get && ρσ_desc.get.__isabstractmethod__) {
97
+ abstract.add(ρσ_k);
98
+ }
99
+ }
100
+ """
101
+
102
+ return abstract
103
+
104
+
105
+ def _install_abstract_guard(cls):
106
+ """
107
+ Replace cls.prototype.__init__ with a wrapper that raises TypeError if the
108
+ concrete class being instantiated still has un-overridden abstract methods.
109
+ The check uses this.__class__.__abstractmethods__ at call-time, so a
110
+ concrete subclass that inherits this guard from an abstract parent passes.
111
+ """
112
+ v"""
113
+ var ρσ_orig_init = Object.prototype.hasOwnProperty.call(cls.prototype, '__init__')
114
+ ? cls.prototype.__init__
115
+ : null;
116
+ cls.prototype.__init__ = function() {
117
+ var ρσ_actual_cls = (this && (this.__class__ || this.constructor)) || cls;
118
+ var ρσ_am = ρσ_actual_cls && ρσ_actual_cls.__abstractmethods__;
119
+ if (ρσ_am && ρσ_am.size > 0) {
120
+ var ρσ_names = Array.from(ρσ_am).sort().join(', ');
121
+ var ρσ_s = ρσ_am.size > 1 ? 's' : '';
122
+ throw new TypeError(
123
+ "Can't instantiate abstract class " + ρσ_actual_cls.__name__ +
124
+ " with abstract method" + ρσ_s + " " + ρσ_names
125
+ );
126
+ }
127
+ if (typeof ρσ_orig_init === 'function') {
128
+ ρσ_orig_init.apply(this, arguments);
129
+ }
130
+ };
131
+ """
132
+
133
+
134
+ class ABCMeta:
135
+ """
136
+ Metaclass for defining Abstract Base Classes (informational in RapydScript).
137
+
138
+ In Python, ABCMeta is the true metaclass that powers abstract classes.
139
+ RapydScript does not support metaclasses; use ABC as a regular base class
140
+ instead. ABCMeta is provided for compatibility with code that references it.
141
+ """
142
+ pass
143
+
144
+
145
+ class ABC:
146
+ """
147
+ Helper class for defining Abstract Base Classes via inheritance.
148
+
149
+ Any class that inherits from ABC (directly or transitively) and still has
150
+ un-overridden @abstractmethod declarations cannot be instantiated — a
151
+ TypeError is raised at construction time.
152
+
153
+ Use ABC.register(subclass) to declare a virtual subclass that passes
154
+ isinstance() checks without actual inheritance.
155
+
156
+ Example::
157
+
158
+ class Vehicle(ABC):
159
+ @abstractmethod
160
+ def drive(self): ...
161
+
162
+ class Car(Vehicle):
163
+ def drive(self):
164
+ print('vroom')
165
+
166
+ Car() # OK
167
+ Vehicle() # TypeError: Can't instantiate abstract class Vehicle
168
+ # with abstract method drive
169
+ """
170
+
171
+ @classmethod
172
+ def __init_subclass__(cls, **kwargs):
173
+ am = _collect_abstract_methods(cls)
174
+ cls.__abstractmethods__ = am
175
+
176
+ v"""
177
+ cls.__abc_registry__ = new Set();
178
+ var ρσ_registry = cls.__abc_registry__;
179
+ // Two install sites for register():
180
+ //
181
+ // 1. cls.register (constructor property): used when @MyABC.register is
182
+ // written as a class decorator — RapydScript stores the expression value
183
+ // [_MyABC.register] in ρσ_decorators, then calls ρσ_decorators[0](Cls).
184
+ // Here 'subclass' receives the class being decorated.
185
+ cls.register = function(subclass) {
186
+ ρσ_registry.add(subclass);
187
+ return subclass;
188
+ };
189
+ // 2. cls.prototype.register (prototype method): used when the user writes
190
+ // MyABC.register(Cls) as a plain call — RapydScript compiles this to
191
+ // MyABC.prototype.register.call(Cls), so 'this' is the class to register.
192
+ cls.prototype.register = function() {
193
+ ρσ_registry.add(this);
194
+ return this;
195
+ };
196
+ Object.defineProperty(cls, Symbol.hasInstance, {
197
+ configurable: true,
198
+ value: function(instance) {
199
+ if (instance === null || instance === undefined) return false;
200
+ if (Object.prototype.isPrototypeOf.call(cls.prototype, instance)) return true;
201
+ var reg = cls.__abc_registry__;
202
+ if (reg && reg.size > 0) {
203
+ var ctor = instance.__class__ || instance.constructor;
204
+ while (ctor && ctor !== Function.prototype) {
205
+ if (reg.has(ctor)) return true;
206
+ ctor = Object.getPrototypeOf(ctor);
207
+ }
208
+ }
209
+ return false;
210
+ }
211
+ });
212
+ """
213
+
214
+ if am.size > 0:
215
+ _install_abstract_guard(cls)
216
+
217
+
218
+ class Protocol:
219
+ """
220
+ Base class for protocol classes (structural subtyping — PEP 544).
221
+
222
+ Define a Protocol to specify a structural interface: any class that has
223
+ the required methods satisfies the protocol at runtime. Use
224
+ @runtime_checkable to enable isinstance() checks based on method presence
225
+ rather than inheritance.
226
+
227
+ Example::
228
+
229
+ from abc import Protocol, runtime_checkable
230
+
231
+ @runtime_checkable
232
+ class Drawable(Protocol):
233
+ def draw(self): ...
234
+
235
+ class Canvas:
236
+ def draw(self):
237
+ print('drawing...')
238
+
239
+ isinstance(Canvas(), Drawable) # True
240
+ isinstance(42, Drawable) # False
241
+ """
242
+
243
+ @classmethod
244
+ def __init_subclass__(cls, **kwargs):
245
+ am = _collect_abstract_methods(cls)
246
+ cls.__abstractmethods__ = am
247
+
248
+ v"""
249
+ var ρσ_proto_attrs = new Set();
250
+ var ρσ_pbases = (cls.prototype && cls.prototype.__bases__) || [];
251
+ for (var ρσ_pbi = 0; ρσ_pbi < ρσ_pbases.length; ρσ_pbi++) {
252
+ var ρσ_pbase = ρσ_pbases[ρσ_pbi];
253
+ if (ρσ_pbase && ρσ_pbase.__protocol_attrs__) {
254
+ for (var ρσ_pa of ρσ_pbase.__protocol_attrs__) {
255
+ ρσ_proto_attrs.add(ρσ_pa);
256
+ }
257
+ }
258
+ }
259
+ var ρσ_pproto = cls.prototype;
260
+ var ρσ_pkeys = Object.getOwnPropertyNames(ρσ_pproto);
261
+ for (var ρσ_pki = 0; ρσ_pki < ρσ_pkeys.length; ρσ_pki++) {
262
+ var ρσ_pk = ρσ_pkeys[ρσ_pki];
263
+ if (ρσ_pk.startsWith('_') || ρσ_pk.startsWith('ρσ')) continue;
264
+ var ρσ_pd = Object.getOwnPropertyDescriptor(ρσ_pproto, ρσ_pk);
265
+ if (ρσ_pd && typeof ρσ_pd.value === 'function') {
266
+ ρσ_proto_attrs.add(ρσ_pk);
267
+ }
268
+ }
269
+ cls.__protocol_attrs__ = ρσ_proto_attrs;
270
+ """
271
+
272
+ if am.size > 0:
273
+ _install_abstract_guard(cls)
274
+
275
+
276
+ def runtime_checkable(cls):
277
+ """
278
+ Decorator for Protocol subclasses to allow isinstance() structural checks.
279
+
280
+ After applying @runtime_checkable, isinstance(obj, MyProtocol) returns True
281
+ if *obj* has all the non-dunder methods declared in the Protocol, regardless
282
+ of inheritance.
283
+
284
+ Example::
285
+
286
+ @runtime_checkable
287
+ class Closeable(Protocol):
288
+ def close(self): ...
289
+
290
+ class File:
291
+ def close(self): ...
292
+
293
+ isinstance(File(), Closeable) # True
294
+ isinstance(42, Closeable) # False
295
+ """
296
+ cls.__runtime_checkable__ = True
297
+
298
+ v"""
299
+ var ρσ_attrs = cls.__protocol_attrs__ || new Set();
300
+ Object.defineProperty(cls, Symbol.hasInstance, {
301
+ configurable: true,
302
+ value: function(instance) {
303
+ if (instance === null || instance === undefined) return false;
304
+ for (var ρσ_attr of ρσ_attrs) {
305
+ if (typeof instance[ρσ_attr] !== 'function') return false;
306
+ }
307
+ return true;
308
+ }
309
+ });
310
+ """
311
+
312
+ return cls
313
+
314
+
315
+ def get_cache_token():
316
+ """Return the current ABC cache invalidation token (always 0 in RapydScript)."""
317
+ return 0
@@ -0,0 +1,120 @@
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD
3
+ # RapydScript implementation of Python's copy standard library.
4
+ #
5
+ # Supported: copy, deepcopy
6
+ # Classes may define __copy__() and __deepcopy__(memo) for custom behaviour.
7
+
8
+
9
+ def _is_primitive(x):
10
+ t = jstype(x)
11
+ return x is None or t is 'number' or t is 'boolean' or t is 'string' or t is 'undefined'
12
+
13
+
14
+ def copy(x):
15
+ """Return a shallow copy of x.
16
+
17
+ For immutable primitives (numbers, strings, booleans, None) the object
18
+ itself is returned unchanged. For containers a new container of the same
19
+ type is created whose top-level items are the same objects as in the
20
+ original.
21
+
22
+ Dispatch order:
23
+ 1. Primitive → return as-is.
24
+ 2. ``__copy__`` method → call and return.
25
+ 3. list → ``list(x)`` (slice).
26
+ 4. set → ``set(x)``.
27
+ 5. frozenset → ``frozenset(x)``.
28
+ 6. dict (ρσ_dict) → ``x.copy()``.
29
+ 7. Plain JS object (constructor is Object or null-proto) → Object.assign.
30
+ 8. Other object (class instance) → Object.create + Object.assign.
31
+ """
32
+ if _is_primitive(x):
33
+ return x
34
+ if jstype(x.__copy__) is 'function':
35
+ return x.__copy__()
36
+ if Array.isArray(x):
37
+ return list(x)
38
+ if isinstance(x, set):
39
+ return set(x)
40
+ if isinstance(x, frozenset):
41
+ return frozenset(x)
42
+ if isinstance(x, dict):
43
+ return x.copy()
44
+ proto = Object.getPrototypeOf(x)
45
+ if x.constructor is Object or proto is None:
46
+ return Object.assign({}, x)
47
+ # Class instance: create a same-prototype object and copy own properties.
48
+ result = Object.create(proto)
49
+ Object.assign(result, x)
50
+ return result
51
+
52
+
53
+ def deepcopy(x, memo=None):
54
+ """Return a deep (recursive) copy of x.
55
+
56
+ Circular references are handled via the *memo* mapping (a JS Map), which
57
+ stores already-copied objects so that they are only copied once.
58
+
59
+ Dispatch order (same structure as ``copy`` but recursive):
60
+ 1. Primitive → return as-is.
61
+ 2. Memo hit → return the previously copied object.
62
+ 3. ``__deepcopy__(memo)`` method → call and return.
63
+ 4. list → recurse into elements.
64
+ 5. set → recurse into elements, build new set.
65
+ 6. frozenset → recurse into elements, build new frozenset.
66
+ 7. dict → recurse into keys and values.
67
+ 8. Plain JS object → recurse into own-enumerable properties.
68
+ 9. Class instance → recurse into own-enumerable properties.
69
+ """
70
+ if memo is None:
71
+ memo = v'new Map()'
72
+ if _is_primitive(x):
73
+ return x
74
+ if memo.has(x):
75
+ return memo.get(x)
76
+ if jstype(x.__deepcopy__) is 'function':
77
+ result = x.__deepcopy__(memo)
78
+ memo.set(x, result)
79
+ return result
80
+ if Array.isArray(x):
81
+ result = []
82
+ memo.set(x, result)
83
+ for i in range(x.length):
84
+ result.push(deepcopy(x[i], memo))
85
+ return result
86
+ if isinstance(x, set):
87
+ result = set()
88
+ memo.set(x, result)
89
+ iterator = x[ρσ_iterator_symbol]()
90
+ r = iterator.next()
91
+ while not r.done:
92
+ result.add(deepcopy(r.value, memo))
93
+ r = iterator.next()
94
+ return result
95
+ if isinstance(x, frozenset):
96
+ items = []
97
+ iterator = x[ρσ_iterator_symbol]()
98
+ r = iterator.next()
99
+ while not r.done:
100
+ items.push(deepcopy(r.value, memo))
101
+ r = iterator.next()
102
+ result = frozenset(items)
103
+ memo.set(x, result)
104
+ return result
105
+ if isinstance(x, dict):
106
+ result = dict()
107
+ memo.set(x, result)
108
+ iterator = x.items()
109
+ r = iterator.next()
110
+ while not r.done:
111
+ result.set(deepcopy(r.value[0], memo), deepcopy(r.value[1], memo))
112
+ r = iterator.next()
113
+ return result
114
+ proto = Object.getPrototypeOf(x)
115
+ result = Object.create(proto)
116
+ memo.set(x, result)
117
+ keys = Object.keys(x)
118
+ for i in range(keys.length):
119
+ result[keys[i]] = deepcopy(x[keys[i]], memo)
120
+ return result