2013-07-28 19:03:06 -04:00
|
|
|
# encoding: utf-8
|
|
|
|
|
2012-12-06 15:30:28 -05:00
|
|
|
module Mutant
|
2013-07-29 20:34:02 -04:00
|
|
|
|
2012-12-06 15:30:28 -05:00
|
|
|
# Generator for mutations
|
|
|
|
class Mutator
|
2013-07-29 20:34:02 -04:00
|
|
|
|
2012-12-06 15:30:28 -05:00
|
|
|
# Abstract base class for node mutators
|
|
|
|
class Node < self
|
2013-06-14 13:35:09 -04:00
|
|
|
include AbstractType, NodeHelpers, Unparser::Constants
|
2012-12-06 15:30:28 -05:00
|
|
|
|
2012-12-10 18:17:19 -05:00
|
|
|
# Return identity of node
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-04 04:25:13 -04:00
|
|
|
# @param [Parser::AST::Node] node
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2012-12-10 18:17:19 -05:00
|
|
|
# @return [String]
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2012-12-12 16:31:14 -05:00
|
|
|
# @api private
|
|
|
|
#
|
2012-12-10 18:17:19 -05:00
|
|
|
def self.identity(node)
|
2013-06-04 14:23:06 -04:00
|
|
|
Unparser.unparse(node)
|
2012-12-06 15:30:28 -05:00
|
|
|
end
|
|
|
|
|
2013-06-21 09:02:47 -04:00
|
|
|
# Define named child
|
|
|
|
#
|
|
|
|
# @param [Symbol] name
|
|
|
|
# @param [Fixnum] index
|
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def self.define_named_child(name, index)
|
2013-12-07 14:53:56 -05:00
|
|
|
define_method(name) do
|
2013-06-21 12:38:15 -04:00
|
|
|
children.at(index)
|
2013-06-21 09:02:47 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
define_method("emit_#{name}_mutations") do
|
|
|
|
mutate_child(index)
|
|
|
|
end
|
|
|
|
|
|
|
|
define_method("emit_#{name}") do |node|
|
|
|
|
emit_child_update(index, node)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
private_class_method :define_named_child
|
|
|
|
|
|
|
|
# Define remaining children
|
|
|
|
#
|
2013-06-21 09:51:30 -04:00
|
|
|
# @param [Array<Symbol>] names
|
2013-06-21 09:02:47 -04:00
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2013-06-21 09:51:30 -04:00
|
|
|
def self.define_remaining_children(names)
|
|
|
|
define_method(:remaining_children_with_index) do
|
|
|
|
children.each_with_index.drop(names.length)
|
|
|
|
end
|
|
|
|
|
2013-06-21 09:02:47 -04:00
|
|
|
define_method(:remaining_children) do
|
2013-06-21 09:51:30 -04:00
|
|
|
children.drop(names.length)
|
2013-06-21 09:02:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
private_class_method :define_remaining_children
|
|
|
|
|
|
|
|
# Create name helpers
|
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def self.children(*names)
|
|
|
|
names.each_with_index do |name, index|
|
|
|
|
define_named_child(name, index)
|
|
|
|
end
|
2013-06-21 09:51:30 -04:00
|
|
|
define_remaining_children(names)
|
2013-06-21 09:02:47 -04:00
|
|
|
end
|
|
|
|
private_class_method :children
|
|
|
|
|
2012-12-29 10:34:39 -05:00
|
|
|
private
|
2012-12-10 18:17:19 -05:00
|
|
|
|
2012-12-12 16:31:14 -05:00
|
|
|
# Return mutated node
|
|
|
|
#
|
2013-06-04 04:25:13 -04:00
|
|
|
# @return [Parser::AST::Node]
|
2012-12-12 16:31:14 -05:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2012-12-10 18:17:19 -05:00
|
|
|
alias_method :node, :input
|
2012-12-12 16:31:14 -05:00
|
|
|
|
|
|
|
# Return duplicated node
|
|
|
|
#
|
2013-06-04 04:25:13 -04:00
|
|
|
# @return [Parser::AST::Node]
|
2012-12-12 16:31:14 -05:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2012-12-10 18:17:19 -05:00
|
|
|
alias_method :dup_node, :dup_input
|
2012-12-06 15:30:28 -05:00
|
|
|
|
2013-06-04 17:44:17 -04:00
|
|
|
# Emit children mutations
|
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def emit_children_mutations
|
2013-06-24 16:10:40 -04:00
|
|
|
Mutator::Util::Array.each(children, self) do |children|
|
2013-06-10 04:15:59 -04:00
|
|
|
emit_self(*children)
|
2013-06-04 17:44:17 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-04 14:23:06 -04:00
|
|
|
# Return children
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
# @return [Array<Parser::AST::Node>]
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
def children
|
|
|
|
node.children
|
2012-12-06 15:30:28 -05:00
|
|
|
end
|
|
|
|
|
2013-06-04 14:23:06 -04:00
|
|
|
# Dispatch on child index
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
# @param [Fixnum] index
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
# @return [undefined]
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
def mutate_child(index, mutator = Mutator)
|
2013-07-04 21:01:59 -04:00
|
|
|
child = children.at(index)
|
2013-06-24 16:10:40 -04:00
|
|
|
mutator.each(child, self) do |mutation|
|
2013-06-04 14:23:06 -04:00
|
|
|
emit_child_update(index, mutation)
|
|
|
|
end
|
2012-12-06 15:30:28 -05:00
|
|
|
end
|
|
|
|
|
2013-06-14 12:22:34 -04:00
|
|
|
# Emit delete child mutation
|
|
|
|
#
|
|
|
|
# @param [Fixnum] index
|
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def delete_child(index)
|
|
|
|
dup_children = children.dup
|
|
|
|
dup_children.delete_at(index)
|
|
|
|
emit_self(*dup_children)
|
|
|
|
end
|
|
|
|
|
2013-06-04 14:23:06 -04:00
|
|
|
# Emit updated child
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
# @param [Fixnum] index
|
2013-07-04 21:01:59 -04:00
|
|
|
# @param [Parser::AST::Node] node
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
2013-07-04 21:01:59 -04:00
|
|
|
def emit_child_update(index, node)
|
2013-06-04 14:23:06 -04:00
|
|
|
new_children = children.dup
|
2013-07-27 14:21:27 -04:00
|
|
|
new_children[index] = node
|
2013-06-10 04:15:59 -04:00
|
|
|
emit_self(*new_children)
|
2012-12-06 15:30:28 -05:00
|
|
|
end
|
|
|
|
|
2013-06-04 14:23:06 -04:00
|
|
|
# Emit a new AST node with same class as wrapped node
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-04 14:23:06 -04:00
|
|
|
# @param [Array<Parser::AST::Node>] children
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
2013-06-15 10:37:43 -04:00
|
|
|
# @return [undefined]
|
|
|
|
#
|
2012-12-06 15:30:28 -05:00
|
|
|
# @api private
|
|
|
|
#
|
2013-06-10 04:15:59 -04:00
|
|
|
def emit_self(*children)
|
|
|
|
emit(new_self(*children))
|
2012-12-06 15:30:28 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
# Emit a new AST node with NilLiteral class
|
|
|
|
#
|
2013-06-25 03:33:28 -04:00
|
|
|
# @return [undefined]
|
2012-12-06 15:30:28 -05:00
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def emit_nil
|
2013-09-08 02:10:25 -04:00
|
|
|
emit(N_NIL) unless agsn_left?
|
2012-12-06 15:30:28 -05:00
|
|
|
end
|
|
|
|
|
2013-06-10 04:15:59 -04:00
|
|
|
# Return new self typed child
|
|
|
|
#
|
|
|
|
# @return [Parser::AST::Node]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def new_self(*children)
|
|
|
|
Parser::AST::Node.new(node.type, children)
|
|
|
|
end
|
|
|
|
|
2013-06-12 13:09:43 -04:00
|
|
|
# Emit values
|
|
|
|
#
|
|
|
|
# @param [Array<Object>] values
|
|
|
|
#
|
|
|
|
# @return [undefined]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def emit_values(values)
|
|
|
|
values.each do |value|
|
|
|
|
emit_self(value)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-07-14 15:37:22 -04:00
|
|
|
# Return parent type
|
|
|
|
#
|
|
|
|
# @return [Symbol] type
|
|
|
|
# if parent with type is presnet
|
|
|
|
#
|
|
|
|
# @return [nil]
|
|
|
|
# otherwise
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def parent_type
|
|
|
|
parent && parent.node.type
|
|
|
|
end
|
|
|
|
|
2013-09-08 02:10:25 -04:00
|
|
|
# Test if the node is the left of an or_asgn or op_asgn
|
|
|
|
#
|
|
|
|
# @return [Boolean]
|
|
|
|
#
|
|
|
|
# @api private
|
|
|
|
#
|
|
|
|
def agsn_left?
|
2013-09-08 05:37:53 -04:00
|
|
|
OP_ASSIGN.include?(parent_type) && parent.left.equal?(node)
|
2013-09-08 02:10:25 -04:00
|
|
|
end
|
|
|
|
|
2013-06-04 04:25:13 -04:00
|
|
|
end # Node
|
|
|
|
end # Mutator
|
|
|
|
end # Mutant
|