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
Binary file
@@ -0,0 +1,589 @@
1
+ require 'parser/current'
2
+ require_relative '../runtime'
3
+ require_relative '../model'
4
+ require_relative '../types'
5
+
6
+ module TypedRb
7
+ class TermParsingError < TypeCheckError; end
8
+
9
+ # Custom parser for type signatures.
10
+ # It will transform the signature string into a hash
11
+ # with the type information.
12
+ class AstParser
13
+
14
+ class AssignationWrapper
15
+ def initialize(assignation, children)
16
+ @assignation = assignation
17
+ @children = children
18
+ end
19
+
20
+ def children
21
+ @children
22
+ end
23
+
24
+ ts_ignore
25
+ def method_missing(m, *args, &block)
26
+ @assignation.send(m, *args)
27
+ end
28
+
29
+ def to_s
30
+ @assignation.to_s
31
+ end
32
+ end
33
+
34
+ class RewrittenWrapper
35
+ attr_reader :rewritten
36
+ def initialize(parsed)
37
+ @rewritten = parsed
38
+ end
39
+
40
+ def type
41
+ :rewritten
42
+ end
43
+
44
+ def to_sexp
45
+ "REWRITTEN: #{@rewritten}"
46
+ end
47
+ end
48
+
49
+ include Model
50
+
51
+ def ast(ruby_code)
52
+ Parser::CurrentRuby.parse(ruby_code)
53
+ end
54
+
55
+ def parse(expr)
56
+ map(ast(expr), ParsingContext.new)
57
+ end
58
+
59
+ private
60
+
61
+ def map(node, context)
62
+ if @ignore_node
63
+ @ignore_node = false
64
+ return TmNil.new(node)
65
+ end
66
+ if node
67
+ sexp = node.to_sexp
68
+ sexp = "#{sexp[0..50]} ... #{sexp[-50..-1]}" if sexp.size > 100
69
+ TypedRb.log(binding, :debug, "Parsing node #{node}:\n#{sexp}")
70
+ end
71
+ case node.type
72
+ when :rewritten
73
+ node.rewritten
74
+ when :nil
75
+ TmNil.new(node)
76
+ when :module
77
+ parse_module(node, context)
78
+ when :class
79
+ parse_class(node, context)
80
+ when :def
81
+ parse_def(node, context)
82
+ when :defs
83
+ parse_defs(node, context)
84
+ when :ivar
85
+ parse_instance_var(node, context)
86
+ when :ivasgn
87
+ parse_instance_var_assign(node, context)
88
+ when :lvar
89
+ TmVar.new(node.children.first, node)
90
+ when :lvasgn
91
+ parse_lvasgn(node, context)
92
+ when :gvar
93
+ parse_global_var(node, context)
94
+ when :gvasgn
95
+ parse_global_var_assign(node, context)
96
+ when :masgn
97
+ parse_mass_assign(node, context)
98
+ when :begin, :kwbegin
99
+ parse_begin(node, context)
100
+ when :rescue
101
+ parse_try(node, context)
102
+ when :resbody
103
+ parse_rescue(node, context)
104
+ when :int
105
+ TmInt.new(node)
106
+ when :array
107
+ parse_array_literal(node, context)
108
+ when :hash
109
+ parse_hash_literal(node, context)
110
+ when :true, :false
111
+ TmBoolean.new(node)
112
+ when :str
113
+ TmString.new(node)
114
+ when :float
115
+ TmFloat.new(node)
116
+ when :sym
117
+ TmSymbol.new(node)
118
+ when :regexp
119
+ parse_regexp(node, context)
120
+ when :if
121
+ parse_if_then_else(node, context)
122
+ when :case
123
+ parse_case_when(node, context)
124
+ when :block
125
+ parse_block(node, context)
126
+ when :send
127
+ parse_send(node, context)
128
+ when :yield
129
+ parse_yield(node, context)
130
+ when :const
131
+ TmConst.new(parse_const(node), node)
132
+ when :casgn
133
+ map(node.children.last, context)
134
+ when :sclass
135
+ parse_sclass(node, context)
136
+ when :dstr
137
+ parse_string_interpolation(node, context)
138
+ when :dsym
139
+ parse_symbol_interpolation(node, context)
140
+ when :return
141
+ parse_return(node, context)
142
+ when :self
143
+ parse_self(node, context)
144
+ when :or
145
+ parse_boolean_operation(:or, node, context)
146
+ when :and
147
+ parse_boolean_operation(:and, node, context)
148
+ when :block_pass
149
+ parse_block_pass(node, context)
150
+ when :or_asgn, :and_asgn
151
+ parse_boolean_asgn(node, context)
152
+ when :op_asgn
153
+ parse_op_asgn(node, context)
154
+ when :defined?
155
+ TmDefined.new(map(node.children.first, context), node)
156
+ when :zsuper
157
+ TmSuper.new(nil, node)
158
+ when :super
159
+ parse_super_with_args(node, context)
160
+ when :while, :while_post, :until, :until_post
161
+ parse_while(node, context)
162
+ when :for
163
+ parse_for(node, context)
164
+ when :irange, :erange
165
+ parse_range(node, context)
166
+ when :break
167
+ parse_break(node, context)
168
+ when :next
169
+ parse_next(node, context)
170
+ else
171
+ fail TermParsingError.new("Unknown term #{node.type}: #{node.to_sexp}", node)
172
+ end
173
+ end
174
+
175
+ def parse_super_with_args(node, context)
176
+ args = node.children.map { |arg_node| map(arg_node, context) }
177
+ TmSuper.new(args, node)
178
+ end
179
+
180
+ def parse_instance_var(node, _context)
181
+ TmInstanceVar.new(node.children.first, node)
182
+ end
183
+
184
+ def parse_instance_var_assign(node, context)
185
+ ivar = TmInstanceVar.new(node.children.first, node)
186
+ TmInstanceVarAssignment.new(ivar, map(node.children.last, context), node)
187
+ end
188
+
189
+ def parse_global_var(node, _context)
190
+ TmGlobalVar.new(node.children.first, node)
191
+ end
192
+
193
+ def parse_global_var_assign(node, context)
194
+ gvar = TmGlobalVar.new(node.children.first, node)
195
+ TmGlobalVarAssignment.new(gvar, map(node.children.last, context), node)
196
+ end
197
+
198
+ def parse_string_interpolation(node, context)
199
+ units = node.children.map { |child| map(child, context) }
200
+ TmStringInterpolation.new(units, node)
201
+ end
202
+
203
+ def parse_symbol_interpolation(node, context)
204
+ units = node.children.map { |child| map(child, context) }
205
+ TmSymbolInterpolation.new(units, node)
206
+ end
207
+
208
+ def parse_regexp(node, context)
209
+ # ignore the regular expression options
210
+ TmRegexp.new(map(node.children[0], context), nil, node)
211
+ end
212
+
213
+ def parse_block(node, context)
214
+ if node.children[0].type == :send && node.children[0].children[1] == :lambda
215
+ parse_lambda(node, context)
216
+ elsif node.children[0].type == :send && node.children[0].children[0] && node.children[0].children[0].children[1] == :Proc
217
+ parse_proc(node, context)
218
+ else
219
+ parse_send_block(node, context)
220
+ end
221
+ end
222
+
223
+ def parse_block_pass(node, context)
224
+ passed = if node.children.first.type == :sym
225
+ symbol = node.children.first.children.first
226
+ map(ast("Proc.new { |obj| obj.#{symbol} }"), context)
227
+ else
228
+ map(node.children.first, context)
229
+ end
230
+ [:block_pass, passed]
231
+ end
232
+
233
+ def parse_send_block(node, context)
234
+ block = parse_lambda(node, context)
235
+ send = parse_send(node.children[0], context)
236
+ send.with_block(block)
237
+ send
238
+ end
239
+
240
+ def parse_lambda(node, context)
241
+ args = node.children[1]
242
+ body = node.children[2]
243
+ if args.type != :args
244
+ fail Types::TypeParsingError.new("Error parsing function args [#{args}]", node)
245
+ end
246
+ args = parse_args(args.children, context, node)
247
+ body = map(body, context)
248
+
249
+ # TODO: deal with abs with a provided type, like block passed to typed functions.
250
+ TmAbs.new(args,
251
+ body,
252
+ :lambda, # no type for the lambda so far.
253
+ node)
254
+ end
255
+
256
+ def parse_proc(node, context)
257
+ args = node.children[1]
258
+ body = node.children[2]
259
+ if args.type != :args
260
+ fail Types::TypeParsingError.new("Error parsing function args [#{args}]", node)
261
+ end
262
+ args = parse_args(args.children, context, node)
263
+ body = map(body, context)
264
+
265
+ # TODO: deal with abs with a provided type, like block passed to typed functions.
266
+ TmAbs.new(args,
267
+ body,
268
+ :proc, # no type for the lambda so far.
269
+ node)
270
+ end
271
+
272
+ def parse_lvasgn(node, context)
273
+ lhs, rhs = node.children
274
+ TmLocalVarAsgn.new(lhs.to_s, map(rhs, context), node)
275
+ end
276
+
277
+ def parse_mass_assign(node, context)
278
+ # each children is a :lvasgn
279
+ lhs = node.children.first.children
280
+ rhs = map(node.children.last, context)
281
+ TmMassAsgn.new(lhs, rhs, node)
282
+ end
283
+
284
+ def parse_args(args, context, node)
285
+ args.map do |arg|
286
+ case arg.type
287
+ when :arg
288
+ [:arg, arg.children.last]
289
+ when :optarg
290
+ [:optarg, arg.children.first, map(arg.children.last, context)]
291
+ when :blockarg
292
+ [:blockarg, arg.children.first]
293
+ when :restarg
294
+ [:restarg, arg.children.last]
295
+ when :mlhs
296
+ [:mlhs, TmMlhs.new(arg.children.map { |n| n.children.last }, arg)]
297
+ else
298
+ fail Types::TypeParsingError.new("Unknown type of arg '#{arg.type}'", node)
299
+ end
300
+ end
301
+ end
302
+
303
+ def parse_send(node, context)
304
+ children = node.children
305
+ message = children[1]
306
+ if message == :ts_ignore
307
+ @ignore_node = true
308
+ return
309
+ end
310
+ receiver_node = children[0]
311
+ receiver = receiver_node.nil? ? receiver_node : map(receiver_node, context)
312
+ args = (children.drop(2) || []).map { |arg| map(arg, context) }
313
+ build_send_message(receiver, message, args, node, context)
314
+ end
315
+
316
+ def build_send_message(receiver, message, args, node, _context)
317
+ if message == :typesig
318
+ # ignore
319
+ else
320
+ if receiver.nil? && (message == :fail || message == :raise)
321
+ TmError.new(node)
322
+ else
323
+ if args.last.is_a?(Array) && args.last.first == :block_pass
324
+ block_pass = args.pop
325
+ tm_send = TmSend.new(receiver, message, args, node)
326
+ tm_send.with_block(block_pass.last)
327
+ tm_send
328
+ else
329
+ TmSend.new(receiver, message, args, node)
330
+ end
331
+ end
332
+ end
333
+ end
334
+
335
+ def parse_yield(node, context)
336
+ args = node.children
337
+ TmSend.new(nil, :yield, args.map { |arg| map(arg, context) }, node)
338
+ end
339
+
340
+ def parse_module(node, context)
341
+ module_name = parse_const(node.children[0])
342
+ context.with_type([:module, module_name]) do
343
+ module_body = map(node.children[1], context) if node.children[1]
344
+ TmModule.new(context.path_name, module_body, node)
345
+ end
346
+ end
347
+
348
+ def parse_class(node, context)
349
+ fail Types::TypeParsingError.new('Nil value parsing class') if node.nil? # No explicit class -> Object by default
350
+ class_name = parse_const(node.children[0])
351
+ super_class_name = parse_const(node.children[1]) || 'Object'
352
+ context.with_type([:class, class_name, super_class_name]) do
353
+ class_body = map(node.children[2], context) if node.children[2]
354
+ TmClass.new(context.path_name, super_class_name, class_body, node)
355
+ end
356
+ end
357
+
358
+ def parse_sclass(node, context)
359
+ class_name = if node.children[0].type == :self
360
+ :self
361
+ else
362
+ parse_const(node.children[0])
363
+ end
364
+ context.with_type([:self, class_name]) do
365
+ class_body = map(node.children[1], context)
366
+ TmSClass.new(class_name, class_body, node)
367
+ end
368
+ end
369
+
370
+ def parse_const(const_node, accum = [])
371
+ return nil if const_node.nil?
372
+ accum << const_node.children.last
373
+ if const_node.children.first.nil?
374
+ accum.reverse.join('::')
375
+ else
376
+ parse_const(const_node.children.first, accum)
377
+ end
378
+ end
379
+
380
+ def parse_def(node, context)
381
+ fun_name, args, body = node.children
382
+ owner = :self if context.singleton_class?
383
+ parse_fun(owner, fun_name, args, body, node, context)
384
+ end
385
+
386
+ def parse_defs(node, context)
387
+ owner, fun_name, args, body = node.children
388
+ parse_fun(owner, fun_name, args, body, node, context)
389
+ end
390
+
391
+ def parse_fun(owner, fun_name, args, body, node, context)
392
+ if args.type != :args
393
+ fail Types::TypeParsingError.new("Error parsing function args [#{args}]", node)
394
+ end
395
+ # parse the owner of the function
396
+ owner = if owner.nil? || owner == :self
397
+ owner
398
+ elsif owner.type == :const
399
+ TmConst.new(parse_const(owner), node)
400
+ elsif owner.type == :self
401
+ owner
402
+ else
403
+ map(owner, context)
404
+ end
405
+ tm_body = if body.nil?
406
+ TmNil.new(node)
407
+ else
408
+ map(body, context)
409
+ end
410
+ parsed_args = parse_args(args.children, context, node)
411
+ TmFun.new(owner, fun_name, parsed_args, tm_body, node)
412
+ end
413
+
414
+ def parse_if_then_else(node, context)
415
+ cond_expr, then_expr, else_expr = node.children
416
+ then_expr_term = then_expr.nil? ? then_expr : map(then_expr, context)
417
+ else_expr_term = else_expr.nil? ? else_expr : map(else_expr, context)
418
+ TmIfElse.new(node,
419
+ map(cond_expr, context),
420
+ then_expr_term,
421
+ else_expr_term)
422
+ end
423
+
424
+ def parse_case_when(node, context)
425
+ case_statement = map(node.children.first, context)
426
+ when_statements = node.children.drop(1).compact.select { |statement| statement.type == :when }
427
+ default_statement = node.children.drop(1).compact.reverse.find { |statement| statement.type != :when }
428
+ when_statements = when_statements.map do |statement|
429
+ [
430
+ statement,
431
+ map(statement.children[0], context),
432
+ map(statement.children[1], context)
433
+ ]
434
+ end
435
+ default_statement = map(default_statement, context) if default_statement
436
+ TmCaseWhen.new(node, case_statement, when_statements, default_statement)
437
+ end
438
+
439
+ def parse_while(node, context)
440
+ condition, body = node.children
441
+ condition_expr = map(condition, context)
442
+ body_expr = body ? map(body, context) : nil
443
+ TmWhile.new(condition_expr, body_expr, node)
444
+ end
445
+
446
+ def parse_for(node, context)
447
+ lhs, rhs, body = node.children
448
+ lhs_chilren = []
449
+ lhs.children.each do |child|
450
+ lhs_chilren << child
451
+ end
452
+ lhs_chilren << RewrittenWrapper.new(TmSend.new(TmSend.new(map(rhs, context),:each, [], node), :next, [], node))
453
+
454
+ lhs_wrapped = AssignationWrapper.new(lhs, lhs_chilren)
455
+ TmFor.new(map(lhs_wrapped, context), map(body, context), node)
456
+ end
457
+
458
+ def parse_begin(node, context)
459
+ mapped = node.children.map do |child_node|
460
+ map(child_node, context)
461
+ end
462
+ sequencing = TmSequencing.new(mapped, node)
463
+ if sequencing.terms.size == 1
464
+ sequencing.terms.first
465
+ else
466
+ sequencing
467
+ end
468
+ end
469
+
470
+ def parse_try(node, context)
471
+ try_term = map(node.children.first, context)
472
+ rescue_terms = node.children.drop(1).compact.map { |term| map(term, context) }
473
+ TmTry.new(try_term, rescue_terms, node)
474
+ end
475
+
476
+ def parse_rescue(node, context)
477
+ catched_types = if node.children[0].nil?
478
+ []
479
+ else
480
+ node.children[0].children.map do |node|
481
+ map(node, context)
482
+ end
483
+ end
484
+ assigned_exception = node.children[1].nil? ? nil : node.children[1].children[0]
485
+
486
+ rescue_body = node.children[2].nil? ? nil : map(node.children[2], context)
487
+ TmRescue.new(catched_types, assigned_exception, rescue_body)
488
+ end
489
+
490
+ def parse_array_literal(node, context)
491
+ TmArrayLiteral.new(node.children.map do |child|
492
+ map(child, context)
493
+ end, node)
494
+ end
495
+
496
+ def parse_hash_literal(node, context)
497
+ pairs = node.children.map do |pair|
498
+ [map(pair.children.first, context), map(pair.children.last, context)]
499
+ end
500
+ TmHashLiteral.new(pairs, node)
501
+ end
502
+
503
+ def parse_range(node, context)
504
+ start_range = map(node.children.first, context)
505
+ end_range = map(node.children.last, context)
506
+ TmRangeLiteral.new(start_range, end_range, node)
507
+ end
508
+
509
+ def parse_return(node, context)
510
+ elements = node.children.map { |element| map(element, context) }
511
+ TmReturn.new(elements, node)
512
+ end
513
+
514
+ def parse_break(node, context)
515
+ elements = node.children.map { |element| map(element, context) }
516
+ TmBreak.new(elements, node)
517
+ end
518
+
519
+ def parse_next(node, context)
520
+ elements = node.children.map { |element| map(element, context) }
521
+ TmNext.new(elements, node)
522
+ end
523
+
524
+ def parse_self(node, _context)
525
+ TmSelf.new(node)
526
+ end
527
+
528
+ def parse_boolean_operation(operation, node, context)
529
+ TmBooleanOperator.new(operation,
530
+ map(node.children.first, context),
531
+ map(node.children.last, context),
532
+ node)
533
+ end
534
+
535
+ def parse_boolean_asgn(node, context)
536
+ lhs = node.children.first
537
+ rhs = map(node.children.last, context)
538
+ case lhs.type
539
+ when :ivasgn
540
+ ivar = TmInstanceVar.new(lhs.children.first, lhs)
541
+ TmBooleanOperator.new(:or, ivar, TmInstanceVarAssignment.new(ivar, rhs, node), node)
542
+ when :gvasgn
543
+ gvar = TmGlobalVar.new(lhs.children.first, lhs)
544
+ TmBooleanOperator.new(:or, gvar, TmGlobalVarAssignment.new(gvar, rhs, node), node)
545
+ when :lvasgn
546
+ TmLocalVarAsgn.new(lhs.children.first.to_s, rhs, node)
547
+ when :send
548
+ receiver = map(lhs.children.first, context)
549
+ message = lhs.children.last
550
+ attr_reader = build_send_message(receiver, message, [], lhs, context)
551
+ attr_writer = build_send_message(receiver, "#{message}=", [rhs], lhs, context)
552
+ TmBooleanOperator.new(:or, attr_reader, attr_writer, node)
553
+ end
554
+ end
555
+
556
+ def parse_op_asgn(node, context)
557
+ lvalue, message, arg_expr = node.children
558
+ lreceiver = lvalue.children.first
559
+ arg = map(arg_expr, context)
560
+ rvalue = case lvalue.type
561
+ when :lvasgn
562
+ TmSend.new(TmVar.new(lreceiver, lvalue),
563
+ message, [arg], node)
564
+ when :ivasgn
565
+ TmSend.new(TmInstanceVar.new(lreceiver, lvalue),
566
+ message, [arg], node)
567
+ when :gvasgn
568
+ TmSend.new(TmGlobalVar.new(lreceiver, lvalue),
569
+ message, [arg], node)
570
+ when :casgn
571
+ constant_name = parse_const(lvalue)
572
+ return TmSend.new(TmConst.new(constant_name, lvalue), message, [arg], node)
573
+ when :send
574
+ return TmSend.new(map(lvalue, context), message, [arg], node)
575
+ else
576
+ fail Types::TypeParsingError.new("Unknown += operator application for node '#{lvalue.type}'", node)
577
+ end
578
+
579
+ case lvalue.type
580
+ when :lvasgn
581
+ TmLocalVarAsgn.new(lvalue, rvalue, node)
582
+ when :ivasgn
583
+ TmInstanceVarAssignment.new(TmInstanceVar.new(lreceiver, lvalue), rvalue, node)
584
+ when :gvasgn
585
+ TmGlobalVarAssignment.new(TmGlobalVar.new(lreceiver, lvalue), rvalue, node)
586
+ end
587
+ end
588
+ end
589
+ end
@@ -0,0 +1,72 @@
1
+ module TypedRb
2
+ module Runtime
3
+ class MethodSignatureProcessor
4
+ class << self
5
+ def process(full_signature, base_object)
6
+ kind, receiver, message, type_signature = destruct_signature(full_signature)
7
+ receiver = parse_implicit_receiver(base_object) if receiver.empty?
8
+ message, method_type_variables = parse_method_type_variable(message)
9
+
10
+ type_ast = ::TypedRb::TypeSignature::Parser.parse(type_signature, method_type_variables)
11
+ BasicObject::TypeRegistry.register_type_information(kind, receiver, message, type_ast)
12
+ end
13
+
14
+ private
15
+
16
+ def destruct_signature(full_signature)
17
+ parts = full_signature.split(%r{\s*/\s*})
18
+ type_signature = parts.pop
19
+ receiver_and_message = parts.join('/')
20
+ if receiver_and_message.index('#')
21
+ kind = :instance
22
+ receiver, message = receiver_and_message.split('#')
23
+ elsif receiver_and_message.index('.')
24
+ kind = :class
25
+ receiver, message = receiver_and_message.split('.')
26
+ else
27
+ fail ::TypedRb::Types::TypeParsingError, "Error parsing receiver, method type_signature: #{full_signature}"
28
+ end
29
+ kind = :"#{kind}_variable" if message.index('@')
30
+ [kind, receiver, message, type_signature]
31
+ end
32
+
33
+ def parse_implicit_receiver(base_object)
34
+ return 'main' if top_level?(base_object)
35
+ return parse_class_implicit_receiver(base_object) if class_or_module?(base_object)
36
+ base_object.class.name # instance object
37
+ end
38
+
39
+ def top_level?(base_object)
40
+ base_object.object_id == ::TOPLEVEL_BINDING.receiver.object_id
41
+ end
42
+
43
+ def class_or_module?(base_object)
44
+ base_object.instance_of?(::Class) || base_object.instance_of?(::Module)
45
+ end
46
+
47
+ def parse_class_implicit_receiver(base_object)
48
+ if base_object.name.nil?
49
+ # singleton classes
50
+ base_object.to_s.match(/Class:(.*)>/)[1]
51
+ else
52
+ base_object.name
53
+ end
54
+ end
55
+
56
+ def parse_method_type_variable(message)
57
+ type_variables = message.scan(/(\[\w+(\s*[<>]\s*\w+)?\])/).map(&:first).map do |var|
58
+ ::TypedRb::TypeSignature::Parser.parse(var)
59
+ end
60
+ message = message.split(/\[[\w]+/).first
61
+
62
+ method_type_var_info = type_variables.each_with_object(::Hash.call(::String, 'Hash[Symbol][String]').new) do |variable, acc|
63
+ var_name = variable[:type]
64
+ variable[:type] = "#{message}:#{var_name}"
65
+ acc[var_name] = variable
66
+ end
67
+ [message, method_type_var_info]
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end