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
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