rdl 2.0.0.rc2 → 2.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +7 -1
  3. data/README.md +94 -20
  4. data/lib/rdl.rb +4 -1
  5. data/lib/rdl/config.rb +90 -3
  6. data/lib/rdl/info.rb +16 -0
  7. data/lib/rdl/typecheck.rb +207 -79
  8. data/lib/rdl/types/bot.rb +1 -1
  9. data/lib/rdl/types/dependent_arg.rb +17 -8
  10. data/lib/rdl/types/{finitehash.rb → finite_hash.rb} +3 -29
  11. data/lib/rdl/types/generic.rb +1 -37
  12. data/lib/rdl/types/intersection.rb +1 -0
  13. data/lib/rdl/types/lexer.rex +2 -1
  14. data/lib/rdl/types/lexer.rex.rb +4 -1
  15. data/lib/rdl/types/method.rb +2 -12
  16. data/lib/rdl/types/nominal.rb +1 -22
  17. data/lib/rdl/types/non_null.rb +50 -0
  18. data/lib/rdl/types/parser.racc +3 -1
  19. data/lib/rdl/types/parser.tab.rb +222 -190
  20. data/lib/rdl/types/singleton.rb +1 -6
  21. data/lib/rdl/types/structural.rb +1 -10
  22. data/lib/rdl/types/top.rb +1 -2
  23. data/lib/rdl/types/tuple.rb +3 -19
  24. data/lib/rdl/types/type.rb +223 -0
  25. data/lib/rdl/types/union.rb +12 -2
  26. data/lib/rdl/types/var.rb +4 -1
  27. data/lib/rdl/types/wild_query.rb +1 -0
  28. data/lib/rdl/wrap.rb +199 -169
  29. data/lib/rdl_disable.rb +41 -0
  30. data/lib/rdl_types.rb +1 -4
  31. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/_aliases.rb +0 -0
  32. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/abbrev.rb +0 -0
  33. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/array.rb +56 -56
  34. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/base64.rb +0 -0
  35. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/basic_object.rb +0 -0
  36. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/benchmark.rb +0 -0
  37. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bigdecimal.rb +0 -0
  38. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bigmath.rb +0 -0
  39. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bignum.rb +0 -0
  40. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/class.rb +0 -0
  41. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/complex.rb +0 -0
  42. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/coverage.rb +0 -0
  43. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/csv.rb +0 -0
  44. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/date.rb +0 -0
  45. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/dir.rb +0 -0
  46. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/encoding.rb +0 -0
  47. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/enumerable.rb +0 -0
  48. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/enumerator.rb +0 -0
  49. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/exception.rb +0 -0
  50. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/file.rb +0 -0
  51. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/fileutils.rb +0 -0
  52. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/fixnum.rb +0 -0
  53. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/float.rb +26 -26
  54. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/gem.rb +0 -0
  55. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/hash.rb +0 -0
  56. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/integer.rb +8 -8
  57. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/io.rb +0 -0
  58. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/kernel.rb +12 -11
  59. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/marshal.rb +0 -0
  60. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/matchdata.rb +0 -0
  61. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/math.rb +0 -0
  62. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/module.rb +0 -0
  63. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/nil.rb +0 -0
  64. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/numeric.rb +0 -0
  65. data/lib/types/core-ruby-2.x/object.rb +75 -0
  66. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/pathname.rb +0 -0
  67. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/process.rb +0 -0
  68. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/random.rb +0 -0
  69. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/range.rb +0 -0
  70. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/rational.rb +0 -0
  71. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/regexp.rb +0 -0
  72. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/set.rb +0 -0
  73. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/string.rb +0 -0
  74. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/strscan.rb +0 -0
  75. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/symbol.rb +0 -0
  76. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/time.rb +0 -0
  77. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/uri.rb +0 -0
  78. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/yaml.rb +0 -0
  79. data/lib/types/core.rb +4 -0
  80. data/rdl.gemspec +2 -2
  81. data/test/test_le.rb +77 -35
  82. data/test/test_parser.rb +75 -59
  83. data/test/test_rdl.rb +18 -0
  84. data/test/test_typecheck.rb +73 -4
  85. metadata +54 -57
  86. data/lib/rails_types.rb +0 -1
  87. data/types/rails-4.2.1/fixnum.rb +0 -3
  88. data/types/rails-4.2.1/string.rb +0 -3
  89. data/types/rails-tmp/action_dispatch.rb +0 -406
  90. data/types/rails-tmp/active_record.rb +0 -406
  91. data/types/rails-tmp/devise_contracts.rb +0 -216
  92. data/types/ruby-2.x/object.rb +0 -73
@@ -0,0 +1,75 @@
1
+ class Object
2
+ # Instead of rdl_nowrap, mark individual methods as not being wrapped so
3
+ # we can wrap stuff defined by the user at the top level (since those
4
+ # methods are added to Object).
5
+
6
+ # type :ARGF, ARGF
7
+ # type :ARGV, 'Array<String>'
8
+ # type :DATA, 'File'
9
+ # type :ENV, ENV
10
+ # type :FALSE, '%false'
11
+ # type :NIL, 'nil'
12
+ # type :RUBY_COPYRIGHT, 'String'
13
+ # type :RUBY_DESCRIPTION, 'String'
14
+ # type :RUBY_ENGINE, 'String'
15
+ # type :RUBY_PATCHLEVEL, Fixnum
16
+ # type :RUBY_PLATFORM, 'String'
17
+ # type :RUBY_RELEASE_DATE, 'String'
18
+ # type :RUBY_REVISION, Fixnum
19
+ # type :RUBY_VERSION, 'String'
20
+ # type :STDERR, 'IO'
21
+ # type :STDIN, 'IO'
22
+ # type :STDOUT, 'IO'
23
+ # type :TOPLEVEL_BINDING, 'Binding'
24
+ # type :TRUE, '%true'
25
+
26
+ type :!~, '(%any other) -> %bool', wrap: false
27
+ type :<=>, '(%any other) -> Fixnum or nil', wrap: false
28
+ type :===, '(%any other) -> %bool', wrap: false
29
+ type :=~, '(%any other) -> nil', wrap: false
30
+ type :class, '() -> Class', wrap: false
31
+ type :clone, '() -> self', wrap: false
32
+ # type :define_singleton_method, '(XXXX : *XXXX)') # TODO
33
+ type :display, '(IO port) -> nil', wrap: false
34
+ type :dup, '() -> self an_object', wrap: false
35
+ type :enum_for, '(?Symbol method, *%any args) -> Enumerator<%any>', wrap: false
36
+ type :enum_for, '(?Symbol method, *%any args) { (*%any args) -> %any } -> Enumerator<%any>', wrap: false
37
+ type :eql?, '(%any other) -> %bool', wrap: false
38
+ # type :extend, '(XXXX : *XXXX)') # TODO
39
+ type :freeze, '() -> self', wrap: false
40
+ type :frozen?, '() -> %bool', wrap: false
41
+ type :hash, '() -> Fixnum', wrap: false
42
+ type :inspect, '() -> String', wrap: false
43
+ type :instance_of?, '(Class) -> %bool', wrap: false
44
+ type :instance_variable_defined?, '(Symbol or String) -> %bool', wrap: false
45
+ type :instance_variable_get, '(Symbol or String) -> %any', wrap: false
46
+ type :instance_variable_set, '(Symbol or String, %any) -> %any', wrap: false # returns 2nd argument
47
+ type :instance_variables, '() -> Array<Symbol>', wrap: false
48
+ type :is_a?, '(Class or Module) -> %bool', wrap: false
49
+ type :kind_of?, '(Class) -> %bool', wrap: false
50
+ type :method, '(Symbol) -> Method', wrap: false
51
+ type :methods, '(?%bool regular) -> Array<Symbol>', wrap: false
52
+ type :nil?, '() -> %bool', wrap: false
53
+ type :private_methods, '(?%bool all) -> Array<Symbol>', wrap: false
54
+ type :protected_methods, '(?%bool all) -> Array<Symbol>', wrap: false
55
+ type :public_method, '(Symbol) -> Method', wrap: false
56
+ type :public_methods, '(?%bool all) -> Array<Symbol>', wrap: false
57
+ type :public_send, '(Symbol or String, *%any args) -> %any', wrap: false
58
+ type :remove_instance_variable, '(Symbol) -> %any', wrap: false
59
+ # type :respond_to?, '(Symbol or String, ?%bool include_all) -> %bool'
60
+ type :send, '(Symbol or String, *%any args) -> %any', wrap: false # Can't wrap this, used outside wrap switch
61
+ type :singleton_class, '() -> Class', wrap: false
62
+ type :singleton_method, '(Symbol) -> Method', wrap: false
63
+ type :singleton_methods, '(?%bool all) -> Array<Symbol>', wrap: false
64
+ type :taint, '() -> self', wrap: false
65
+ type :tainted?, '() -> %bool', wrap: false
66
+ # type :tap, '()') # TODO
67
+ type :to_enum, '(?Symbol method, *%any args) -> Enumerator<%any>', wrap: false
68
+ type :to_enum, '(?Symbol method, *%any args) {(*%any args) -> %any} -> Enumerator<%any>', wrap: false
69
+ # TODO: above alias for enum_for?
70
+ type :to_s, '() -> String', wrap: false
71
+ type :trust, '() -> self', wrap: false
72
+ type :untaint, '() -> self', wrap: false
73
+ type :untrust, '() -> self', wrap: false
74
+ type :untrusted?, '() -> %bool', wrap: false
75
+ end
@@ -0,0 +1,4 @@
1
+ dir = RUBY_VERSION.split('.')[0] + ".x"
2
+
3
+ require_relative "core-ruby-#{dir}/_aliases.rb" # load type aliases first
4
+ Dir[File.dirname(__FILE__) + "/core-ruby-#{dir}/**/*.rb"].each { |f| require f }
@@ -4,8 +4,8 @@
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'rdl'
7
- s.version = '2.0.0.rc2'
8
- s.date = '2016-07-19'
7
+ s.version = '2.0.0.rc3'
8
+ s.date = '2016-08-11'
9
9
  s.summary = 'Ruby type and contract system'
10
10
  s.description = <<-EOF
11
11
  RDL is a gem that adds types and contracts to Ruby. RDL includes extensive
@@ -15,6 +15,11 @@ class TestLe < Minitest::Test
15
15
  class C < B
16
16
  end
17
17
 
18
+ # convert arg string to a type
19
+ def tt(t)
20
+ $__rdl_parser.scan_str('#T ' + t)
21
+ end
22
+
18
23
  def setup
19
24
  @tbasicobject = NominalType.new "BasicObject"
20
25
  @tsymfoo = SingletonType.new :foo
@@ -93,45 +98,42 @@ class TestLe < Minitest::Test
93
98
  assert (not (t2 <= t1))
94
99
  assert (not (tarray <= t1))
95
100
  assert (t1 <= t2) # covariant subtyping since tuples are *immutable*
96
- t123 = $__rdl_parser.scan_str "#T [1, 2, 3]"
97
- tfff = $__rdl_parser.scan_str "#T [Fixnum, Fixnum, Fixnum]"
98
- tooo = $__rdl_parser.scan_str "#T [Object, Object, Object]"
99
- assert (t123 <= tfff) # covariant subtyping with singletons
100
- assert (tfff <= tooo)
101
- assert (t123 <= tooo)
101
+ assert (tt("[1, 2, 3]") <= tt("[Fixnum, Fixnum, Fixnum]")) # covariant subtyping with singletons
102
+ assert (tt("[Fixnum, Fixnum, Fixnum]") <= tt("[Object, Object, Object]"))
103
+ assert (tt("[1, 2, 3]") <= tt("[Object, Object, Object]"))
102
104
 
103
105
  # subtyping of tuples and arrays
104
- tfs_1 = $__rdl_parser.scan_str "#T [Fixnum, String]"
105
- tafs_1 = $__rdl_parser.scan_str "#T Array<Fixnum or String>"
106
+ tfs_1 = tt "[Fixnum, String]"
107
+ tafs_1 = tt "Array<Fixnum or String>"
106
108
  assert (tfs_1 <= tafs_1) # subtyping allowed by tfs_1 promoted to array
107
- tfs2_1 = $__rdl_parser.scan_str "#T [Fixnum, String]"
109
+ tfs2_1 = tt "[Fixnum, String]"
108
110
  assert (not (tfs_1 <= tfs2_1)) # t12 has been promoted to array, no longer subtype
109
111
 
110
- tfs_2 = $__rdl_parser.scan_str "#T [Fixnum, String]"
111
- tfs2_2 = $__rdl_parser.scan_str "#T [Fixnum, String]"
112
+ tfs_2 = tt "[Fixnum, String]"
113
+ tfs2_2 = tt "[Fixnum, String]"
112
114
  assert (tfs_2 <= tfs2_2) # this is allowed here because tfs_2 is still a tuple
113
- tafs_2 = $__rdl_parser.scan_str "#T Array<Fixnum or String>"
115
+ tafs_2 = tt "Array<Fixnum or String>"
114
116
  assert (not (tfs_2 <= tafs_2)) # subtyping not allowed because tfs_2 <= tfs2_2 unsatisfiable after tfs_2 promoted
115
117
 
116
- tfs_3 = $__rdl_parser.scan_str "#T [Fixnum, String]"
117
- tfs2_3 = $__rdl_parser.scan_str "#T [Object, Object]"
118
+ tfs_3 = tt "[Fixnum, String]"
119
+ tfs2_3 = tt "[Object, Object]"
118
120
  assert (tfs_3 <= tfs2_3) # this is allowed here because t12a is still a tuple
119
- tafs_3 = $__rdl_parser.scan_str "#T Array<Object>"
121
+ tafs_3 = tt "Array<Object>"
120
122
  assert (not (tfs2_3 <= tafs_3)) # subtyping not allowed because tfs_3 <= tfs2_3 unsatisfiable after tfs2_3 promoted
121
123
 
122
- tfs_4 = $__rdl_parser.scan_str "#T [Fixnum, String]"
123
- tfs2_4 = $__rdl_parser.scan_str "#T [Fixnum, String]"
124
+ tfs_4 = tt "[Fixnum, String]"
125
+ tfs2_4 = tt "[Fixnum, String]"
124
126
  assert (tfs_4 <= tfs2_4) # allowed, types are the same
125
- tafs_4 = $__rdl_parser.scan_str "#T Array<Fixnum or String>"
127
+ tafs_4 = tt "Array<Fixnum or String>"
126
128
  assert (tfs2_4 <= tafs_4) # allowed, both tfs2_4 and tfs_4 promoted to array
127
- tfs3_4 = $__rdl_parser.scan_str "#T [Fixnum, String]"
129
+ tfs3_4 = tt "[Fixnum, String]"
128
130
  assert (not(tfs_4 <= tfs3_4)) # not allowed, tfs_4 has been promoted
129
131
  end
130
132
 
131
133
  def test_finite_hash
132
- t12 = $__rdl_parser.scan_str "#T {a: 1, b: 2}"
133
- tfs = $__rdl_parser.scan_str "#T {a: Fixnum, b: Fixnum}"
134
- too = $__rdl_parser.scan_str "#T {a: Object, b: Object}"
134
+ t12 = tt "{a: 1, b: 2}"
135
+ tfs = tt "{a: Fixnum, b: Fixnum}"
136
+ too = tt "{a: Object, b: Object}"
135
137
  assert (t12 <= tfs)
136
138
  assert (t12 <= too)
137
139
  assert (tfs <= too)
@@ -141,30 +143,30 @@ class TestLe < Minitest::Test
141
143
 
142
144
  # subtyping of finite hashes and hashes; same pattern as tuples
143
145
  # subtyping of tuples and arrays
144
- tfs_1 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
145
- thfs_1 = $__rdl_parser.scan_str "#T Hash<Symbol, Fixnum or String>"
146
+ tfs_1 = tt "{x: Fixnum, y: String}"
147
+ thfs_1 = tt "Hash<Symbol, Fixnum or String>"
146
148
  assert (tfs_1 <= thfs_1) # subtyping allowed because tfs_1 promoted to hash
147
- tfs2_1 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
149
+ tfs2_1 = tt "{x: Fixnum, y: String}"
148
150
  assert (not (tfs_1 <= tfs2_1)) # t12 has been promoted to hash, no longer subtype
149
151
 
150
- tfs_2 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
151
- tfs2_2 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
152
+ tfs_2 = tt "{x: Fixnum, y: String}"
153
+ tfs2_2 = tt "{x: Fixnum, y: String}"
152
154
  assert (tfs_2 <= tfs2_2) # this is allowed here because tfs_2 is still finite
153
- thfs_2 = $__rdl_parser.scan_str "#T Hash<Symbol, Fixnum or String>"
155
+ thfs_2 = tt "Hash<Symbol, Fixnum or String>"
154
156
  assert (not (tfs_2 <= thfs_2)) # subtyping not allowed because tfs_2 <= tfs2_2 unsatisfiable after tfs_2 promoted
155
157
 
156
- tfs_3 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
157
- tfs2_3 = $__rdl_parser.scan_str "#T {x: Object, y: Object}"
158
+ tfs_3 = tt "{x: Fixnum, y: String}"
159
+ tfs2_3 = tt "{x: Object, y: Object}"
158
160
  assert (tfs_3 <= tfs2_3) # this is allowed here because t12a is still finite
159
- thfs_3 = $__rdl_parser.scan_str "#T Hash<Symbol, Object>"
161
+ thfs_3 = tt "Hash<Symbol, Object>"
160
162
  assert (not (tfs2_3 <= thfs_3)) # subtyping not allowed because tfs_3 <= tfs2_3 unsatisfiable after tfs2_3 promoted
161
163
 
162
- tfs_4 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
163
- tfs2_4 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
164
+ tfs_4 = tt "{x: Fixnum, y: String}"
165
+ tfs2_4 = tt "{x: Fixnum, y: String}"
164
166
  assert (tfs_4 <= tfs2_4) # allowed, types are the same
165
- thfs_4 = $__rdl_parser.scan_str "#T Hash<Symbol, Fixnum or String>"
167
+ thfs_4 = tt "Hash<Symbol, Fixnum or String>"
166
168
  assert (tfs2_4 <= thfs_4) # allowed, both tfs2_4 and tfs_4 promoted to hash
167
- tfs3_4 = $__rdl_parser.scan_str "#T {x: Fixnum, y: String}"
169
+ tfs3_4 = tt "{x: Fixnum, y: String}"
168
170
  assert (not(tfs_4 <= tfs3_4)) # not allowed, tfs_4 has been promoted
169
171
  end
170
172
 
@@ -251,6 +253,46 @@ class TestLe < Minitest::Test
251
253
  assert (not (tnomt <= ts4))
252
254
  end
253
255
 
256
+ def test_leq_inst
257
+ # when return of do_leq is false, ignore resulting inst, since that's very implementation dependent
258
+ assert_equal [true, {t: @ta}], do_leq(tt("t"), @ta, true)
259
+ assert_equal false, do_leq(tt("t"), @ta, false)[0]
260
+ assert_equal false, do_leq(@ta, tt("t"), true)[0]
261
+ assert_equal [true, {t: @ta}], do_leq(@ta, tt("t"), false)
262
+ assert_equal [true, {}], do_leq($__rdl_bot_type, tt("t"), true)
263
+ assert_equal [true, {}], do_leq($__rdl_bot_type, tt("t"), false)
264
+ assert_equal false, do_leq($__rdl_top_type, tt("t"), true)[0]
265
+ assert_equal [true, {t: $__rdl_top_type}], do_leq($__rdl_top_type, tt("t"), false)
266
+ assert_equal [true, {t: @ta, u: @ta}], do_leq(tt("t or u"), @ta, true)
267
+ assert_equal false, do_leq(tt("t or u"), @ta, false)[0]
268
+ assert_equal false, do_leq(tt("3"), tt("t"), true)[0]
269
+ assert_equal [true, {t: tt("3")}], do_leq(tt("3"), tt("t"), false)
270
+ assert_equal [true, {t: $__rdl_fixnum_type}], do_leq(tt("Array<t>"), tt("Array<Fixnum>"), true)
271
+ assert_equal false, do_leq(tt("Array<t>"), tt("Array<Fixnum>"), false)[0]
272
+ assert_equal [true, {t: $__rdl_fixnum_type}], do_leq(tt("Array<Fixnum>"), tt("Array<t>"), false)
273
+ assert_equal false, do_leq(tt("Array<Fixnum>"), tt("Array<t>"), true)[0]
274
+ assert_equal [true, {t: $__rdl_fixnum_type, u: $__rdl_string_type}], do_leq(tt("Hash<t,u>"), tt("Hash<Fixnum,String>"), true)
275
+ assert_equal [true, {t: $__rdl_fixnum_type}], do_leq(tt("Hash<t,t>"), tt("Hash<Fixnum,Fixnum>"), true)
276
+ assert_equal false, do_leq(tt("Hash<t,t>"), tt("Hash<Fixnum,String>"), true)[0]
277
+ assert_equal false, do_leq(tt("[m:()->t]"), tt("[m:()->Fixnum]"), true)[0] # no inst inside structural types
278
+ end
279
+
280
+ def do_leq(tleft, tright, ileft)
281
+ inst = Hash.new
282
+ r = Type.leq(tleft, tright, inst, ileft)
283
+ return [r, inst]
284
+ end
285
+
286
+ # nonnull annotation is simply removed! so doesn't matter
287
+ def test_leq_nonnull
288
+ assert tt("!Fixnum") <= tt("!Fixnum")
289
+ assert tt("!Fixnum") <= tt("Fixnum")
290
+ assert tt("Fixnum") <= tt("!Fixnum")
291
+ assert tt("!Fixnum") <= tt("!Object")
292
+ assert tt("!Fixnum") <= tt("Object")
293
+ assert tt("Fixnum") <= tt("!Object")
294
+ end
295
+
254
296
  # def test_intersection
255
297
  # skip "<= not defined on intersection"
256
298
  # tobject_and_basicobject = IntersectionType.new($__rdl_object_type, @tbasicobject)
@@ -26,168 +26,184 @@ class TestParser < Minitest::Test
26
26
  @tsymbolx = AnnotatedArgType.new("x", @tsymbol)
27
27
  end
28
28
 
29
+ def tt(t)
30
+ $__rdl_parser.scan_str('#T ' + t)
31
+ end
32
+
33
+ def tm(t)
34
+ $__rdl_parser.scan_str t
35
+ end
36
+
29
37
  def test_basic
30
- t1 = $__rdl_parser.scan_str "(nil) -> nil"
38
+ t1 = tm "(nil) -> nil"
31
39
  assert_equal (MethodType.new [$__rdl_nil_type], nil, $__rdl_nil_type), t1
32
- t2 = $__rdl_parser.scan_str "(Fixnum, Fixnum) -> Fixnum"
40
+ t2 = tm "(Fixnum, Fixnum) -> Fixnum"
33
41
  assert_equal (MethodType.new [$__rdl_fixnum_type, $__rdl_fixnum_type], nil, $__rdl_fixnum_type), t2
34
- t3 = $__rdl_parser.scan_str "() -> Enumerator"
42
+ t3 = tm "() -> Enumerator"
35
43
  assert_equal (MethodType.new [], nil, @tenum), t3
36
- t4 = $__rdl_parser.scan_str "(%any) -> nil"
44
+ t4 = tm "(%any) -> nil"
37
45
  assert_equal (MethodType.new [$__rdl_top_type], nil, $__rdl_nil_type), t4
38
- t5 = $__rdl_parser.scan_str "(%bool) -> Fixnum"
46
+ t5 = tm "(%bool) -> Fixnum"
39
47
  assert_equal (MethodType.new [$__rdl_bool_type], nil, $__rdl_fixnum_type), t5
40
- assert_raises(RuntimeError) { $__rdl_parser.scan_str "(%foo) -> nil" }
41
- t6 = $__rdl_parser.scan_str "(A) -> nil"
48
+ assert_raises(RuntimeError) { tm "(%foo) -> nil" }
49
+ t6 = tm "(A) -> nil"
42
50
  assert_equal (MethodType.new [@ta], nil, $__rdl_nil_type), t6
43
- t7 = $__rdl_parser.scan_str "(TestParser::A) -> nil"
51
+ t7 = tm "(TestParser::A) -> nil"
44
52
  assert_equal (MethodType.new [NominalType.new("TestParser::A")], nil, $__rdl_nil_type), t7
45
- t8 = $__rdl_parser.scan_str "(Fixnum) { (%any, String) -> nil } -> :symbol"
53
+ t8 = tm "(Fixnum) { (%any, String) -> nil } -> :symbol"
46
54
  assert_equal (MethodType.new [$__rdl_fixnum_type], MethodType.new([$__rdl_top_type, $__rdl_string_type], nil, $__rdl_nil_type), @tsymbol), t8
47
- t9 = $__rdl_parser.scan_str "(true) -> false"
55
+ t9 = tm "(true) -> false"
48
56
  assert_equal (MethodType.new [$__rdl_true_type], nil, $__rdl_false_type), t9
49
57
  end
50
58
 
51
59
  def test_opt_vararg
52
- t1 = $__rdl_parser.scan_str "(Fixnum, ?Fixnum) -> Fixnum"
60
+ t1 = tm "(Fixnum, ?Fixnum) -> Fixnum"
53
61
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumopt], nil, $__rdl_fixnum_type), t1
54
- t2 = $__rdl_parser.scan_str "(Fixnum, *Fixnum) -> Fixnum"
62
+ t2 = tm "(Fixnum, *Fixnum) -> Fixnum"
55
63
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumvararg], nil, $__rdl_fixnum_type), t2
56
- t3 = $__rdl_parser.scan_str "(Fixnum, ?Fixnum, ?Fixnum, *Fixnum) -> Fixnum"
64
+ t3 = tm "(Fixnum, ?Fixnum, ?Fixnum, *Fixnum) -> Fixnum"
57
65
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumopt, @tfixnumopt, @tfixnumvararg], nil, $__rdl_fixnum_type), t3
58
- t4 = $__rdl_parser.scan_str "(?Fixnum) -> nil"
66
+ t4 = tm "(?Fixnum) -> nil"
59
67
  assert_equal (MethodType.new [@tfixnumopt], nil, $__rdl_nil_type), t4
60
- t5 = $__rdl_parser.scan_str "(*Fixnum) -> nil"
68
+ t5 = tm "(*Fixnum) -> nil"
61
69
  assert_equal (MethodType.new [@tfixnumvararg], nil, $__rdl_nil_type), t5
62
70
  end
63
71
 
64
72
  def test_union
65
- t1 = $__rdl_parser.scan_str "(Fixnum or String) -> nil"
73
+ t1 = tm "(Fixnum or String) -> nil"
66
74
  assert_equal (MethodType.new [UnionType.new($__rdl_fixnum_type, $__rdl_string_type)], nil, $__rdl_nil_type), t1
67
- t2 = $__rdl_parser.scan_str "(Fixnum or String or Symbol) -> nil"
75
+ t2 = tm "(Fixnum or String or Symbol) -> nil"
68
76
  assert_equal (MethodType.new [UnionType.new($__rdl_fixnum_type, $__rdl_string_type, $__rdl_symbol_type)], nil, $__rdl_nil_type), t2
69
- t3 = $__rdl_parser.scan_str "() -> Fixnum or String or Symbol"
77
+ t3 = tm "() -> Fixnum or String or Symbol"
70
78
  assert_equal (MethodType.new [], nil, UnionType.new($__rdl_fixnum_type, $__rdl_string_type, $__rdl_symbol_type)), t3
71
79
  end
72
80
 
73
81
  def test_bare
74
- t1 = $__rdl_parser.scan_str "#T nil"
82
+ t1 = tt "nil"
75
83
  assert_equal $__rdl_nil_type, t1
76
- t2 = $__rdl_parser.scan_str "#T %any"
84
+ t2 = tt "%any"
77
85
  assert_equal $__rdl_top_type, t2
78
- t3 = $__rdl_parser.scan_str "#T A"
86
+ t3 = tt "A"
79
87
  assert_equal NominalType.new("A"), t3
80
88
  end
81
89
 
82
90
  def test_symbol
83
- t1 = $__rdl_parser.scan_str "#T :symbol"
91
+ t1 = tt ":symbol"
84
92
  assert_equal @tsymbol, t1
85
93
  end
86
94
 
87
95
  def test_annotated_params
88
- t1 = $__rdl_parser.scan_str "(Fixnum x, Fixnum) -> Fixnum"
96
+ t1 = tm "(Fixnum x, Fixnum) -> Fixnum"
89
97
  assert_equal (MethodType.new [@tfixnumx, $__rdl_fixnum_type], nil, $__rdl_fixnum_type), t1
90
- t2 = $__rdl_parser.scan_str "(Fixnum, ?Fixnum x) -> Fixnum"
98
+ t2 = tm "(Fixnum, ?Fixnum x) -> Fixnum"
91
99
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumoptx], nil, $__rdl_fixnum_type), t2
92
- t3 = $__rdl_parser.scan_str "(Fixnum, *Fixnum x) -> Fixnum"
100
+ t3 = tm "(Fixnum, *Fixnum x) -> Fixnum"
93
101
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumvarargx], nil, $__rdl_fixnum_type), t3
94
- t4 = $__rdl_parser.scan_str "(Fixnum, Fixnum y) -> Fixnum"
102
+ t4 = tm "(Fixnum, Fixnum y) -> Fixnum"
95
103
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumy], nil, $__rdl_fixnum_type), t4
96
- t5 = $__rdl_parser.scan_str "(Fixnum x, Fixnum y) -> Fixnum"
104
+ t5 = tm "(Fixnum x, Fixnum y) -> Fixnum"
97
105
  assert_equal (MethodType.new [@tfixnumx, @tfixnumy], nil, $__rdl_fixnum_type), t5
98
- t6 = $__rdl_parser.scan_str "(Fixnum, Fixnum) -> Fixnum ret"
106
+ t6 = tm "(Fixnum, Fixnum) -> Fixnum ret"
99
107
  assert_equal (MethodType.new [$__rdl_fixnum_type, $__rdl_fixnum_type], nil, @tfixnumret), t6
100
- t7 = $__rdl_parser.scan_str "(Fixnum x, Fixnum) -> Fixnum ret"
108
+ t7 = tm "(Fixnum x, Fixnum) -> Fixnum ret"
101
109
  assert_equal (MethodType.new [@tfixnumx, $__rdl_fixnum_type], nil, @tfixnumret), t7
102
- t8 = $__rdl_parser.scan_str "(Fixnum, Fixnum y) -> Fixnum ret"
110
+ t8 = tm "(Fixnum, Fixnum y) -> Fixnum ret"
103
111
  assert_equal (MethodType.new [$__rdl_fixnum_type, @tfixnumy], nil, @tfixnumret), t8
104
- t9 = $__rdl_parser.scan_str "(Fixnum x, Fixnum y) -> Fixnum ret"
112
+ t9 = tm "(Fixnum x, Fixnum y) -> Fixnum ret"
105
113
  assert_equal (MethodType.new [@tfixnumx, @tfixnumy], nil, @tfixnumret), t9
106
- t10 = $__rdl_parser.scan_str "(:symbol x) -> Fixnum"
114
+ t10 = tm "(:symbol x) -> Fixnum"
107
115
  assert_equal (MethodType.new [@tsymbolx], nil, $__rdl_fixnum_type), t10
108
116
  end
109
117
 
110
118
  def test_generic
111
- t1 = $__rdl_parser.scan_str "#T t"
119
+ t1 = tt "t"
112
120
  assert_equal (VarType.new "t"), t1
113
- t2 = $__rdl_parser.scan_str "#T Array"
121
+ t2 = tt "Array"
114
122
  assert_equal (NominalType.new "Array"), t2
115
- t3 = $__rdl_parser.scan_str "#T Array<t>"
123
+ t3 = tt "Array<t>"
116
124
  assert_equal (GenericType.new(t2, t1)), t3
117
- t4 = $__rdl_parser.scan_str "#T Array<Array<t>>"
125
+ t4 = tt "Array<Array<t>>"
118
126
  assert_equal (GenericType.new(t2, t3)), t4
119
- t5 = $__rdl_parser.scan_str "#T Hash"
127
+ t5 = tt "Hash"
120
128
  assert_equal (NominalType.new "Hash"), t5
121
- t6 = $__rdl_parser.scan_str "#T Hash<u, v>"
129
+ t6 = tt "Hash<u, v>"
122
130
  assert_equal (GenericType.new(t5, VarType.new("u"), VarType.new("v"))), t6
123
- t7 = $__rdl_parser.scan_str "#T Foo<String, Array<t>, Array<Array<t>>>"
131
+ t7 = tt "Foo<String, Array<t>, Array<Array<t>>>"
124
132
  assert_equal (GenericType.new(NominalType.new("Foo"), $__rdl_string_type, t3, t4)), t7
125
133
  end
126
134
 
127
135
  def test_tuple
128
- t1 = $__rdl_parser.scan_str "#T [Fixnum, String]"
136
+ t1 = tt "[Fixnum, String]"
129
137
  assert_equal (TupleType.new($__rdl_fixnum_type, $__rdl_string_type)), t1
130
- t2 = $__rdl_parser.scan_str "#T [String]"
138
+ t2 = tt "[String]"
131
139
  assert_equal (TupleType.new($__rdl_string_type)), t2
132
140
  end
133
141
 
134
142
  def test_fixnum
135
- t1 = $__rdl_parser.scan_str "#T 42"
143
+ t1 = tt "42"
136
144
  assert_equal (SingletonType.new(42)), t1
137
- t2 = $__rdl_parser.scan_str "#T -42"
145
+ t2 = tt "-42"
138
146
  assert_equal (SingletonType.new(-42)), t2
139
147
  end
140
148
 
141
149
  def test_float
142
- t1 = $__rdl_parser.scan_str "#T 3.14"
150
+ t1 = tt "3.14"
143
151
  assert_equal (SingletonType.new(3.14)), t1
144
152
  end
145
153
 
146
154
  def test_const
147
- t1 = $__rdl_parser.scan_str "#T ${Math::PI}"
155
+ t1 = tt "${Math::PI}"
148
156
  assert_equal (SingletonType.new(Math::PI)), t1
149
157
  end
150
158
 
151
159
  def test_type_alias
152
160
  type_alias '%foobarbaz', $__rdl_nil_type
153
- assert_equal $__rdl_nil_type, ($__rdl_parser.scan_str "#T %foobarbaz")
161
+ assert_equal $__rdl_nil_type, (tt "%foobarbaz")
154
162
  type_alias '%quxquxqux', 'nil'
155
- assert_equal $__rdl_nil_type, ($__rdl_parser.scan_str "#T %quxquxqux")
163
+ assert_equal $__rdl_nil_type, (tt "%quxquxqux")
156
164
  assert_raises(RuntimeError) { type_alias '%quxquxqux', 'nil' }
157
- assert_raises(RuntimeError) { $__rdl_parser.scan_str "#T %qux" }
165
+ assert_raises(RuntimeError) { tt "%qux" }
158
166
  end
159
167
 
160
168
  def test_structural
161
- t1 = $__rdl_parser.scan_str "#T [to_str: () -> String]"
169
+ t1 = tt "[to_str: () -> String]"
162
170
  tm1 = MethodType.new [], nil, $__rdl_string_type
163
171
  ts1 = StructuralType.new(to_str: tm1)
164
172
  assert_equal ts1, t1
165
173
  end
166
174
 
167
175
  def test_finite_hash
168
- t1 = $__rdl_parser.scan_str "#T {a: Fixnum, b: String}"
176
+ t1 = tt "{a: Fixnum, b: String}"
169
177
  assert_equal (FiniteHashType.new({a: $__rdl_fixnum_type, b: $__rdl_string_type})), t1
170
- t2 = $__rdl_parser.scan_str "#T {'a'=>Fixnum, 2=>String}"
178
+ t2 = tt "{'a'=>Fixnum, 2=>String}"
171
179
  assert_equal (FiniteHashType.new({"a"=>$__rdl_fixnum_type, 2=>$__rdl_string_type})), t2
172
180
  end
173
181
 
174
182
  def test_named_params
175
- t1 = $__rdl_parser.scan_str "(Fixnum, x: Fixnum) -> Fixnum"
183
+ t1 = tm "(Fixnum, x: Fixnum) -> Fixnum"
176
184
  assert_equal (MethodType.new [$__rdl_fixnum_type, FiniteHashType.new(x: $__rdl_fixnum_type)], nil, $__rdl_fixnum_type), t1
177
- t2 = $__rdl_parser.scan_str "(Fixnum, x: Fixnum, y: String) -> Fixnum"
185
+ t2 = tm "(Fixnum, x: Fixnum, y: String) -> Fixnum"
178
186
  assert_equal (MethodType.new [$__rdl_fixnum_type, FiniteHashType.new(x: $__rdl_fixnum_type, y: $__rdl_string_type)], nil, $__rdl_fixnum_type), t2
179
- t3 = $__rdl_parser.scan_str "(Fixnum, y: String, x: Fixnum) -> Fixnum"
187
+ t3 = tm "(Fixnum, y: String, x: Fixnum) -> Fixnum"
180
188
  assert_equal (MethodType.new [$__rdl_fixnum_type, FiniteHashType.new(x: $__rdl_fixnum_type, y: $__rdl_string_type)], nil, $__rdl_fixnum_type), t3
181
- t4 = $__rdl_parser.scan_str "(Fixnum, y: String, x: ?Fixnum) -> Fixnum"
189
+ t4 = tm "(Fixnum, y: String, x: ?Fixnum) -> Fixnum"
182
190
  assert_equal (MethodType.new [$__rdl_fixnum_type, FiniteHashType.new(x: @tfixnumopt, y: $__rdl_string_type)], nil, $__rdl_fixnum_type), t4
183
- t4 = $__rdl_parser.scan_str "(Fixnum, y: ?String, x: Fixnum) -> Fixnum"
191
+ t4 = tm "(Fixnum, y: ?String, x: Fixnum) -> Fixnum"
184
192
  assert_equal (MethodType.new [$__rdl_fixnum_type, FiniteHashType.new(x: $__rdl_fixnum_type, y: @tstringopt)], nil, $__rdl_fixnum_type), t4
185
- t5 = $__rdl_parser.scan_str "(Fixnum x, x: Fixnum) -> Fixnum"
193
+ t5 = tm "(Fixnum x, x: Fixnum) -> Fixnum"
186
194
  assert_equal (MethodType.new [@tfixnumx, FiniteHashType.new(x: $__rdl_fixnum_type)], nil, $__rdl_fixnum_type), t5
187
- t6 = $__rdl_parser.scan_str "(x: Fixnum) -> Fixnum"
195
+ t6 = tm "(x: Fixnum) -> Fixnum"
188
196
  assert_equal (MethodType.new [FiniteHashType.new(x: $__rdl_fixnum_type)], nil, $__rdl_fixnum_type), t6
189
- t7 = $__rdl_parser.scan_str "(x: Fixnum) { (%any, String) -> nil } -> :symbol"
197
+ t7 = tm "(x: Fixnum) { (%any, String) -> nil } -> :symbol"
190
198
  assert_equal (MethodType.new [FiniteHashType.new(x: $__rdl_fixnum_type)], MethodType.new([$__rdl_top_type, $__rdl_string_type], nil, $__rdl_nil_type), @tsymbol), t7
191
199
  end
192
200
 
201
+ def test_nonnull
202
+ assert_equal NonNullType.new(@ta), tt("!A")
203
+ tm2 = MethodType.new [], nil, $__rdl_string_type
204
+ ts2 = StructuralType.new(to_str: tm2)
205
+ assert_equal NonNullType.new(ts2), tt("![to_str: () -> String]")
206
+ assert_raises(RuntimeError) { tt("!3") }
207
+ end
208
+
193
209
  end