prism 0.19.0 → 0.24.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 +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/lib/prism/node_ext.rb
    CHANGED
    
    | @@ -81,7 +81,7 @@ module Prism | |
| 81 81 | 
             
              class RationalNode < Node
         | 
| 82 82 | 
             
                # Returns the value of the node as a Ruby Rational.
         | 
| 83 83 | 
             
                def value
         | 
| 84 | 
            -
                  Rational(slice.chomp("r"))
         | 
| 84 | 
            +
                  Rational(numeric.is_a?(IntegerNode) ? numeric.value : slice.chomp("r"))
         | 
| 85 85 | 
             
                end
         | 
| 86 86 | 
             
              end
         | 
| 87 87 |  | 
| @@ -94,7 +94,7 @@ module Prism | |
| 94 94 |  | 
| 95 95 | 
             
                # Returns the full name of this constant. For example: "Foo"
         | 
| 96 96 | 
             
                def full_name
         | 
| 97 | 
            -
                  name. | 
| 97 | 
            +
                  name.to_s
         | 
| 98 98 | 
             
                end
         | 
| 99 99 | 
             
              end
         | 
| 100 100 |  | 
| @@ -118,7 +118,7 @@ module Prism | |
| 118 118 | 
             
                    current = current.parent
         | 
| 119 119 | 
             
                  end
         | 
| 120 120 |  | 
| 121 | 
            -
                   | 
| 121 | 
            +
                  if !current.is_a?(ConstantReadNode) && !current.nil?
         | 
| 122 122 | 
             
                    raise DynamicPartsInConstantPathError, "Constant path contains dynamic parts. Cannot compute full name"
         | 
| 123 123 | 
             
                  end
         | 
| 124 124 |  | 
| @@ -135,7 +135,17 @@ module Prism | |
| 135 135 | 
             
                # Returns the list of parts for the full name of this constant path.
         | 
| 136 136 | 
             
                # For example: [:Foo, :Bar]
         | 
| 137 137 | 
             
                def full_name_parts
         | 
| 138 | 
            -
                   | 
| 138 | 
            +
                  parts = case parent
         | 
| 139 | 
            +
                  when ConstantPathNode, ConstantReadNode
         | 
| 140 | 
            +
                    parent.full_name_parts
         | 
| 141 | 
            +
                  when nil
         | 
| 142 | 
            +
                    [:""]
         | 
| 143 | 
            +
                  else
         | 
| 144 | 
            +
                    raise ConstantPathNode::DynamicPartsInConstantPathError,
         | 
| 145 | 
            +
                      "Constant path target contains dynamic parts. Cannot compute full name"
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                  parts.push(child.name)
         | 
| 139 149 | 
             
                end
         | 
| 140 150 |  | 
| 141 151 | 
             
                # Returns the full name of this constant path. For example: "Foo::Bar"
         | 
| @@ -144,6 +154,19 @@ module Prism | |
| 144 154 | 
             
                end
         | 
| 145 155 | 
             
              end
         | 
| 146 156 |  | 
| 157 | 
            +
              class ConstantTargetNode < Node
         | 
| 158 | 
            +
                # Returns the list of parts for the full name of this constant.
         | 
| 159 | 
            +
                # For example: [:Foo]
         | 
| 160 | 
            +
                def full_name_parts
         | 
| 161 | 
            +
                  [name]
         | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                # Returns the full name of this constant. For example: "Foo"
         | 
| 165 | 
            +
                def full_name
         | 
| 166 | 
            +
                  name.to_s
         | 
| 167 | 
            +
                end
         | 
| 168 | 
            +
              end
         | 
| 169 | 
            +
             | 
| 147 170 | 
             
              class ParametersNode < Node
         | 
| 148 171 | 
             
                # Mirrors the Method#parameters method.
         | 
| 149 172 | 
             
                def signature
         | 
    
        data/lib/prism/parse_result.rb
    CHANGED
    
    | @@ -9,18 +9,16 @@ module Prism | |
| 9 9 | 
             
                attr_reader :source
         | 
| 10 10 |  | 
| 11 11 | 
             
                # The line number where this source starts.
         | 
| 12 | 
            -
                 | 
| 12 | 
            +
                attr_reader :start_line
         | 
| 13 13 |  | 
| 14 14 | 
             
                # The list of newline byte offsets in the source code.
         | 
| 15 15 | 
             
                attr_reader :offsets
         | 
| 16 16 |  | 
| 17 | 
            -
                # Create a new source object with the given source code | 
| 18 | 
            -
                 | 
| 19 | 
            -
                # the source code.
         | 
| 20 | 
            -
                def initialize(source, start_line = 1, offsets = compute_offsets(source))
         | 
| 17 | 
            +
                # Create a new source object with the given source code.
         | 
| 18 | 
            +
                def initialize(source, start_line = 1, offsets = [])
         | 
| 21 19 | 
             
                  @source = source
         | 
| 22 | 
            -
                  @start_line = start_line
         | 
| 23 | 
            -
                  @offsets = offsets
         | 
| 20 | 
            +
                  @start_line = start_line # set after parsing is done
         | 
| 21 | 
            +
                  @offsets = offsets # set after parsing is done
         | 
| 24 22 | 
             
                end
         | 
| 25 23 |  | 
| 26 24 | 
             
                # Perform a byteslice on the source code using the given byte offset and
         | 
| @@ -56,6 +54,23 @@ module Prism | |
| 56 54 | 
             
                  character_offset(byte_offset) - character_offset(line_start(byte_offset))
         | 
| 57 55 | 
             
                end
         | 
| 58 56 |  | 
| 57 | 
            +
                # Returns the offset from the start of the file for the given byte offset
         | 
| 58 | 
            +
                # counting in code units for the given encoding.
         | 
| 59 | 
            +
                #
         | 
| 60 | 
            +
                # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
         | 
| 61 | 
            +
                # concept of code units that differs from the number of characters in other
         | 
| 62 | 
            +
                # encodings, it is not captured here.
         | 
| 63 | 
            +
                def code_units_offset(byte_offset, encoding)
         | 
| 64 | 
            +
                  byteslice = source.byteslice(0, byte_offset).encode(encoding)
         | 
| 65 | 
            +
                  (encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # Returns the column number in code units for the given encoding for the
         | 
| 69 | 
            +
                # given byte offset.
         | 
| 70 | 
            +
                def code_units_column(byte_offset, encoding)
         | 
| 71 | 
            +
                  code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 59 74 | 
             
                private
         | 
| 60 75 |  | 
| 61 76 | 
             
                # Binary search through the offsets to find the line number for the given
         | 
| @@ -77,21 +92,14 @@ module Prism | |
| 77 92 |  | 
| 78 93 | 
             
                  left - 1
         | 
| 79 94 | 
             
                end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                # Find all of the newlines in the source code and return their byte offsets
         | 
| 82 | 
            -
                # from the start of the string an array.
         | 
| 83 | 
            -
                def compute_offsets(code)
         | 
| 84 | 
            -
                  offsets = [0]
         | 
| 85 | 
            -
                  code.b.scan("\n") { offsets << $~.end(0) }
         | 
| 86 | 
            -
                  offsets
         | 
| 87 | 
            -
                end
         | 
| 88 95 | 
             
              end
         | 
| 89 96 |  | 
| 90 97 | 
             
              # This represents a location in the source.
         | 
| 91 98 | 
             
              class Location
         | 
| 92 99 | 
             
                # A Source object that is used to determine more information from the given
         | 
| 93 100 | 
             
                # offset and length.
         | 
| 94 | 
            -
                 | 
| 101 | 
            +
                attr_reader :source
         | 
| 102 | 
            +
                protected :source
         | 
| 95 103 |  | 
| 96 104 | 
             
                # The byte offset from the beginning of the source where this location
         | 
| 97 105 | 
             
                # starts.
         | 
| @@ -137,6 +145,11 @@ module Prism | |
| 137 145 | 
             
                  source.character_offset(start_offset)
         | 
| 138 146 | 
             
                end
         | 
| 139 147 |  | 
| 148 | 
            +
                # The offset from the start of the file in code units of the given encoding.
         | 
| 149 | 
            +
                def start_code_units_offset(encoding = Encoding::UTF_16LE)
         | 
| 150 | 
            +
                  source.code_units_offset(start_offset, encoding)
         | 
| 151 | 
            +
                end
         | 
| 152 | 
            +
             | 
| 140 153 | 
             
                # The byte offset from the beginning of the source where this location ends.
         | 
| 141 154 | 
             
                def end_offset
         | 
| 142 155 | 
             
                  start_offset + length
         | 
| @@ -148,6 +161,11 @@ module Prism | |
| 148 161 | 
             
                  source.character_offset(end_offset)
         | 
| 149 162 | 
             
                end
         | 
| 150 163 |  | 
| 164 | 
            +
                # The offset from the start of the file in code units of the given encoding.
         | 
| 165 | 
            +
                def end_code_units_offset(encoding = Encoding::UTF_16LE)
         | 
| 166 | 
            +
                  source.code_units_offset(end_offset, encoding)
         | 
| 167 | 
            +
                end
         | 
| 168 | 
            +
             | 
| 151 169 | 
             
                # The line number where this location starts.
         | 
| 152 170 | 
             
                def start_line
         | 
| 153 171 | 
             
                  source.line(start_offset)
         | 
| @@ -176,6 +194,12 @@ module Prism | |
| 176 194 | 
             
                  source.character_column(start_offset)
         | 
| 177 195 | 
             
                end
         | 
| 178 196 |  | 
| 197 | 
            +
                # The column number in code units of the given encoding where this location
         | 
| 198 | 
            +
                # starts from the start of the line.
         | 
| 199 | 
            +
                def start_code_units_column(encoding = Encoding::UTF_16LE)
         | 
| 200 | 
            +
                  source.code_units_column(start_offset, encoding)
         | 
| 201 | 
            +
                end
         | 
| 202 | 
            +
             | 
| 179 203 | 
             
                # The column number in bytes where this location ends from the start of the
         | 
| 180 204 | 
             
                # line.
         | 
| 181 205 | 
             
                def end_column
         | 
| @@ -188,6 +212,12 @@ module Prism | |
| 188 212 | 
             
                  source.character_column(end_offset)
         | 
| 189 213 | 
             
                end
         | 
| 190 214 |  | 
| 215 | 
            +
                # The column number in code units of the given encoding where this location
         | 
| 216 | 
            +
                # ends from the start of the line.
         | 
| 217 | 
            +
                def end_code_units_column(encoding = Encoding::UTF_16LE)
         | 
| 218 | 
            +
                  source.code_units_column(end_offset, encoding)
         | 
| 219 | 
            +
                end
         | 
| 220 | 
            +
             | 
| 191 221 | 
             
                # Implement the hash pattern matching interface for Location.
         | 
| 192 222 | 
             
                def deconstruct_keys(keys)
         | 
| 193 223 | 
             
                  { start_offset: start_offset, end_offset: end_offset }
         | 
| @@ -312,20 +342,24 @@ module Prism | |
| 312 342 | 
             
                # A Location object representing the location of this error in the source.
         | 
| 313 343 | 
             
                attr_reader :location
         | 
| 314 344 |  | 
| 345 | 
            +
                # The level of this error.
         | 
| 346 | 
            +
                attr_reader :level
         | 
| 347 | 
            +
             | 
| 315 348 | 
             
                # Create a new error object with the given message and location.
         | 
| 316 | 
            -
                def initialize(message, location)
         | 
| 349 | 
            +
                def initialize(message, location, level)
         | 
| 317 350 | 
             
                  @message = message
         | 
| 318 351 | 
             
                  @location = location
         | 
| 352 | 
            +
                  @level = level
         | 
| 319 353 | 
             
                end
         | 
| 320 354 |  | 
| 321 355 | 
             
                # Implement the hash pattern matching interface for ParseError.
         | 
| 322 356 | 
             
                def deconstruct_keys(keys)
         | 
| 323 | 
            -
                  { message: message, location: location }
         | 
| 357 | 
            +
                  { message: message, location: location, level: level }
         | 
| 324 358 | 
             
                end
         | 
| 325 359 |  | 
| 326 360 | 
             
                # Returns a string representation of this error.
         | 
| 327 361 | 
             
                def inspect
         | 
| 328 | 
            -
                  "#<Prism::ParseError @message=#{@message.inspect} @location=#{@location.inspect}>"
         | 
| 362 | 
            +
                  "#<Prism::ParseError @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
         | 
| 329 363 | 
             
                end
         | 
| 330 364 | 
             
              end
         | 
| 331 365 |  | 
| @@ -337,20 +371,24 @@ module Prism | |
| 337 371 | 
             
                # A Location object representing the location of this warning in the source.
         | 
| 338 372 | 
             
                attr_reader :location
         | 
| 339 373 |  | 
| 374 | 
            +
                # The level of this warning.
         | 
| 375 | 
            +
                attr_reader :level
         | 
| 376 | 
            +
             | 
| 340 377 | 
             
                # Create a new warning object with the given message and location.
         | 
| 341 | 
            -
                def initialize(message, location)
         | 
| 378 | 
            +
                def initialize(message, location, level)
         | 
| 342 379 | 
             
                  @message = message
         | 
| 343 380 | 
             
                  @location = location
         | 
| 381 | 
            +
                  @level = level
         | 
| 344 382 | 
             
                end
         | 
| 345 383 |  | 
| 346 384 | 
             
                # Implement the hash pattern matching interface for ParseWarning.
         | 
| 347 385 | 
             
                def deconstruct_keys(keys)
         | 
| 348 | 
            -
                  { message: message, location: location }
         | 
| 386 | 
            +
                  { message: message, location: location, level: level }
         | 
| 349 387 | 
             
                end
         | 
| 350 388 |  | 
| 351 389 | 
             
                # Returns a string representation of this warning.
         | 
| 352 390 | 
             
                def inspect
         | 
| 353 | 
            -
                  "#<Prism::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect}>"
         | 
| 391 | 
            +
                  "#<Prism::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect} @level=#{@level.inspect}>"
         | 
| 354 392 | 
             
                end
         | 
| 355 393 | 
             
              end
         | 
| 356 394 |  | 
| @@ -369,9 +407,9 @@ module Prism | |
| 369 407 | 
             
                # The list of magic comments that were encountered during parsing.
         | 
| 370 408 | 
             
                attr_reader :magic_comments
         | 
| 371 409 |  | 
| 372 | 
            -
                # An optional location that represents the location of the  | 
| 373 | 
            -
                #  | 
| 374 | 
            -
                # file being parsed is the main file being executed.
         | 
| 410 | 
            +
                # An optional location that represents the location of the __END__ marker
         | 
| 411 | 
            +
                # and the rest of the content of the file. This content is loaded into the
         | 
| 412 | 
            +
                # DATA constant when the file being parsed is the main file being executed.
         | 
| 375 413 | 
             
                attr_reader :data_loc
         | 
| 376 414 |  | 
| 377 415 | 
             
                # The list of errors that were generated during parsing.
         | 
| @@ -414,17 +452,19 @@ module Prism | |
| 414 452 |  | 
| 415 453 | 
             
              # This represents a token from the Ruby source.
         | 
| 416 454 | 
             
              class Token
         | 
| 455 | 
            +
                # The Source object that represents the source this token came from.
         | 
| 456 | 
            +
                attr_reader :source
         | 
| 457 | 
            +
                private :source
         | 
| 458 | 
            +
             | 
| 417 459 | 
             
                # The type of token that this token is.
         | 
| 418 460 | 
             
                attr_reader :type
         | 
| 419 461 |  | 
| 420 462 | 
             
                # A byteslice of the source that this token represents.
         | 
| 421 463 | 
             
                attr_reader :value
         | 
| 422 464 |  | 
| 423 | 
            -
                # A Location object representing the location of this token in the source.
         | 
| 424 | 
            -
                attr_reader :location
         | 
| 425 | 
            -
             | 
| 426 465 | 
             
                # Create a new token object with the given type, value, and location.
         | 
| 427 | 
            -
                def initialize(type, value, location)
         | 
| 466 | 
            +
                def initialize(source, type, value, location)
         | 
| 467 | 
            +
                  @source = source
         | 
| 428 468 | 
             
                  @type = type
         | 
| 429 469 | 
             
                  @value = value
         | 
| 430 470 | 
             
                  @location = location
         | 
| @@ -435,6 +475,12 @@ module Prism | |
| 435 475 | 
             
                  { type: type, value: value, location: location }
         | 
| 436 476 | 
             
                end
         | 
| 437 477 |  | 
| 478 | 
            +
                # A Location object representing the location of this token in the source.
         | 
| 479 | 
            +
                def location
         | 
| 480 | 
            +
                  return @location if @location.is_a?(Location)
         | 
| 481 | 
            +
                  @location = Location.new(source, @location >> 32, @location & 0xFFFFFFFF)
         | 
| 482 | 
            +
                end
         | 
| 483 | 
            +
             | 
| 438 484 | 
             
                # Implement the pretty print interface for Token.
         | 
| 439 485 | 
             
                def pretty_print(q)
         | 
| 440 486 | 
             
                  q.group do
         |