rtype 0.6.8-java

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.
@@ -0,0 +1,200 @@
1
+ require 'benchmark/ips'
2
+
3
+ is_mri = RUBY_ENGINE == 'ruby'
4
+
5
+ require "rtype"
6
+ require "rubype" if is_mri
7
+ require "sig"
8
+ require "contracts"
9
+ require "contracts/version"
10
+ require "typecheck"
11
+
12
+ puts "Ruby version: #{RUBY_VERSION}"
13
+ puts "Ruby engine: #{RUBY_ENGINE}"
14
+ puts "Ruby description: #{RUBY_DESCRIPTION}"
15
+
16
+ puts "Rtype version: #{Rtype::VERSION}"
17
+ puts "Rubype version: #{Rubype::VERSION}" if is_mri
18
+ puts "Sig version: #{Sig::VERSION}"
19
+ puts "Contracts version: #{Contracts::VERSION}"
20
+ puts "Typecheck version: #{Typecheck::VERSION}"
21
+
22
+ if !Rtype::NATIVE_EXT_VERSION.nil?
23
+ puts "Rtype with native extension"
24
+ elsif !Rtype::JAVA_EXT_VERSION.nil?
25
+ puts "Rtype with java extension"
26
+ else
27
+ puts "Rtype without native extension"
28
+ end
29
+
30
+ class PureTest
31
+ def sum(x, y)
32
+ x + y
33
+ end
34
+
35
+ def mul(x, y)
36
+ x * y
37
+ end
38
+
39
+ def args(a, b, c, d)
40
+ end
41
+ end
42
+ pure_obj = PureTest.new
43
+
44
+ class RtypeTest
45
+ rtype [Numeric, Numeric] => Numeric
46
+ def sum(x, y)
47
+ x + y
48
+ end
49
+
50
+ rtype [:to_i, :to_i] => Numeric
51
+ def mul(x, y)
52
+ x * y
53
+ end
54
+
55
+ rtype [Integer, Numeric, String, :to_i] => Any
56
+ def args(a, b, c, d)
57
+ end
58
+ end
59
+ rtype_obj = RtypeTest.new
60
+
61
+ if is_mri
62
+ class RubypeTest
63
+ def sum(x, y)
64
+ x + y
65
+ end
66
+ typesig :sum, [Numeric, Numeric] => Numeric
67
+
68
+ def mul(x, y)
69
+ x * y
70
+ end
71
+ typesig :mul, [:to_i, :to_i] => Numeric
72
+
73
+ def args(a, b, c, d)
74
+ end
75
+ typesig :args, [Integer, Numeric, String, :to_i] => Any
76
+ end
77
+ rubype_obj = RubypeTest.new
78
+ end
79
+
80
+ class SigTest
81
+ sig [Numeric, Numeric], Numeric,
82
+ def sum(x, y)
83
+ x + y
84
+ end
85
+
86
+ sig [:to_i, :to_i], Numeric,
87
+ def mul(x, y)
88
+ x * y
89
+ end
90
+
91
+ # nil means wildcard
92
+ sig [Integer, Numeric, String, :to_i], nil,
93
+ def args(a, b, c, d)
94
+ end
95
+ end
96
+ sig_obj = SigTest.new
97
+
98
+ class ContractsTest
99
+ include Contracts
100
+
101
+ Contract Num, Num => Num
102
+ def sum(x, y)
103
+ x + y
104
+ end
105
+
106
+ Contract RespondTo[:to_i], RespondTo[:to_i] => Num
107
+ def mul(x, y)
108
+ x * y
109
+ end
110
+
111
+ Contract Int, Num, String, RespondTo[:to_i] => Any
112
+ def args(a, b, c, d)
113
+ end
114
+ end
115
+ contracts_obj = ContractsTest.new
116
+
117
+ class TypecheckTest
118
+ extend Typecheck
119
+
120
+ typecheck 'Numeric, Numeric -> Numeric',
121
+ def sum(x, y)
122
+ x + y
123
+ end
124
+
125
+ typecheck '#to_i, #to_i -> Numeric',
126
+ def mul(x, y)
127
+ x * y
128
+ end
129
+
130
+ typecheck 'Integer, Numeric, String, #to_i -> BasicObject',
131
+ def args(a, b, c, d)
132
+ end
133
+ end
134
+ typecheck_obj = TypecheckTest.new
135
+
136
+ Benchmark.ips do |x|
137
+ x.report("pure") do |times|
138
+ i = 0
139
+ while i < times
140
+ pure_obj.sum(1, 2)
141
+ pure_obj.mul(1, 2)
142
+ pure_obj.args(1, 2, "c", 4)
143
+ i += 1
144
+ end
145
+ end
146
+
147
+ x.report("rtype") do |times|
148
+ i = 0
149
+ while i < times
150
+ rtype_obj.sum(1, 2)
151
+ rtype_obj.mul(1, 2)
152
+ rtype_obj.args(1, 2, "c", 4)
153
+ i += 1
154
+ end
155
+ end
156
+
157
+ if is_mri
158
+ x.report("rubype") do |times|
159
+ i = 0
160
+ while i < times
161
+ rubype_obj.sum(1, 2)
162
+ rubype_obj.mul(1, 2)
163
+ rubype_obj.args(1, 2, "c", 4)
164
+ i += 1
165
+ end
166
+ end
167
+ end
168
+
169
+ x.report("sig") do |times|
170
+ i = 0
171
+ while i < times
172
+ sig_obj.sum(1, 2)
173
+ sig_obj.mul(1, 2)
174
+ sig_obj.args(1, 2, "c", 4)
175
+ i += 1
176
+ end
177
+ end
178
+
179
+ x.report("contracts") do |times|
180
+ i = 0
181
+ while i < times
182
+ contracts_obj.sum(1, 2)
183
+ contracts_obj.mul(1, 2)
184
+ contracts_obj.args(1, 2, "c", 4)
185
+ i += 1
186
+ end
187
+ end
188
+
189
+ x.report("typecheck") do |times|
190
+ i = 0
191
+ while i < times
192
+ typecheck_obj.sum(1, 2)
193
+ typecheck_obj.mul(1, 2)
194
+ typecheck_obj.args(1, 2, "c", 4)
195
+ i += 1
196
+ end
197
+ end
198
+
199
+ x.compare!
200
+ end
@@ -0,0 +1,4 @@
1
+ module Rtype
2
+ class ArgumentTypeError < ArgumentError
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ module Rtype
2
+ module Behavior
3
+ class And < Base
4
+ def initialize(*types)
5
+ @types = types
6
+ end
7
+
8
+ def valid?(value)
9
+ @types.all? do |e|
10
+ Rtype::valid? e, value
11
+ end
12
+ end
13
+
14
+ def error_message(value)
15
+ arr = @types.map { |e| Rtype::type_error_message(e, value) }
16
+ arr.join "\nAND "
17
+ end
18
+ end
19
+ end
20
+
21
+ def self.and(*args)
22
+ Behavior::And[*args]
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ module Rtype
2
+ module Behavior
3
+ class Base
4
+ def self.[](*vals)
5
+ new(*vals)
6
+ end
7
+
8
+ def valid?(value)
9
+ raise NotImplementedError, "Abstract method"
10
+ end
11
+
12
+ def error_message(value)
13
+ raise NotImplementedError, "Abstract method"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,174 @@
1
+ class Object
2
+ # @return [Rtype::Behavior::And]
3
+ def and(*others)
4
+ ::Rtype::and(self, *others)
5
+ end
6
+
7
+ # @return [Rtype::Behavior::Nilable]
8
+ def nilable
9
+ ::Rtype::nilable(self)
10
+ end
11
+ alias_method :or_nil, :nilable
12
+
13
+ # @return [Rtype::Behavior::Not]
14
+ def not
15
+ ::Rtype::not(self)
16
+ end
17
+
18
+ # @return [Rtype::Behavior::Xor]
19
+ def xor(*others)
20
+ ::Rtype::xor(self, *others)
21
+ end
22
+ end
23
+
24
+ class Array
25
+ # @return [Rtype::Behavior::TypedArray]
26
+ def self.of(type_sig)
27
+ ::Rtype::Behavior::TypedArray.new(type_sig)
28
+ end
29
+
30
+ # @return [Rtype::Behavior::And]
31
+ def comb
32
+ ::Rtype::Behavior::And[*self]
33
+ end
34
+ end
35
+
36
+ class Set
37
+ # @return [Rtype::Behavior::TypedSet]
38
+ def self.of(type_sig)
39
+ ::Rtype::Behavior::TypedSet.new(type_sig)
40
+ end
41
+ end
42
+
43
+ class Hash
44
+ # @return [Rtype::Behavior::TypedHash]
45
+ def self.of(key_type, value_type)
46
+ ::Rtype::Behavior::TypedHash.new(key_type, value_type)
47
+ end
48
+ end
49
+
50
+ class Num
51
+ # @param [Numeric] x
52
+ # @return [Rtype::Behavior::NumericCheck]
53
+ # @example Value must be a Numeric and > 2
54
+ # rtype [Num > 2] => Any
55
+ def self.>(x)
56
+ ::Rtype::Behavior::NumericCheck.new(:>, x)
57
+ end
58
+
59
+ # @param [Numeric] x
60
+ # @return [Rtype::Behavior::NumericCheck]
61
+ # @example Value must be a Numeric and > 2
62
+ # rtype [Num > 2] => Any
63
+ def self.>=(x)
64
+ ::Rtype::Behavior::NumericCheck.new(:>=, x)
65
+ end
66
+
67
+ # @param [Numeric] x
68
+ # @return [Rtype::Behavior::NumericCheck]
69
+ # @example Value must be a Numeric and > 2
70
+ # rtype [Num > 2] => Any
71
+ def self.<(x)
72
+ ::Rtype::Behavior::NumericCheck.new(:<, x)
73
+ end
74
+
75
+ # @param [Numeric] x
76
+ # @return [Rtype::Behavior::NumericCheck]
77
+ # @example Value must be a Numeric and > 2
78
+ # rtype [Num > 2] => Any
79
+ def self.<=(x)
80
+ ::Rtype::Behavior::NumericCheck.new(:<=, x)
81
+ end
82
+
83
+ # @param [Numeric] x
84
+ # @return [Rtype::Behavior::NumericCheck]
85
+ # @example Value must be a Numeric and > 2
86
+ # rtype [Num > 2] => Any
87
+ def self.==(x)
88
+ ::Rtype::Behavior::NumericCheck.new(:==, x)
89
+ end
90
+ end
91
+
92
+ class Int
93
+ # @param [Numeric] x
94
+ # @return [Rtype::Behavior::IntegerCheck]
95
+ # @example Value must be a Integer and > 2
96
+ # rtype [Int > 2] => Any
97
+ def self.>(x)
98
+ ::Rtype::Behavior::IntegerCheck.new(:>, x)
99
+ end
100
+
101
+ # @param [Numeric] x
102
+ # @return [Rtype::Behavior::IntegerCheck]
103
+ # @example Value must be a Integer and > 2
104
+ # rtype [Int > 2] => Any
105
+ def self.>=(x)
106
+ ::Rtype::Behavior::IntegerCheck.new(:>=, x)
107
+ end
108
+
109
+ # @param [Numeric] x
110
+ # @return [Rtype::Behavior::IntegerCheck]
111
+ # @example Value must be a Integer and > 2
112
+ # rtype [Int > 2] => Any
113
+ def self.<(x)
114
+ ::Rtype::Behavior::IntegerCheck.new(:<, x)
115
+ end
116
+
117
+ # @param [Numeric] x
118
+ # @return [Rtype::Behavior::IntegerCheck]
119
+ # @example Value must be a Integer and > 2
120
+ # rtype [Int > 2] => Any
121
+ def self.<=(x)
122
+ ::Rtype::Behavior::IntegerCheck.new(:<=, x)
123
+ end
124
+
125
+ # @param [Numeric] x
126
+ # @return [Rtype::Behavior::IntegerCheck]
127
+ # @example Value must be a Integer and > 2
128
+ # rtype [Int > 2] => Any
129
+ def self.==(x)
130
+ ::Rtype::Behavior::IntegerCheck.new(:==, x)
131
+ end
132
+ end
133
+
134
+ class Flo
135
+ # @param [Numeric] x
136
+ # @return [Rtype::Behavior::FloatCheck]
137
+ # @example Value must be a Float and > 2
138
+ # rtype [Flo > 2] => Any
139
+ def self.>(x)
140
+ ::Rtype::Behavior::FloatCheck.new(:>, x)
141
+ end
142
+
143
+ # @param [Numeric] x
144
+ # @return [Rtype::Behavior::FloatCheck]
145
+ # @example Value must be a Float and > 2
146
+ # rtype [Flo > 2] => Any
147
+ def self.>=(x)
148
+ ::Rtype::Behavior::FloatCheck.new(:>=, x)
149
+ end
150
+
151
+ # @param [Numeric] x
152
+ # @return [Rtype::Behavior::FloatCheck]
153
+ # @example Value must be a Float and > 2
154
+ # rtype [Flo > 2] => Any
155
+ def self.<(x)
156
+ ::Rtype::Behavior::FloatCheck.new(:<, x)
157
+ end
158
+
159
+ # @param [Numeric] x
160
+ # @return [Rtype::Behavior::FloatCheck]
161
+ # @example Value must be a Float and > 2
162
+ # rtype [Flo > 2] => Any
163
+ def self.<=(x)
164
+ ::Rtype::Behavior::FloatCheck.new(:<=, x)
165
+ end
166
+
167
+ # @param [Numeric] x
168
+ # @return [Rtype::Behavior::FloatCheck]
169
+ # @example Value must be a Float and > 2
170
+ # rtype [Flo > 2] => Any
171
+ def self.==(x)
172
+ ::Rtype::Behavior::FloatCheck.new(:==, x)
173
+ end
174
+ end
@@ -0,0 +1,17 @@
1
+ module Rtype
2
+ module Behavior
3
+ class FloatCheck < NumericCheck
4
+ def valid?(value)
5
+ if value.is_a?(Float)
6
+ @lambda.call(value)
7
+ else
8
+ false
9
+ end
10
+ end
11
+
12
+ def error_message(value)
13
+ "Expected #{value.inspect} to be a float #{@condition} #{@x}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Rtype
2
+ module Behavior
3
+ class IntegerCheck < NumericCheck
4
+ def valid?(value)
5
+ if value.is_a?(Integer)
6
+ @lambda.call(value)
7
+ else
8
+ false
9
+ end
10
+ end
11
+
12
+ def error_message(value)
13
+ "Expected #{value.inspect} to be an integer #{@condition} #{@x}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Rtype
2
+ module Behavior
3
+ class Nilable < Base
4
+ def initialize(type)
5
+ @type = type
6
+ end
7
+
8
+ def valid?(value)
9
+ value.nil? || Rtype::valid?(@type, value)
10
+ end
11
+
12
+ def error_message(value)
13
+ Rtype::type_error_message(@type, value) + "\nOR " + Rtype::type_error_message(nil, value)
14
+ end
15
+ end
16
+ end
17
+
18
+ def nilable(*args)
19
+ Behavior::Nilable[*args]
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ module Rtype
2
+ module Behavior
3
+ class Not < Base
4
+ def initialize(*types)
5
+ @types = types
6
+ end
7
+
8
+ def valid?(value)
9
+ @types.all? do |e|
10
+ !Rtype::valid?(e, value)
11
+ end
12
+ end
13
+
14
+ def error_message(value)
15
+ arr = @types.map { |e| "NOT " + Rtype::type_error_message(e, value) }
16
+ arr.join "\nAND "
17
+ end
18
+ end
19
+ end
20
+
21
+ def not(*args)
22
+ Behavior::Not[*args]
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ module Rtype
2
+ module Behavior
3
+ class NumericCheck < Base
4
+ @@conditions = [
5
+ :>, :<, :>=, :<=, :==
6
+ ]
7
+
8
+ # @param [Symbol] condition
9
+ # @param [Numeric] x
10
+ def initialize(condition, x)
11
+ raise ArgumentError, "Invalid condition '#{condition}'" unless @@conditions.include?(condition)
12
+ raise ArgumentError, "x is not a Numeric" unless x.is_a?(Numeric)
13
+ @condition = condition
14
+ @x = x
15
+ @lambda = case condition
16
+ when :>
17
+ lambda { |obj| obj > @x }
18
+ when :<
19
+ lambda { |obj| obj < @x }
20
+ when :>=
21
+ lambda { |obj| obj >= @x }
22
+ when :<=
23
+ lambda { |obj| obj <= @x }
24
+ when :==
25
+ lambda { |obj| obj == @x }
26
+ end
27
+ end
28
+
29
+ def valid?(value)
30
+ if value.is_a?(Numeric)
31
+ @lambda.call(value)
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ def error_message(value)
38
+ "Expected #{value.inspect} to be a numeric #{@condition} #{@x}"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module Rtype
2
+ module Behavior
3
+ # Typed array behavior. empty array allowed
4
+ class TypedArray < Base
5
+ def initialize(type)
6
+ @type = type
7
+ Rtype.assert_valid_argument_type_sig_element(@type)
8
+ end
9
+
10
+ def valid?(value)
11
+ if value.is_a?(Array)
12
+ any = value.any? do |e|
13
+ !Rtype::valid?(@type, e)
14
+ end
15
+ !any
16
+ else
17
+ false
18
+ end
19
+ end
20
+
21
+ def error_message(value)
22
+ "Expected #{value.inspect} to be an array with type #{@type.inspect}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ module Rtype
2
+ module Behavior
3
+ # Typed hash behavior. empty hash allowed
4
+ class TypedHash < Base
5
+ def initialize(key_type, value_type)
6
+ @ktype = key_type
7
+ @vtype = value_type
8
+ Rtype.assert_valid_argument_type_sig_element(@ktype)
9
+ Rtype.assert_valid_argument_type_sig_element(@vtype)
10
+ end
11
+
12
+ def valid?(value)
13
+ if value.is_a?(Hash)
14
+ any = value.any? do |k, v|
15
+ !Rtype::valid?(@ktype, k) ||
16
+ !Rtype::valid?(@vtype, v)
17
+ end
18
+ !any
19
+ else
20
+ false
21
+ end
22
+ end
23
+
24
+ def error_message(value)
25
+ "Expected #{value.inspect} to be a hash with key type #{@ktype.inspect} and value type #{@vtype.inspect}"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module Rtype
2
+ module Behavior
3
+ # Typed set behavior. empty set allowed
4
+ class TypedSet < Base
5
+ def initialize(type)
6
+ @type = type
7
+ Rtype.assert_valid_argument_type_sig_element(@type)
8
+ end
9
+
10
+ def valid?(value)
11
+ if value.is_a?(Set)
12
+ any = value.any? do |e|
13
+ !Rtype::valid?(@type, e)
14
+ end
15
+ !any
16
+ else
17
+ false
18
+ end
19
+ end
20
+
21
+ def error_message(value)
22
+ "Expected #{value.inspect} to be a set with type #{@type.inspect}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Rtype
2
+ module Behavior
3
+ class Xor < Base
4
+ def initialize(*types)
5
+ @types = types
6
+ end
7
+
8
+ def valid?(value)
9
+ result = @types.map do |e|
10
+ Rtype::valid? e, value
11
+ end
12
+ result.count(true) == 1
13
+ end
14
+
15
+ def error_message(value)
16
+ arr = @types.map { |e| Rtype::type_error_message(e, value) }
17
+ arr.join "\nXOR "
18
+ end
19
+ end
20
+ end
21
+
22
+ def xor(*args)
23
+ Behavior::Xor[*args]
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module Rtype
2
+ module Behavior
3
+ end
4
+ end
5
+
6
+ require_relative 'behavior/base'
7
+ require_relative 'behavior/and'
8
+ require_relative 'behavior/xor'
9
+ require_relative 'behavior/not'
10
+ require_relative 'behavior/nilable'
11
+ require_relative 'behavior/typed_array'
12
+ require_relative 'behavior/typed_set'
13
+ require_relative 'behavior/typed_hash'
14
+ require_relative 'behavior/numeric_check'
15
+ require_relative 'behavior/integer_check'
16
+ require_relative 'behavior/float_check'
17
+ require_relative 'behavior/core_ext'