rapydscript-ns 0.8.2 → 0.8.4
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 -1
- package/.github/workflows/ci.yml +38 -38
- package/=template.pyj +5 -5
- package/CHANGELOG.md +39 -0
- package/HACKING.md +103 -103
- package/LICENSE +24 -24
- package/PYTHON_DIFFERENCES_REPORT.md +291 -0
- package/PYTHON_FEATURE_COVERAGE.md +106 -15
- package/README.md +831 -52
- package/TODO.md +4 -286
- package/add-toc-to-readme +2 -2
- package/bin/export +75 -75
- package/bin/rapydscript +70 -70
- package/bin/web-repl-export +102 -102
- package/build +2 -2
- package/language-service/index.js +4623 -0
- package/language-service/language-service.d.ts +40 -0
- package/package.json +9 -7
- package/publish.py +37 -37
- package/release/baselib-plain-pretty.js +2006 -229
- package/release/baselib-plain-ugly.js +70 -3
- package/release/compiler.js +11554 -3870
- package/release/signatures.json +31 -29
- package/session.vim +4 -4
- package/setup.cfg +2 -2
- package/src/ast.pyj +93 -1
- package/src/baselib-builtins.pyj +99 -2
- package/src/baselib-containers.pyj +107 -4
- package/src/baselib-errors.pyj +44 -0
- package/src/baselib-internal.pyj +124 -5
- package/src/baselib-itertools.pyj +97 -97
- package/src/baselib-str.pyj +32 -1
- package/src/compiler.pyj +36 -36
- package/src/errors.pyj +30 -30
- package/src/lib/aes.pyj +646 -646
- package/src/lib/collections.pyj +1 -1
- package/src/lib/copy.pyj +120 -0
- package/src/lib/elementmaker.pyj +83 -83
- package/src/lib/encodings.pyj +126 -126
- package/src/lib/gettext.pyj +569 -569
- package/src/lib/itertools.pyj +580 -580
- package/src/lib/math.pyj +193 -193
- package/src/lib/numpy.pyj +10 -10
- package/src/lib/operator.pyj +11 -11
- package/src/lib/pythonize.pyj +20 -20
- package/src/lib/random.pyj +118 -118
- package/src/lib/re.pyj +470 -470
- package/src/lib/react.pyj +74 -0
- package/src/lib/traceback.pyj +63 -63
- package/src/lib/uuid.pyj +77 -77
- package/src/monaco-language-service/analyzer.js +131 -9
- package/src/monaco-language-service/builtins.js +17 -2
- package/src/monaco-language-service/completions.js +170 -1
- package/src/monaco-language-service/diagnostics.js +25 -3
- package/src/monaco-language-service/dts.js +550 -550
- package/src/monaco-language-service/index.js +17 -0
- package/src/monaco-language-service/scope.js +3 -0
- package/src/output/classes.pyj +128 -11
- package/src/output/codegen.pyj +17 -3
- package/src/output/comments.pyj +45 -45
- package/src/output/exceptions.pyj +201 -105
- package/src/output/functions.pyj +13 -16
- package/src/output/jsx.pyj +164 -0
- package/src/output/literals.pyj +28 -2
- package/src/output/loops.pyj +0 -9
- package/src/output/modules.pyj +2 -5
- package/src/output/operators.pyj +22 -2
- package/src/output/statements.pyj +2 -2
- package/src/output/stream.pyj +1 -13
- package/src/output/treeshake.pyj +182 -182
- package/src/output/utils.pyj +72 -72
- package/src/parse.pyj +434 -114
- package/src/string_interpolation.pyj +72 -72
- package/src/tokenizer.pyj +29 -0
- package/src/unicode_aliases.pyj +576 -576
- package/src/utils.pyj +192 -192
- package/test/_import_one.pyj +37 -37
- package/test/_import_two/__init__.pyj +11 -11
- package/test/_import_two/level2/deep.pyj +4 -4
- package/test/_import_two/other.pyj +6 -6
- package/test/_import_two/sub.pyj +13 -13
- package/test/aes_vectors.pyj +421 -421
- package/test/annotations.pyj +80 -80
- package/test/baselib.pyj +4 -4
- package/test/classes.pyj +56 -17
- package/test/collections.pyj +5 -5
- package/test/decorators.pyj +77 -77
- package/test/docstrings.pyj +39 -39
- package/test/elementmaker_test.pyj +45 -45
- package/test/functions.pyj +151 -151
- package/test/generators.pyj +41 -41
- package/test/generic.pyj +370 -370
- package/test/imports.pyj +72 -72
- package/test/internationalization.pyj +73 -73
- package/test/lint.pyj +164 -164
- package/test/loops.pyj +85 -85
- package/test/numpy.pyj +734 -734
- package/test/omit_function_metadata.pyj +20 -20
- package/test/python_compat.pyj +326 -0
- package/test/python_features.pyj +129 -29
- package/test/regexp.pyj +55 -55
- package/test/repl.pyj +121 -121
- package/test/scoped_flags.pyj +76 -76
- package/test/slice.pyj +105 -0
- package/test/str.pyj +25 -0
- package/test/unit/fixtures/fibonacci_expected.js +1 -1
- package/test/unit/index.js +2296 -71
- package/test/unit/language-service-builtins.js +70 -0
- package/test/unit/language-service-bundle.js +5 -5
- package/test/unit/language-service-completions.js +180 -0
- package/test/unit/language-service-dts.js +543 -543
- package/test/unit/language-service-hover.js +455 -455
- package/test/unit/language-service-index.js +350 -0
- package/test/unit/language-service-scope.js +255 -0
- package/test/unit/language-service.js +625 -4
- package/test/unit/run-language-service.js +1 -0
- package/test/unit/web-repl.js +437 -0
- package/tools/build-language-service.js +2 -2
- package/tools/cli.js +547 -547
- package/tools/compile.js +219 -219
- package/tools/compiler.js +0 -24
- package/tools/completer.js +131 -131
- package/tools/embedded_compiler.js +251 -251
- package/tools/export.js +3 -37
- package/tools/gettext.js +185 -185
- package/tools/ini.js +65 -65
- package/tools/msgfmt.js +187 -187
- package/tools/repl.js +223 -223
- package/tools/test.js +118 -118
- package/tools/utils.js +128 -128
- package/tools/web_repl.js +95 -95
- package/try +41 -41
- package/web-repl/env.js +196 -74
- package/web-repl/index.html +163 -163
- package/web-repl/main.js +252 -254
- package/web-repl/prism.css +139 -139
- package/web-repl/prism.js +113 -113
- package/web-repl/rapydscript.js +227 -139
- package/web-repl/sha1.js +25 -25
- package/hack_demo.pyj +0 -112
- package/web-repl/language-service.js +0 -4187
|
@@ -45,6 +45,13 @@ export const KEYWORDS = [
|
|
|
45
45
|
* @returns {{ type: string, objectName?: string, moduleName?: string, prefix: string }}
|
|
46
46
|
*/
|
|
47
47
|
export function detect_context(linePrefix) {
|
|
48
|
+
// `obj.method().attr` — dot access on a call result (single-level call expression).
|
|
49
|
+
// Must be checked before the plain dot match since `[\w.]+` cannot span `()`.
|
|
50
|
+
const call_result_match = linePrefix.match(/([\w.]+)\([^)]*\)\.([\w]*)$/);
|
|
51
|
+
if (call_result_match) {
|
|
52
|
+
return { type: 'call_result', callPath: call_result_match[1], prefix: call_result_match[2] };
|
|
53
|
+
}
|
|
54
|
+
|
|
48
55
|
// `obj.attr` or `obj.sub.attr` — dot access (captures multi-level path)
|
|
49
56
|
const dot_match = linePrefix.match(/([\w.]+)\.([\w]*)$/);
|
|
50
57
|
if (dot_match) {
|
|
@@ -265,6 +272,9 @@ export class CompletionEngine {
|
|
|
265
272
|
getCompletions(scopeMap, position, linePrefix, monacoKind) {
|
|
266
273
|
const ctx = detect_context(linePrefix);
|
|
267
274
|
|
|
275
|
+
if (ctx.type === 'call_result') {
|
|
276
|
+
return { suggestions: this._call_result_completions(position, ctx, monacoKind, scopeMap) };
|
|
277
|
+
}
|
|
268
278
|
if (ctx.type === 'dot') {
|
|
269
279
|
return { suggestions: this._dot_completions(scopeMap, position, ctx, monacoKind) };
|
|
270
280
|
}
|
|
@@ -346,6 +356,82 @@ export class CompletionEngine {
|
|
|
346
356
|
return items;
|
|
347
357
|
}
|
|
348
358
|
|
|
359
|
+
// ---- Return-type helpers -----------------------------------------------
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Analyze a module and return the `return_type` of a named function.
|
|
363
|
+
* @param {string} func_name
|
|
364
|
+
* @param {string} module_name
|
|
365
|
+
* @returns {string|null}
|
|
366
|
+
*/
|
|
367
|
+
_get_return_type_from_module(func_name, module_name) {
|
|
368
|
+
const src = this._virtualFiles[module_name] || this._stdlibFiles[module_name];
|
|
369
|
+
if (!src) return null;
|
|
370
|
+
let mod_map;
|
|
371
|
+
try {
|
|
372
|
+
mod_map = this._analyzer.analyze(src, {});
|
|
373
|
+
} catch (_e) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
const mod_frame = mod_map.frames.find(f => f.kind === 'module');
|
|
377
|
+
if (!mod_frame) return null;
|
|
378
|
+
const fn_sym = mod_frame.getSymbol(func_name);
|
|
379
|
+
if (fn_sym && fn_sym.return_type) return fn_sym.return_type;
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Resolve a type name (e.g. from inferred_class) through function return annotations,
|
|
385
|
+
* including cross-file imports. Returns the resolved type name, or null if unresolvable.
|
|
386
|
+
* @param {string} name
|
|
387
|
+
* @param {import('./scope.js').ScopeMap} scopeMap
|
|
388
|
+
* @returns {string|null}
|
|
389
|
+
*/
|
|
390
|
+
_resolve_type_through_functions(name, scopeMap) {
|
|
391
|
+
let sym = null;
|
|
392
|
+
for (const frame of scopeMap.frames) {
|
|
393
|
+
const s = frame.getSymbol(name);
|
|
394
|
+
if (s) { sym = s; break; }
|
|
395
|
+
}
|
|
396
|
+
if (!sym) return null;
|
|
397
|
+
|
|
398
|
+
if (sym.kind === 'function' || sym.kind === 'method') {
|
|
399
|
+
// return_type is set by explicit annotation or inferred by the analyzer
|
|
400
|
+
if (sym.return_type) return sym.return_type;
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (sym.kind === 'import' && sym.source_module) {
|
|
405
|
+
const orig = sym.original_name || sym.name;
|
|
406
|
+
return this._get_return_type_from_module(orig, sym.source_module);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Get the member map for a given type name.
|
|
414
|
+
* Checks builtins, then user class frames. Returns null if unknown.
|
|
415
|
+
* @param {string} type_name
|
|
416
|
+
* @param {import('./scope.js').ScopeMap|null} scopeMap
|
|
417
|
+
* @returns {Map|null}
|
|
418
|
+
*/
|
|
419
|
+
_get_members_for_type(type_name, scopeMap) {
|
|
420
|
+
if (!type_name) return null;
|
|
421
|
+
if (this._builtins) {
|
|
422
|
+
const m = this._builtins.getTypeMembers(type_name);
|
|
423
|
+
if (m) return m;
|
|
424
|
+
}
|
|
425
|
+
if (scopeMap) {
|
|
426
|
+
for (const frame of scopeMap.frames) {
|
|
427
|
+
if (frame.kind === 'class' && frame.name === type_name) {
|
|
428
|
+
return frame.symbols;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
|
|
349
435
|
// ---- Dot completions ---------------------------------------------------
|
|
350
436
|
|
|
351
437
|
_dot_completions(scopeMap, position, ctx, monacoKind) {
|
|
@@ -413,6 +499,13 @@ export class CompletionEngine {
|
|
|
413
499
|
}
|
|
414
500
|
}
|
|
415
501
|
|
|
502
|
+
// Resolve class_name through function return type annotations.
|
|
503
|
+
// e.g. x = getAllServers() → inferred_class='getAllServers' → resolve 'list'
|
|
504
|
+
if (class_name) {
|
|
505
|
+
const resolved = this._resolve_type_through_functions(class_name, scopeMap);
|
|
506
|
+
if (resolved) class_name = resolved;
|
|
507
|
+
}
|
|
508
|
+
|
|
416
509
|
if (class_name) {
|
|
417
510
|
for (const frame of scopeMap.frames) {
|
|
418
511
|
if (frame.kind === 'class' && frame.name === class_name) {
|
|
@@ -433,7 +526,13 @@ export class CompletionEngine {
|
|
|
433
526
|
// 1.5. Built-in type members — list, str, dict, number.
|
|
434
527
|
// Used when inferred_class names a built-in type, not a user class.
|
|
435
528
|
if (!scope_matched && this._builtins && obj_sym && obj_sym.inferred_class) {
|
|
436
|
-
|
|
529
|
+
// Re-resolve in case inferred_class itself is a function name.
|
|
530
|
+
let type_name = obj_sym.inferred_class;
|
|
531
|
+
if (scopeMap) {
|
|
532
|
+
const resolved = this._resolve_type_through_functions(type_name, scopeMap);
|
|
533
|
+
if (resolved) type_name = resolved;
|
|
534
|
+
}
|
|
535
|
+
const members = this._builtins.getTypeMembers(type_name);
|
|
437
536
|
if (members) {
|
|
438
537
|
scope_matched = true;
|
|
439
538
|
for (const [name, member] of members) {
|
|
@@ -496,6 +595,76 @@ export class CompletionEngine {
|
|
|
496
595
|
return items;
|
|
497
596
|
}
|
|
498
597
|
|
|
598
|
+
// ---- Call-result dot completions (e.g. ns.self().attr) -----------------
|
|
599
|
+
|
|
600
|
+
_call_result_completions(position, ctx, monacoKind, scopeMap) {
|
|
601
|
+
const range = word_range(position, ctx.prefix);
|
|
602
|
+
const items = [];
|
|
603
|
+
const seen = new Set();
|
|
604
|
+
const call_path = ctx.callPath;
|
|
605
|
+
const last_dot = call_path.lastIndexOf('.');
|
|
606
|
+
|
|
607
|
+
// --- DTS path (existing logic) ---
|
|
608
|
+
if (this._dts) {
|
|
609
|
+
let member_ti = null;
|
|
610
|
+
if (last_dot > 0) {
|
|
611
|
+
const object_path = call_path.slice(0, last_dot);
|
|
612
|
+
const method_name = call_path.slice(last_dot + 1);
|
|
613
|
+
member_ti = this._dts.getMemberInfo(object_path, method_name);
|
|
614
|
+
} else {
|
|
615
|
+
member_ti = this._dts.getGlobal(call_path);
|
|
616
|
+
}
|
|
617
|
+
if (member_ti && member_ti.return_type) {
|
|
618
|
+
const return_ti = this._dts.getGlobal(resolve_first_type(member_ti.return_type));
|
|
619
|
+
if (return_ti && return_ti.members) {
|
|
620
|
+
for (const [name, member] of return_ti.members) {
|
|
621
|
+
if (!ctx.prefix || name.startsWith(ctx.prefix)) {
|
|
622
|
+
seen.add(name);
|
|
623
|
+
items.push(_dts_member_to_item(member, range, monacoKind));
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// --- User-defined function return types (scopeMap) ---
|
|
631
|
+
if (scopeMap && last_dot < 0) {
|
|
632
|
+
// Simple call like getAllServers() — look up function in scope
|
|
633
|
+
let sym = null;
|
|
634
|
+
for (const frame of scopeMap.frames) {
|
|
635
|
+
const s = frame.getSymbol(call_path);
|
|
636
|
+
if (s) { sym = s; break; }
|
|
637
|
+
}
|
|
638
|
+
if (sym) {
|
|
639
|
+
let return_type = null;
|
|
640
|
+
if (sym.kind === 'function' || sym.kind === 'method') {
|
|
641
|
+
return_type = sym.return_type;
|
|
642
|
+
} else if (sym.kind === 'import' && sym.source_module) {
|
|
643
|
+
const orig = sym.original_name || sym.name;
|
|
644
|
+
return_type = this._get_return_type_from_module(orig, sym.source_module);
|
|
645
|
+
}
|
|
646
|
+
if (return_type) {
|
|
647
|
+
const members = this._get_members_for_type(return_type, scopeMap);
|
|
648
|
+
if (members) {
|
|
649
|
+
for (const [name, member] of members) {
|
|
650
|
+
if (!seen.has(name) && (!ctx.prefix || name.startsWith(ctx.prefix))) {
|
|
651
|
+
seen.add(name);
|
|
652
|
+
// members may be SymbolInfo (class frame) or TypeInfo/BuiltinInfo
|
|
653
|
+
const item = member.kind === 'function' || member.kind === 'method' ||
|
|
654
|
+
member.kind === 'variable' || member.kind === 'parameter'
|
|
655
|
+
? symbol_to_item(member, range, monacoKind, '0')
|
|
656
|
+
: _dts_member_to_item(member, range, monacoKind);
|
|
657
|
+
items.push(item);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return items;
|
|
666
|
+
}
|
|
667
|
+
|
|
499
668
|
// ---- from X import completions -----------------------------------------
|
|
500
669
|
|
|
501
670
|
_from_import_completions(position, ctx, monacoKind) {
|
|
@@ -22,6 +22,20 @@ const MESSAGES = {
|
|
|
22
22
|
'dup-method': 'The method "{name}" was defined previously at line: {line}',
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
// Built-in stdlib modules that are always available in RapydScript (bundled
|
|
26
|
+
// with the compiler from src/lib/). These should never produce 'Unknown module'
|
|
27
|
+
// errors regardless of what virtualFiles or stdlibFiles are configured.
|
|
28
|
+
export const STDLIB_MODULES = [
|
|
29
|
+
'aes', 'collections', 'copy', 'elementmaker', 'encodings', 'functools',
|
|
30
|
+
'gettext', 'itertools', 'math', 'numpy', 'operator', 'pythonize',
|
|
31
|
+
'random', 're', 'react', 'traceback', 'uuid',
|
|
32
|
+
// Pseudo-modules for language feature flags (from __python__ import ...)
|
|
33
|
+
'__python__', '__builtins__',
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const _STDLIB_MODULE_SET = Object.create(null);
|
|
37
|
+
STDLIB_MODULES.forEach(m => { _STDLIB_MODULE_SET[m] = true; });
|
|
38
|
+
|
|
25
39
|
// Symbols always available in RapydScript (from tools/lint.js BUILTINS list).
|
|
26
40
|
export const BASE_BUILTINS = (
|
|
27
41
|
'this self window document chr ord iterator_symbol print len range dir' +
|
|
@@ -30,11 +44,11 @@ export const BASE_BUILTINS = (
|
|
|
30
44
|
' isNaN JSON Math list set list_wrap ρσ_modules require bool int bin' +
|
|
31
45
|
' float iter Error EvalError set_wrap frozenset RangeError ReferenceError SyntaxError' +
|
|
32
46
|
' str TypeError URIError Exception AssertionError IndexError AttributeError KeyError' +
|
|
33
|
-
' ValueError ZeroDivisionError map hex filter zip dict dict_wrap UnicodeDecodeError HTMLCollection' +
|
|
47
|
+
' ValueError ZeroDivisionError ImportError ModuleNotFoundError StopIteration map hex filter zip dict dict_wrap UnicodeDecodeError HTMLCollection' +
|
|
34
48
|
' NodeList alert console Node Symbol NamedNodeMap ρσ_eslice ρσ_delslice Number' +
|
|
35
49
|
' Boolean encodeURIComponent decodeURIComponent setTimeout setInterval' +
|
|
36
50
|
' setImmediate clearTimeout clearInterval clearImmediate requestAnimationFrame' +
|
|
37
|
-
' id repr sorted __name__ equals get_module ρσ_str jstype divmod NaN super Ellipsis'
|
|
51
|
+
' id repr sorted __name__ equals get_module ρσ_str jstype divmod NaN super Ellipsis slice all any next __import__ ρσ_new ρσ_object_new hash ρσ_object_setattr ρσ_object_getattr ρσ_object_delattr ExceptionGroup BaseExceptionGroup tuple'
|
|
38
52
|
).split(' ');
|
|
39
53
|
|
|
40
54
|
// ---------------------------------------------------------------------------
|
|
@@ -384,7 +398,13 @@ function Linter(RS, toplevel, code, builtins, knownModules) {
|
|
|
384
398
|
};
|
|
385
399
|
|
|
386
400
|
this.handle_symbol_funarg = function() {
|
|
387
|
-
this.
|
|
401
|
+
const node = this.current_node;
|
|
402
|
+
this.add_binding(node.name);
|
|
403
|
+
// Suppress undefined-symbol errors for type names used in argument
|
|
404
|
+
// annotations: `def foo(x: MyType):` — MyType is a hint, not a ref.
|
|
405
|
+
if (node.annotation instanceof RS.AST_SymbolRef) {
|
|
406
|
+
node.annotation.lint_visited = true;
|
|
407
|
+
}
|
|
388
408
|
};
|
|
389
409
|
|
|
390
410
|
this.handle_comprehension = function() {
|
|
@@ -681,6 +701,8 @@ export class Diagnostics {
|
|
|
681
701
|
const sf = options.stdlibFiles;
|
|
682
702
|
if ((vf && Object.keys(vf).length > 0) || (sf && Object.keys(sf).length > 0)) {
|
|
683
703
|
knownModules = Object.create(null);
|
|
704
|
+
// Always include built-in stdlib so they never produce bad-import errors.
|
|
705
|
+
Object.assign(knownModules, _STDLIB_MODULE_SET);
|
|
684
706
|
if (vf) Object.keys(vf).forEach(k => { knownModules[k] = true; });
|
|
685
707
|
if (sf) Object.keys(sf).forEach(k => { knownModules[k] = true; });
|
|
686
708
|
}
|