class Opal::Rewriters::PatternMatching

def convert_full_pattern(from, pat)

def convert_full_pattern(from, pat)
  if from.class == Symbol
    from = s(:lvar, from)
  end
  converter = PatternConverter.new(pat)
  converter.run!
  # a, b, c = ::PatternMatching.(from, [...])
  s(:masgn,
    s(:mlhs,
      *converter.variables
    ),
    s(:send,
      s(:const, s(:cbase), :PatternMatching),
      :call,
      from,
      converter.pattern,
    )
  )
end

def initialize

def initialize
  @depth = 0
  super
end

def on_case_match(node)

case a; in b; end
def on_case_match(node)
  @depth += 1
  cmvar = :"$cmvar#{@depth}"
  from, *cases, els = *node
  if els
    process els
  else
    els = raise_no_matching_pattern_error(cmvar)
  end
  s(:begin,
    s(:lvasgn, cmvar, from),
    single_case_match(cmvar, *cases, els)
  )
end

def on_match_pattern(node)

a => b
def on_match_pattern(node)
  from, pat = *node
  s(:begin,
    s(:lvasgn, :"$pmvar", from),
    s(:if,
      convert_full_pattern(from, pat),
      nil,
      raise_no_matching_pattern_error(:"$pmvar")
    )
  )
end

def on_match_pattern_p(node)

a in b
def on_match_pattern_p(node)
  from, pat = *node
  s(:if,
    convert_full_pattern(from, pat),
    s(:true),
    s(:false)
  )
end

def raise_no_matching_pattern_error(from)

raise NoMatchingPatternError, from
def raise_no_matching_pattern_error(from)
  s(:send, nil, :raise,
    s(:const, s(:cbase), :NoMatchingPatternError),
    s(:lvar, from)
  )
end

def single_case_match(from, *cases, els)

in b
def single_case_match(from, *cases, els)
  cas = cases.shift
  pat, if_guard, body = *cas
  pat = convert_full_pattern(from, pat)
  if if_guard
    guard, = *if_guard
    case if_guard.type
    when :if_guard
      pat = s(:and, pat, guard)
    when :unless_guard
      pat = s(:and, pat, s(:send, guard, :!))
    end
  end
  s(:if,
    pat,
    process(body),
    if !cases.empty?
      single_case_match(from, *cases, els)
    elsif els != s(:empty_else)
      els
    end
  )
end