rtype 0.6.8-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'