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