<commit_before>module Orbacle
  class TypingService
    class NominalType < Struct.new(:name)
      def each_possible_type
        yield self
      end

      def pretty
        name
      end
    end
    class ClassType < Struct.new(:name)
      def each_possible_type
        yield self
      end

      def pretty
        "class(#{name})"
      end
    end
    class MainType
      def each_possible_type
      end

      def pretty
        "main"
      end

      def ==(other)
        self.class == other.class
      end
    end
    class UnionType < Struct.new(:types)
      def each_possible_type
        types.each do |type|
          yield type
        end
      end

      def pretty
        "Union(#{types.map {|t| t.nil? ? "nil" : t.pretty }.join(" or ")})"
      end
    end
    class GenericType < Struct.new(:name, :parameters)
      def each_possible_type
        yield self
      end

      def pretty
        "generic(#{name}, [#{parameters.map {|t| t.nil? ? "nil" : t.pretty }.join(", ")}])"
      end
    end

    def initialize(logger)
      @logger = logger
    end

    def call(graph, worklist, tree)
      @worklist = worklist
      @graph = graph
      @tree = tree

      @result = {}

      @worklist.nodes = @graph.vertices.to_a
      while !@worklist.nodes.empty?
        while !@worklist.nodes.empty?
          node = @worklist.nodes.shift
          @worklist.count_node(node)
          if !@worklist.limit_exceeded?(node)
            current_result = @result[node]
            @result[node] = compute_result(node, @graph.parent_vertices(node))
            if current_result != @result[node]
              @graph.adjacent_vertices(node).each do |adjacent_node|
                @worklist.enqueue_node(adjacent_node)
              end
            end
          end
        end

        @worklist.message_sends.each do |message_send|
          case message_send
          when Worklist::MessageSend
            if satisfied_message_send?(message_send) && !@worklist.message_send_handled?(message_send)
              handle_message_send(message_send)
              @worklist.mark_message_send_as_handled(message_send)
            end
          when Worklist::SuperSend
            if satisfied_super_send?(message_send) && !@worklist.message_send_handled?(message_send)
              handle_super_send(message_send)
              @worklist.mark_message_send_as_handled(message_send)
            end
          when Worklist::Super0Send
            if !@worklist.message_send_handled?(message_send)
              handle_super0_send(message_send)
              @worklist.mark_message_send_as_handled(message_send)
            end
          else raise "Not handled message send"
          end
        end
      end

      return @result
    end

    private
    attr_reader :logger

    def compute_result(node, sources)
      case node.type
      when :int then handle_int(node, sources)
      when :float then handle_float(node, sources)
      when :nil then handle_nil(node, sources)
      when :bool then handle_bool(node, sources)
      when :str then handle_just_string(node, sources)
      when :dstr then handle_just_string(node, sources)
      when :xstr then handle_just_string(node, sources)
      when :sym then handle_just_symbol(node, sources)
      when :dsym then handle_just_symbol(node, sources)
      when :regexp then handle_regexp(node, sources)
      when :break then handle_bottom(node, sources)

      when :hash_keys then handle_group(node, sources)
      when :hash_values then handle_group(node, sources)
      when :hash then handle_hash(node, sources)

      when :defined then handle_maybe_string(node, sources)

      when :casgn then handle_group(node, sources)

      when :range_from then handle_group(node, sources)
      when :range_to then handle_group(node, sources)
      when :range then handle_range(node, sources)
      when :self then handle_self(node, sources)
      when :lvar then handle_group(node, sources)
      when :array then handle_wrap_array(node, sources)
      when :splat_array then handle_unwrap_array(node, sources)
      when :lvasgn then handle_pass_lte1(node, sources)
      when :call_obj then handle_pass1(node, sources)
      when :call_result then handle_group(node, sources)
      when :call_arg then handle_group(node, sources)
      when :call_splatarg then handle_group(node, sources)
      when :formal_arg then handle_group(node, sources)
      when :formal_optarg then handle_group(node, sources)
      when :formal_restarg then handle_wrap_array(node, sources)
      when :formal_kwarg then handle_group(node, sources)
      when :formal_kwoptarg then handle_group(node, sources)
      when :formal_kwrestarg then handle_pass_lte1(node, sources)
      when :block_result then handle_pass_lte1(node, sources)
      when :unwrap_hash_values then handle_unwrap_hash_values(node, sources)
      when :unwrap_hash_keys then handle_unwrap_hash_keys(node, sources)
      when :const then handle_const(node, sources)
      when :const_definition then handle_group(node, sources)
      when :constructor then handle_constructor(node, sources)
      when :method_result then handle_group(node, sources)
      when :method_caller then handle_group(node, sources)

      when :yield then handle_group(node, sources)

      when :gvasgn then handle_group(node, sources)
      when :gvar_definition then handle_group(node, sources)
      when :gvar then handle_pass1(node, sources)
      when :backref then handle_just_string(node, sources)
      when :nthref then handle_just_string(node, sources)

      when :ivasgn then handle_group(node, sources)
      when :ivar_definition then handle_group(node, sources)
      when :clivar_definition then handle_group(node, sources)
      when :ivar then handle_pass1(node, sources)
      when :extract_class then handle_extract_class(node, sources)


      # below not really tested
      when :if_result then handle_group(node, sources)

      when :case_result then handle_group(node, sources)

      when :and then handle_bool(node, sources)
      when :or then handle_bool(node, sources)

      when :class then handle_nil(node, sources)

      when :unwrap_array then handle_unwrap_array(node, sources)
      when :unwrap_error_array then handle_unwrap_array(node, sources)
      when :wrap_array then handle_wrap_array(node, sources)
      when :rescue then handle_nil(node, sources)

      when :lambda then handle_nil(node, sources)
      when :definition_by_id then handle_definition_by_id(node, sources)

      when :ensure then handle_bottom(node, sources)

      when :yield_result then handle_group(node, sources)

      else raise ArgumentError.new(node.type)
      end
    end
<commit_msg>Few more cases in TypingService<commit_after>module Orbacle
  class TypingService
    class NominalType < Struct.new(:name)
      def each_possible_type
        yield self
      end

      def pretty
        name
      end
    end
    class ClassType < Struct.new(:name)
      def each_possible_type
        yield self
      end

      def pretty
        "class(#{name})"
      end
    end
    class MainType
      def each_possible_type
      end

      def pretty
        "main"
      end

      def ==(other)
        self.class == other.class
      end
    end
    class UnionType < Struct.new(:types)
      def each_possible_type
        types.each do |type|
          yield type
        end
      end

      def pretty
        "Union(#{types.map {|t| t.nil? ? "nil" : t.pretty }.join(" or ")})"
      end
    end
    class GenericType < Struct.new(:name, :parameters)
      def each_possible_type
        yield self
      end

      def pretty
        "generic(#{name}, [#{parameters.map {|t| t.nil? ? "nil" : t.pretty }.join(", ")}])"
      end
    end

    def initialize(logger)
      @logger = logger
    end

    def call(graph, worklist, tree)
      @worklist = worklist
      @graph = graph
      @tree = tree

      @result = {}

      processed_nodes = 0

      @worklist.nodes = @graph.vertices.to_a
      while !@worklist.nodes.empty?
        while !@worklist.nodes.empty?
          node = @worklist.nodes.shift
          @worklist.count_node(node)
          if !@worklist.limit_exceeded?(node)
            current_result = @result[node]
            @result[node] = compute_result(node, @graph.parent_vertices(node))
            processed_nodes += 1
            puts "Processed nodes: #{processed_nodes} remaining nodes #{@worklist.nodes.size} msends #{@worklist.handled_message_sends.size} / #{@worklist.message_sends.size}" if processed_nodes % 1000 == 0
            if current_result != @result[node]
              @graph.adjacent_vertices(node).each do |adjacent_node|
                @worklist.enqueue_node(adjacent_node)
              end
            end
          end
        end

        @worklist.message_sends.each do |message_send|
          case message_send
          when Worklist::MessageSend
            if satisfied_message_send?(message_send) && !@worklist.message_send_handled?(message_send)
              handle_message_send(message_send)
              @worklist.mark_message_send_as_handled(message_send)
            end
          when Worklist::SuperSend
            if satisfied_super_send?(message_send) && !@worklist.message_send_handled?(message_send)
              handle_super_send(message_send)
              @worklist.mark_message_send_as_handled(message_send)
            end
          when Worklist::Super0Send
            if !@worklist.message_send_handled?(message_send)
              handle_super0_send(message_send)
              @worklist.mark_message_send_as_handled(message_send)
            end
          else raise "Not handled message send"
          end
        end
      end

      return @result
    end

    private
    attr_reader :logger

    def compute_result(node, sources)
      case node.type
      when :int then handle_int(node, sources)
      when :float then handle_float(node, sources)
      when :nil then handle_nil(node, sources)
      when :bool then handle_bool(node, sources)
      when :str then handle_just_string(node, sources)
      when :dstr then handle_just_string(node, sources)
      when :xstr then handle_just_string(node, sources)
      when :sym then handle_just_symbol(node, sources)
      when :dsym then handle_just_symbol(node, sources)
      when :regexp then handle_regexp(node, sources)
      when :break then handle_bottom(node, sources)
      when :retry then handle_bottom(node, sources)
      when :dynamic_const then handle_bottom(node, sources)

      when :hash_keys then handle_group(node, sources)
      when :hash_values then handle_group(node, sources)
      when :hash then handle_hash(node, sources)

      when :defined then handle_maybe_string(node, sources)

      when :casgn then handle_group(node, sources)

      when :range_from then handle_group(node, sources)
      when :range_to then handle_group(node, sources)
      when :range then handle_range(node, sources)
      when :self then handle_self(node, sources)
      when :lvar then handle_group(node, sources)
      when :array then handle_wrap_array(node, sources)
      when :splat_array then handle_unwrap_array(node, sources)
      when :lvasgn then handle_pass_lte1(node, sources)
      when :call_obj then handle_pass1(node, sources)
      when :call_result then handle_group(node, sources)
      when :call_arg then handle_group(node, sources)
      when :call_splatarg then handle_group(node, sources)
      when :formal_arg then handle_group(node, sources)
      when :formal_optarg then handle_group(node, sources)
      when :formal_restarg then handle_wrap_array(node, sources)
      when :formal_kwarg then handle_group(node, sources)
      when :formal_kwoptarg then handle_group(node, sources)
      when :formal_kwrestarg then handle_pass_lte1(node, sources)
      when :formal_blockarg then handle_group(node, sources)
      when :block_result then handle_pass_lte1(node, sources)
      when :unwrap_hash_values then handle_unwrap_hash_values(node, sources)
      when :unwrap_hash_keys then handle_unwrap_hash_keys(node, sources)
      when :const then handle_const(node, sources)
      when :const_definition then handle_group(node, sources)
      when :constructor then handle_constructor(node, sources)
      when :method_result then handle_group(node, sources)
      when :method_caller then handle_group(node, sources)

      when :yield then handle_group(node, sources)

      when :gvasgn then handle_group(node, sources)
      when :gvar_definition then handle_group(node, sources)
      when :gvar then handle_pass1(node, sources)
      when :backref then handle_just_string(node, sources)
      when :nthref then handle_just_string(node, sources)

      when :ivasgn then handle_group(node, sources)
      when :ivar_definition then handle_group(node, sources)
      when :clivar_definition then handle_group(node, sources)
      when :ivar then handle_pass1(node, sources)

      when :extract_class then handle_extract_class(node, sources)

      when :cvasgn then handle_group(node, sources)
      when :cvar_definition then handle_group(node, sources)
      when :cvar then handle_pass1(node, sources)

      # below not really tested
      when :if_result then handle_group(node, sources)

      when :case_result then handle_group(node, sources)

      when :and then handle_bool(node, sources)
      when :or then handle_bool(node, sources)

      when :class then handle_nil(node, sources)

      when :unwrap_array then handle_unwrap_array(node, sources)
      when :unwrap_error_array then handle_unwrap_array(node, sources)
      when :wrap_array then handle_wrap_array(node, sources)
      when :rescue then handle_nil(node, sources)

      when :lambda then handle_nil(node, sources)
      when :definition_by_id then handle_definition_by_id(node, sources)

      when :ensure then handle_bottom(node, sources)

      when :yield_result then handle_group(node, sources)

      else raise ArgumentError.new(node.type)
      end
    end

{'fraction_non_alphanumeric': 0.07675376313547287, 'fraction_numerical': 0.0017040613462084636, 'mean_word_length': 2.828486001630878, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, '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': '6318405', 'n_tokens_mistral': 4165, 'n_tokens_neox': 4106, 'n_words': 1088}