module Destructure
Public Instance Methods
dbind(x, &pat_block)
click to toggle source
# File lib/destructure/destructure.rb, line 35 def dbind(x, &pat_block) dbind_internal(x, pat_block.to_sexp(strip_enclosure: true, ignore_nested: true), binding.of_caller(1), caller_locations(1,1)[0].label) end
dmatch(*args)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 175 def dmatch(*args) DMatch::match(*args) end
format_hash_call(args)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 151 def format_hash_call(args) "[#{transform_args(args)}].".gsub(/\(\)$/, '') end
format_method_call(msg, args)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 147 def format_method_call(msg, args) "#{msg}(#{transform_args(args)})".gsub(/\(\)$/, '') + '.' end
identifier?(x)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 130 def identifier?(x) x =~ /^[_a-zA-Z][_0-9a-zA-Z]*$/ end
is_constant?(x, env=nil)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 167 def is_constant?(x, env=nil) x.is_a?(Symbol) && is_uppercase?(x.to_s[0]) end
is_uppercase?(char)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 171 def is_uppercase?(char) char == char.upcase end
let_var(name, pattern)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 183 def let_var(name, pattern) DMatch::Var.new(name) { |x, env| DMatch.new(env).match(pattern, x) } end
make_field_map(sexp_args)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 110 def make_field_map(sexp_args) case # Class[a: 1, b: 2] when e = dmatch([:arglist, [:hash, splat(:kv_sexps)]], sexp_args) kvs = transform_many(e[:kv_sexps]) Hash[*kvs] # Class[a, b, c] when e = dmatch([:arglist, splat(:field_name_sexps)], sexp_args) field_names = transform_many(e[:field_name_sexps]) Hash[field_names.map { |f| [f.name, var(f.name)] }] else; raise 'oops' end end
make_obj(klass_sym, field_map)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 163 def make_obj(klass_sym, field_map) DMatch::Obj.of_type(klass_sym.to_s.constantize, field_map) end
splat(name)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 187 def splat(name) DMatch::Splat.new(name) end
transform_args(args)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 155 def transform_args(args) transform_many(args).map { |x| x.is_a?(Symbol) ? ":#{x}" : x.to_s }.join(', ') end
transform_call(*sexp_call)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 83 def transform_call(*sexp_call) sexp_receiver, sexp_msg, sexp_args = sexp_call _ = DMatch::_ klass_sym_var = DMatch::Var.new(&method(:is_constant?)) case # Class[...] when e = dmatch([[:const, klass_sym_var], :[]], [sexp_receiver, sexp_msg]) field_map = make_field_map(sexp_args) klass_sym = e[klass_sym_var] klass_sym == :Hash ? field_map : make_obj(klass_sym, field_map) # namespace-qualified constant receiver when e = dmatch([:colon2, splat(:args)], sexp_receiver) field_map = make_field_map(sexp_args) klass_sym = read_fq_const(sexp_receiver) make_obj(klass_sym, field_map) # local variable when e = dmatch([nil, var(:name), [:arglist]], sexp_call) var(e[:name]) # call chain (@one.two(12).three[3].four) else var(unwind_receivers_and_clean([:call, *sexp_call])) end end
transform_many(xs)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 159 def transform_many(xs) xs.map(&method(:transform)) end
unwind_receivers(receiver)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 134 def unwind_receivers(receiver) case when receiver.nil?; '' when e = dmatch([:lit, var(:value)], receiver); "#{e[:value]}." when e = dmatch([:ivar, var(:name)], receiver); "#{e[:name]}." when e = dmatch([:call, var(:receiver), :[], [:arglist, splat(:args)]], receiver) unwind_receivers(e[:receiver]) + format_hash_call(e[:args]) when e = dmatch([:call, var(:receiver), var(:msg), [:arglist, splat(:args)]], receiver) unwind_receivers(e[:receiver]) + format_method_call(e[:msg], e[:args]) else; raise 'oops' end end
unwind_receivers_and_clean(receiver)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 125 def unwind_receivers_and_clean(receiver) unwound = unwind_receivers(receiver).gsub(/\.$/, '').gsub(/\.\[/, '[') identifier?(unwound) ? unwound.to_sym : unwound end
var(name)
click to toggle source
# File lib/destructure/sexp_transformer.rb, line 179 def var(name) DMatch::Var.new(name) end