rapydscript-ns 0.8.1 → 0.8.3

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 (58) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/CONTRIBUTORS +3 -2
  3. package/PYTHON_DIFFERENCES_REPORT.md +291 -0
  4. package/PYTHON_FEATURE_COVERAGE.md +200 -0
  5. package/README.md +480 -79
  6. package/TODO.md +6 -318
  7. package/hack_demo.pyj +112 -0
  8. package/language-service/index.js +4474 -0
  9. package/language-service/language-service.d.ts +40 -0
  10. package/package.json +9 -10
  11. package/src/ast.pyj +30 -6
  12. package/src/baselib-builtins.pyj +181 -11
  13. package/src/baselib-containers.pyj +154 -5
  14. package/src/baselib-errors.pyj +3 -0
  15. package/src/baselib-internal.pyj +40 -1
  16. package/src/baselib-str.pyj +42 -1
  17. package/src/lib/collections.pyj +1 -1
  18. package/src/lib/numpy.pyj +10 -10
  19. package/src/monaco-language-service/analyzer.js +132 -22
  20. package/src/monaco-language-service/builtins.js +22 -2
  21. package/src/monaco-language-service/completions.js +224 -3
  22. package/src/monaco-language-service/diagnostics.js +55 -5
  23. package/src/monaco-language-service/index.js +26 -5
  24. package/src/monaco-language-service/scope.js +3 -0
  25. package/src/output/classes.pyj +20 -3
  26. package/src/output/codegen.pyj +38 -3
  27. package/src/output/functions.pyj +35 -25
  28. package/src/output/loops.pyj +64 -11
  29. package/src/output/modules.pyj +1 -4
  30. package/src/output/operators.pyj +67 -1
  31. package/src/output/statements.pyj +7 -3
  32. package/src/output/stream.pyj +6 -13
  33. package/src/parse.pyj +94 -14
  34. package/src/tokenizer.pyj +1 -0
  35. package/test/baselib.pyj +4 -4
  36. package/test/classes.pyj +56 -17
  37. package/test/collections.pyj +5 -5
  38. package/test/python_compat.pyj +326 -0
  39. package/test/python_features.pyj +1271 -0
  40. package/test/slice.pyj +105 -0
  41. package/test/str.pyj +25 -0
  42. package/test/unit/fixtures/fibonacci_expected.js +1 -1
  43. package/test/unit/index.js +119 -7
  44. package/test/unit/language-service-builtins.js +70 -0
  45. package/test/unit/language-service-bundle.js +83 -0
  46. package/test/unit/language-service-completions.js +289 -0
  47. package/test/unit/language-service-index.js +350 -0
  48. package/test/unit/language-service-scope.js +255 -0
  49. package/test/unit/language-service.js +158 -1
  50. package/test/unit/run-language-service.js +2 -0
  51. package/test/unit/web-repl.js +134 -0
  52. package/tools/build-language-service.js +2 -2
  53. package/tools/compiler.js +0 -24
  54. package/tools/export.js +3 -37
  55. package/tools/lint.js +1 -1
  56. package/tools/self.js +1 -9
  57. package/web-repl/rapydscript.js +6 -40
  58. package/web-repl/language-service.js +0 -4084
@@ -770,6 +770,261 @@ function make_tests(SourceAnalyzer, RS) {
770
770
  },
771
771
  },
772
772
 
773
+ // ── Return type inference ─────────────────────────────────────────
774
+
775
+ {
776
+ name: "infer_return_type_list_literal",
777
+ description: "return [] infers return_type = 'list'",
778
+ run: function () {
779
+ var m = analyze("def get_items():\n return []");
780
+ var sym = find(m.getAllSymbols(), "get_items");
781
+ assert.ok(sym, "Expected 'get_items' symbol");
782
+ assert.strictEqual(sym.return_type, "list",
783
+ "Expected return_type 'list', got: " + sym.return_type);
784
+ },
785
+ },
786
+
787
+ {
788
+ name: "infer_return_type_dict_literal",
789
+ description: "return {} infers return_type = 'dict'",
790
+ run: function () {
791
+ var m = analyze("def get_map():\n return {}");
792
+ var sym = find(m.getAllSymbols(), "get_map");
793
+ assert.ok(sym, "Expected 'get_map' symbol");
794
+ assert.strictEqual(sym.return_type, "dict",
795
+ "Expected return_type 'dict', got: " + sym.return_type);
796
+ },
797
+ },
798
+
799
+ {
800
+ name: "infer_return_type_string_literal",
801
+ description: "return 'hello' infers return_type = 'str'",
802
+ run: function () {
803
+ var m = analyze("def get_name():\n return 'hello'");
804
+ var sym = find(m.getAllSymbols(), "get_name");
805
+ assert.ok(sym, "Expected 'get_name' symbol");
806
+ assert.strictEqual(sym.return_type, "str",
807
+ "Expected return_type 'str', got: " + sym.return_type);
808
+ },
809
+ },
810
+
811
+ {
812
+ name: "infer_return_type_number_literal",
813
+ description: "return 42 infers return_type = 'number'",
814
+ run: function () {
815
+ var m = analyze("def get_count():\n return 42");
816
+ var sym = find(m.getAllSymbols(), "get_count");
817
+ assert.ok(sym, "Expected 'get_count' symbol");
818
+ assert.strictEqual(sym.return_type, "number",
819
+ "Expected return_type 'number', got: " + sym.return_type);
820
+ },
821
+ },
822
+
823
+ {
824
+ name: "infer_return_type_bool_literal",
825
+ description: "return True infers return_type = 'bool'",
826
+ run: function () {
827
+ var m = analyze("def is_valid():\n return True");
828
+ var sym = find(m.getAllSymbols(), "is_valid");
829
+ assert.ok(sym, "Expected 'is_valid' symbol");
830
+ assert.strictEqual(sym.return_type, "bool",
831
+ "Expected return_type 'bool', got: " + sym.return_type);
832
+ },
833
+ },
834
+
835
+ {
836
+ name: "infer_return_type_constructor_call",
837
+ description: "return MyClass() infers return_type = 'MyClass'",
838
+ run: function () {
839
+ var m = analyze([
840
+ "class MyClass:",
841
+ " def __init__(self):",
842
+ " pass",
843
+ "def make():",
844
+ " return MyClass()",
845
+ ].join("\n"));
846
+ var sym = find(m.getAllSymbols(), "make");
847
+ assert.ok(sym, "Expected 'make' symbol");
848
+ assert.strictEqual(sym.return_type, "MyClass",
849
+ "Expected return_type 'MyClass', got: " + sym.return_type);
850
+ },
851
+ },
852
+
853
+ {
854
+ name: "infer_return_type_local_variable",
855
+ description: "return local_var infers type from local variable's inferred_class",
856
+ run: function () {
857
+ var m = analyze([
858
+ "def get_items():",
859
+ " result = []",
860
+ " return result",
861
+ ].join("\n"));
862
+ var sym = find(m.getAllSymbols(), "get_items");
863
+ assert.ok(sym, "Expected 'get_items' symbol");
864
+ assert.strictEqual(sym.return_type, "list",
865
+ "Expected return_type 'list' via local var, got: " + sym.return_type);
866
+ },
867
+ },
868
+
869
+ {
870
+ name: "infer_return_type_consistent_multiple_returns",
871
+ description: "Multiple returns of the same type still infer correctly",
872
+ run: function () {
873
+ var m = analyze([
874
+ "def get_name(flag):",
875
+ " if flag:",
876
+ " return 'yes'",
877
+ " return 'no'",
878
+ ].join("\n"));
879
+ var sym = find(m.getAllSymbols(), "get_name");
880
+ assert.ok(sym, "Expected 'get_name' symbol");
881
+ assert.strictEqual(sym.return_type, "str",
882
+ "Expected return_type 'str' for consistent returns, got: " + sym.return_type);
883
+ },
884
+ },
885
+
886
+ {
887
+ name: "infer_return_type_mixed_returns_no_inference",
888
+ description: "Mixed return types produce no inference (return_type stays null)",
889
+ run: function () {
890
+ var m = analyze([
891
+ "def ambiguous(flag):",
892
+ " if flag:",
893
+ " return []",
894
+ " return 'nope'",
895
+ ].join("\n"));
896
+ var sym = find(m.getAllSymbols(), "ambiguous");
897
+ assert.ok(sym, "Expected 'ambiguous' symbol");
898
+ assert.strictEqual(sym.return_type, null,
899
+ "Expected return_type null for mixed types, got: " + sym.return_type);
900
+ },
901
+ },
902
+
903
+ {
904
+ name: "infer_return_type_bare_return_ignored",
905
+ description: "Bare return (no value) does not block inference from typed returns",
906
+ run: function () {
907
+ var m = analyze([
908
+ "def maybe_get(flag):",
909
+ " if not flag:",
910
+ " return",
911
+ " return []",
912
+ ].join("\n"));
913
+ var sym = find(m.getAllSymbols(), "maybe_get");
914
+ assert.ok(sym, "Expected 'maybe_get' symbol");
915
+ assert.strictEqual(sym.return_type, "list",
916
+ "Expected return_type 'list' ignoring bare return, got: " + sym.return_type);
917
+ },
918
+ },
919
+
920
+ {
921
+ name: "infer_return_type_explicit_annotation_not_overwritten",
922
+ description: "An explicit -> annotation is not replaced by inference",
923
+ run: function () {
924
+ var m = analyze("def get_name() -> str:\n return 42");
925
+ var sym = find(m.getAllSymbols(), "get_name");
926
+ assert.ok(sym, "Expected 'get_name' symbol");
927
+ assert.strictEqual(sym.return_type, "str",
928
+ "Explicit annotation should win, got: " + sym.return_type);
929
+ },
930
+ },
931
+
932
+ {
933
+ name: "infer_return_type_nested_function_not_confused",
934
+ description: "Returns inside a nested function do not affect the outer function's type",
935
+ run: function () {
936
+ var m = analyze([
937
+ "def outer():",
938
+ " def inner():",
939
+ " return 'text'",
940
+ " return []",
941
+ ].join("\n"));
942
+ var outer = find(m.getAllSymbols(), "outer");
943
+ var inner = find(m.getAllSymbols(), "inner");
944
+ assert.ok(outer, "Expected 'outer' symbol");
945
+ assert.ok(inner, "Expected 'inner' symbol");
946
+ assert.strictEqual(outer.return_type, "list",
947
+ "outer return_type should be 'list', got: " + outer.return_type);
948
+ assert.strictEqual(inner.return_type, "str",
949
+ "inner return_type should be 'str', got: " + inner.return_type);
950
+ },
951
+ },
952
+
953
+ // ── Nested classes ────────────────────────────────────────────────
954
+
955
+ {
956
+ name: "nested_class_creates_inner_frame",
957
+ description: "A nested class definition creates its own 'class' frame inside the outer class frame",
958
+ run: function () {
959
+ var m = analyze([
960
+ "class Outer:",
961
+ " class Inner:",
962
+ " def method(self):",
963
+ " pass",
964
+ ].join("\n"));
965
+ var cls_frames = m.frames.filter(function (f) { return f.kind === "class"; });
966
+ assert.ok(cls_frames.length >= 2, "Expected at least 2 class frames (Outer + Inner), got " + cls_frames.length);
967
+ var names = cls_frames.map(function (f) { return f.name; });
968
+ assert.ok(names.indexOf("Outer") >= 0, "Expected 'Outer' class frame");
969
+ assert.ok(names.indexOf("Inner") >= 0, "Expected 'Inner' class frame");
970
+ },
971
+ },
972
+
973
+ {
974
+ name: "nested_class_symbol_in_outer_scope",
975
+ description: "The nested class name appears as a 'class' symbol in the outer class frame",
976
+ run: function () {
977
+ var m = analyze([
978
+ "class Outer:",
979
+ " class Inner:",
980
+ " pass",
981
+ ].join("\n"));
982
+ var outer_frame = m.frames.find(function (f) { return f.kind === "class" && f.name === "Outer"; });
983
+ assert.ok(outer_frame, "Expected 'Outer' class frame");
984
+ var inner_sym = outer_frame.getSymbol("Inner");
985
+ assert.ok(inner_sym, "Expected 'Inner' symbol in Outer's class frame");
986
+ assert.strictEqual(inner_sym.kind, "class");
987
+ },
988
+ },
989
+
990
+ {
991
+ name: "nested_class_methods_in_inner_frame",
992
+ description: "Methods of the nested class appear in the inner class frame, not the outer one",
993
+ run: function () {
994
+ var m = analyze([
995
+ "class Outer:",
996
+ " class Inner:",
997
+ " def greet(self):",
998
+ " pass",
999
+ " def do_outer(self):",
1000
+ " pass",
1001
+ ].join("\n"));
1002
+ var inner_frame = m.frames.find(function (f) { return f.kind === "class" && f.name === "Inner"; });
1003
+ assert.ok(inner_frame, "Expected 'Inner' class frame");
1004
+ assert.ok(inner_frame.getSymbol("greet"), "Expected 'greet' in Inner frame");
1005
+ var outer_frame = m.frames.find(function (f) { return f.kind === "class" && f.name === "Outer"; });
1006
+ assert.ok(outer_frame, "Expected 'Outer' class frame");
1007
+ assert.ok(!outer_frame.getSymbol("greet"), "'greet' should NOT be in Outer frame");
1008
+ assert.ok(outer_frame.getSymbol("do_outer"), "Expected 'do_outer' in Outer frame");
1009
+ },
1010
+ },
1011
+
1012
+ {
1013
+ name: "nested_class_appears_in_module_scope",
1014
+ description: "The outer class appears in module scope; the inner class does not pollute module scope",
1015
+ run: function () {
1016
+ var m = analyze([
1017
+ "class Outer:",
1018
+ " class Inner:",
1019
+ " pass",
1020
+ ].join("\n"));
1021
+ var module_frame = m.frames.find(function (f) { return f.kind === "module"; });
1022
+ assert.ok(module_frame, "Expected module frame");
1023
+ assert.ok(module_frame.getSymbol("Outer"), "Expected 'Outer' in module scope");
1024
+ assert.ok(!module_frame.getSymbol("Inner"), "'Inner' should NOT appear directly in module scope");
1025
+ },
1026
+ },
1027
+
773
1028
  ];
774
1029
 
775
1030
  return TESTS;
@@ -242,7 +242,7 @@ function make_tests(Diagnostics, RS) {
242
242
 
243
243
  {
244
244
  name: "import_error_caught",
245
- description: "An unresolvable import is caught and returned as a single Error marker",
245
+ description: "An unresolvable import produces a single Error marker (unused-import) when no module registry is configured",
246
246
  run: function () {
247
247
  var markers = d().check("from nonexistent_lib_xyz import something");
248
248
  assert.strictEqual(markers.length, 1);
@@ -250,6 +250,78 @@ function make_tests(Diagnostics, RS) {
250
250
  },
251
251
  },
252
252
 
253
+ // ── Bad-import squiggles ───────────────────────────────────────────
254
+
255
+ {
256
+ name: "bad_import_unknown_module",
257
+ description: "Importing from an unknown module produces a bad-import Error when a module registry is active",
258
+ run: function () {
259
+ var markers = d().check(
260
+ "from typo_mod import foo\nprint(foo())",
261
+ { virtualFiles: { mymod: "def foo(): return 1" } }
262
+ );
263
+ var bad = markers.filter(function (m) { return m.message.indexOf('Unknown module') !== -1; });
264
+ assert.ok(bad.length >= 1, "Expected at least one 'Unknown module' marker, got: " + JSON.stringify(markers));
265
+ assert.strictEqual(bad[0].severity, SEV_ERROR);
266
+ // Squiggle should point at the module name on line 1
267
+ assert.strictEqual(bad[0].startLineNumber, 1);
268
+ },
269
+ },
270
+
271
+ {
272
+ name: "bad_import_known_module_no_error",
273
+ description: "Importing from a registered module produces no bad-import error",
274
+ run: function () {
275
+ var markers = d().check(
276
+ "from mymod import foo\nprint(foo())",
277
+ { virtualFiles: { mymod: "def foo(): return 1" } }
278
+ );
279
+ var bad = markers.filter(function (m) { return m.message.indexOf('Unknown module') !== -1; });
280
+ assert.strictEqual(bad.length, 0, "Expected no 'Unknown module' marker for a known module");
281
+ },
282
+ },
283
+
284
+ {
285
+ name: "bad_import_no_registry_no_error",
286
+ description: "Unknown imports produce no bad-import error when no module registry is configured",
287
+ run: function () {
288
+ var markers = d().check("from anything import foo\nprint(foo())");
289
+ var bad = markers.filter(function (m) { return m.message.indexOf('Unknown module') !== -1; });
290
+ assert.strictEqual(bad.length, 0, "Expected no 'Unknown module' marker when no registry is configured");
291
+ },
292
+ },
293
+
294
+ {
295
+ name: "bad_import_squiggle_span",
296
+ description: "The bad-import squiggle covers the module name",
297
+ run: function () {
298
+ var markers = d().check(
299
+ "from typo_mod import foo",
300
+ { virtualFiles: { mymod: "def foo(): return 1" } }
301
+ );
302
+ var bad = markers.filter(function (m) { return m.message.indexOf('Unknown module') !== -1; });
303
+ assert.ok(bad.length >= 1, "Expected a bad-import marker");
304
+ var m = bad[0];
305
+ // 'typo_mod' appears after 'from ' (col 5, 1-indexed col 6)
306
+ assert.strictEqual(m.startColumn, 6, "startColumn should be 6 (start of 'typo_mod')");
307
+ // endColumn should cover all of 'typo_mod' (8 chars)
308
+ assert.ok(m.endColumn > m.startColumn, "endColumn should be past startColumn");
309
+ },
310
+ },
311
+
312
+ {
313
+ name: "bad_import_stdlib_registry",
314
+ description: "Importing from a registered stdlib module produces no bad-import error",
315
+ run: function () {
316
+ var markers = d().check(
317
+ "from mathlib import sqrt",
318
+ { stdlibFiles: { mathlib: "def sqrt(x): return x ** 0.5" } }
319
+ );
320
+ var bad = markers.filter(function (m) { return m.message.indexOf('Unknown module') !== -1; });
321
+ assert.strictEqual(bad.length, 0, "Expected no 'Unknown module' marker for a known stdlib module");
322
+ },
323
+ },
324
+
253
325
  // ── Semicolon warnings ────────────────────────────────────────────
254
326
 
255
327
  {
@@ -641,6 +713,91 @@ function make_tests(Diagnostics, RS) {
641
713
  },
642
714
  },
643
715
 
716
+ // ── Type annotations ──────────────────────────────────────────────
717
+
718
+ {
719
+ name: "annotated_assign_no_undef",
720
+ description: "Variable declared with type annotation (a: int = 5) is not flagged as undefined",
721
+ run: function () {
722
+ var markers = d().check([
723
+ "async def main():",
724
+ " a: int = 5",
725
+ " a += 4",
726
+ ].join("\n"));
727
+ var undef = markers.filter(function (m) { return m.message.indexOf("Undefined symbol") !== -1; });
728
+ assert.deepStrictEqual(undef, [],
729
+ "Expected no 'Undefined symbol' errors but got: " + JSON.stringify(undef));
730
+ },
731
+ },
732
+
733
+ {
734
+ name: "annotated_assign_used",
735
+ description: "Variable declared with type annotation is recognized as used when referenced",
736
+ run: function () {
737
+ var markers = d().check([
738
+ "def foo():",
739
+ " x: str = 'hello'",
740
+ " return x",
741
+ ].join("\n"));
742
+ var errors = markers.filter(function (m) { return m.severity === SEV_ERROR; });
743
+ assert.deepStrictEqual(errors, [],
744
+ "Expected no errors for annotated var used in same scope, got: " + JSON.stringify(errors));
745
+ },
746
+ },
747
+
748
+ {
749
+ name: "annotated_assign_compound_ops",
750
+ description: "All compound assignment operators work on annotated variables without undef errors",
751
+ run: function () {
752
+ var markers = d().check([
753
+ "def bar():",
754
+ " n: int = 10",
755
+ " n += 1",
756
+ " n -= 1",
757
+ " n *= 2",
758
+ " return n",
759
+ ].join("\n"));
760
+ var undef = markers.filter(function (m) { return m.message.indexOf("Undefined symbol") !== -1; });
761
+ assert.deepStrictEqual(undef, [],
762
+ "Expected no 'Undefined symbol' errors but got: " + JSON.stringify(undef));
763
+ },
764
+ },
765
+
766
+ {
767
+ name: "slice_builtin_no_undef_error",
768
+ description: "slice() usage produces no 'Undefined symbol' diagnostic",
769
+ run: function () {
770
+ var inst = new Diagnostics(RS);
771
+ var markers = inst.check([
772
+ "s = slice(1, 5)",
773
+ "x = [1, 2, 3, 4, 5]",
774
+ "ok = isinstance(s, slice)",
775
+ ].join("\n"));
776
+ var undef = markers.filter(function (m) {
777
+ return m.message.indexOf("Undefined symbol") !== -1 &&
778
+ m.message.indexOf("slice") !== -1;
779
+ });
780
+ assert.deepStrictEqual(undef, [],
781
+ "Expected no 'Undefined symbol: slice' but got: " + JSON.stringify(undef));
782
+ },
783
+ },
784
+
785
+ {
786
+ name: "list_concat_no_diagnostics",
787
+ description: "list + list and += produce no diagnostic errors",
788
+ run: function () {
789
+ var markers = d().check([
790
+ "a = [1, 2]",
791
+ "b = [3, 4]",
792
+ "c = a + b",
793
+ "a += [5, 6]",
794
+ "print(c)",
795
+ "print(a)",
796
+ ].join("\n"));
797
+ assert_count(markers, SEV_ERROR, 0, "list concat");
798
+ },
799
+ },
800
+
644
801
  ];
645
802
 
646
803
  return TESTS;
@@ -24,6 +24,8 @@ var FILES = [
24
24
  "language-service-hover.js",
25
25
  "language-service-dts.js",
26
26
  "language-service-builtins.js",
27
+ "language-service-index.js",
28
+ "language-service-bundle.js",
27
29
  "web-repl.js",
28
30
  ];
29
31
 
@@ -445,6 +445,140 @@ var TESTS = [
445
445
  },
446
446
  },
447
447
 
448
+ {
449
+ name: "nested_class_web_repl",
450
+ description: "Nested class definitions compile and run correctly via the web-repl bundle",
451
+ run: function () {
452
+ var repl = RS.web_repl();
453
+ var js = bundle_compile(repl, [
454
+ "class Outer:",
455
+ " class Inner:",
456
+ " def __init__(self, val):",
457
+ " self.val = val",
458
+ " def __init__(self, v):",
459
+ " self.inner = Outer.Inner(v)",
460
+ "o = Outer(99)",
461
+ "assrt.equal(o.inner.val, 99)",
462
+ "assrt.ok(isinstance(o.inner, Outer.Inner))",
463
+ "assrt.ok(o.Inner is Outer.Inner)",
464
+ ].join("\n"));
465
+ run_js(js);
466
+ },
467
+ },
468
+
469
+ // ── slice() builtin ───────────────────────────────────────────────────
470
+
471
+ {
472
+ name: "bundle_slice_constructor",
473
+ description: "slice() constructor stores start/stop/step attributes correctly",
474
+ run: function () {
475
+ var repl = RS.web_repl();
476
+ var js = bundle_compile(repl, [
477
+ "s1 = slice(5)",
478
+ "assrt.equal(s1.start, None)",
479
+ "assrt.equal(s1.stop, 5)",
480
+ "assrt.equal(s1.step, None)",
481
+ "s2 = slice(2, 8)",
482
+ "assrt.equal(s2.start, 2)",
483
+ "assrt.equal(s2.stop, 8)",
484
+ "assrt.equal(s2.step, None)",
485
+ "s3 = slice(1, 9, 2)",
486
+ "assrt.equal(s3.start, 1)",
487
+ "assrt.equal(s3.stop, 9)",
488
+ "assrt.equal(s3.step, 2)",
489
+ ].join("\n"));
490
+ run_js(js);
491
+ },
492
+ },
493
+
494
+ {
495
+ name: "bundle_slice_subscript",
496
+ description: "slice object used as list subscript returns the correct sub-list",
497
+ run: function () {
498
+ var repl = RS.web_repl();
499
+ var js = bundle_compile(repl, [
500
+ "from __python__ import overload_getitem",
501
+ "lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]",
502
+ "s = slice(2, 5)",
503
+ "assrt.deepEqual(lst[s], [2, 3, 4])",
504
+ "assrt.deepEqual(lst[slice(0, 6, 2)], [0, 2, 4])",
505
+ "assrt.deepEqual(lst[slice(5, 1, -1)], [5, 4, 3, 2])",
506
+ ].join("\n"));
507
+ run_js(js);
508
+ },
509
+ },
510
+
511
+ {
512
+ name: "bundle_slice_indices",
513
+ description: "slice.indices() returns normalised (start, stop, step) tuple",
514
+ run: function () {
515
+ var repl = RS.web_repl();
516
+ var js = bundle_compile(repl, [
517
+ "s = slice(2, 8)",
518
+ "idx = s.indices(10)",
519
+ "assrt.equal(idx[0], 2)",
520
+ "assrt.equal(idx[1], 8)",
521
+ "assrt.equal(idx[2], 1)",
522
+ "# negative indices normalised",
523
+ "s2 = slice(-3, -1)",
524
+ "idx2 = s2.indices(10)",
525
+ "assrt.equal(idx2[0], 7)",
526
+ "assrt.equal(idx2[1], 9)",
527
+ ].join("\n"));
528
+ run_js(js);
529
+ },
530
+ },
531
+
532
+ {
533
+ name: "bundle_slice_repr",
534
+ description: "str(slice(...)) produces the Python-style repr",
535
+ run: function () {
536
+ var repl = RS.web_repl();
537
+ var js = bundle_compile(repl, [
538
+ "assrt.equal(str(slice(1, 5, None)), 'slice(1, 5, None)')",
539
+ "assrt.equal(str(slice(None, 5, 2)), 'slice(None, 5, 2)')",
540
+ ].join("\n"));
541
+ run_js(js);
542
+ },
543
+ },
544
+
545
+ {
546
+ name: "bundle_slice_isinstance",
547
+ description: "isinstance(slice(...), slice) returns True in bundled baselib",
548
+ run: function () {
549
+ var repl = RS.web_repl();
550
+ var js = bundle_compile(repl, [
551
+ "s = slice(1, 5)",
552
+ "assrt.ok(isinstance(s, slice))",
553
+ ].join("\n"));
554
+ run_js(js);
555
+ },
556
+ },
557
+
558
+ {
559
+ name: "bundle_list_concatenation",
560
+ description: "list + list returns a concatenated list in the bundled baselib",
561
+ run: function () {
562
+ var repl = RS.web_repl();
563
+ var js = bundle_compile(repl, [
564
+ "a = [1, 2]",
565
+ "b = [3, 4]",
566
+ "c = a + b",
567
+ "assrt.deepEqual(c, [1, 2, 3, 4])",
568
+ "assrt.deepEqual(a, [1, 2])",
569
+ "assrt.deepEqual(b, [3, 4])",
570
+ "# iadd extends in-place",
571
+ "a += [5]",
572
+ "assrt.deepEqual(a, [1, 2, 5])",
573
+ "# numbers still work",
574
+ "assrt.equal(1 + 2, 3)",
575
+ "# strings still work",
576
+ "assrt.equal('foo' + 'bar', 'foobar')",
577
+ ].join("\n"));
578
+ run_js(js);
579
+ },
580
+ },
581
+
448
582
  ];
449
583
 
450
584
  // ---------------------------------------------------------------------------
@@ -14,7 +14,7 @@ var path = require("path");
14
14
 
15
15
  var SRC_DIR = path.join(__dirname, "..", "src", "monaco-language-service");
16
16
  var COMPILER_JS = path.join(__dirname, "..", "web-repl", "rapydscript.js");
17
- var DEFAULT_OUT = path.join(__dirname, "..", "web-repl", "language-service.js");
17
+ var DEFAULT_OUT = path.join(__dirname, "..", "language-service", "index.js");
18
18
 
19
19
  // Parse --out flag
20
20
  var out_path = DEFAULT_OUT;
@@ -124,7 +124,7 @@ var chunks = [
124
124
  "// language-service.js — RapydScript Monaco Language Service",
125
125
  "// Auto-generated by tools/build-language-service.js — do not edit directly.",
126
126
  "// Source: src/monaco-language-service/ + web-repl/rapydscript.js (embedded)",
127
- "// Usage: import { registerRapydScript } from './language-service.js';",
127
+ "// Usage: import { registerRapydScript } from 'rapydscript-ns/language-service';",
128
128
  "// No external compiler bundle needed — the compiler is bundled inside.",
129
129
  "",
130
130
  compiler_chunk,
package/tools/compiler.js CHANGED
@@ -13,7 +13,6 @@ var path = require("path");
13
13
  var fs = require("fs");
14
14
  var crypto = require('crypto');
15
15
  var vm = require("vm");
16
- var regenerator = require('regenerator');
17
16
  var UglifyJS = require("uglify-js");
18
17
 
19
18
  function sha1sum(data) {
@@ -38,28 +37,6 @@ function uglify(code) {
38
37
  }
39
38
 
40
39
 
41
- function regenerate(code, beautify) {
42
- var ans, start, end;
43
- if (code) {
44
- ans = regenerator.compile(code).code;
45
- if (!beautify) {
46
- ans = uglify(ans);
47
- }
48
- } else {
49
- // Return the runtime
50
- ans = regenerator.compile('', {includeRuntime:true}).code;
51
- start = ans.indexOf('=') + 1;
52
- end = ans.lastIndexOf('typeof');
53
- end = ans.lastIndexOf('}(', end);
54
- ans = ans.slice(start + 1, end);
55
- if (!beautify) {
56
- var extra = '})()';
57
- ans = uglify(ans + extra).slice(0, extra.length);
58
- }
59
- }
60
- return ans;
61
- }
62
-
63
40
  var _current_virtual_files = null;
64
41
 
65
42
  function virtual_readfile(name, encoding) {
@@ -90,7 +67,6 @@ function create_compiler() {
90
67
  writefile : virtual_writefile,
91
68
  sha1sum : sha1sum,
92
69
  require : require,
93
- regenerate : regenerate,
94
70
  exports : compiler_exports,
95
71
  });
96
72