2012-07-26 13:25:23 -04:00
|
|
|
module Mutant
|
|
|
|
# Mutate rubinius AST nodes
|
|
|
|
class Mutator
|
2012-07-27 16:39:31 -04:00
|
|
|
include Enumerable, Veritas::Immutable
|
|
|
|
|
|
|
|
# Build mutation node
|
|
|
|
#
|
|
|
|
# @param [Rubinius::AST::Node] node
|
|
|
|
#
|
|
|
|
# @return [Mutator]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def self.build(node)
|
|
|
|
mutator(node).new(node)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return mutator for node or raise
|
|
|
|
#
|
|
|
|
# @param [Rubinius::AST::Node] node
|
|
|
|
#
|
|
|
|
# @return [Mutator]
|
|
|
|
#
|
|
|
|
# @raise [ArgumentError]
|
|
|
|
# raises ArgumentError if mutator for node cannot be found
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def self.mutator(node)
|
|
|
|
unqualified_name = node.class.name.split('::').last
|
|
|
|
self.const_get(unqualified_name)
|
|
|
|
end
|
|
|
|
|
|
|
|
class Generator
|
|
|
|
def initialize(block)
|
|
|
|
@block = block
|
|
|
|
end
|
|
|
|
|
|
|
|
def append(node)
|
|
|
|
@block.call(node)
|
|
|
|
end
|
|
|
|
|
|
|
|
alias :<< :append
|
|
|
|
end
|
|
|
|
|
|
|
|
# Enumerate mutated asts
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def each(&block)
|
2012-07-29 12:03:44 -04:00
|
|
|
return to_enum unless block_given?
|
2012-07-27 16:39:31 -04:00
|
|
|
mutants(Generator.new(block))
|
|
|
|
self
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
# Return wrapped node
|
|
|
|
#
|
|
|
|
# @return [Rubinius::AST::Node]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
attr_reader :node
|
|
|
|
|
|
|
|
# Initialize mutator with
|
2012-07-26 13:25:23 -04:00
|
|
|
#
|
|
|
|
# @param [Rubinius::AST::Node] node
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def initialize(node)
|
|
|
|
@node = node
|
|
|
|
end
|
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
# Create a new AST node
|
|
|
|
#
|
|
|
|
# @param [Rubinis::AST::Node:Class] node_class
|
|
|
|
#
|
|
|
|
# @return [Rubinius::AST::Node]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def new(node_class,*arguments)
|
|
|
|
node_class.new(node.line,*arguments)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Create a new AST node with same class as wrapped node
|
|
|
|
#
|
|
|
|
# @return [Rubinius::AST::Node]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def new_self(*arguments)
|
|
|
|
new(node.class,*arguments)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Create a new AST node with NilLiteral class
|
|
|
|
#
|
|
|
|
# @return [Rubinius::AST::NilLiteral]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def new_nil
|
|
|
|
new(Rubinius::AST::NilLiteral)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Append mutations
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
# @param [#<<] generator
|
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
def mutants(generator)
|
|
|
|
Mutant.not_implemented(self)
|
|
|
|
end
|
2012-07-26 13:25:23 -04:00
|
|
|
end
|
|
|
|
end
|