lib/patternmatching/pattern.rb in patternmatching-0.1.2 vs lib/patternmatching/pattern.rb in patternmatching-0.1.3
- old
+ new
@@ -1,16 +1,20 @@
module PatternMatching
+ #Private Exception for stop matching
class NotMatched < Exception
end
+ #Private class for build structured data
class NodeBuilder
+ private
def method_missing(name, *args)
Node.new(name, args)
end
end
+ #Class for structured data/patterns
class Node
def initialize(name, children)
@name = name
@children = children
end
@@ -21,11 +25,12 @@
def size
@children.size
end
end
- class Collector
+ #Private module for pattern matching and to collect var/val pairs
+ module Collector
def self.walk(source, target, list)
case source
when Symbol
list[source] = target
when Node
@@ -97,10 +102,11 @@
raise NotMatched.new
end
end
end
+ #Private class to run pattern matching
class MatchExec
def self.exec_as(target, patterns, receiver)
patterns.each do |pair|
pattern = pair.keys[0]
action = pair[pattern]
@@ -113,10 +119,12 @@
end
return ExecuteAs.new(args, receiver).call(&action)
end
end
+ #Private class enabling to use the name of symbols in patterns
+ #like a local variables in action blocks
class ExecuteAs
def initialize(args, receiver)
@this = receiver
@args = args
end
@@ -139,10 +147,11 @@
result
end
end
end
+ #Private class for collecting pattern/action fragments
class PatternFragments
def initialize(patterns)
@patterns = patterns
end
def seems(pattern, &action)
@@ -155,143 +164,81 @@
def something
proc {_}
end
end
- # DSL element
- def build(&block)
- NodeBuilder.new.instance_eval(&block)
- end
- def self.build(&block)
- NodeBuilder.new.instance_eval(&block)
- end
- def make(target, &block)
- patterns = []
- PatternFragments.new(patterns).instance_eval(&block)
- MatchExec.exec_as(target, patterns, self)
- end
- def as(&block)
- block
- end
- def something
- proc {_}
- end
- def func(name, &block)
- pattern_name = ("@_pattern_" + name.to_s ).to_sym
- unless method_defined?(name)
+ # Domain Specific Language style methods
+ module DSL
+ #Build structured data
+ #=== Usage
+ # build {[foo(bar, 100), foo(buzz, "abc")]}
+ def build(&block)
+ NodeBuilder.new.instance_eval(&block)
+ end
+
+ #Build structured data
+ #=== Usage
+ # PatternMatching.build {[foo(bar, 100), foo(buzz, "abc")]}
+ def self.build(&block)
+ NodeBuilder.new.instance_eval(&block)
+ end
+
+ #Do pattern matching
+ #===Usage
+ # make TARGET do
+ # seems as {PATTERN_1} do ACTION_1 end
+ # seems as {PATTERN_2} do ACTION_2 end
+ # seems something do ACTION_DEFAULT end
+ # end
+ def make(target, &block)
patterns = []
- instance_variable_set(pattern_name, patterns)
- define_method(name) do |target|
- MatchExec.exec_as(target, patterns, self)
- end
+ PatternFragments.new(patterns).instance_eval(&block)
+ MatchExec.exec_as(target, patterns, self)
end
- patterns = instance_variable_get(pattern_name)
- fragments = PatternFragments.new(patterns)
- if block
- fragments.instance_eval(&block)
+
+ #A pattern matches description inside block
+ #=== Usage
+ # seems as {some pattern...} do ... end
+ def as(&block)
+ block
end
- fragments
- end
-end
-
-=begin
-# If installed from rubygems
-require "rubygems"
-gem "patternmatching"
-
-# for use
-require "patternmatching"
-
-
-# partial func example
-class Calc
- extend PatternMatching
-
- func(:calcm).seems as {plus(:a, :b)} do
- calcm(a) + calcm(b)
- end
- func(:calcm).seems as {mul(:a, :b)} do
- calcm(a) * calcm(b)
- end
- func(:calcm).seems as {:value} do
- value
- end
-end
-
-val = 200
-code = PatternMatching.build {plus(mul(100, 100), val)}
-p Calc.new.calcm(code)
-
-# another partial func example
-class CalcX
- extend PatternMatching
-
- func(:calcx) do
- seems as {plus(:a, :b)} do
- calcx(a) + calcx(b)
+
+ #A pattern matches anything
+ #=== Usage
+ # seems something do ... end
+ def something
+ proc {_}
end
- seems as {mul(:a, :b)} do
- calcx(a) * calcx(b)
+
+ #Define method as partial style
+ #=== Usage
+ # func(NAME).seems as {PATTERN_1} do ACTION_1 end
+ # func(NAME).seems as {PATTERN_2} do ACTION_2 end
+ # func(NAME).seems something do ACTION_DEFAULT end
+ #
+ #or
+ #
+ # func NAME do
+ # seems as {PATTERN_1} do ACTION_1 end
+ # seems as {PATTERN_2} do ACTION_2 end
+ # seems something do ACTION_DEFAULT end
+ # end
+ #
+ def func(name, &block)
+ pattern_name = ("@_pattern_" + name.to_s ).to_sym
+ unless method_defined?(name)
+ patterns = []
+ instance_variable_set(pattern_name, patterns)
+ define_method(name) do |target|
+ MatchExec.exec_as(target, patterns, self)
+ end
+ end
+ patterns = instance_variable_get(pattern_name)
+ fragments = PatternFragments.new(patterns)
+ if block
+ fragments.instance_eval(&block)
+ end
+ fragments
end
end
- func(:calcx).seems as {:value} do
- value
- end
+ include DSL
end
-
-p CalcX.new.calcx(code)
-
-# pattern example
-include PatternMatching
-
-def calc(code)
- make(code) {
- seems as {plus(:a, :b)} do calc(a) + calc(b) end
- seems as {mul(:a, :b)} do calc(a) * calc(b) end
- seems something do code end
- }
-end
-
-p calc(code)
-
-
-# enumerable match example
-is = build { exact([1,2,3,4,5]) }
-make is do
- seems as {exact([:a,:b, _!(:c)])} do
- puts a.to_s + ", " + b.to_s + " and " + c.to_s
- end
- seems something do
- puts "not matched"
- end
-end
-
-# hash to hash match example
-dict = build { {:name => "Taro", :age => 5} }
-make dict do
- seems as {{:name => :name}} do
- puts "He is " + name
- end
- seems something do
- puts "no name"
- end
-end
-
-# hash to obj match example
-class Person
- def initialize(name, age)
- @name = name
- @age = age
- end
- attr :name
- attr :age
-end
-
-make Person.new("Jiro", 3) do
- seems as {{:name => :name}} do
- puts "He is " + name
- end
- seems something do
- puts "no name"
- end
-end
-=end