![Markus Schirp](/assets/img/avatar_default.png)
* This is in progress code. The plan is to support all literals before beginning to cleanup and dedup the mutation generation. Have to understand the AST and the possible mutations more in depth before making structural decisions here.
120 lines
2.1 KiB
Ruby
120 lines
2.1 KiB
Ruby
module Mutant
|
|
# Mutate rubinius AST nodes
|
|
class Mutator
|
|
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)
|
|
return to_enum(__method__) unless block_given?
|
|
mutants(Generator.new(block))
|
|
self
|
|
end
|
|
|
|
private
|
|
|
|
# Return wrapped node
|
|
#
|
|
# @return [Rubinius::AST::Node]
|
|
#
|
|
# @api private
|
|
#
|
|
attr_reader :node
|
|
|
|
# Initialize mutator with
|
|
#
|
|
# @param [Rubinius::AST::Node] node
|
|
#
|
|
# @api private
|
|
#
|
|
def initialize(node)
|
|
@node = node
|
|
end
|
|
|
|
# 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
|
|
end
|
|
end
|