prism 1.4.0 → 1.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +73 -1
- data/Makefile +7 -5
- data/README.md +3 -1
- data/config.yml +294 -41
- data/docs/build_system.md +2 -2
- data/docs/cruby_compilation.md +1 -1
- data/docs/design.md +2 -2
- data/docs/parser_translation.md +8 -23
- data/docs/releasing.md +6 -25
- data/docs/ripper_translation.md +1 -1
- data/ext/prism/api_node.c +9 -3
- data/ext/prism/extconf.rb +1 -1
- data/ext/prism/extension.c +24 -3
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +360 -70
- data/include/prism/diagnostic.h +7 -0
- data/include/prism/options.h +49 -3
- data/include/prism/parser.h +3 -0
- data/include/prism/regexp.h +2 -2
- data/include/prism/util/pm_buffer.h +8 -0
- data/include/prism/util/pm_integer.h +4 -0
- data/include/prism/util/pm_list.h +6 -0
- data/include/prism/util/pm_string.h +12 -2
- data/include/prism/version.h +2 -2
- data/include/prism.h +40 -15
- data/lib/prism/compiler.rb +456 -151
- data/lib/prism/desugar_compiler.rb +1 -0
- data/lib/prism/dispatcher.rb +16 -0
- data/lib/prism/dot_visitor.rb +10 -1
- data/lib/prism/dsl.rb +5 -2
- data/lib/prism/ffi.rb +28 -10
- data/lib/prism/inspect_visitor.rb +4 -0
- data/lib/prism/lex_compat.rb +1 -0
- data/lib/prism/mutation_compiler.rb +3 -0
- data/lib/prism/node.rb +559 -349
- data/lib/prism/node_ext.rb +4 -1
- data/lib/prism/pack.rb +2 -0
- data/lib/prism/parse_result/comments.rb +1 -0
- data/lib/prism/parse_result/errors.rb +1 -0
- data/lib/prism/parse_result/newlines.rb +1 -0
- data/lib/prism/parse_result.rb +3 -15
- data/lib/prism/pattern.rb +1 -0
- data/lib/prism/polyfill/scan_byte.rb +14 -0
- data/lib/prism/polyfill/warn.rb +36 -0
- data/lib/prism/reflection.rb +4 -1
- data/lib/prism/relocation.rb +1 -0
- data/lib/prism/serialize.rb +30 -22
- data/lib/prism/string_query.rb +1 -0
- data/lib/prism/translation/parser/builder.rb +1 -0
- data/lib/prism/translation/parser/compiler.rb +63 -41
- data/lib/prism/translation/parser/lexer.rb +29 -21
- data/lib/prism/translation/parser.rb +25 -4
- data/lib/prism/translation/parser33.rb +1 -0
- data/lib/prism/translation/parser34.rb +1 -0
- data/lib/prism/translation/parser35.rb +2 -6
- data/lib/prism/translation/parser40.rb +13 -0
- data/lib/prism/translation/parser41.rb +13 -0
- data/lib/prism/translation/parser_current.rb +26 -0
- data/lib/prism/translation/ripper/sexp.rb +1 -0
- data/lib/prism/translation/ripper.rb +19 -3
- data/lib/prism/translation/ruby_parser.rb +340 -22
- data/lib/prism/translation.rb +4 -0
- data/lib/prism/visitor.rb +457 -152
- data/lib/prism.rb +22 -0
- data/prism.gemspec +9 -1
- data/rbi/prism/dsl.rbi +6 -6
- data/rbi/prism/node.rbi +42 -17
- data/rbi/prism/translation/parser35.rbi +0 -2
- data/rbi/prism/translation/parser40.rbi +6 -0
- data/rbi/prism/translation/parser41.rbi +6 -0
- data/sig/prism/dispatcher.rbs +3 -0
- data/sig/prism/dsl.rbs +5 -5
- data/sig/prism/node.rbs +462 -38
- data/sig/prism/node_ext.rbs +84 -17
- data/sig/prism/parse_result/comments.rbs +38 -0
- data/sig/prism/parse_result.rbs +4 -0
- data/sig/prism/reflection.rbs +1 -1
- data/sig/prism.rbs +4 -0
- data/src/diagnostic.c +13 -1
- data/src/encoding.c +172 -67
- data/src/node.c +11 -0
- data/src/options.c +17 -7
- data/src/prettyprint.c +18 -0
- data/src/prism.c +1495 -2021
- data/src/serialize.c +9 -1
- data/src/token_type.c +38 -36
- data/src/util/pm_constant_pool.c +1 -1
- data/src/util/pm_string.c +6 -8
- metadata +11 -3
data/docs/parser_translation.md
CHANGED
|
@@ -6,34 +6,19 @@ Prism ships with the ability to translate its syntax tree into the syntax tree u
|
|
|
6
6
|
|
|
7
7
|
The `parser` gem provides multiple parsers to support different versions of the Ruby grammar. This includes all of the Ruby versions going back to 1.8, as well as third-party parsers like MacRuby and RubyMotion. The `prism` gem provides another parser that uses the `prism` parser to build the syntax tree.
|
|
8
8
|
|
|
9
|
-
You can use the `prism` parser like you would any other. After requiring
|
|
9
|
+
You can use the `prism` parser like you would any other. After requiring `prism`, you should be able to call any of the regular `Parser::Base` APIs that you would normally use.
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
12
|
require "prism"
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
### RuboCop
|
|
18
|
-
|
|
19
|
-
Prism as a parser engine is directly supported since RuboCop 1.62. The class used for parsing is `Prism::Translation::Parser`.
|
|
20
|
-
|
|
21
|
-
First, specify `prism` in your Gemfile:
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
gem "prism"
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
To use Prism with RuboCop, specify `ParserEngine` and `TargetRubyVersion` in your RuboCop configuration file:
|
|
14
|
+
# Same as `Parser::Ruby34`
|
|
15
|
+
Prism::Translation::Parser34.parse_file("path/to/file.rb")
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ParserEngine: parser_prism
|
|
32
|
-
TargetRubyVersion: 3.3
|
|
17
|
+
# Same as `Parser::CurrentRuby`
|
|
18
|
+
Prism::Translation::ParserCurrent.parse("puts 'Hello World!'")
|
|
33
19
|
```
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
The parser class is determined by the combination of values for `ParserEngine` and `TargetRubyVersion`. For example, if `TargetRubyVersion: 3.3`, parsing is performed by `Prism::Translation::Parser33`, and for `TargetRubyVersion 3.4`, parsing is performed by `Prism::Translation::Parser34`.
|
|
21
|
+
All the parsers are autoloaded, so you don't have to worry about requiring them yourself.
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
https://
|
|
23
|
+
If you also need to parse Ruby versions below 3.3 (for which the `prism` translation layer does not have explicit support), check out
|
|
24
|
+
[this guide](https://github.com/whitequark/parser/blob/master/doc/PRISM_TRANSLATION.md) from the `parser` gem on how to use both in conjunction.
|
data/docs/releasing.md
CHANGED
|
@@ -40,14 +40,17 @@ ruby -pi -e 'gsub(/^ruby-prism-sys = \{ version = ".+?"/, %Q{ruby-prism-sys = \{
|
|
|
40
40
|
* Update the `Gemfile.lock` file:
|
|
41
41
|
|
|
42
42
|
```sh
|
|
43
|
-
chruby ruby-
|
|
43
|
+
chruby ruby-4.0.0-dev
|
|
44
44
|
bundle install
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
* Update the version-specific lockfiles:
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
|
-
|
|
50
|
+
for VERSION in "2.7" "3.0" "3.1" "3.2" "3.3" "3.4"; do docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/$VERSION/Gemfile" "ruby:$VERSION" bundle update; done
|
|
51
|
+
docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/4.0/Gemfile" ruby:4.0.0-preview2 bundle update
|
|
52
|
+
docker run -it --rm -v "$PWD":/usr/src/app -w /usr/src/app -e BUNDLE_GEMFILE="gemfiles/jruby/Gemfile" jruby:latest bundle update
|
|
53
|
+
BUNDLE_GEMFILE=gemfiles/truffleruby/Gemfile chruby-exec truffleruby -- bundle update
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
* Update the cargo lockfiles:
|
|
@@ -71,26 +74,4 @@ git push
|
|
|
71
74
|
## Publishing
|
|
72
75
|
|
|
73
76
|
* Update the GitHub release page with a copy of the latest entry in the `CHANGELOG.md` file.
|
|
74
|
-
*
|
|
75
|
-
|
|
76
|
-
```sh
|
|
77
|
-
bundle exec rake release
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
* Generate the `wasm` artifact (or download it from GitHub actions and put it in `javascript/src/prism.wasm`).
|
|
81
|
-
|
|
82
|
-
```sh
|
|
83
|
-
make wasm
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
* Publish the JavaScript package to [npmjs.com](npmjs.com). Note that you must have access to the `@ruby/prism` package to do this.
|
|
87
|
-
|
|
88
|
-
```sh
|
|
89
|
-
npm publish
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
* Publish the rust crate to [crates.io](crates.io). Note that you must have access to the `ruby-prism-sys` and `ruby-prism` crates to do this.
|
|
93
|
-
|
|
94
|
-
```sh
|
|
95
|
-
bundle exec rake cargo:publish:real
|
|
96
|
-
```
|
|
77
|
+
* Push a new tag to the GitHub repository, following the `vX.Y.Z` format.
|
data/docs/ripper_translation.md
CHANGED
|
@@ -55,7 +55,7 @@ It is helpful to understand the differences between the `Ripper` library and the
|
|
|
55
55
|
|
|
56
56
|
### Design
|
|
57
57
|
|
|
58
|
-
`Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to
|
|
58
|
+
`Ripper` is a streaming parser. This means as it is parsing Ruby code, it dispatches events back to the consumer. This allows quite a bit of flexibility. You can use it to build your own syntax tree or to find specific patterns in the code. `Prism` on the other hand returns to you the completed syntax tree _before_ it allows you to manipulate it. This means the tree that you get back is the only representation that can be generated by the parser _at parse time_ (but of course can be manipulated later).
|
|
59
59
|
|
|
60
60
|
### Fields
|
|
61
61
|
|
data/ext/prism/api_node.c
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/* :markup: markdown */
|
|
2
|
+
|
|
1
3
|
/*----------------------------------------------------------------------------*/
|
|
2
4
|
/* This file is generated by the templates/template.rb script and should not */
|
|
3
5
|
/* be modified manually. See */
|
|
@@ -1787,7 +1789,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
|
|
|
1787
1789
|
#line 190 "prism/templates/ext/prism/api_node.c.erb"
|
|
1788
1790
|
case PM_CALL_NODE: {
|
|
1789
1791
|
pm_call_node_t *cast = (pm_call_node_t *) node;
|
|
1790
|
-
VALUE argv[
|
|
1792
|
+
VALUE argv[13];
|
|
1791
1793
|
|
|
1792
1794
|
// source
|
|
1793
1795
|
argv[0] = source;
|
|
@@ -1830,11 +1832,15 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
|
|
|
1830
1832
|
#line 243 "prism/templates/ext/prism/api_node.c.erb"
|
|
1831
1833
|
argv[10] = cast->closing_loc.start == NULL ? Qnil : pm_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source, freeze);
|
|
1832
1834
|
|
|
1835
|
+
// equal_loc
|
|
1836
|
+
#line 243 "prism/templates/ext/prism/api_node.c.erb"
|
|
1837
|
+
argv[11] = cast->equal_loc.start == NULL ? Qnil : pm_location_new(parser, cast->equal_loc.start, cast->equal_loc.end, source, freeze);
|
|
1838
|
+
|
|
1833
1839
|
// block
|
|
1834
1840
|
#line 213 "prism/templates/ext/prism/api_node.c.erb"
|
|
1835
|
-
argv[
|
|
1841
|
+
argv[12] = rb_ary_pop(value_stack);
|
|
1836
1842
|
|
|
1837
|
-
VALUE value = rb_class_new_instance(
|
|
1843
|
+
VALUE value = rb_class_new_instance(13, argv, rb_cPrismCallNode);
|
|
1838
1844
|
if (freeze) rb_obj_freeze(value);
|
|
1839
1845
|
|
|
1840
1846
|
rb_ary_push(value_stack, value);
|
data/ext/prism/extconf.rb
CHANGED
|
@@ -37,7 +37,7 @@ end
|
|
|
37
37
|
def generate_templates
|
|
38
38
|
Dir.chdir(File.expand_path("../..", __dir__)) do
|
|
39
39
|
if !File.exist?("include/prism/ast.h") && Dir.exist?(".git")
|
|
40
|
-
system("templates/template.rb", exception: true)
|
|
40
|
+
system(RbConfig.ruby, "templates/template.rb", exception: true)
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
end
|
data/ext/prism/extension.c
CHANGED
|
@@ -25,6 +25,7 @@ VALUE rb_cPrismLexResult;
|
|
|
25
25
|
VALUE rb_cPrismParseLexResult;
|
|
26
26
|
VALUE rb_cPrismStringQuery;
|
|
27
27
|
VALUE rb_cPrismScope;
|
|
28
|
+
VALUE rb_cPrismCurrentVersionError;
|
|
28
29
|
|
|
29
30
|
VALUE rb_cPrismDebugEncoding;
|
|
30
31
|
|
|
@@ -199,7 +200,12 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
|
|
|
199
200
|
if (!NIL_P(value)) {
|
|
200
201
|
const char *version = check_string(value);
|
|
201
202
|
|
|
202
|
-
if (
|
|
203
|
+
if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
|
|
204
|
+
const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
|
|
205
|
+
if (!pm_options_version_set(options, current_version, 3)) {
|
|
206
|
+
rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version));
|
|
207
|
+
}
|
|
208
|
+
} else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
|
|
203
209
|
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
|
|
204
210
|
}
|
|
205
211
|
}
|
|
@@ -888,7 +894,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
|
|
|
888
894
|
* version of Ruby syntax (which you can trigger with `nil` or
|
|
889
895
|
* `"latest"`). You may also restrict the syntax to a specific version of
|
|
890
896
|
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
|
|
891
|
-
* the current Ruby is running use `version:
|
|
897
|
+
* the current Ruby is running use `version: "current"`. Raises
|
|
892
898
|
* ArgumentError if the version is not currently supported by Prism.
|
|
893
899
|
*/
|
|
894
900
|
static VALUE
|
|
@@ -994,6 +1000,14 @@ profile_file(int argc, VALUE *argv, VALUE self) {
|
|
|
994
1000
|
return Qnil;
|
|
995
1001
|
}
|
|
996
1002
|
|
|
1003
|
+
static int
|
|
1004
|
+
parse_stream_eof(void *stream) {
|
|
1005
|
+
if (rb_funcall((VALUE) stream, rb_intern("eof?"), 0)) {
|
|
1006
|
+
return 1;
|
|
1007
|
+
}
|
|
1008
|
+
return 0;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
997
1011
|
/**
|
|
998
1012
|
* An implementation of fgets that is suitable for use with Ruby IO objects.
|
|
999
1013
|
*/
|
|
@@ -1034,7 +1048,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
|
|
|
1034
1048
|
pm_parser_t parser;
|
|
1035
1049
|
pm_buffer_t buffer;
|
|
1036
1050
|
|
|
1037
|
-
pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
|
|
1051
|
+
pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options);
|
|
1038
1052
|
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
|
1039
1053
|
|
|
1040
1054
|
VALUE source = pm_source_new(&parser, encoding, options.freeze);
|
|
@@ -1331,6 +1345,11 @@ Init_prism(void) {
|
|
|
1331
1345
|
);
|
|
1332
1346
|
}
|
|
1333
1347
|
|
|
1348
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
1349
|
+
// Mark this extension as Ractor-safe.
|
|
1350
|
+
rb_ext_ractor_safe(true);
|
|
1351
|
+
#endif
|
|
1352
|
+
|
|
1334
1353
|
// Grab up references to all of the constants that we're going to need to
|
|
1335
1354
|
// reference throughout this extension.
|
|
1336
1355
|
rb_cPrism = rb_define_module("Prism");
|
|
@@ -1351,6 +1370,8 @@ Init_prism(void) {
|
|
|
1351
1370
|
rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
|
|
1352
1371
|
rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
|
|
1353
1372
|
|
|
1373
|
+
rb_cPrismCurrentVersionError = rb_const_get(rb_cPrism, rb_intern("CurrentVersionError"));
|
|
1374
|
+
|
|
1354
1375
|
// Intern all of the IDs eagerly that we support so that we don't have to do
|
|
1355
1376
|
// it every time we parse.
|
|
1356
1377
|
rb_id_option_command_line = rb_intern_const("command_line");
|