lib/opal/nodes/call_special.rb in opal-1.7.4 vs lib/opal/nodes/call_special.rb in opal-1.8.0.alpha1
- old
+ new
@@ -58,69 +58,93 @@
end
push ')'
end
end
- # /regexp/ =~ rhs
- # s(:match_with_lvasgn, lhs, rhs)
+ # Handles match_with_lvasgn nodes which represent matching a regular expression
+ # with a right-hand side value and assigning the match result to a left-hand side variable.
class Match3Node < Base
handle :match_with_lvasgn
children :lhs, :rhs
def compile
sexp = s(:send, lhs, :=~, rhs)
+
# Handle named matches like: /(?<abc>b)/ =~ 'b'
if lhs.type == :regexp && lhs.children.first.type == :str
- re = lhs.children.first.children.first
- names = re.scan(/\(\?<([^>]*)>/).flatten.map(&:to_sym)
+ names = extract_names(lhs)
+
unless names.empty?
- # $m3names = $~ ? $~.named_captures : {}
- names_def = s(:lvasgn, :$m3names,
- s(:if,
- s(:gvar, :$~),
- s(:send, s(:gvar, :$~), :named_captures),
- s(:hash)
- )
- )
+ names_def = generate_names_definition
+ names_assignments = generate_names_assignments(names)
- names = names.map do |name|
- # abc = $m3names[:abc]
- s(:lvasgn, name,
- s(:send,
- s(:lvar, :$m3names),
- :[],
- s(:sym, name)
- )
- )
- end
-
- if stmt?
- # 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]
- sexp = s(:begin, sexp, names_def, *names)
- else
- # 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
- sexp = s(:begin,
- s(:lvasgn, :$m3tmp, sexp),
- names_def,
- *names,
- s(:lvar, :$m3tmp)
- )
- end
+ 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
+
+ private
+
+ def extract_names(regexp_node)
+ re = regexp_node.children.first.children.first
+ re.scan(/\(\?<([^>]*)>/).flatten.map(&:to_sym)
+ end
+
+ 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 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 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
+
+ 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
end
end
end