prism 0.15.1 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- 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();
|