typed.rb 0.0.11

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 (173) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +26 -0
  3. data/bin/typed.rb +110 -0
  4. data/lib/typed/language.rb +131 -0
  5. data/lib/typed/model/tm_abs.rb +104 -0
  6. data/lib/typed/model/tm_array_literal.rb +25 -0
  7. data/lib/typed/model/tm_boolean.rb +15 -0
  8. data/lib/typed/model/tm_boolean_operator.rb +34 -0
  9. data/lib/typed/model/tm_break.rb +24 -0
  10. data/lib/typed/model/tm_case_when.rb +38 -0
  11. data/lib/typed/model/tm_class.rb +63 -0
  12. data/lib/typed/model/tm_const.rb +29 -0
  13. data/lib/typed/model/tm_defined.rb +19 -0
  14. data/lib/typed/model/tm_error.rb +16 -0
  15. data/lib/typed/model/tm_float.rb +15 -0
  16. data/lib/typed/model/tm_for.rb +42 -0
  17. data/lib/typed/model/tm_fun.rb +165 -0
  18. data/lib/typed/model/tm_global_var.rb +22 -0
  19. data/lib/typed/model/tm_global_var_assignment.rb +20 -0
  20. data/lib/typed/model/tm_hash_literal.rb +32 -0
  21. data/lib/typed/model/tm_if_else.rb +24 -0
  22. data/lib/typed/model/tm_instance_var.rb +23 -0
  23. data/lib/typed/model/tm_instance_var_assignment.rb +32 -0
  24. data/lib/typed/model/tm_int.rb +15 -0
  25. data/lib/typed/model/tm_local_var_asgn.rb +35 -0
  26. data/lib/typed/model/tm_mass_asgn.rb +60 -0
  27. data/lib/typed/model/tm_mlhs.rb +87 -0
  28. data/lib/typed/model/tm_module.rb +51 -0
  29. data/lib/typed/model/tm_next.rb +24 -0
  30. data/lib/typed/model/tm_nil.rb +14 -0
  31. data/lib/typed/model/tm_range_literal.rb +30 -0
  32. data/lib/typed/model/tm_regexp.rb +27 -0
  33. data/lib/typed/model/tm_rescue.rb +27 -0
  34. data/lib/typed/model/tm_return.rb +24 -0
  35. data/lib/typed/model/tm_s_class.rb +30 -0
  36. data/lib/typed/model/tm_self.rb +22 -0
  37. data/lib/typed/model/tm_send.rb +300 -0
  38. data/lib/typed/model/tm_sequencing.rb +53 -0
  39. data/lib/typed/model/tm_string.rb +15 -0
  40. data/lib/typed/model/tm_string_interpolation.rb +21 -0
  41. data/lib/typed/model/tm_super.rb +27 -0
  42. data/lib/typed/model/tm_symbol.rb +15 -0
  43. data/lib/typed/model/tm_symbol_interpolation.rb +21 -0
  44. data/lib/typed/model/tm_try.rb +29 -0
  45. data/lib/typed/model/tm_var.rb +28 -0
  46. data/lib/typed/model/tm_while.rb +43 -0
  47. data/lib/typed/model.rb +48 -0
  48. data/lib/typed/prelude.rb +939 -0
  49. data/lib/typed/prelude_existential_registry.bin +0 -0
  50. data/lib/typed/prelude_generic_registry.bin +0 -0
  51. data/lib/typed/prelude_registry.bin +0 -0
  52. data/lib/typed/runtime/ast_parser.rb +589 -0
  53. data/lib/typed/runtime/method_signature_processor.rb +72 -0
  54. data/lib/typed/runtime/normalization/validations.rb +47 -0
  55. data/lib/typed/runtime/normalization.rb +196 -0
  56. data/lib/typed/runtime/parser_context.rb +36 -0
  57. data/lib/typed/runtime/type_parser.rb +215 -0
  58. data/lib/typed/runtime/type_registry.rb +170 -0
  59. data/lib/typed/runtime/type_signature_processor.rb +34 -0
  60. data/lib/typed/runtime.rb +33 -0
  61. data/lib/typed/type_signature/parser.rb +240 -0
  62. data/lib/typed/types/polymorphism/existential_type_variable.rb +13 -0
  63. data/lib/typed/types/polymorphism/generic_comparisons.rb +134 -0
  64. data/lib/typed/types/polymorphism/generic_variables.rb +24 -0
  65. data/lib/typed/types/polymorphism/type_variable.rb +138 -0
  66. data/lib/typed/types/polymorphism/type_variable_register.rb +298 -0
  67. data/lib/typed/types/polymorphism/unification.rb +579 -0
  68. data/lib/typed/types/ty_boolean.rb +15 -0
  69. data/lib/typed/types/ty_dynamic.rb +39 -0
  70. data/lib/typed/types/ty_either.rb +168 -0
  71. data/lib/typed/types/ty_error.rb +18 -0
  72. data/lib/typed/types/ty_existential_type.rb +22 -0
  73. data/lib/typed/types/ty_function.rb +144 -0
  74. data/lib/typed/types/ty_generic_function.rb +115 -0
  75. data/lib/typed/types/ty_generic_object.rb +180 -0
  76. data/lib/typed/types/ty_generic_singleton_object.rb +238 -0
  77. data/lib/typed/types/ty_object.rb +256 -0
  78. data/lib/typed/types/ty_singleton_object.rb +78 -0
  79. data/lib/typed/types/ty_stack_jump.rb +44 -0
  80. data/lib/typed/types/ty_top_level_object.rb +38 -0
  81. data/lib/typed/types.rb +60 -0
  82. data/lib/typed/typing_context.rb +206 -0
  83. data/lib/typed/version.rb +3 -0
  84. data/lib/typed.rb +161 -0
  85. data/spec/lib/ast_parser_spec.rb +101 -0
  86. data/spec/lib/examples/animals.rb +44 -0
  87. data/spec/lib/examples/counter.rb +16 -0
  88. data/spec/lib/examples/if.rb +31 -0
  89. data/spec/lib/language_spec.rb +36 -0
  90. data/spec/lib/model/tm_abs_spec.rb +66 -0
  91. data/spec/lib/model/tm_array_literal_spec.rb +36 -0
  92. data/spec/lib/model/tm_case_when_spec.rb +39 -0
  93. data/spec/lib/model/tm_class_spec.rb +67 -0
  94. data/spec/lib/model/tm_defined_spec.rb +10 -0
  95. data/spec/lib/model/tm_for_spec.rb +150 -0
  96. data/spec/lib/model/tm_fun_spec.rb +11 -0
  97. data/spec/lib/model/tm_hash_literal_spec.rb +40 -0
  98. data/spec/lib/model/tm_mass_asgn_spec.rb +104 -0
  99. data/spec/lib/model/tm_module_spec.rb +42 -0
  100. data/spec/lib/model/tm_regexp_spec.rb +9 -0
  101. data/spec/lib/model/tm_return_spec.rb +47 -0
  102. data/spec/lib/model/tm_s_class_spec.rb +27 -0
  103. data/spec/lib/model/tm_self_spec.rb +19 -0
  104. data/spec/lib/model/tm_string_interpolation_spec.rb +10 -0
  105. data/spec/lib/model/tm_symbol_interpolation_spec.rb +10 -0
  106. data/spec/lib/model/tm_symbol_spec.rb +9 -0
  107. data/spec/lib/model/tm_while_spec.rb +141 -0
  108. data/spec/lib/polymorphism/type_variable_spec.rb +14 -0
  109. data/spec/lib/polymorphism/unification_spec.rb +328 -0
  110. data/spec/lib/prelude/array_spec.rb +263 -0
  111. data/spec/lib/prelude/class_spec.rb +12 -0
  112. data/spec/lib/prelude/enumerable_spec.rb +278 -0
  113. data/spec/lib/prelude/enumerator_spec.rb +101 -0
  114. data/spec/lib/prelude/hash_spec.rb +361 -0
  115. data/spec/lib/prelude/kernel_spec.rb +23 -0
  116. data/spec/lib/prelude/object_spec.rb +22 -0
  117. data/spec/lib/prelude/pair_spec.rb +16 -0
  118. data/spec/lib/prelude/showable_spec.rb +31 -0
  119. data/spec/lib/prelude/string_spec.rb +98 -0
  120. data/spec/lib/runtime/normalization_spec.rb +29 -0
  121. data/spec/lib/runtime/validations_spec.rb +56 -0
  122. data/spec/lib/runtime_spec.rb +503 -0
  123. data/spec/lib/type_signature/parser_spec.rb +239 -0
  124. data/spec/lib/types/comparisons_spec.rb +35 -0
  125. data/spec/lib/types/polymorphism/generic_comparisons_spec.rb +492 -0
  126. data/spec/lib/types/polymorphism/type_variable_register_spec.rb +128 -0
  127. data/spec/lib/types/ty_dynamic_spec.rb +103 -0
  128. data/spec/lib/types/ty_either_spec.rb +288 -0
  129. data/spec/lib/types/ty_error_spec.rb +18 -0
  130. data/spec/lib/types/ty_generic_object_spec.rb +78 -0
  131. data/spec/lib/types/ty_generic_singleton_object_spec.rb +288 -0
  132. data/spec/lib/types/typing_context_spec.rb +86 -0
  133. data/spec/lib/types_spec.rb +174 -0
  134. data/spec/lib/typing/boolean_asgn_spec.rb +134 -0
  135. data/spec/lib/typing/break_spec.rb +79 -0
  136. data/spec/lib/typing/generics_spec.rb +191 -0
  137. data/spec/lib/typing/instance_vars_spec.rb +103 -0
  138. data/spec/lib/typing/next_spec.rb +29 -0
  139. data/spec/lib/typing/op_asgn_spec.rb +104 -0
  140. data/spec/lib/typing/overriden_methods_spec.rb +31 -0
  141. data/spec/lib/typing/subtyping_spec.rb +112 -0
  142. data/spec/lib/typing/tm_boolean_operator_spec.rb +100 -0
  143. data/spec/lib/typing/tm_boolean_spec.rb +61 -0
  144. data/spec/lib/typing/tm_const_spec.rb +28 -0
  145. data/spec/lib/typing/tm_defined_spec.rb +12 -0
  146. data/spec/lib/typing/tm_fun_spec.rb +347 -0
  147. data/spec/lib/typing/tm_global_var_spec.rb +33 -0
  148. data/spec/lib/typing/tm_if_else_spec.rb +104 -0
  149. data/spec/lib/typing/tm_ignore_spec.rb +24 -0
  150. data/spec/lib/typing/tm_instance_vars_spec.rb +117 -0
  151. data/spec/lib/typing/tm_local_var_asgn_spec.rb +134 -0
  152. data/spec/lib/typing/tm_mlhs_spec.rb +164 -0
  153. data/spec/lib/typing/tm_module_spec.rb +89 -0
  154. data/spec/lib/typing/tm_raise_spec.rb +31 -0
  155. data/spec/lib/typing/tm_range_literal_spec.rb +25 -0
  156. data/spec/lib/typing/tm_regexp_spec.rb +14 -0
  157. data/spec/lib/typing/tm_return_spec.rb +45 -0
  158. data/spec/lib/typing/tm_send_casting_spec.rb +26 -0
  159. data/spec/lib/typing/tm_send_class_methods_spec.rb +42 -0
  160. data/spec/lib/typing/tm_send_generic_apply_spec.rb +103 -0
  161. data/spec/lib/typing/tm_send_generic_methods_spec.rb +77 -0
  162. data/spec/lib/typing/tm_send_initialize_spec.rb +68 -0
  163. data/spec/lib/typing/tm_send_lambda_spec.rb +135 -0
  164. data/spec/lib/typing/tm_send_spec.rb +217 -0
  165. data/spec/lib/typing/tm_send_yield_block_spec.rb +308 -0
  166. data/spec/lib/typing/tm_sequencing_spec.rb +174 -0
  167. data/spec/lib/typing/tm_string_interpolation_spec.rb +19 -0
  168. data/spec/lib/typing/tm_super_spec.rb +63 -0
  169. data/spec/lib/typing/tm_symbol_interpolation_spec.rb +19 -0
  170. data/spec/lib/typing/tm_symbol_spec.rb +14 -0
  171. data/spec/lib/typing/tm_try_spec.rb +73 -0
  172. data/spec/spec_helper.rb +140 -0
  173. metadata +216 -0
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # range literals
7
+ class TmRangeLiteral < Expr
8
+ attr_reader :start_range, :end_range
9
+ def initialize(start_range, end_range, node)
10
+ super(node)
11
+ @start_range = start_range
12
+ @end_range = end_range
13
+ end
14
+
15
+ def check_type(context)
16
+ start_range_type = start_range.check_type(context)
17
+ end_range_type = end_range.check_type(context)
18
+ max_type = [start_range_type, end_range_type].max
19
+
20
+ type_var = Types::Polymorphism::TypeVariable.new('Range:T',
21
+ :node => node,
22
+ :gen_name => false,
23
+ :upper_bound => max_type,
24
+ :lower_bound => max_type)
25
+ type_var.bind(max_type)
26
+ Types::TyGenericObject.new(Range, [type_var], node)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # Regular expresssion
7
+ class TmRegexp < Expr
8
+ attr_reader :exp, :options
9
+ def initialize(exp, options, node)
10
+ super(node)
11
+ @exp = exp
12
+ @ptions = options
13
+ end
14
+
15
+ def check_type(context)
16
+ options.check_type(context) if options
17
+ exp_type = exp.check_type(context)
18
+ if exp_type.compatible?(Types::TyString.new(node), :lt)
19
+ Types::TyRegexp.new(node)
20
+ else
21
+ error_message = "Error type checking Regexp: Expected String type for expression, found #{exp_type}"
22
+ fail Types::TypeCheckError.new(error_message, node)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../model'
2
+
3
+ module TypedRb
4
+ module Model
5
+ class TmRescue < Expr
6
+
7
+ attr_reader :exceptions, :catch_var, :rescue_body
8
+ def initialize(exceptions, catch_var, rescue_body)
9
+ @exceptions = exceptions
10
+ @catch_var = catch_var
11
+ @rescue_body = rescue_body
12
+ end
13
+
14
+ def check_type(context)
15
+ if catch_var
16
+ exception_type = exceptions.map{|e| e.check_type(context) }.max
17
+ context.add_binding!(catch_var, exception_type)
18
+ end
19
+ if rescue_body
20
+ rescue_body.check_type(context)
21
+ else
22
+ Types::TyUnit.new
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ require_relative '../model'
2
+
3
+ module TypedRb
4
+ module Model
5
+ class TmReturn < Expr
6
+ attr_reader :elements
7
+ def initialize(elements, node)
8
+ super(node)
9
+ @elements = elements
10
+ end
11
+
12
+ def check_type(context)
13
+ returned_type = if elements.size == 0
14
+ Types::TyUnit.new(node)
15
+ elsif elements.size == 1
16
+ elements.first.check_type(context)
17
+ else
18
+ TmArrayLiteral.new(elements, node).check_type(context)
19
+ end
20
+ Types::TyStackJump.return(returned_type, node)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # Class expression
7
+ class TmSClass < Expr
8
+ attr_reader :class_name, :super_class_name, :body
9
+
10
+ def initialize(class_name, body, node)
11
+ super(node)
12
+ @class_name = class_name
13
+ @body = body
14
+ end
15
+
16
+ def check_type(context)
17
+ if class_name != :self
18
+ class_ruby_type = Types::TypingContext.find_namespace(class_name)
19
+ class_type = Runtime::TypeParser.parse_singleton_object_type(class_ruby_type.name)
20
+ class_type.node = node
21
+ context = context.add_binding(:self, class_type)
22
+ end
23
+ Types::TypingContext.push_context(:sclass)
24
+ res = body.check_type(context)
25
+ Types::TypingContext.pop_context
26
+ res
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # booleans
7
+ class TmSelf < Expr
8
+ def initialize(node)
9
+ super(node)
10
+ end
11
+
12
+ def check_type(context)
13
+ self_type = context.get_type_for(:self)
14
+ if self_type.nil?
15
+ fail TypeCheckError.new.new('Error type checking self reference: Cannot find self reference in typing context', node)
16
+ else
17
+ self_type
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,300 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # message send
7
+ class TmSend < Expr
8
+ attr_accessor :receiver, :message, :args, :block
9
+ def initialize(receiver, message, args, node)
10
+ super(node)
11
+ @receiver = receiver
12
+ @message = message
13
+ @args = args
14
+ @block = nil
15
+ end
16
+
17
+ def with_block(block)
18
+ @block = block
19
+ end
20
+
21
+ def check_type(context)
22
+ @context = context
23
+ TypedRb.log(binding, :debug, "Type checking message sent: #{message} at line #{node.loc.line}")
24
+ if receiver.nil? && message == :ts
25
+ # ignore, => type annotation
26
+ Types::TyUnit.new(node)
27
+ elsif message == :new && !singleton_object_type(receiver, context).nil? # clean this!
28
+ check_instantiation(context)
29
+ elsif receiver == :self || receiver.nil?
30
+ # self.m(args), m(args), m
31
+ check_type_no_explicit_receiver(context)
32
+ else
33
+ # x.m(args)
34
+ check_type_explicit_receiver(context)
35
+ end
36
+ end
37
+
38
+ def singleton_object_type(receiver, context)
39
+ parsed_receiver_type = if receiver.nil? || receiver == :self
40
+ context.get_type_for(:self)
41
+ else
42
+ receiver_type
43
+ end
44
+ return parsed_receiver_type if parsed_receiver_type.is_a?(Types::TySingletonObject)
45
+ end
46
+
47
+ # we received new, but we look for initialize in the class,
48
+ # not the singleton class.
49
+ # we then run the regular application,
50
+ # but we return the class type instead of the return type
51
+ # for the constructor application (should be unit/nil).
52
+ def check_instantiation(context)
53
+ self_type = singleton_object_type(receiver, context).as_object_type
54
+ function_klass_type, function_type = self_type.find_function_type(:initialize, args.size, @block)
55
+ # function application
56
+ @message = :initialize
57
+ begin
58
+ check_application(self_type, function_type, context)
59
+ rescue TypeCheckError => error
60
+ raise error if function_klass_type == self_type.ruby_type
61
+ end
62
+ self_type
63
+ end
64
+
65
+ def check_type_no_explicit_receiver(context)
66
+ if message == :yield
67
+ check_yield_application(context)
68
+ else
69
+ @receiver_type = context.get_type_for(:self) # check message in self type -> application
70
+ check_type_explicit_receiver(context)
71
+ end
72
+ end
73
+
74
+ def check_yield_application(context)
75
+ yield_abs_type = context.get_type_for(:yield)
76
+ if yield_abs_type
77
+ check_lambda_application(yield_abs_type, context)
78
+ else
79
+ fail TypeCheckError.new("Error type checking message sent '#{message}': Cannot find yield function defined in typing context", node)
80
+ end
81
+ end
82
+
83
+ def check_type_explicit_receiver(context)
84
+ if receiver_type.is_a?(Types::Polymorphism::TypeVariable)
85
+ # Existential type (Module) if receiver_type is self
86
+ # TODO: what can we do if this is the inclusion of a module?
87
+ arg_types = args.map { |arg| arg.check_type(context) }
88
+ receiver_type.add_message_constraint(message, arg_types)
89
+ elsif receiver_type.is_a?(Types::TyGenericSingletonObject) && (message == :call)
90
+ # Application of types accept a type class or a string with a type description
91
+ arg_types = parse_type_application_arguments(args, context)
92
+ check_type_application_to_generic(receiver_type, arg_types)
93
+ elsif receiver_type.is_a?(Types::TyFunction) && (message == :[] || message == :call)
94
+ check_lambda_application(receiver_type, context)
95
+ else
96
+ function_klass_type, function_type = receiver_type.find_function_type(message, args.size, @block)
97
+ # begin
98
+ if function_type.nil?
99
+ error_message = "Error type checking message sent '#{message}': Type information for #{receiver_type}:#{message} not found."
100
+ fail TypeCheckError.new(error_message, node)
101
+ elsif cast?(function_klass_type)
102
+ check_casting(context)
103
+ elsif module_include_implementation?(function_klass_type)
104
+ check_module_inclusions(receiver_type, context)
105
+ else
106
+ # function application
107
+ check_application(receiver_type, function_type, context)
108
+ end
109
+ # rescue TypeCheckError => error
110
+ # if function_klass_type != receiver_type.ruby_type
111
+ # Types::TyDynamic.new(Object, node)
112
+ # else
113
+ # raise error
114
+ # end
115
+ # end
116
+ end
117
+ end
118
+
119
+ def parse_type_application_arguments(arguments, context)
120
+ arguments.map do |argument|
121
+ if argument.is_a?(Model::TmString)
122
+ type_var_signature = argument.node.children.first
123
+ maybe_generic_method_var = Types::TypingContext.vars_info(:method)[type_var_signature]
124
+ maybe_generic_class_var = Types::TypingContext.vars_info(:class)[type_var_signature]
125
+ if maybe_generic_method_var || maybe_generic_class_var
126
+ maybe_generic_method_var || maybe_generic_class_var
127
+ else
128
+ parsed_types = TypeSignature::Parser.parse(type_var_signature)
129
+ if parsed_types.is_a?(Array)
130
+ parsed_types.map { |parsed_type| parse_type_application_argument(parsed_type) }
131
+ else
132
+ parse_type_application_argument(parsed_types)
133
+ end
134
+ end
135
+ else
136
+ argument.check_type(context)
137
+ end
138
+ end.flatten
139
+ end
140
+
141
+ def parse_type_application_argument(type)
142
+ # TODO: do this recursively in the case of nested generic type
143
+ # TODO: do we need it at all?
144
+ klass = if type.is_a?(Hash) && type[:kind] == :generic_type
145
+ Class.for_name(type[:type])
146
+ end
147
+ Runtime::TypeParser.parse(type, klass)
148
+ end
149
+
150
+ def type_application_counter
151
+ @type_application_counter ||= 0
152
+ @type_application_counter += 1
153
+ end
154
+
155
+ def check_type_application_to_generic(generic_type, args)
156
+ generic_type.materialize(args)
157
+ end
158
+
159
+ def check_application(receiver_type, function_type, context)
160
+ if function_type.is_a?(Types::TyDynamicFunction)
161
+ function_type.to
162
+ else
163
+ if function_type.generic?
164
+ function_type.local_typing_context.parent = Types::TypingContext.type_variables_register
165
+ return_type = function_type.materialize do |materialized_function|
166
+ check_application(receiver_type, materialized_function, context)
167
+ end.to
168
+ return_type.respond_to?(:as_object_type) ? return_type.as_object_type : return_type
169
+ else
170
+ formal_parameters = function_type.from
171
+ parameters_info = function_type.parameters_info
172
+ TypedRb.log(binding, :debug, "Checking function application #{receiver_type}::#{message}( #{parameters_info} )")
173
+ check_args_application(parameters_info, formal_parameters, args, context)
174
+ if @block
175
+ block_type = @block.check_type(context)
176
+ # TODO:
177
+ # Unification is run here
178
+ # Algorithm is failing:
179
+ # G > String,
180
+ # G < E
181
+ # ========
182
+ # G = [String, ?]
183
+ # -----
184
+ # G = [String, E]
185
+ # E = [String, ?]
186
+ block_return_type = if function_type.block_type
187
+ # materialization and unification will happen in this invocation
188
+ block_type.compatible?(function_type.block_type, :lt)
189
+ else
190
+ block_type.to
191
+ end
192
+ if block_return_type.to.stack_jump?
193
+ break_type = block_return_type.to.wrapped_type.check_type(context)
194
+ unless break_type.compatible?(function_type.to, :lt)
195
+ error_message = "Incompatible 'break' type, expected #{function_type.to}, found #{break_type}"
196
+ fail error_message, block_return_type.to.node
197
+ end
198
+ elsif block_return_type.to.either?
199
+ max_type = block_return_type.check_type(context, [:return, :break, :normal])
200
+ unless max_type.compatible?(function_type.to, :lt)
201
+ error_message = "Incompatible either max type, expected #{function_type.to}, found #{max_type}"
202
+ fail error_message, block_return_type.to.node
203
+ end
204
+ end
205
+ end
206
+ return_type = function_type.to
207
+ return_type.respond_to?(:as_object_type) ? return_type.as_object_type : return_type
208
+ end
209
+ end
210
+ end
211
+
212
+ def check_lambda_application(lambda_type, context)
213
+ lambda_type.check_args_application(args, context).to
214
+ end
215
+
216
+ def check_args_application(parameters_info, formal_parameters, actual_arguments, context)
217
+ #binding.pry if actual_arguments.size == 1 && actual_arguments.first.class == TypedRb::Model::TmVar && actual_arguments.first.val == "klass" && actual_arguments.first.col == 36
218
+ parameters_info.each_with_index do |(require_info, arg_name), index|
219
+ actual_argument = actual_arguments[index]
220
+ formal_parameter_type = formal_parameters[index]
221
+ if formal_parameter_type.nil? && !require_info == :block
222
+ fail TypeCheckError.new("Error type checking message sent '#{message}': Missing information about argument #{arg_name} in #{receiver}##{message}", node)
223
+ end
224
+ if actual_argument.nil? && require_info != :opt && require_info != :rest && require_info != :block
225
+ fail TypeCheckError.new("Error type checking message sent '#{message}': Missing mandatory argument #{arg_name} in #{receiver}##{message}", node)
226
+ else
227
+ if require_info == :rest
228
+ break if actual_argument.nil? # invocation without any of the optional arguments
229
+ rest_type = formal_parameter_type.type_vars.first
230
+ formal_parameter_type = if rest_type.respond_to?(:bound)
231
+ rest_type.bound
232
+ else
233
+ rest_type
234
+ end
235
+ actual_arguments[index..-1].each do |actual_argument|
236
+ unless actual_argument.check_type(context).compatible?(formal_parameter_type, :lt)
237
+ error_message = "Error type checking message sent '#{message}': #{formal_parameter_type} expected, #{actual_argument_type} found"
238
+ fail TypeCheckError.new(error_message, node)
239
+ end
240
+ end
241
+ break
242
+ else
243
+ unless actual_argument.nil? # opt or block if this is nil
244
+ actual_argument_type = actual_argument.check_type(context)
245
+ fail TypeCheckError.new("Error type checking message sent '#{message}': Missing type information for argument '#{arg_name}'", node) if formal_parameter_type.nil?
246
+ begin
247
+ unless actual_argument_type.compatible?(formal_parameter_type, :lt)
248
+ error_message = "Error type checking message sent '#{message}': #{formal_parameter_type} expected, #{actual_argument_type} found"
249
+ fail TypeCheckError.new(error_message, node)
250
+ end
251
+ rescue Types::UncomparableTypes, ArgumentError
252
+ raise Types::UncomparableTypes.new(actual_argument_type, formal_parameter_type, node)
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
259
+
260
+ def cast?(function_klass_type)
261
+ function_klass_type == BasicObject && message == :cast
262
+ end
263
+
264
+ def check_casting(context)
265
+ from_type = args[0].check_type(context)
266
+ to = parse_type_application_arguments([args[1]], context).first
267
+ to_type = to.is_a?(Types::TyObject) ? to.as_object_type : to
268
+ TypedRb.log(binding, :info, "Casting #{from_type} into #{to_type}")
269
+ to_type
270
+ end
271
+
272
+ def module_include_implementation?(function_klass_type)
273
+ function_klass_type == Module && message == :include
274
+ end
275
+
276
+ def check_module_inclusions(self_type, context)
277
+ args.map do |arg|
278
+ arg.check_type(context)
279
+ end.each do |module_type|
280
+ if module_type.is_a?(Types::TyExistentialType)
281
+ if module_type.local_typing_context
282
+ module_type.check_inclusion(self_type)
283
+ else
284
+ # TODO: report warning about missing module information
285
+ TypedRb.log(binding, :debug, "Not type checking module #{module_type.ruby_type} inclusion due to lack of module information")
286
+ end
287
+ else
288
+ error_message = "Error type checking message sent '#{message}': Module type expected for inclusion in #{self_type}, #{module_type} found"
289
+ fail TypeCheckError.new(error_message, node)
290
+ end
291
+ end
292
+ self_type
293
+ end
294
+
295
+ def receiver_type
296
+ @receiver_type ||= receiver.check_type(@context)
297
+ end
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ class TmSequencing < Expr
7
+ attr_accessor :terms
8
+ def initialize(terms, node)
9
+ super(node)
10
+ @terms = terms.reject(&:nil?)
11
+ end
12
+
13
+ def check_type(context)
14
+ process_terms_before_return(@terms, context)
15
+ end
16
+
17
+ private
18
+
19
+ def process_terms_before_return(terms, context, processed_terms=[], potential_return=nil)
20
+ if terms.empty?
21
+ make_final_return(processed_terms.last, potential_return)
22
+ else
23
+ term_type = terms.first.check_type(context)
24
+ if term_type.stack_jump?
25
+ process_terms_after_return(terms.drop(1), context)
26
+ make_final_return(term_type, potential_return)
27
+ elsif term_type.either?
28
+ process_terms_before_return(terms.drop(1), context, processed_terms << nil, make_final_return(term_type, potential_return))
29
+ else
30
+ process_terms_before_return(terms.drop(1), context, processed_terms << term_type, potential_return)
31
+ end
32
+ end
33
+ end
34
+
35
+ def process_terms_after_return(terms, context)
36
+ terms.each { |term| term.check_type(context) }
37
+ end
38
+
39
+
40
+ def make_final_return(type_a, type_b)
41
+ return (type_a || type_b) if type_a.nil? || type_b.nil?
42
+ either_types = [type_a, type_b].map{ |type| Types::TyEither.wrap(type) }
43
+ reduced_final_type = either_types.reduce { |a,b| a.compatible_either?(b) }.unwrap
44
+ if type_a.stack_jump? || type_b.stack_jump?
45
+ jump_kind = [type_a, type_b].detect {|type| type.stack_jump? }.jump_kind
46
+ reduced_final_type[jump_kind]
47
+ else
48
+ reduced_final_type
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # strings
7
+ class TmString < Expr
8
+ attr_accessor :val
9
+ def initialize(node)
10
+ super(node, Types::TyString.new(node))
11
+ @val = node.children.first
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../model'
2
+
3
+ module TypedRb
4
+ module Model
5
+ # String interpolation
6
+ class TmStringInterpolation < Expr
7
+ attr_reader :units
8
+ def initialize(units, node)
9
+ super(node)
10
+ @units = units
11
+ end
12
+
13
+ def check_type(context)
14
+ units.each do |unit|
15
+ unit.check_type(context)
16
+ end
17
+ Types::TyString.new(node)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # super keyword invocations
7
+ class TmSuper < Expr
8
+ attr_reader :args
9
+ def initialize(args, node)
10
+ super(node)
11
+ @args = args
12
+ end
13
+
14
+ def check_type(context)
15
+ if Types::TypingContext.function_context
16
+ self_type, message, args = Types::TypingContext.function_context
17
+ parent_self_type = Types::TyObject.new(self_type.hierarchy.first, node)
18
+ args = @args || args
19
+ args = args.map { |arg| arg.check_type(context) }
20
+ TmSend.new(parent_self_type, message, args, node).check_type(context)
21
+ else
22
+ fail TypeCheckError.new("Error type checking 'super' invocation without function context.", node)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # floats
7
+ class TmSymbol < Expr
8
+ attr_accessor :val
9
+ def initialize(node)
10
+ super(node, Types::TySymbol.new(node))
11
+ @val = node.children.first
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../model'
2
+
3
+ module TypedRb
4
+ module Model
5
+ # Symbol interpolation
6
+ class TmSymbolInterpolation < Expr
7
+ attr_reader :units
8
+ def initialize(units, node)
9
+ super(node)
10
+ @units = units
11
+ end
12
+
13
+ def check_type(context)
14
+ units.each do |unit|
15
+ unit.check_type(context)
16
+ end
17
+ Types::TySymbol.new(node)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ class TmTry < Expr
7
+ def initialize(try_term, rescue_terms, node)
8
+ super(node)
9
+ @try_term = try_term
10
+ @rescue_terms = rescue_terms
11
+ end
12
+
13
+ def check_type(context)
14
+ try_term_type = @try_term.check_type(context)
15
+ rescue_term_types = @rescue_terms.map do |term|
16
+ term.check_type(context)
17
+ end.reject do |type|
18
+ type.is_a?(Types::TyUnit)
19
+ end
20
+ incompatible_type = rescue_term_types.detect { |term_type| !try_term_type.compatible?(term_type) }
21
+ if incompatible_type
22
+ fail TypeCheckError.new("Type error checking try statement: Error in rescue clause, expected type #{try_term_type} got #{incompatible_type}", node)
23
+ else
24
+ try_term_type
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+ require_relative '../model'
3
+
4
+ module TypedRb
5
+ module Model
6
+ # variable
7
+ class TmVar < Expr
8
+ attr_accessor :val
9
+
10
+ def initialize(val, node)
11
+ super(node)
12
+ @val = val.to_s
13
+ end
14
+
15
+ def to_s
16
+ "#{GenSym.resolve(@val)}"
17
+ end
18
+
19
+ def check_type(context)
20
+ type = context.get_type_for(@val)
21
+ if type.nil?
22
+ fail TypeCheckError.new("Type error checking local var #{@val}: Cannot find binding local var in the typing context", node)
23
+ end
24
+ type
25
+ end
26
+ end
27
+ end
28
+ end