Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

wip

  • Loading branch information...
commit 715aca0c734cb18bd976716f88ea1dcf601e9cea 1 parent a53c30c
@txus authored
Showing with 25 additions and 14 deletions.
  1. +3 −4 lib/lambra/bytecode_compiler.rb
  2. +22 −10 lib/lambra/syntax/ast.rb
View
7 lib/lambra/bytecode_compiler.rb
@@ -322,22 +322,21 @@ def visit_Match(o)
success = g.new_label
done = g.new_label
- o.patterns.each do |pattern|
+ o.patterns.each_with_index do |pattern, idx|
failure = g.new_label
g.dup_top
- pattern.match(self, failure)
+ pattern.match(self, failure) # consumes 1 stack
pattern.execute(self, success)
failure.set!
end
- g.push_self
g.push_cpath_top
g.find_const :ArgumentError
g.push_literal "Pattern match failed"
g.send :new, 1
- g.send :raise, 1, true
+ g.raise_exc
g.goto done
success.set!
View
32 lib/lambra/syntax/ast.rb
@@ -166,7 +166,7 @@ def self.from(list)
attr_reader :value, :actions
- def initialize(value, actions)
+ def initialize(value, actions=[])
@value = value
@actions = actions
end
@@ -176,16 +176,11 @@ def bound
end
def execute(compiler, success, g=compiler.g)
- if bound.empty?
- actions.each_with_index do |action, idx|
- action.accept(compiler)
- g.pop unless actions.count - 1 == idx
- end
- else
- execution_closure.accept(compiler)
+ execution_closure.accept(compiler)
+ if bound.any?
g.swap_stack
- g.send :call, bound.size
end
+ g.send :call, bound.size
g.goto success
end
@@ -209,8 +204,9 @@ def match(compiler, failure, g=compiler.g)
end
class SymbolPattern < Pattern
- def match(compiler, failure)
+ def match(compiler, failure, g=compiler.g)
# always matches
+ g.pop
end
def bound
@@ -221,6 +217,11 @@ def bound
class VectorPattern < Pattern
def match(compiler, failure, g=compiler.g)
match_length(g, failure)
+
+ subpatterns.each_with_index do |pattern, idx|
+ g.shift_array
+ pattern.match(compiler, failure)
+ end
end
def execute(compiler, success, g=compiler.g)
@@ -228,8 +229,19 @@ def execute(compiler, success, g=compiler.g)
g.goto success
end
+ def bound
+ subpatterns.map(&:bound).uniq
+ end
+
private
+ def subpatterns
+ @subpatterns ||= value.elements.map { |x|
+ l = List.new(value.line, value.column, x)
+ Pattern.from(l)
+ }
+ end
+
def match_length(g, failure)
g.send :length, 0
g.push value.elements.length
Please sign in to comment.
Something went wrong with that request. Please try again.