Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruby tree deserialization error on valid programme #448

Open
jamesrweb opened this issue Dec 5, 2023 · 7 comments
Open

Ruby tree deserialization error on valid programme #448

jamesrweb opened this issue Dec 5, 2023 · 7 comments

Comments

@jamesrweb
Copy link

  • Ruby version: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin23]
  • Rubyfmt git sha: rubyfmt-main 0.10.0

Ruby executes the code perfectly fine and outputs the correct values but rubyfmt cannot format the document.

Input file

# @param [String] filename
#
# @return [Array<String>]
def read_lines_from_file(filename)
  File.open(filename, 'r', chomp: true)
end

# @param [Hash<Integer>] folder_sizes
# @param [Array<String>] stack
# @param [String] line
#
# @return [Array<Hash<Integer>, Array<String>>]
def parse_instruction(folder_sizes, stack, line)
  if line in ['$', 'cd', '..']
    stack.pop
  elsif line in ['$', 'cd', folder]
    stack.push folder
  elsif line in [size, _] and size.match?(/^\d+$/)
    stack.reduce('') do |previous_path, current_path|
      path_key = previous_path + current_path

      folder_sizes[path_key] += size.to_i

      path_key
    end
  end

  [folder_sizes, stack]
end

# @param [Array<Hash<Integer>, Array<String>>] accumulator
# @param [String] line
#
# @return [Array<Hash<Integer>, Array<String>>]
def instruction_accumulator(accumulator, line)
  folder_sizes, stack = accumulator

  parse_instruction(folder_sizes, stack, line)
end

# @param [Array<String>] instructions
#
# @return [Hash<Integer>]
def folder_sizes_from_instructions(instructions)
  instructions
    .map(&:split)
    .reduce([Hash.new(0), []], &method(:instruction_accumulator))
    .shift
end

# @param [Hash<Integer>] folder_sizes
#
# @return [Integer]
def solve_part_one(folder_sizes)
  size_limit = 100_000

  folder_sizes.values.select { |folder_size| folder_size <= size_limit }.sum
end

# @param [Hash<Integer>] folder_sizes
#
# @return [Integer]
def solve_part_two(folder_sizes)
  total_disk_space = 70_000_000
  minimum_unused_space_requirement = 30_000_000
  difference = total_disk_space - minimum_unused_space_requirement

  folder_sizes
    .values
    .reject { |folder_size| folder_size < folder_sizes['/'] - difference }
    .min
end

def main
  instructions = read_lines_from_file(__dir__ + '/input.txt')
  folder_sizes = folder_sizes_from_instructions(instructions)

  puts 'Part one: ' + solve_part_one(folder_sizes).to_s
  puts 'Part two: ' + solve_part_two(folder_sizes).to_s
end

main

Rubyfmt's output

Error! source: <redacted>/index.rb

!!! Ruby Tree Deserialization Error !!!

Rubyfmt failed to correctly deserialize a tree from ripper. This is a bug that needs to be reported.
File a bug report at https://github.com/penelopezone/rubyfmt/issues/new.
Ideally you would include the full source code of the program you ran rubyfmt with.
If you can't do that for some reason, the best thing you can do is rerun rubyfmt on this program
with the debug binary with `2>log_file` on the end and then send us the log file that gets generated.

This breaks because

Rubyfmt failed to correctly deserialize a tree from ripper. (What is ripper even?)

@reese
Copy link
Collaborator

reese commented Dec 5, 2023

I believe this is a dup of #447

@jamesrweb
Copy link
Author

jamesrweb commented Dec 5, 2023

I believe this is a dup of #447

Actually no, I believe this is similar but different in that, it fails on THIS file specifically but not on 2 others with similar constructs in place. Ruby runs all 3 perfectly fine.

If you want to mark it as a duplicate, you can, but it is still unique in my case to this code sample specifically.

@reese
Copy link
Collaborator

reese commented Dec 5, 2023

What do you mean by "with similar constructs"? My point in calling this a duplicate is that all the individual expression types represented by this file are marked as bugs in other places: #447 for and expressions and #399/#325 for pattern matching. If there are additional constructs in those other files you're referencing, then this may be distinct, but I'd need some additional information there.

@jamesrweb
Copy link
Author

What do you mean by "with similar constructs"? My point in calling this a duplicate is that all the individual expression types represented by this file are marked as bugs in other places: #447 for and expressions and #399/#325 for pattern matching. If there are additional constructs in those other files you're referencing, then this may be distinct, but I'd need some additional information there.

I mean the way to load and parse the files and output is roughly similar in those other files.

As I said, up to you, I appreciate the tool either way, just strange how it failed for this one. ☺️

@pjg
Copy link

pjg commented Dec 13, 2023

Side question, are you considering switching to prism from ripper for ruby parsing?

@reese
Copy link
Collaborator

reese commented Dec 14, 2023

Switching to prism would be great (largely because right now we have to have a whole Ruby checkout just to build Ripper, and just having prism on its own would make getting development way more lightweight), but it's also pretty far down on the priority list at the moment compared to getting things feature-complete for Ruby 3, fixing bugs, etc.

@jamesrweb
Copy link
Author

@reese what's the current plan for this? Is there a roadmap for prism or anything else we could use to resolve the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants