rdl 2.0.0.rc2 → 2.0.0.rc3

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.
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