class Object
Public Instance Methods
_destructure_set(name, value, binding, caller)
click to toggle source
# File lib/destructure/destructure.rb, line 64 def _destructure_set(name, value, binding, caller) if name.is_a?(String) || binding.eval("defined? #{name}") == 'local-variable' $binding_temp = value binding.eval("#{name} = $binding_temp") else if binding.eval('self').respond_to?(name, true) raise "Cannot have pattern variable named '#{name}'. A method already exists with that name. Choose a different name, " + "or pre-initialize a local variable that shadows the method." end @_destructure_env ||= {} @_destructure_env[caller] ||= {} @_destructure_env[caller][name] = value end end
all_field_patterns_match(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 47 def all_field_patterns_match(pat, x) all_match(pat.fields.keys.map { |name| x.respond_to?(name) && match(pat.fields[name], x.send(name)) }) end
all_match(xs)
click to toggle source
# File lib/destructure/dmatch.rb, line 153 def all_match(xs) xs.all?{|x| x.is_a?(Env)} end
dbind_internal(x, sexp, caller_binding, caller_location)
click to toggle source
# File lib/destructure/destructure.rb, line 45 def dbind_internal(x, sexp, caller_binding, caller_location) env = dbind_no_ostruct_sexp(x, sexp, caller_binding) return nil if env.nil? if bind_locals env.keys.each {|k| _destructure_set(k.name, env[k], caller_binding, caller_location)} end ostruct_env = env.to_openstruct set_custom_env(ostruct_env) if self.respond_to?(:set_custom_env, true) ostruct_env end
dbind_no_ostruct_sexp(x, sexp, caller_binding)
click to toggle source
# File lib/destructure/destructure.rb, line 58 def dbind_no_ostruct_sexp(x, sexp, caller_binding) sp = sexp pat = SexpTransformer.transform(sp, caller_binding) DMatch::match(pat, x) end
decompose_splatted_enumerable(pat)
click to toggle source
# File lib/destructure/dmatch.rb, line 106 def decompose_splatted_enumerable(pat) before = [] splat = nil after = [] pat.each do |p| case when p.is_a?(Splat) if splat.nil? splat = p else raise "cannot have more than one splat in a single array: #{pat.inspect}" end when splat.nil? before.push(p) else after.push(p) end end splat && [before, splat, after] end
enumerable(*xs)
click to toggle source
# File lib/destructure/dmatch.rb, line 145 def enumerable(*xs) xs.all?{|x| x.is_a?(Enumerable)} end
hash(*xs)
click to toggle source
# File lib/destructure/dmatch.rb, line 149 def hash(*xs) xs.all?{|x| x.is_a?(Hash)} end
len(x)
click to toggle source
# File lib/destructure/dmatch.rb, line 137 def len(x) x.respond_to?(:length) ? x.length : x.count end
match_enumerable(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 77 def match_enumerable(pat, x) case when (parts = decompose_splatted_enumerable(pat)) pat_before, pat_splat, pat_after = parts x_before = x.take(pat_before.length) if pat_after.any? splat_len = len(x) - pat_before.length - pat_after.length return nil if splat_len < 0 x_splat = x.drop(pat_before.length).take(splat_len) else x_splat = x.drop(pat_before.length) end before_and_splat_result = match_enumerable_no_splats(pat_before, x_before) && match(pat_splat, x_splat) if before_and_splat_result && pat_after.any? # do this only if we have to, since it requires access to the end of the enumerable, # which doesn't work with infinite enumerables x_after = take_last(pat_after.length, x) match_enumerable_no_splats(pat_after, x_after) else before_and_splat_result end when len(pat) == len(x) match_enumerable_no_splats(pat, x) else; nil end end
match_enumerable_no_splats(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 141 def match_enumerable_no_splats(pat, x) all_match(pat.zip(x).map{|a| match(*a)}) ? @env : nil end
match_filter_splat(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 73 def match_filter_splat(pat, x) @env.bind(pat, x.map { |z| [z, match(pat.pattern, z)] }.reject { |q| q.last.nil? }.map { |q| q.first }) end
match_or(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 55 def match_or(pat, x) pat.patterns.lazy.map{|p| match(p, x)}.reject{|e| e.nil?}.first end
match_regexp(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 42 def match_regexp(pat, x) m = pat.match(x) m && @env.merge!(Hash[pat.named_captures.keys.map { |k| [Var.new(k.to_sym), m[k]] }]) end
match_select_splat(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 63 def match_select_splat(pat, x) x_match_and_env = x.map { |z| [z, DMatch::match(pat.pattern, z)] }.reject { |q| q.last.nil? }.first if x_match_and_env x_match, env = x_match_and_env @env.bind(pat, x_match) && @env.merge!(env) else nil end end
match_splat(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 59 def match_splat(pat, x) @env.bind(pat, enumerable(x) ? x : [x]) end
match_var(pat, x)
click to toggle source
# File lib/destructure/dmatch.rb, line 51 def match_var(pat, x) @env.bind(pat, x) end
method_missing(name, *args, &block)
click to toggle source
Calls superclass method
# File lib/destructure/destructure.rb, line 79 def method_missing(name, *args, &block) if bind_locals c = caller_locations(1,1)[0].label @_destructure_env ||= {} caller_hash = @_destructure_env[c] caller_hash && caller_hash.keys.include?(name) ? caller_hash[name] : super else super end end
take_last(n, xs)
click to toggle source
# File lib/destructure/dmatch.rb, line 128 def take_last(n, xs) result = [] xs.reverse_each do |x| break if result.length == n result.unshift x end result end