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.
- package/.agignore +1 -0
- package/.gitattributes +4 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/web-repl-page-deploy.yml +42 -0
- package/=template.pyj +5 -0
- package/CHANGELOG.md +456 -0
- package/CONTRIBUTORS +13 -0
- package/HACKING.md +103 -0
- package/LICENSE +24 -0
- package/README.md +2512 -0
- package/TODO.md +327 -0
- package/add-toc-to-readme +2 -0
- package/bin/export +75 -0
- package/bin/rapydscript +70 -0
- package/bin/web-repl-export +102 -0
- package/build +3 -0
- package/package.json +46 -0
- package/publish.py +37 -0
- package/release/baselib-plain-pretty.js +4370 -0
- package/release/baselib-plain-ugly.js +3 -0
- package/release/compiler.js +18394 -0
- package/release/signatures.json +31 -0
- package/session.vim +4 -0
- package/setup.cfg +2 -0
- package/src/ast.pyj +1356 -0
- package/src/baselib-builtins.pyj +279 -0
- package/src/baselib-containers.pyj +723 -0
- package/src/baselib-errors.pyj +37 -0
- package/src/baselib-internal.pyj +421 -0
- package/src/baselib-itertools.pyj +97 -0
- package/src/baselib-str.pyj +798 -0
- package/src/compiler.pyj +36 -0
- package/src/errors.pyj +30 -0
- package/src/lib/aes.pyj +646 -0
- package/src/lib/collections.pyj +695 -0
- package/src/lib/elementmaker.pyj +83 -0
- package/src/lib/encodings.pyj +126 -0
- package/src/lib/functools.pyj +148 -0
- package/src/lib/gettext.pyj +569 -0
- package/src/lib/itertools.pyj +580 -0
- package/src/lib/math.pyj +193 -0
- package/src/lib/numpy.pyj +2101 -0
- package/src/lib/operator.pyj +11 -0
- package/src/lib/pythonize.pyj +20 -0
- package/src/lib/random.pyj +118 -0
- package/src/lib/re.pyj +470 -0
- package/src/lib/traceback.pyj +63 -0
- package/src/lib/uuid.pyj +77 -0
- package/src/monaco-language-service/analyzer.js +526 -0
- package/src/monaco-language-service/builtins.js +543 -0
- package/src/monaco-language-service/completions.js +498 -0
- package/src/monaco-language-service/diagnostics.js +643 -0
- package/src/monaco-language-service/dts.js +550 -0
- package/src/monaco-language-service/hover.js +121 -0
- package/src/monaco-language-service/index.js +386 -0
- package/src/monaco-language-service/scope.js +162 -0
- package/src/monaco-language-service/signature.js +144 -0
- package/src/output/__init__.pyj +0 -0
- package/src/output/classes.pyj +296 -0
- package/src/output/codegen.pyj +492 -0
- package/src/output/comments.pyj +45 -0
- package/src/output/exceptions.pyj +105 -0
- package/src/output/functions.pyj +491 -0
- package/src/output/literals.pyj +109 -0
- package/src/output/loops.pyj +444 -0
- package/src/output/modules.pyj +329 -0
- package/src/output/operators.pyj +429 -0
- package/src/output/statements.pyj +463 -0
- package/src/output/stream.pyj +309 -0
- package/src/output/treeshake.pyj +182 -0
- package/src/output/utils.pyj +72 -0
- package/src/parse.pyj +3106 -0
- package/src/string_interpolation.pyj +72 -0
- package/src/tokenizer.pyj +702 -0
- package/src/unicode_aliases.pyj +576 -0
- package/src/utils.pyj +192 -0
- package/test/_import_one.pyj +37 -0
- package/test/_import_two/__init__.pyj +11 -0
- package/test/_import_two/level2/__init__.pyj +0 -0
- package/test/_import_two/level2/deep.pyj +4 -0
- package/test/_import_two/other.pyj +6 -0
- package/test/_import_two/sub.pyj +13 -0
- package/test/aes_vectors.pyj +421 -0
- package/test/annotations.pyj +80 -0
- package/test/baselib.pyj +319 -0
- package/test/classes.pyj +452 -0
- package/test/collections.pyj +152 -0
- package/test/decorators.pyj +77 -0
- package/test/dict_spread.pyj +76 -0
- package/test/docstrings.pyj +39 -0
- package/test/elementmaker_test.pyj +45 -0
- package/test/ellipsis.pyj +49 -0
- package/test/functions.pyj +151 -0
- package/test/generators.pyj +41 -0
- package/test/generic.pyj +370 -0
- package/test/imports.pyj +72 -0
- package/test/internationalization.pyj +73 -0
- package/test/lint.pyj +164 -0
- package/test/loops.pyj +85 -0
- package/test/numpy.pyj +734 -0
- package/test/omit_function_metadata.pyj +20 -0
- package/test/regexp.pyj +55 -0
- package/test/repl.pyj +121 -0
- package/test/scoped_flags.pyj +76 -0
- package/test/starargs.pyj +506 -0
- package/test/starred_assign.pyj +104 -0
- package/test/str.pyj +198 -0
- package/test/subscript_tuple.pyj +53 -0
- package/test/unit/fixtures/fibonacci_expected.js +46 -0
- package/test/unit/index.js +2989 -0
- package/test/unit/language-service-builtins.js +815 -0
- package/test/unit/language-service-completions.js +1067 -0
- package/test/unit/language-service-dts.js +543 -0
- package/test/unit/language-service-hover.js +455 -0
- package/test/unit/language-service-scope.js +833 -0
- package/test/unit/language-service-signature.js +458 -0
- package/test/unit/language-service.js +705 -0
- package/test/unit/run-language-service.js +41 -0
- package/test/unit/web-repl.js +484 -0
- package/tools/build-language-service.js +190 -0
- package/tools/cli.js +547 -0
- package/tools/compile.js +219 -0
- package/tools/compiler.js +108 -0
- package/tools/completer.js +131 -0
- package/tools/embedded_compiler.js +251 -0
- package/tools/export.js +316 -0
- package/tools/gettext.js +185 -0
- package/tools/ini.js +65 -0
- package/tools/lint.js +705 -0
- package/tools/msgfmt.js +187 -0
- package/tools/repl.js +223 -0
- package/tools/self.js +162 -0
- package/tools/test.js +118 -0
- package/tools/utils.js +128 -0
- package/tools/web_repl.js +95 -0
- package/try +41 -0
- package/web-repl/env.js +74 -0
- package/web-repl/index.html +163 -0
- package/web-repl/language-service.js +4084 -0
- package/web-repl/main.js +254 -0
- package/web-repl/prism.css +139 -0
- package/web-repl/prism.js +113 -0
- package/web-repl/rapydscript.js +435 -0
- package/web-repl/sha1.js +25 -0
package/TODO.md
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
|
|
2
|
+
### libraries
|
|
3
|
+
- allow var etc as property name
|
|
4
|
+
- revert numpy variance method to be var
|
|
5
|
+
|
|
6
|
+
- omit_function_metadata breaks imports - it needs to be changed to only affect imported modules, maybe?
|
|
7
|
+
|
|
8
|
+
- variables just say (variable) on hover, not their type?
|
|
9
|
+
|
|
10
|
+
- vscode plugin based on language service
|
|
11
|
+
|
|
12
|
+
- export language service to npm module
|
|
13
|
+
- update url links
|
|
14
|
+
- make npm module
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
I would like you to add support for [ Python's extended subscript syntax where commas inside [] implicitly form a tuple ] to rapydscript. It should have the same syntax as the Python implementation, and be transpiled into equivalent javascript. Please ensure with unit tests that it transpiles and the output JS runs correctly, and that the language service correctly handles it in parsed code. Please make sure it works in the web-repl too. Please also update the README to mention this support.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# 1. Placeholder body (like pass)
|
|
24
|
+
def todo():
|
|
25
|
+
...
|
|
26
|
+
|
|
27
|
+
class MyProtocol:
|
|
28
|
+
def method(self) -> int: ...
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# 3. Sentinel / default marker
|
|
32
|
+
_MISSING = ...
|
|
33
|
+
|
|
34
|
+
def greet(name=...):
|
|
35
|
+
if name is ...:
|
|
36
|
+
name = "World"
|
|
37
|
+
print(f"Hello, {name}!")
|
|
38
|
+
|
|
39
|
+
greet() # Hello, World!
|
|
40
|
+
greet("Alice") # Hello, Alice!
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# 4. NumPy-style slice shorthand (all leading dimensions)
|
|
44
|
+
import numpy as np
|
|
45
|
+
arr = np.zeros((2, 3, 4))
|
|
46
|
+
print(arr[..., 0] ) # shape (2, 3) — first element of last axis
|
|
47
|
+
print(arr[1, ...]) # shape (3, 4) — entire second "sheet"
|
|
48
|
+
|
|
49
|
+
# 5. Identity check
|
|
50
|
+
print(... is ...) # True (singleton)
|
|
51
|
+
print(... is Ellipsis) # True
|
|
52
|
+
print(type(...).__name__) # ellipsis
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
Python Feature Gap Report: RapydScript-NS
|
|
61
|
+
|
|
62
|
+
Summary
|
|
63
|
+
|
|
64
|
+
RapydScript-NS covers the vast majority of Python 2/3 core syntax well. The gaps fall into four categories: modern Python syntax, OOP/protocol features, standard library modules, and semantic
|
|
65
|
+
differences.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
1. Modern Python Syntax (Not Supported)
|
|
69
|
+
|
|
70
|
+
┌───────────────────────────────────────────────┬────────────────┬──────────────────────────────────────────────────────────────┐
|
|
71
|
+
│ Feature │ Python Version │ Notes │
|
|
72
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
73
|
+
│ match/case (structural pattern matching) │ 3.10+ │ -tested │
|
|
74
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
75
|
+
│ Walrus operator := │ 3.8+ │ -tested │
|
|
76
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
77
|
+
│ lambda keyword │ all │ -tested │
|
|
78
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
79
|
+
│ Variable type annotations x: int = 1 │ 3.6+ │ needs testing │
|
|
80
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
81
|
+
│ Positional-only parameters (def f(a, /, b):) │ 3.8+ │ -tested │
|
|
82
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
83
|
+
│ Keyword-only parameters (def f(a, *, b):) │ 3.0+ │ -tested │
|
|
84
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
85
|
+
│ Starred assignment a, *b, c = [1,2,3,4,5] │ 3.0+ │ -tested │
|
|
86
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
87
|
+
│ Dict merge literal {**d1, **d2} │ 3.5+ │ -tested │
|
|
88
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
89
|
+
│ Parenthesized with (multi-context) │ 3.10+ │ - doesn't make sense in a web context │
|
|
90
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
91
|
+
│ Exception chaining raise X from Y │ 3.0+ │ Plain raise only │
|
|
92
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
93
|
+
│ except* (exception groups) │ 3.11+ │ No support │
|
|
94
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
95
|
+
│ Nested comprehensions (for a in b for c in d) │ all │ -tested │
|
|
96
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
97
|
+
│ Complex number literals 3+4j │ all │ No j suffix │
|
|
98
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
99
|
+
│ Ellipsis literal ... as expression │ all │ Only valid as slice (a[...]) │
|
|
100
|
+
├───────────────────────────────────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
|
|
101
|
+
│ b'...' bytes literals │ all │ No b prefix; encoding module exists but no native bytes type │
|
|
102
|
+
└───────────────────────────────────────────────┴────────────────┴──────────────────────────────────────────────────────────────┘
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
2. OOP and Dunder Protocol Gaps
|
|
106
|
+
|
|
107
|
+
Not Supported at All
|
|
108
|
+
|
|
109
|
+
┌─────────────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
|
|
110
|
+
│ Feature │ Notes │
|
|
111
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
112
|
+
│ super() │ -tested │
|
|
113
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
114
|
+
│ __new__ │ No alternative constructor support │
|
|
115
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
116
|
+
│ __del__ │ No destructor/finalizer │
|
|
117
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
118
|
+
│ __hash__ │ Explicitly noted as not implemented; set/dict uses === identity │
|
|
119
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
120
|
+
│ __bool__ │ Empty [] and {} are truthy in JS (differs from Python) │
|
|
121
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
122
|
+
│ __call__ │ Objects cannot be made callable via dunder │
|
|
123
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
124
|
+
│ __getattr__ / __setattr__ / __delattr__ │ No attribute access interception │
|
|
125
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
126
|
+
│ __getattribute__ │ No attribute lookup overriding │
|
|
127
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
128
|
+
│ __format__ │ No custom format() behavior │
|
|
129
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
130
|
+
│ __slots__ │ No slot declarations │
|
|
131
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
132
|
+
│ __class_getitem__ │ No MyClass[T] generic syntax support │
|
|
133
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
134
|
+
│ __init_subclass__ │ No subclass hooks │
|
|
135
|
+
├─────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
|
|
136
|
+
│ classmethod decorator │ Not tested/documented (may partially work via @staticmethod) │
|
|
137
|
+
└─────────────────────────────────────────┴─────────────────────────────────────────────────────────────────┘
|
|
138
|
+
|
|
139
|
+
Arithmetic/Comparison Operator Overloading
|
|
140
|
+
|
|
141
|
+
All of these dunder methods are not dispatched — operators always use JS native semantics:
|
|
142
|
+
|
|
143
|
+
__add__, __radd__, __sub__, __mul__, __truediv__, __floordiv__, __mod__, __pow__, __lt__, __le__, __gt__, __ge__, __ne__, __neg__, __pos__, __abs__, __invert__, __lshift__, __rshift__, __and__,
|
|
144
|
+
__or__, __xor__
|
|
145
|
+
|
|
146
|
+
(Only __eq__, __contains__, __iter__, __len__, __enter__, __exit__, __repr__, __str__ are dispatched)
|
|
147
|
+
|
|
148
|
+
Nested Classes
|
|
149
|
+
|
|
150
|
+
Noted in test file (test/classes.pyj) as "not yet fully implemented."
|
|
151
|
+
|
|
152
|
+
Abstract Base Classes (ABCs)
|
|
153
|
+
|
|
154
|
+
No abc module, no @abstractmethod, no Protocol support.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
3. Built-in Functions Missing
|
|
158
|
+
|
|
159
|
+
┌──────────────────────────┬────────────────────────────────────────────────┐
|
|
160
|
+
│ Function │ Notes │
|
|
161
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
162
|
+
│ super() │ tested │
|
|
163
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
164
|
+
│ issubclass() │ Not implemented │
|
|
165
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
166
|
+
│ hash() │ Not implemented │
|
|
167
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
168
|
+
│ format(value, spec) │ Not listed; str.format() works │
|
|
169
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
170
|
+
│ vars() │ Not listed │
|
|
171
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
172
|
+
│ locals() │ Not listed │
|
|
173
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
174
|
+
│ globals() │ Not listed │
|
|
175
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
176
|
+
│ exec() │ Not listed (JS eval works directly via v'...') │
|
|
177
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
178
|
+
│ eval() │ Not listed │
|
|
179
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
180
|
+
│ compile() │ N/A │
|
|
181
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
182
|
+
│ __import__() │ Not supported │
|
|
183
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
184
|
+
│ input() │ Not built in │
|
|
185
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
186
|
+
│ open() │ Not built in │
|
|
187
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
188
|
+
│ bytes() / bytearray() │ Not built in │
|
|
189
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
190
|
+
│ memoryview() │ N/A (browser context) │
|
|
191
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
192
|
+
│ zip(..., strict=True) │ strict kwarg not supported │
|
|
193
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
194
|
+
│ enumerate(x, start=N) │ start parameter may not be supported │
|
|
195
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
196
|
+
│ all() / any() │ tested │
|
|
197
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
198
|
+
│ next(iter, default?) │ Not listed │
|
|
199
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
200
|
+
│ iter(callable, sentinel) │ Two-arg form likely not supported │
|
|
201
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
202
|
+
│ round(x, ndigits?) │ Not listed │
|
|
203
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
204
|
+
│ slice() │ Not listed as builtin object │
|
|
205
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
206
|
+
│ frozenset() │ Not listed │
|
|
207
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
208
|
+
│ complex() │ Not listed │
|
|
209
|
+
├──────────────────────────┼────────────────────────────────────────────────┤
|
|
210
|
+
│ object() │ Not listed │
|
|
211
|
+
└──────────────────────────┴────────────────────────────────────────────────┘
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
4. Standard Library Modules Missing
|
|
215
|
+
|
|
216
|
+
These are Python stdlib modules with no equivalent in src/lib/:
|
|
217
|
+
|
|
218
|
+
┌─────────────┬─────────────────────────────────────────────────────────────────────────────────┐
|
|
219
|
+
│ Module │ What's Missing │
|
|
220
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
221
|
+
│ collections │ tested │
|
|
222
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
223
|
+
│ functools │ tested │
|
|
224
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
225
|
+
│ itertools │ tested │
|
|
226
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
227
|
+
│ typing │ List, Dict, Optional, Union, Tuple, Generic, TypeVar, etc. │
|
|
228
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
229
|
+
│ dataclasses │ @dataclass, field(), asdict(), astuple() │
|
|
230
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
231
|
+
│ contextlib │ contextmanager, suppress, ExitStack, asynccontextmanager │
|
|
232
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
233
|
+
│ copy │ copy(), deepcopy() │
|
|
234
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
235
|
+
│ string │ Character constants, Template, Formatter │
|
|
236
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
237
|
+
│ json │ dumps, loads (JS JSON works directly, but no Python wrapper) │
|
|
238
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
239
|
+
│ datetime │ date, time, datetime, timedelta │
|
|
240
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
241
|
+
│ inspect │ signature, getmembers, isfunction, etc. │
|
|
242
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
243
|
+
│ asyncio │ Event loop, gather, sleep, Queue, Task wrappers │
|
|
244
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
245
|
+
│ enum │ Enum, IntEnum, Flag │
|
|
246
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
247
|
+
│ abc │ ABC, abstractmethod │
|
|
248
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
249
|
+
│ io │ StringIO, BytesIO │
|
|
250
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
251
|
+
│ struct │ Binary packing/unpacking │
|
|
252
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
253
|
+
│ hashlib │ MD5, SHA-256, etc. │
|
|
254
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
255
|
+
│ hmac │ Keyed hashing │
|
|
256
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
257
|
+
│ base64 │ (partial — encodings module exists) │
|
|
258
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
259
|
+
│ urllib │ URL parsing/encoding (no urllib.parse) │
|
|
260
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
261
|
+
│ html │ escape, unescape │
|
|
262
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
263
|
+
│ csv │ CSV parsing │
|
|
264
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
265
|
+
│ textwrap │ wrap, fill, dedent, indent │
|
|
266
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
267
|
+
│ pprint │ Pretty-printing │
|
|
268
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
269
|
+
│ logging │ Logging framework │
|
|
270
|
+
├─────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
271
|
+
│ unittest │ Test framework (custom runner used instead) │
|
|
272
|
+
└─────────────┴─────────────────────────────────────────────────────────────────────────────────┘
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
5. Semantic Differences (Traps)
|
|
276
|
+
|
|
277
|
+
These features exist but behave differently from Python:
|
|
278
|
+
|
|
279
|
+
┌─────────────────────────┬────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────┐
|
|
280
|
+
│ Feature │ Python Behavior │ RapydScript Behavior │
|
|
281
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
282
|
+
│ Truthiness of [] │ False │ True (JS semantics) │
|
|
283
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
284
|
+
│ Truthiness of {} │ False │ True (JS semantics) │
|
|
285
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
286
|
+
│ is / is not │ Object identity │ Strict equality === / !== │
|
|
287
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
288
|
+
│ // on floats │ math.floor(a/b) │ Correct for integers; JS Math.floor used │
|
|
289
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
290
|
+
│ % on negative numbers │ Python modulo (always positive) │ JS remainder (can be negative) │
|
|
291
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
292
|
+
│ int / float distinction │ Separate types │ Both are JS number │
|
|
293
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
294
|
+
│ String * repetition │ 'a' * 3 == 'aaa' │ Requires pythonize module or JS-side workaround │
|
|
295
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
296
|
+
│ sort() / pop() │ Standard list methods │ Renamed to pysort() / pypop() │
|
|
297
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
298
|
+
│ Method binding │ Unbound by default, self passed explicitly │ Same — but differs if you store methods in variables without bound_methods flag │
|
|
299
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
300
|
+
│ dict key ordering │ Insertion order (3.7+) │ Depends on JS engine (V8: insertion order) │
|
|
301
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
302
|
+
│ global scoping │ Full cross-scope declaration │ Partial — interactions with nonlocal can be confusing │
|
|
303
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
304
|
+
│ Exception .message │ Not standard (Python uses .args[0]) │ .message is standard (JS style) │
|
|
305
|
+
├─────────────────────────┼────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────┤
|
|
306
|
+
│ re module │ Full PCRE features │ No lookbehind, limited unicode, no (?(1)...) │
|
|
307
|
+
└─────────────────────────┴────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────┘
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
Priority Gaps (Most Impactful)
|
|
311
|
+
|
|
312
|
+
If prioritizing what to implement next, these have the highest user impact:
|
|
313
|
+
|
|
314
|
+
1. super() — required for idiomatic OOP code - done
|
|
315
|
+
2. Operator overloading (__add__, __lt__, etc.) — blocks numerical/scientific code - done
|
|
316
|
+
3. __bool__ / truthiness fix — silent Python compatibility trap
|
|
317
|
+
4. lambda keyword — commonly expected - done
|
|
318
|
+
5. all() / any() — extremely common builtins - done
|
|
319
|
+
6. functools.reduce / partial — core functional programming tools - done
|
|
320
|
+
7. collections.defaultdict / Counter — frequently used - done
|
|
321
|
+
8. Nested comprehensions — common Python pattern - done
|
|
322
|
+
9. Walrus operator := — increasingly common in modern Python - done
|
|
323
|
+
10. classmethod decorator — standard OOP pattern - done
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
package/bin/export
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// vim:ft=javascript:ts=4:et
|
|
3
|
+
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
var fs = require('fs');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
var crypto = require('crypto');
|
|
9
|
+
|
|
10
|
+
var base = path.join(path.dirname(__dirname));
|
|
11
|
+
var meta = JSON.parse(fs.readFileSync(path.join(base, 'package.json'), {'encoding':'utf-8'}));
|
|
12
|
+
var compiler_dir = path.join(base, 'dev');
|
|
13
|
+
if (!path_exists(path.join(compiler_dir, 'compiler.js'))) compiler_dir = path.join(base, 'release');
|
|
14
|
+
|
|
15
|
+
var manifest = {}, total = 0;
|
|
16
|
+
['compiler.js', 'baselib-plain-pretty.js', 'baselib-plain-ugly.js'].forEach(function(x) {
|
|
17
|
+
manifest[x] = fs.readFileSync(path.join(compiler_dir, x), {'encoding':'utf-8'});
|
|
18
|
+
total += manifest[x].length;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
['web_repl.js', 'repl.js', 'completer.js', 'utils.js', 'gettext.js', 'msgfmt.js'].forEach(function(x) {
|
|
22
|
+
x = 'tools/' + x;
|
|
23
|
+
manifest[x] = fs.readFileSync(path.join(base, x), {'encoding':'utf-8'});
|
|
24
|
+
total += manifest[x].length;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
var dedup = {};
|
|
29
|
+
|
|
30
|
+
function path_exists(path) {
|
|
31
|
+
try {
|
|
32
|
+
fs.statSync(path);
|
|
33
|
+
return true;
|
|
34
|
+
} catch(e) {
|
|
35
|
+
if (e.code != 'ENOENT') throw e;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function sha1sum(data) {
|
|
40
|
+
var h = crypto.createHash('sha1');
|
|
41
|
+
h.update(data);
|
|
42
|
+
return h.digest('hex');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function process_dir(name) {
|
|
46
|
+
var dpath = path.join(base, name);
|
|
47
|
+
var items = fs.readdirSync(dpath);
|
|
48
|
+
items.forEach(function (x) {
|
|
49
|
+
var iname = name + '/' + x;
|
|
50
|
+
var ipath = path.join(dpath, x);
|
|
51
|
+
var s = fs.statSync(ipath);
|
|
52
|
+
if (s.isDirectory()) return process_dir(iname);
|
|
53
|
+
var raw = fs.readFileSync(ipath, {'encoding':'utf-8'});
|
|
54
|
+
var sig = sha1sum(raw);
|
|
55
|
+
if (dedup.hasOwnProperty(sig)) {
|
|
56
|
+
manifest[iname] = [dedup[sig]];
|
|
57
|
+
} else {
|
|
58
|
+
manifest[iname] = raw;
|
|
59
|
+
dedup[sig] = iname;
|
|
60
|
+
total += s.size;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Object.keys(meta.dependencies).forEach(function (x) {
|
|
66
|
+
process_dir('node_modules/' + x);
|
|
67
|
+
});
|
|
68
|
+
console.log('// vim:fileencoding=utf-8');
|
|
69
|
+
console.log('(function() {');
|
|
70
|
+
console.log('var rs_version = ' + JSON.stringify(meta.version) + ';');
|
|
71
|
+
console.log('var data = ' + JSON.stringify(manifest) + ';');
|
|
72
|
+
console.log();
|
|
73
|
+
console.log(fs.readFileSync(path.join(base, 'tools', 'export.js'), {'encoding':'utf-8'}));
|
|
74
|
+
console.log('})()');
|
|
75
|
+
console.error('RapydScript compiler (uncompressed) size: ' + (total/(1024 * 1024)).toFixed(1) + ' MB');
|
package/bin/rapydscript
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// vim:ft=javascript:ts=4:et
|
|
3
|
+
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
function load(mod) {
|
|
7
|
+
return require('../tools/' + mod);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
var utils = load('utils');
|
|
11
|
+
|
|
12
|
+
// We need ES 6 generators so relaunch with the --harmony flag
|
|
13
|
+
if (!utils.generators_available()) {
|
|
14
|
+
if (process.execArgv.indexOf('--harmony') != -1) {
|
|
15
|
+
console.error('RapydScript needs ES 6 generators, update your version of nodejs');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
var args = ['--harmony', module.filename].concat(process.argv.slice(2));
|
|
19
|
+
require('child_process').spawn(process.execPath, args, {stdio:'inherit'}).on('exit', function(code, signal) {
|
|
20
|
+
process.exit(code);
|
|
21
|
+
});
|
|
22
|
+
} else {
|
|
23
|
+
|
|
24
|
+
var start_time = new Date().getTime();
|
|
25
|
+
var path = require('path');
|
|
26
|
+
|
|
27
|
+
var argv = load('cli').argv;
|
|
28
|
+
|
|
29
|
+
var base_path = path.normalize(path.join(path.dirname(module.filename), ".."));
|
|
30
|
+
var src_path = path.join(base_path, 'src');
|
|
31
|
+
var lib_path = path.join(base_path, 'dev');
|
|
32
|
+
if (!utils.path_exists(path.join(lib_path, 'compiler.js'))) lib_path = path.join(base_path, 'release');
|
|
33
|
+
|
|
34
|
+
if (argv.mode === 'self') {
|
|
35
|
+
if (argv.files.length > 0) {
|
|
36
|
+
console.error("WARN: Ignoring input files since --self was passed");
|
|
37
|
+
}
|
|
38
|
+
load('self')(base_path, src_path, lib_path, argv.complete, argv.profile);
|
|
39
|
+
if (argv.test) {
|
|
40
|
+
console.log('\nRunning test suite...\n');
|
|
41
|
+
argv.files = []; // Ensure all tests are run
|
|
42
|
+
load('test')(argv, base_path, src_path, path.join(base_path, 'dev'));
|
|
43
|
+
}
|
|
44
|
+
process.exit(0);
|
|
45
|
+
} else
|
|
46
|
+
|
|
47
|
+
if (argv.mode === 'test') {
|
|
48
|
+
load('test')(argv, base_path, src_path, lib_path);
|
|
49
|
+
} else
|
|
50
|
+
|
|
51
|
+
if (argv.mode === 'lint') {
|
|
52
|
+
load('lint').cli(argv, base_path, src_path, lib_path);
|
|
53
|
+
} else
|
|
54
|
+
|
|
55
|
+
if (argv.mode === 'repl') {
|
|
56
|
+
load('repl')({'lib_path':lib_path, 'imp_path':path.join(src_path, 'lib'), show_js:!argv.no_js});
|
|
57
|
+
} else
|
|
58
|
+
|
|
59
|
+
if (argv.mode === 'gettext') {
|
|
60
|
+
load('gettext').cli(argv, base_path, src_path, lib_path);
|
|
61
|
+
} else
|
|
62
|
+
|
|
63
|
+
if (argv.mode === 'msgfmt') {
|
|
64
|
+
load('msgfmt').cli(argv, base_path, src_path, lib_path);
|
|
65
|
+
} else
|
|
66
|
+
|
|
67
|
+
{
|
|
68
|
+
load('compile')(start_time, argv, base_path, src_path, lib_path);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// vim:ft=javascript:ts=4:et
|
|
3
|
+
|
|
4
|
+
"use strict";
|
|
5
|
+
|
|
6
|
+
var fs = require('fs');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
|
|
9
|
+
var base = path.normalize(path.resolve(path.join(path.dirname(__dirname))));
|
|
10
|
+
var meta = JSON.parse(fs.readFileSync(path.join(base, 'package.json'), {'encoding':'utf-8'}));
|
|
11
|
+
var commit_sha = fs.readFileSync(path.join(base, '.git', 'refs', 'heads', 'master'), {'encoding':'utf-8'}).trim();
|
|
12
|
+
var compiler_dir = path.join(base, 'dev');
|
|
13
|
+
if (!path_exists(path.join(compiler_dir, 'compiler.js'))) compiler_dir = path.join(base, 'release');
|
|
14
|
+
|
|
15
|
+
var manifest = {}, total = 0;
|
|
16
|
+
['compiler.js', 'baselib-plain-pretty.js'].forEach(function(x) {
|
|
17
|
+
manifest[x] = fs.readFileSync(path.join(compiler_dir, x), {'encoding':'utf-8'});
|
|
18
|
+
total += manifest[x].length;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
['web_repl.js', 'embedded_compiler.js', 'utils.js', 'completer.js', 'msgfmt.js', 'gettext.js'].forEach(function(x) {
|
|
22
|
+
x = 'tools/' + x;
|
|
23
|
+
manifest[x] = fs.readFileSync(path.join(base, x), {'encoding':'utf-8'});
|
|
24
|
+
total += manifest[x].length;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
var stdlib = path.join(base, 'src', 'lib');
|
|
28
|
+
|
|
29
|
+
function path_exists(path) {
|
|
30
|
+
try {
|
|
31
|
+
fs.statSync(path);
|
|
32
|
+
return true;
|
|
33
|
+
} catch(e) {
|
|
34
|
+
if (e.code != 'ENOENT') throw e;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function process_dir(relpath) {
|
|
39
|
+
var fullpath = (relpath) ? path.join(stdlib, relpath) : stdlib;
|
|
40
|
+
fs.readdirSync(fullpath).forEach(function (x) {
|
|
41
|
+
var q = path.join(fullpath, x);
|
|
42
|
+
var s = fs.statSync(q);
|
|
43
|
+
if (s.isDirectory()) return process_dir(relpath + '/' + x);
|
|
44
|
+
if (!x.endsWith('.pyj')) return;
|
|
45
|
+
var iname = ('__stdlib__' + '/' + relpath + '/' + x).replace(/\\/g, '/').replace(/\/+/g, '/');
|
|
46
|
+
var raw = fs.readFileSync(q, {'encoding':'utf-8'});
|
|
47
|
+
manifest[iname] = raw;
|
|
48
|
+
total += s.size;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
process_dir('');
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
var rs = '// vim:fileencoding=utf-8\n';
|
|
55
|
+
rs += '(function(external_namespace) {\n';
|
|
56
|
+
rs += '"use strict;"\n';
|
|
57
|
+
rs += 'var rs_version = ' + JSON.stringify(meta.version) + ';\n';
|
|
58
|
+
rs += 'var rs_commit_sha = ' + JSON.stringify(commit_sha) + ';\n';
|
|
59
|
+
rs += '\n// Embedded modules {{{\n';
|
|
60
|
+
rs += 'var data = ' + JSON.stringify(manifest) + ';\n\n';
|
|
61
|
+
rs += '// End embedded modules }}}\n\n';
|
|
62
|
+
rs += fs.readFileSync(path.join(base, 'web-repl', 'env.js'));
|
|
63
|
+
rs += '\n// Embedded sha1 implementation {{{\n';
|
|
64
|
+
rs += '(function() {\n';
|
|
65
|
+
rs += fs.readFileSync(path.join(base, 'web-repl', 'sha1.js'));
|
|
66
|
+
rs += '}).call(jsSHA);\n';
|
|
67
|
+
rs += '// End embedded sha1 implementation }}}\n\n';
|
|
68
|
+
rs += 'var exports = namespace;\n';
|
|
69
|
+
rs += fs.readFileSync(path.join(base, 'tools', 'export.js'), {'encoding':'utf-8'});
|
|
70
|
+
rs += 'external_namespace.RapydScript = namespace;\n';
|
|
71
|
+
rs += '})(this);\n';
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
var base_dir = process.argv.slice(-1)[0];
|
|
75
|
+
if (process.argv.length !== 3) {
|
|
76
|
+
console.error('Usage: web-repl-export /path/to/export/directory');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
base_dir = path.normalize(path.resolve(base_dir));
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
fs.mkdirSync(base_dir);
|
|
84
|
+
} catch(e) {
|
|
85
|
+
if (e.code !== 'EEXIST') throw e;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
process.chdir(base_dir);
|
|
90
|
+
} catch(e) {
|
|
91
|
+
if (e.code === 'ENOTDIR') { console.error(base_dir + ' is not a directory'); process.exit(1); }
|
|
92
|
+
throw e;
|
|
93
|
+
}
|
|
94
|
+
fs.writeFileSync('rapydscript.js', rs, {'encoding':'utf-8'});
|
|
95
|
+
var web_repl = path.join(base, 'web-repl');
|
|
96
|
+
fs.readdirSync(web_repl).forEach(function(x) {
|
|
97
|
+
if (['sha1.js', 'env.js'].indexOf(x) !== -1) return;
|
|
98
|
+
var data = fs.readFileSync(path.join(web_repl, x), {'encoding':'utf-8'});
|
|
99
|
+
fs.writeFileSync(x, data, {'encoding':'utf-8'});
|
|
100
|
+
});
|
|
101
|
+
console.log('RapydScript compiler (uncompressed) size: ' + (total/(1024)).toFixed(1) + ' KB');
|
|
102
|
+
console.log('web-repl exported to: ' + base_dir);
|
package/build
ADDED