Last active
August 29, 2015 14:02
-
-
Save mbj/e153042cb18bd0770a32 to your computer and use it in GitHub Desktop.
mutant longest prefix match configuration spike
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"*"=>{"isolation"=>true, "selector"=>"exact"}, "Foo::Bar"=>{"isolation"=>false, "selector"=>"Foo#bar"}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[#<Configuration expression=#<Mutant::Expression::Namespace::Recursive syntax="*"> isolation=true selector="exact">, | |
#<Configuration expression=#<Mutant::Expression::Namespace::Exact syntax="Foo::Bar"> isolation=false selector="Foo#bar">] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'mutant' | |
require 'yaml' | |
class Selector | |
class Exact < self | |
end # Exact | |
end # Selector | |
class Configuration | |
include Adamantium, Anima.new(:expression, :isolation, :selector) | |
DEFAULTS = new( | |
expression: Mutant::Expression.parse('*'), | |
isolation: true, | |
selector: Selector::Exact | |
) | |
end # Configuration | |
raw = YAML.load(<<-YAML) | |
--- | |
'*': | |
isolation: true | |
strategy: rspec | |
selector: exact | |
Foo::Bar: | |
selector: Foo#bar | |
isolation: false | |
YAML | |
neddles = %w( | |
Foo | |
Foo::Bar | |
Foo::Bar::Baz | |
Foo::Bar::Baz::Boz | |
Foo::Bar::Baz#boz | |
).map(&Mutant::Expression.method(:parse)) | |
module Morpher | |
class Evaluator | |
class Transformer < self | |
class PushKey < self | |
include Nullary::Parameterized | |
register :push_key | |
def call(input) | |
input.map do |key, value| | |
value.merge(param => key) | |
end | |
end | |
def inverse | |
PullKey.new(param) | |
end | |
end # PushKey | |
class PullKey < self | |
include Nullary::Parameterized | |
def call(input) | |
input.each_with_object({}) do |hash, aggregate| | |
dup = hash.dup | |
value = dup.fetch(param) | |
dup.delete(param) | |
aggregate[value] = dup | |
end | |
end | |
end | |
end # Transformer | |
end # Evaluator | |
end # Morpher | |
module Morpher | |
class Evaluator | |
class Transformer < self | |
class Custom < self | |
include Nullary::Parameterized | |
register :custom | |
def call(input) | |
param.first.call(input) | |
end | |
def inverse | |
self.class.new(param.reverse) | |
end | |
end # PushKey | |
end # Transformer | |
end # Evaluator | |
end # Morpher | |
LOADER = Morpher.build do | |
s(:block, | |
s(:guard, s(:primitive, Hash)), | |
s(:push_key, 'expression'), | |
s(:map, | |
s(:block, | |
s(:hash_transform, | |
s(:key_symbolize, :expression, | |
s(:custom, [Mutant::Expression.method(:parse), ->(input) { input.syntax }]), | |
), | |
s(:key_symbolize, :isolation, | |
s(:guard, | |
s(:or, | |
s(:primitive, TrueClass), | |
s(:primitive, FalseClass) | |
) | |
) | |
), | |
s(:key_symbolize, :selector, | |
s(:guard, s(:primitive, String)) | |
) | |
), | |
s(:load_attribute_hash, s(:param, Configuration)) | |
) | |
) | |
) | |
end | |
evaluation = LOADER.evaluation(raw) | |
unless evaluation.success? | |
puts evaluation.description | |
fail | |
end | |
CONFIGURATION = evaluation.output | |
require 'pp' | |
pp CONFIGURATION | |
p LOADER.inverse.evaluation(CONFIGURATION).output | |
def select(candidates, neddle) | |
matches = Hash.new { |hash, key| hash[key] = Set.new } | |
candidates.each do |candidate| | |
match_length = candidate.match_length(neddle) | |
matches[match_length] << candidate | |
end | |
maximum = matches.keys.max | |
if maximum.nil? || maximum.zero? | |
fail "No match for #{neddle.inspect}" | |
end | |
matches = matches.fetch(maximum) | |
case matches.length | |
when 1 | |
return matches.first | |
when 0 | |
else | |
fail "Ambigous match for: #{neddle.inspect} with #{matches.inspect}" | |
end | |
fail "No match for #{neddle.inspect}" | |
end | |
puts "Candidates:" | |
candidates.each(&method(:p)) | |
neddles.each do |neddle| | |
result = select(candidates, neddle) | |
puts "neddle: #{neddle.inspect} matches: #{result.inspect}" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment