class Opal::Nodes::Match3Node
with a right-hand side value and assigning the match result to a left-hand side variable.
Handles match_with_lvasgn nodes which represent matching a regular expression
def compile
def compile sexp = s(:send, lhs, :=~, rhs) # Handle named matches like: /(?<abc>b)/ =~ 'b' if lhs.type == :regexp && lhs.children.first.type == :str names = extract_names(lhs) unless names.empty? names_def = generate_names_definition names_assignments = generate_names_assignments(names) sexp = if stmt? handle_statement(sexp, names_def, names_assignments) else handle_non_statement(sexp, names_def, names_assignments) end end end push process(sexp, @level) end
def extract_names(regexp_node)
def extract_names(regexp_node) re = regexp_node.children.first.children.first re.scan(/\(\?<([^>]*)>/).flatten.map(&:to_sym) end
def generate_names_assignments(names)
def generate_names_assignments(names) # Generate names assignments: abc = $m3names[:abc] names.map do |name| s(:lvasgn, name, s(:send, s(:lvar, :$m3names), :[], s(:sym, name) ) ) end end
def generate_names_definition
def generate_names_definition # Generate names definition: $m3names = $~ ? $~.named_captures : {} s(:lvasgn, :$m3names, s(:if, s(:gvar, :$~), s(:send, s(:gvar, :$~), :named_captures), s(:hash) ) ) end
def handle_non_statement(sexp, names_def, names_assignments)
def handle_non_statement(sexp, names_def, names_assignments) # We actually do care about a return value, so we must # keep it saved. # # $m3tmp = (/(?<abc>b)/ =~ 'f') # $m3names = $~ ? $~.named_captures : {} # abc = $m3names[:abc] # $m3tmp s(:begin, s(:lvasgn, :$m3tmp, sexp), names_def, *names_assignments, s(:lvar, :$m3tmp) ) end
def handle_statement(sexp, names_def, names_assignments)
def handle_statement(sexp, names_def, names_assignments) # We don't care about a return value of this one, so we # ignore it and just assign the local variables. # # (/(?<abc>b)/ =~ 'f') # $m3names = $~ ? $~.named_captures : {} # abc = $m3names[:abc] s(:begin, sexp, names_def, *names_assignments) end