module SinRefinements

Constants

VERSION

Public Class Methods

get_local_variable_names(ast, buf = []) click to toggle source
# File lib/sin_refinements.rb, line 11
def get_local_variable_names(ast, buf = [])
  if ast.type == :send
    params = ast.to_a
    if params[0].nil? && params.length == 2
      buf << params[1]
    end
  end

  ast.children.each do |node|
    if node.is_a?(Parser::AST::Node)
      get_local_variable_names(node, buf)
    end
  end

  buf
end
light_refining(b, mod, *variables, &block) click to toggle source
# File lib/sin_refinements.rb, line 52
                        def light_refining(b, mod, *variables, &block)
      source_location = block.source_location
      unless refined_class_table[source_location][mod]
        block_source = block.to_source
        matched = block_source.match(/do(.*)end/m)
        proc_source = "proc #{matched[0]}"

        refined_class_table[source_location][mod] = TOPLEVEL_BINDING.eval(<<~RUBY)
          Class.new do
            using #{mod.to_s}

            def self.process(b, *variables)
              pr = #{proc_source}
              b.receiver.instance_exec(*variables, &pr)
            end
          end
        RUBY
      end
      refined_class_table[source_location][mod].process(b, *variables)
    end
refined_class_table() click to toggle source
# File lib/sin_refinements.rb, line 48
def refined_class_table
  @refined_class_table ||= Hash.new { |h, k| h[k] = {} }
end
refining(b, mod, &block) click to toggle source
# File lib/sin_refinements.rb, line 28
                        def refining(b, mod, &block)
      block_source = block.to_source
      matched = block_source.match(/do(.*)end/m)
      proc_source = "proc #{matched[0]}"
      used_local_variables = get_local_variable_names(Parser::CurrentRuby.parse(matched[1]))

      c = TOPLEVEL_BINDING.eval(<<~RUBY)
        Class.new do
          using #{mod.to_s}

          def self.process(b)
            #{b.local_variables.select { |v| used_local_variables.include?(v) }.map { |v| "#{v} = b.local_variable_get(:#{v})" }.join("\n")}
            pr = #{proc_source}
            b.receiver.instance_exec(&pr)
          end
        end
      RUBY
      c.process(b)
    end