rubype 0.0.1 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8245a625a95d3dc343ff7fc3b8b174ade30da9a3
4
- data.tar.gz: cd5dc17e64353d10ce7edd75e99be2042346ea04
3
+ metadata.gz: 8d3acd50cc84b3a88ae2270111796825a1d7b916
4
+ data.tar.gz: 53745d33a11a70db20b39199df8cd54115cf3e6e
5
5
  SHA512:
6
- metadata.gz: 69b14ea4de852e73345b8c91317b0625afd0244fde38f019fa4590beac853e2c52f624571cba7506e5dfde740a3f55454b1580332dec45b8c4db82b0b3b65b55
7
- data.tar.gz: 59bcb2b702a7c9fbf2a9b9e2d48dcea0cdff1ad4116bff6b260648e046b2cae2e0c7ee3245b0a8ec4905b3a80f187817ad0b55e2e356b8cf88b079f570b2feeb
6
+ metadata.gz: 28374048f7e03c8611d69d1cc6ee842ed93e0cda775968f0e9f4d1e7da31f29a6694fd136445d8c93864403fa0ed97001bc08cdbeb14d85447326c81070829e8
7
+ data.tar.gz: b0faae01aa81746ca428efd63993969b6f4c4d4f8437b5a4fd76051b7bd7ecf48f1cd78bed70bb2470a140c57dcbe8dd161c0b27bc41bc023a282c799f4ccc51
data/.travis.yml CHANGED
@@ -1,3 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.1.2
4
+ - 2.0.0
5
+ - 1.9.3
6
+ notifications:
7
+ email: false
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in rubype.gemspec
3
+ gem 'pry'
4
4
  gemspec
data/README.md CHANGED
@@ -1,31 +1,116 @@
1
- # Rubype
1
+ # Ruby with Type.
2
2
 
3
- TODO: Write a gem description
3
+ Matz has mentioned Ruby3.0 with static type at some confluences. But almost all rubyists(include me) are not sure how typed Ruby is.
4
4
 
5
- ## Installation
5
+ But it's worth thinking more. This gem is kind of trial without so much side-effect.
6
+
7
+ ```rb
8
+ require 'rubype'
9
+
10
+ # ex1
11
+ class MyClass
12
+ def sum(x, y)
13
+ x + y
14
+ end
15
+ type Numeric, Numeric >= Numeric, :sum
16
+
17
+ def wrong_sum(x, y)
18
+ 'string'
19
+ end
20
+ type Numeric, Numeric >= Numeric, :sum
21
+ end
22
+
23
+ MyClass.new.sum(1, 2)
24
+ #=> 3
25
+
26
+ MyClass.new.sum(1, 'string')
27
+ #=> ArgumentError: Wrong type of argument, type of "str" should be Numeric
28
+
29
+ MyClass.new.wrong_sum(1, 2)
30
+ #=> TypeError: Expected wrong_sum to return Numeric but got "str" instead
31
+
32
+ # ex2: (Ruby 2.1.0+)
33
+ class MyClass
34
+ type Numeric, Numeric >= Numeric, def sum(x, y)
35
+ x + y
36
+ end
37
+
38
+ type Numeric, Numeric >= Numeric, def wrong_sum(x, y)
39
+ 'string'
40
+ end
41
+ end
42
+
43
+ # ex3: (Ruby 2.1.0+)
44
+ class People
45
+ type People >= Any, def marry(people)
46
+ # Your Ruby code as usual
47
+ end
48
+ end
49
+
50
+ People.new.marry(People.new)
51
+ #=> no error
52
+
53
+ People.new.marry('non people')
54
+ #=> ArgumentError: Wrong type of argument, type of "non people" should be People
55
+ ```
6
56
 
7
- Add this line to your application's Gemfile:
57
+ ## Feature
58
+ ### Typed method can coexist with non-typed method
8
59
 
9
60
  ```ruby
10
- gem 'rubype'
61
+ # It's totally OK!!
62
+ class MyClass
63
+ def sum(x, y)
64
+ x + y
65
+ end
66
+ type Numeric, Numeric >= Numeric, :sum
67
+
68
+ def wrong_sum(x, y)
69
+ 'string'
70
+ end
71
+ end
72
+ ```
73
+
74
+ ### Duck typing
75
+
76
+ ```ruby
77
+
78
+ class MyClass
79
+ def foo(any_obj)
80
+ 1
81
+ end
82
+ type Any >= Numeric, :foo
83
+ end
84
+
85
+ # It's totally OK!!
86
+ MyClass.new.foo(1)
87
+ # It's totally OK!!
88
+ MyClass.new.foo('str')
11
89
  ```
12
90
 
13
- And then execute:
91
+ ## Installation
92
+
93
+ gem install rubype or add gem 'rubype' to your Gemfile.
94
+
95
+ This gem requires Ruby 2.0.0+.
96
+
97
+ ### Contributing
98
+
99
+ Fork it ( https://github.com/[my-github-username]/rubype/fork )
100
+
101
+ Create your feature branch (`git checkout -b my-new-feature`)
14
102
 
15
- $ bundle
103
+ $ bundle install --path vendor/bundle
16
104
 
17
- Or install it yourself as:
105
+ Commit your changes (`git commit -am 'Add some feature'`)
18
106
 
19
- $ gem install rubype
107
+ $ bundle exec rake test
20
108
 
21
- ## Usage
109
+ > 5 runs, 39 assertions, 0 failures, 0 errors, 0 skips
22
110
 
23
- TODO: Write usage instructions here
111
+ Push to the branch (`git push origin my-new-feature`)
24
112
 
25
- ## Contributing
113
+ Create a new Pull Request
26
114
 
27
- 1. Fork it ( https://github.com/[my-github-username]/rubype/fork )
28
- 2. Create your feature branch (`git checkout -b my-new-feature`)
29
- 3. Commit your changes (`git commit -am 'Add some feature'`)
30
- 4. Push to the branch (`git push origin my-new-feature`)
31
- 5. Create a new Pull Request
115
+ ## Credits
116
+ [@chancancode](https://github.com/chancancode) first brought this to my attention. I've stolen some idea from him.
@@ -0,0 +1,7 @@
1
+ class TypePair < Struct.new(:last_arg_type, :rtn_type); end
2
+
3
+ class Module
4
+ def >=(r)
5
+ TypePair.new(self, r)
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module Rubype
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/rubype.rb CHANGED
@@ -1,6 +1,49 @@
1
- require "rubype/version"
2
- require "rubype/rubype"
1
+ require 'rubype/type_pair'
2
+
3
+ # Builtin Contracts
4
+ class Any; end
5
+ module Boolean; end
6
+ TrueClass.send(:include, Boolean)
7
+ FalseClass.send(:include, Boolean)
8
+
9
+ class Module
10
+ private
11
+ def __rubype__
12
+ prepend (@__rubype__ = Module.new) unless @__rubype__
13
+ @__rubype__
14
+ end
15
+
16
+ def type(*arguments)
17
+ *arg_types, type_pair, meth = arguments
18
+
19
+ __rubype__.send(:define_method, meth) do |*args, &block|
20
+ ::Rubype.assert_arg_type(meth, args, arg_types << type_pair.last_arg_type)
21
+ rtn = super(*args, &block)
22
+ ::Rubype.assert_trn_type(meth, rtn, type_pair.rtn_type)
23
+ rtn
24
+ end
25
+ self
26
+ end
27
+ end
3
28
 
4
29
  module Rubype
5
- # Your code goes here...
30
+ class << self
31
+ def assert_arg_type(meth, args, klasses)
32
+ args.each_with_index do |arg, i|
33
+ if wrong_type?(arg, klasses[i])
34
+ raise ArgumentError, "Wrong type of argument, type of #{arg.inspect} should be #{klasses[i]}"
35
+ end
36
+ end
37
+ end
38
+
39
+ def assert_trn_type(meth, rtn, klass)
40
+ if wrong_type?(rtn, klass)
41
+ raise TypeError, "Expected #{meth} to return #{klass} but got #{rtn.inspect} instead"
42
+ end
43
+ end
44
+
45
+ def wrong_type?(obj, klass)
46
+ !(obj.is_a?(klass) || klass == Any)
47
+ end
48
+ end
6
49
  end
data/rubype.gemspec CHANGED
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["gogotanaka"]
10
10
  spec.email = ["mail@tanakakazuki.com"]
11
11
  spec.extensions = ["ext/rubype/extconf.rb"]
12
- spec.summary = %q{ Ruby with typed method.}
13
- spec.description = %q{ Ruby with typed method.}
14
- spec.homepage = ""
12
+ spec.summary = %q{Ruby with type.}
13
+ spec.description = %q{Ruby with type.}
14
+ spec.homepage = "http://azabuhs.org/"
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0")
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.7"
23
- spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "bundler"
23
+ spec.add_development_dependency "rake"
24
24
  spec.add_development_dependency "rake-compiler"
25
25
  spec.add_development_dependency "minitest"
26
26
  end
data/test/test_rubype.rb CHANGED
@@ -1,11 +1,113 @@
1
1
  require 'minitest_helper'
2
-
2
+ class TypePair
3
+ def to_s
4
+ "#{last_arg_type} >= #{rtn_type}"
5
+ end
6
+ end
3
7
  class TestRubype < MiniTest::Unit::TestCase
4
- def test_that_it_has_a_version_number
5
- refute_nil ::Rubype::VERSION
8
+ def setup
9
+ @string = 'str'
10
+ @numeric = 1
11
+ @symbol = :test
12
+ @array = [1, 2, 3]
13
+ @hash = { test: :hash }
14
+ end
15
+
16
+ def test_type_list
17
+ assert_equal_to_s "Numeric >= Numeric", Numeric >= Numeric
18
+ assert_equal_to_s "Numeric >= Array", Numeric >= Array
19
+ assert_equal_to_s "Array >= String", Array >= String
20
+ end
21
+
22
+ def test_correct_type
23
+ assert_correct_type [Numeric >= Numeric], [@numeric], @numeric
24
+ assert_correct_type [Numeric >= Array ], [@numeric], @array
25
+ assert_correct_type [Numeric >= String ], [@numeric], @string
26
+ assert_correct_type [Numeric >= Hash ], [@numeric], @hash
27
+ assert_correct_type [Numeric >= Symbol ], [@numeric], @symbol
28
+ assert_correct_type [Numeric >= Boolean], [@numeric], true
29
+ assert_correct_type [Numeric >= Boolean], [@numeric], false
30
+
31
+ assert_correct_type [Boolean, Numeric >= Numeric], [true, @numeric], @numeric
32
+ assert_correct_type [Boolean, Array >= Array ], [true, @array ], @array
33
+ assert_correct_type [Boolean, String >= String ], [true, @string ], @string
34
+ assert_correct_type [Boolean, Hash >= Hash ], [true, @hash ], @hash
35
+ assert_correct_type [Boolean, Symbol >= Symbol ], [true, @symbol ], @symbol
36
+ end
37
+
38
+ def test_wrong_return_type
39
+ assert_wrong_rtn [Numeric >= Numeric], [@numeric], @array
40
+ assert_wrong_rtn [Numeric >= Numeric], [@numeric], @string
41
+ assert_wrong_rtn [Numeric >= Numeric], [@numeric], @hash
42
+ assert_wrong_rtn [Numeric >= Numeric], [@numeric], @symbol
43
+ assert_wrong_rtn [Numeric >= Numeric], [@numeric], true
44
+
45
+ assert_wrong_rtn [Numeric, Numeric >= Numeric], [@numeric, @numeric], @array
46
+ assert_wrong_rtn [Numeric, Numeric >= Numeric], [@numeric, @numeric], @string
47
+ assert_wrong_rtn [Numeric, Numeric >= Numeric], [@numeric, @numeric], @hash
48
+ assert_wrong_rtn [Numeric, Numeric >= Numeric], [@numeric, @numeric], @symbol
49
+ assert_wrong_rtn [Numeric, Numeric >= Numeric], [@numeric, @numeric], true
6
50
  end
7
51
 
8
- def test_it_does_something_useful
9
- assert false
52
+ def test_wrong_args_type
53
+ assert_wrong_arg [Numeric >= Numeric], [@array ], @numeric
54
+ assert_wrong_arg [Numeric >= Numeric], [@string], @numeric
55
+ assert_wrong_arg [Numeric >= Numeric], [@hash ], @numeric
56
+ assert_wrong_arg [Numeric >= Numeric], [@symbol], @numeric
57
+ assert_wrong_arg [Numeric >= Numeric], [true ], @numeric
58
+
59
+ assert_wrong_arg [Numeric, Numeric >= Numeric], [@numeric, @array ], @numeric
60
+ assert_wrong_arg [Numeric, Numeric >= Numeric], [@numeric, @string], @numeric
61
+ assert_wrong_arg [Numeric, Numeric >= Numeric], [@numeric, @hash ], @numeric
62
+ assert_wrong_arg [Numeric, Numeric >= Numeric], [@numeric, @symbol], @numeric
63
+ assert_wrong_arg [Numeric, Numeric >= Numeric], [@numeric, true ], @numeric
10
64
  end
65
+
66
+ def test_any
67
+ assert_correct_type [Any >= Any], [@array ], @numeric
68
+ assert_correct_type [Any >= Any], [@string], @numeric
69
+ assert_correct_type [Any >= Any], [@hash ], @numeric
70
+ assert_correct_type [Any >= Any], [@symbol], @numeric
71
+
72
+ assert_correct_type [Any, Any >= Any], [@numeric, @array ], @numeric
73
+ assert_correct_type [Any, Any >= Any], [@numeric, @string], @numeric
74
+ assert_correct_type [Any, Any >= Any], [@numeric, @hash ], @numeric
75
+ assert_correct_type [Any, Any >= Any], [@numeric, @symbol], @numeric
76
+ end
77
+
78
+ private
79
+ def assert_equal_to_s(str, val)
80
+ assert_equal str, val.to_s
81
+ end
82
+
83
+ def assert_correct_type(type_list, args, val)
84
+ assert_equal val, define_test_method(type_list, args, val).call(*args)
85
+ end
86
+
87
+ def assert_wrong_arg(type_list, args, val)
88
+ assert_raises(ArgumentError) { define_test_method(type_list, args, val).call(*args) }
89
+ end
90
+
91
+ def assert_wrong_rtn(type_list, args, val)
92
+ assert_raises(TypeError) { define_test_method(type_list, args, val).call(*args) }
93
+ end
94
+
95
+ def define_test_method(type_list, args, val)
96
+ klass = Class.new.class_eval <<-RUBY_CODE
97
+ def call(#{arg_literal(args.count)})
98
+ #{obj_literal(val)}
99
+ end
100
+ type #{type_list.map(&:to_s).join(',')}, :call
101
+ RUBY_CODE
102
+
103
+ klass.new
104
+ end
105
+
106
+ def obj_literal(obj)
107
+ "ObjectSpace._id2ref(#{obj.__id__})"
108
+ end
109
+
110
+ def arg_literal(count)
111
+ ('a'..'z').to_a[0..count-1].join(',')
112
+ end
11
113
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gogotanaka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-05 00:00:00.000000000 Z
11
+ date: 2014-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.7'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.7'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake-compiler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: " Ruby with typed method."
69
+ description: Ruby with type.
70
70
  email:
71
71
  - mail@tanakakazuki.com
72
72
  executables:
@@ -86,11 +86,12 @@ files:
86
86
  - ext/rubype/rubype.c
87
87
  - ext/rubype/rubype.h
88
88
  - lib/rubype.rb
89
+ - lib/rubype/type_pair.rb
89
90
  - lib/rubype/version.rb
90
91
  - rubype.gemspec
91
92
  - test/minitest_helper.rb
92
93
  - test/test_rubype.rb
93
- homepage: ''
94
+ homepage: http://azabuhs.org/
94
95
  licenses:
95
96
  - MIT
96
97
  metadata: {}
@@ -113,7 +114,7 @@ rubyforge_project:
113
114
  rubygems_version: 2.2.2
114
115
  signing_key:
115
116
  specification_version: 4
116
- summary: Ruby with typed method.
117
+ summary: Ruby with type.
117
118
  test_files:
118
119
  - test/minitest_helper.rb
119
120
  - test/test_rubype.rb