Sha256: 383e79acde6c6690ae8b28c6a7bd53060e8144c0f6b713fedce71b18ba6da151

Contents?: true

Size: 1.24 KB

Versions: 5

Compression:

Stored size: 1.24 KB

Contents

require "attributable"
require "metamorpher/rewriter/traverser"

module Metamorpher
  module Rewriter
    class Rule
      extend Attributable
      attributes :pattern, :replacement, traverser: Traverser.new

      def apply(ast, &block)
        rewrite_all(ast, matches_for(ast).take(1), &block)
      end

      def reduce(ast, &block)
        rewrite_all(ast, matches_for(ast), &block)
      end

      private

      def rewrite_all(ast, matches, &block)
        matches.reduce(ast) { |a, e| rewrite(a, e, &block) }
      end

      def rewrite(ast, match, &block)
        original = match.root
        substitution = substitution_with_special_values(match)
        rewritten = replacement.substitute(substitution)
        block.call(original, rewritten) if block
        ast.replace(original.path, rewritten)
      end

      def substitution_with_special_values(match)
        match.substitution.dup.tap do |substitution|
          substitution[:&] = match.root.dup # add the "whole match" special variable (&)
        end
      end

      def matches_for(ast)
        traverser.traverse(ast)
          .lazy # only compute the next match when needed
          .map { |current| pattern.match(current) }
          .select(&:matches?)
      end
    end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
metamorpher-0.2.6 lib/metamorpher/rewriter/rule.rb
metamorpher-0.2.5 lib/metamorpher/rewriter/rule.rb
metamorpher-0.2.4 lib/metamorpher/rewriter/rule.rb
metamorpher-0.2.3 lib/metamorpher/rewriter/rule.rb
metamorpher-0.2.2 lib/metamorpher/rewriter/rule.rb