{
qget_path: <<~RUBY.chomp,
ensure_module: <<~RUBY.chomp,
ensure_class: <<~RUBY.chomp,
destructure: <<~RUBY.chomp,
destructure_into: <<~'RUBY'.chomp,
match_pattern: <<~RUBY.chomp,
match_pattern_into: <<~'RUBY'.chomp
def kap_match_pattern_into(pattern, value, bindings)
case pattern[0]
when :bind
name = pattern[1]
allow_nil = pattern[2]
return false if value.nil? && !allow_nil
bindings[name] = value
true
when :ref
bindings.key?(pattern[1]) && bindings[pattern[1]] == value
when :wild
true
when :vec
return false unless value.is_a?(Array) || value.respond_to?(:to_ary)
array = value.is_a?(Array) ? value : value.to_ary
items = pattern[1]
rest_idx = items.index { |item| item.is_a?(Array) && item[0] == :rest }
if rest_idx
before = items[0...rest_idx]
rest_pattern = items[rest_idx][1]
return false if array.length < before.length
before.each_with_index do |item, i|
return false unless kap_match_pattern_into(item, array[i], bindings)
end
kap_match_pattern_into(rest_pattern, array[rest_idx..], bindings)
else
return false unless array.length >= items.length
items.each_with_index do |item, i|
return false unless kap_match_pattern_into(item, array[i], bindings)
end
true
end
when :hash
return false unless value.is_a?(Hash)
pattern[1].each do |key, subpattern|
return false unless value.key?(key)
return false unless kap_match_pattern_into(subpattern, value[key], bindings)
end
true
when :lit
value == pattern[1]
when :pin
value == pattern[1]
when :or
pattern[1].any? do |option|
option_bindings = bindings.dup
next false unless kap_match_pattern_into(option, value, option_bindings)
bindings.replace(option_bindings)
true
end
else
raise "bad pattern: #{pattern.inspect}"
end
end
RUBY
}.transform_values(&:freeze).freeze