rapydscript-ng 0.7.23 → 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 (114) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +72 -26
  3. package/bin/package.json +1 -0
  4. package/bin/rapydscript +65 -62
  5. package/editor-plugins/nvim/rapydscript/README.md +184 -0
  6. package/editor-plugins/nvim/rapydscript/bin/rapydscript.so +0 -0
  7. package/editor-plugins/nvim/rapydscript/ftdetect/rapydscript.lua +10 -0
  8. package/editor-plugins/nvim/rapydscript/lua/rapydscript/health.lua +88 -0
  9. package/editor-plugins/nvim/rapydscript/lua/rapydscript/init.lua +279 -0
  10. package/local-agent.md +28 -0
  11. package/package.json +4 -5
  12. package/release/baselib-plain-pretty.js +448 -326
  13. package/release/baselib-plain-ugly.js +3 -3
  14. package/release/compiler.js +2528 -1672
  15. package/release/signatures.json +17 -17
  16. package/src/ast.pyj +73 -25
  17. package/src/baselib-builtins.pyj +2 -2
  18. package/src/baselib-containers.pyj +153 -151
  19. package/src/baselib-internal.pyj +3 -3
  20. package/src/baselib-str.pyj +5 -5
  21. package/src/lib/aes.pyj +1 -1
  22. package/src/lib/encodings.pyj +1 -1
  23. package/src/lib/pythonize.pyj +1 -1
  24. package/src/lib/re.pyj +2 -2
  25. package/src/lib/traceback.pyj +165 -28
  26. package/src/lib/uuid.pyj +1 -1
  27. package/src/output/codegen.pyj +10 -3
  28. package/src/output/functions.pyj +31 -40
  29. package/src/output/literals.pyj +11 -14
  30. package/src/output/loops.pyj +25 -87
  31. package/src/output/modules.pyj +5 -47
  32. package/src/output/statements.pyj +1 -1
  33. package/src/output/stream.pyj +58 -31
  34. package/src/parse.pyj +777 -427
  35. package/src/tokenizer.pyj +16 -4
  36. package/src/utils.pyj +1 -1
  37. package/test/_treeshake_mod.pyj +30 -0
  38. package/test/_treeshake_side_effect.pyj +9 -0
  39. package/test/ast_serialization.pyj +392 -0
  40. package/test/async.pyj +95 -0
  41. package/test/baselib.pyj +1 -2
  42. package/test/embedded_compiler.pyj +57 -0
  43. package/test/fmt.pyj +201 -0
  44. package/test/generic.pyj +7 -3
  45. package/test/imports.pyj +8 -6
  46. package/test/internationalization.pyj +38 -37
  47. package/test/lint.pyj +120 -115
  48. package/test/lsp.pyj +222 -0
  49. package/test/repl.pyj +70 -65
  50. package/test/sourcemaps.pyj +315 -0
  51. package/test/starargs.pyj +46 -39
  52. package/test/traceback.pyj +263 -0
  53. package/test/treeshaking.pyj +181 -0
  54. package/test/web_repl_export.pyj +88 -0
  55. package/tools/ast_serialize.mjs +557 -0
  56. package/tools/cli.mjs +510 -0
  57. package/tools/compile.mjs +201 -0
  58. package/tools/compiler.mjs +127 -0
  59. package/tools/{completer.js → completer.mjs} +6 -6
  60. package/tools/{embedded_compiler.js → embedded_compiler.mjs} +17 -13
  61. package/tools/export.js +109 -56
  62. package/tools/fmt.mjs +735 -0
  63. package/tools/{gettext.js → gettext.mjs} +46 -53
  64. package/tools/{ini.js → ini.mjs} +9 -10
  65. package/tools/{lint.js → lint.mjs} +107 -56
  66. package/tools/lsp.mjs +914 -0
  67. package/tools/lsp_protocol.mjs +259 -0
  68. package/tools/lsp_symbols.mjs +418 -0
  69. package/tools/{msgfmt.js → msgfmt.mjs} +18 -18
  70. package/tools/{repl.js → repl.mjs} +52 -41
  71. package/tools/{self.js → self.mjs} +56 -46
  72. package/tools/sourcemap.mjs +123 -0
  73. package/tools/test.mjs +152 -0
  74. package/tools/treeshake.mjs +400 -0
  75. package/tools/{utils.js → utils.mjs} +26 -23
  76. package/tools/{web_repl.js → web_repl.mjs} +15 -13
  77. package/tools/web_repl_export.mjs +93 -0
  78. package/tree-sitter/README.md +101 -0
  79. package/tree-sitter/grammar.js +992 -0
  80. package/tree-sitter/package.json +43 -0
  81. package/tree-sitter/queries/rapydscript/highlights.scm +232 -0
  82. package/tree-sitter/queries/rapydscript/indents.scm +64 -0
  83. package/tree-sitter/queries/rapydscript/injections.scm +14 -0
  84. package/tree-sitter/queries/rapydscript/locals.scm +108 -0
  85. package/tree-sitter/src/grammar.json +4976 -0
  86. package/tree-sitter/src/node-types.json +2901 -0
  87. package/tree-sitter/src/parser.c +196465 -0
  88. package/tree-sitter/src/scanner.c +294 -0
  89. package/tree-sitter/src/tree_sitter/alloc.h +54 -0
  90. package/tree-sitter/src/tree_sitter/array.h +330 -0
  91. package/tree-sitter/src/tree_sitter/parser.h +286 -0
  92. package/tree-sitter/test/corpus/chaining.txt +99 -0
  93. package/tree-sitter/test/corpus/classes.txt +147 -0
  94. package/tree-sitter/test/corpus/comprehensions.txt +155 -0
  95. package/tree-sitter/test/corpus/containers.txt +242 -0
  96. package/tree-sitter/test/corpus/control_flow.txt +361 -0
  97. package/tree-sitter/test/corpus/decorators.txt +64 -0
  98. package/tree-sitter/test/corpus/existential.txt +102 -0
  99. package/tree-sitter/test/corpus/functions.txt +293 -0
  100. package/tree-sitter/test/corpus/imports.txt +117 -0
  101. package/tree-sitter/test/corpus/literals.txt +135 -0
  102. package/tree-sitter/test/corpus/operators.txt +296 -0
  103. package/tree-sitter/test/corpus/statements.txt +189 -0
  104. package/tree-sitter/test/corpus/strings.txt +90 -0
  105. package/tree-sitter/test/corpus/subscripts.txt +227 -0
  106. package/tree-sitter/tree-sitter.json +36 -0
  107. package/web-repl/env.js +35 -23
  108. package/web-repl/main.js +8 -8
  109. package/bin/export +0 -75
  110. package/bin/web-repl-export +0 -102
  111. package/tools/cli.js +0 -523
  112. package/tools/compile.js +0 -184
  113. package/tools/compiler.js +0 -84
  114. package/tools/test.js +0 -110
@@ -1,18 +1,21 @@
1
1
  /* vim:fileencoding=utf-8
2
- *
2
+ *
3
3
  * Copyright (C) 2016 Kovid Goyal <kovid at kovidgoyal.net>
4
4
  *
5
5
  * Distributed under terms of the BSD license
6
6
  */
7
- "use strict"; /*jshint node:true */
8
- var vm = require('vm');
9
- var embedded_compiler = require('tools/embedded_compiler.js');
7
+ "use strict";
8
+
9
+ import vm from 'vm';
10
+ import embedded_compiler from './embedded_compiler.mjs';
11
+ import tree_shake from './treeshake.mjs';
12
+ import { generate_source_map } from './sourcemap.mjs';
10
13
 
11
- module.exports = function(compiler, baselib) {
14
+ export default async function(compiler, baselib) {
12
15
  var ctx = vm.createContext();
13
16
  var LINE_CONTINUATION_CHARS = ':\\';
14
17
  var find_completions = null;
15
- var streaming_compiler = embedded_compiler(compiler, baselib, function(js) { return vm.runInContext(js, ctx); }, '__repl__');
18
+ var streaming_compiler = await embedded_compiler(compiler, baselib, function(js) { return vm.runInContext(js, ctx); }, '__repl__', tree_shake, generate_source_map);
16
19
 
17
20
  return {
18
21
  'in_block_mode': false,
@@ -20,13 +23,13 @@ module.exports = function(compiler, baselib) {
20
23
  'replace_print': function replace_print(write_line_func) {
21
24
  ctx.print = function() {
22
25
  var parts = [];
23
- for (var i = 0; i < arguments.length; i++)
26
+ for (var i = 0; i < arguments.length; i++)
24
27
  parts.push(ctx.ρσ_str(arguments[i]));
25
28
  write_line_func(parts.join(' '));
26
29
  };
27
30
  },
28
31
 
29
- 'is_input_complete': function is_input_complete(source) {
32
+ 'is_input_complete': async function is_input_complete(source) {
30
33
  if (!source || !source.trim()) return false;
31
34
  var lines = source.split('\n');
32
35
  var last_line = lines[lines.length - 1].trimRight();
@@ -45,7 +48,7 @@ module.exports = function(compiler, baselib) {
45
48
  return false;
46
49
  }
47
50
  try {
48
- compiler.parse(source, {'filename': '<repl>', 'basedir': '__stdlib__'});
51
+ await compiler.parse(source, {'filename': '<repl>', 'basedir': '__stdlib__'});
49
52
  } catch(e) {
50
53
  if (e.is_eof && e.line === lines.length && e.col > 0) {
51
54
  return false;
@@ -57,11 +60,11 @@ module.exports = function(compiler, baselib) {
57
60
  return true;
58
61
  },
59
62
 
60
- 'compile': function web_repl_compile(code, opts) {
63
+ 'compile': async function web_repl_compile(code, opts) {
61
64
  opts = opts || {};
62
65
  opts.keep_docstrings = true;
63
66
  opts.filename = '<input>';
64
- return streaming_compiler.compile(code, opts);
67
+ return await streaming_compiler.compile(code, opts);
65
68
  },
66
69
 
67
70
  'runjs': function runjs(code) {
@@ -83,5 +86,4 @@ module.exports = function(compiler, baselib) {
83
86
  },
84
87
 
85
88
  };
86
- };
87
-
89
+ }
@@ -0,0 +1,93 @@
1
+ /*
2
+ * web_repl_export.mjs
3
+ * Copyright (C) 2015 Kovid Goyal <kovid at kovidgoyal.net>
4
+ *
5
+ * Distributed under terms of the BSD license.
6
+ */
7
+
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import * as utils from './utils.mjs';
11
+
12
+ export default async function run_web_repl_export(base_path, lib_path, argv) {
13
+ var output_dir = argv.files[0];
14
+ if (!output_dir) {
15
+ console.error('Usage: rapydscript web-repl-export /path/to/export/directory');
16
+ process.exit(1);
17
+ }
18
+
19
+ var meta = JSON.parse(await fs.promises.readFile(path.join(base_path, 'package.json'), 'utf-8'));
20
+ var commit_sha = (await fs.promises.readFile(path.join(base_path, '.git', 'refs', 'heads', 'master'), 'utf-8')).trim();
21
+
22
+ var manifest = {}, total = 0;
23
+ for (const x of ['compiler.js', 'baselib-plain-pretty.js']) {
24
+ manifest[x] = await fs.promises.readFile(path.join(lib_path, x), 'utf-8');
25
+ total += manifest[x].length;
26
+ }
27
+
28
+ for (const x of ['web_repl.js', 'embedded_compiler.js', 'treeshake.js', 'sourcemap.js', 'utils.js', 'completer.js', 'msgfmt.js', 'gettext.js', 'ast_serialize.mjs']) {
29
+ var mjs = x.replace(/\.js$/, '.mjs');
30
+ var mjs_path = path.join(base_path, 'tools', mjs);
31
+ var js_path = path.join(base_path, 'tools', x);
32
+ var use_mjs = await utils.path_exists(mjs_path);
33
+ var key = 'tools/' + (use_mjs ? mjs : x);
34
+ manifest[key] = await fs.promises.readFile(use_mjs ? mjs_path : js_path, 'utf-8');
35
+ total += manifest[key].length;
36
+ }
37
+
38
+ var stdlib = path.join(base_path, 'src', 'lib');
39
+
40
+ async function process_stdlib_dir(relpath) {
41
+ var fullpath = relpath ? path.join(stdlib, relpath) : stdlib;
42
+ var entries = await fs.promises.readdir(fullpath);
43
+ for (const x of entries) {
44
+ var q = path.join(fullpath, x);
45
+ var s = await fs.promises.stat(q);
46
+ if (s.isDirectory()) { await process_stdlib_dir(relpath + '/' + x); continue; }
47
+ if (!x.endsWith('.pyj')) continue;
48
+ var iname = path.normalize('__stdlib__' + '/' + relpath + '/' + x);
49
+ var raw = await fs.promises.readFile(q, 'utf-8');
50
+ manifest[iname] = raw;
51
+ total += s.size;
52
+ }
53
+ }
54
+ await process_stdlib_dir('');
55
+
56
+ var rs = '// vim:fileencoding=utf-8\n';
57
+ rs += '(function(external_namespace) {\n';
58
+ rs += '"use strict;"\n';
59
+ rs += 'var rs_version = ' + JSON.stringify(meta.version) + ';\n';
60
+ rs += 'var rs_commit_sha = ' + JSON.stringify(commit_sha) + ';\n';
61
+ rs += '\n// Embedded modules {{{\n';
62
+ rs += 'var data = ' + JSON.stringify(manifest) + ';\n\n';
63
+ rs += '// End embedded modules }}}\n\n';
64
+ rs += await fs.promises.readFile(path.join(base_path, 'web-repl', 'env.js'));
65
+ rs += '\n// Embedded sha1 implementation {{{\n';
66
+ rs += '(function() {\n';
67
+ rs += await fs.promises.readFile(path.join(base_path, 'web-repl', 'sha1.js'));
68
+ rs += '}).call(jsSHA);\n';
69
+ rs += '// End embedded sha1 implementation }}}\n\n';
70
+ rs += 'var exports = namespace;\n';
71
+ rs += await fs.promises.readFile(path.join(base_path, 'tools', 'export.js'), 'utf-8');
72
+ rs += 'external_namespace.RapydScript = namespace;\n';
73
+ rs += '})(this);\n';
74
+
75
+ var base_dir = path.normalize(path.resolve(output_dir));
76
+
77
+ try {
78
+ await fs.promises.mkdir(base_dir);
79
+ } catch(e) {
80
+ if (e.code !== 'EEXIST') throw e;
81
+ }
82
+
83
+ await fs.promises.writeFile(path.join(base_dir, 'rapydscript.js'), rs, 'utf-8');
84
+ var web_repl_dir = path.join(base_path, 'web-repl');
85
+ var web_repl_files = await fs.promises.readdir(web_repl_dir);
86
+ for (const x of web_repl_files) {
87
+ if (['sha1.js', 'env.js'].indexOf(x) !== -1) continue;
88
+ var file_data = await fs.promises.readFile(path.join(web_repl_dir, x), 'utf-8');
89
+ await fs.promises.writeFile(path.join(base_dir, x), file_data, 'utf-8');
90
+ }
91
+ console.log('RapydScript compiler (uncompressed) size: ' + (total/(1024)).toFixed(1) + ' KB');
92
+ console.log('web-repl exported to: ' + base_dir);
93
+ }
@@ -0,0 +1,101 @@
1
+ # tree-sitter-rapydscript
2
+
3
+ A [tree-sitter](https://tree-sitter.github.io/tree-sitter/) grammar for
4
+ [RapydScript](../README.md) (`.pyj` files).
5
+
6
+ RapydScript is a Python-like language that compiles to JavaScript. This grammar
7
+ covers the language as implemented by `rapydscript-ng`, including the features
8
+ that distinguish it from Python:
9
+
10
+ - **multi-line anonymous functions** declared with `def(...)` / `async def(...)`
11
+ (RapydScript's answer to Python's single-expression `lambda`), both inline
12
+ (`f = def(a, b): return a + b`) and with an indented block body;
13
+ - the **existential operator** `?` in all its forms — `a?` (existence check),
14
+ `a?.b` / `a?[i]` / `a?()` (safe access), and `a ? b` (default operator);
15
+ - **verbatim JavaScript** literals via the `v` string modifier (`v'...'`) and
16
+ the native `for v'i=0; i<n; i++':` loop;
17
+ - JavaScript **regular-expression literals**, including the verbose
18
+ `/// ... ///` form;
19
+ - `do: ... .while cond` loops;
20
+ - **scoped compiler flags** (`from __python__ import dict_literals, ...`).
21
+
22
+ It deliberately does **not** accept constructs that RapydScript itself rejects,
23
+ such as the walrus operator `:=`, `match`/`case`, or `*`-unpacking in assignment
24
+ targets.
25
+
26
+ It **does** handle the trickier corners of the language, including assignment as
27
+ an expression (`if m = re.exec(x):`, `a[i -= 1]`), keyword-vs-assignment
28
+ disambiguation in calls, named function *expressions* (`x = def named(a): ...`),
29
+ typed `*args`/`**kwargs`, bare generator arguments (`sum(x for x in xs)`),
30
+ multi-line anonymous-function arguments with the comma-on-the-next-line idiom,
31
+ and comma-first dict literals whose values are multi-line functions.
32
+
33
+ ### Known limitations
34
+
35
+ A few rarely-used constructs — found only in the RapydScript compiler's own
36
+ source and standard library, not in ordinary programs — are not parsed. Every
37
+ file under `test/` (representative user code) and every example in the language
38
+ [README](../README.md) parses cleanly; the exceptions are:
39
+
40
+ - the colon-less one-line `if`: `if (cond) do_something()`;
41
+ - chained assignment whose value is a multi-line-block anonymous function:
42
+ `a = b = def(): <block>`;
43
+ - a ternary used as the return value of an *inline* anonymous function that is
44
+ itself a call argument, with a trailing `;`.
45
+
46
+ In these cases tree-sitter's error recovery still highlights the surrounding
47
+ code.
48
+
49
+ ## Layout
50
+
51
+ ```
52
+ tree-sitter/
53
+ ├── grammar.js # the grammar
54
+ ├── tree-sitter.json # grammar metadata (CLI)
55
+ ├── package.json # npm package metadata
56
+ ├── src/
57
+ │ ├── parser.c # generated parser (checked in)
58
+ │ ├── scanner.c # external scanner: indentation + regex literals
59
+ │ ├── grammar.json # generated
60
+ │ └── node-types.json # generated
61
+ ├── queries/
62
+ │ ├── highlights.scm # syntax highlighting
63
+ │ └── injections.scm # embedded-language injections
64
+ └── test/corpus/ # tree-sitter test suite
65
+ ```
66
+
67
+ ## Building & testing
68
+
69
+ From this directory:
70
+
71
+ ```sh
72
+ tree-sitter generate # regenerate src/parser.c from grammar.js
73
+ tree-sitter test # run the corpus tests in test/corpus/
74
+ tree-sitter parse FILE # parse a .pyj file and print its syntax tree
75
+ tree-sitter build # compile the parser (+ scanner) into a shared object
76
+ ```
77
+
78
+ ## Using it in Neovim
79
+
80
+ With [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter),
81
+ register the parser and map the `.pyj` extension to it:
82
+
83
+ ```lua
84
+ local rapyd_repo_path = vim.fn.expand("/path/to/rapydscript/tree-sitter")
85
+ vim.api.nvim_create_autocmd('User', {
86
+ pattern = 'TSUpdate',
87
+ callback = function()
88
+ require("nvim-treesitter.parsers").rapydscript = {
89
+ install_info = {
90
+ path = rapyd_repo_path,
91
+ files = { "src/parser.c", "src/scanner.c" },
92
+ },
93
+ filetype = "rapydscript",
94
+ }
95
+ end
96
+ })
97
+ vim.opt.rtp:append(rapyd_repo_path)
98
+ vim.filetype.add({ extension = { pyj = "rapydscript" } })
99
+ ```
100
+
101
+ Then `:TSInstall rapydscript`.