patternmatching 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)