prism 0.19.0 → 0.24.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 +102 -1
- data/Makefile +5 -0
- data/README.md +9 -6
- data/config.yml +236 -38
- data/docs/build_system.md +19 -2
- data/docs/cruby_compilation.md +27 -0
- data/docs/parser_translation.md +34 -0
- data/docs/parsing_rules.md +19 -0
- data/docs/releasing.md +84 -16
- data/docs/ruby_api.md +1 -1
- data/docs/ruby_parser_translation.md +19 -0
- data/docs/serialization.md +19 -5
- data/ext/prism/api_node.c +1989 -1525
- data/ext/prism/extension.c +130 -30
- data/ext/prism/extension.h +2 -2
- data/include/prism/ast.h +1700 -505
- data/include/prism/defines.h +8 -0
- data/include/prism/diagnostic.h +49 -7
- data/include/prism/encoding.h +17 -0
- data/include/prism/options.h +40 -14
- data/include/prism/parser.h +34 -18
- data/include/prism/util/pm_buffer.h +9 -0
- data/include/prism/util/pm_constant_pool.h +18 -0
- data/include/prism/util/pm_newline_list.h +4 -14
- data/include/prism/util/pm_strpbrk.h +4 -1
- data/include/prism/version.h +2 -2
- data/include/prism.h +19 -2
- data/lib/prism/debug.rb +11 -5
- data/lib/prism/desugar_compiler.rb +225 -80
- data/lib/prism/dot_visitor.rb +36 -14
- data/lib/prism/dsl.rb +302 -299
- data/lib/prism/ffi.rb +107 -76
- data/lib/prism/lex_compat.rb +17 -1
- data/lib/prism/node.rb +4580 -2607
- data/lib/prism/node_ext.rb +27 -4
- data/lib/prism/parse_result.rb +75 -29
- data/lib/prism/serialize.rb +633 -305
- data/lib/prism/translation/parser/compiler.rb +1838 -0
- data/lib/prism/translation/parser/lexer.rb +335 -0
- data/lib/prism/translation/parser/rubocop.rb +45 -0
- data/lib/prism/translation/parser.rb +190 -0
- data/lib/prism/translation/parser33.rb +12 -0
- data/lib/prism/translation/parser34.rb +12 -0
- data/lib/prism/translation/ripper.rb +696 -0
- data/lib/prism/translation/ruby_parser.rb +1521 -0
- data/lib/prism/translation.rb +11 -0
- data/lib/prism.rb +1 -1
- data/prism.gemspec +18 -7
- data/rbi/prism.rbi +150 -88
- data/rbi/prism_static.rbi +15 -3
- data/sig/prism.rbs +996 -961
- data/sig/prism_static.rbs +123 -46
- data/src/diagnostic.c +264 -219
- data/src/encoding.c +21 -26
- data/src/node.c +2 -6
- data/src/options.c +29 -5
- data/src/prettyprint.c +176 -44
- data/src/prism.c +1499 -564
- data/src/serialize.c +35 -21
- data/src/token_type.c +353 -4
- data/src/util/pm_buffer.c +11 -0
- data/src/util/pm_constant_pool.c +37 -11
- data/src/util/pm_newline_list.c +6 -15
- data/src/util/pm_string.c +0 -7
- data/src/util/pm_strpbrk.c +122 -14
- metadata +16 -5
- data/docs/building.md +0 -29
- data/lib/prism/ripper_compat.rb +0 -207
data/config.yml
CHANGED
@@ -347,6 +347,8 @@ flags:
|
|
347
347
|
comment: "a call that could have been a local variable"
|
348
348
|
- name: ATTRIBUTE_WRITE
|
349
349
|
comment: "a call that is an attribute write, so the value being written should be returned"
|
350
|
+
- name: IGNORE_VISIBILITY
|
351
|
+
comment: "a call that ignores method visibility"
|
350
352
|
comment: Flags for call nodes.
|
351
353
|
- name: EncodingFlags
|
352
354
|
values:
|
@@ -368,14 +370,19 @@ flags:
|
|
368
370
|
comment: Flags for integer nodes that correspond to the base of the integer.
|
369
371
|
- name: KeywordHashNodeFlags
|
370
372
|
values:
|
371
|
-
- name:
|
372
|
-
comment: "a keyword hash which only has `AssocNode` elements all with
|
373
|
+
- name: SYMBOL_KEYS
|
374
|
+
comment: "a keyword hash which only has `AssocNode` elements all with symbol keys, which means the elements can be treated as keyword arguments"
|
373
375
|
comment: Flags for keyword hash nodes.
|
374
376
|
- name: LoopFlags
|
375
377
|
values:
|
376
378
|
- name: BEGIN_MODIFIER
|
377
379
|
comment: "a loop after a begin statement, so the body is executed first before the condition"
|
378
380
|
comment: Flags for while and until loop nodes.
|
381
|
+
- name: ParameterFlags
|
382
|
+
values:
|
383
|
+
- name: REPEATED_PARAMETER
|
384
|
+
comment: "a parameter name that has been repeated in the method signature"
|
385
|
+
comment: Flags for parameter nodes.
|
379
386
|
- name: RangeFlags
|
380
387
|
values:
|
381
388
|
- name: EXCLUDE_END
|
@@ -468,10 +475,31 @@ nodes:
|
|
468
475
|
fields:
|
469
476
|
- name: left
|
470
477
|
type: node
|
478
|
+
comment: |
|
479
|
+
Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
480
|
+
|
481
|
+
left and right
|
482
|
+
^^^^
|
483
|
+
|
484
|
+
1 && 2
|
485
|
+
^
|
471
486
|
- name: right
|
472
487
|
type: node
|
488
|
+
comment: |
|
489
|
+
Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
490
|
+
|
491
|
+
left && right
|
492
|
+
^^^^^
|
493
|
+
|
494
|
+
1 and 2
|
495
|
+
^
|
473
496
|
- name: operator_loc
|
474
497
|
type: location
|
498
|
+
comment: |
|
499
|
+
The location of the `and` keyword or the `&&` operator.
|
500
|
+
|
501
|
+
left and right
|
502
|
+
^^^
|
475
503
|
comment: |
|
476
504
|
Represents the use of the `&&` operator or the `and` keyword.
|
477
505
|
|
@@ -501,8 +529,7 @@ nodes:
|
|
501
529
|
- name: closing_loc
|
502
530
|
type: location?
|
503
531
|
comment: |
|
504
|
-
Represents an array literal. This can be a regular array using brackets or
|
505
|
-
a special array using % like %w or %i.
|
532
|
+
Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i.
|
506
533
|
|
507
534
|
[1, 2, 3]
|
508
535
|
^^^^^^^^^
|
@@ -541,10 +568,34 @@ nodes:
|
|
541
568
|
fields:
|
542
569
|
- name: key
|
543
570
|
type: node
|
571
|
+
comment: |
|
572
|
+
The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
573
|
+
|
574
|
+
{ a: b }
|
575
|
+
^
|
576
|
+
|
577
|
+
{ foo => bar }
|
578
|
+
^^^
|
579
|
+
|
580
|
+
{ def a; end => 1 }
|
581
|
+
^^^^^^^^^^
|
544
582
|
- name: value
|
545
|
-
type: node
|
583
|
+
type: node
|
584
|
+
comment: |
|
585
|
+
The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
586
|
+
|
587
|
+
{ foo => bar }
|
588
|
+
^^^
|
589
|
+
|
590
|
+
{ x: 1 }
|
591
|
+
^
|
546
592
|
- name: operator_loc
|
547
593
|
type: location?
|
594
|
+
comment: |
|
595
|
+
The location of the `=>` operator, if present.
|
596
|
+
|
597
|
+
{ foo => bar }
|
598
|
+
^^
|
548
599
|
comment: |
|
549
600
|
Represents a hash key/value pair.
|
550
601
|
|
@@ -554,8 +605,18 @@ nodes:
|
|
554
605
|
fields:
|
555
606
|
- name: value
|
556
607
|
type: node?
|
608
|
+
comment: |
|
609
|
+
The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used.
|
610
|
+
|
611
|
+
{ **foo }
|
612
|
+
^^^
|
557
613
|
- name: operator_loc
|
558
614
|
type: location
|
615
|
+
comment: |
|
616
|
+
The location of the `**` operator.
|
617
|
+
|
618
|
+
{ **x }
|
619
|
+
^^
|
559
620
|
comment: |
|
560
621
|
Represents a splat in a hash literal.
|
561
622
|
|
@@ -565,6 +626,12 @@ nodes:
|
|
565
626
|
fields:
|
566
627
|
- name: name
|
567
628
|
type: constant
|
629
|
+
comment: |
|
630
|
+
The name of the back-reference variable, including the leading `$`.
|
631
|
+
|
632
|
+
$& # name `:$&`
|
633
|
+
|
634
|
+
$+ # name `:$+`
|
568
635
|
comment: |
|
569
636
|
Represents reading a reference to a field in the previous match.
|
570
637
|
|
@@ -609,6 +676,9 @@ nodes:
|
|
609
676
|
^^^^^^^^^^
|
610
677
|
- name: BlockLocalVariableNode
|
611
678
|
fields:
|
679
|
+
- name: flags
|
680
|
+
type: flags
|
681
|
+
kind: ParameterFlags
|
612
682
|
- name: name
|
613
683
|
type: constant
|
614
684
|
comment: |
|
@@ -620,8 +690,6 @@ nodes:
|
|
620
690
|
fields:
|
621
691
|
- name: locals
|
622
692
|
type: constant[]
|
623
|
-
- name: locals_body_index
|
624
|
-
type: uint32
|
625
693
|
- name: parameters
|
626
694
|
type: node?
|
627
695
|
- name: body
|
@@ -633,10 +701,13 @@ nodes:
|
|
633
701
|
comment: |
|
634
702
|
Represents a block of ruby code.
|
635
703
|
|
636
|
-
|
637
|
-
|
704
|
+
[1, 2, 3].each { |i| puts x }
|
705
|
+
^^^^^^^^^^^^^^
|
638
706
|
- name: BlockParameterNode
|
639
707
|
fields:
|
708
|
+
- name: flags
|
709
|
+
type: flags
|
710
|
+
kind: ParameterFlags
|
640
711
|
- name: name
|
641
712
|
type: constant?
|
642
713
|
- name: name_loc
|
@@ -712,6 +783,17 @@ nodes:
|
|
712
783
|
kind: CallNodeFlags
|
713
784
|
- name: receiver
|
714
785
|
type: node?
|
786
|
+
comment: |
|
787
|
+
The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
788
|
+
|
789
|
+
foo.bar
|
790
|
+
^^^
|
791
|
+
|
792
|
+
+foo
|
793
|
+
^^^
|
794
|
+
|
795
|
+
foo + bar
|
796
|
+
^^^
|
715
797
|
- name: call_operator_loc
|
716
798
|
type: location?
|
717
799
|
- name: name
|
@@ -950,6 +1032,12 @@ nodes:
|
|
950
1032
|
fields:
|
951
1033
|
- name: name
|
952
1034
|
type: constant
|
1035
|
+
comment: |
|
1036
|
+
The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
|
1037
|
+
|
1038
|
+
@@abc # name `:@@abc`
|
1039
|
+
|
1040
|
+
@@_test # name `:@@_test`
|
953
1041
|
comment: |
|
954
1042
|
Represents referencing a class variable.
|
955
1043
|
|
@@ -1120,6 +1208,12 @@ nodes:
|
|
1120
1208
|
fields:
|
1121
1209
|
- name: name
|
1122
1210
|
type: constant
|
1211
|
+
comment: |
|
1212
|
+
The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants).
|
1213
|
+
|
1214
|
+
X # name `:X`
|
1215
|
+
|
1216
|
+
SOME_CONSTANT # name `:SOME_CONSTANT`
|
1123
1217
|
comment: |
|
1124
1218
|
Represents referencing a constant.
|
1125
1219
|
|
@@ -1164,8 +1258,6 @@ nodes:
|
|
1164
1258
|
type: node?
|
1165
1259
|
- name: locals
|
1166
1260
|
type: constant[]
|
1167
|
-
- name: locals_body_index
|
1168
|
-
type: uint32
|
1169
1261
|
- name: def_keyword_loc
|
1170
1262
|
type: location
|
1171
1263
|
- name: operator_loc
|
@@ -1407,6 +1499,12 @@ nodes:
|
|
1407
1499
|
fields:
|
1408
1500
|
- name: name
|
1409
1501
|
type: constant
|
1502
|
+
comment: |
|
1503
|
+
The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol.
|
1504
|
+
|
1505
|
+
$foo # name `:$foo`
|
1506
|
+
|
1507
|
+
$_Test # name `:$_Test`
|
1410
1508
|
comment: |
|
1411
1509
|
Represents referencing a global variable.
|
1412
1510
|
|
@@ -1440,10 +1538,28 @@ nodes:
|
|
1440
1538
|
fields:
|
1441
1539
|
- name: opening_loc
|
1442
1540
|
type: location
|
1541
|
+
comment: |
|
1542
|
+
The location of the opening brace.
|
1543
|
+
|
1544
|
+
{ a => b }
|
1545
|
+
^
|
1443
1546
|
- name: elements
|
1444
1547
|
type: node[]
|
1548
|
+
comment: |
|
1549
|
+
The elements of the hash. These can be either `AssocNode`s or `AssocSplatNode`s.
|
1550
|
+
|
1551
|
+
{ a: b }
|
1552
|
+
^^^^
|
1553
|
+
|
1554
|
+
{ **foo }
|
1555
|
+
^^^^^
|
1445
1556
|
- name: closing_loc
|
1446
1557
|
type: location
|
1558
|
+
comment: |
|
1559
|
+
The location of the closing brace.
|
1560
|
+
|
1561
|
+
{ a => b }
|
1562
|
+
^
|
1447
1563
|
comment: |
|
1448
1564
|
Represents a hash literal.
|
1449
1565
|
|
@@ -1507,14 +1623,16 @@ nodes:
|
|
1507
1623
|
- name: value
|
1508
1624
|
type: node
|
1509
1625
|
comment: |
|
1510
|
-
Represents a node that is implicitly being added to the tree but doesn't
|
1511
|
-
correspond directly to a node in the source.
|
1626
|
+
Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source.
|
1512
1627
|
|
1513
1628
|
{ foo: }
|
1514
1629
|
^^^^
|
1515
1630
|
|
1516
1631
|
{ Foo: }
|
1517
1632
|
^^^^
|
1633
|
+
|
1634
|
+
foo in { bar: }
|
1635
|
+
^^^^
|
1518
1636
|
- name: ImplicitRestNode
|
1519
1637
|
comment: |
|
1520
1638
|
Represents using a trailing comma to indicate an implicit rest parameter.
|
@@ -1709,6 +1827,12 @@ nodes:
|
|
1709
1827
|
fields:
|
1710
1828
|
- name: name
|
1711
1829
|
type: constant
|
1830
|
+
comment: |
|
1831
|
+
The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
|
1832
|
+
|
1833
|
+
@x # name `:@x`
|
1834
|
+
|
1835
|
+
@_test # name `:@_test`
|
1712
1836
|
comment: |
|
1713
1837
|
Represents referencing an instance variable.
|
1714
1838
|
|
@@ -1761,9 +1885,7 @@ nodes:
|
|
1761
1885
|
type: location
|
1762
1886
|
newline: parts
|
1763
1887
|
comment: |
|
1764
|
-
Represents a regular expression literal that contains interpolation that
|
1765
|
-
is being used in the predicate of a conditional to implicitly match
|
1766
|
-
against the last line read by an IO object.
|
1888
|
+
Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object.
|
1767
1889
|
|
1768
1890
|
if /foo #{bar} baz/ then end
|
1769
1891
|
^^^^^^^^^^^^^^^^
|
@@ -1840,6 +1962,9 @@ nodes:
|
|
1840
1962
|
^^^^
|
1841
1963
|
- name: KeywordRestParameterNode
|
1842
1964
|
fields:
|
1965
|
+
- name: flags
|
1966
|
+
type: flags
|
1967
|
+
kind: ParameterFlags
|
1843
1968
|
- name: name
|
1844
1969
|
type: constant?
|
1845
1970
|
- name: name_loc
|
@@ -1856,8 +1981,6 @@ nodes:
|
|
1856
1981
|
fields:
|
1857
1982
|
- name: locals
|
1858
1983
|
type: constant[]
|
1859
|
-
- name: locals_body_index
|
1860
|
-
type: uint32
|
1861
1984
|
- name: operator_loc
|
1862
1985
|
type: location
|
1863
1986
|
- name: opening_loc
|
@@ -1930,12 +2053,33 @@ nodes:
|
|
1930
2053
|
fields:
|
1931
2054
|
- name: name
|
1932
2055
|
type: constant
|
2056
|
+
comment: |
|
2057
|
+
The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
|
2058
|
+
|
2059
|
+
x # name `:x`
|
2060
|
+
|
2061
|
+
_Test # name `:_Test`
|
2062
|
+
|
2063
|
+
Note that this can also be an underscore followed by a number for the default block parameters.
|
2064
|
+
|
2065
|
+
_1 # name `:_1`
|
2066
|
+
|
2067
|
+
Finally, for the default `it` block parameter, the name is `0it`. This is to distinguish it from an `it` local variable that is explicitly declared.
|
2068
|
+
|
2069
|
+
it # name `:0it`
|
2070
|
+
|
1933
2071
|
- name: depth
|
1934
2072
|
type: uint32
|
2073
|
+
comment: |
|
2074
|
+
The number of visible scopes that should be searched to find the origin of this local variable.
|
2075
|
+
|
2076
|
+
foo = 1; foo # depth 0
|
2077
|
+
|
2078
|
+
bar = 2; tap { bar } # depth 1
|
2079
|
+
|
2080
|
+
The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md).
|
1935
2081
|
comment: |
|
1936
|
-
Represents reading a local variable. Note that this requires that a local
|
1937
|
-
variable of the same name has already been written to in the same scope,
|
1938
|
-
otherwise it is parsed as a method call.
|
2082
|
+
Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call.
|
1939
2083
|
|
1940
2084
|
foo
|
1941
2085
|
^^^
|
@@ -1981,9 +2125,7 @@ nodes:
|
|
1981
2125
|
- name: unescaped
|
1982
2126
|
type: string
|
1983
2127
|
comment: |
|
1984
|
-
Represents a regular expression literal used in the predicate of a
|
1985
|
-
conditional to implicitly match against the last line read by an IO
|
1986
|
-
object.
|
2128
|
+
Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object.
|
1987
2129
|
|
1988
2130
|
if /foo/i then end
|
1989
2131
|
^^^^^^
|
@@ -2021,15 +2163,13 @@ nodes:
|
|
2021
2163
|
- name: targets
|
2022
2164
|
type: node[]
|
2023
2165
|
comment: |
|
2024
|
-
Represents writing local variables using a regular expression match with
|
2025
|
-
named capture groups.
|
2166
|
+
Represents writing local variables using a regular expression match with named capture groups.
|
2026
2167
|
|
2027
2168
|
/(?<foo>bar)/ =~ baz
|
2028
2169
|
^^^^^^^^^^^^^^^^^^^^
|
2029
2170
|
- name: MissingNode
|
2030
2171
|
comment: |
|
2031
|
-
Represents a node that is missing from the source and results in a syntax
|
2032
|
-
error.
|
2172
|
+
Represents a node that is missing from the source and results in a syntax error.
|
2033
2173
|
- name: ModuleNode
|
2034
2174
|
fields:
|
2035
2175
|
- name: locals
|
@@ -2122,8 +2262,7 @@ nodes:
|
|
2122
2262
|
- name: maximum
|
2123
2263
|
type: uint8
|
2124
2264
|
comment: |
|
2125
|
-
Represents an implicit set of parameters through the use of numbered
|
2126
|
-
parameters within a block or lambda.
|
2265
|
+
Represents an implicit set of parameters through the use of numbered parameters within a block or lambda.
|
2127
2266
|
|
2128
2267
|
-> { _1 + _2 }
|
2129
2268
|
^^^^^^^^^^^^^^
|
@@ -2131,6 +2270,14 @@ nodes:
|
|
2131
2270
|
fields:
|
2132
2271
|
- name: number
|
2133
2272
|
type: uint32
|
2273
|
+
comment: |
|
2274
|
+
The (1-indexed, from the left) number of the capture group. Numbered references that would overflow a `uint32` result in a `number` of exactly `2**32 - 1`.
|
2275
|
+
|
2276
|
+
$1 # number `1`
|
2277
|
+
|
2278
|
+
$5432 # number `5432`
|
2279
|
+
|
2280
|
+
$4294967296 # number `4294967295`
|
2134
2281
|
comment: |
|
2135
2282
|
Represents reading a numbered reference to a capture in the previous match.
|
2136
2283
|
|
@@ -2138,6 +2285,9 @@ nodes:
|
|
2138
2285
|
^^
|
2139
2286
|
- name: OptionalKeywordParameterNode
|
2140
2287
|
fields:
|
2288
|
+
- name: flags
|
2289
|
+
type: flags
|
2290
|
+
kind: ParameterFlags
|
2141
2291
|
- name: name
|
2142
2292
|
type: constant
|
2143
2293
|
- name: name_loc
|
@@ -2152,6 +2302,9 @@ nodes:
|
|
2152
2302
|
end
|
2153
2303
|
- name: OptionalParameterNode
|
2154
2304
|
fields:
|
2305
|
+
- name: flags
|
2306
|
+
type: flags
|
2307
|
+
kind: ParameterFlags
|
2155
2308
|
- name: name
|
2156
2309
|
type: constant
|
2157
2310
|
- name: name_loc
|
@@ -2170,10 +2323,31 @@ nodes:
|
|
2170
2323
|
fields:
|
2171
2324
|
- name: left
|
2172
2325
|
type: node
|
2326
|
+
comment: |
|
2327
|
+
Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
2328
|
+
|
2329
|
+
left or right
|
2330
|
+
^^^^
|
2331
|
+
|
2332
|
+
1 || 2
|
2333
|
+
^
|
2173
2334
|
- name: right
|
2174
2335
|
type: node
|
2336
|
+
comment: |
|
2337
|
+
Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
2338
|
+
|
2339
|
+
left || right
|
2340
|
+
^^^^^
|
2341
|
+
|
2342
|
+
1 or 2
|
2343
|
+
^
|
2175
2344
|
- name: operator_loc
|
2176
2345
|
type: location
|
2346
|
+
comment: |
|
2347
|
+
The location of the `or` keyword or the `||` operator.
|
2348
|
+
|
2349
|
+
left or right
|
2350
|
+
^^
|
2177
2351
|
comment: |
|
2178
2352
|
Represents the use of the `||` operator or the `or` keyword.
|
2179
2353
|
|
@@ -2227,8 +2401,7 @@ nodes:
|
|
2227
2401
|
- name: rparen_loc
|
2228
2402
|
type: location
|
2229
2403
|
comment: |
|
2230
|
-
Represents the use of the `^` operator for pinning an expression in a
|
2231
|
-
pattern matching expression.
|
2404
|
+
Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
|
2232
2405
|
|
2233
2406
|
foo in ^(bar)
|
2234
2407
|
^^^^^^
|
@@ -2239,8 +2412,7 @@ nodes:
|
|
2239
2412
|
- name: operator_loc
|
2240
2413
|
type: location
|
2241
2414
|
comment: |
|
2242
|
-
Represents the use of the `^` operator for pinning a variable in a pattern
|
2243
|
-
matching expression.
|
2415
|
+
Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
|
2244
2416
|
|
2245
2417
|
foo in ^bar
|
2246
2418
|
^^^^
|
@@ -2291,10 +2463,29 @@ nodes:
|
|
2291
2463
|
kind: RangeFlags
|
2292
2464
|
- name: left
|
2293
2465
|
type: node?
|
2466
|
+
comment: |
|
2467
|
+
The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
2468
|
+
|
2469
|
+
1...
|
2470
|
+
^
|
2471
|
+
|
2472
|
+
hello...goodbye
|
2473
|
+
^^^^^
|
2294
2474
|
- name: right
|
2295
2475
|
type: node?
|
2476
|
+
comment: |
|
2477
|
+
The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
|
2478
|
+
|
2479
|
+
..5
|
2480
|
+
^
|
2481
|
+
|
2482
|
+
1...foo
|
2483
|
+
^^^
|
2484
|
+
If neither right-hand or left-hand side was included, this will be a MissingNode.
|
2296
2485
|
- name: operator_loc
|
2297
2486
|
type: location
|
2487
|
+
comment: |
|
2488
|
+
The location of the `..` or `...` operator.
|
2298
2489
|
comment: |
|
2299
2490
|
Represents the use of the `..` or `...` operators.
|
2300
2491
|
|
@@ -2338,6 +2529,9 @@ nodes:
|
|
2338
2529
|
^^^^^^
|
2339
2530
|
- name: RequiredKeywordParameterNode
|
2340
2531
|
fields:
|
2532
|
+
- name: flags
|
2533
|
+
type: flags
|
2534
|
+
kind: ParameterFlags
|
2341
2535
|
- name: name
|
2342
2536
|
type: constant
|
2343
2537
|
- name: name_loc
|
@@ -2350,6 +2544,9 @@ nodes:
|
|
2350
2544
|
end
|
2351
2545
|
- name: RequiredParameterNode
|
2352
2546
|
fields:
|
2547
|
+
- name: flags
|
2548
|
+
type: flags
|
2549
|
+
kind: ParameterFlags
|
2353
2550
|
- name: name
|
2354
2551
|
type: constant
|
2355
2552
|
comment: |
|
@@ -2397,10 +2594,12 @@ nodes:
|
|
2397
2594
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
2398
2595
|
end
|
2399
2596
|
|
2400
|
-
`Foo, *splat, Bar` are in the `exceptions` field.
|
2401
|
-
`ex` is in the `exception` field.
|
2597
|
+
`Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `exception` field.
|
2402
2598
|
- name: RestParameterNode
|
2403
2599
|
fields:
|
2600
|
+
- name: flags
|
2601
|
+
type: flags
|
2602
|
+
kind: ParameterFlags
|
2404
2603
|
- name: name
|
2405
2604
|
type: constant?
|
2406
2605
|
- name: name_loc
|
@@ -2511,8 +2710,7 @@ nodes:
|
|
2511
2710
|
- name: unescaped
|
2512
2711
|
type: string
|
2513
2712
|
comment: |
|
2514
|
-
Represents a string literal, a string contained within a `%w` list, or
|
2515
|
-
plain string content within an interpolated string.
|
2713
|
+
Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string.
|
2516
2714
|
|
2517
2715
|
"foo"
|
2518
2716
|
^^^^^
|
data/docs/build_system.md
CHANGED
@@ -53,7 +53,7 @@ Because of course those files are not part of the git repository.
|
|
53
53
|
|
54
54
|
### Building prism as part of CRuby
|
55
55
|
|
56
|
-
[This script](https://github.com/ruby/ruby/blob/
|
56
|
+
[This script](https://github.com/ruby/ruby/blob/5124f9ac7513eb590c37717337c430cb93caa151/tool/sync_default_gems.rb#L399-L422) imports prism sources in CRuby.
|
57
57
|
|
58
58
|
The script generates the templates when importing.
|
59
59
|
|
@@ -71,4 +71,21 @@ and links to `libprism.a` (to avoid exporting symbols, so no conflict when insta
|
|
71
71
|
|
72
72
|
### Building prism as part of JRuby
|
73
73
|
|
74
|
-
TODO,
|
74
|
+
TODO, similar to TruffleRuby.
|
75
|
+
|
76
|
+
### Building prism from source as a C library
|
77
|
+
|
78
|
+
All of the source files match `src/**/*.c` and all of the headers match `include/**/*.h`.
|
79
|
+
|
80
|
+
If you want to build prism as a shared library and link against it, you should compile with:
|
81
|
+
|
82
|
+
* `-fPIC -shared` - Compile as a shared library
|
83
|
+
* `-DPRISM_EXPORT_SYMBOLS` - Export the symbols (by default nothing is exported)
|
84
|
+
|
85
|
+
#### Flags
|
86
|
+
|
87
|
+
`make` respects the `MAKEFLAGS` environment variable. As such, to speed up the build you can run:
|
88
|
+
|
89
|
+
```
|
90
|
+
MAKEFLAGS="-j10" bundle exec rake compile
|
91
|
+
```
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Compiling Prism's AST
|
2
|
+
|
3
|
+
One important class of consumers of Prism's AST is compilers. Currently [CRuby](https://github.com/ruby/ruby), [JRuby](https://github.com/jruby/jruby), [TruffleRuby](https://github.com/oracle/truffleruby), and [Natalie](https://github.com/natalie-lang/natalie) have all built compilation code on top of Prism's AST.
|
4
|
+
|
5
|
+
This document will describe, at a high level, how CRuby's compilation of Prism's AST works.
|
6
|
+
|
7
|
+
As described in the [build system documentation](build_system.md), there is a "push" Webhook set up within the Prism repo triggered on each new commit to send information about the commit to [git.ruby-lang.org](https://github.com/ruby/git.ruby-lang.org). This in turn runs [a script](https://github.com/ruby/ruby/blob/master/tool/sync_default_gems.rb) to sync over new changes in Prism to their corresponding files in Ruby. Any failures in this sync script will show alerts in the #alerts-sync channel in the RubyLang Slack. The result of this step is that files are synced from Prism into ruby/ruby for its use. It is also worth noting that [`common.mk`](https://github.com/ruby/ruby/blob/master/common.mk) contains a list of Prism files which it needs to correctly compile. If there are new Prism files added, this file should also be updated.
|
8
|
+
|
9
|
+
ruby/ruby uses the Prism code to generate an AST from which it can generate instruction sequences. Compilation in ruby/ruby has three main steps:
|
10
|
+
|
11
|
+
1. Compute an AST
|
12
|
+
|
13
|
+
Syncing over the Prism code allows ruby/ruby to compute the AST using Prism. It currently does this within [`iseq.c`](https://github.com/ruby/ruby/blob/master/iseq.c) using the `pm_parser_init` fuction.
|
14
|
+
|
15
|
+
2. Run a first pass of compilation
|
16
|
+
|
17
|
+
Once the AST has been created, it is recursively descended in order to compute the appropriate instruction sequences. This is the crux of compilation, and we go into more detail about nuances in the following paragraphs.
|
18
|
+
|
19
|
+
The code for this step is almost exclusively in [`prism_compile.c`](https://github.com/ruby/ruby/blob/master/prism_compile.c). The main function used for compilation is `pm_compile_node` which is essentially a huge switch statement over practically every node type which computes the appropriate instruction sequences for that node type. There are several convenience helpers, such as `PM_COMPILE`, `PM_COMPILE_POPPED`, `PM_COMPILE_NOT_POPPED` which all call into the `pm_compile_node` function.
|
20
|
+
|
21
|
+
There are also several functions, like `parse_string`, `parse_integer` which consume Prism nodes and return CRuby values. These are all called for their relevant types within the big switch statement.
|
22
|
+
|
23
|
+
The Prism compiler also uses a concept of "scope nodes" which are not standard Prism nodes in the AST, but instead nodes constructed within the compiler for the sole purpose of making compilation easier. Scope nodes are defined in [`prism_compile.h`](https://github.com/ruby/ruby/blob/master/prism_compile.h) and store information such as locals, local table size, local depth offset and the index lookup tables. Scope nodes can be generated for node types which have their own "scope".
|
24
|
+
|
25
|
+
3. Run an optimization pass of compilation
|
26
|
+
|
27
|
+
After the instruction sequences are initially computed, there is an existing (non-Prism based) optimization pass of the instruction sequences. There are several optimizations currently inlined into step 2, however, most of them happen in this step. Specifically, any peephole optimizations happen in this step. By the end of step 2, however, the instruction sequences take the same form regardless of if the initial AST was generated by Prism or not. Therefore, step 3 is agnostic to the parser, and should not require any Prism specific code.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# parser translation
|
2
|
+
|
3
|
+
Prism ships with the ability to translate its syntax tree into the syntax tree used by the [whitequark/parser](https://github.com/whitequark/parser) gem. This allows you to use tools built on top of the `parser` gem with the `prism` parser.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
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
|
+
|
9
|
+
You can use the `prism` parser like you would any other. After requiring the parser, you should be able to call any of the regular `Parser::Base` APIs that you would normally use.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require "prism"
|
13
|
+
|
14
|
+
Prism::Translation::Parser.parse_file("path/to/file.rb")
|
15
|
+
```
|
16
|
+
|
17
|
+
### RuboCop
|
18
|
+
|
19
|
+
To run RuboCop using the `prism` gem as the parser, you will need to require the `prism/translation/parser/rubocop` file. This file injects `prism` into the known options for both `rubocop` and `rubocop-ast`, such that you can specify it in your `.rubocop.yml` file. Unfortunately `rubocop` doesn't support any direct way to do this, so we have to get a bit hacky.
|
20
|
+
|
21
|
+
First, set the `TargetRubyVersion` in your RuboCop configuration file to `80_82_73_83_77.33`. This is the version of Ruby that `prism` reports itself as. (The leading numbers are the ASCII values for `PRISM`.)
|
22
|
+
|
23
|
+
```yaml
|
24
|
+
AllCops:
|
25
|
+
TargetRubyVersion: 80_82_73_83_77.33
|
26
|
+
```
|
27
|
+
|
28
|
+
Now when you run `rubocop` you will need to require the `prism/translation/parser/rubocop` file before executing so that it can inject the `prism` parser into the known options.
|
29
|
+
|
30
|
+
```
|
31
|
+
bundle exec ruby -rprism/translation/parser/rubocop $(bundle exec which rubocop)
|
32
|
+
```
|
33
|
+
|
34
|
+
This should run RuboCop using the `prism` parser.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Rules
|
2
|
+
|
3
|
+
This document contains information related to the rules of the parser for Ruby source code.
|
4
|
+
|
5
|
+
As an example, in the documentation of many of the fields of nodes, it's mentioned that a field follows the lexing rules for `identifier` or `constant`. This document describes what those rules are.
|
6
|
+
|
7
|
+
## Constants
|
8
|
+
|
9
|
+
Constants in Ruby begin with an upper-case letter. This is followed by any number of underscores, alphanumeric, or non-ASCII characters. The definition of "alphanumeric" and "upper-case letter" are encoding-dependent.
|
10
|
+
|
11
|
+
## Non-void expression
|
12
|
+
|
13
|
+
Most expressions in CRuby are non-void. This means the expression they represent resolves to a value. For example, `1 + 2` is a non-void expression, because it resolves to a method call. Even things like `class Foo; end` is a non-void expression, because it returns the last evaluated expression in the body of the class (or `nil`).
|
14
|
+
|
15
|
+
Certain nodes, however, are void expressions, and cannot be combined to form larger expressions. For example, `BEGIN {}`, `END {}`, `alias foo bar`, and `undef foo`.
|
16
|
+
|
17
|
+
## Identifiers
|
18
|
+
|
19
|
+
Identifiers in Ruby begin with an underscore or lower-case letter. This is followed by any number of underscores, alphanumeric, or non-ASCII characters. The definition of "alphanumeric" and "lower-case letter" are encoding-dependent.
|