typed.rb 0.0.18 → 0.0.19
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.
- checksums.yaml +4 -4
- data/lib/typed/language.rb +1 -0
- data/lib/typed/prelude_existential_registry.bin +0 -0
- data/lib/typed/prelude_generic_registry.bin +0 -0
- data/lib/typed/prelude_registry.bin +0 -0
- data/lib/typed/runtime/type_registry.rb +20 -9
- data/lib/typed/types/polymorphism/generic_comparisons.rb +17 -6
- data/lib/typed/types/polymorphism/generic_object.rb +13 -0
- data/lib/typed/types/polymorphism/unification.rb +10 -3
- data/lib/typed/types/singleton_object.rb +92 -0
- data/lib/typed/types/ty_generic_existential_type.rb +49 -0
- data/lib/typed/types/ty_generic_object.rb +0 -14
- data/lib/typed/types/ty_generic_singleton_object.rb +2 -122
- data/lib/typed/types/ty_object.rb +2 -1
- data/lib/typed/version.rb +1 -1
- data/spec/lib/typing/tm_module_spec.rb +103 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 275c43f2dc819f16b312b04476aeb6e2348b901c
|
4
|
+
data.tar.gz: a3bee9cfa379440d26e4ed53d65bda969deeaa8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d56e1eb679fc7443cb0f85da729c1680236cea4f6bf25e6eed316cb54ed5a1b5783cebc121ce5b34843060a1f97570f6f9f82eb42e9ab8c2712591fc6d6ae3d6
|
7
|
+
data.tar.gz: d3de0f7e334161c2e99e700efe52d0492e57b464d612413c5c86f069114e9393c94d2b8356270a509de8efb69471df627d7df879ce71f1eef9f6810fb19cdc25
|
data/lib/typed/language.rb
CHANGED
Binary file
|
Binary file
|
Binary file
|
@@ -29,21 +29,32 @@ class BasicObject
|
|
29
29
|
|
30
30
|
ts '.register_generic_type_information / Hash[Object][Object] -> Hash[Object][Object] -> unit'
|
31
31
|
def register_generic_type_information(generic_type_information, generic_super_types_information)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
if generic_type_information.is_a?(String)
|
33
|
+
# concrete type with a generic super type
|
34
|
+
generic_type_information = {
|
35
|
+
:type => generic_type_information,
|
36
|
+
:parameters => [],
|
37
|
+
:kind => :generic_type
|
38
|
+
}
|
39
|
+
end
|
40
|
+
generic_type_information[:super_type] = generic_super_types_information
|
41
|
+
if generic_types_parser_registry[generic_type_information[:type]]
|
42
|
+
super_type = (generic_types_parser_registry[generic_type_information[:type]][:super_type] || [])
|
43
|
+
generic_types_parser_registry[generic_type_information[:type]][:super_type]= super_type.concat(generic_type_information[:super_type])
|
44
|
+
else
|
45
|
+
generic_types_parser_registry[generic_type_information[:type]] = generic_type_information
|
40
46
|
end
|
41
47
|
end
|
42
48
|
|
43
49
|
def find_existential_type(type)
|
44
50
|
existential_type = existential_types_registry[type]
|
45
51
|
if existential_type.nil?
|
46
|
-
|
52
|
+
generic_existential_type = generic_types_registry[type]
|
53
|
+
existential_type = if generic_existential_type
|
54
|
+
TypedRb::Types::TyGenericExistentialType.new(type, generic_existential_type.type_vars)
|
55
|
+
else
|
56
|
+
TypedRb::Types::TyExistentialType.new(type)
|
57
|
+
end
|
47
58
|
@existential_types_registry[type] = existential_type
|
48
59
|
end
|
49
60
|
existential_type
|
@@ -31,8 +31,8 @@ module TypedRb
|
|
31
31
|
def compatible?(other_type, relation = :lt)
|
32
32
|
if other_type.is_a?(TyDynamic) || other_type.is_a?(TyError)
|
33
33
|
true
|
34
|
-
elsif other_type.is_a?(TyGenericObject) || other_type.is_a?(TyGenericSingletonObject)
|
35
|
-
if check_generic_type_relation(other_type
|
34
|
+
elsif other_type.is_a?(TyGenericObject) || other_type.is_a?(TyGenericSingletonObject) || other_type.is_a?(TyGenericExistentialType)
|
35
|
+
if check_generic_type_relation(other_type, relation)
|
36
36
|
type_vars.each_with_index do |type_var, i|
|
37
37
|
other_type_var = other_type.type_vars[i]
|
38
38
|
compatible = if incompatible_free_type_vars?(type_var, other_type_var)
|
@@ -49,7 +49,7 @@ module TypedRb
|
|
49
49
|
false
|
50
50
|
end
|
51
51
|
elsif other_type.is_a?(TyObject)
|
52
|
-
check_generic_type_relation(other_type
|
52
|
+
check_generic_type_relation(other_type, relation)
|
53
53
|
else
|
54
54
|
other_type.compatible?(self, relation == :lt ? :gt : :lt)
|
55
55
|
end
|
@@ -79,14 +79,25 @@ module TypedRb
|
|
79
79
|
TypingContext.bound_generic_type_var?(right_var))
|
80
80
|
end
|
81
81
|
|
82
|
-
def check_generic_type_relation(
|
82
|
+
def check_generic_type_relation(other_type, relation)
|
83
83
|
if relation == :gt
|
84
|
-
|
84
|
+
to_ty_object(self) >= to_ty_object(other_type)
|
85
85
|
else
|
86
|
-
|
86
|
+
to_ty_object(self) <= to_ty_object(other_type)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
def to_ty_object(type)
|
91
|
+
ty_object = TyObject.new(type.ruby_type)
|
92
|
+
if type.is_a?(Types::TySingletonObject) ||
|
93
|
+
type.is_a?(Types::TyGenericSingletonObject) ||
|
94
|
+
type.is_a?(Types::TyExistentialType) ||
|
95
|
+
type.is_a?(Types::TyGenericExistentialType)
|
96
|
+
ty_object.hierarchy = type.ruby_type.meta_ancestors
|
97
|
+
end
|
98
|
+
ty_object
|
99
|
+
end
|
100
|
+
|
90
101
|
def check_type_var_inclusion(type_var, other_type_var, relation)
|
91
102
|
if (!type_var.wildcard? && !type_var.fully_bound?) ||
|
92
103
|
(!other_type_var.wildcard? && !other_type_var.fully_bound?)
|
@@ -107,6 +107,19 @@ module TypedRb
|
|
107
107
|
i && type_vars[i]
|
108
108
|
end
|
109
109
|
|
110
|
+
def to_s
|
111
|
+
base_string = super
|
112
|
+
var_types_strings = @type_vars.map do |var_type|
|
113
|
+
if var_type.respond_to?(:bound) && var_type.bound
|
114
|
+
# "[#{var_type.variable} <= #{var_type.bound}]"
|
115
|
+
"[#{var_type.bound}]"
|
116
|
+
else
|
117
|
+
"[#{var_type}]"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
"#{base_string}#{var_types_strings.join}"
|
121
|
+
end
|
122
|
+
|
110
123
|
end
|
111
124
|
end
|
112
125
|
end
|
@@ -163,10 +163,17 @@ module TypedRb
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def [](var)
|
166
|
-
if var.is_a?(TypeVariable)
|
167
|
-
|
166
|
+
found = if var.is_a?(TypeVariable)
|
167
|
+
groups[var]
|
168
|
+
else
|
169
|
+
var
|
170
|
+
end
|
171
|
+
if found.nil?
|
172
|
+
var_key = groups.keys.detect{ |key| key.name == var.name }
|
173
|
+
found = groups[var_key]
|
174
|
+
found || raise(TypedRb::Types::Polymorphism::UnificationError.new("Unification error, cannot find type variable #{var}"))
|
168
175
|
else
|
169
|
-
|
176
|
+
found
|
170
177
|
end
|
171
178
|
end
|
172
179
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module TypedRb
|
2
|
+
module Types
|
3
|
+
module SingletonObject
|
4
|
+
def apply_type_arguments(fresh_vars_generic_type, actual_arguments)
|
5
|
+
fresh_vars_generic_type.type_vars.each_with_index do |type_var, i|
|
6
|
+
if type_var.bound.is_a?(TyGenericSingletonObject)
|
7
|
+
type_var.bind(apply_type_arguments_recursively(type_var.bound, actual_arguments))
|
8
|
+
else
|
9
|
+
apply_type_argument(actual_arguments[i], type_var)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def clone_with_substitutions(substitutions)
|
15
|
+
materialized_type_vars = type_vars(recursive: false).map do |type_var|
|
16
|
+
if type_var.is_a?(Polymorphism::TypeVariable) && type_var.bound_to_generic?
|
17
|
+
new_type_var = Polymorphism::TypeVariable.new(type_var.variable, node: type_var.node, gen_name: false)
|
18
|
+
new_type_var.to_wildcard! if type_var.wildcard?
|
19
|
+
bound = type_var.bound.clone_with_substitutions(substitutions)
|
20
|
+
new_type_var.bind(bound)
|
21
|
+
new_type_var.upper_bound = bound if type_var.upper_bound
|
22
|
+
new_type_var.lower_bound = bound if type_var.lower_bound
|
23
|
+
new_type_var
|
24
|
+
elsif type_var.is_a?(Polymorphism::TypeVariable)
|
25
|
+
substitutions[type_var.variable] || type_var.clone
|
26
|
+
elsif type_var.is_a?(TyGenericSingletonObject) || type_var.is_a?(TyGenericObject)
|
27
|
+
type_var.clone_with_substitutions(substitutions)
|
28
|
+
else
|
29
|
+
type_var
|
30
|
+
end
|
31
|
+
end
|
32
|
+
self.class.new(ruby_type, materialized_type_vars, node)
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply_type_argument(argument, type_var)
|
36
|
+
if argument.is_a?(Polymorphism::TypeVariable)
|
37
|
+
if argument.wildcard?
|
38
|
+
# Wild card type
|
39
|
+
# If the type is T =:= E < Type1 or E > Type1 only that constraint should be added
|
40
|
+
{ :lt => :upper_bound, :gt => :lower_bound }.each do |relation, bound|
|
41
|
+
if argument.send(bound)
|
42
|
+
value = if argument.send(bound).is_a?(TyGenericSingletonObject)
|
43
|
+
argument.send(bound).clone # .self_materialize
|
44
|
+
else
|
45
|
+
argument.send(bound)
|
46
|
+
end
|
47
|
+
type_var.compatible?(value, relation)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
type_var.to_wildcard! # WILD CARD
|
51
|
+
elsif argument.bound # var type with a particular value
|
52
|
+
argument = argument.bound
|
53
|
+
if argument.is_a?(TyGenericSingletonObject)
|
54
|
+
argument = argument.clone # .self_materialize
|
55
|
+
end
|
56
|
+
# This is only for matches T =:= Type1 -> T < Type1, T > Type1
|
57
|
+
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :lt)
|
58
|
+
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :gt)
|
59
|
+
else
|
60
|
+
# Type variable
|
61
|
+
type_var.bound = argument
|
62
|
+
type_var.lower_bound = argument
|
63
|
+
type_var.upper_bound = argument
|
64
|
+
end
|
65
|
+
else
|
66
|
+
if argument.is_a?(TyGenericSingletonObject)
|
67
|
+
argument = argument.clone # .self_materialize
|
68
|
+
end
|
69
|
+
# This is only for matches T =:= Type1 -> T < Type1, T > Type1
|
70
|
+
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :lt)
|
71
|
+
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :gt)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def apply_type_arguments_recursively(generic_type_bound, actual_arguments)
|
76
|
+
arg_names = actual_arguments_hash(actual_arguments)
|
77
|
+
recursive_actual_arguments = generic_type_bound.type_vars.map do |type_var|
|
78
|
+
arg_names[type_var.variable] || fail("Unbound type variable #{type_var.variable} for recursive generic type #{generic_type_bound}")
|
79
|
+
end
|
80
|
+
generic_type_bound.materialize(recursive_actual_arguments)
|
81
|
+
end
|
82
|
+
|
83
|
+
def actual_arguments_hash(actual_arguments)
|
84
|
+
acc = {}
|
85
|
+
type_vars.each_with_index do |type_var, i|
|
86
|
+
acc[type_var.variable] = actual_arguments[i]
|
87
|
+
end
|
88
|
+
acc
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'ty_object'
|
2
|
+
require_relative 'singleton_object'
|
3
|
+
|
4
|
+
module TypedRb
|
5
|
+
module Types
|
6
|
+
class TyGenericExistentialType < TyExistentialType
|
7
|
+
include Polymorphism::GenericObject
|
8
|
+
include Polymorphism::GenericComparisons
|
9
|
+
include Polymorphism::GenericVariables
|
10
|
+
include SingletonObject
|
11
|
+
|
12
|
+
attr_accessor :local_typing_context, :self_variable
|
13
|
+
|
14
|
+
def initialize(ruby_type, type_vars, node = nil)
|
15
|
+
super(ruby_type, node)
|
16
|
+
@type_vars = type_vars
|
17
|
+
end
|
18
|
+
|
19
|
+
def check_inclusion(self_type)
|
20
|
+
if self_type.generic?
|
21
|
+
if ancestor_of_super_type?(self_type.super_type, ruby_type)
|
22
|
+
super_type = ancestor_of_super_type?(self_type.super_type, ruby_type)
|
23
|
+
materialize(self_type, super_type.type_vars)
|
24
|
+
else
|
25
|
+
materialize(self_type, self_type.type_vars)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
# not generic extending a generic type
|
29
|
+
raise StandardError, "Extending generic module type #{ruby_type} in #{self_type} without matching super annotation"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def materialize(self_type, actual_arguments)
|
34
|
+
TypedRb.log binding, :debug, "Materialising generic existential type '#{self}' with args [#{actual_arguments.map(&:to_s).join(',')}]"
|
35
|
+
compute_minimal_typing_context if @local_typing_context.nil?
|
36
|
+
|
37
|
+
applied_typing_context, substitutions = @local_typing_context.clone(:module_self)
|
38
|
+
fresh_vars_generic_type = clone_with_substitutions(substitutions)
|
39
|
+
TypingContext.with_context(applied_typing_context) do
|
40
|
+
apply_type_arguments(fresh_vars_generic_type, actual_arguments)
|
41
|
+
context_self_type = Types::TypingContext.type_variable_for(ruby_type, :module_self, [ruby_type])
|
42
|
+
context_self_type.compatible?(self_type, :lt)
|
43
|
+
end
|
44
|
+
Polymorphism::Unification.new(applied_typing_context.all_constraints).run(false)
|
45
|
+
applied_typing_context.unlink # these constraints have already been satisfied
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -37,19 +37,6 @@ module TypedRb
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def to_s
|
41
|
-
base_string = super
|
42
|
-
var_types_strings = @type_vars.map do |var_type|
|
43
|
-
if var_type.respond_to?(:bound) && var_type.bound
|
44
|
-
# "[#{var_type.variable} <= #{var_type.bound}]"
|
45
|
-
"[#{var_type.bound}]"
|
46
|
-
else
|
47
|
-
"[#{var_type}]"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
"#{base_string}#{var_types_strings.join}"
|
51
|
-
end
|
52
|
-
|
53
40
|
def clone_with_substitutions(substitutions)
|
54
41
|
materialized_type_vars = type_vars(recursive: false).map do |type_var|
|
55
42
|
if type_var.is_a?(Polymorphism::TypeVariable)
|
@@ -74,7 +61,6 @@ module TypedRb
|
|
74
61
|
end
|
75
62
|
self
|
76
63
|
end
|
77
|
-
|
78
64
|
end
|
79
65
|
end
|
80
66
|
end
|
@@ -2,6 +2,7 @@ require_relative 'ty_singleton_object'
|
|
2
2
|
require_relative 'polymorphism/generic_comparisons'
|
3
3
|
require_relative 'polymorphism/generic_variables'
|
4
4
|
require_relative 'polymorphism/generic_object'
|
5
|
+
require_relative 'singleton_object'
|
5
6
|
|
6
7
|
module TypedRb
|
7
8
|
module Types
|
@@ -9,6 +10,7 @@ module TypedRb
|
|
9
10
|
include Polymorphism::GenericObject
|
10
11
|
include Polymorphism::GenericComparisons
|
11
12
|
include Polymorphism::GenericVariables
|
13
|
+
include SingletonObject
|
12
14
|
|
13
15
|
attr_accessor :local_typing_context, :super_type
|
14
16
|
|
@@ -82,26 +84,6 @@ module TypedRb
|
|
82
84
|
fresh_vars_generic_type.apply_bindings(unification.bindings_map)
|
83
85
|
end
|
84
86
|
|
85
|
-
# TODO: We do need this for cases like Array.(Int).class_method
|
86
|
-
|
87
|
-
# def find_function_type(message)
|
88
|
-
# function_type = BasicObject::TypeRegistry.find(:class, ruby_type, message)
|
89
|
-
# replace_bound_type_vars(function_type, type_vars)
|
90
|
-
# end
|
91
|
-
|
92
|
-
# def find_function_type(message)
|
93
|
-
# BasicObject::TypeRegistry.find(:class, ruby_type, message)
|
94
|
-
# end
|
95
|
-
#
|
96
|
-
# def find_var_type(var)
|
97
|
-
# var_type = BasicObject::TypeRegistry.find(:class_variable, ruby_type, var)
|
98
|
-
# if var_type
|
99
|
-
# var_type
|
100
|
-
# else
|
101
|
-
# Types::TypingContext.type_variable_for(:class_variable, var, hierarchy)
|
102
|
-
# end
|
103
|
-
# end
|
104
|
-
|
105
87
|
def as_object_type
|
106
88
|
# this should only be used to check the body type of this
|
107
89
|
# class. The variables are going to be unbound.
|
@@ -131,41 +113,6 @@ module TypedRb
|
|
131
113
|
TyGenericSingletonObject.new(ruby_type, cloned_type_vars, super_type, node)
|
132
114
|
end
|
133
115
|
|
134
|
-
def to_s
|
135
|
-
base_string = super
|
136
|
-
var_types_strings = @type_vars.map do |var_type|
|
137
|
-
if !var_type.is_a?(Polymorphism::TypeVariable)
|
138
|
-
"[#{var_type}]"
|
139
|
-
elsif var_type.bound && var_type.bound.is_a?(Polymorphism::TypeVariable)
|
140
|
-
"[#{var_type.variable} <= #{var_type.bound.bound || var_type.bound.variable}]"
|
141
|
-
else
|
142
|
-
"[#{var_type.bound || var_type.variable}]"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
"#{base_string}#{var_types_strings.join}"
|
146
|
-
end
|
147
|
-
|
148
|
-
def clone_with_substitutions(substitutions)
|
149
|
-
materialized_type_vars = type_vars(recursive: false).map do |type_var|
|
150
|
-
if type_var.is_a?(Polymorphism::TypeVariable) && type_var.bound_to_generic?
|
151
|
-
new_type_var = Polymorphism::TypeVariable.new(type_var.variable, node: type_var.node, gen_name: false)
|
152
|
-
new_type_var.to_wildcard! if type_var.wildcard?
|
153
|
-
bound = type_var.bound.clone_with_substitutions(substitutions)
|
154
|
-
new_type_var.bind(bound)
|
155
|
-
new_type_var.upper_bound = bound if type_var.upper_bound
|
156
|
-
new_type_var.lower_bound = bound if type_var.lower_bound
|
157
|
-
new_type_var
|
158
|
-
elsif type_var.is_a?(Polymorphism::TypeVariable)
|
159
|
-
substitutions[type_var.variable] || type_var.clone
|
160
|
-
elsif type_var.is_a?(TyGenericSingletonObject) || type_var.is_a?(TyGenericObject)
|
161
|
-
type_var.clone_with_substitutions(substitutions)
|
162
|
-
else
|
163
|
-
type_var
|
164
|
-
end
|
165
|
-
end
|
166
|
-
self.class.new(ruby_type, materialized_type_vars, super_type, node)
|
167
|
-
end
|
168
|
-
|
169
116
|
# This object has concrete type parameters
|
170
117
|
# The generic Function we retrieve from the registry might be generic
|
171
118
|
# If it is generic we apply the bound parameters and we obtain a concrete function type
|
@@ -188,73 +135,6 @@ module TypedRb
|
|
188
135
|
end
|
189
136
|
end
|
190
137
|
|
191
|
-
protected
|
192
|
-
|
193
|
-
def apply_type_arguments(fresh_vars_generic_type, actual_arguments)
|
194
|
-
fresh_vars_generic_type.type_vars.each_with_index do |type_var, i|
|
195
|
-
if type_var.bound.is_a?(TyGenericSingletonObject)
|
196
|
-
type_var.bind(apply_type_arguments_recursively(type_var.bound, actual_arguments))
|
197
|
-
else
|
198
|
-
apply_type_argument(actual_arguments[i], type_var)
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
def apply_type_argument(argument, type_var)
|
204
|
-
if argument.is_a?(Polymorphism::TypeVariable)
|
205
|
-
if argument.wildcard?
|
206
|
-
# Wild card type
|
207
|
-
# If the type is T =:= E < Type1 or E > Type1 only that constraint should be added
|
208
|
-
{ :lt => :upper_bound, :gt => :lower_bound }.each do |relation, bound|
|
209
|
-
if argument.send(bound)
|
210
|
-
value = if argument.send(bound).is_a?(TyGenericSingletonObject)
|
211
|
-
argument.send(bound).clone # .self_materialize
|
212
|
-
else
|
213
|
-
argument.send(bound)
|
214
|
-
end
|
215
|
-
type_var.compatible?(value, relation)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
type_var.to_wildcard! # WILD CARD
|
219
|
-
elsif argument.bound # var type with a particular value
|
220
|
-
argument = argument.bound
|
221
|
-
if argument.is_a?(TyGenericSingletonObject)
|
222
|
-
argument = argument.clone # .self_materialize
|
223
|
-
end
|
224
|
-
# This is only for matches T =:= Type1 -> T < Type1, T > Type1
|
225
|
-
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :lt)
|
226
|
-
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :gt)
|
227
|
-
else
|
228
|
-
# Type variable
|
229
|
-
type_var.bound = argument
|
230
|
-
type_var.lower_bound = argument
|
231
|
-
type_var.upper_bound = argument
|
232
|
-
end
|
233
|
-
else
|
234
|
-
if argument.is_a?(TyGenericSingletonObject)
|
235
|
-
argument = argument.clone # .self_materialize
|
236
|
-
end
|
237
|
-
# This is only for matches T =:= Type1 -> T < Type1, T > Type1
|
238
|
-
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :lt)
|
239
|
-
fail Types::UncomparableTypes.new(type_var, argument) unless type_var.compatible?(argument, :gt)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
def apply_type_arguments_recursively(generic_type_bound, actual_arguments)
|
244
|
-
arg_names = actual_arguments_hash(actual_arguments)
|
245
|
-
recursive_actual_arguments = generic_type_bound.type_vars.map do |type_var|
|
246
|
-
arg_names[type_var.variable] || fail("Unbound type variable #{type_var.variable} for recursive generic type #{generic_type_bound}")
|
247
|
-
end
|
248
|
-
generic_type_bound.materialize(recursive_actual_arguments)
|
249
|
-
end
|
250
|
-
|
251
|
-
def actual_arguments_hash(actual_arguments)
|
252
|
-
acc = {}
|
253
|
-
type_vars.each_with_index do |type_var, i|
|
254
|
-
acc[type_var.variable] = actual_arguments[i]
|
255
|
-
end
|
256
|
-
acc
|
257
|
-
end
|
258
138
|
end
|
259
139
|
end
|
260
140
|
end
|
@@ -19,7 +19,8 @@ module TypedRb
|
|
19
19
|
class TyObject < Type
|
20
20
|
include Comparable
|
21
21
|
|
22
|
-
attr_reader :
|
22
|
+
attr_reader :classes, :modules, :ruby_type, :with_ruby_type
|
23
|
+
attr_accessor :hierarchy
|
23
24
|
|
24
25
|
def initialize(ruby_type, node = nil, classes = [], modules = [])
|
25
26
|
super(node)
|
data/lib/typed/version.rb
CHANGED
@@ -86,4 +86,107 @@ __CODE
|
|
86
86
|
result = language.check(code)
|
87
87
|
expect(result.ruby_type).to eq(Integer)
|
88
88
|
end
|
89
|
+
|
90
|
+
it 'typechecks the inclusion of a polymorphic module into a class' do
|
91
|
+
code = <<__CODE
|
92
|
+
module TMod5
|
93
|
+
ts '#head[T] / Array[T] -> [T]'
|
94
|
+
def head(xs); xs.first; end
|
95
|
+
end
|
96
|
+
|
97
|
+
class TMod5C
|
98
|
+
include TMod5
|
99
|
+
end
|
100
|
+
|
101
|
+
TMod5C.new.head([1,2,3])
|
102
|
+
__CODE
|
103
|
+
|
104
|
+
result = language.check(code)
|
105
|
+
expect(result.ruby_type).to eq(Integer)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'typechecks the inclusion of a polymorphic nested module into a class' do
|
109
|
+
code = <<__CODE
|
110
|
+
module Categories
|
111
|
+
module Polymorphism
|
112
|
+
|
113
|
+
ts '#head[A] / Array[A] -> [A]'
|
114
|
+
def head(xs)
|
115
|
+
xs.first
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
include Categories::Polymorphism
|
122
|
+
|
123
|
+
head([1,2,3])
|
124
|
+
__CODE
|
125
|
+
|
126
|
+
result = language.check(code)
|
127
|
+
expect(result.ruby_type).to eq(Integer)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'typechecks the inclusion of a polymorphic module into the top level object' do
|
131
|
+
code = <<__CODE
|
132
|
+
module TMod5
|
133
|
+
ts '#head[T] / Array[T] -> [T]'
|
134
|
+
def head(xs); xs.first; end
|
135
|
+
end
|
136
|
+
|
137
|
+
include TMod5
|
138
|
+
|
139
|
+
head([1,2,3])
|
140
|
+
__CODE
|
141
|
+
|
142
|
+
result = language.check(code)
|
143
|
+
expect(result.ruby_type).to eq(Integer)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'typechecks modules with generic parameters' do
|
147
|
+
code = <<__CODE
|
148
|
+
ts 'type TMod6[T]'
|
149
|
+
module TMod6
|
150
|
+
ts '#test1 / Array[T] -> [T]'
|
151
|
+
def test1(x); x.first; end
|
152
|
+
end
|
153
|
+
|
154
|
+
ts 'type TestTMod6 super TMod6[String]'
|
155
|
+
class TestTMod6
|
156
|
+
include TMod6
|
157
|
+
end
|
158
|
+
|
159
|
+
TestTMod6.new.test1(['a','b','c'])
|
160
|
+
__CODE
|
161
|
+
|
162
|
+
result = language.check(code)
|
163
|
+
expect(result.ruby_type).to eq(String)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'typechecks modules with generic parameters 2' do
|
167
|
+
code = <<__CODE
|
168
|
+
module Categories
|
169
|
+
ts 'type Categories::Equal[T]'
|
170
|
+
module Equal
|
171
|
+
|
172
|
+
ts '#eq? / [T] -> Boolean'
|
173
|
+
def eq?(o); self.eql?(o); end
|
174
|
+
|
175
|
+
ts '#not_eq? / [T] -> Boolean'
|
176
|
+
def not_eq?(o); ! self.eq?(o); end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
ts 'type String super Categories::Equal[String]'
|
182
|
+
class String
|
183
|
+
include Categories::Equal
|
184
|
+
end
|
185
|
+
|
186
|
+
"test".eq? "other"
|
187
|
+
__CODE
|
188
|
+
|
189
|
+
result = language.check(code)
|
190
|
+
expect(result.to_s).to eq('Boolean')
|
191
|
+
end
|
89
192
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typed.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Antonio Garrote
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-01-
|
11
|
+
date: 2016-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -130,12 +130,14 @@ files:
|
|
130
130
|
- lib/typed/types/polymorphism/type_variable.rb
|
131
131
|
- lib/typed/types/polymorphism/type_variable_register.rb
|
132
132
|
- lib/typed/types/polymorphism/unification.rb
|
133
|
+
- lib/typed/types/singleton_object.rb
|
133
134
|
- lib/typed/types/ty_boolean.rb
|
134
135
|
- lib/typed/types/ty_dynamic.rb
|
135
136
|
- lib/typed/types/ty_either.rb
|
136
137
|
- lib/typed/types/ty_error.rb
|
137
138
|
- lib/typed/types/ty_existential_type.rb
|
138
139
|
- lib/typed/types/ty_function.rb
|
140
|
+
- lib/typed/types/ty_generic_existential_type.rb
|
139
141
|
- lib/typed/types/ty_generic_function.rb
|
140
142
|
- lib/typed/types/ty_generic_object.rb
|
141
143
|
- lib/typed/types/ty_generic_singleton_object.rb
|
@@ -261,8 +263,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
261
263
|
version: '0'
|
262
264
|
requirements: []
|
263
265
|
rubyforge_project:
|
264
|
-
rubygems_version: 2.4.
|
266
|
+
rubygems_version: 2.4.6
|
265
267
|
signing_key:
|
266
268
|
specification_version: 4
|
267
269
|
summary: Gradual type checker for Ruby
|
268
270
|
test_files: []
|
271
|
+
has_rdoc:
|