rdl 2.1.0 → 2.2.0

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 (102) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -6
  4. data/CHANGES.md +29 -0
  5. data/README.md +94 -26
  6. data/lib/rdl/boot.rb +82 -41
  7. data/lib/rdl/boot_rails.rb +5 -0
  8. data/lib/rdl/config.rb +9 -1
  9. data/lib/rdl/query.rb +2 -2
  10. data/lib/rdl/typecheck.rb +972 -225
  11. data/lib/rdl/types/annotated_arg.rb +8 -0
  12. data/lib/rdl/types/ast_node.rb +73 -0
  13. data/lib/rdl/types/bot.rb +8 -0
  14. data/lib/rdl/types/bound_arg.rb +63 -0
  15. data/lib/rdl/types/computed.rb +48 -0
  16. data/lib/rdl/types/dependent_arg.rb +9 -0
  17. data/lib/rdl/types/dynamic.rb +61 -0
  18. data/lib/rdl/types/finite_hash.rb +54 -9
  19. data/lib/rdl/types/generic.rb +33 -0
  20. data/lib/rdl/types/intersection.rb +8 -0
  21. data/lib/rdl/types/lexer.rex +6 -1
  22. data/lib/rdl/types/lexer.rex.rb +13 -1
  23. data/lib/rdl/types/method.rb +14 -0
  24. data/lib/rdl/types/nominal.rb +8 -0
  25. data/lib/rdl/types/non_null.rb +8 -0
  26. data/lib/rdl/types/optional.rb +8 -0
  27. data/lib/rdl/types/parser.racc +31 -5
  28. data/lib/rdl/types/parser.tab.rb +540 -302
  29. data/lib/rdl/types/rdl_types.rb +45 -0
  30. data/lib/rdl/types/singleton.rb +14 -1
  31. data/lib/rdl/types/string.rb +104 -0
  32. data/lib/rdl/types/structural.rb +8 -0
  33. data/lib/rdl/types/top.rb +8 -0
  34. data/lib/rdl/types/tuple.rb +32 -8
  35. data/lib/rdl/types/type.rb +54 -11
  36. data/lib/rdl/types/union.rb +41 -2
  37. data/lib/rdl/types/var.rb +10 -0
  38. data/lib/rdl/types/vararg.rb +8 -0
  39. data/lib/rdl/util.rb +13 -10
  40. data/lib/rdl/wrap.rb +271 -27
  41. data/lib/rdl_disable.rb +16 -2
  42. data/lib/types/active_record.rb +1 -0
  43. data/lib/types/core/array.rb +442 -23
  44. data/lib/types/core/basic_object.rb +3 -3
  45. data/lib/types/core/bigdecimal.rb +5 -0
  46. data/lib/types/core/class.rb +2 -0
  47. data/lib/types/core/dir.rb +3 -3
  48. data/lib/types/core/enumerable.rb +4 -4
  49. data/lib/types/core/enumerator.rb +1 -1
  50. data/lib/types/core/file.rb +4 -4
  51. data/lib/types/core/float.rb +203 -0
  52. data/lib/types/core/hash.rb +390 -15
  53. data/lib/types/core/integer.rb +223 -10
  54. data/lib/types/core/io.rb +2 -2
  55. data/lib/types/core/kernel.rb +8 -5
  56. data/lib/types/core/marshal.rb +3 -0
  57. data/lib/types/core/module.rb +3 -3
  58. data/lib/types/core/numeric.rb +0 -2
  59. data/lib/types/core/object.rb +5 -5
  60. data/lib/types/core/pathname.rb +2 -2
  61. data/lib/types/core/process.rb +1 -3
  62. data/lib/types/core/range.rb +1 -1
  63. data/lib/types/core/regexp.rb +2 -2
  64. data/lib/types/core/set.rb +1 -1
  65. data/lib/types/core/string.rb +408 -16
  66. data/lib/types/core/symbol.rb +3 -3
  67. data/lib/types/core/time.rb +1 -1
  68. data/lib/types/core/uri.rb +13 -13
  69. data/lib/types/rails/_helpers.rb +7 -1
  70. data/lib/types/rails/action_controller/mime_responds.rb +2 -0
  71. data/lib/types/rails/active_record/associations.rb +42 -30
  72. data/lib/types/rails/active_record/comp_types.rb +637 -0
  73. data/lib/types/rails/active_record/finder_methods.rb +1 -1
  74. data/lib/types/rails/active_record/model_schema.rb +28 -16
  75. data/lib/types/rails/active_record/relation.rb +5 -3
  76. data/lib/types/rails/active_record/sql-strings.rb +166 -0
  77. data/lib/types/rails/string.rb +1 -1
  78. data/lib/types/sequel.rb +1 -0
  79. data/lib/types/sequel/comp_types.rb +581 -0
  80. data/rdl.gemspec +5 -4
  81. data/test/test_alias.rb +4 -0
  82. data/test/test_array_types.rb +244 -0
  83. data/test/test_bound_types.rb +80 -0
  84. data/test/test_contract.rb +4 -0
  85. data/test/test_dsl.rb +5 -0
  86. data/test/test_dyn_comptype_checks.rb +206 -0
  87. data/test/test_generic.rb +21 -20
  88. data/test/test_hash_types.rb +322 -0
  89. data/test/test_intersection.rb +1 -0
  90. data/test/test_le.rb +29 -4
  91. data/test/test_member.rb +3 -1
  92. data/test/test_parser.rb +5 -0
  93. data/test/test_query.rb +1 -0
  94. data/test/test_rdl.rb +63 -28
  95. data/test/test_rdl_type.rb +4 -0
  96. data/test/test_string_types.rb +102 -0
  97. data/test/test_type_contract.rb +59 -37
  98. data/test/test_typecheck.rb +480 -75
  99. data/test/test_types.rb +17 -0
  100. data/test/test_wrap.rb +5 -0
  101. metadata +35 -5
  102. data/lib/types/rails/active_record/schema_types.rb +0 -51
@@ -1,9 +1,9 @@
1
1
  RDL.nowrap :BasicObject
2
2
 
3
- RDL.type :BasicObject, :==, '(%any other) -> %bool'
3
+ RDL.type :BasicObject, :==, '(%any other) -> %bool', effect: [:+, :+]
4
4
  RDL.type :BasicObject, :equal?, '(%any other) -> %bool'
5
- RDL.type :BasicObject, :!, '() -> %bool'
6
- RDL.type :BasicObject, :!=, '(%any other) -> %bool'
5
+ RDL.type :BasicObject, :!, '() -> %bool', effect: [:+, :+]
6
+ RDL.type :BasicObject, :!=, '(%any other) -> %bool', effect: [:+, :+]
7
7
  RDL.type :BasicObject, :instance_eval, '(String, ?String filename, ?Integer lineno) -> %any'
8
8
  RDL.type :BasicObject, :instance_eval, '() { () -> %any } -> %any'
9
9
  RDL.type :BasicObject, :instance_exec, '(*%any args) { (*%any) -> %any } -> %any'
@@ -1,5 +1,10 @@
1
1
  RDL.nowrap :BigDecimal
2
2
 
3
+ class BigDecimal < Numeric; end ## Hacky way around existing issue.
4
+ ## The issue is any types that even reference BigDecimal, e.g., Integer#+ etc., will
5
+ ## call const_get on it, but without the above, the class is undefined.
6
+ ## May want to come up with more elegant solution in the future.
7
+
3
8
  RDL.type :BigDecimal, :%, '(%numeric) -> BigDecimal'
4
9
  RDL.pre(:BigDecimal, :%) { |x| x!=0&&(if x.is_a?(Float) then x!=Float::INFINITY && !x.nan? else true end)}
5
10
 
@@ -13,3 +13,5 @@ RDL.type :Class, :instance_methods, '(?%bool) -> Array<Symbol>'
13
13
  RDL.type :Class, :class, '() -> Class'
14
14
  RDL.type :Class, :superclass, '() -> Class'
15
15
  RDL.type :Class, :name, '() -> String'
16
+ RDL.type :Class, :==, '(%any) -> %bool', effect: [:+, :+]
17
+ RDL.type :Class, :===, '(%any) -> %bool', effect: [:+, :+]
@@ -1,6 +1,6 @@
1
1
  RDL.nowrap :Dir
2
2
 
3
- RDL.rdl_alias :Dir, :[], :glob
3
+ RDL.rdl_alias :Dir, :'self.[]', :'self.glob'
4
4
 
5
5
  RDL.type :Dir, 'self.chdir', '(?(String or Pathname)) -> 0'
6
6
  RDL.type :Dir, 'self.chdir', '(?(String or Pathname)) { (String) -> u } -> u'
@@ -12,8 +12,8 @@ RDL.type :Dir, 'self.exist?', '(String file) -> %bool'
12
12
  RDL.type :Dir, 'self.foreach', '(String dir, ?Encoding) { (String) -> %any } -> nil'
13
13
  RDL.type :Dir, 'self.foreach', '(String dir, ?Encoding) -> Enumerator<String>'
14
14
  RDL.type :Dir, 'self.getwd', '() -> String'
15
- RDL.type :Dir, 'self.glob', '(String or Array<String> pattern, ?Fixum flags) -> Array<String>'
16
- RDL.type :Dir, 'self.glob', '(String or Array<String> pattern, ?Fixum flags) { (String) -> %any} -> nil'
15
+ RDL.type :Dir, 'self.glob', '(String or Array<String> pattern, ?Fixnum flags) -> Array<String>'
16
+ RDL.type :Dir, 'self.glob', '(String or Array<String> pattern, ?Fixnum flags) { (String) -> %any} -> nil'
17
17
  RDL.type :Dir, 'self.home', '(?String) -> String'
18
18
  RDL.type :Dir, 'self.mkdir', '(String, ?Integer) -> 0'
19
19
  RDL.type :Dir, 'self.open', '(String, ?Encoding) -> Dir'
@@ -2,8 +2,8 @@ RDL.nowrap :Enumerable
2
2
 
3
3
  RDL.type_params :Enumerable, [:t], :all?
4
4
 
5
- RDL.type :Enumerable, :all?, '() -> %bool'
6
- RDL.type :Enumerable, :all?, '() { (t) -> %bool } -> %bool'
5
+ RDL.type :Enumerable, :all?, '() -> %bool', effect: [:blockdep, :blockdep]
6
+ RDL.type :Enumerable, :all?, '() { (t) -> %bool } -> %bool', effect: [:blockdep, :blockdep]
7
7
  RDL.type :Enumerable, :any?, '() -> %bool'
8
8
  RDL.type :Enumerable, :any?, '() { (t) -> %bool } -> %bool'
9
9
  # RDL.type :Enumerable, :chunk, '(XXXX : *XXXX)' # TODO
@@ -24,8 +24,8 @@ RDL.type :Enumerable, :each_cons, '(Integer n) { (Array<t>) -> %any } -> nil'
24
24
  RDL.type :Enumerable, :each_cons, '(Integer n) -> Enumerator<t>'
25
25
  # RDL.type :Enumerable, :each_entry, '(XXXX : *XXXX)' # TODO
26
26
  RDL.rdl_alias :Enumerable, :each_slice, :each_cons
27
- RDL.type :Enumerable, :each_with_index, '() { (t, Integer) -> %any } -> Enumerable<t>' # args! note may not return self
28
- RDL.type :Enumerable, :each_with_index, '() -> Enumerable<t>' # args! note may not return self
27
+ RDL.type :Enumerable, :each_with_index, '() { (t, Integer) -> %any } -> Enumerable<t>', effect: [:blockdep, :blockdep] # args! note may not return self
28
+ RDL.type :Enumerable, :each_with_index, '() -> Enumerable<t>', effect: [:blockdep, :blockdep] # args! note may not return self
29
29
  # RDL.type :Enumerable, :each_with_object, '(XXXX : XXXX)' #TODO
30
30
  RDL.type :Enumerable, :entries, '() -> Array<t>' # TODO args?
31
31
  RDL.rdl_alias :Enumerable, :find, :detect
@@ -18,7 +18,7 @@ RDL.type :Enumerator, :next, '() -> t'
18
18
  RDL.type :Enumerator, :next_values, '() -> Array<t>'
19
19
  RDL.type :Enumerator, :peek, '() -> t'
20
20
  RDL.type :Enumerator, :peek_values, '() -> Array<t>'
21
- RDL.type :Enumerator, :rewrind, '() -> self'
21
+ RDL.type :Enumerator, :rewind, '() -> self'
22
22
  RDL.type :Enumerator, :size, '() -> Integer or Float or nil'
23
23
  RDL.rdl_alias :Enumerator, :with_index, :each_with_index
24
24
  RDL.rdl_alias :Enumerator, :with_object, :each_with_object
@@ -23,7 +23,7 @@ RDL.type :File, 'self.expand_path', '(%path file, ?%path dir) -> String abs_file
23
23
  RDL.type :File, 'self.extname', '(String path) -> String'
24
24
  RDL.type :File, 'self.file?', '(String or IO file) -> %bool'
25
25
  RDL.type :File, 'self.fnmatch', '(String pattern, String path, ?Integer flags) -> %bool'
26
- RDL.rdl_alias :File, :fnmatch?, :fnmatch
26
+ RDL.rdl_alias :File, :'self.fnmatch?', :'self.fnmatch'
27
27
  RDL.type :File, 'self.ftype', '(String file) -> String' # TODO: return in set of strings
28
28
  RDL.type :File, 'self.grpowned?', '(String or IO file) -> %bool'
29
29
  RDL.type :File, 'self.identical?', '(String or IO file_1, String or IO file_2) -> %bool'
@@ -41,7 +41,7 @@ RDL.type :File, 'self.pipe?', '(String file) -> %bool'
41
41
  RDL.type :File, 'self.readable?', '(String file) -> %bool'
42
42
  RDL.type :File, 'self.readable_real?', '(String file) -> %bool'
43
43
  RDL.type :File, 'self.readlink', '(String link) -> String file'
44
- RDL.type :File, 'self.readldirpath', '(String pathname, ?String dir) -> String real_pathname'
44
+ RDL.type :File, 'self.realdirpath', '(String pathname, ?String dir) -> String real_pathname'
45
45
  RDL.type :File, 'self.realpath', '(String pathname, ?String dir) -> String real_pathname'
46
46
  RDL.type :File, 'self.rename', '(String old, String new) -> 0'
47
47
  RDL.type :File, 'self.setgid?', '(String file) -> %bool'
@@ -56,7 +56,7 @@ RDL.type :File, 'self.symlink', '(String old, String new) -> 0'
56
56
  RDL.type :File, 'self.symlink?', '(String file) -> %bool'
57
57
  RDL.type :File, 'self.truncate', '(String file, Integer) -> 0'
58
58
  RDL.type :File, 'self.umask', '(?Integer) -> Integer'
59
- RDL.rdl_alias :File, :unlink, :delete
59
+ RDL.rdl_alias :File, :'self.unlink', :'self.delete'
60
60
  RDL.type :File, 'self.utime', '(Time atime, Time mtime, *String files) -> Integer'
61
61
  RDL.type :File, 'self.world_readable?', '(String or IO file) -> Integer or nil'
62
62
  RDL.type :File, 'self.world_writable?', '(String or IO file) -> Integer or nil'
@@ -105,7 +105,7 @@ RDL.type :'File::Stat', :mode, '() -> Integer'
105
105
  RDL.type :'File::Stat', :mtime, '() -> Time'
106
106
  RDL.type :'File::Stat', :nlink, '() -> Integer'
107
107
  RDL.type :'File::Stat', :owned?, '() -> %bool'
108
- RDL.type :'File::Stat', :pip?, '() -> %bool'
108
+ RDL.type :'File::Stat', :pipe?, '() -> %bool'
109
109
  RDL.type :'File::Stat', :rdev, '() -> Integer or nil'
110
110
  RDL.type :'File::Stat', :rdev_major, '() -> Integer'
111
111
  RDL.type :'File::Stat', :rdev_minor, '() -> Integer'
@@ -1,5 +1,208 @@
1
1
  RDL.nowrap :Float
2
2
 
3
+ RDL.type :Float, :%, '(Integer x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :%, "Float")``'
4
+ RDL.type :Float, :%, '(Float x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :%, "Float")``'
5
+ RDL.type :Float, :%, '(Rational x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :%, "Float")``'
6
+ RDL.type :Float, :%, '(BigDecimal x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :%, "BigDecimal")``'
7
+
8
+ RDL.type :Float, :*, '(Integer) -> ``sing_or_type(trec, targs, :*, "Float")``'
9
+ RDL.type :Float, :*, '(Float) -> ``sing_or_type(trec, targs, :*, "Float")``'
10
+ RDL.type :Float, :*, '(Rational) -> ``sing_or_type(trec, targs, :*, "Float")``'
11
+ RDL.type :Float, :*, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :*, "BigDecimal")``'
12
+ RDL.type :Float, :*, '(Complex) -> ``sing_or_type(trec, targs, :*, "Complex")``'
13
+ RDL.pre(:Float, :*) { |x| if (x.real.is_a?(BigDecimal)||x.imaginary.is_a?(BigDecimal)) then (if x.real.is_a?(Float) then (x.real!=Float::INFINITY && !(x.real.nan?)) elsif(x.imaginary.is_a?(Float)) then x.imaginary!=Float::INFINITY && !(x.imaginary.nan?) else true end) && self!=Float::INFINITY && !(self.nan?) else true end} #can't have a complex with part BigDecimal, other part infinity/NAN
14
+
15
+ RDL.type :Float, :**, '(Integer) -> ``sing_or_type(trec, targs, :**, "Float")``'
16
+ RDL.type :Float, :**, '(Float) -> ``sing_or_type(trec, targs, :**, "%numeric")``'
17
+ RDL.type :Float, :**, '(Rational) -> ``sing_or_type(trec, targs, :**, "%numeric")``'
18
+ RDL.type :Float, :**, '(BigDecimal) -> ``sing_or_type(trec, targs, :**, "BigDecimal")``'
19
+ RDL.pre(:Float, :**) { |x| x!=BigDecimal::INFINITY && if self<0 then x<=-1||x>=0 else true end}
20
+ RDL.post(:Float, :**) { |x| x.real?}
21
+ RDL.type :Float, :**, '(Complex) -> ``sing_or_type(trec, targs, :**, "Complex")``'
22
+ RDL.pre(:Float, :**) { |x| x != 0 && if (x.real.is_a?(BigDecimal)||x.imaginary.is_a?(BigDecimal)) then (if x.real.is_a?(Float) then (x.real!=Float::INFINITY && !(x.real.nan?)) elsif(x.imaginary.is_a?(Float)) then x.imaginary!=Float::INFINITY && !(x.imaginary.nan?) else true end) && self!=Float::INFINITY && !(self.nan?) else true end}
23
+
24
+ RDL.type :Float, :+, '(Integer) -> ``sing_or_type(trec, targs, :+, "Float")``'
25
+ RDL.type :Float, :+, '(Float) -> ``sing_or_type(trec, targs, :+, "Float")``'
26
+ RDL.type :Float, :+, '(Rational) -> ``sing_or_type(trec, targs, :+, "Float")``'
27
+ RDL.type :Float, :+, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :+, "BigDecimal")``'
28
+ RDL.type :Float, :+, '(Complex) -> ``sing_or_type(trec, targs, :+, "Complex")``'
29
+ RDL.pre(:Float, :+) { |x| if x.real.is_a?(BigDecimal) then self!=Float::INFINITY && !(self.nan?) else true end}
30
+
31
+ RDL.type :Float, :-, '(Integer) -> ``sing_or_type(trec, targs, :-, "Float")``'
32
+ RDL.type :Float, :-, '(Float) -> ``sing_or_type(trec, targs, :-, "Float")``'
33
+ RDL.type :Float, :-, '(Rational) -> ``sing_or_type(trec, targs, :-, "Float")``'
34
+ RDL.type :Float, :-, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :-, "BigDecimal")``'
35
+ RDL.type :Float, :-, '(Complex) -> ``sing_or_type(trec, targs, :-, "Complex")``'
36
+ RDL.pre(:Float, :-) { |x| if x.real.is_a?(BigDecimal) then self!=Float::INFINITY && !(self.nan?) else true end}
37
+
38
+ RDL.type :Float, :-@, '() -> ``sing_or_type(trec, targs, :-@, "Float")``'
39
+
40
+ RDL.type :Float, :+@, '() -> ``sing_or_type(trec, targs, :+@, "Float")``'
41
+
42
+ RDL.type :Float, :/, '(Integer x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :/, "Float")``'
43
+ RDL.type :Float, :/, '(Float x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :/, "Float")``'
44
+ RDL.type :Float, :/, '(Rational x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :/, "Float")``'
45
+ RDL.type :Float, :/, '(BigDecimal x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :/, "BigDecimal")``'
46
+ RDL.type :Float, :/, '(Complex x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :/, "Complex")``'
47
+ RDL.pre(:Float, :/) { |x| if (x.real.is_a?(BigDecimal)||x.imaginary.is_a?(BigDecimal)) then (if x.real.is_a?(Float) then (x.real!=Float::INFINITY && !(x.real.nan?)) elsif(x.imaginary.is_a?(Float)) then x.imaginary!=Float::INFINITY && !(x.imaginary.nan?) else true end) && self!=Float::INFINITY && !(self.nan?) else true end && if (x.real.is_a?(Rational) && x.imaginary.is_a?(Float)) then !x.imaginary.nan? else true end}
48
+
49
+ RDL.type :Float, :<, '(Integer) -> ``sing_or_type(trec, targs, :<, "%bool")``'
50
+ RDL.type :Float, :<, '(Float) -> ``sing_or_type(trec, targs, :<, "%bool")``'
51
+ RDL.type :Float, :<, '(Rational) -> ``sing_or_type(trec, targs, :<, "%bool")``'
52
+ RDL.type :Float, :<, '(BigDecimal x {{ !self.nan? && !self.infinite? }}) -> ``sing_or_type(trec, targs, :<, "%bool")``'
53
+
54
+ RDL.type :Float, :<=, '(Integer) -> ``sing_or_type(trec, targs, :<=, "%bool")``'
55
+ RDL.type :Float, :<=, '(Float) -> ``sing_or_type(trec, targs, :<=, "%bool")``'
56
+ RDL.type :Float, :<=, '(Rational) -> ``sing_or_type(trec, targs, :<=, "%bool")``'
57
+ RDL.type :Float, :<=, '(BigDecimal x {{ !self.nan? && !self.infinite? }}) -> ``sing_or_type(trec, targs, :<=, "%bool")``'
58
+
59
+ RDL.type :Float, :<=>, '(Integer) -> ``sing_or_type(trec, targs, :<=>, "Integer")``'
60
+ RDL.post(:Float, :<=>) { |x| x == -1 || x==0 || x==1}
61
+ RDL.type :Float, :<=>, '(Float) -> ``sing_or_type(trec, targs, :<=>, "Integer")``'
62
+ RDL.post(:Float, :<=>) { |x| x == -1 || x==0 || x==1}
63
+ RDL.type :Float, :<=>, '(Rational) -> ``sing_or_type(trec, targs, :<=>, "Integer")``'
64
+ RDL.post(:Float, :<=>) { |x| x == -1 || x==0 || x==1}
65
+ RDL.type :Float, :<=>, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :<=>, "Integer")``'
66
+ RDL.post(:Float, :<=>) { |x| x == -1 || x==0 || x==1}
67
+
68
+ RDL.type :Float, :==, '(Object) -> ``sing_or_type(trec, targs, :==, "%bool")``'
69
+ RDL.pre(:Float, :==) { |x| if (x.is_a?(BigDecimal)) then (!self.nan? && self!=Float::INFINITY) else true end}
70
+
71
+ RDL.type :Float, :===, '(Object) -> ``sing_or_type(trec, targs, :===, "%bool")``'
72
+ RDL.pre(:Float, :===) { |x| if (x.is_a?(BigDecimal)) then (!self.nan? && self!=Float::INFINITY) else true end}
73
+
74
+ RDL.type :Float, :>, '(Integer) -> ``sing_or_type(trec, targs, :>, "%bool")``'
75
+ RDL.type :Float, :>, '(Float) -> ``sing_or_type(trec, targs, :>, "%bool")``'
76
+ RDL.type :Float, :>, '(Rational) -> ``sing_or_type(trec, targs, :>, "%bool")``'
77
+ RDL.type :Float, :>, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :>, "%bool")``'
78
+
79
+ RDL.type :Float, :>=, '(Integer) -> ``sing_or_type(trec, targs, :>=, "%bool")``'
80
+ RDL.type :Float, :>=, '(Float) -> ``sing_or_type(trec, targs, :>=, "%bool")``'
81
+ RDL.type :Float, :>=, '(Rational) -> ``sing_or_type(trec, targs, :>=, "%bool")``'
82
+ RDL.type :Float, :>=, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :>=, "%bool")``'
83
+
84
+ RDL.type :Float, :abs, '() -> Float r {{ r>=0 || (if self.nan? then r.nan? end) }}' ## TODO
85
+
86
+ RDL.type :Float, :abs2, '() -> Float r {{ r>=0 || (if self.nan? then r.nan? end) }}' ## TODO
87
+
88
+ RDL.type :Float, :div, '(Integer x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :div, "Integer")``'
89
+ RDL.type :Float, :div, '(Float x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :div, "Integer")``'
90
+ RDL.type :Float, :div, '(Rational x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :div, "Integer")``'
91
+ RDL.type :Float, :div, '(BigDecimal x {{ x != 0 && !x.nan? && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :div, "Integer")``'
92
+
93
+ RDL.type :Float, :divmod, '(%real) -> [%real, %real]'
94
+ RDL.pre(:Float, :divmod) { |x| x != 0 && if x.is_a?(Float) then !x.nan? else true end && self!=Float::INFINITY && !self.nan?}
95
+
96
+ RDL.type :Float, :angle, '() -> ``sing_or_type(trec, targs, :angle, "%numeric")``'
97
+ RDL.post(:Float, :angle) { |r,x| r == 0 || r == Math::PI || r == Float::NAN}
98
+
99
+ RDL.type :Float, :arg, '() -> ``sing_or_type(trec, targs, :rg, "%numeric")``'
100
+ RDL.post(:Float, :arg) { |r,x| r == 0 || r == Math::PI || r == Float::NAN}
101
+
102
+ RDL.type :Float, :ceil, '() -> ``sing_or_type(trec, targs, :ceil, "Integer")``'
103
+ RDL.pre(:Float, :ceil) { !self.infinite? && !self.nan?}
104
+
105
+ RDL.type :Float, :coerce, '(%real) -> [Float, Float]'
106
+
107
+ RDL.type :Float, :denominator, '() -> Integer r {{ r>0 }}' ## TODO
108
+
109
+ RDL.type :Float, :equal?, '(Object) -> ``sing_or_type(trec, targs, :equal?, "%bool")``'
110
+
111
+ RDL.type :Float, :eql?, '(Object) -> ``sing_or_type(trec, targs, :eql?, "%bool")``'
112
+
113
+ RDL.type :Float, :fdiv, '(Integer) -> ``sing_or_type(trec, targs, :fdiv, "Float")``'
114
+ RDL.type :Float, :fdiv, '(Float) -> ``sing_or_type(trec, targs, :fdiv, "Float")``'
115
+ RDL.type :Float, :fdiv, '(Rational) -> ``sing_or_type(trec, targs, :fdiv, "Float")``'
116
+ RDL.type :Float, :fdiv, '(BigDecimal x {{ !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :fdiv, "BigDecimal")``'
117
+ RDL.type :Float, :fdiv, '(Complex) -> ``sing_or_type(trec, targs, :fdiv, "Complex")``'
118
+ RDL.pre(:Float, :fdiv) { |x| x != 0 && if (x.real.is_a?(BigDecimal)||x.imaginary.is_a?(BigDecimal)) then (if x.real.is_a?(Float) then (x.real!=Float::INFINITY && !(x.real.nan?)) elsif(x.imaginary.is_a?(Float)) then x.imaginary!=Float::INFINITY && !(x.imaginary.nan?) else true end) && self!=Float::INFINITY && !(self.nan?) else true end && if (x.real.is_a?(Rational) && x.imaginary.is_a?(Float)) then !x.imaginary.nan? else true end}
119
+
120
+ RDL.type :Float, :finite?, '() -> ``sing_or_type(trec, targs, :finite?, "%bool")``'
121
+
122
+ RDL.type :Float, :floor, '() -> ``sing_or_type(trec, targs, :floor, "Integer")``'
123
+ RDL.pre(:Float, :ceil) { !self.infinite? && !self.nan?}
124
+
125
+ RDL.type :Float, :hash, '() -> Integer'
126
+
127
+ RDL.type :Float, :infinite?, '() -> ``sing_or_type(trec, targs, :infinite?, "Integer")``'
128
+ RDL.post(:Float, :infinite?) { |r,x| r == -1 || r == 1 || r == nil }
129
+
130
+ RDL.type :Float, :to_s, '() -> String'
131
+ RDL.type :Float, :inspect, '() -> String'
132
+
133
+ RDL.type :Float, :magnitude, '() -> ``sing_or_type(trec, targs, :magnitude, "Float")``'
134
+ RDL.post(:Float, :magnitude) { |r,x| r>=0 }
135
+
136
+ RDL.type :Float, :modulo, '(Integer x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :modulo, "Float")``'
137
+ RDL.type :Float, :modulo, '(Float x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :modulo, "Float")``'
138
+ RDL.type :Float, :modulo, '(Rational x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :modulo, "Float")``'
139
+ RDL.type :Float, :modulo, '(BigDecimal x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :modulo, "BigDecimal")``'
140
+
141
+ RDL.type :Float, :nan?, '() -> ``sing_or_type(trec, targs, :nan?, "%bool")``'
142
+
143
+ RDL.type :Float, :next_float, '() -> ``sing_or_type(trec, targs, :next_float, "Float")``'
144
+
145
+ RDL.type :Float, :numerator, '() -> ``sing_or_type(trec, targs, :numerator, "Integer")``'
146
+
147
+ RDL.type :Float, :phase, '() -> ``sing_or_type(trec, targs, :phase, "%numeric")``'
148
+ RDL.post(:Float, :phase) { |r,x| r == 0 || r == Math::PI || r == Float::NAN}
149
+
150
+ RDL.type :Float, :prev_float, '() -> ``sing_or_type(trec, targs, :prev_float, "Float")``'
151
+
152
+ RDL.type :Float, :quo, '(Integer x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :quo, "Float")``'
153
+ RDL.type :Float, :quo, '(Float x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :quo, "Float")``'
154
+ RDL.type :Float, :quo, '(Rational x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :quo, "Float")``'
155
+ RDL.type :Float, :quo, '(BigDecimal x {{ x != 0 && !self.infinite? && !self.nan? }}) -> ``sing_or_type(trec, targs, :quo, "BigDecimal")``'
156
+ RDL.type :Float, :quo, '(Complex x {{ x != 0 }}) -> ``sing_or_type(trec, targs, :quo, "Complex")``'
157
+ RDL.pre(:Float, :quo) { |x| if (x.real.is_a?(BigDecimal)||x.imaginary.is_a?(BigDecimal)) then (if x.real.is_a?(Float) then (x.real!=Float::INFINITY && !(x.real.nan?)) elsif(x.imaginary.is_a?(Float)) then x.imaginary!=Float::INFINITY && !(x.imaginary.nan?) else true end) && self!=Float::INFINITY && !(self.nan?) else true end && if (x.real.is_a?(Rational) && x.imaginary.is_a?(Float)) then !x.imaginary.nan? else true end}
158
+
159
+ RDL.type :Float, :rationalize, '() -> ``sing_or_type(trec, targs, :rationalize, "Rational")``'
160
+ RDL.pre(:Float, :rationalize) { !self.infinite? && !self.nan?}
161
+
162
+ RDL.type :Float, :rationalize, '(%numeric) -> ``sing_or_type(trec, targs, :rationalize, "Rational")``'
163
+ RDL.pre(:Float, :rationalize) { |x| if x.is_a?(Float) then x!=Float::INFINITY && !x.nan? else true end}
164
+
165
+ RDL.type :Float, :round, '() -> ``sing_or_type(trec, targs, :round, "Integer")``'
166
+ RDL.pre(:Float, :round) { !self.infinite? && !self.nan?}
167
+
168
+ RDL.type :Float, :round, '(%numeric) -> ``sing_or_type(trec, targs, :round, "%numeric")``'
169
+ RDL.pre(:Float, :round) { |x| x != 0 && if x.is_a?(Complex) then x.imaginary==0 && (if x.real.is_a?(Float)||x.real.is_a?(BigDecimal) then !x.real.infinite? && !x.real.nan? else true end) elsif x.is_a?(Float) then x!=Float::INFINITY && !x.nan? elsif x.is_a?(BigDecimal) then x!=BigDecimal::INFINITY && !x.nan? else true end} #Also, x must be in range [-2**31, 2**31].
170
+
171
+ RDL.type :Float, :to_f, '() -> self'
172
+
173
+ RDL.type :Float, :to_i, '() -> ``sing_or_type(trec, targs, :to_i, "Integer")``'
174
+ RDL.pre(:Float, :to_i) { !self.infinite? && !self.nan?}
175
+
176
+ RDL.type :Float, :to_int, '() -> ``sing_or_type(trec, targs, :to_int, "Integer")``'
177
+ RDL.pre(:Float, :to_int) { !self.infinite? && !self.nan?}
178
+
179
+ RDL.type :Float, :to_r, '() -> ``sing_or_type(trec, targs, :to_r, "Rational")``'
180
+ RDL.pre(:Float, :to_r) { !self.infinite? && !self.nan?}
181
+
182
+ RDL.type :Float, :truncate, '() -> ``sing_or_type(trec, targs, :truncate, "Integer")``'
183
+
184
+ RDL.type :Float, :zero?, '() -> ``sing_or_type(trec, targs, :zero, "%bool")``'
185
+
186
+ RDL.type :Float, :conj, '() -> ``sing_or_type(trec, targs, :conj, "Float")``'
187
+ RDL.type :Float, :conjugate, '() -> ``sing_or_type(trec, targs, :conjugate, "Float")``'
188
+
189
+ RDL.type :Float, :imag, '() -> Integer r {{ r==0 }}' ## TODO
190
+ RDL.type :Float, :imaginary, '() -> Integer r {{ r==0 }}' ## TODO
191
+
192
+ RDL.type :Float, :real, '() -> ``sing_or_type(trec, targs, :real, "Float")``'
193
+
194
+ RDL.type :Float, :real?, '() -> ``sing_or_type(trec, targs, :real?, "%bool")``'
195
+
196
+ RDL.type :Float, :to_c, '() -> Complex r {{ r.imaginary == 0 }}' ## TODO
197
+
198
+ RDL.type :Float, :coerce, '(%numeric) -> [Float, Float]'
199
+ RDL.pre(:Float, :coerce) { |x| if x.is_a?(Complex) then x.imaginary==0 else true end}
200
+
201
+
202
+
203
+ ######### Non-dependent types below #########
204
+
205
+
3
206
  RDL.type :Float, :%, '(Integer x {{ x != 0 }}) -> Float'
4
207
  RDL.type :Float, :%, '(Float x {{ x != 0 }}) -> Float'
5
208
  RDL.type :Float, :%, '(Rational x {{ x != 0 }}) -> Float'
@@ -2,14 +2,386 @@ RDL.nowrap :Hash
2
2
 
3
3
  RDL.type_params :Hash, [:k, :v], :all?
4
4
 
5
- RDL.type :Hash, 'self.[]', '(*u) -> Hash<u, u>' # example: Hash[1,2,3,4]
6
- RDL.type :Hash, 'self.[]', '(Array<[a,b]>) -> Hash<a, b>'
7
- RDL.type :Hash, 'self.[]', '([to_hash: () -> Hash<a, b>]) -> Hash<a, b>'
5
+ def Hash.output_type(trec, targs, meth_name, default1, default2=default1, nil_default: false, use_sing_val: true)
6
+ case trec
7
+ when RDL::Type::FiniteHashType
8
+ if targs.empty? || targs.all? { |t| t.is_a?(RDL::Type::SingletonType) }
9
+ vals = RDL.type_cast((if use_sing_val then targs.map { |t| RDL.type_cast(t, "RDL::Type::SingletonType").val } else targs end), "Array<%any>", force: true)
10
+ res = RDL.type_cast(trec.elts.send(meth_name, *vals), "Object", force: true)
11
+ if nil_default && res.nil?
12
+ if default1 == :promoted_val
13
+ return trec.promote.params[1]
14
+ elsif default1 == :promoted_key
15
+ return trec.promote.params[0]
16
+ else
17
+ return RDL::Globals.parser.scan_str "#T #{default1}"
18
+ end
19
+ end
20
+ to_type(res)
21
+ else
22
+ if default1 == :promoted_val
23
+ x = trec.promote.params[1]
24
+ return x
25
+ elsif default1 == :promoted_key
26
+ return trec.promote.params[0]
27
+ else
28
+ RDL::Globals.parser.scan_str "#T #{default1}"
29
+ end
30
+ end
31
+ else
32
+ RDL::Globals.parser.scan_str "#T #{default2}"
33
+ end
34
+ end
35
+ RDL.type Hash, 'self.output_type', "(RDL::Type::Type, Array<RDL::Type::Type>, Symbol, Symbol or String, ?(Symbol or String), { nil_default: ?%bool, use_sing_val: ?%bool } ) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
36
+
37
+
38
+ def Hash.to_type(t)
39
+ case t
40
+ when RDL::Type::Type
41
+ t
42
+ when Array
43
+ RDL::Type::TupleType.new(*(t.map { |i| to_type(i) }))
44
+ else
45
+ ## symbols, ints, nil, ...
46
+ RDL::Type::SingletonType.new(t)
47
+ end
48
+ end
49
+ RDL.type Hash, 'self.to_type', "(%any) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
50
+
51
+ def Hash.any_or_k(trec)
52
+ case trec
53
+ when RDL::Type::FiniteHashType
54
+ RDL::Globals.types[:top]
55
+ else
56
+ RDL::Globals.parser.scan_str "#T k"
57
+ end
58
+ end
59
+ RDL.type Hash, 'self.any_or_k', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
60
+
61
+ def Hash.any_or_v(trec)
62
+ case trec
63
+ when RDL::Type::FiniteHashType
64
+ RDL::Globals.types[:top]
65
+ else
66
+ RDL::Globals.parser.scan_str "#T v"
67
+ end
68
+ end
69
+ RDL.type Hash, 'self.any_or_v', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
70
+
71
+ def Hash.promoted_or_v(trec)
72
+ case trec
73
+ when RDL::Type::FiniteHashType
74
+ trec.promote.params[1]
75
+ else
76
+ RDL::Globals.parser.scan_str "#T v"
77
+ end
78
+ end
79
+ RDL.type Hash, 'self.promoted_or_v', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
80
+
81
+
82
+ def Hash.weak_promote(val)
83
+ case val
84
+ when RDL::Type::UnionType
85
+ if val.types.all? { |t| t.is_a?(RDL::Type::SingletonType) }
86
+ klass = RDL.type_cast(val.types[0], "RDL::Type::SingletonType", force: true).nominal.klass
87
+ if val.types.all? { |t| RDL.type_cast(t, "RDL::Type::SingletonType", force: true).nominal.klass == klass }
88
+ return RDL::Type::NominalType.new(klass)
89
+ else
90
+ return val
91
+ end
92
+ else
93
+ return val
94
+ end
95
+ else
96
+ val
97
+ end
98
+ end
99
+ RDL.type Hash, 'self.weak_promote', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
100
+
101
+ #RDL.type :Hash, 'self.[]', '(*%any) -> ``hash_create_output_from_list(targs)``'
102
+ RDL.type :Hash, 'self.[]', '(*%any) -> ``hash_create_output(targs)``'
103
+
104
+ def Hash.hash_create_output_from_list(targs)
105
+ raise RDL::Typecheck::StaticTypeError, "Hash[...] expect only 1 argument. Have #{targs}." if targs.size > 1
106
+ raise RDL::Typecheck::StaticTypeError, "The argument has to be an array or tuple" unless (targs[0].is_a?(RDL::Type::GenericType) && targs[0].base.klass == Array)
107
+
108
+ case targs[0].params[0]
109
+ when RDL::Type::GenericType
110
+ return RDL::Globals.parser.scan_str "#T Hash<#{targs[0].params[0].params[0]}, #{targs[0].params[0].params[0]}>"
111
+ when RDL::Type::TupleType
112
+ return RDL::Type::GenericType.new(RDL::Type::NominalType.new(Hash), targs[0].params[0].params[0], targs[0].params[0].params[1])
113
+ end
114
+ end
115
+
116
+ def Hash.hash_create_output(targs)
117
+ return hash_create_output_from_list(targs) if targs.size == 1
118
+
119
+ raise RDL::Typecheck::StaticTypeError, "Hash.[] expects an even number of arguments. Have #{targs}." if targs.size.odd?
120
+ args = RDL.type_cast([], "Array<%any>", force: true)
121
+ i = -1
122
+ args = targs.map { |a| i = i+1 ; if i.even? && a.is_a?(RDL::Type::SingletonType) then RDL.type_cast(a, "RDL::Type::SingletonType", force: true).val else a end }
123
+ RDL::Type::FiniteHashType.new(RDL.type_cast(Hash[*args], "Hash<%any, RDL::Type::Type>", force: true), nil)
124
+ end
125
+ RDL.type Hash, 'self.hash_create_output', "(Array<RDL::Type::Type>) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
126
+
127
+ RDL.type :Hash, :[], '(``any_or_k(trec)``) -> ``output_type(trec, targs, :[], :promoted_val, "v", nil_default: true)``', effect: [:+, :+]
128
+
129
+ RDL.type :Hash, :[]=, '(``any_or_k(trec)``, ``any_or_v(trec)``) -> ``assign_output(trec, targs)``'
130
+
131
+
132
+ def Hash.assign_output(trec, targs)
133
+ case trec
134
+ when RDL::Type::FiniteHashType
135
+ case targs[0]
136
+ when RDL::Type::SingletonType ### TODO: adjust for strings
137
+ argval = RDL.type_cast(targs[0], "RDL::Type::SingletonType", force: true).val
138
+ trec.elts[argval] = RDL::Type::UnionType.new(trec.elts[argval], targs[1]).canonical
139
+ trec.elts[argval] = weak_promote(trec.elts[argval]) if RDL::Config.instance.weak_update_promote
140
+ raise RDL::Typecheck::StaticTypeError, "Failed to mutate hash: new hash does not match prior type constraints." unless trec.check_bounds(true)
141
+ return targs[1]
142
+ else
143
+ raise "Unable to promote tuple #{trec} to Hash." unless trec.promote!(targs[0], targs[1])
144
+ return targs[1]
145
+ end
146
+ else
147
+ RDL::Globals.parser.scan_str "#T v"
148
+ end
149
+ end
150
+ RDL.type Hash, 'self.assign_output', "(RDL::Type::Type, Array<RDL::Type::Type>) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:~, :+]
151
+
152
+ RDL.type :Hash, :store, '(``any_or_k(trec)``, ``any_or_v(trec)``) -> ``assign_output(trec, targs)``'
153
+ RDL.type :Hash, :assoc, '(``any_or_k(trec)``) -> ``RDL::Type::TupleType.new(targs[0], output_type(trec, targs, :[], :promoted_val, "v", nil_default: true))``'
154
+ RDL.type :Hash, :clear, '() -> self'
155
+ RDL.type :Hash, :compare_by_identity, '() -> self'
156
+ RDL.type :Hash, :compare_by_identity?, '() -> %bool'
157
+ RDL.type :Hash, :default, '() -> ``promoted_or_v(trec)``'
158
+ RDL.type :Hash, :default, '(``any_or_k(trec)``) -> ``promoted_or_v(trec)``'
159
+ RDL.type :Hash, :default=, '(``promoted_or_v(trec)``) -> ``promoted_or_v(trec)``'
160
+
161
+ RDL.type :Hash, :delete, '(``any_or_k(trec)``) -> ``delete_output(trec, targs, false)``'
162
+ RDL.type :Hash, :delete, '(``any_or_k(trec)``) { (``any_or_k(trec)``) -> u } -> ``delete_output(trec, targs, true)``'
163
+
164
+ def Hash.delete_output(trec, targs, block)
165
+ case trec
166
+ when RDL::Type::FiniteHashType
167
+ case targs[0]
168
+ when RDL::Type::SingletonType
169
+ argval = RDL.type_cast(targs[0], "RDL::Type::SingletonType", force: true).val
170
+ if trec.elts.include?(argval)
171
+ trec.elts[argval]
172
+ else
173
+ trec.promote.params[1]
174
+ end
175
+ else
176
+ if block
177
+ RDL::Type::UnionType.new(trec.promote.params[1], RDL::Globals.parser.scan_str("#T u"))
178
+ else
179
+ trec.promote.params[1]
180
+ end
181
+ end
182
+ else
183
+ t = (if block then "u or v" else "v" end)
184
+ RDL::Globals.parser.scan_str "#T #{t}"
185
+ end
186
+ end
187
+ RDL.type Hash, 'self.delete_output', "(RDL::Type::Type, Array<RDL::Type::Type>, %bool) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
188
+
189
+ RDL.type :Hash, :delete_if, '() { (``any_or_k(trec)``, ``any_or_v(trec)``) -> %any } -> self'
190
+ RDL.type :Hash, :delete_if, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), RDL::Type::TupleType.new(any_or_k(trec), any_or_v(trec)))``' ## I had made a mistake here, type checker caught it.
191
+ RDL.type :Hash, :each, '() { (``any_or_k(trec)``, ``any_or_v(trec)``) -> %any } -> self'
192
+ RDL.type :Hash, :each, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), RDL::Type::TupleType.new(any_or_k(trec), any_or_v(trec)))``' ## I had made a mistake here, type checker caught it.
193
+ RDL.type :Hash, :each_pair, '() { (``any_or_k(trec)``, ``any_or_v(trec)``) -> %any } -> self'
194
+ RDL.type :Hash, :each_pair, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), RDL::Type::TupleType.new(any_or_k(trec), any_or_v(trec)))``' ## I had made a mistake here, type checker caught it.
195
+ RDL.type :Hash, :each_key, '() { (``any_or_k(trec)``) -> %any } -> self'
196
+ RDL.type :Hash, :each_key, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), any_or_k(trec))``'
197
+ RDL.type :Hash, :each_value, '() { (``any_or_v(trec)``) -> %any } -> self'
198
+ RDL.type :Hash, :each_value, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), any_or_v(trec))``'
199
+ RDL.type :Hash, :empty?, '() -> ``output_type(trec, targs, :empty?, "%bool")``'
200
+ RDL.type :Hash, :fetch, '(``any_or_k(trec)``) -> ``output_type(trec, targs, :fetch, :promoted_val, "v", nil_default: true)``'
201
+ RDL.type :Hash, :fetch, '(``any_or_k(trec)``, u) -> ``RDL::Type::UnionType.new(RDL::Globals.parser.scan_str("u"), output_type(trec, targs, :fetch, :promoted_val, "v", nil_default: true))``'
202
+ RDL.type :Hash, :fetch, '(``any_or_k(trec)``) { (``any_or_k(trec)``) -> u } -> ``RDL::Type::UnionType.new(RDL::Globals.parser.scan_str("u"), output_type(trec, targs, :fetch, :promoted_val, "v", nil_default: true))``'
203
+ RDL.type :Hash, :member?, '(%any) -> ``output_type(trec, targs, :member?, "%bool")``'
204
+ RDL.type :Hash, :has_key?, '(%any) -> ``output_type(trec, targs, :has_key?, "%bool")``', effect: [:+, :+]
205
+ RDL.type :Hash, :key?, '(%any) -> ``output_type(trec, targs, :key?, "%bool")``'
206
+ RDL.type :Hash, :has_value?, '(%any) -> ``output_type(trec, targs, :has_value?, "%bool")``'
207
+ RDL.type :Hash, :value?, '(%any) -> ``output_type(trec, targs, :value?, "%bool")``'
208
+ RDL.type :Hash, :to_s, '() -> String'
209
+ RDL.type :Hash, :inspect, '() -> String'
210
+ RDL.type :Hash, :invert, '() -> ``invert_output(trec)``'
211
+
212
+
213
+ def Hash.invert_output(trec)
214
+ case trec
215
+ when RDL::Type::FiniteHashType
216
+ hash = trec.elts.invert
217
+ hash = Hash[hash.map { |k, v| if !RDL.type_cast(v, "Object", force: true).is_a?(RDL::Type::Type) then [k, RDL::Type::SingletonType.new(v)] else [k, v] end }]
218
+ RDL::Type::FiniteHashType.new(RDL.type_cast(hash, "Hash<%any, RDL::Type::Type>", force: true), nil)
219
+ else
220
+ RDL::Globals.parser.scan_str "#T Hash<v, k>"
221
+ end
222
+ end
223
+ RDL.type Hash, 'self.invert_output', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
224
+
225
+ RDL.type :Hash, :keep_if, '() { (``any_or_k(trec)``,``any_or_v(trec)``) -> %bool } -> self'
226
+ RDL.type :Hash, :keep_if, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), RDL::Type::TupleType.new(any_or_k(trec), any_or_v(trec)))``' ## I had made a mistake here, type checker caught it.
227
+ RDL.type :Hash, :key, '(%any) -> ``output_type(trec, targs, :key, :promoted_key, "k", nil_default: true, use_sing_val: false)``'
228
+ RDL.type :Hash, :keys, '() -> ``output_type(trec, targs, :keys, "Array<k>")``'
229
+ RDL.type :Hash, :length, '() -> ``output_type(trec, targs, :length, "Integer")``'
230
+ RDL.type :Hash, :size, '() -> ``output_type(trec, targs, :size, "Integer")``'
231
+ RDL.type :Hash, :merge, '(``merge_input(targs)``) -> ``merge_output(trec, targs)``'
232
+ RDL.type :Hash, :merge!, '(``merge_input(targs, true)``) -> ``merge_output(trec, targs, true)``'
233
+
234
+
235
+ def Hash.merge_input(targs, mutate=false)
236
+ case targs[0]
237
+ when RDL::Type::FiniteHashType
238
+ return targs[0]
239
+ when RDL::Type::GenericType
240
+ if mutate
241
+ return RDL::Globals.parser.scan_str "#T Hash<k, v>"
242
+ else
243
+ return RDL::Globals.parser.scan_str "#T Hash<a, b>"
244
+ end
245
+ else
246
+ RDL::Globals.types[:hash]
247
+ end
248
+ end
249
+ RDL.type Hash, 'self.merge_input', "(Array<RDL::Type::Type>, ?%bool) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
250
+
251
+
252
+ def Hash.merge_output(trec, targs, mutate=false)
253
+ case trec
254
+ when RDL::Type::NominalType
255
+ return RDL::Globals.types[:hash]
256
+ when RDL::Type::GenericType
257
+ case targs[0]
258
+ when RDL::Type::FiniteHashType
259
+ promoted = RDL.type_cast(targs[0], "RDL::Type::FiniteHashType", force: true).promote
260
+ key_union = RDL::Type::UnionType.new(promoted.params[0], trec.params[0]).canonical
261
+ value_union = RDL::Type::UnionType.new(promoted.params[1], trec.params[1]).canonical
262
+ if mutate
263
+ raise "Call to `merge!` would change type of Hash." unless (key_union == trec.params[0]) && (value_union == trec.params[1])
264
+ return trec
265
+ else
266
+ return RDL::Type::GenericType.new(trec.base, key_union, value_union)
267
+ end
268
+ when RDL::Type::GenericType
269
+ ret = (if mutate then "Hash<k, v>" else "Hash<a or k, b or v>" end)
270
+ return RDL::Globals.parser.scan_str "#T #{ret}"
271
+ else
272
+ ## targs[0] should just be hash here
273
+ return RDL::Globals.types[:hash]
274
+ end
275
+ when RDL::Type::FiniteHashType
276
+ case targs[0]
277
+ when RDL::Type::FiniteHashType
278
+ arg = RDL.type_cast(targs[0], "RDL::Type::FiniteHashType", force: true)
279
+ if mutate
280
+ if arg.elts.any? { |k, v| !RDL.type_cast(k, "Object", force: true).is_a?(Symbol) }
281
+ arg_key = arg.promote.params[0]
282
+ arg_val = arg.promote.params[1]
283
+ raise "Unable to promote tuple #{trec} to Hash." unless trec.promote!(arg_key, arg_val)
284
+ return trec
285
+ end
286
+ trec.elts = RDL.type_cast(Hash[trec.elts.map { |k, v| if arg.elts.has_key?(k) then [k, RDL::Type::UnionType.new(arg.elts[k], v).canonical] else [k, v] end } ].merge(arg.elts), "Hash<%any, RDL::Type::Type>", force: true)
287
+ raise RDL::Typecheck::StaticTypeError, "Failed to mutate hash: new hash does not match prior type constraints." unless trec.check_bounds(true)
288
+ return trec
289
+ else
290
+ return RDL::Type::FiniteHashType.new(trec.elts.merge(arg.elts), nil)
291
+ end
292
+ when RDL::Type::GenericType
293
+ arg0 = RDL.type_cast(targs[0], "RDL::Type::GenericType", force: true)
294
+ promoted = trec.promote
295
+ key_union = RDL::Type::UnionType.new(promoted.params[0], arg0.params[0]).canonical
296
+ value_union = RDL::Type::UnionType.new(promoted.params[1], arg0.params[1]).canonical
297
+ if mutate
298
+ raise "Unable to promote tuple #{trec} to Hash." unless trec.promote!(arg0.params[0], arg0.params[1])
299
+ return trec
300
+ else
301
+ return RDL::Type::GenericType.new(arg0.base, key_union, value_union)
302
+ end
303
+ else
304
+ ## targs[0] should just be Hash here
305
+ return RDL::Globals.types[:hash]
306
+ end
307
+ end
308
+
309
+ end
310
+ RDL.type Hash, 'self.merge_output', "(RDL::Type::Type, Array<RDL::Type::Type>, ?%bool) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:~, :+]
311
+
312
+ RDL.type :Hash, :merge, '(Hash<a,b>) { (k,v,b) -> v or b } -> Hash<a or k, b or v>'
313
+ RDL.type :Hash, :rassoc, '(``any_or_v(trec)``) -> ``RDL::Type::TupleType.new(output_type(trec, targs, :key, :promoted_key, "k", nil_default: true, use_sing_val: false),targs[0])``'
314
+ RDL.type :Hash, :rehash, '() -> self'
315
+ RDL.type :Hash, :reject, '() -> ``RDL::Type::GenericType.new(RDL::Type::NominalType.new(Enumerator), any_or_k(trec), any_or_v(trec))``'
316
+ RDL.type :Hash, :reject, '() {(``any_or_k(trec)``,``any_or_v(trec)``) -> %bool} -> self'
317
+ RDL.type :Hash, :reject!, '() {(``any_or_k(trec)``,``any_or_v(trec)``) -> %bool} -> self'
318
+ RDL.type :Hash, :select, '() {(``any_or_k(trec)``,``any_or_v(trec)``) -> %bool} -> self'
319
+ RDL.type :Hash, :select!, '() {(``any_or_k(trec)``,``any_or_v(trec)``) -> %bool} -> self'
320
+ RDL.type :Hash, :shift, '() -> ``shift_output(trec)``'
321
+
322
+
323
+ def Hash.shift_output(trec)
324
+ case trec
325
+ when RDL::Type::FiniteHashType
326
+ promoted = trec.promote
327
+ RDL::Type::TupleType.new(*promoted.params) ## Type error found by type checker here.
328
+ else
329
+ RDL::Globals.parser.scan_str "#T [k, v]"
330
+ end
331
+ end
332
+ RDL.type Hash, 'self.shift_output', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:+, :+]
333
+
334
+ RDL.type :Hash, :to_a, '() -> ``output_type(trec, targs, :to_a, "Array<[k, v]>")``'
335
+ RDL.type :Hash, :to_hash, '() -> self'
336
+ RDL.type :Hash, :values, '() -> ``output_type(trec, targs, :values, "Array<v>")``'
337
+ RDL.type :Hash, :values_at, '(``values_at_input(trec)``) -> ``values_at_output(trec, targs)``'
338
+
339
+
340
+ def Hash.values_at_input(trec)
341
+ case trec
342
+ when RDL::Type::FiniteHashType
343
+ RDL::Type::VarargType.new(RDL::Globals.types[:top])
344
+ else
345
+ RDL::Type::VarargType.new(RDL::Type::VarType.new("k"))
346
+ end
347
+ end
348
+ RDL.type Hash, 'self.values_at_input', "(RDL::Type::Type) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:~, :+]
349
+
350
+
351
+ def Hash.values_at_output(trec, targs)
352
+ case trec
353
+ when RDL::Type::FiniteHashType
354
+ if targs.all? { |t| t.is_a? RDL::Type::SingletonType }
355
+ res = trec.elts.values_at(*targs.map { |t| RDL.type_cast(t, "RDL::Type::SingletonType<%any>", force: true).val })
356
+ if res.all? { |t| !t.nil? }
357
+ to_type(res)
358
+ else
359
+ RDL::Type::GenericType.new(RDL::Type::NominalType.new(Array), trec.promote.params[1])
360
+ end
361
+ else
362
+ RDL::Type::GenericType.new(RDL::Type::NominalType.new(Array), trec.promote.params[1])
363
+ end
364
+ else
365
+ RDL::Globals.parser.scan_str "#T Array<v>"
366
+ end
367
+ end
368
+ RDL.type Hash, 'self.values_at_output', "(RDL::Type::Type, Array<RDL::Type::Type>) -> RDL::Type::Type", typecheck: :type_code, wrap: false, effect: [:~, :+]
369
+
370
+
371
+
372
+
373
+
374
+ ######### Non-dependent types below #########
375
+
376
+ RDL.type :Hash, 'self.[]', '(*u) -> Hash<u, u>', effect: [:+, :+] # example: Hash[1,2,3,4]
377
+ RDL.type :Hash, 'self.[]', '(Array<[a,b]>) -> Hash<a, b>', effect: [:+, :+]
378
+ RDL.type :Hash, 'self.[]', '([to_hash: () -> Hash<a, b>]) -> Hash<a, b>', effect: [:+, :+]
8
379
 
9
380
  RDL.type :Hash, :[], '(k) -> v'
10
- RDL.type :Hash, :[]=, '(k, v) -> v'
381
+ RDL.type :Hash, :[]=, '(k, v) -> v', effect: [:-, :+]
11
382
  RDL.type :Hash, :store, '(k,v) -> v'
12
383
 
384
+ RDL.type :Hash, :any?, "() { (k, v) -> %any } -> %bool", effect: [:blockdep, :blockdep]
13
385
  # RDL.type :Hash, :assoc, '(k) -> [k, v]' # TODO
14
386
  RDL.type :Hash, :assoc, '(k) -> Array<k or v>'
15
387
  RDL.type :Hash, :clear, '() -> Hash<k,v>'
@@ -27,41 +399,44 @@ RDL.type :Hash, :delete, '(k) -> v'
27
399
  RDL.type :Hash, :delete, '(k) { (k) -> u } -> u or v'
28
400
  RDL.type :Hash, :delete_if, '() { (k,v) -> %bool } -> Hash<k,v>'
29
401
  RDL.type :Hash, :delete_if, '() -> Enumerator<[k, v]>'
30
- RDL.type :Hash, :each, '() { (k,v) -> %any } -> Hash<k,v>'
31
- RDL.type :Hash, :each, '() -> Enumerator<[k, v]>'
402
+ RDL.type :Hash, :each, '() { (k,v) -> %any } -> Hash<k,v>', effect: [:blockdep, :blockdep]
403
+ RDL.type :Hash, :each, '() -> Enumerator<[k, v]>', effect: [:blockdep, :blockdep]
32
404
  RDL.type :Hash, :each_pair, '() { (k,v) -> %any } -> Hash<k,v>'
33
405
  RDL.type :Hash, :each_pair, '() -> Enumerator<[k, v]>'
34
- RDL.type :Hash, :each_key, '() { (k) -> %any } -> Hash<k,v>'
35
- RDL.type :Hash, :each_key, '() -> Enumerator<[k, v]>'
406
+ RDL.type :Hash, :each_key, '() { (k) -> %any } -> Hash<k,v>', effect: [:blockdep, :blockdep]
407
+ RDL.type :Hash, :each_key, '() -> Enumerator<[k, v]>', effect: [:blockdep, :blockdep]
36
408
  RDL.type :Hash, :each_value, '() { (v) -> %any } -> Hash<k,v>'
37
409
  RDL.type :Hash, :each_value, '() -> Enumerator<[k, v]>'
38
410
  RDL.type :Hash, :empty?, '() -> %bool'
411
+ RDL.type :Hash, :except, '(%any) -> self', effect: [:+, :+]
39
412
  RDL.type :Hash, :fetch, '(k) -> v'
40
413
  RDL.type :Hash, :fetch, '(k,u) -> u or v'
41
414
  RDL.type :Hash, :fetch, '(k) { (k) -> u } -> u or v'
415
+ RDL.type :Hash, :map, "() { (k, v) -> x } -> Array<x>", effect: [:+, :blockdep]
42
416
  RDL.type :Hash, :member?, '(t) -> %bool'
43
417
  RDL.type :Hash, :has_key?, '(t) -> %bool'
44
418
  RDL.type :Hash, :key?, '(t) -> %bool'
45
419
  RDL.type :Hash, :has_value?, '(t) -> %bool'
46
420
  RDL.type :Hash, :value?, '(t) -> %bool'
47
421
  RDL.type :Hash, :to_s, '() -> String'
422
+ RDL.type :Hash, :include?, '(%any) -> %bool', effect: [:+, :+]
48
423
  RDL.type :Hash, :inspect, '() -> String'
49
- RDL.type :Hash, :invert, '() -> Hash<v,k>'
424
+ RDL.type :Hash, :invert, '() -> Hash<v,k>', effect: [:+, :+]
50
425
  RDL.type :Hash, :keep_if, '() { (k,v) -> %bool } -> Hash<k,v>'
51
426
  RDL.type :Hash, :keep_if, '() -> Enumerator<[k, v]>'
52
427
  RDL.type :Hash, :key, '(t) -> k'
53
- RDL.type :Hash, :keys, '() -> Array<k>'
428
+ RDL.type :Hash, :keys, '() -> Array<k>', effect: [:+, :+]
54
429
  RDL.type :Hash, :length, '() -> Integer'
55
- RDL.type :Hash, :size, '() -> Integer'
56
- RDL.type :Hash, :merge, '(Hash<a,b>) -> Hash<a or k, b or v>'
57
- RDL.type :Hash, :merge, '(Hash<a,b>) { (k,v,b) -> v or b } -> Hash<a or k, b or v>'
430
+ RDL.type :Hash, :size, '() -> Integer', effect: [:+, :+]
431
+ RDL.type :Hash, :merge, '(Hash<a,b>) -> Hash<a or k, b or v>', effect: [:+, :+]
432
+ RDL.type :Hash, :merge, '(Hash<a,b>) { (k,v,b) -> v or b } -> Hash<a or k, b or v>', effect: [:+, :+]
58
433
  # RDL.type :Hash, :rassoc, '(k) -> Tuple<k,v>'
59
434
  RDL.type :Hash, :rassoc, '(k) -> Array<k or v>'
60
435
  RDL.type :Hash, :rehash, '() -> Hash<k,v>'
61
436
  RDL.type :Hash, :reject, '() -> Enumerator<[k, v]>'
62
437
  RDL.type :Hash, :reject, '() {(k,v) -> %bool} -> Hash<k,v>'
63
438
  RDL.type :Hash, :reject!, '() {(k,v) -> %bool} -> Hash<k,v>'
64
- RDL.type :Hash, :select, '() {(k,v) -> %bool} -> Hash<k,v>'
439
+ RDL.type :Hash, :select, '() {(k,v) -> %bool} -> Hash<k,v>', effect: [:+, :blockdep]
65
440
  RDL.type :Hash, :select!, '() {(k,v) -> %bool} -> Hash<k,v>'
66
441
  # RDL.type :Hash, :shift, '() -> Tuple<k,v>'
67
442
  RDL.type :Hash, :shift, '() -> Array<k or v>'
@@ -69,4 +444,4 @@ RDL.type :Hash, :shift, '() -> Array<k or v>'
69
444
  RDL.type :Hash, :to_a, '() -> Array<Array<k or v>>'
70
445
  RDL.type :Hash, :to_hash, '() -> Hash<k,v>'
71
446
  RDL.type :Hash, :values, '() -> Array<v>'
72
- RDL.type :Hash, :values_at, '(*k) -> Array<v>'
447
+ RDL.type :Hash, :values_at, '(*k) -> Array<v>', effect: [:+, :+]