Permalink
Browse files

Fix pattern matching specs with post splat arguments

This handles pattern matching for post splat block arguments.

Fixes #1569, fixes #2073, fixes #2094, fixes #1777
  • Loading branch information...
dbussink committed Jul 29, 2013
1 parent 9566534 commit 2ab0d142a52a4dac19f24822f2af6fc669b51dbb
Showing with 130 additions and 9 deletions.
  1. +35 −6 lib/compiler/ast/definitions.rb
  2. +1 −1 lib/compiler/ast/sends.rb
  3. +16 −0 lib/compiler/ast/values.rb
  4. +78 −2 lib/compiler/ast/variables.rb
@@ -520,12 +520,40 @@ class PatternArguments < Node
def self.from_masgn(node)
array = []
- node.left.body.map do |n|
+ size = 0
+ if node.left
+ size += node.left.body.size
+ node.left.body.map do |n|
+ case n
+ when MultipleAssignment
+ array << PatternArguments.from_masgn(n)
+ when LocalVariable
+ array << LeftPatternVariable.new(n.line, n.name)
+ end
+ end
+ end
+
+ if node.post
+ idx = 0
+ post_args = []
+ node.post.body.map do |n|
+ case n
+ when MultipleAssignment
+ post_args << PatternArguments.from_masgn(n)
+ when LocalVariable
+ post_args << PostPatternVariable.new(n.line, n.name, idx)
+ end
+ idx += 1
+ end
+ array.concat(post_args.reverse)
+ end
+
+ if node.splat
+ n = node.splat
case n
- when MultipleAssignment
- array << PatternArguments.from_masgn(n)
- when LocalVariable
- array << PatternVariable.new(n.line, n.name)
+ when EmptySplat
+ when SplatAssignment, SplatWrapped, SplatArray
+ array << SplatPatternVariable.new(n.value.line, n.value.name)
end
end
@@ -545,7 +573,8 @@ def map_arguments(scope)
arguments = @arguments.body
while arguments
node = arguments.first
- if node.kind_of? PatternVariable
+ case node
+ when LeftPatternVariable, PostPatternVariable, SplatPatternVariable
@argument = node
scope.new_local node.name
scope.assign_local_reference node
@@ -294,7 +294,7 @@ def size
end
def splat?
- @arguments.kind_of? SplatValue or @arguments.kind_of? ConcatArgs
+ @arguments.splat?
end
def bytecode(g)
View
@@ -18,6 +18,10 @@ def bytecode(g)
def to_sexp
[:splat, @value.to_sexp]
end
+
+ def splat?
+ true
+ end
end
class ConcatArgs < Node
@@ -60,6 +64,10 @@ def peel_lhs
def to_sexp
[:argscat, @array.to_sexp, @rest.to_sexp]
end
+
+ def splat?
+ true
+ end
end
class PushArgs < Node
@@ -81,6 +89,14 @@ def bytecode(g)
def to_sexp
[:argspush, @arguments.to_sexp, @value.to_sexp]
end
+
+ def size
+ 1
+ end
+
+ def splat?
+ @arguments.splat?
+ end
end
@@ -549,7 +549,7 @@ def initialize(line, into, rest)
end
class MultipleAssignment < Node
- attr_accessor :left, :right, :splat, :block
+ attr_accessor :left, :right, :splat, :block, :post
def initialize(line, left, right, splat)
@line = line
@@ -752,7 +752,7 @@ def to_sexp
end
end
- class PatternVariable < Node
+ class LeftPatternVariable < Node
include LocalVariable
attr_accessor :name, :value
@@ -780,5 +780,81 @@ def bytecode(g)
g.pop
end
end
+
+ class SplatPatternVariable < Node
+ include LocalVariable
+
+ attr_accessor :name, :value
+
+ def initialize(line, name)
+ @line = line
+ @name = name
+ @variable = nil
+ end
+
+ def position_bytecode(g)
+ @variable.get_bytecode(g)
+ g.cast_array
+ end
+
+ def bytecode(g)
+ pos(g)
+
+ unless @variable
+ g.state.scope.assign_local_reference self
+ end
+
+ g.dup
+ @variable.set_bytecode(g)
+ g.pop
+ end
+ end
+
+ class PostPatternVariable < Node
+ include LocalVariable
+
+ attr_accessor :name, :value
+
+ def initialize(line, name, idx)
+ @line = line
+ @name = name
+ @pos = idx
+ @variable = nil
+ end
+
+ def position_bytecode(g)
+ @variable.get_bytecode(g)
+ g.cast_array
+ end
+
+ def bytecode(g)
+ pos(g)
+
+ unless @variable
+ g.state.scope.assign_local_reference self
+ end
+
+ too_big = g.new_label
+ done = g.new_label
+
+ g.dup
+ g.send :size, 0
+ g.push_int @pos
+ g.send :>, 1
+ g.gif too_big
+ g.dup
+ g.send :pop, 0
+
+ g.goto done
+ too_big.set!
+ g.push_nil
+ @variable.set_bytecode(g)
+ g.goto done
+
+ done.set!
+ @variable.set_bytecode(g)
+ g.pop
+ end
+ end
end
end

2 comments on commit 2ab0d14

I am so happy you fixed this.. I will now use rbx as my day to day ruby! Goodbye MRI!

Thank you!

Contributor

badosu replied Jul 30, 2013

Great work!

Please sign in to comment.