Class: EagerRewriter

Inherits:
Parser::TreeRewriter
  • Object
show all
Defined in:
lib/zombie_killer/eager_rewriter.rb

Overview

Rewrite Zombies with their idiomatic replacements

Constant Summary collapse

OPS =
Parser::AST::Node.new(:const, [nil, :Ops])
INFIX =
{
  add: :+,
  subtract: :-,
  multiply: :*,
  divide: :/,
  modulo: :%,
  bitwise_and: :&,
  bitwise_or: :|,
  bitwise_xor: :^,

  less_than: :<,
  less_or_equal: :<=,
  greater_than: :>,
  greater_or_equal: :>=
}.freeze
AS_OPS =
Set.new [:+, :-]

Instance Method Summary collapse

Instance Method Details

#lvar_vname2(receiver) ⇒ Object



53
54
55
# File 'lib/zombie_killer/eager_rewriter.rb', line 53

def lvar_vname2(receiver)
  receiver.children.first if receiver && receiver.type == :lvar
end

#on_lvasgn(node) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/zombie_killer/eager_rewriter.rb', line 43

def on_lvasgn(node)
  super
  vname1, value = *node
  return unless value && value.type == :send
  receiver, oname, *args = *value
  if vname1 == lvar_vname2(receiver) && AS_OPS.include?(oname)
    replace_node(node, s(:op_asgn, s(:lvasgn, vname1), oname, args[0]))
  end
end

#on_send(node) ⇒ Object



33
34
35
36
37
38
39
40
# File 'lib/zombie_killer/eager_rewriter.rb', line 33

def on_send(node)
  super
  receiver, name, *args = *node
  replacement = INFIX[name]
  if receiver == OPS && replacement && args.size == 2
    replace_node(node, s(:send, args[0], replacement, args[1]))
  end
end

#replace_node(old_node, new_node) ⇒ Object



28
29
30
31
# File 'lib/zombie_killer/eager_rewriter.rb', line 28

def replace_node(old_node, new_node)
  source_range = old_node.loc.expression
  replace(source_range, Unparser.unparse(new_node))
end

#s(name, *children) ⇒ Object



24
25
26
# File 'lib/zombie_killer/eager_rewriter.rb', line 24

def s(name, *children)
  Parser::AST::Node.new(name, children)
end