patternmatching 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.1.0 2007-06-03
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 ICHIYAMA Ryoichi
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,25 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ examples/enumerable_matching.rb
7
+ examples/hash_matching.rb
8
+ examples/matching.rb
9
+ examples/object_matching.rb
10
+ examples/partial_style_method.rb
11
+ examples/partial_style_method2.rb
12
+ lib/patternmatching.rb
13
+ lib/patternmatching/pattern.rb
14
+ lib/patternmatching/version.rb
15
+ scripts/makemanifest.rb
16
+ scripts/txt2html
17
+ setup.rb
18
+ spec/patternmatching_spec.rb
19
+ spec/spec.opts
20
+ spec/spec_helper.rb
21
+ website/index.html
22
+ website/index.txt
23
+ website/javascripts/rounded_corners_lite.inc.js
24
+ website/stylesheets/screen.css
25
+ website/template.rhtml
data/README.txt ADDED
@@ -0,0 +1,163 @@
1
+ h1. PatternMatching module
2
+
3
+ h1. → 'patternmatching'
4
+
5
+ h2. What
6
+
7
+ Provides a pure ruby module that:
8
+ * can build structured objects easily
9
+ * can enable pattern match of objects
10
+ * can define method as a partial function style
11
+
12
+ h2. Installing
13
+
14
+ <pre syntax="ruby">sudo gem install patternmatching</pre>
15
+
16
+ h2. The basics
17
+
18
+ This module provides methods for tree pattern matching features.
19
+
20
+ * For detail, see Wikipedia: "Pattern matching":http://en.wikipedia.org/wiki/Pattern_matching
21
+ * Syntax based on meta-programming, like "rspec", and so on.
22
+
23
+ Note: Default equivalence used in structured pattern matching is
24
+ based on "pattern === data", so "foo(Numeric)" matches with "foo(100)"
25
+
26
+ Note: Not thread safe now.
27
+
28
+ h2. Demonstration of usage
29
+
30
+ <h3>Pattern matching expression</h3>
31
+ <pre>
32
+ require "patternmatching"
33
+
34
+ # For DSL style code, include PatternMatching
35
+ include PatternMatching
36
+
37
+ # match example
38
+ def calc(code)
39
+ make(code) {
40
+ seems as {plus(:x, :y)} do calc(x) + calc(y) end
41
+ seems as {mul(:x, :y)} do calc(x) * calc(y) end
42
+ seems something do code end
43
+ }
44
+ end
45
+
46
+ code = build {plus(mul(100, 100), 200)}
47
+ p calc(code) #=> 10200
48
+ </pre>
49
+
50
+ <h3>Partial style method</h3>
51
+ <pre>
52
+ require "patternmatching"
53
+
54
+ # Structured data builder
55
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
56
+
57
+ # Partial style method example
58
+ class Calc
59
+ # At first, extends with the module
60
+ extend PatternMatching
61
+
62
+ # def calcm(o), as 3 partial styles
63
+ func(:calcm).seems as {plus(:x, :y)} do
64
+ calcm(x) + calcm(y)
65
+ end
66
+ func(:calcm).seems as {mul(:x, :y)} do
67
+ calcm(x) * calcm(y)
68
+ end
69
+ func(:calcm).seems as {:value} do
70
+ value
71
+ end
72
+ end
73
+
74
+ # use as standard method
75
+ p Calc.new.calcm(code) #=> 10200
76
+ </pre>
77
+
78
+ <h3>Array/Enumerable pattern</h3>
79
+ <pre>
80
+ require "patternmatching"
81
+
82
+ include PatternMatching
83
+
84
+ # Example for matching Enumerable
85
+ is = build { exact([1,2,3,4,5]) }
86
+ make is do
87
+ # _! matches rest of lists
88
+ seems as {exact([:a,:b, _!(:c)])} do
89
+ puts a.to_s + ", " + b.to_s + " and " + c.to_s
90
+ end
91
+ seems something do
92
+ puts "not matched"
93
+ end
94
+ end # => "1, 2, and 345"
95
+ </pre>
96
+
97
+ <h3>Hash pattern</h3>
98
+ <pre>
99
+ require "patternmatching"
100
+
101
+ include PatternMatching
102
+
103
+ # Example for matching Hash
104
+ dict = build { {:name => "Taro", :age => 5} }
105
+ make dict do
106
+ seems as {{:name => :name}} do
107
+ puts "He is " + name
108
+ end
109
+ seems something do
110
+ puts "no name"
111
+ end
112
+ end # => "He is Taro"
113
+ </pre>
114
+
115
+ <h3>Non-Hash/Object pattern</h3>
116
+ <pre>
117
+ require "patternmatching"
118
+
119
+ include PatternMatching
120
+
121
+ class Person
122
+ def initialize(name, age)
123
+ @name = name
124
+ @age = age
125
+ end
126
+ attr :name
127
+ attr :age
128
+ end
129
+
130
+ # Example for matching Object except Hash
131
+ person = Person.new("Jiro", 3)
132
+ make person do
133
+ seems as {{:name => :name}} do
134
+ puts "He is " + name
135
+ end
136
+ seems something do
137
+ puts "no name"
138
+ end
139
+ end # => "He is Jiro"
140
+ </pre>
141
+
142
+ h2. Forum
143
+
144
+
145
+ h2. How to submit patches
146
+
147
+ Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above.
148
+
149
+ The trunk repository is <code>svn://rubyforge.org/var/svn/patternmatching/trunk</code> for anonymous access.
150
+
151
+ h2. License
152
+
153
+ This code is free to use under the terms of the MIT license.
154
+
155
+ h2. Link
156
+
157
+ * "Web Site":http://patternmatching.rubyforge.org/
158
+ * "Project Page":http://rubyforge.org/projects/patternmatching/
159
+
160
+ h2. Contact
161
+
162
+ Comments are welcome. Send an email to "ICHIYAMA Ryoichi":mailto:bellbind@gmail.com. "My blog":http://d.hatena.ne.jp/bellbind (written in Japanese) could be help you.
163
+
data/Rakefile ADDED
@@ -0,0 +1,143 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ begin
12
+ require 'spec/rake/spectask'
13
+ rescue LoadError
14
+ puts 'To use rspec for testing you must install rspec gem:'
15
+ puts '$ sudo gem install rspec'
16
+ exit
17
+ end
18
+
19
+ include FileUtils
20
+ require File.join(File.dirname(__FILE__), 'lib', 'patternmatching', 'version')
21
+
22
+ AUTHOR = 'ICHIYAMA Ryoichi' # can also be an array of Authors
23
+ EMAIL = "bellbind@gmail.com"
24
+ DESCRIPTION = %{Provide a pure ruby module that
25
+ can build structured objects easily,
26
+ can enable pattern match of objects,
27
+ and can define method as a partial function style.}
28
+ GEM_NAME = 'patternmatching' # what ppl will type to install your gem
29
+
30
+ @config_file = "~/.rubyforge/user-config.yml"
31
+ @config = nil
32
+ def rubyforge_username
33
+ unless @config
34
+ begin
35
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
36
+ rescue
37
+ puts <<-EOS
38
+ ERROR: No rubyforge config file found: #{@config_file}"
39
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
40
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
41
+ EOS
42
+ exit
43
+ end
44
+ end
45
+ @rubyforge_username ||= @config["username"]
46
+ end
47
+
48
+ RUBYFORGE_PROJECT = 'patternmatching' # The unix name for your project
49
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
50
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
51
+
52
+ NAME = "patternmatching"
53
+ REV = nil
54
+ # UNCOMMENT IF REQUIRED:
55
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
56
+ VERS = PatternMatching::VERSION::STRING + (REV ? ".#{REV}" : "")
57
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
58
+ RDOC_OPTS = ['--quiet', '--title', 'patternmatching documentation',
59
+ "--opname", "index.html",
60
+ "--line-numbers",
61
+ "--main", "README",
62
+ "--inline-source"]
63
+
64
+ class Hoe
65
+ def extra_deps
66
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
67
+ end
68
+ end
69
+
70
+ # Generate all the Rake tasks
71
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
72
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
73
+ p.author = AUTHOR
74
+ p.description = DESCRIPTION
75
+ p.email = EMAIL
76
+ p.summary = DESCRIPTION
77
+ p.url = HOMEPATH
78
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
79
+ p.test_globs = ["test/**/test_*.rb"]
80
+ p.clean_globs = CLEAN #An array of file patterns to delete on clean.
81
+
82
+ # == Optional
83
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
84
+ #p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
85
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
86
+ end
87
+
88
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\n\n")
89
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
90
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
91
+
92
+ desc 'Generate website files'
93
+ task :website_generate do
94
+ Dir['website/**/*.txt'].each do |txt|
95
+ sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
96
+ end
97
+ end
98
+
99
+ desc 'Upload website files to rubyforge'
100
+ task :website_upload do
101
+ host = "#{rubyforge_username}@rubyforge.org"
102
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
103
+ local_dir = 'website'
104
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
105
+ end
106
+
107
+ desc 'Generate and upload website files'
108
+ # task :website => [:website_generate]
109
+ task :website => [:website_generate, :website_upload]
110
+
111
+ desc 'Release the website and new gem version'
112
+ task :deploy => [:check_version, :website, :release] do
113
+ puts "Remember to create SVN tag:"
114
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
115
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
116
+ puts "Suggested comment:"
117
+ puts "Tagging release #{CHANGES}"
118
+ end
119
+
120
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
121
+ task :local_deploy => [:website_generate, :install_gem]
122
+
123
+ task :check_version do
124
+ unless ENV['VERSION']
125
+ puts 'Must pass a VERSION=x.y.z release version'
126
+ exit
127
+ end
128
+ unless ENV['VERSION'] == VERS
129
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
130
+ exit
131
+ end
132
+ end
133
+
134
+ desc "Run the specs under spec/models"
135
+ Spec::Rake::SpecTask.new do |t|
136
+ t.spec_opts = ['--options', "spec/spec.opts"]
137
+ t.spec_files = FileList['spec/*_spec.rb']
138
+ t.libs << "lib"
139
+ end
140
+
141
+ desc "Default task is to run specs"
142
+ task :default => :spec
143
+
@@ -0,0 +1,16 @@
1
+
2
+ require "patternmatching"
3
+
4
+ include PatternMatching
5
+
6
+ # Example for matching Enumerable
7
+ inputs = build { exact([1,2,3,4,5]) }
8
+ make inputs do
9
+ # _! matches rests of list
10
+ seems as {exact([:a,:b, _!(:c)])} do
11
+ puts a.to_s + ", " + b.to_s + " and " + c.to_s
12
+ end
13
+ seems something do
14
+ puts "not matched"
15
+ end
16
+ end # => "1, 2, and 345"
@@ -0,0 +1,16 @@
1
+
2
+ require "patternmatching"
3
+
4
+ include PatternMatching
5
+
6
+ # Example for matching Hash
7
+ dict = build { {:name => "Taro", :age => 5} }
8
+ make dict do
9
+ seems as {{:name => :name}} do
10
+ puts "He is " + name
11
+ end
12
+ seems something do
13
+ puts "no name"
14
+ end
15
+ end # => "He is Taro"
16
+
@@ -0,0 +1,19 @@
1
+
2
+ require "patternmatching"
3
+
4
+
5
+ # For DSL style code, include PatternMatching
6
+ include PatternMatching
7
+
8
+ # match example
9
+ def calc(code)
10
+ make (code) {
11
+ seems as {plus(:x, :y)} do calc(x) + calc(y) end
12
+ seems as {mul(:x, :y)} do calc(x) * calc(y) end
13
+ seems something do code end
14
+ }
15
+ end
16
+
17
+
18
+ code = build {plus(mul(100, 100), 200)}
19
+ p calc(code) #=> 10200
@@ -0,0 +1,25 @@
1
+
2
+ require "patternmatching"
3
+
4
+ include PatternMatching
5
+
6
+ class Person
7
+ def initialize(name, age)
8
+ @name = name
9
+ @age = age
10
+ end
11
+ attr :name
12
+ attr :age
13
+ end
14
+
15
+ # Example for matching Object except Hash
16
+ person = Person.new("Jiro", 3)
17
+ make person do
18
+ seems as {{:name => :name}} do
19
+ puts "He is " + name
20
+ end
21
+ seems something do
22
+ puts "no name"
23
+ end
24
+ end # => "He is Jiro"
25
+
@@ -0,0 +1,24 @@
1
+ require "patternmatching"
2
+
3
+ # Structured data builder
4
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
5
+
6
+ # Partial style method example
7
+ class Calc
8
+ # At first, extends with the module
9
+ extend PatternMatching
10
+
11
+ # def calcm(o), as 3 partial styles
12
+ func(:calcm).seems as {plus(:x, :y)} do
13
+ calcm(x) + calcm(y)
14
+ end
15
+ func(:calcm).seems as {mul(:x, :y)} do
16
+ calcm(x) * calcm(y)
17
+ end
18
+ func(:calcm).seems as {:value} do
19
+ value
20
+ end
21
+ end
22
+
23
+ # use as standard method
24
+ p Calc.new.calcm(code)