prism 1.4.0 → 1.6.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 +51 -1
- data/Makefile +4 -2
- data/README.md +2 -0
- data/config.yml +266 -38
- data/docs/design.md +2 -2
- data/docs/parser_translation.md +8 -23
- data/docs/releasing.md +5 -24
- data/docs/ripper_translation.md +1 -1
- data/ext/prism/api_node.c +2 -0
- data/ext/prism/extension.c +25 -3
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +306 -50
- data/include/prism/diagnostic.h +5 -0
- data/include/prism/options.h +43 -3
- 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 +39 -14
- 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 +5 -1
- data/lib/prism/dsl.rb +3 -0
- data/lib/prism/ffi.rb +25 -9
- data/lib/prism/inspect_visitor.rb +3 -0
- data/lib/prism/lex_compat.rb +1 -0
- data/lib/prism/mutation_compiler.rb +3 -0
- data/lib/prism/node.rb +507 -336
- 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 +1 -0
- 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 +3 -0
- data/lib/prism/relocation.rb +1 -0
- data/lib/prism/serialize.rb +25 -19
- data/lib/prism/string_query.rb +1 -0
- data/lib/prism/translation/parser/builder.rb +1 -0
- data/lib/prism/translation/parser/compiler.rb +47 -25
- data/lib/prism/translation/parser/lexer.rb +29 -21
- data/lib/prism/translation/parser.rb +21 -2
- data/lib/prism/translation/parser33.rb +1 -0
- data/lib/prism/translation/parser34.rb +1 -0
- data/lib/prism/translation/parser35.rb +1 -0
- data/lib/prism/translation/parser_current.rb +24 -0
- data/lib/prism/translation/ripper/sexp.rb +1 -0
- data/lib/prism/translation/ripper.rb +17 -1
- data/lib/prism/translation/ruby_parser.rb +287 -4
- data/lib/prism/translation.rb +2 -0
- data/lib/prism/visitor.rb +457 -152
- data/lib/prism.rb +23 -0
- data/prism.gemspec +5 -1
- data/rbi/prism/dsl.rbi +3 -3
- data/rbi/prism/node.rbi +21 -9
- data/sig/prism/dispatcher.rbs +3 -0
- data/sig/prism/dsl.rbs +3 -3
- data/sig/prism/node.rbs +444 -30
- 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 +9 -1
- data/src/node.c +2 -0
- data/src/options.c +2 -2
- data/src/prettyprint.c +2 -0
- data/src/prism.c +324 -147
- data/src/serialize.c +2 -0
- data/src/token_type.c +36 -34
- data/src/util/pm_string.c +6 -8
- metadata +7 -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
|
@@ -47,7 +47,10 @@ bundle install
|
|
|
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/3.5/Gemfile" ruby:3.5.0-preview1 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
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,13 @@ 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
|
+
VALUE current_ruby_value = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"));
|
|
205
|
+
const char *current_version = RSTRING_PTR(current_ruby_value);
|
|
206
|
+
if (!pm_options_version_set(options, current_version, 3)) {
|
|
207
|
+
rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, current_ruby_value));
|
|
208
|
+
}
|
|
209
|
+
} else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
|
|
203
210
|
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
|
|
204
211
|
}
|
|
205
212
|
}
|
|
@@ -888,7 +895,7 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
|
|
|
888
895
|
* version of Ruby syntax (which you can trigger with `nil` or
|
|
889
896
|
* `"latest"`). You may also restrict the syntax to a specific version of
|
|
890
897
|
* Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
|
|
891
|
-
* the current Ruby is running use `version:
|
|
898
|
+
* the current Ruby is running use `version: "current"`. Raises
|
|
892
899
|
* ArgumentError if the version is not currently supported by Prism.
|
|
893
900
|
*/
|
|
894
901
|
static VALUE
|
|
@@ -994,6 +1001,14 @@ profile_file(int argc, VALUE *argv, VALUE self) {
|
|
|
994
1001
|
return Qnil;
|
|
995
1002
|
}
|
|
996
1003
|
|
|
1004
|
+
static int
|
|
1005
|
+
parse_stream_eof(void *stream) {
|
|
1006
|
+
if (rb_funcall((VALUE) stream, rb_intern("eof?"), 0)) {
|
|
1007
|
+
return 1;
|
|
1008
|
+
}
|
|
1009
|
+
return 0;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
997
1012
|
/**
|
|
998
1013
|
* An implementation of fgets that is suitable for use with Ruby IO objects.
|
|
999
1014
|
*/
|
|
@@ -1034,7 +1049,7 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
|
|
|
1034
1049
|
pm_parser_t parser;
|
|
1035
1050
|
pm_buffer_t buffer;
|
|
1036
1051
|
|
|
1037
|
-
pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
|
|
1052
|
+
pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options);
|
|
1038
1053
|
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
|
|
1039
1054
|
|
|
1040
1055
|
VALUE source = pm_source_new(&parser, encoding, options.freeze);
|
|
@@ -1331,6 +1346,11 @@ Init_prism(void) {
|
|
|
1331
1346
|
);
|
|
1332
1347
|
}
|
|
1333
1348
|
|
|
1349
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
|
1350
|
+
// Mark this extension as Ractor-safe.
|
|
1351
|
+
rb_ext_ractor_safe(true);
|
|
1352
|
+
#endif
|
|
1353
|
+
|
|
1334
1354
|
// Grab up references to all of the constants that we're going to need to
|
|
1335
1355
|
// reference throughout this extension.
|
|
1336
1356
|
rb_cPrism = rb_define_module("Prism");
|
|
@@ -1351,6 +1371,8 @@ Init_prism(void) {
|
|
|
1351
1371
|
rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
|
|
1352
1372
|
rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
|
|
1353
1373
|
|
|
1374
|
+
rb_cPrismCurrentVersionError = rb_const_get(rb_cPrism, rb_intern("CurrentVersionError"));
|
|
1375
|
+
|
|
1354
1376
|
// Intern all of the IDs eagerly that we support so that we don't have to do
|
|
1355
1377
|
// it every time we parse.
|
|
1356
1378
|
rb_id_option_command_line = rb_intern_const("command_line");
|