typed.rb 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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