syntax: add PExpr:is_typed and PExpr::is_statement
[nit.git] / src / syntax / typing.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Analysis property bodies, statements and expressions
18 package typing
19
20 import syntax_base
21 import escape
22
23 redef class MMSrcModule
24 # Walk trough the module and type statments and expressions
25 # Require than supermodules are processed
26 meth do_typing(tc: ToolContext)
27 do
28 var tv = new TypingVisitor(tc, self)
29 tv.visit(node)
30 end
31 end
32
33 # Typing visitor
34 # * Associate local variables to nodes
35 # * Distinguish method call and local variable access
36 # * Resolve call and attribute access
37 # * Check type conformance
38 private class TypingVisitor
39 special AbsSyntaxVisitor
40 redef meth visit(n)
41 do
42 if n != null then n.accept_typing(self)
43 end
44
45 # Current knowledge about variables names and types
46 readable writable attr _variable_ctx: VariableContext
47
48 # Current knowledge about escapable blocks
49 readable writable attr _escapable_ctx: EscapableContext = new EscapableContext(self)
50
51 # The current reciever
52 readable writable attr _self_var: ParamVariable
53
54 # Block of the current method
55 readable writable attr _top_block: PExpr
56
57 # List of explicit invocation of constructors of super-classes
58 readable writable attr _explicit_super_init_calls: Array[MMMethod]
59
60 # Is a other constructor of the same class invoked
61 readable writable attr _explicit_other_init_call: Bool
62
63 # Make the if_true_variable_ctx of the expression effective
64 private meth use_if_true_variable_ctx(e: PExpr)
65 do
66 var ctx = e.if_true_variable_ctx
67 if ctx != null then
68 variable_ctx = ctx
69 end
70 end
71
72 init(tc, module) do super
73
74 private meth get_default_constructor_for(n: PNode, c: MMLocalClass, prop: MMSrcMethod): MMMethod
75 do
76 var v = self
77 #var prop = v.local_property
78 #assert prop isa MMMethod
79 var candidates = new Array[MMMethod]
80 var false_candidates = new Array[MMMethod]
81 var parity = prop.signature.arity
82 for g in c.global_properties do
83 if not g.is_init_for(c) then continue
84 var gp = c[g]
85 var gps = gp.signature_for(c.get_type)
86 assert gp isa MMSrcMethod
87 var garity = gps.arity
88 if prop != null and gp.name == prop.name then
89 if garity == 0 or (parity == garity and prop.signature < gps) then
90 return gp
91 else
92 false_candidates.add(gp)
93 end
94 else if garity == 0 and gp.name == once ("init".to_symbol) then
95 candidates.add(gp)
96 false_candidates.add(gp)
97 else
98 false_candidates.add(gp)
99 end
100 end
101 if candidates.length == 1 then
102 return candidates.first
103 else if candidates.length > 0 then
104 var a = new Array[String]
105 for p in candidates do
106 a.add("{p.full_name}{p.signature}")
107 end
108 v.error(n, "Error: Conflicting default constructor to call for {c}: {a.join(", ")}.")
109 return null
110 else if false_candidates.length > 0 then
111 var a = new Array[String]
112 for p in false_candidates do
113 a.add("{p.full_name}{p.signature}")
114 end
115 v.error(n, "Error: there is no available compatible constrctor in {c}. Discarded candidates are {a.join(", ")}.")
116 return null
117 else
118 v.error(n, "Error: there is no available compatible constrctor in {c}.")
119 return null
120 end
121 end
122 end
123
124 # Associate symbols to variable and variables to type
125 # Can be nested
126 private class VariableContext
127 # Look for the variable from its name
128 # Return null if nothing found
129 meth [](s: Symbol): Variable
130 do
131 if _dico.has_key(s) then
132 return _dico[s]
133 else
134 return null
135 end
136 end
137
138 # Register a new variable with its name
139 meth add(v: Variable)
140 do
141 _dico[v.name] = v
142 end
143
144
145 # The effective static type of a given variable
146 # May be different from the declaration static type
147 meth stype(v: Variable): MMType
148 do
149 return v.stype
150 end
151
152 # Variables by name (in the current context only)
153 attr _dico: Map[Symbol, Variable]
154
155 # Build a new VariableContext
156 meth sub: SubVariableContext
157 do
158 return new SubVariableContext.with_prev(self)
159 end
160
161 # Build a nested VariableContext with new variable information
162 meth sub_with(v: Variable, t: MMType): SubVariableContext
163 do
164 return new CastVariableContext.with_prev(self, v, t)
165 end
166
167 init
168 do
169 _dico = new HashMap[Symbol, Variable]
170 end
171 end
172
173 private class SubVariableContext
174 special VariableContext
175 readable attr _prev: VariableContext
176
177 redef meth [](s)
178 do
179 if _dico.has_key(s) then
180 return _dico[s]
181 else
182 return prev[s]
183 end
184 end
185
186 redef meth stype(v)
187 do
188 return prev.stype(v)
189 end
190
191 init with_prev(p: VariableContext)
192 do
193 init
194 _prev = p
195 end
196 end
197
198 private class CastVariableContext
199 special SubVariableContext
200 attr _variable: Variable
201 attr _var_type: MMType
202
203 redef meth stype(v)
204 do
205 if _variable == v then
206 return _var_type
207 end
208 return prev.stype(v)
209 end
210
211 init with_prev(p: VariableContext, v: Variable, t: MMType)
212 do
213 super(p)
214 _variable = v
215 _var_type =t
216 end
217 end
218
219 ###############################################################################
220
221 redef class PNode
222 private meth accept_typing(v: TypingVisitor)
223 do
224 accept_abs_syntax_visitor(v)
225 after_typing(v)
226 end
227 private meth after_typing(v: TypingVisitor) do end
228 end
229
230 redef class PClassdef
231 redef meth accept_typing(v)
232 do
233 v.self_var = new ParamVariable("self".to_symbol, self)
234 v.self_var.stype = local_class.get_type
235 super
236 end
237 end
238
239 redef class AAttrPropdef
240 redef meth accept_typing(v)
241 do
242 super
243 if n_expr != null then
244 v.check_conform_expr(n_expr, prop.signature.return_type)
245 end
246 end
247 end
248
249 redef class AMethPropdef
250 redef readable attr _self_var: ParamVariable
251 redef meth accept_typing(v)
252 do
253 v.variable_ctx = new VariableContext
254 _self_var = v.self_var
255 super
256 end
257 end
258
259 redef class AConcreteInitPropdef
260 readable attr _super_init_calls: Array[MMMethod] = new Array[MMMethod]
261 readable attr _explicit_super_init_calls: Array[MMMethod] = new Array[MMMethod]
262 redef meth accept_typing(v)
263 do
264 v.top_block = n_block
265 v.explicit_super_init_calls = explicit_super_init_calls
266 v.explicit_other_init_call = false
267 super
268 if v.explicit_other_init_call or method.global.intro != method then
269 # TODO: something?
270 else
271 var i = 0
272 var l = explicit_super_init_calls.length
273 var cur_m: MMMethod = null
274 var cur_c: MMLocalClass = null
275 if i < l then
276 cur_m = explicit_super_init_calls[i]
277 cur_c = cur_m.global.intro.local_class.for_module(v.module)
278 end
279 var j = 0
280 while j < v.local_class.cshe.direct_greaters.length do
281 var c = v.local_class.cshe.direct_greaters[j]
282 if c.global.is_interface or c.global.is_universal or c.global.is_mixin then
283 j += 1
284 else if cur_c != null and (c.cshe <= cur_c or cur_c.global.is_mixin) then
285 if c == cur_c then j += 1
286 super_init_calls.add(cur_m)
287 i += 1
288 if i < l then
289 cur_m = explicit_super_init_calls[i]
290 cur_c = cur_m.global.intro.local_class.for_module(v.module)
291 else
292 cur_m = null
293 cur_c = null
294 end
295 else
296 var p = v.get_default_constructor_for(self, c, method)
297 if p != null then
298 super_init_calls.add(p)
299 end
300 j += 1
301 end
302 end
303 end
304 end
305 end
306
307 redef class PParam
308 redef meth after_typing(v)
309 do
310 # TODO: why the test?
311 if v.variable_ctx != null then
312 v.variable_ctx.add(variable)
313 end
314 end
315 end
316
317 redef class AClosureDecl
318 # The corresponding escapable object
319 readable attr _escapable: EscapableBlock
320
321 redef meth accept_typing(v)
322 do
323 # Register the closure for ClosureCallExpr
324 v.variable_ctx.add(variable)
325
326 var old_var_ctx = v.variable_ctx
327 v.variable_ctx = v.variable_ctx.sub
328
329 _escapable = new EscapableClosure(self, variable.closure, null)
330 v.escapable_ctx.push(_escapable)
331
332 super
333
334 v.variable_ctx = old_var_ctx
335 v.escapable_ctx.pop
336 end
337 end
338
339 redef class PType
340 readable attr _stype: MMType
341 redef meth after_typing(v)
342 do
343 _stype = get_stype(v)
344 end
345 end
346
347 redef class PExpr
348 redef readable attr _is_typed: Bool = true # FIXME: Switch to false once subclasses are adapted
349 redef meth is_statement: Bool do return _stype == null
350 redef meth stype
351 do
352 return _stype
353 end
354 attr _stype: MMType
355
356 # Is the expression the implicit receiver
357 meth is_implicit_self: Bool do return false
358
359 # Is the expression the current receiver (implicit or explicit)
360 meth is_self: Bool do return false
361
362 # The variable accessed is any
363 meth its_variable: Variable do return null
364
365 # The variable type information if current boolean expression is true
366 readable private attr _if_true_variable_ctx: VariableContext
367 end
368
369 redef class AVardeclExpr
370 redef meth after_typing(v)
371 do
372 var va = new VarVariable(n_id.to_symbol, self)
373 variable = va
374 v.variable_ctx.add(va)
375
376 if n_type != null then
377 va.stype = n_type.stype
378 if n_expr != null then
379 v.check_conform_expr(n_expr, va.stype)
380 end
381 else
382 v.check_expr(n_expr)
383 va.stype = n_expr.stype
384 end
385 end
386 end
387
388 redef class ABlockExpr
389 redef meth accept_typing(v)
390 do
391 var old_var_ctx = v.variable_ctx
392 v.variable_ctx = v.variable_ctx.sub
393
394 super
395
396 v.variable_ctx = old_var_ctx
397 end
398 end
399
400 redef class AReturnExpr
401 redef meth after_typing(v)
402 do
403 var t = v.local_property.signature.return_type
404 if n_expr == null and t != null then
405 v.error(self, "Error: Return without value in a function.")
406 else if n_expr != null and t == null then
407 v.error(self, "Error: Return with value in a procedure.")
408 else if n_expr != null and t != null then
409 v.check_conform_expr(n_expr, t)
410 end
411 end
412 end
413
414 redef class AContinueExpr
415 redef meth after_typing(v)
416 do
417 var esc = compute_escapable_block(v.escapable_ctx)
418 if esc == null then return
419
420 if esc.is_break_block then
421 v.error(self, "Error: 'continue' forbiden in break blocks.")
422 return
423 end
424
425 var t = esc.continue_stype
426 if n_expr == null and t != null then
427 v.error(self, "Error: continue with a value required in this block.")
428 else if n_expr != null and t == null then
429 v.error(self, "Error: continue without value required in this block.")
430 else if n_expr != null and t != null then
431 v.check_conform_expr(n_expr, t)
432 end
433 end
434 end
435
436 redef class ABreakExpr
437 redef meth after_typing(v)
438 do
439 var esc = compute_escapable_block(v.escapable_ctx)
440 if esc == null then return
441
442 var bl = esc.break_list
443 if n_expr == null and bl != null then
444 v.error(self, "Error: break with a value required in this block.")
445 else if n_expr != null and bl == null then
446 v.error(self, "Error: break without value required in this block.")
447 else if n_expr != null and bl != null then
448 # Typing check can only be done later
449 bl.add(n_expr)
450 end
451 end
452 end
453
454 redef class AIfExpr
455 redef meth accept_typing(v)
456 do
457 var old_var_ctx = v.variable_ctx
458 v.visit(n_expr)
459 v.check_conform_expr(n_expr, v.type_bool)
460
461 v.use_if_true_variable_ctx(n_expr)
462
463 v.visit(n_then)
464 # Restore variable ctx
465 v.variable_ctx = old_var_ctx
466
467 if n_else != null then
468 v.visit(n_else)
469 v.variable_ctx = old_var_ctx
470 end
471 end
472 end
473
474 redef class AWhileExpr
475 # The corresponding escapable block
476 readable attr _escapable: EscapableBlock
477
478 redef meth accept_typing(v)
479 do
480 _escapable = new EscapableBlock(self)
481 v.escapable_ctx.push(_escapable)
482
483 super
484
485 v.check_conform_expr(n_expr, v.type_bool)
486 v.escapable_ctx.pop
487 end
488 end
489
490 redef class AForExpr
491 # The corresponding escapable block
492 readable attr _escapable: EscapableBlock
493
494 readable attr _meth_iterator: MMMethod
495 readable attr _meth_is_ok: MMMethod
496 readable attr _meth_item: MMMethod
497 readable attr _meth_next: MMMethod
498 redef meth accept_typing(v)
499 do
500 _escapable = new EscapableBlock(self)
501 v.escapable_ctx.push(_escapable)
502
503 v.variable_ctx = v.variable_ctx.sub
504 var va = new AutoVariable(n_id.to_symbol, self)
505 variable = va
506 v.variable_ctx.add(va)
507
508 v.visit(n_expr)
509
510 var expr_type = n_expr.stype
511 if not v.check_conform_expr(n_expr, v.type_collection) then
512 return
513 end
514 _meth_iterator = expr_type.local_class.select_method(once ("iterator".to_symbol))
515 if _meth_iterator == null then
516 v.error(self, "Error: Collection MUST have an iterate method")
517 return
518 end
519 var iter_type = _meth_iterator.signature_for(expr_type).return_type
520 _meth_is_ok = iter_type.local_class.select_method(once ("is_ok".to_symbol))
521 if _meth_is_ok == null then
522 v.error(self, "Error: {iter_type} MUST have an is_ok method")
523 return
524 end
525 _meth_item = iter_type.local_class.select_method(once ("item".to_symbol))
526 if _meth_item == null then
527 v.error(self, "Error: {iter_type} MUST have an item method")
528 return
529 end
530 _meth_next = iter_type.local_class.select_method(once ("next".to_symbol))
531 if _meth_next == null then
532 v.error(self, "Error: {iter_type} MUST have a next method")
533 return
534 end
535 var t = _meth_item.signature_for(iter_type).return_type
536 if not n_expr.is_self then t = t.not_for_self
537 va.stype = t
538
539 if n_block != null then v.visit(n_block)
540
541 # pop context
542 var varctx = v.variable_ctx
543 assert varctx isa SubVariableContext
544 v.variable_ctx = varctx.prev
545
546 v.escapable_ctx.pop
547 end
548 end
549
550 redef class AAssertExpr
551 redef meth after_typing(v)
552 do
553 v.check_conform_expr(n_expr, v.type_bool)
554 v.use_if_true_variable_ctx(n_expr)
555 end
556 end
557
558 redef class AVarExpr
559 redef meth its_variable do return variable
560
561 redef meth after_typing(v)
562 do
563 _stype = v.variable_ctx.stype(variable)
564 end
565 end
566
567 redef class AVarAssignExpr
568 redef meth after_typing(v)
569 do
570 var t = v.variable_ctx.stype(variable)
571 v.check_conform_expr(n_value, t)
572 end
573 end
574
575 redef class AReassignFormExpr
576 # Compute and check method used through the reassigment operator
577 private meth do_lvalue_typing(v: TypingVisitor, type_lvalue: MMType)
578 do
579 if type_lvalue == null then
580 return
581 end
582 var name = n_assign_op.method_name
583 var lc = type_lvalue.local_class
584 if not lc.has_global_property_by_name(name) then
585 v.error(self, "Error: Method '{name}' doesn't exists in {type_lvalue}.")
586 return
587 end
588 var prop = lc.select_method(name)
589 prop.global.check_visibility(v, self, v.module, false)
590 var psig = prop.signature_for(type_lvalue)
591 _assign_method = prop
592 v.check_conform_expr(n_value, psig[0].not_for_self)
593 v.check_conform(self, psig.return_type.not_for_self, n_value.stype)
594 end
595
596 # Method used through the reassigment operator (once computed)
597 readable attr _assign_method: MMMethod
598 end
599
600 redef class AVarReassignExpr
601 redef meth after_typing(v)
602 do
603 var t = v.variable_ctx.stype(variable)
604 do_lvalue_typing(v, t)
605 end
606 end
607
608 redef class PAssignOp
609 meth method_name: Symbol is abstract
610 end
611 redef class APlusAssignOp
612 redef meth method_name do return once "+".to_symbol
613 end
614 redef class AMinusAssignOp
615 redef meth method_name do return once "-".to_symbol
616 end
617
618 redef class ASelfExpr
619 redef meth its_variable do return variable
620
621 redef meth after_typing(v)
622 do
623 variable = v.self_var
624 _stype = v.variable_ctx.stype(variable)
625 end
626
627 redef meth is_self do return true
628 end
629
630 redef class AImplicitSelfExpr
631 redef meth is_implicit_self do return true
632 end
633
634 redef class AIfexprExpr
635 redef meth accept_typing(v)
636 do
637 var old_var_ctx = v.variable_ctx
638
639 v.visit(n_expr)
640 v.use_if_true_variable_ctx(n_expr)
641 v.visit(n_then)
642 v.variable_ctx = old_var_ctx
643 v.visit(n_else)
644
645 v.check_conform_expr(n_expr, v.type_bool)
646
647 _stype = v.check_conform_multiexpr(null, [n_then, n_else])
648 end
649 end
650
651 redef class ABoolExpr
652 redef meth after_typing(v)
653 do
654 _stype = v.type_bool
655 end
656 end
657
658 redef class AOrExpr
659 redef meth after_typing(v)
660 do
661 v.check_conform_expr(n_expr, v.type_bool)
662 v.check_conform_expr(n_expr2, v.type_bool)
663 _stype = v.type_bool
664 end
665 end
666
667 redef class AAndExpr
668 redef meth accept_typing(v)
669 do
670 var old_var_ctx = v.variable_ctx
671
672 v.visit(n_expr)
673 v.use_if_true_variable_ctx(n_expr)
674
675 v.visit(n_expr2)
676 if n_expr2.if_true_variable_ctx != null then
677 _if_true_variable_ctx = n_expr2.if_true_variable_ctx
678 else
679 _if_true_variable_ctx = v.variable_ctx
680 end
681
682 v.variable_ctx = old_var_ctx
683
684 v.check_conform_expr(n_expr, v.type_bool)
685 v.check_conform_expr(n_expr2, v.type_bool)
686 _stype = v.type_bool
687 end
688 end
689
690 redef class ANotExpr
691 redef meth after_typing(v)
692 do
693 v.check_conform_expr(n_expr, v.type_bool)
694 _stype = v.type_bool
695 end
696 end
697
698 redef class AIntExpr
699 redef meth after_typing(v)
700 do
701 _stype = v.type_int
702
703 end
704 end
705
706 redef class AFloatExpr
707 redef meth after_typing(v)
708 do
709 _stype = v.type_float
710 end
711 end
712
713 redef class ACharExpr
714 redef meth after_typing(v)
715 do
716 _stype = v.type_char
717 end
718 end
719
720 redef class AStringFormExpr
721 readable attr _meth_with_native: MMMethod
722 redef meth after_typing(v)
723 do
724 _stype = v.type_string
725 _meth_with_native = _stype.local_class.select_method(once "with_native".to_symbol)
726 if _meth_with_native == null then v.error(self, "{_stype} MUST have a with_native method.")
727 end
728 end
729
730 redef class ASuperstringExpr
731 readable attr _meth_with_capacity: MMMethod
732 readable attr _meth_add: MMMethod
733 readable attr _meth_to_s: MMMethod
734 readable attr _atype: MMType
735 redef meth after_typing(v)
736 do
737 _stype = v.type_string
738 _atype = v.type_array(_stype)
739 _meth_with_capacity = _atype.local_class.select_method(once "with_capacity".to_symbol)
740 if _meth_with_capacity == null then v.error(self, "{_atype} MUST have a with_capacity method.")
741 _meth_add = _atype.local_class.select_method(once "add".to_symbol)
742 if _meth_add == null then v.error(self, "{_atype} MUST have an add method.")
743 _meth_to_s = v.type_object.local_class.select_method(once "to_s".to_symbol)
744 if _meth_to_s == null then v.error(self, "Object MUST have a to_s method.")
745 end
746 end
747
748 redef class ANullExpr
749 redef meth after_typing(v)
750 do
751 _stype = v.type_none
752 end
753 end
754
755 redef class AArrayExpr
756 readable attr _meth_with_capacity: MMMethod
757 readable attr _meth_add: MMMethod
758
759 redef meth after_typing(v)
760 do
761 var stype = v.check_conform_multiexpr(null, n_exprs)
762 if stype == null then return
763 do_typing(v, stype)
764 end
765
766 private meth do_typing(v: TypingVisitor, element_type: MMType)
767 do
768 _stype = v.type_array(element_type)
769
770 _meth_with_capacity = _stype.local_class.select_method(once "with_capacity".to_symbol)
771 if _meth_with_capacity == null then v.error(self, "{_stype} MUST have a with_capacity method.")
772 _meth_add = _stype.local_class.select_method(once "add".to_symbol)
773 if _meth_add == null then v.error(self, "{_stype} MUST have an add method.")
774 end
775 end
776
777 redef class ARangeExpr
778 readable attr _meth_init: MMMethod
779 redef meth after_typing(v)
780 do
781 var ntype = n_expr.stype
782 var ntype2 = n_expr2.stype
783 if ntype == null or ntype == null then
784 return
785 end
786 if ntype < ntype2 then
787 ntype = ntype2
788 else if not ntype2 < ntype then
789 v.error(self, "Type error: {ntype} incompatible with {ntype2}.")
790 return
791 end
792 var dtype = v.type_discrete
793 v.check_conform_expr(n_expr, dtype)
794 v.check_conform_expr(n_expr2, dtype)
795 _stype = v.type_range(ntype)
796 end
797 end
798
799 redef class ACrangeExpr
800 redef meth after_typing(v)
801 do
802 super
803 _meth_init = stype.local_class.select_method(once "init".to_symbol)
804 end
805 end
806 redef class AOrangeExpr
807 redef meth after_typing(v)
808 do
809 super
810 _meth_init = stype.local_class.select_method(once "without_last".to_symbol)
811 end
812 end
813
814
815 redef class ASuperExpr
816 special ASuperInitCall
817 # readable attr _prop: MMSrcMethod
818 readable attr _init_in_superclass: MMMethod
819 redef meth after_typing(v)
820 do
821 var precs: Array[MMLocalProperty] = v.local_property.prhe.direct_greaters
822 if not precs.is_empty then
823 v.local_property.need_super = true
824 else if v.local_property.global.is_init then
825 var base_precs = v.local_class.super_methods_named(v.local_property.name)
826 for p in base_precs do
827 if not p.global.is_init then
828 v.error(self, "Error: {p.local_class}::{p} is not a constructor.")
829 else
830 precs.add(v.local_class[p.global])
831 end
832 end
833 if precs.is_empty then
834 v.error(self, "Error: No contructor named {v.local_property.name} in superclasses.")
835 return
836 else if precs.length > 1 then
837 v.error(self, "Error: Conflicting contructors named {v.local_property.name} in superclasses: {precs.join(", ")}.")
838 return
839 end
840 var p = base_precs.first
841 assert p isa MMMethod
842 _init_in_superclass = p
843 register_super_init_call(v, p)
844 if n_args.length > 0 then
845 var signature = get_signature(v, v.self_var.stype, p, true)
846 _arguments = process_signature(v, signature, p.name, n_args.to_a)
847 end
848 else
849 v.error(self, "Error: No super method to call for {v.local_property}.")
850 return
851 end
852
853 if precs.first.signature_for(v.self_var.stype).return_type != null then
854 var stypes = new Array[MMType]
855 var stype: MMType = null
856 for prop in precs do
857 assert prop isa MMMethod
858 var t = prop.signature_for(v.self_var.stype).return_type.for_module(v.module).adapt_to(v.local_property.signature.recv)
859 stypes.add(t)
860 if stype == null or stype < t then
861 stype = t
862 end
863 end
864 for t in stypes do
865 v.check_conform(self, t, stype)
866 end
867 _stype = stype
868 end
869 var p = v.local_property
870 assert p isa MMSrcMethod
871 _prop = p
872 end
873 end
874
875 redef class AAttrFormExpr
876 # Attribute accessed
877 readable attr _prop: MMAttribute
878
879 # Attribute type of the acceded attribute
880 readable attr _attr_type: MMType
881
882 # Compute the attribute accessed
883 private meth do_typing(v: TypingVisitor)
884 do
885 if not v.check_expr(n_expr) then return
886 var type_recv = n_expr.stype
887 var name = n_id.to_symbol
888 var lc = type_recv.local_class
889 if not lc.has_global_property_by_name(name) then
890 v.error(self, "Error: Attribute {name} doesn't exists in {type_recv}.")
891 return
892 end
893 var prop = lc.select_attribute(name)
894 if v.module.visibility_for(prop.global.local_class.module) < 3 then
895 v.error(self, "Error: Attribute {name} from {prop.global.local_class.module} is invisible in {v.module}")
896 end
897 _prop = prop
898 var at = prop.signature_for(type_recv).return_type
899 if not n_expr.is_self then at = at.not_for_self
900 _attr_type = at
901 end
902 end
903
904 redef class AAttrExpr
905 redef meth after_typing(v)
906 do
907 do_typing(v)
908 if prop == null then
909 return
910 end
911 _stype = attr_type
912 end
913 end
914
915 redef class AAttrAssignExpr
916 redef meth after_typing(v)
917 do
918 do_typing(v)
919 if prop == null then
920 return
921 end
922 v.check_conform_expr(n_value, attr_type)
923 end
924 end
925
926 redef class AAttrReassignExpr
927 redef meth after_typing(v)
928 do
929 do_typing(v)
930 if prop == null then
931 return
932 end
933 do_lvalue_typing(v, attr_type)
934 end
935 end
936
937 class AAbsAbsSendExpr
938 special PExpr
939 # The signature of the called property
940 readable attr _prop_signature: MMSignature
941
942 # The real arguments used (after star transformation) (once computed)
943 readable attr _arguments: Array[PExpr]
944
945 # Check the conformity of a set of arguments `raw_args' to a signature.
946 private meth process_signature(v: TypingVisitor, psig: MMSignature, name: Symbol, raw_args: Array[PExpr]): Array[PExpr]
947 do
948 var par_vararg = psig.vararg_rank
949 var par_arity = psig.arity
950 var raw_arity: Int
951 if raw_args == null then raw_arity = 0 else raw_arity = raw_args.length
952 if par_arity > raw_arity or (par_arity != raw_arity and par_vararg == -1) then
953 v.error(self, "Error: '{name}' arity missmatch.")
954 return null
955 end
956 var arg_idx = 0
957 var args = new Array[PExpr]
958 for par_idx in [0..par_arity[ do
959 var a: PExpr
960 var par_type = psig[par_idx]
961 if par_idx == par_vararg then
962 var star = new Array[PExpr]
963 for i in [0..(raw_arity-par_arity)] do
964 a = raw_args[arg_idx]
965 v.check_conform_expr(a, par_type)
966 star.add(a)
967 arg_idx = arg_idx + 1
968 end
969 var aa = new AArrayExpr.init_aarrayexpr(star)
970 aa.do_typing(v, par_type)
971 a = aa
972 else
973 a = raw_args[arg_idx]
974 v.check_conform_expr(a, par_type)
975 arg_idx = arg_idx + 1
976 end
977 args.add(a)
978 end
979 return args
980 end
981
982 # Check the conformity of a set of defined closures
983 private meth process_closures(v: TypingVisitor, psig: MMSignature, name: Symbol, cd: Array[PClosureDef]): MMType
984 do
985 var t = psig.return_type
986 var cs = psig.closures # Declared closures
987 var min_arity = 0
988 for c in cs do
989 if not c.is_optional then min_arity += 1
990 end
991 if cd != null then
992 if cs.length == 0 then
993 v.error(self, "Error: {name} does not require blocks.")
994 else if cd.length > cs.length or cd.length < min_arity then
995 v.error(self, "Error: {name} requires {cs.length} blocks, {cd.length} found.")
996 else
997 # Initialize the break list if a value is required for breaks (ie. if the method is a function)
998 var break_list: Array[ABreakExpr] = null
999 if t != null then break_list = new Array[ABreakExpr]
1000
1001 # Process each closure definition
1002 for i in [0..cd.length[ do
1003 var csi = cs[i]
1004 var cdi = cd[i]
1005 var esc = new EscapableClosure(cdi, csi, break_list)
1006 v.escapable_ctx.push(esc)
1007 cdi.accept_typing2(v, esc)
1008 v.escapable_ctx.pop
1009 end
1010
1011 # Check break type conformity
1012 if break_list != null then
1013 t = v.check_conform_multiexpr(t, break_list)
1014 end
1015 end
1016 else if min_arity != 0 then
1017 v.error(self, "Error: {name} requires {cs.length} blocks.")
1018 end
1019 return t
1020 end
1021 end
1022
1023 class AAbsSendExpr
1024 special AAbsAbsSendExpr
1025 # Compute the called global property
1026 private meth do_typing(v: TypingVisitor, type_recv: MMType, is_implicit_self: Bool, recv_is_self: Bool, name: Symbol, raw_args: Array[PExpr], closure_defs: Array[PClosureDef])
1027 do
1028 var prop = get_property(v, type_recv, is_implicit_self, name)
1029 if prop == null then return
1030 var sig = get_signature(v, type_recv, prop, recv_is_self)
1031 if sig == null then return
1032 var args = process_signature(v, sig, prop.name, raw_args)
1033 if args == null then return
1034 var rtype = process_closures(v, sig, prop.name, closure_defs)
1035 _prop = prop
1036 _prop_signature = sig
1037 _arguments = args
1038 _return_type = rtype
1039 end
1040
1041 private meth get_property(v: TypingVisitor, type_recv: MMType, is_implicit_self: Bool, name: Symbol): MMMethod
1042 do
1043 if type_recv == null then return null
1044 var lc = type_recv.local_class
1045 var prop: MMMethod = null
1046 if lc.has_global_property_by_name(name) then prop = lc.select_method(name)
1047 if prop == null and v.local_property.global.is_init then
1048 var props = type_recv.local_class.super_methods_named(name)
1049 if props.length > 1 then
1050 v.error(self, "Error: Ambigous method name '{name}' for {props.join(", ")}. Use explicit designation.")
1051 return null
1052 else if props.length == 1 then
1053 var p = type_recv.local_class[props.first.global]
1054 assert p isa MMMethod
1055 prop = p
1056 end
1057
1058 end
1059 if prop == null then
1060 if is_implicit_self then
1061 v.error(self, "Error: Method or variable '{name}' unknown in {type_recv}.")
1062 else
1063 v.error(self, "Error: Method '{name}' doesn't exists in {type_recv}.")
1064 end
1065 return null
1066 end
1067 return prop
1068 end
1069
1070 # Get the signature for a local property and a receiver
1071 private meth get_signature(v: TypingVisitor, type_recv: MMType, prop: MMMethod, recv_is_self: Bool): MMSignature
1072 do
1073 prop.global.check_visibility(v, self, v.module, recv_is_self)
1074 var psig = prop.signature_for(type_recv)
1075 if not recv_is_self then psig = psig.not_for_self
1076 return psig
1077 end
1078
1079 # The invoked method (once computed)
1080 readable attr _prop: MMMethod
1081
1082 # The return type (if any) (once computed)
1083 readable attr _return_type: MMType
1084 end
1085
1086 # A possible call of constructor in a super class
1087 # Could be an explicit call or with the 'super' keyword
1088 class ASuperInitCall
1089 special AAbsSendExpr
1090 private meth register_super_init_call(v: TypingVisitor, property: MMMethod)
1091 do
1092 if parent != v.top_block and self != v.top_block then
1093 v.error(self, "Error: Constructor invocation {property} must not be in nested block.")
1094 end
1095 var cla = v.module[property.global.intro.local_class.global]
1096 var prev_class: MMLocalClass = null
1097 if not v.explicit_super_init_calls.is_empty then
1098 prev_class = v.explicit_super_init_calls.last.global.intro.local_class
1099 end
1100 var order = v.local_class.cshe.reverse_linear_extension
1101 if cla == v.local_class then
1102 v.explicit_other_init_call = true
1103 else if not order.has(cla) then
1104 v.error(self, "Error: Constructor of class {cla} must be one in {order.join(", ")}.")
1105 else if cla == prev_class then
1106 v.error(self, "Error: Only one super constructor invocation of class {cla} is allowed.")
1107 else
1108 var last_is_found = prev_class == null
1109 for c in order do
1110 if c == prev_class then
1111 last_is_found = true
1112 else if c == cla then
1113 if not last_is_found then
1114 v.error(self, "Error: Constructor of {c} must be invoked before constructor of {prev_class}")
1115 end
1116 v.explicit_super_init_calls.add(property)
1117 break
1118 end
1119 end
1120 end
1121 end
1122
1123 end
1124
1125 redef class ANewExpr
1126 special AAbsSendExpr
1127 redef meth after_typing(v)
1128 do
1129 var t = n_type.stype
1130 if t == null then return
1131 if t.local_class.global.is_abstract then
1132 v.error(self, "Error: try to instantiate abstract class {t.local_class}.")
1133 return
1134 end
1135 var name: Symbol
1136 if n_id == null then
1137 name = once "init".to_symbol
1138 else
1139 name = n_id.to_symbol
1140 end
1141
1142 do_typing(v, t, false, false, name, n_args.to_a, null)
1143 if prop == null then return
1144
1145 if not prop.global.is_init then
1146 v.error(self, "Error: {prop} is not a constructor.")
1147 end
1148 _stype = t
1149 end
1150 end
1151
1152
1153 redef class ASendExpr
1154 special ASuperInitCall
1155 # Name of the invoked property
1156 meth name: Symbol is abstract
1157
1158 # Raw arguments used (withour star transformation)
1159 meth raw_arguments: Array[PExpr] is abstract
1160
1161 # Closure definitions
1162 meth closure_defs: Array[PClosureDef] do return null
1163
1164 redef meth after_typing(v)
1165 do
1166 do_all_typing(v)
1167 end
1168
1169 private meth do_all_typing(v: TypingVisitor)
1170 do
1171 if not v.check_expr(n_expr) then return
1172 do_typing(v, n_expr.stype, n_expr.is_implicit_self, n_expr.is_self, name, raw_arguments, closure_defs)
1173 if prop == null then return
1174
1175 if prop.global.is_init then
1176 if not v.local_property.global.is_init then
1177 v.error(self, "Error: try to invoke constructor {prop} in a method.")
1178 else if not n_expr.is_self then
1179 v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
1180 else
1181 register_super_init_call(v, prop)
1182 end
1183 end
1184
1185 _stype = return_type
1186 end
1187 end
1188
1189 class ASendReassignExpr
1190 special ASendExpr
1191 special AReassignFormExpr
1192 readable attr _read_prop: MMMethod
1193 redef meth do_all_typing(v)
1194 do
1195 if not v.check_expr(n_expr) then return
1196 var raw_args = raw_arguments
1197 do_typing(v, n_expr.stype, n_expr.is_implicit_self, n_expr.is_self, name, raw_args, null)
1198 if prop == null then return
1199 if prop.global.is_init then
1200 if not v.local_property.global.is_init then
1201 v.error(self, "Error: try to invoke constructor {prop} in a method.")
1202 else if not n_expr.is_self then
1203 v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
1204 end
1205 end
1206 var t = prop.signature_for(n_expr.stype).return_type
1207 if not n_expr.is_self then t = t.not_for_self
1208
1209 do_lvalue_typing(v, t)
1210
1211 _read_prop = prop
1212 var old_args = arguments
1213 raw_args.add(n_value)
1214
1215 do_typing(v, n_expr.stype, n_expr.is_implicit_self, n_expr.is_self, "{name}=".to_symbol, raw_args, null)
1216 if prop == null then return
1217 if prop.global.is_init then
1218 if not v.local_property.global.is_init then
1219 v.error(self, "Error: try to invoke constructor {prop} in a method.")
1220 else if not n_expr.is_self then
1221 v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
1222 end
1223 end
1224
1225 _arguments = old_args # FIXME: What if star parameters do not match betwen the two methods?
1226 end
1227 end
1228
1229 redef class ABinopExpr
1230 redef meth raw_arguments do return [n_expr2]
1231 end
1232 redef class AEqExpr
1233 redef meth name do return once "==".to_symbol
1234 end
1235 redef class ANeExpr
1236 redef meth name do return once "!=".to_symbol
1237 end
1238 redef class ALtExpr
1239 redef meth name do return once "<".to_symbol
1240 end
1241 redef class ALeExpr
1242 redef meth name do return once "<=".to_symbol
1243 end
1244 redef class AGtExpr
1245 redef meth name do return once ">".to_symbol
1246 end
1247 redef class AGeExpr
1248 redef meth name do return once ">=".to_symbol
1249 end
1250 redef class APlusExpr
1251 redef meth name do return once "+".to_symbol
1252 end
1253 redef class AMinusExpr
1254 redef meth name do return once "-".to_symbol
1255 end
1256 redef class AStarshipExpr
1257 redef meth name do return once "<=>".to_symbol
1258 end
1259 redef class AStarExpr
1260 redef meth name do return once "*".to_symbol
1261 end
1262 redef class ASlashExpr
1263 redef meth name do return once "/".to_symbol
1264 end
1265 redef class APercentExpr
1266 redef meth name do return once "%".to_symbol
1267 end
1268
1269 redef class AUminusExpr
1270 redef meth name do return once "unary -".to_symbol
1271 redef meth raw_arguments do return null
1272 end
1273
1274 redef class ACallFormExpr
1275 redef meth after_typing(v)
1276 do
1277 if n_expr != null and n_expr.is_implicit_self then
1278 var name = n_id.to_symbol
1279 var variable = v.variable_ctx[name]
1280 if variable != null then
1281 if variable isa ClosureVariable then
1282 var n = new AClosureCallExpr.init_aclosurecallexpr(n_id, n_args, n_closure_defs)
1283 replace_with(n)
1284 n.variable = variable
1285 n.after_typing(v)
1286 return
1287 else
1288 if not n_args.is_empty then
1289 v.error(self, "Error: {name} is variable, not a function.")
1290 end
1291 var vform = variable_create(variable)
1292 vform.variable = variable
1293 replace_with(vform)
1294 vform.after_typing(v)
1295 return
1296 end
1297 end
1298 end
1299
1300 super
1301 end
1302
1303 redef meth closure_defs
1304 do
1305 if n_closure_defs == null or n_closure_defs.is_empty then
1306 return null
1307 else
1308 return n_closure_defs.to_a
1309 end
1310 end
1311
1312 # Create a variable acces corresponding to the call form
1313 meth variable_create(variable: Variable): AVarFormExpr is abstract
1314 end
1315
1316 redef class ACallExpr
1317 redef meth variable_create(variable)
1318 do
1319 return new AVarExpr.init_avarexpr(n_id)
1320 end
1321
1322 redef meth name do return n_id.to_symbol
1323 redef meth raw_arguments do return n_args.to_a
1324 end
1325
1326 redef class ACallAssignExpr
1327 redef meth variable_create(variable)
1328 do
1329 return new AVarAssignExpr.init_avarassignexpr(n_id, n_assign, n_value)
1330 end
1331
1332 redef meth name do return (n_id.text + "=").to_symbol
1333 redef meth raw_arguments do
1334 var res = n_args.to_a
1335 res.add(n_value)
1336 return res
1337 end
1338 end
1339
1340 redef class ACallReassignExpr
1341 special ASendReassignExpr
1342 redef meth variable_create(variable)
1343 do
1344 return new AVarReassignExpr.init_avarreassignexpr(n_id, n_assign_op, n_value)
1345 end
1346
1347 redef meth name do return n_id.to_symbol
1348 redef meth raw_arguments do return n_args.to_a
1349 end
1350
1351 redef class ABraExpr
1352 redef meth name do return once "[]".to_symbol
1353 redef meth raw_arguments do return n_args.to_a
1354 end
1355
1356 redef class ABraAssignExpr
1357 redef meth name do return once "[]=".to_symbol
1358 redef meth raw_arguments do
1359 var res = n_args.to_a
1360 res.add(n_value)
1361 return res
1362 end
1363 end
1364
1365 redef class ABraReassignExpr
1366 special ASendReassignExpr
1367 redef meth name do return once "[]".to_symbol
1368 redef meth raw_arguments do return n_args.to_a
1369 end
1370
1371 redef class AInitExpr
1372 redef meth name do return once "init".to_symbol
1373 redef meth raw_arguments do return n_args.to_a
1374 end
1375
1376 redef class AClosureCallExpr
1377 special AAbsAbsSendExpr
1378 redef meth after_typing(v)
1379 do
1380 var va = variable
1381 var sig = va.closure.signature
1382 var args = process_signature(v, sig, n_id.to_symbol, n_args.to_a)
1383 if not n_closure_defs.is_empty then
1384 process_closures(v, sig, n_id.to_symbol, n_closure_defs.to_a)
1385 end
1386 if args == null then return
1387 _prop_signature = sig
1388 _arguments = args
1389 _stype = sig.return_type
1390 end
1391 end
1392
1393 redef class PClosureDef
1394 # The corresponding escapable object
1395 readable attr _escapable: EscapableBlock
1396
1397 attr _accept_typing2: Bool
1398 redef meth accept_typing(v)
1399 do
1400 # Typing is deferred, wait accept_typing2(v)
1401 if _accept_typing2 then super
1402 end
1403
1404 private meth accept_typing2(v: TypingVisitor, esc: EscapableClosure) is abstract
1405 end
1406
1407 redef class AClosureDef
1408 redef meth accept_typing2(v, esc)
1409 do
1410 _escapable = esc
1411
1412 var sig = esc.closure.signature
1413 if sig.arity != n_id.length then
1414 v.error(self, "Error: {sig.arity} automatic variable names expected, {n_id.length} found.")
1415 return
1416 end
1417
1418 closure = esc.closure
1419
1420 v.variable_ctx = v.variable_ctx.sub
1421 variables = new Array[AutoVariable]
1422 for i in [0..n_id.length[ do
1423 var va = new AutoVariable(n_id[i].to_symbol, self)
1424 variables.add(va)
1425 va.stype = sig[i]
1426 v.variable_ctx.add(va)
1427 end
1428
1429 _accept_typing2 = true
1430 accept_typing(v)
1431 end
1432 end
1433
1434 redef class AIsaExpr
1435 redef meth after_typing(v)
1436 do
1437 var variable = n_expr.its_variable
1438 if variable != null then
1439 _if_true_variable_ctx = v.variable_ctx.sub_with(variable, n_type.stype)
1440 end
1441 _stype = v.type_bool
1442 end
1443 end
1444
1445 redef class AAsCastExpr
1446 redef meth after_typing(v)
1447 do
1448 v.check_expr(n_expr)
1449 _stype = n_type.stype
1450 end
1451 end
1452
1453 redef class AProxyExpr
1454 redef meth after_typing(v)
1455 do
1456 _stype = n_expr.stype
1457 end
1458 end