<commit_before>UNNAMED_BLOCK = '__unnamed_block'

if RUBY_PLATFORM == 'opal'
  def gets
  end

  def puts *args
    if args.size > 0
      $stdout.write args.map { |arg|
        arg_to_s = "#{arg}"
        arg_to_s + (arg_to_s.end_with?("\n") ? "" : "\n")
      }.join
    else
      $stdout.write "\n"
    end
  end

  def p *args
    args.each do |arg|
      $stdout.write arg.inspect + "\n"
    end
    case args.size
      when 0 then nil
      when 1 then args[0]
      else args
    end
  end
end

$console_texts = []
$is_capturing_output = false
class <<$stdout
  alias :old_write :write
  def write *args
    if $is_capturing_output
      $console_texts = $console_texts.clone +
        args.map { |arg| [:stdout, "#{arg}"] }
    else
      old_write *args
    end
  end
end
class <<$stderr
  alias :old_write :write
  def write *args
    if $is_capturing_output
      $console_texts = $console_texts.clone +
        args.map { |arg| [:stderr, "#{arg}"] }
    else
      old_write *args
    end
  end
end

class String
  def <<(*args)
    self + args.map { |arg| "#{arg}" }.join
  end
end

class ProgramTerminated < RuntimeError
  attr_reader :cause
  def initialize(cause)
    @cause = cause
  end
end

class BytecodeInterpreter
  def initialize
    @partial_calls = []
    @num_partial_call_executing = nil
    @result = [] # a stack with 0 or 1 items in it
    @vars_stack = [{}]
    @main = (RUBY_PLATFORM == 'opal') ?
      `Opal.top` : TOPLEVEL_BINDING.eval('self')
    @accepting_input = false
    @accepted_input = nil
    @rescue_labels = []
      # list of tuples:
        # [0] label
        # [1] stack_size1 is with counting pop_next_one_too_on_return
        # [2] stack_size2 is when you don't count pop_next_one_too_on_return
        # [3] pc_size means partial_calls
        # [4] pending_var_names: so pending vars from start_vars get reset
    # path, method, line, col, pop_next_one_too_on_return
    @method_stack = [['Runtime', '<main>', nil, nil, false]]
    $console_texts = []
    begin raise ''; rescue; end # set $! to RuntimeError.new('')
  end

  def visible_state
    used_object_ids = [] # show closure variables only once
    {
      partial_calls: @partial_calls.map { |call| call.clone },
      vars_stack: @vars_stack.map do |vars|
        vars.reject do |name, tuple|
          if used_object_ids.include? tuple.object_id
            true
          else
            used_object_ids.push tuple.object_id
            false
          end
        end
      end,
      output: $console_texts,
      num_partial_call_executing: @num_partial_call_executing,
      accepting_input: @accepting_input,
    }
  end

  def is_accepting_input?<commit_msg>Include result in interpreters.visible_state for debug.rb's inspect command.<commit_after>UNNAMED_BLOCK = '__unnamed_block'

if RUBY_PLATFORM == 'opal'
  def gets
  end

  def puts *args
    if args.size > 0
      $stdout.write args.map { |arg|
        arg_to_s = "#{arg}"
        arg_to_s + (arg_to_s.end_with?("\n") ? "" : "\n")
      }.join
    else
      $stdout.write "\n"
    end
  end

  def p *args
    args.each do |arg|
      $stdout.write arg.inspect + "\n"
    end
    case args.size
      when 0 then nil
      when 1 then args[0]
      else args
    end
  end
end

$console_texts = []
$is_capturing_output = false
class <<$stdout
  alias :old_write :write
  def write *args
    if $is_capturing_output
      $console_texts = $console_texts.clone +
        args.map { |arg| [:stdout, "#{arg}"] }
    else
      old_write *args
    end
  end
end
class <<$stderr
  alias :old_write :write
  def write *args
    if $is_capturing_output
      $console_texts = $console_texts.clone +
        args.map { |arg| [:stderr, "#{arg}"] }
    else
      old_write *args
    end
  end
end

class String
  def <<(*args)
    self + args.map { |arg| "#{arg}" }.join
  end
end

class ProgramTerminated < RuntimeError
  attr_reader :cause
  def initialize(cause)
    @cause = cause
  end
end

class BytecodeInterpreter
  def initialize
    @partial_calls = []
    @num_partial_call_executing = nil
    @result = [] # a stack with 0 or 1 items in it
    @vars_stack = [{}]
    @main = (RUBY_PLATFORM == 'opal') ?
      `Opal.top` : TOPLEVEL_BINDING.eval('self')
    @accepting_input = false
    @accepted_input = nil
    @rescue_labels = []
      # list of tuples:
        # [0] label
        # [1] stack_size1 is with counting pop_next_one_too_on_return
        # [2] stack_size2 is when you don't count pop_next_one_too_on_return
        # [3] pc_size means partial_calls
        # [4] pending_var_names: so pending vars from start_vars get reset
    # path, method, line, col, pop_next_one_too_on_return
    @method_stack = [['Runtime', '<main>', nil, nil, false]]
    $console_texts = []
    begin raise ''; rescue; end # set $! to RuntimeError.new('')
  end

  def visible_state
    used_object_ids = [] # show closure variables only once
    {
      partial_calls: @partial_calls.map { |call| call.clone },
      vars_stack: @vars_stack.map do |vars|
        vars.reject do |name, tuple|
          if used_object_ids.include? tuple.object_id
            true
          else
            used_object_ids.push tuple.object_id
            false
          end
        end
      end,
      output: $console_texts,
      num_partial_call_executing: @num_partial_call_executing,
      accepting_input: @accepting_input,
      result: @result,
    }
  end

  def is_accepting_input?
{'fraction_non_alphanumeric': 0.10571637962623671, 'fraction_numerical': 0.004763649688530597, 'mean_word_length': 2.4837268666241226, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '212863', 'n_tokens_mistral': 1913, 'n_tokens_neox': 1878, 'n_words': 492}