class Destructure::SexpTransformer

Public Class Methods

new(caller_binding) click to toggle source
# File lib/destructure/sexp_transformer.rb, line 11
def initialize(caller_binding)
  @caller_binding = caller_binding
end
transform(sp, caller_binding) click to toggle source
# File lib/destructure/sexp_transformer.rb, line 7
def self.transform(sp, caller_binding)
  SexpTransformer.new(caller_binding).transform(sp)
end

Public Instance Methods

transform(sp) click to toggle source
# File lib/destructure/sexp_transformer.rb, line 15
def transform(sp)
  _ = DMatch::_
  klass_sym = DMatch::Var.new(&method(:is_constant?))
  case

    # '_' (wildcard)
  when e = dmatch([:call, _, :_, _], sp); _

    # object matcher without parameters
  when e = dmatch([:const, klass_sym], sp)
    make_obj(e[klass_sym], {})

    # namespace-qualified object matcher without parameters
  when e = dmatch([:colon2, splat(:args)], sp)
    make_obj(read_fq_const(sp), {})

    # '~' (splat)
  when e = dmatch([:call, var(:identifier_sexp), :~, [:arglist]], sp); splat(unwind_receivers_and_clean(e[:identifier_sexp]))

    # '!' (variable value)
  when e = dmatch([:not, var(:value_sexp)], sp)
    @caller_binding.eval(unwind_receivers_and_clean(e[:value_sexp]).to_s)

    # '|' (alternative patterns)
  when e = dmatch([:call, var(:rest), :|, [:arglist, var(:alt)]], sp); DMatch::Or.new(*[e[:rest], e[:alt]].map(&method(:transform)))

    # generic call
  when e = dmatch([:call, var(:receiver), var(:msg), var(:arglist)], sp)
    transform_call(e[:receiver], e[:msg], e[:arglist])

    # instance variable
  when e = dmatch([:ivar, var(:name)], sp); var(e[:name].to_s)

    # let
    # ... with local or instance vars
  when e = dmatch([DMatch::Or.new(:lasgn, :iasgn), var(:lhs), var(:rhs)], sp)
    let_var(e[:lhs], transform(e[:rhs]))

    # ... with attributes or something more complicated
  when e = dmatch([:attrasgn, var(:obj), var(:attr), [:arglist, var(:rhs)]], sp)
    var_name = unwind_receivers_and_clean([:call, e[:obj], e[:attr].to_s.sub(/=$/,'').to_sym, [:arglist]])
    let_var(var_name, transform(e[:rhs]))

    # literal values
  when e = dmatch([:lit, var(:value)], sp); e[:value]
  when e = dmatch([:true], sp); true
  when e = dmatch([:false], sp); false
  when e = dmatch([:nil], sp); nil
  when e = dmatch([:str, var(:s)], sp); e[:s]
  when e = dmatch([:array, splat(:items)], sp); e[:items].map(&method(:transform))
  when e = dmatch([:hash, splat(:kvs)], sp); Hash[*e[:kvs].map(&method(:transform))]
  else; raise "Unexpected sexp: #{sp.inspect}"
  end
end