rapydscript-ns 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.agignore +1 -0
  2. package/.gitattributes +4 -0
  3. package/.github/workflows/ci.yml +38 -0
  4. package/.github/workflows/web-repl-page-deploy.yml +42 -0
  5. package/=template.pyj +5 -0
  6. package/CHANGELOG.md +456 -0
  7. package/CONTRIBUTORS +13 -0
  8. package/HACKING.md +103 -0
  9. package/LICENSE +24 -0
  10. package/README.md +2512 -0
  11. package/TODO.md +327 -0
  12. package/add-toc-to-readme +2 -0
  13. package/bin/export +75 -0
  14. package/bin/rapydscript +70 -0
  15. package/bin/web-repl-export +102 -0
  16. package/build +3 -0
  17. package/package.json +46 -0
  18. package/publish.py +37 -0
  19. package/release/baselib-plain-pretty.js +4370 -0
  20. package/release/baselib-plain-ugly.js +3 -0
  21. package/release/compiler.js +18394 -0
  22. package/release/signatures.json +31 -0
  23. package/session.vim +4 -0
  24. package/setup.cfg +2 -0
  25. package/src/ast.pyj +1356 -0
  26. package/src/baselib-builtins.pyj +279 -0
  27. package/src/baselib-containers.pyj +723 -0
  28. package/src/baselib-errors.pyj +37 -0
  29. package/src/baselib-internal.pyj +421 -0
  30. package/src/baselib-itertools.pyj +97 -0
  31. package/src/baselib-str.pyj +798 -0
  32. package/src/compiler.pyj +36 -0
  33. package/src/errors.pyj +30 -0
  34. package/src/lib/aes.pyj +646 -0
  35. package/src/lib/collections.pyj +695 -0
  36. package/src/lib/elementmaker.pyj +83 -0
  37. package/src/lib/encodings.pyj +126 -0
  38. package/src/lib/functools.pyj +148 -0
  39. package/src/lib/gettext.pyj +569 -0
  40. package/src/lib/itertools.pyj +580 -0
  41. package/src/lib/math.pyj +193 -0
  42. package/src/lib/numpy.pyj +2101 -0
  43. package/src/lib/operator.pyj +11 -0
  44. package/src/lib/pythonize.pyj +20 -0
  45. package/src/lib/random.pyj +118 -0
  46. package/src/lib/re.pyj +470 -0
  47. package/src/lib/traceback.pyj +63 -0
  48. package/src/lib/uuid.pyj +77 -0
  49. package/src/monaco-language-service/analyzer.js +526 -0
  50. package/src/monaco-language-service/builtins.js +543 -0
  51. package/src/monaco-language-service/completions.js +498 -0
  52. package/src/monaco-language-service/diagnostics.js +643 -0
  53. package/src/monaco-language-service/dts.js +550 -0
  54. package/src/monaco-language-service/hover.js +121 -0
  55. package/src/monaco-language-service/index.js +386 -0
  56. package/src/monaco-language-service/scope.js +162 -0
  57. package/src/monaco-language-service/signature.js +144 -0
  58. package/src/output/__init__.pyj +0 -0
  59. package/src/output/classes.pyj +296 -0
  60. package/src/output/codegen.pyj +492 -0
  61. package/src/output/comments.pyj +45 -0
  62. package/src/output/exceptions.pyj +105 -0
  63. package/src/output/functions.pyj +491 -0
  64. package/src/output/literals.pyj +109 -0
  65. package/src/output/loops.pyj +444 -0
  66. package/src/output/modules.pyj +329 -0
  67. package/src/output/operators.pyj +429 -0
  68. package/src/output/statements.pyj +463 -0
  69. package/src/output/stream.pyj +309 -0
  70. package/src/output/treeshake.pyj +182 -0
  71. package/src/output/utils.pyj +72 -0
  72. package/src/parse.pyj +3106 -0
  73. package/src/string_interpolation.pyj +72 -0
  74. package/src/tokenizer.pyj +702 -0
  75. package/src/unicode_aliases.pyj +576 -0
  76. package/src/utils.pyj +192 -0
  77. package/test/_import_one.pyj +37 -0
  78. package/test/_import_two/__init__.pyj +11 -0
  79. package/test/_import_two/level2/__init__.pyj +0 -0
  80. package/test/_import_two/level2/deep.pyj +4 -0
  81. package/test/_import_two/other.pyj +6 -0
  82. package/test/_import_two/sub.pyj +13 -0
  83. package/test/aes_vectors.pyj +421 -0
  84. package/test/annotations.pyj +80 -0
  85. package/test/baselib.pyj +319 -0
  86. package/test/classes.pyj +452 -0
  87. package/test/collections.pyj +152 -0
  88. package/test/decorators.pyj +77 -0
  89. package/test/dict_spread.pyj +76 -0
  90. package/test/docstrings.pyj +39 -0
  91. package/test/elementmaker_test.pyj +45 -0
  92. package/test/ellipsis.pyj +49 -0
  93. package/test/functions.pyj +151 -0
  94. package/test/generators.pyj +41 -0
  95. package/test/generic.pyj +370 -0
  96. package/test/imports.pyj +72 -0
  97. package/test/internationalization.pyj +73 -0
  98. package/test/lint.pyj +164 -0
  99. package/test/loops.pyj +85 -0
  100. package/test/numpy.pyj +734 -0
  101. package/test/omit_function_metadata.pyj +20 -0
  102. package/test/regexp.pyj +55 -0
  103. package/test/repl.pyj +121 -0
  104. package/test/scoped_flags.pyj +76 -0
  105. package/test/starargs.pyj +506 -0
  106. package/test/starred_assign.pyj +104 -0
  107. package/test/str.pyj +198 -0
  108. package/test/subscript_tuple.pyj +53 -0
  109. package/test/unit/fixtures/fibonacci_expected.js +46 -0
  110. package/test/unit/index.js +2989 -0
  111. package/test/unit/language-service-builtins.js +815 -0
  112. package/test/unit/language-service-completions.js +1067 -0
  113. package/test/unit/language-service-dts.js +543 -0
  114. package/test/unit/language-service-hover.js +455 -0
  115. package/test/unit/language-service-scope.js +833 -0
  116. package/test/unit/language-service-signature.js +458 -0
  117. package/test/unit/language-service.js +705 -0
  118. package/test/unit/run-language-service.js +41 -0
  119. package/test/unit/web-repl.js +484 -0
  120. package/tools/build-language-service.js +190 -0
  121. package/tools/cli.js +547 -0
  122. package/tools/compile.js +219 -0
  123. package/tools/compiler.js +108 -0
  124. package/tools/completer.js +131 -0
  125. package/tools/embedded_compiler.js +251 -0
  126. package/tools/export.js +316 -0
  127. package/tools/gettext.js +185 -0
  128. package/tools/ini.js +65 -0
  129. package/tools/lint.js +705 -0
  130. package/tools/msgfmt.js +187 -0
  131. package/tools/repl.js +223 -0
  132. package/tools/self.js +162 -0
  133. package/tools/test.js +118 -0
  134. package/tools/utils.js +128 -0
  135. package/tools/web_repl.js +95 -0
  136. package/try +41 -0
  137. package/web-repl/env.js +74 -0
  138. package/web-repl/index.html +163 -0
  139. package/web-repl/language-service.js +4084 -0
  140. package/web-repl/main.js +254 -0
  141. package/web-repl/prism.css +139 -0
  142. package/web-repl/prism.js +113 -0
  143. package/web-repl/rapydscript.js +435 -0
  144. package/web-repl/sha1.js +25 -0
@@ -0,0 +1,543 @@
1
+ // builtins.js — Typed stubs for RapydScript / Python built-in functions.
2
+ //
3
+ // Provides hover docs, signature help, and richer completion detail for
4
+ // functions that are always available in RapydScript without any import.
5
+ //
6
+ // Public API:
7
+ // import { BuiltinsRegistry } from './builtins.js';
8
+ // const reg = new BuiltinsRegistry();
9
+ // reg.get('len'); // BuiltinInfo | null
10
+ // reg.getNames(); // string[]
11
+ // reg.getHoverMarkdown('len'); // string | null
12
+ // reg.getSignatureInfo('len'); // SignatureInfo | null
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // BuiltinInfo
16
+ // ---------------------------------------------------------------------------
17
+
18
+ /**
19
+ * Descriptor for a single built-in symbol.
20
+ *
21
+ * @typedef {{ label: string, type?: string, optional?: boolean, rest?: boolean }} BParam
22
+ */
23
+ export class BuiltinInfo {
24
+ /**
25
+ * @param {object} opts
26
+ * @param {string} opts.name
27
+ * @param {string} [opts.kind='function'] 'function' | 'class' | 'var'
28
+ * @param {BParam[]|null} [opts.params]
29
+ * @param {string|null} [opts.return_type]
30
+ * @param {string|null} [opts.doc]
31
+ */
32
+ constructor(opts) {
33
+ this.name = opts.name;
34
+ this.kind = opts.kind || 'function';
35
+ this.params = opts.params || null;
36
+ this.return_type = opts.return_type || null;
37
+ this.doc = opts.doc || null;
38
+ }
39
+ }
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Stub definitions
43
+ // ---------------------------------------------------------------------------
44
+
45
+ /** Shorthand for building a param descriptor. */
46
+ function p(label, opts) {
47
+ return Object.assign({ label }, opts || {});
48
+ }
49
+
50
+ const STUBS = [
51
+ // ── Python built-ins ──────────────────────────────────────────────────
52
+ new BuiltinInfo({ name: 'abs',
53
+ params: [p('x', { type: 'number' })],
54
+ return_type: 'number',
55
+ doc: 'Return the absolute value of x.' }),
56
+
57
+ new BuiltinInfo({ name: 'all',
58
+ params: [p('iterable')],
59
+ return_type: 'bool',
60
+ doc: 'Return True if all elements of the iterable are true (or if the iterable is empty).' }),
61
+
62
+ new BuiltinInfo({ name: 'any',
63
+ params: [p('iterable')],
64
+ return_type: 'bool',
65
+ doc: 'Return True if any element of the iterable is true.' }),
66
+
67
+ new BuiltinInfo({ name: 'bool', kind: 'class',
68
+ params: [p('x', { optional: true })],
69
+ return_type: 'bool',
70
+ doc: 'Return a Boolean value. x is converted using the standard truth-testing procedure.' }),
71
+
72
+ new BuiltinInfo({ name: 'callable',
73
+ params: [p('obj')],
74
+ return_type: 'bool',
75
+ doc: 'Return True if the object appears callable.' }),
76
+
77
+ new BuiltinInfo({ name: 'chr',
78
+ params: [p('i', { type: 'int' })],
79
+ return_type: 'str',
80
+ doc: 'Return the string representing a character at Unicode code point i.' }),
81
+
82
+ new BuiltinInfo({ name: 'dict', kind: 'class',
83
+ params: [p('**kwargs', { rest: true })],
84
+ return_type: 'dict',
85
+ doc: 'Create a new dictionary.' }),
86
+
87
+ new BuiltinInfo({ name: 'dir',
88
+ params: [p('obj', { optional: true })],
89
+ return_type: 'list',
90
+ doc: 'Without argument, return the list of names in the current local scope. With argument, return a list of attributes of that object.' }),
91
+
92
+ new BuiltinInfo({ name: 'divmod',
93
+ params: [p('a', { type: 'number' }), p('b', { type: 'number' })],
94
+ return_type: '[int, int]',
95
+ doc: 'Return (a // b, a % b) as a pair.' }),
96
+
97
+ new BuiltinInfo({ name: 'enumerate',
98
+ params: [p('iterable'), p('start', { type: 'int', optional: true })],
99
+ return_type: 'iterable',
100
+ doc: 'Return an enumerate object yielding (index, value) pairs.' }),
101
+
102
+ new BuiltinInfo({ name: 'filter',
103
+ params: [p('function'), p('iterable')],
104
+ return_type: 'iterable',
105
+ doc: 'Return an iterator of elements from iterable for which function returns true.' }),
106
+
107
+ new BuiltinInfo({ name: 'float', kind: 'class',
108
+ params: [p('x', { optional: true })],
109
+ return_type: 'float',
110
+ doc: 'Return a floating-point number from x.' }),
111
+
112
+ new BuiltinInfo({ name: 'getattr',
113
+ params: [p('obj'), p('name', { type: 'str' }), p('default', { optional: true })],
114
+ return_type: 'any',
115
+ doc: 'Return the value of the named attribute of obj. If not found, return default (or raise AttributeError).' }),
116
+
117
+ new BuiltinInfo({ name: 'hasattr',
118
+ params: [p('obj'), p('name', { type: 'str' })],
119
+ return_type: 'bool',
120
+ doc: 'Return True if obj has an attribute with the given name.' }),
121
+
122
+ new BuiltinInfo({ name: 'hex',
123
+ params: [p('x', { type: 'int' })],
124
+ return_type: 'str',
125
+ doc: 'Return the hexadecimal representation of an integer.' }),
126
+
127
+ new BuiltinInfo({ name: 'id',
128
+ params: [p('obj')],
129
+ return_type: 'int',
130
+ doc: 'Return the identity of an object.' }),
131
+
132
+ new BuiltinInfo({ name: 'int', kind: 'class',
133
+ params: [p('x', { optional: true }), p('base', { type: 'int', optional: true })],
134
+ return_type: 'int',
135
+ doc: 'Return an integer from x, optionally in the given base.' }),
136
+
137
+ new BuiltinInfo({ name: 'isinstance',
138
+ params: [p('obj'), p('classinfo')],
139
+ return_type: 'bool',
140
+ doc: 'Return True if obj is an instance of classinfo (or a subclass thereof).' }),
141
+
142
+ new BuiltinInfo({ name: 'iter',
143
+ params: [p('obj')],
144
+ return_type: 'iterator',
145
+ doc: 'Return an iterator object for obj.' }),
146
+
147
+ new BuiltinInfo({ name: 'len',
148
+ params: [p('s')],
149
+ return_type: 'int',
150
+ doc: 'Return the number of items in a container.' }),
151
+
152
+ new BuiltinInfo({ name: 'list', kind: 'class',
153
+ params: [p('iterable', { optional: true })],
154
+ return_type: 'list',
155
+ doc: 'Create a list from an iterable, or an empty list.' }),
156
+
157
+ new BuiltinInfo({ name: 'map',
158
+ params: [p('function'), p('iterable'), p('*iterables', { rest: true })],
159
+ return_type: 'iterable',
160
+ doc: 'Return an iterator applying function to each item of iterable.' }),
161
+
162
+ new BuiltinInfo({ name: 'max',
163
+ params: [p('iterable'), p('*args', { rest: true })],
164
+ return_type: 'any',
165
+ doc: 'Return the largest item in an iterable or the largest of two or more arguments.' }),
166
+
167
+ new BuiltinInfo({ name: 'min',
168
+ params: [p('iterable'), p('*args', { rest: true })],
169
+ return_type: 'any',
170
+ doc: 'Return the smallest item in an iterable or the smallest of two or more arguments.' }),
171
+
172
+ new BuiltinInfo({ name: 'ord',
173
+ params: [p('c', { type: 'str' })],
174
+ return_type: 'int',
175
+ doc: 'Return the Unicode code point integer for a one-character string.' }),
176
+
177
+ new BuiltinInfo({ name: 'pow',
178
+ params: [p('base', { type: 'number' }), p('exp', { type: 'number' }), p('mod', { optional: true })],
179
+ return_type: 'number',
180
+ doc: 'Return base raised to the power exp, optionally modulo mod.' }),
181
+
182
+ new BuiltinInfo({ name: 'print',
183
+ params: [p('*args', { rest: true }), p('sep', { default_val: "' '" }), p('end', { default_val: "'\\n'" })],
184
+ return_type: 'None',
185
+ doc: 'Print objects to the console. Items are separated by sep (default space). Transpiles to console.log().' }),
186
+
187
+ new BuiltinInfo({ name: 'range',
188
+ params: [p('start_or_stop', { type: 'int' }), p('stop', { type: 'int', optional: true }), p('step', { type: 'int', optional: true })],
189
+ return_type: 'range',
190
+ doc: 'Return a sequence of numbers. range(stop) counts from 0. range(start, stop[, step]) counts from start.' }),
191
+
192
+ new BuiltinInfo({ name: 'repr',
193
+ params: [p('obj')],
194
+ return_type: 'str',
195
+ doc: 'Return a string containing a printable representation of obj.' }),
196
+
197
+ new BuiltinInfo({ name: 'reversed',
198
+ params: [p('seq')],
199
+ return_type: 'iterator',
200
+ doc: 'Return a reverse iterator over a sequence.' }),
201
+
202
+ new BuiltinInfo({ name: 'round',
203
+ params: [p('number', { type: 'number' }), p('ndigits', { type: 'int', optional: true })],
204
+ return_type: 'number',
205
+ doc: 'Round number to ndigits decimal places (default 0).' }),
206
+
207
+ new BuiltinInfo({ name: 'set', kind: 'class',
208
+ params: [p('iterable', { optional: true })],
209
+ return_type: 'set',
210
+ doc: 'Create a new set, optionally populated from an iterable.' }),
211
+
212
+ new BuiltinInfo({ name: 'setattr',
213
+ params: [p('obj'), p('name', { type: 'str' }), p('value')],
214
+ return_type: 'None',
215
+ doc: 'Set the named attribute on obj to value.' }),
216
+
217
+ new BuiltinInfo({ name: 'sorted',
218
+ params: [p('iterable'), p('key', { optional: true }), p('reverse', { type: 'bool', optional: true })],
219
+ return_type: 'list',
220
+ doc: 'Return a new sorted list from the items in iterable.' }),
221
+
222
+ new BuiltinInfo({ name: 'super',
223
+ params: [],
224
+ return_type: 'object',
225
+ doc: 'Return a proxy object that delegates method calls to a parent class.\n\nUse `super()` inside a class method to call parent class methods:\n\n class Child(Parent):\n def __init__(self):\n super().__init__()\n def greet(self):\n return super().greet() + " from child"\n\nAlso supports the two-argument form `super(ClassName, self)` for explicit MRO lookup.' }),
226
+
227
+ new BuiltinInfo({ name: 'str', kind: 'class',
228
+ params: [p('obj', { optional: true })],
229
+ return_type: 'str',
230
+ doc: 'Return a string version of obj.' }),
231
+
232
+ new BuiltinInfo({ name: 'sum',
233
+ params: [p('iterable'), p('start', { optional: true })],
234
+ return_type: 'number',
235
+ doc: 'Sum the items of iterable, optionally starting from start (default 0).' }),
236
+
237
+ new BuiltinInfo({ name: 'type',
238
+ params: [p('obj')],
239
+ return_type: 'type',
240
+ doc: 'Return the type of an object.' }),
241
+
242
+ new BuiltinInfo({ name: 'zip',
243
+ params: [p('*iterables', { rest: true })],
244
+ return_type: 'iterable',
245
+ doc: 'Return an iterator of tuples, where each tuple groups the i-th element from each iterable.' }),
246
+
247
+ // ── RapydScript-specific ──────────────────────────────────────────────
248
+ new BuiltinInfo({ name: 'jstype',
249
+ params: [p('x')],
250
+ return_type: 'str',
251
+ doc: 'Return the JavaScript typeof string for x (e.g. "number", "string", "object").' }),
252
+
253
+ new BuiltinInfo({ name: 'repr',
254
+ params: [p('obj')],
255
+ return_type: 'str',
256
+ doc: 'Return a developer-friendly string representation of obj.' }),
257
+
258
+ // ── JS globals ────────────────────────────────────────────────────────
259
+ new BuiltinInfo({ name: 'parseInt',
260
+ params: [p('string', { type: 'str' }), p('radix', { type: 'int', optional: true })],
261
+ return_type: 'int',
262
+ doc: 'Parse a string and return an integer. Specify radix for the base (e.g. 16 for hex).' }),
263
+
264
+ new BuiltinInfo({ name: 'parseFloat',
265
+ params: [p('string', { type: 'str' })],
266
+ return_type: 'float',
267
+ doc: 'Parse a string and return a floating-point number.' }),
268
+
269
+ new BuiltinInfo({ name: 'isNaN',
270
+ params: [p('value')],
271
+ return_type: 'bool',
272
+ doc: 'Return True if value is NaN (Not a Number).' }),
273
+
274
+ new BuiltinInfo({ name: 'isFinite',
275
+ params: [p('value')],
276
+ return_type: 'bool',
277
+ doc: 'Return True if value is a finite number.' }),
278
+
279
+ new BuiltinInfo({ name: 'setTimeout',
280
+ params: [p('callback'), p('delay', { type: 'number' }), p('*args', { rest: true })],
281
+ return_type: 'int',
282
+ doc: 'Call callback after delay milliseconds. Returns a timeout ID.' }),
283
+
284
+ new BuiltinInfo({ name: 'setInterval',
285
+ params: [p('callback'), p('delay', { type: 'number' })],
286
+ return_type: 'int',
287
+ doc: 'Call callback repeatedly at every delay milliseconds. Returns an interval ID.' }),
288
+
289
+ new BuiltinInfo({ name: 'clearTimeout',
290
+ params: [p('id', { type: 'int' })],
291
+ return_type: 'None',
292
+ doc: 'Cancel a timeout set with setTimeout.' }),
293
+
294
+ new BuiltinInfo({ name: 'clearInterval',
295
+ params: [p('id', { type: 'int' })],
296
+ return_type: 'None',
297
+ doc: 'Cancel an interval set with setInterval.' }),
298
+
299
+ new BuiltinInfo({ name: 'encodeURIComponent',
300
+ params: [p('str', { type: 'str' })],
301
+ return_type: 'str',
302
+ doc: 'Encode a URI component by escaping special characters.' }),
303
+
304
+ new BuiltinInfo({ name: 'decodeURIComponent',
305
+ params: [p('str', { type: 'str' })],
306
+ return_type: 'str',
307
+ doc: 'Decode a URI component previously encoded with encodeURIComponent.' }),
308
+ ];
309
+
310
+ // ---------------------------------------------------------------------------
311
+ // Built-in type member stubs
312
+ // Each entry is compatible with _dts_member_to_item in completions.js:
313
+ // { name, kind ('method'|'property'), params?, return_type?, doc? }
314
+ // ---------------------------------------------------------------------------
315
+
316
+ function m(name, kind, params, return_type, doc) {
317
+ return { name, kind, params: params || null, return_type: return_type || null, doc: doc || null };
318
+ }
319
+ function mp(label, type) { return { name: label, type, optional: false, rest: false }; }
320
+
321
+ const TYPE_MEMBERS = {
322
+ list: new Map([
323
+ // JS array property
324
+ ['length', m('length', 'property', null, 'int', 'The number of elements in the array.')],
325
+ // Python-compat methods
326
+ ['append', m('append', 'method', [mp('item', 'any')], 'None', 'Append item to the end of the list.')],
327
+ ['extend', m('extend', 'method', [mp('iterable', 'any')], 'None', 'Extend the list by appending all items from the iterable.')],
328
+ ['insert', m('insert', 'method', [mp('index', 'int'), mp('item', 'any')], 'None', 'Insert item before index.')],
329
+ ['remove', m('remove', 'method', [mp('item', 'any')], 'None', 'Remove the first occurrence of item.')],
330
+ ['pop', m('pop', 'method', [mp('index', 'int')], 'any', 'Remove and return item at index (default last).')],
331
+ ['index', m('index', 'method', [mp('item', 'any')], 'int', 'Return first index of item.')],
332
+ ['count', m('count', 'method', [mp('item', 'any')], 'int', 'Return number of occurrences of item.')],
333
+ ['sort', m('sort', 'method', [], 'None', 'Sort the list in place.')],
334
+ ['reverse', m('reverse', 'method', [], 'None', 'Reverse the list in place.')],
335
+ ['copy', m('copy', 'method', [], 'list', 'Return a shallow copy of the list.')],
336
+ ['clear', m('clear', 'method', [], 'None', 'Remove all items from the list.')],
337
+ // JS array methods
338
+ ['push', m('push', 'method', [mp('...items', 'any')], 'int', 'Append one or more elements and return the new length.')],
339
+ ['slice', m('slice', 'method', [mp('start', 'int'), mp('end', 'int')], 'list', 'Return a shallow slice of the array.')],
340
+ ['splice', m('splice', 'method', [mp('start', 'int'), mp('deleteCount', 'int')], 'list', 'Change contents by removing or inserting elements.')],
341
+ ['concat', m('concat', 'method', [mp('...arrays', 'any')], 'list', 'Merge two or more arrays.')],
342
+ ['join', m('join', 'method', [mp('separator', 'str')], 'str', 'Join all elements into a string.')],
343
+ ['indexOf', m('indexOf', 'method', [mp('item', 'any')], 'int', 'Return first index of item, or -1 if not found.')],
344
+ ['lastIndexOf', m('lastIndexOf', 'method', [mp('item', 'any')], 'int', 'Return last index of item, or -1 if not found.')],
345
+ ['includes', m('includes', 'method', [mp('item', 'any')], 'bool', 'Return true if item is in the array.')],
346
+ ['forEach', m('forEach', 'method', [mp('callback', 'function')], 'None', 'Execute callback for each element.')],
347
+ ['map', m('map', 'method', [mp('callback', 'function')], 'list', 'Create a new array with the results of calling callback.')],
348
+ ['filter', m('filter', 'method', [mp('callback', 'function')], 'list', 'Create a new array with elements that pass the callback test.')],
349
+ ['reduce', m('reduce', 'method', [mp('callback', 'function'), mp('initial', 'any')], 'any', 'Reduce array to a single value.')],
350
+ ['find', m('find', 'method', [mp('callback', 'function')], 'any', 'Return first element satisfying callback, or undefined.')],
351
+ ['findIndex', m('findIndex', 'method', [mp('callback', 'function')], 'int', 'Return index of first element satisfying callback, or -1.')],
352
+ ['every', m('every', 'method', [mp('callback', 'function')], 'bool', 'Return true if all elements satisfy callback.')],
353
+ ['some', m('some', 'method', [mp('callback', 'function')], 'bool', 'Return true if at least one element satisfies callback.')],
354
+ ['flat', m('flat', 'method', [mp('depth', 'int')], 'list', 'Create a new array with sub-arrays flattened.')],
355
+ ['fill', m('fill', 'method', [mp('value', 'any'), mp('start', 'int'), mp('end', 'int')], 'list', 'Fill elements with a static value.')],
356
+ ['shift', m('shift', 'method', [], 'any', 'Remove and return the first element.')],
357
+ ['unshift', m('unshift', 'method', [mp('...items', 'any')], 'int', 'Prepend elements and return the new length.')],
358
+ ]),
359
+
360
+ str: new Map([
361
+ // JS string property
362
+ ['length', m('length', 'property', null, 'int', 'The number of characters in the string.')],
363
+ // Python-compat methods
364
+ ['upper', m('upper', 'method', [], 'str', 'Return an upper-case copy of the string.')],
365
+ ['lower', m('lower', 'method', [], 'str', 'Return a lower-case copy of the string.')],
366
+ ['strip', m('strip', 'method', [mp('chars', 'str')], 'str', 'Return a copy with leading and trailing whitespace removed.')],
367
+ ['lstrip', m('lstrip', 'method', [mp('chars', 'str')], 'str', 'Return a copy with leading whitespace removed.')],
368
+ ['rstrip', m('rstrip', 'method', [mp('chars', 'str')], 'str', 'Return a copy with trailing whitespace removed.')],
369
+ ['split', m('split', 'method', [mp('sep', 'str'), mp('maxsplit', 'int')], 'list', 'Return a list of words split on sep.')],
370
+ ['find', m('find', 'method', [mp('sub', 'str')], 'int', 'Return the lowest index of sub, or -1 if not found.')],
371
+ ['replace', m('replace', 'method', [mp('old', 'str'), mp('new', 'str')], 'str', 'Return a copy with all occurrences of old replaced by new.')],
372
+ ['startswith', m('startswith', 'method', [mp('prefix', 'str')], 'bool', 'Return True if the string starts with prefix.')],
373
+ ['endswith', m('endswith', 'method', [mp('suffix', 'str')], 'bool', 'Return True if the string ends with suffix.')],
374
+ ['format', m('format', 'method', [mp('*args', 'any')], 'str', 'Return a formatted version of the string.')],
375
+ ['encode', m('encode', 'method', [mp('encoding', 'str')], 'bytes', 'Encode the string.')],
376
+ ['join', m('join', 'method', [mp('iterable', 'any')], 'str', 'Join iterable elements with this string as separator.')],
377
+ // JS string methods
378
+ ['toUpperCase', m('toUpperCase', 'method', [], 'str', 'Return an upper-case copy of the string.')],
379
+ ['toLowerCase', m('toLowerCase', 'method', [], 'str', 'Return a lower-case copy of the string.')],
380
+ ['trim', m('trim', 'method', [], 'str', 'Return a copy with leading and trailing whitespace removed.')],
381
+ ['trimStart', m('trimStart', 'method', [], 'str', 'Return a copy with leading whitespace removed.')],
382
+ ['trimEnd', m('trimEnd', 'method', [], 'str', 'Return a copy with trailing whitespace removed.')],
383
+ ['includes', m('includes', 'method', [mp('sub', 'str')], 'bool', 'Return true if sub is found anywhere in the string.')],
384
+ ['startsWith', m('startsWith', 'method', [mp('prefix', 'str')], 'bool', 'Return true if the string starts with prefix.')],
385
+ ['endsWith', m('endsWith', 'method', [mp('suffix', 'str')], 'bool', 'Return true if the string ends with suffix.')],
386
+ ['indexOf', m('indexOf', 'method', [mp('sub', 'str')], 'int', 'Return first index of sub, or -1.')],
387
+ ['lastIndexOf', m('lastIndexOf', 'method', [mp('sub', 'str')], 'int', 'Return last index of sub, or -1.')],
388
+ ['slice', m('slice', 'method', [mp('start', 'int'), mp('end', 'int')], 'str', 'Extract a section of the string.')],
389
+ ['substring', m('substring', 'method', [mp('start', 'int'), mp('end', 'int')], 'str', 'Return characters between start and end.')],
390
+ ['charAt', m('charAt', 'method', [mp('index', 'int')], 'str', 'Return character at the given index.')],
391
+ ['charCodeAt', m('charCodeAt', 'method', [mp('index', 'int')], 'int', 'Return UTF-16 code of character at index.')],
392
+ ['repeat', m('repeat', 'method', [mp('count', 'int')], 'str', 'Return the string repeated count times.')],
393
+ ['padStart', m('padStart', 'method', [mp('length', 'int'), mp('pad', 'str')], 'str', 'Pad start of string to target length.')],
394
+ ['padEnd', m('padEnd', 'method', [mp('length', 'int'), mp('pad', 'str')], 'str', 'Pad end of string to target length.')],
395
+ ['match', m('match', 'method', [mp('regex', 'str')], 'list', 'Match string against a regular expression.')],
396
+ ['replaceAll', m('replaceAll', 'method', [mp('old', 'str'), mp('new', 'str')], 'str', 'Return a copy with all occurrences replaced.')],
397
+ ]),
398
+
399
+ dict: new Map([
400
+ // Python-compat methods
401
+ ['keys', m('keys', 'method', [], 'list', 'Return a view of the dictionary keys.')],
402
+ ['values', m('values', 'method', [], 'list', 'Return a view of the dictionary values.')],
403
+ ['items', m('items', 'method', [], 'list', 'Return a view of the (key, value) pairs.')],
404
+ ['get', m('get', 'method', [mp('key', 'any'), mp('default', 'any')], 'any', 'Return value for key, or default if not found.')],
405
+ ['update', m('update', 'method', [mp('other', 'dict')], 'None', 'Update the dictionary with key-value pairs from other.')],
406
+ ['pop', m('pop', 'method', [mp('key', 'any'), mp('default', 'any')], 'any', 'Remove and return value for key.')],
407
+ ['clear', m('clear', 'method', [], 'None', 'Remove all items from the dictionary.')],
408
+ ['copy', m('copy', 'method', [], 'dict', 'Return a shallow copy of the dictionary.')],
409
+ ['setdefault', m('setdefault', 'method', [mp('key', 'any'), mp('default', 'any')], 'any', 'Return value for key; if missing, insert key with default.')],
410
+ ['has_key', m('has_key', 'method', [mp('key', 'any')], 'bool', 'Return True if key is in the dictionary.')],
411
+ ]),
412
+
413
+ number: new Map([
414
+ ['toFixed', m('toFixed', 'method', [mp('digits', 'int')], 'str', 'Format number to fixed decimal places.')],
415
+ ['toPrecision', m('toPrecision', 'method', [mp('precision', 'int')], 'str', 'Format number to specified precision.')],
416
+ ['toString', m('toString', 'method', [mp('radix', 'int')], 'str', 'Convert number to string in given base.')],
417
+ ['toExponential', m('toExponential', 'method', [mp('digits', 'int')], 'str', 'Format number in exponential notation.')],
418
+ ]),
419
+ };
420
+
421
+ // Extra str members added when pythonize_strings is enabled.
422
+ // These are the methods from pythonize.strings() not already in TYPE_MEMBERS.str.
423
+ const PYTHONIZE_STR_EXTRA_MEMBERS = new Map([
424
+ ['capitalize', m('capitalize', 'method', [], 'str', 'Return a copy with the first character capitalized and the rest lowercased.')],
425
+ ['islower', m('islower', 'method', [], 'bool', 'Return True if all cased characters are lowercase.')],
426
+ ['isupper', m('isupper', 'method', [], 'bool', 'Return True if all cased characters are uppercase.')],
427
+ ['isspace', m('isspace', 'method', [], 'bool', 'Return True if all characters in the string are whitespace.')],
428
+ ['swapcase', m('swapcase', 'method', [], 'str', 'Return a copy with uppercase characters converted to lowercase and vice versa.')],
429
+ ['title', m('title', 'method', [], 'str', 'Return a title-cased version of the string.')],
430
+ ['center', m('center', 'method', [mp('width', 'int'), mp('fillchar', 'str')], 'str', 'Return the string centered in a field of the given width.')],
431
+ ['count', m('count', 'method', [mp('sub', 'str'), mp('start', 'int'), mp('end', 'int')], 'int', 'Return the number of non-overlapping occurrences of sub.')],
432
+ ['rfind', m('rfind', 'method', [mp('sub', 'str'), mp('start', 'int'), mp('end', 'int')], 'int', 'Return the highest index of sub, or -1 if not found.')],
433
+ ['index', m('index', 'method', [mp('sub', 'str'), mp('start', 'int'), mp('end', 'int')], 'int', 'Like find, but raise ValueError if sub is not found.')],
434
+ ['rindex', m('rindex', 'method', [mp('sub', 'str'), mp('start', 'int'), mp('end', 'int')], 'int', 'Like rfind, but raise ValueError if sub is not found.')],
435
+ ['ljust', m('ljust', 'method', [mp('width', 'int'), mp('fillchar', 'str')], 'str', 'Return the string left-justified in a field of the given width.')],
436
+ ['rjust', m('rjust', 'method', [mp('width', 'int'), mp('fillchar', 'str')], 'str', 'Return the string right-justified in a field of the given width.')],
437
+ ['partition', m('partition', 'method', [mp('sep', 'str')], 'list', 'Split at the first occurrence of sep; return a 3-element tuple.')],
438
+ ['rpartition', m('rpartition', 'method', [mp('sep', 'str')], 'list', 'Split at the last occurrence of sep; return a 3-element tuple.')],
439
+ ['rsplit', m('rsplit', 'method', [mp('sep', 'str'), mp('maxsplit', 'int')], 'list', 'Return a list of words split on sep from the right.')],
440
+ ['splitlines', m('splitlines', 'method', [mp('keepends', 'bool')], 'list', 'Return a list of the lines in the string, breaking at line boundaries.')],
441
+ ['zfill', m('zfill', 'method', [mp('width', 'int')], 'str', 'Pad the string on the left with zeros to fill a field of the given width.')],
442
+ ]);
443
+
444
+ // ---------------------------------------------------------------------------
445
+ // BuiltinsRegistry
446
+ // ---------------------------------------------------------------------------
447
+
448
+ export class BuiltinsRegistry {
449
+ constructor() {
450
+ this._stubs = new Map();
451
+ for (const stub of STUBS) {
452
+ this._stubs.set(stub.name, stub);
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Return the BuiltinInfo for name, or null.
458
+ * @param {string} name
459
+ * @returns {BuiltinInfo|null}
460
+ */
461
+ get(name) {
462
+ return this._stubs.get(name) || null;
463
+ }
464
+
465
+ /**
466
+ * Return all registered stub names.
467
+ * @returns {string[]}
468
+ */
469
+ getNames() {
470
+ return Array.from(this._stubs.keys());
471
+ }
472
+
473
+ /**
474
+ * Merge the pythonize string methods into the 'str' type members so that
475
+ * dot-completions on string variables include all Python-style methods.
476
+ * Safe to call multiple times (idempotent).
477
+ */
478
+ enablePythonizeStrings() {
479
+ const str_map = TYPE_MEMBERS.str;
480
+ for (const [name, member] of PYTHONIZE_STR_EXTRA_MEMBERS) {
481
+ if (!str_map.has(name)) str_map.set(name, member);
482
+ }
483
+ }
484
+
485
+ /**
486
+ * Return the Map of member stubs for a built-in type, or null.
487
+ * Each value is compatible with _dts_member_to_item in completions.js.
488
+ * @param {string} type_name e.g. 'list', 'str', 'dict', 'number'
489
+ * @returns {Map|null}
490
+ */
491
+ getTypeMembers(type_name) {
492
+ return TYPE_MEMBERS[type_name] || null;
493
+ }
494
+
495
+ /**
496
+ * Return hover markdown for a built-in, or null.
497
+ * @param {string} name
498
+ * @returns {string|null}
499
+ */
500
+ getHoverMarkdown(name) {
501
+ const stub = this.get(name);
502
+ if (!stub) return null;
503
+ const sig = _build_sig(stub);
504
+ let md = '```python\n' + sig + '\n```';
505
+ if (stub.doc) md += '\n\n' + stub.doc;
506
+ return md;
507
+ }
508
+
509
+ /**
510
+ * Return Monaco-compatible signature info for a built-in, or null.
511
+ * @param {string} name
512
+ * @returns {{ label: string, params: {label: string}[], doc: string|null }|null}
513
+ */
514
+ getSignatureInfo(name) {
515
+ const stub = this.get(name);
516
+ if (!stub || !stub.params) return null;
517
+ const param_strs = stub.params.map(_param_label);
518
+ const label = stub.name + '(' + param_strs.join(', ') + ')';
519
+ return {
520
+ label,
521
+ params: param_strs.map(function (s) { return { label: s }; }),
522
+ doc: stub.doc,
523
+ };
524
+ }
525
+ }
526
+
527
+ // ---------------------------------------------------------------------------
528
+ // Rendering helpers
529
+ // ---------------------------------------------------------------------------
530
+
531
+ function _param_label(p) {
532
+ let s = p.label;
533
+ if (p.type && p.type !== 'any') s += ': ' + p.type;
534
+ if (p.optional) s += '?';
535
+ return s;
536
+ }
537
+
538
+ function _build_sig(stub) {
539
+ const ps = stub.params ? stub.params.map(_param_label).join(', ') : '';
540
+ let sig = stub.name + '(' + ps + ')';
541
+ if (stub.return_type && stub.return_type !== 'None') sig += ' → ' + stub.return_type;
542
+ return sig;
543
+ }