Skip to content

Instantly share code, notes, and snippets.

@mbj
Last active August 29, 2015 14:02
Show Gist options
  • Save mbj/e153042cb18bd0770a32 to your computer and use it in GitHub Desktop.
Save mbj/e153042cb18bd0770a32 to your computer and use it in GitHub Desktop.
mutant longest prefix match configuration spike
{"*"=>{"isolation"=>true, "selector"=>"exact"}, "Foo::Bar"=>{"isolation"=>false, "selector"=>"Foo#bar"}}
[#<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">]
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