prism 0.15.1 → 0.16.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 +20 -1
- data/Makefile +6 -0
- data/README.md +2 -0
- data/config.yml +21 -20
- data/docs/configuration.md +2 -0
- data/docs/javascript.md +90 -0
- data/docs/releasing.md +27 -0
- data/docs/ruby_api.md +2 -0
- data/ext/prism/api_node.c +66 -68
- data/ext/prism/extension.c +73 -0
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +40 -40
- data/include/prism/defines.h +9 -0
- data/include/prism/enc/pm_encoding.h +1 -0
- data/include/prism/node.h +0 -17
- data/include/prism/parser.h +1 -0
- data/include/prism/prettyprint.h +15 -0
- data/include/prism/util/pm_buffer.h +10 -4
- data/include/prism/util/pm_constant_pool.h +1 -1
- data/include/prism/util/pm_newline_list.h +1 -1
- data/include/prism/version.h +3 -3
- data/include/prism.h +11 -11
- data/lib/prism/compiler.rb +0 -3
- data/lib/prism/debug.rb +20 -6
- data/lib/prism/desugar_compiler.rb +1 -1
- data/lib/prism/dispatcher.rb +0 -14
- data/lib/prism/dsl.rb +8 -13
- data/lib/prism/ffi.rb +25 -0
- data/lib/prism/lex_compat.rb +1 -1
- data/lib/prism/mutation_compiler.rb +3 -8
- data/lib/prism/node.rb +123 -159
- data/lib/prism/node_ext.rb +23 -16
- data/lib/prism/parse_result.rb +21 -5
- data/lib/prism/pattern.rb +3 -3
- data/lib/prism/serialize.rb +901 -305
- data/lib/prism/visitor.rb +0 -3
- data/prism.gemspec +8 -1
- data/rbi/prism.rbi +7261 -0
- data/rbi/prism_static.rbi +182 -0
- data/sig/prism.rbs +4439 -0
- data/sig/prism_static.rbs +110 -0
- data/src/enc/pm_unicode.c +1 -1
- data/src/node.c +28 -29
- data/src/prettyprint.c +7674 -1647
- data/src/prism.c +353 -300
- data/src/regexp.c +2 -0
- data/src/serialize.c +392 -381
- data/src/util/pm_buffer.c +47 -12
- data/src/util/pm_constant_pool.c +1 -1
- data/src/util/pm_newline_list.c +8 -54
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 498f20248401af377faf45d30b7154d819b8bea560be2747c030d5ae536851c9
|
4
|
+
data.tar.gz: 8d3bb4fc0afb899869d8d6a55a526a40769fb46a582cf465035de750824d72d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d71744c4342a671b578ed7ebf3dede7b0146404a61e40ed8b082c544f5d8e9d83dc4e1f0780555cab4c70bd052156e26f9d8b46a2f2012bcedf89bf5b21d54b
|
7
|
+
data.tar.gz: 2a2178b5615fe4c55d7c16156901423fe38dee075e4f60cc893c367630e7c136cc7d6bc19f3fcf037a6958d158b2663f61389656754fe679570271503a5b35a2
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.16.0] - 2023-10-30
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- `InterpolatedMatchLastLineNode#options` and `MatchLastLineNode#options` are added, which are the same methods as are exposed on `InterpolatedRegularExpressionNode` and `RegularExpressionNode`.
|
14
|
+
- The project can now be compiled with `wasi-sdk` to expose a WebAssembly interface.
|
15
|
+
- `ArgumentsNode#keyword_splat?` is added to indicate if the arguments node has a keyword splat.
|
16
|
+
- The C API `pm_prettyprint` has a much improved output which lines up closely with `Node#inspect`.
|
17
|
+
- Prism now ships with `RBS` and `RBI` type signatures (in the `/sig` and `/rbi` directories, respectively).
|
18
|
+
- `Prism::parse_comments` and `Prism::parse_file_comments` APIs are added to extract only the comments from the source code.
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
|
22
|
+
- **BREAKING**: `Multi{Target,Write}Node#targets` is split up now into `lefts`, `rest`, and `rights`. This is to avoid having to scan the list in the case that there are splat nodes.
|
23
|
+
- Some bugs are fixed on `Multi{Target,Write}Node` accidentally creating additional nesting when not necessary.
|
24
|
+
- **BREAKING**: `RequiredDestructuredParameterNode` has been removed in favor of using `MultiTargetNode` in those places.
|
25
|
+
- **BREAKING**: `HashPatternNode#assocs` has been renamed to `HashPatternNode#elements`. `HashPatternNode#kwrest` has been renamed to `HashPatternNode#rest`.
|
26
|
+
|
9
27
|
## [0.15.1] - 2023-10-18
|
10
28
|
|
11
29
|
### Changed
|
@@ -201,7 +219,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
201
219
|
|
202
220
|
- 🎉 Initial release! 🎉
|
203
221
|
|
204
|
-
[unreleased]: https://github.com/ruby/prism/compare/v0.
|
222
|
+
[unreleased]: https://github.com/ruby/prism/compare/v0.16.0...HEAD
|
223
|
+
[0.16.0]: https://github.com/ruby/prism/compare/v0.15.1...v0.16.0
|
205
224
|
[0.15.1]: https://github.com/ruby/prism/compare/v0.15.0...v0.15.1
|
206
225
|
[0.15.0]: https://github.com/ruby/prism/compare/v0.14.0...v0.15.0
|
207
226
|
[0.14.0]: https://github.com/ruby/prism/compare/v0.13.0...v0.14.0
|
data/Makefile
CHANGED
@@ -13,6 +13,7 @@ SOEXT := $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]')
|
|
13
13
|
CPPFLAGS := -Iinclude
|
14
14
|
CFLAGS := -g -O2 -std=c99 -Wall -Werror -Wextra -Wpedantic -Wundef -Wconversion -fPIC -fvisibility=hidden
|
15
15
|
CC := cc
|
16
|
+
WASI_SDK_PATH := /opt/wasi-sdk
|
16
17
|
|
17
18
|
HEADERS := $(shell find include -name '*.h')
|
18
19
|
SOURCES := $(shell find src -name '*.c')
|
@@ -23,6 +24,7 @@ all: shared static
|
|
23
24
|
|
24
25
|
shared: build/librubyparser.$(SOEXT)
|
25
26
|
static: build/librubyparser.a
|
27
|
+
wasm: javascript/src/prism.wasm
|
26
28
|
|
27
29
|
build/librubyparser.$(SOEXT): $(SHARED_OBJECTS)
|
28
30
|
$(ECHO) "linking $@"
|
@@ -32,6 +34,10 @@ build/librubyparser.a: $(STATIC_OBJECTS)
|
|
32
34
|
$(ECHO) "building $@"
|
33
35
|
$(Q) $(AR) $(ARFLAGS) $@ $(STATIC_OBJECTS) $(Q1:0=>/dev/null)
|
34
36
|
|
37
|
+
javascript/src/prism.wasm: Makefile $(SOURCES) $(HEADERS)
|
38
|
+
$(ECHO) "building $@"
|
39
|
+
$(Q) $(WASI_SDK_PATH)/bin/clang --sysroot=$(WASI_SDK_PATH)/share/wasi-sysroot/ $(DEBUG_FLAGS) -DPRISM_EXPORT_SYMBOLS -D_WASI_EMULATED_MMAN -lwasi-emulated-mman $(CPPFLAGS) $(CFLAGS) -Wl,--export-all -Wl,--no-entry -mexec-model=reactor -o $@ $(SOURCES)
|
40
|
+
|
35
41
|
build/shared/%.o: src/%.c Makefile $(HEADERS)
|
36
42
|
$(ECHO) "compiling $@"
|
37
43
|
$(Q) mkdir -p $(@D)
|
data/README.md
CHANGED
@@ -85,7 +85,9 @@ See the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information. We additio
|
|
85
85
|
* [Encoding](docs/encoding.md)
|
86
86
|
* [Fuzzing](docs/fuzzing.md)
|
87
87
|
* [Heredocs](docs/heredocs.md)
|
88
|
+
* [JavaScript](docs/javascript.md)
|
88
89
|
* [Mapping](docs/mapping.md)
|
90
|
+
* [Releasing](docs/releasing.md)
|
89
91
|
* [Ripper](docs/ripper.md)
|
90
92
|
* [Ruby API](docs/ruby_api.md)
|
91
93
|
* [Serialization](docs/serialization.md)
|
data/config.yml
CHANGED
@@ -329,6 +329,10 @@ tokens:
|
|
329
329
|
- name: __END__
|
330
330
|
comment: "marker for the point in the file at which the parser should stop"
|
331
331
|
flags:
|
332
|
+
- name: ArgumentsNodeFlags
|
333
|
+
values:
|
334
|
+
- name: KEYWORD_SPLAT
|
335
|
+
comment: "if arguments contain keyword splat"
|
332
336
|
- name: CallNodeFlags
|
333
337
|
values:
|
334
338
|
- name: SAFE_NAVIGATION
|
@@ -432,6 +436,9 @@ nodes:
|
|
432
436
|
fields:
|
433
437
|
- name: arguments
|
434
438
|
type: node[]
|
439
|
+
- name: flags
|
440
|
+
type: flags
|
441
|
+
kind: ArgumentsNodeFlags
|
435
442
|
comment: |
|
436
443
|
Represents a set of arguments to a method or a keyword.
|
437
444
|
|
@@ -1349,9 +1356,9 @@ nodes:
|
|
1349
1356
|
fields:
|
1350
1357
|
- name: constant
|
1351
1358
|
type: node?
|
1352
|
-
- name:
|
1359
|
+
- name: elements
|
1353
1360
|
type: node[]
|
1354
|
-
- name:
|
1361
|
+
- name: rest
|
1355
1362
|
type: node?
|
1356
1363
|
- name: opening_loc
|
1357
1364
|
type: location?
|
@@ -1915,7 +1922,11 @@ nodes:
|
|
1915
1922
|
^^^^^^^^^^^^^^
|
1916
1923
|
- name: MultiTargetNode
|
1917
1924
|
fields:
|
1918
|
-
- name:
|
1925
|
+
- name: lefts
|
1926
|
+
type: node[]
|
1927
|
+
- name: rest
|
1928
|
+
type: node?
|
1929
|
+
- name: rights
|
1919
1930
|
type: node[]
|
1920
1931
|
- name: lparen_loc
|
1921
1932
|
type: location?
|
@@ -1924,11 +1935,15 @@ nodes:
|
|
1924
1935
|
comment: |
|
1925
1936
|
Represents a multi-target expression.
|
1926
1937
|
|
1927
|
-
a, b, c = 1, 2, 3
|
1928
|
-
|
1938
|
+
a, (b, c) = 1, 2, 3
|
1939
|
+
^^^^^^
|
1929
1940
|
- name: MultiWriteNode
|
1930
1941
|
fields:
|
1931
|
-
- name:
|
1942
|
+
- name: lefts
|
1943
|
+
type: node[]
|
1944
|
+
- name: rest
|
1945
|
+
type: node?
|
1946
|
+
- name: rights
|
1932
1947
|
type: node[]
|
1933
1948
|
- name: lparen_loc
|
1934
1949
|
type: location?
|
@@ -2169,20 +2184,6 @@ nodes:
|
|
2169
2184
|
|
2170
2185
|
/foo/i
|
2171
2186
|
^^^^^^
|
2172
|
-
- name: RequiredDestructuredParameterNode
|
2173
|
-
fields:
|
2174
|
-
- name: parameters
|
2175
|
-
type: node[]
|
2176
|
-
- name: opening_loc
|
2177
|
-
type: location
|
2178
|
-
- name: closing_loc
|
2179
|
-
type: location
|
2180
|
-
comment: |
|
2181
|
-
Represents a destructured required parameter node.
|
2182
|
-
|
2183
|
-
def foo((bar, baz))
|
2184
|
-
^^^^^^^^^^
|
2185
|
-
end
|
2186
2187
|
- name: RequiredParameterNode
|
2187
2188
|
fields:
|
2188
2189
|
- name: name
|
data/docs/configuration.md
CHANGED
@@ -4,6 +4,8 @@ A lot of code in prism's repository is templated from a single configuration fil
|
|
4
4
|
|
5
5
|
* `ext/prism/api_node.c` - for defining how to build Ruby objects for the nodes out of C structs
|
6
6
|
* `include/prism/ast.h` - for defining the C structs that represent the nodes
|
7
|
+
* `javascript/src/deserialize.js` - for defining how to deserialize the nodes in JavaScript
|
8
|
+
* `javascript/src/nodes.js` - for defining the nodes in JavaScript
|
7
9
|
* `java/org/prism/AbstractNodeVisitor.java` - for defining the visitor interface for the nodes in Java
|
8
10
|
* `java/org/prism/Loader.java` - for defining how to deserialize the nodes in Java
|
9
11
|
* `java/org/prism/Nodes.java` - for defining the nodes in Java
|
data/docs/javascript.md
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# JavaScript
|
2
|
+
|
3
|
+
Prism provides bindings to JavaScript out of the box.
|
4
|
+
|
5
|
+
## Node
|
6
|
+
|
7
|
+
To use the package from node, install the `@ruby/prism` dependency:
|
8
|
+
|
9
|
+
```sh
|
10
|
+
npm install @ruby/prism
|
11
|
+
```
|
12
|
+
|
13
|
+
Then import the package:
|
14
|
+
|
15
|
+
```js
|
16
|
+
import { loadPrism } from "@ruby/prism";
|
17
|
+
```
|
18
|
+
|
19
|
+
Then call the load function to get a parse function:
|
20
|
+
|
21
|
+
```js
|
22
|
+
const parse = await loadPrism();
|
23
|
+
```
|
24
|
+
|
25
|
+
## Browser
|
26
|
+
|
27
|
+
To use the package from the browser, you will need to do some additional work. The [javascript/example.html](javascript/example.html) file shows an example of running Prism in the browser. You will need to instantiate the WebAssembly module yourself and then pass it to the `parsePrism` function.
|
28
|
+
|
29
|
+
First, get a shim for WASI since not all browsers support it yet.
|
30
|
+
|
31
|
+
```js
|
32
|
+
import { WASI } from "https://unpkg.com/@bjorn3/browser_wasi_shim@latest/dist/index.js";
|
33
|
+
```
|
34
|
+
|
35
|
+
Next, import the `parsePrism` function from `@ruby/prism`, either through a CDN or by bundling it with your application.
|
36
|
+
|
37
|
+
```js
|
38
|
+
import { parsePrism } from "https://unpkg.com/@ruby/prism@latest/src/parsePrism.js";
|
39
|
+
```
|
40
|
+
|
41
|
+
Next, fetch and instantiate the WebAssembly module. You can access it through a CDN or by bundling it with your application.
|
42
|
+
|
43
|
+
```js
|
44
|
+
const wasm = await WebAssembly.compileStreaming(fetch("https://unpkg.com/@ruby/prism@latest/src/prism.wasm"));
|
45
|
+
```
|
46
|
+
|
47
|
+
Next, instantiate the module and initialize WASI.
|
48
|
+
|
49
|
+
```js
|
50
|
+
const wasi = new WASI([], [], []);
|
51
|
+
const instance = await WebAssembly.instantiate(wasm, { wasi_snapshot_preview1: wasi.wasiImport });
|
52
|
+
wasi.initialize(instance);
|
53
|
+
```
|
54
|
+
|
55
|
+
Finally, you can create a function that will parse a string of Ruby code.
|
56
|
+
|
57
|
+
```js
|
58
|
+
function parse(source) {
|
59
|
+
return parsePrism(instance.exports, source);
|
60
|
+
}
|
61
|
+
```
|
62
|
+
|
63
|
+
## API
|
64
|
+
|
65
|
+
Now that we have access to a `parse` function, we can use it to parse Ruby code:
|
66
|
+
|
67
|
+
```js
|
68
|
+
const parseResult = parse("1 + 2");
|
69
|
+
```
|
70
|
+
|
71
|
+
A ParseResult object is very similar to the Prism::ParseResult object from Ruby. It has the same properties: `value`, `comments`, `magicComments`, `errors`, and `warnings`. Here we can serialize the AST to JSON.
|
72
|
+
|
73
|
+
```js
|
74
|
+
console.log(JSON.stringify(parseResult.value, null, 2));
|
75
|
+
```
|
76
|
+
|
77
|
+
## Building
|
78
|
+
|
79
|
+
To build the WASM package yourself, first obtain a copy of `wasi-sdk`. You can retrieve this here: <https://github.com/WebAssembly/wasi-sdk>. Next, run:
|
80
|
+
|
81
|
+
```sh
|
82
|
+
make wasm WASI_SDK_PATH=path/to/wasi-sdk
|
83
|
+
```
|
84
|
+
|
85
|
+
This will generate `javascript/src/prism.wasm`. From there, you can run the tests to verify everything was generated correctly.
|
86
|
+
|
87
|
+
```sh
|
88
|
+
cd javascript
|
89
|
+
node test
|
90
|
+
```
|
data/docs/releasing.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Releasing
|
2
|
+
|
3
|
+
To release a new version of Prism, perform the following steps:
|
4
|
+
|
5
|
+
## Preparation
|
6
|
+
|
7
|
+
* Update the CHANGELOG.md file.
|
8
|
+
* Add a new section for the new version at the top of the file.
|
9
|
+
* Fill in the relevant changes — it may be easiest to click the link for the `Unreleased` heading to find the commits.
|
10
|
+
* Update the links at the bottom of the file.
|
11
|
+
* Update the version in the following files:
|
12
|
+
* `prism.gemspec` in the `Gem::Specification#version=` method call
|
13
|
+
* `ext/prism/extension.h` in the `EXPECTED_PRISM_VERSION` macro
|
14
|
+
* `include/prism/version.h` in the version macros
|
15
|
+
* `javascript/package.json` in the `version` field
|
16
|
+
* `rust/prism-sys/tests/utils_tests.rs` in the `version_test` function
|
17
|
+
* `templates/java/org/prism/Loader.java.erb` in the `load` function
|
18
|
+
* `templates/javascript/src/deserialize.js.erb` in the version constants
|
19
|
+
* `templates/lib/prism/serialize.rb.erb` in the version constants
|
20
|
+
* Run `bundle install` to update the `Gemfile.lock` file.
|
21
|
+
* Update `rust/prism-sys/Cargo.toml` to match the new version and run `cargo build`
|
22
|
+
* Update `rust/prism/Cargo.toml` to match the new version and run `cargo build`
|
23
|
+
* Commit all of the updated files.
|
24
|
+
|
25
|
+
## Publishing
|
26
|
+
|
27
|
+
* Run `bundle exec rake release` to publish the gem to [rubygems.org](rubygems.org). Note that you must have access to the `prism` gem to do this.
|
data/docs/ruby_api.md
CHANGED
@@ -23,3 +23,5 @@ The full API is documented below.
|
|
23
23
|
* `Prism.parse_lex(source)` - parse the syntax tree corresponding to the given source string and return it within a parse result, along with the tokens
|
24
24
|
* `Prism.parse_lex_file(filepath)` - parse the syntax tree corresponding to the given source file and return it within a parse result, along with the tokens
|
25
25
|
* `Prism.load(source, serialized)` - load the serialized syntax tree using the source as a reference into a syntax tree
|
26
|
+
* `Prism.parse_comments(source)` - parse the comments corresponding to the given source string and return them
|
27
|
+
* `Prism.parse_file_comments(source)` - parse the comments corresponding to the given source file and return them
|
data/ext/prism/api_node.c
CHANGED
@@ -132,7 +132,6 @@ static VALUE rb_cPrismRangeNode;
|
|
132
132
|
static VALUE rb_cPrismRationalNode;
|
133
133
|
static VALUE rb_cPrismRedoNode;
|
134
134
|
static VALUE rb_cPrismRegularExpressionNode;
|
135
|
-
static VALUE rb_cPrismRequiredDestructuredParameterNode;
|
136
135
|
static VALUE rb_cPrismRequiredParameterNode;
|
137
136
|
static VALUE rb_cPrismRescueModifierNode;
|
138
137
|
static VALUE rb_cPrismRescueNode;
|
@@ -607,10 +606,10 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
607
606
|
case PM_HASH_PATTERN_NODE: {
|
608
607
|
pm_hash_pattern_node_t *cast = (pm_hash_pattern_node_t *) node;
|
609
608
|
pm_node_stack_push(&node_stack, (pm_node_t *) cast->constant);
|
610
|
-
for (size_t index = 0; index < cast->
|
611
|
-
pm_node_stack_push(&node_stack, (pm_node_t *) cast->
|
609
|
+
for (size_t index = 0; index < cast->elements.size; index++) {
|
610
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->elements.nodes[index]);
|
612
611
|
}
|
613
|
-
pm_node_stack_push(&node_stack, (pm_node_t *) cast->
|
612
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->rest);
|
614
613
|
break;
|
615
614
|
}
|
616
615
|
#line 108 "api_node.c.erb"
|
@@ -806,16 +805,24 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
806
805
|
#line 108 "api_node.c.erb"
|
807
806
|
case PM_MULTI_TARGET_NODE: {
|
808
807
|
pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node;
|
809
|
-
for (size_t index = 0; index < cast->
|
810
|
-
pm_node_stack_push(&node_stack, (pm_node_t *) cast->
|
808
|
+
for (size_t index = 0; index < cast->lefts.size; index++) {
|
809
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->lefts.nodes[index]);
|
810
|
+
}
|
811
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->rest);
|
812
|
+
for (size_t index = 0; index < cast->rights.size; index++) {
|
813
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->rights.nodes[index]);
|
811
814
|
}
|
812
815
|
break;
|
813
816
|
}
|
814
817
|
#line 108 "api_node.c.erb"
|
815
818
|
case PM_MULTI_WRITE_NODE: {
|
816
819
|
pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node;
|
817
|
-
for (size_t index = 0; index < cast->
|
818
|
-
pm_node_stack_push(&node_stack, (pm_node_t *) cast->
|
820
|
+
for (size_t index = 0; index < cast->lefts.size; index++) {
|
821
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->lefts.nodes[index]);
|
822
|
+
}
|
823
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->rest);
|
824
|
+
for (size_t index = 0; index < cast->rights.size; index++) {
|
825
|
+
pm_node_stack_push(&node_stack, (pm_node_t *) cast->rights.nodes[index]);
|
819
826
|
}
|
820
827
|
pm_node_stack_push(&node_stack, (pm_node_t *) cast->value);
|
821
828
|
break;
|
@@ -908,14 +915,6 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
908
915
|
pm_node_stack_push(&node_stack, (pm_node_t *) cast->numeric);
|
909
916
|
break;
|
910
917
|
}
|
911
|
-
#line 108 "api_node.c.erb"
|
912
|
-
case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: {
|
913
|
-
pm_required_destructured_parameter_node_t *cast = (pm_required_destructured_parameter_node_t *) node;
|
914
|
-
for (size_t index = 0; index < cast->parameters.size; index++) {
|
915
|
-
pm_node_stack_push(&node_stack, (pm_node_t *) cast->parameters.nodes[index]);
|
916
|
-
}
|
917
|
-
break;
|
918
|
-
}
|
919
918
|
#line 108 "api_node.c.erb"
|
920
919
|
case PM_RESCUE_MODIFIER_NODE: {
|
921
920
|
pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node;
|
@@ -1123,7 +1122,7 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
1123
1122
|
#line 134 "api_node.c.erb"
|
1124
1123
|
case PM_ARGUMENTS_NODE: {
|
1125
1124
|
pm_arguments_node_t *cast = (pm_arguments_node_t *) node;
|
1126
|
-
VALUE argv[
|
1125
|
+
VALUE argv[3];
|
1127
1126
|
|
1128
1127
|
// arguments
|
1129
1128
|
#line 148 "api_node.c.erb"
|
@@ -1132,10 +1131,14 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
1132
1131
|
rb_ary_push(argv[0], rb_ary_pop(value_stack));
|
1133
1132
|
}
|
1134
1133
|
|
1134
|
+
// flags
|
1135
|
+
#line 179 "api_node.c.erb"
|
1136
|
+
argv[1] = ULONG2NUM(node->flags & ~PM_NODE_FLAG_COMMON_MASK);
|
1137
|
+
|
1135
1138
|
// location
|
1136
|
-
argv[
|
1139
|
+
argv[2] = pm_location_new(parser, node->location.start, node->location.end, source);
|
1137
1140
|
|
1138
|
-
rb_ary_push(value_stack, rb_class_new_instance(
|
1141
|
+
rb_ary_push(value_stack, rb_class_new_instance(3, argv, rb_cPrismArgumentsNode));
|
1139
1142
|
break;
|
1140
1143
|
}
|
1141
1144
|
#line 134 "api_node.c.erb"
|
@@ -2694,14 +2697,14 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
2694
2697
|
#line 145 "api_node.c.erb"
|
2695
2698
|
argv[0] = rb_ary_pop(value_stack);
|
2696
2699
|
|
2697
|
-
//
|
2700
|
+
// elements
|
2698
2701
|
#line 148 "api_node.c.erb"
|
2699
|
-
argv[1] = rb_ary_new_capa(cast->
|
2700
|
-
for (size_t index = 0; index < cast->
|
2702
|
+
argv[1] = rb_ary_new_capa(cast->elements.size);
|
2703
|
+
for (size_t index = 0; index < cast->elements.size; index++) {
|
2701
2704
|
rb_ary_push(argv[1], rb_ary_pop(value_stack));
|
2702
2705
|
}
|
2703
2706
|
|
2704
|
-
//
|
2707
|
+
// rest
|
2705
2708
|
#line 145 "api_node.c.erb"
|
2706
2709
|
argv[2] = rb_ary_pop(value_stack);
|
2707
2710
|
|
@@ -3681,61 +3684,83 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
3681
3684
|
#line 134 "api_node.c.erb"
|
3682
3685
|
case PM_MULTI_TARGET_NODE: {
|
3683
3686
|
pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node;
|
3684
|
-
VALUE argv[
|
3687
|
+
VALUE argv[6];
|
3685
3688
|
|
3686
|
-
//
|
3689
|
+
// lefts
|
3687
3690
|
#line 148 "api_node.c.erb"
|
3688
|
-
argv[0] = rb_ary_new_capa(cast->
|
3689
|
-
for (size_t index = 0; index < cast->
|
3691
|
+
argv[0] = rb_ary_new_capa(cast->lefts.size);
|
3692
|
+
for (size_t index = 0; index < cast->lefts.size; index++) {
|
3690
3693
|
rb_ary_push(argv[0], rb_ary_pop(value_stack));
|
3691
3694
|
}
|
3692
3695
|
|
3696
|
+
// rest
|
3697
|
+
#line 145 "api_node.c.erb"
|
3698
|
+
argv[1] = rb_ary_pop(value_stack);
|
3699
|
+
|
3700
|
+
// rights
|
3701
|
+
#line 148 "api_node.c.erb"
|
3702
|
+
argv[2] = rb_ary_new_capa(cast->rights.size);
|
3703
|
+
for (size_t index = 0; index < cast->rights.size; index++) {
|
3704
|
+
rb_ary_push(argv[2], rb_ary_pop(value_stack));
|
3705
|
+
}
|
3706
|
+
|
3693
3707
|
// lparen_loc
|
3694
3708
|
#line 173 "api_node.c.erb"
|
3695
|
-
argv[
|
3709
|
+
argv[3] = cast->lparen_loc.start == NULL ? Qnil : pm_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source);
|
3696
3710
|
|
3697
3711
|
// rparen_loc
|
3698
3712
|
#line 173 "api_node.c.erb"
|
3699
|
-
argv[
|
3713
|
+
argv[4] = cast->rparen_loc.start == NULL ? Qnil : pm_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source);
|
3700
3714
|
|
3701
3715
|
// location
|
3702
|
-
argv[
|
3716
|
+
argv[5] = pm_location_new(parser, node->location.start, node->location.end, source);
|
3703
3717
|
|
3704
|
-
rb_ary_push(value_stack, rb_class_new_instance(
|
3718
|
+
rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cPrismMultiTargetNode));
|
3705
3719
|
break;
|
3706
3720
|
}
|
3707
3721
|
#line 134 "api_node.c.erb"
|
3708
3722
|
case PM_MULTI_WRITE_NODE: {
|
3709
3723
|
pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node;
|
3710
|
-
VALUE argv[
|
3724
|
+
VALUE argv[8];
|
3711
3725
|
|
3712
|
-
//
|
3726
|
+
// lefts
|
3713
3727
|
#line 148 "api_node.c.erb"
|
3714
|
-
argv[0] = rb_ary_new_capa(cast->
|
3715
|
-
for (size_t index = 0; index < cast->
|
3728
|
+
argv[0] = rb_ary_new_capa(cast->lefts.size);
|
3729
|
+
for (size_t index = 0; index < cast->lefts.size; index++) {
|
3716
3730
|
rb_ary_push(argv[0], rb_ary_pop(value_stack));
|
3717
3731
|
}
|
3718
3732
|
|
3733
|
+
// rest
|
3734
|
+
#line 145 "api_node.c.erb"
|
3735
|
+
argv[1] = rb_ary_pop(value_stack);
|
3736
|
+
|
3737
|
+
// rights
|
3738
|
+
#line 148 "api_node.c.erb"
|
3739
|
+
argv[2] = rb_ary_new_capa(cast->rights.size);
|
3740
|
+
for (size_t index = 0; index < cast->rights.size; index++) {
|
3741
|
+
rb_ary_push(argv[2], rb_ary_pop(value_stack));
|
3742
|
+
}
|
3743
|
+
|
3719
3744
|
// lparen_loc
|
3720
3745
|
#line 173 "api_node.c.erb"
|
3721
|
-
argv[
|
3746
|
+
argv[3] = cast->lparen_loc.start == NULL ? Qnil : pm_location_new(parser, cast->lparen_loc.start, cast->lparen_loc.end, source);
|
3722
3747
|
|
3723
3748
|
// rparen_loc
|
3724
3749
|
#line 173 "api_node.c.erb"
|
3725
|
-
argv[
|
3750
|
+
argv[4] = cast->rparen_loc.start == NULL ? Qnil : pm_location_new(parser, cast->rparen_loc.start, cast->rparen_loc.end, source);
|
3726
3751
|
|
3727
3752
|
// operator_loc
|
3728
3753
|
#line 170 "api_node.c.erb"
|
3729
|
-
argv[
|
3754
|
+
argv[5] = pm_location_new(parser, cast->operator_loc.start, cast->operator_loc.end, source);
|
3730
3755
|
|
3731
3756
|
// value
|
3732
3757
|
#line 145 "api_node.c.erb"
|
3733
|
-
argv[
|
3758
|
+
argv[6] = rb_ary_pop(value_stack);
|
3734
3759
|
|
3735
3760
|
// location
|
3736
|
-
argv[
|
3761
|
+
argv[7] = pm_location_new(parser, node->location.start, node->location.end, source);
|
3737
3762
|
|
3738
|
-
rb_ary_push(value_stack, rb_class_new_instance(
|
3763
|
+
rb_ary_push(value_stack, rb_class_new_instance(8, argv, rb_cPrismMultiWriteNode));
|
3739
3764
|
break;
|
3740
3765
|
}
|
3741
3766
|
#line 134 "api_node.c.erb"
|
@@ -4131,32 +4156,6 @@ pm_ast_new(pm_parser_t *parser, pm_node_t *node, rb_encoding *encoding) {
|
|
4131
4156
|
rb_ary_push(value_stack, rb_class_new_instance(6, argv, rb_cPrismRegularExpressionNode));
|
4132
4157
|
break;
|
4133
4158
|
}
|
4134
|
-
#line 134 "api_node.c.erb"
|
4135
|
-
case PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE: {
|
4136
|
-
pm_required_destructured_parameter_node_t *cast = (pm_required_destructured_parameter_node_t *) node;
|
4137
|
-
VALUE argv[4];
|
4138
|
-
|
4139
|
-
// parameters
|
4140
|
-
#line 148 "api_node.c.erb"
|
4141
|
-
argv[0] = rb_ary_new_capa(cast->parameters.size);
|
4142
|
-
for (size_t index = 0; index < cast->parameters.size; index++) {
|
4143
|
-
rb_ary_push(argv[0], rb_ary_pop(value_stack));
|
4144
|
-
}
|
4145
|
-
|
4146
|
-
// opening_loc
|
4147
|
-
#line 170 "api_node.c.erb"
|
4148
|
-
argv[1] = pm_location_new(parser, cast->opening_loc.start, cast->opening_loc.end, source);
|
4149
|
-
|
4150
|
-
// closing_loc
|
4151
|
-
#line 170 "api_node.c.erb"
|
4152
|
-
argv[2] = pm_location_new(parser, cast->closing_loc.start, cast->closing_loc.end, source);
|
4153
|
-
|
4154
|
-
// location
|
4155
|
-
argv[3] = pm_location_new(parser, node->location.start, node->location.end, source);
|
4156
|
-
|
4157
|
-
rb_ary_push(value_stack, rb_class_new_instance(4, argv, rb_cPrismRequiredDestructuredParameterNode));
|
4158
|
-
break;
|
4159
|
-
}
|
4160
4159
|
#line 134 "api_node.c.erb"
|
4161
4160
|
case PM_REQUIRED_PARAMETER_NODE: {
|
4162
4161
|
pm_required_parameter_node_t *cast = (pm_required_parameter_node_t *) node;
|
@@ -4849,7 +4848,6 @@ Init_prism_api_node(void) {
|
|
4849
4848
|
rb_cPrismRationalNode = rb_define_class_under(rb_cPrism, "RationalNode", rb_cPrismNode);
|
4850
4849
|
rb_cPrismRedoNode = rb_define_class_under(rb_cPrism, "RedoNode", rb_cPrismNode);
|
4851
4850
|
rb_cPrismRegularExpressionNode = rb_define_class_under(rb_cPrism, "RegularExpressionNode", rb_cPrismNode);
|
4852
|
-
rb_cPrismRequiredDestructuredParameterNode = rb_define_class_under(rb_cPrism, "RequiredDestructuredParameterNode", rb_cPrismNode);
|
4853
4851
|
rb_cPrismRequiredParameterNode = rb_define_class_under(rb_cPrism, "RequiredParameterNode", rb_cPrismNode);
|
4854
4852
|
rb_cPrismRescueModifierNode = rb_define_class_under(rb_cPrism, "RescueModifierNode", rb_cPrismNode);
|
4855
4853
|
rb_cPrismRescueNode = rb_define_class_under(rb_cPrism, "RescueNode", rb_cPrismNode);
|
data/ext/prism/extension.c
CHANGED
@@ -396,6 +396,24 @@ parse_input(pm_string_t *input, const char *filepath) {
|
|
396
396
|
return result;
|
397
397
|
}
|
398
398
|
|
399
|
+
// Parse the given input and return an array of Comment objects.
|
400
|
+
static VALUE
|
401
|
+
parse_input_comments(pm_string_t *input, const char *filepath) {
|
402
|
+
pm_parser_t parser;
|
403
|
+
pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), filepath);
|
404
|
+
|
405
|
+
pm_node_t *node = pm_parse(&parser);
|
406
|
+
rb_encoding *encoding = rb_enc_find(parser.encoding.name);
|
407
|
+
|
408
|
+
VALUE source = pm_source_new(&parser, encoding);
|
409
|
+
VALUE comments = parser_comments(&parser, source);
|
410
|
+
|
411
|
+
pm_node_destroy(&parser, node);
|
412
|
+
pm_parser_free(&parser);
|
413
|
+
|
414
|
+
return comments;
|
415
|
+
}
|
416
|
+
|
399
417
|
// Parse the given string and return a ParseResult instance.
|
400
418
|
static VALUE
|
401
419
|
parse(int argc, VALUE *argv, VALUE self) {
|
@@ -436,6 +454,33 @@ parse_file(VALUE self, VALUE filepath) {
|
|
436
454
|
return value;
|
437
455
|
}
|
438
456
|
|
457
|
+
// Parse the given string and return an array of Comment objects.
|
458
|
+
static VALUE
|
459
|
+
parse_comments(int argc, VALUE *argv, VALUE self) {
|
460
|
+
VALUE string;
|
461
|
+
VALUE filepath;
|
462
|
+
rb_scan_args(argc, argv, "11", &string, &filepath);
|
463
|
+
|
464
|
+
pm_string_t input;
|
465
|
+
input_load_string(&input, string);
|
466
|
+
|
467
|
+
return parse_input_comments(&input, check_string(filepath));
|
468
|
+
}
|
469
|
+
|
470
|
+
// Parse the given file and return an array of Comment objects.
|
471
|
+
static VALUE
|
472
|
+
parse_file_comments(VALUE self, VALUE filepath) {
|
473
|
+
pm_string_t input;
|
474
|
+
|
475
|
+
const char *checked = check_string(filepath);
|
476
|
+
if (!pm_string_mapped_init(&input, checked)) return Qnil;
|
477
|
+
|
478
|
+
VALUE value = parse_input_comments(&input, checked);
|
479
|
+
pm_string_free(&input);
|
480
|
+
|
481
|
+
return value;
|
482
|
+
}
|
483
|
+
|
439
484
|
// Parse the given string and return a ParseResult instance.
|
440
485
|
static VALUE
|
441
486
|
parse_lex(int argc, VALUE *argv, VALUE self) {
|
@@ -554,6 +599,31 @@ parse_serialize_file_metadata(VALUE self, VALUE filepath, VALUE metadata) {
|
|
554
599
|
return result;
|
555
600
|
}
|
556
601
|
|
602
|
+
// Inspect the AST that represents the given source using the prism pretty print
|
603
|
+
// as opposed to the Ruby implementation.
|
604
|
+
static VALUE
|
605
|
+
inspect_node(VALUE self, VALUE source) {
|
606
|
+
pm_string_t input;
|
607
|
+
input_load_string(&input, source);
|
608
|
+
|
609
|
+
pm_parser_t parser;
|
610
|
+
pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL);
|
611
|
+
|
612
|
+
pm_node_t *node = pm_parse(&parser);
|
613
|
+
pm_buffer_t buffer = { 0 };
|
614
|
+
|
615
|
+
pm_prettyprint(&buffer, &parser, node);
|
616
|
+
|
617
|
+
rb_encoding *encoding = rb_enc_find(parser.encoding.name);
|
618
|
+
VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
|
619
|
+
|
620
|
+
pm_buffer_free(&buffer);
|
621
|
+
pm_node_destroy(&parser, node);
|
622
|
+
pm_parser_free(&parser);
|
623
|
+
|
624
|
+
return string;
|
625
|
+
}
|
626
|
+
|
557
627
|
/******************************************************************************/
|
558
628
|
/* Initialization of the extension */
|
559
629
|
/******************************************************************************/
|
@@ -596,6 +666,8 @@ Init_prism(void) {
|
|
596
666
|
rb_define_singleton_method(rb_cPrism, "lex_file", lex_file, 1);
|
597
667
|
rb_define_singleton_method(rb_cPrism, "parse", parse, -1);
|
598
668
|
rb_define_singleton_method(rb_cPrism, "parse_file", parse_file, 1);
|
669
|
+
rb_define_singleton_method(rb_cPrism, "parse_comments", parse_comments, -1);
|
670
|
+
rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, 1);
|
599
671
|
rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
|
600
672
|
rb_define_singleton_method(rb_cPrism, "parse_lex_file", parse_lex_file, 1);
|
601
673
|
|
@@ -606,6 +678,7 @@ Init_prism(void) {
|
|
606
678
|
rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1);
|
607
679
|
rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
|
608
680
|
rb_define_singleton_method(rb_cPrismDebug, "parse_serialize_file_metadata", parse_serialize_file_metadata, 2);
|
681
|
+
rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1);
|
609
682
|
|
610
683
|
// Next, initialize the other APIs.
|
611
684
|
Init_prism_api_node();
|