rdl 1.1.1 → 2.0.0.rc1

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +6 -0
  3. data/README.md +211 -32
  4. data/gemfiles/Gemfile.travis +1 -1
  5. data/lib/rdl.rb +85 -18
  6. data/lib/rdl/info.rb +74 -0
  7. data/lib/rdl/query.rb +8 -9
  8. data/lib/rdl/typecheck.rb +1057 -0
  9. data/lib/rdl/types/annotated_arg.rb +5 -5
  10. data/lib/rdl/types/{nil.rb → bot.rb} +9 -13
  11. data/lib/rdl/types/dependent_arg.rb +5 -5
  12. data/lib/rdl/types/dots_query.rb +2 -0
  13. data/lib/rdl/types/finitehash.rb +67 -24
  14. data/lib/rdl/types/generic.rb +13 -21
  15. data/lib/rdl/types/intersection.rb +9 -8
  16. data/lib/rdl/types/method.rb +30 -32
  17. data/lib/rdl/types/nominal.rb +22 -16
  18. data/lib/rdl/types/optional.rb +8 -22
  19. data/lib/rdl/types/parser.racc +8 -3
  20. data/lib/rdl/types/parser.tab.rb +131 -118
  21. data/lib/rdl/types/singleton.rb +15 -10
  22. data/lib/rdl/types/structural.rb +6 -6
  23. data/lib/rdl/types/top.rb +6 -6
  24. data/lib/rdl/types/tuple.rb +56 -24
  25. data/lib/rdl/types/type.rb +9 -0
  26. data/lib/rdl/types/type_inferencer.rb +1 -1
  27. data/lib/rdl/types/union.rb +52 -26
  28. data/lib/rdl/types/var.rb +7 -6
  29. data/lib/rdl/types/vararg.rb +5 -6
  30. data/lib/rdl/types/wild_query.rb +9 -2
  31. data/lib/rdl/util.rb +9 -7
  32. data/lib/rdl/wrap.rb +90 -72
  33. data/lib/rdl_types.rb +2 -2
  34. data/rdl.gemspec +6 -8
  35. data/test/test_alias.rb +4 -3
  36. data/test/test_contract.rb +5 -4
  37. data/test/test_dsl.rb +2 -1
  38. data/test/test_generic.rb +30 -26
  39. data/test/test_intersection.rb +3 -3
  40. data/test/test_le.rb +129 -61
  41. data/test/test_lib_types.rb +3 -2
  42. data/test/test_member.rb +33 -46
  43. data/test/test_parser.rb +113 -116
  44. data/test/test_query.rb +2 -1
  45. data/test/test_rdl.rb +64 -6
  46. data/test/test_rdl_type.rb +3 -2
  47. data/test/test_type_contract.rb +30 -12
  48. data/test/test_typecheck.rb +893 -0
  49. data/test/test_types.rb +50 -54
  50. data/test/test_wrap.rb +2 -1
  51. data/types/ruby-2.x/_aliases.rb +13 -2
  52. data/types/ruby-2.x/bigdecimal.rb +60 -85
  53. data/types/ruby-2.x/bignum.rb +80 -119
  54. data/types/ruby-2.x/complex.rb +33 -40
  55. data/types/ruby-2.x/fixnum.rb +81 -120
  56. data/types/ruby-2.x/float.rb +79 -116
  57. data/types/ruby-2.x/integer.rb +187 -22
  58. data/types/ruby-2.x/nil.rb +12 -0
  59. data/types/ruby-2.x/numeric.rb +38 -38
  60. data/types/ruby-2.x/object.rb +3 -3
  61. data/types/ruby-2.x/random.rb +2 -0
  62. data/types/ruby-2.x/range.rb +20 -19
  63. data/types/ruby-2.x/rational.rb +40 -40
  64. data/types/ruby-2.x/regexp.rb +4 -4
  65. data/types/ruby-2.x/string.rb +15 -17
  66. metadata +17 -16
  67. data/lib/rdl/types/.#lexer.rex +0 -1
@@ -1,5 +1,3 @@
1
- require_relative 'type_query'
2
-
3
1
  module RDL::Type
4
2
  class WildQuery < TypeQuery
5
3
  @@cache = nil
@@ -18,9 +16,18 @@ module RDL::Type
18
16
  end
19
17
 
20
18
  def ==(other)
19
+ return false if other.nil?
20
+ other = other.canonical
21
21
  return (other.instance_of? WildQuery)
22
22
  end
23
23
 
24
+ alias eql? ==
25
+
26
+ def <=(other)
27
+ other = other.canonical
28
+ return self == other
29
+ end
30
+
24
31
  def match(other)
25
32
  return true
26
33
  end
@@ -2,6 +2,7 @@ class RDL::Util
2
2
 
3
3
  SINGLETON_MARKER = "[s]"
4
4
  SINGLETON_MARKER_REGEXP = Regexp.escape(SINGLETON_MARKER)
5
+ GLOBAL_NAME = "_Globals" # something that's not a valid class name
5
6
 
6
7
  def self.to_class(klass)
7
8
  return klass if klass.class == Class
@@ -30,14 +31,15 @@ class RDL::Util
30
31
  return SINGLETON_MARKER + klass
31
32
  end
32
33
 
34
+ # Duplicate method...
33
35
  # Klass should be a string and may have a singleton marker
34
- def self.pretty_name(klass, meth)
35
- if klass =~ /^#{SINGLETON_MARKER_REGEXP}(.*)/
36
- return "#{$1}.#{meth}"
37
- else
38
- return "#{klass}##{meth}"
39
- end
40
- end
36
+ # def self.pretty_name(klass, meth)
37
+ # if klass =~ /^#{SINGLETON_MARKER_REGEXP}(.*)/
38
+ # return "#{$1}.#{meth}"
39
+ # else
40
+ # return "#{klass}##{meth}"
41
+ # end
42
+ # end
41
43
 
42
44
  def self.method_defined?(klass, method)
43
45
  begin
@@ -7,42 +7,14 @@ class RDL::Wrap
7
7
  klass = klass.to_s
8
8
  meth = meth.to_sym
9
9
  while $__rdl_aliases[klass] && $__rdl_aliases[klass][meth]
10
- raise RuntimeError, "Alias #{klass}\##{meth} has contracts. Contracts are only allowed on methods, not aliases." if has_any_contracts?(klass, meth)
10
+ if $__rdl_info.has_any?(klass, meth, [:pre, :post, :type])
11
+ raise RuntimeError, "Alias #{klass}\##{meth} has contracts. Contracts are only allowed on methods, not aliases."
12
+ end
11
13
  meth = $__rdl_aliases[klass][meth]
12
14
  end
13
15
  return meth
14
16
  end
15
17
 
16
- def self.add_contract(klass, meth, kind, val)
17
- klass = klass.to_s
18
- meth = meth.to_sym
19
- $__rdl_contracts[klass] = {} unless $__rdl_contracts[klass]
20
- $__rdl_contracts[klass][meth] = {} unless $__rdl_contracts[klass][meth]
21
- $__rdl_contracts[klass][meth][kind] = [] unless $__rdl_contracts[klass][meth][kind]
22
- $__rdl_contracts[klass][meth][kind] << val
23
- end
24
-
25
- def self.has_contracts?(klass, meth, kind)
26
- klass = klass.to_s
27
- meth = meth.to_sym
28
- return ($__rdl_contracts.has_key? klass) &&
29
- ($__rdl_contracts[klass].has_key? meth) &&
30
- ($__rdl_contracts[klass][meth].has_key? kind)
31
- end
32
-
33
- def self.has_any_contracts?(klass, meth)
34
- klass = klass.to_s
35
- meth = meth.to_sym
36
- return ($__rdl_contracts.has_key? klass) &&
37
- ($__rdl_contracts[klass].has_key? meth)
38
- end
39
-
40
- def self.get_contracts(klass, meth, kind)
41
- klass = klass.to_s
42
- meth = meth.to_sym
43
- return $__rdl_contracts[klass][meth][kind]
44
- end
45
-
46
18
  def self.get_type_params(klass)
47
19
  klass = klass.to_s
48
20
  $__rdl_type_params[klass]
@@ -52,12 +24,13 @@ class RDL::Wrap
52
24
  # [+meth+] may be a String or Symbol
53
25
  #
54
26
  # Wraps klass#method to check contracts and types. Does not rewrap
55
- # if already wrapped.
27
+ # if already wrapped. Also records source location of method.
56
28
  def self.wrap(klass_str, meth)
57
29
  $__rdl_wrap_switch.off {
58
30
  klass_str = klass_str.to_s
59
31
  klass = RDL::Util.to_class klass_str
60
32
  return if wrapped? klass, meth
33
+ $__rdl_info.set(klass_str, meth, :source_location, klass.instance_method(meth).source_location) # get locs for nowrap meths!
61
34
  return if RDL::Config.instance.nowrap.member? klass
62
35
  raise ArgumentError, "Attempt to wrap #{klass.to_s}\##{meth.to_s}" if klass.to_s =~ /^RDL::/
63
36
  meth_old = wrapped_name(klass, meth) # meth_old is a symbol
@@ -79,24 +52,21 @@ class RDL::Wrap
79
52
  inst = @__rdl_inst if defined? @__rdl_inst
80
53
  inst = Hash[$__rdl_type_params[klass][0].zip []] if (not(inst) && $__rdl_type_params[klass])
81
54
  inst = {} if not inst
82
- #{if not(is_singleton_method) then "inst[:self] = RDL::Type::SingletonType.new(self)" end}
55
+ #{if not(is_singleton_method) then "inst[:self] = RDL::Type::NominalType.new(self.class)" end}
83
56
  # puts "Intercepted #{full_method_name}(\#{args.join(", ")}) { \#{blk} }, inst = \#{inst.inspect}"
84
57
  meth = RDL::Wrap.resolve_alias(klass, #{meth.inspect})
85
- if RDL::Wrap.has_contracts?(klass, meth, :pre)
86
- pres = RDL::Wrap.get_contracts(klass, meth, :pre)
87
- RDL::Contract::AndContract.check_array(pres, self, *args, &blk)
88
- end
89
- if RDL::Wrap.has_contracts?(klass, meth, :type)
90
- types = RDL::Wrap.get_contracts(klass, meth, :type)
58
+ RDL::Typecheck.typecheck(klass, meth) if $__rdl_info.get(klass, meth, :typecheck)
59
+ pres = $__rdl_info.get(klass, meth, :pre)
60
+ RDL::Contract::AndContract.check_array(pres, self, *args, &blk) if pres
61
+ types = $__rdl_info.get(klass, meth, :type)
62
+ if types
91
63
  matches,args,blk,bind = RDL::Type::MethodType.check_arg_types("#{full_method_name}", self, bind, types, inst, *args, &blk)
92
64
  end
93
65
  }
94
66
  ret = send(#{meth_old.inspect}, *args, &blk)
95
67
  $__rdl_wrap_switch.off {
96
- if RDL::Wrap.has_contracts?(klass, meth, :post)
97
- posts = RDL::Wrap.get_contracts(klass, meth, :post)
98
- RDL::Contract::AndContract.check_array(posts, self, ret, *args, &blk)
99
- end
68
+ posts = $__rdl_info.get(klass, meth, :post)
69
+ RDL::Contract::AndContract.check_array(posts, self, ret, *args, &blk) if posts
100
70
  if matches
101
71
  ret = RDL::Type::MethodType.check_ret_types(self, "#{full_method_name}", types, inst, matches, ret, bind, *args, &blk)
102
72
  end
@@ -213,6 +183,7 @@ class Object
213
183
  # [+klass+] may be Class, Symbol, or String
214
184
  # [+method+] may be Symbol or String
215
185
  # [+contract+] must be a Contract
186
+ # [+wrap+] indicates whether the contract should be enforced (true) or just recorded (false)
216
187
  #
217
188
  # Add a precondition to a method. Possible invocations:
218
189
  # pre(klass, meth, contract)
@@ -221,35 +192,39 @@ class Object
221
192
  # pre(meth) { block } = pre(self, meth, FlatContract.new { block })
222
193
  # pre(contract) = pre(self, next method, contract)
223
194
  # pre { block } = pre(self, next method, FlatContract.new { block })
224
- def pre(*args, &blk)
195
+ def pre(*args, wrap: true, &blk)
225
196
  $__rdl_contract_switch.off { # Don't check contracts inside RDL code itself
226
197
  klass, meth, contract = RDL::Wrap.process_pre_post_args(self, "Precondition", *args, &blk)
227
198
  if meth
228
- RDL::Wrap.add_contract(klass, meth, :pre, contract)
229
- if RDL::Util.method_defined?(klass, meth) || meth == :initialize # there is always an initialize
230
- RDL::Wrap.wrap(klass, meth)
231
- else
232
- $__rdl_to_wrap << [klass, meth]
199
+ $__rdl_info.add(klass, meth, :pre, contract)
200
+ if wrap
201
+ if RDL::Util.method_defined?(klass, meth) || meth == :initialize # there is always an initialize
202
+ RDL::Wrap.wrap(klass, meth)
203
+ else
204
+ $__rdl_to_wrap << [klass, meth]
205
+ end
233
206
  end
234
207
  else
235
- $__rdl_deferred << [klass, :pre, contract]
208
+ $__rdl_deferred << [klass, :pre, contract, {wrap: wrap}]
236
209
  end
237
210
  }
238
211
  end
239
212
 
240
213
  # Add a postcondition to a method. Same possible invocations as pre.
241
- def post(*args, &blk)
214
+ def post(*args, wrap: true, &blk)
242
215
  $__rdl_contract_switch.off {
243
216
  klass, meth, contract = RDL::Wrap.process_pre_post_args(self, "Postcondition", *args, &blk)
244
217
  if meth
245
- RDL::Wrap.add_contract(klass, meth, :post, contract)
246
- if RDL::Util.method_defined?(klass, meth) || meth == :initialize
247
- RDL::Wrap.wrap(klass, meth)
248
- else
249
- $__rdl_to_wrap << [klass, meth]
218
+ $__rdl_info.add(klass, meth, :post, contract)
219
+ if wrap
220
+ if RDL::Util.method_defined?(klass, meth) || meth == :initialize
221
+ RDL::Wrap.wrap(klass, meth)
222
+ else
223
+ $__rdl_to_wrap << [klass, meth]
224
+ end
250
225
  end
251
226
  else
252
- $__rdl_deferred << [klass, :post, contract]
227
+ $__rdl_deferred << [klass, :post, contract, {wrap: wrap}]
253
228
  end
254
229
  }
255
230
  end
@@ -257,12 +232,14 @@ class Object
257
232
  # [+klass+] may be Class, Symbol, or String
258
233
  # [+method+] may be Symbol or String
259
234
  # [+type+] may be Type or String
235
+ # [+wrap+] indicates whether the type should be enforced (true) or just recorded (false)
236
+ # [+typecheck+] indicates whether the method should be statically checked against this type (not yet implemented)
260
237
  #
261
238
  # Set a method's type. Possible invocations:
262
239
  # type(klass, meth, type)
263
240
  # type(meth, type)
264
241
  # type(type)
265
- def type(*args, &blk)
242
+ def type(*args, wrap: true, typecheck: false, typecheck_now: false, &blk)
266
243
  $__rdl_contract_switch.off {
267
244
  klass, meth, type = begin
268
245
  RDL::Wrap.process_type_args(self, *args, &blk)
@@ -281,18 +258,37 @@ class Object
281
258
  # if (meth.to_s[-1] == "?") && (type.ret != $__rdl_type_bool)
282
259
  # warn "#{RDL::Util.pp_klass_method(klass, meth)}: methods that end in ? should have return type %bool"
283
260
  # end
284
- RDL::Wrap.add_contract(klass, meth, :type, type)
285
- if RDL::Util.method_defined?(klass, meth) || meth == :initialize
286
- RDL::Wrap.wrap(klass, meth)
287
- else
288
- $__rdl_to_wrap << [klass, meth]
261
+ $__rdl_info.add(klass, meth, :type, type)
262
+ unless $__rdl_info.set(klass, meth, :typecheck, typecheck)
263
+ raise RuntimeError, "Inconsistent typecheck flag on #{klass}##{meth}"
264
+ end
265
+ if wrap
266
+ if RDL::Util.method_defined?(klass, meth) || meth == :initialize
267
+ RDL::Typecheck.typecheck(klass, meth) if typecheck_now
268
+ RDL::Wrap.wrap(klass, meth)
269
+ else
270
+ $__rdl_to_wrap << [klass, meth]
271
+ $__rdl_to_typecheck_now << [klass, meth] if typecheck_now
272
+ end
289
273
  end
290
274
  else
291
- $__rdl_deferred << [klass, :type, type]
275
+ $__rdl_deferred << [klass, :type, type, {wrap: wrap,
276
+ typecheck: typecheck,
277
+ typecheck_now: typecheck_now}]
292
278
  end
293
279
  }
294
280
  end
295
281
 
282
+ def var_type(klass=self, var, typ)
283
+ raise RuntimeError, "Variable cannot begin with capital" if var.to_s =~ /^[A-Z]/
284
+ return if var.to_s =~ /^[a-z]/ # local variables handled specially, inside type checker
285
+ raise Runtimeerror, "Global variables can't be typed in a class" unless klass = self
286
+ klass = RDL::Util::GLOBAL_NAME if var.to_s =~ /^\$/
287
+ unless $__rdl_info.set(klass, var, :type, $__rdl_parser.scan_str("#T #{typ}"))
288
+ raise RuntimeError, "Type already declared for #{var}"
289
+ end
290
+ end
291
+
296
292
  def self.method_added(meth)
297
293
  $__rdl_contract_switch.off {
298
294
  klass = self.to_s
@@ -302,10 +298,15 @@ class Object
302
298
  if $__rdl_deferred.size > 0
303
299
  a = $__rdl_deferred
304
300
  $__rdl_deferred = [] # Reset before doing more work to avoid infinite recursion
305
- a.each { |prev_klass, kind, contract|
301
+ a.each { |prev_klass, kind, contract, h|
306
302
  raise RuntimeError, "Deferred contract from class #{prev_klass} being applied in class #{klass}" if prev_klass != klass
307
- RDL::Wrap.add_contract(klass, meth, kind, contract)
308
- RDL::Wrap.wrap(klass, meth)
303
+ $__rdl_info.add(klass, meth, kind, contract)
304
+ RDL::Wrap.wrap(klass, meth) if h[:wrap]
305
+ RDL::Typecheck.typecheck(klass, meth) if h[:typecheck_now]
306
+ unless $__rdl_info.set(klass, meth, :typecheck, h[:typecheck])
307
+ raise RuntimeError, "Inconsistent typecheck flag on #{klass}##{meth}"
308
+ end
309
+
309
310
  # It turns out Ruby core/stdlib don't always follow this convention...
310
311
  # if (kind == :type) && (meth.to_s[-1] == "?") && (contract.ret != $__rdl_type_bool)
311
312
  # warn "#{RDL::Util.pp_klass_method(klass, meth)}: methods that end in ? should have return type %bool"
@@ -318,6 +319,12 @@ class Object
318
319
  $__rdl_to_wrap.delete [klass, meth]
319
320
  RDL::Wrap.wrap(klass, meth)
320
321
  end
322
+
323
+ # Type check method if requested; must typecheck before wrap
324
+ if $__rdl_to_typecheck_now.member? [klass, meth]
325
+ $__rdl_to_typecheck_now.delete [klass, meth]
326
+ RDL::Typecheck.typecheck(klass, meth)
327
+ end
321
328
  }
322
329
  end
323
330
 
@@ -331,10 +338,14 @@ class Object
331
338
  if $__rdl_deferred.size > 0
332
339
  a = $__rdl_deferred
333
340
  $__rdl_deferred = [] # Reset before doing more work to avoid infinite recursion
334
- a.each { |prev_klass, kind, contract|
341
+ a.each { |prev_klass, kind, contract, h|
335
342
  raise RuntimeError, "Deferred contract from class #{prev_klass} being applied in class #{klass}" if prev_klass != klass
336
- RDL::Wrap.add_contract(sklass, meth, kind, contract)
337
- RDL::Wrap.wrap(sklass, meth)
343
+ $__rdl_info.add(sklass, meth, kind, contract)
344
+ RDL::Wrap.wrap(sklass, meth) if h[:wrap]
345
+ RDL::Typecheck.typecheck(sklass, meth) if h[:typecheck_now]
346
+ unless $__rdl_info.set(klass, meth, :typecheck, h[:typecheck])
347
+ raise RuntimeError, "Inconsistent typecheck flag on #{klass}##{meth}"
348
+ end
338
349
  }
339
350
  end
340
351
 
@@ -343,6 +354,12 @@ class Object
343
354
  $__rdl_to_wrap.delete [sklass, meth]
344
355
  RDL::Wrap.wrap(sklass, meth)
345
356
  end
357
+
358
+ # Type check method if requested
359
+ if $__rdl_to_typecheck_now.member? [sklass, meth]
360
+ $__rdl_to_typecheck_now.delete [sklass, meth]
361
+ RDL::Typecheck.typecheck(sklass, meth)
362
+ end
346
363
  }
347
364
  end
348
365
 
@@ -451,10 +468,11 @@ class Object
451
468
  }
452
469
  end
453
470
 
454
- # Returns a new object that wraps self in a type cast. This cast is *unchecked*, so use with caution
455
- def type_cast(typ)
471
+ # Returns a new object that wraps self in a type cast. If force is true this cast is *unchecked*, so use with caution
472
+ def type_cast(typ, force: false)
456
473
  $__rdl_contract_switch.off {
457
474
  new_typ = if typ.is_a? RDL::Type::Type then typ else $__rdl_parser.scan_str "#T #{typ}" end
475
+ raise RuntimeError, "type cast error: self not a member of #{new_typ}" unless force || typ.member?(self)
458
476
  obj = SimpleDelegator.new(self)
459
477
  obj.instance_variable_set('@__rdl_type', new_typ)
460
478
  return obj
@@ -1,4 +1,4 @@
1
1
  dir = RUBY_VERSION.split('.')[0] + ".x"
2
2
 
3
- require_rel "../types/ruby-#{dir}/_aliases.rb" # load type aliases first
4
- require_rel "../types/ruby-#{dir}/*.rb"
3
+ require_relative "../types/ruby-#{dir}/_aliases.rb" # load type aliases first
4
+ Dir[File.dirname(__FILE__) + "/../types/ruby-#{dir}/*.rb"].each { |f| require f }
@@ -4,15 +4,13 @@
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'rdl'
7
- s.version = '1.1.1'
8
- s.date = '2016-05-21'
7
+ s.version = '2.0.0.rc1'
8
+ s.date = '2016-07-17'
9
9
  s.summary = 'Ruby type and contract system'
10
10
  s.description = <<-EOF
11
- RDL is a gem that allows contracts (pre- and postconditions) to be added to methods.
12
- Preconditions are checked at run time when the method is called, and
13
- postconditions are checked at run time when the method returns.
14
- RDL also includes extensive support for type contracts, which check the types of arguments and returns
15
- when the method is called and when it returns, respectively.
11
+ RDL is a gem that adds types and contracts to Ruby. RDL includes extensive
12
+ support for specifying method types, which can either be enforced as
13
+ contracts or statically checked.
16
14
  EOF
17
15
  s.authors = ['Jeffrey S. Foster', 'Brianna M. Ren', 'T. Stephen Strickland', 'Alexander T. Yu', 'Milod Kazerounian']
18
16
  s.email = ['rdl-users@googlegroups.com']
@@ -20,5 +18,5 @@ EOF
20
18
  s.executables << 'rdl_query'
21
19
  s.homepage = 'https://github.com/plum-umd/rdl'
22
20
  s.license = 'BSD-3-Clause'
23
- s.add_runtime_dependency 'require_all', '~> 1.3', '>= 1.3.3'
21
+ s.add_runtime_dependency 'parser', '~>2.3', '>= 2.3.1.2'
24
22
  end
@@ -1,5 +1,6 @@
1
1
  require 'minitest/autorun'
2
- require_relative '../lib/rdl.rb'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
3
4
 
4
5
  class TestAlias < Minitest::Test
5
6
 
@@ -62,5 +63,5 @@ class TestAlias < Minitest::Test
62
63
  assert_equal 3, m10(3)
63
64
  assert_raises(RDL::Contract::ContractError) { m10(-1) }
64
65
  end
65
-
66
- end
66
+
67
+ end
@@ -1,5 +1,6 @@
1
1
  require 'minitest/autorun'
2
- require_relative '../lib/rdl.rb'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
3
4
 
4
5
  class TestContract < Minitest::Test
5
6
  include RDL::Contract
@@ -26,7 +27,7 @@ class TestContract < Minitest::Test
26
27
  assert (posfivegt.check self, 5)
27
28
  assert_raises(ContractError) { posfivegt.check self, 4 }
28
29
  end
29
-
30
+
30
31
  def test_or
31
32
  pos = FlatContract.new("Positive") { |x| x > 0 }
32
33
  zero = FlatContract.new("Zero") { |x| x == 0 }
@@ -58,7 +59,7 @@ class TestContract < Minitest::Test
58
59
  proc = pc.wrap(self) { |x, &blk| blk.call(x) }
59
60
  assert_equal 42, (proc.call(42) { |y| y })
60
61
  end
61
-
62
+
62
63
  def test_turn_off
63
64
  foo = FlatContract.new("Foo") {
64
65
  pos = FlatContract.new("Positive") { |x| x > 0 }
@@ -67,4 +68,4 @@ class TestContract < Minitest::Test
67
68
  }
68
69
  assert_equal true, foo.check(self)
69
70
  end
70
- end
71
+ end
@@ -1,5 +1,6 @@
1
1
  require 'minitest/autorun'
2
- require_relative '../lib/rdl.rb'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
3
4
 
4
5
  class TestDsl < Minitest::Test
5
6
 
@@ -1,5 +1,6 @@
1
1
  require 'minitest/autorun'
2
- require_relative '../lib/rdl.rb'
2
+ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
3
+ require 'rdl'
3
4
 
4
5
  class TestGeneric < Minitest::Test
5
6
 
@@ -32,22 +33,18 @@ class TestGeneric < Minitest::Test
32
33
  nil
33
34
  end
34
35
  end
35
-
36
+
36
37
  def setup
37
38
  @ta = RDL::Type::NominalType.new "TestGeneric::A"
38
39
  @th = RDL::Type::NominalType.new "TestGeneric::H"
39
- @tstring = RDL::Type::NominalType.new "String"
40
- @tobject = RDL::Type::NominalType.new "Object"
41
- @tfixnum = RDL::Type::NominalType.new "Fixnum"
42
- @tas = RDL::Type::GenericType.new(@ta, @tstring)
43
- @tao = RDL::Type::GenericType.new(@ta, @tobject)
40
+ @tas = RDL::Type::GenericType.new(@ta, $__rdl_string_type)
41
+ @tao = RDL::Type::GenericType.new(@ta, $__rdl_object_type)
44
42
  @taas = RDL::Type::GenericType.new(@ta, @tas)
45
43
  @taao = RDL::Type::GenericType.new(@ta, @tao)
46
- @thss = RDL::Type::GenericType.new(@th, @tstring, @tstring)
47
- @thoo = RDL::Type::GenericType.new(@th, @tobject, @tobject)
48
- @thsf = RDL::Type::GenericType.new(@th, @tstring, @tfixnum)
44
+ @thss = RDL::Type::GenericType.new(@th, $__rdl_string_type, $__rdl_string_type)
45
+ @thoo = RDL::Type::GenericType.new(@th, $__rdl_object_type, $__rdl_object_type)
46
+ @thsf = RDL::Type::GenericType.new(@th, $__rdl_string_type, $__rdl_fixnum_type)
49
47
  @tb = RDL::Type::NominalType.new "TestGeneric::B"
50
- @tnil = RDL::Type::NilType.new
51
48
  end
52
49
 
53
50
  def test_le
@@ -71,10 +68,10 @@ class TestGeneric < Minitest::Test
71
68
  assert (not (@thss <= @th))
72
69
 
73
70
  # Check co- and contravariance using B
74
- tbss = RDL::Type::GenericType.new(@tb, @tstring, @tstring)
75
- tbso = RDL::Type::GenericType.new(@tb, @tstring, @tobject)
76
- tbos = RDL::Type::GenericType.new(@tb, @tobject, @tstring)
77
- tboo = RDL::Type::GenericType.new(@tb, @tobject, @tobject)
71
+ tbss = RDL::Type::GenericType.new(@tb, $__rdl_string_type, $__rdl_string_type)
72
+ tbso = RDL::Type::GenericType.new(@tb, $__rdl_string_type, $__rdl_object_type)
73
+ tbos = RDL::Type::GenericType.new(@tb, $__rdl_object_type, $__rdl_string_type)
74
+ tboo = RDL::Type::GenericType.new(@tb, $__rdl_object_type, $__rdl_object_type)
78
75
  assert (tbss <= tbss)
79
76
  assert (not (tbss <= tbso))
80
77
  assert (tbss <= tbos)
@@ -94,10 +91,10 @@ class TestGeneric < Minitest::Test
94
91
  end
95
92
 
96
93
  def test_le_structural
97
- tbss = RDL::Type::GenericType.new(@tb, @tstring, @tstring)
98
- tma = RDL::Type::MethodType.new([], nil, @tnil)
99
- tmb = RDL::Type::MethodType.new([@tstring], nil, @tnil)
100
- tmc = RDL::Type::MethodType.new([@tfixnum], nil, @tnil)
94
+ tbss = RDL::Type::GenericType.new(@tb, $__rdl_string_type, $__rdl_string_type)
95
+ tma = RDL::Type::MethodType.new([], nil, $__rdl_nil_type)
96
+ tmb = RDL::Type::MethodType.new([$__rdl_string_type], nil, $__rdl_nil_type)
97
+ tmc = RDL::Type::MethodType.new([$__rdl_fixnum_type], nil, $__rdl_nil_type)
101
98
  ts1 = RDL::Type::StructuralType.new(m2: tma)
102
99
  assert (tbss <= ts1)
103
100
  ts2 = RDL::Type::StructuralType.new(m1: tmb)
@@ -109,18 +106,25 @@ class TestGeneric < Minitest::Test
109
106
  ts5 = RDL::Type::StructuralType.new(m1: tmb, m2: tmc)
110
107
  assert (tbss <= ts5)
111
108
  end
112
-
109
+
113
110
  class C
114
111
  type "() -> self"
115
112
  def m1() return self; end
116
113
  type "() -> self"
117
114
  def m2() return C.new; end
115
+ type "() -> self"
116
+ def m3() return Object.new; end
118
117
  end
119
-
118
+
119
+ class D < C
120
+ end
121
+
120
122
  def test_self_type
121
123
  c = C.new
122
124
  assert(c.m1)
123
- assert_raises(RDL::Type::TypeError) { c.m2 }
125
+ assert(c.m2)
126
+ assert_raises(RDL::Type::TypeError) { c.m3 }
127
+ assert(D.new.m1)
124
128
  end
125
129
 
126
130
  def test_member
@@ -137,17 +141,17 @@ class TestGeneric < Minitest::Test
137
141
  end
138
142
 
139
143
  def test_instantiate
140
- assert_raises(RuntimeError) { Object.new.instantiate!(@tstring) }
141
-
144
+ assert_raises(RuntimeError) { Object.new.instantiate!($__rdl_string_type) }
145
+
142
146
  # Array<String>
143
147
  assert (A.new([]).instantiate!('String'))
144
- assert (A.new(["a", "b", "c"]).instantiate!(@tstring))
148
+ assert (A.new(["a", "b", "c"]).instantiate!($__rdl_string_type))
145
149
  assert (A.new(["a", "b", "c"]).instantiate!('String'))
146
150
  assert_raises(RDL::Type::TypeError) { A.new([1, 2, 3]).instantiate!('String') }
147
151
 
148
152
  # Array<Object>
149
153
  assert (A.new([])).instantiate!('Object')
150
- assert (A.new(["a", "b", "c"]).instantiate!(@tobject))
154
+ assert (A.new(["a", "b", "c"]).instantiate!($__rdl_object_type))
151
155
  assert (A.new(["a", "b", "c"]).instantiate!('Object'))
152
156
  assert (A.new([1, 2, 3]).instantiate!('Object'))
153
157