First NIT release and new clean mercurial repository
[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
22 redef class MMSrcModule
23 # Walk trough the module and type statments and expressions
24 # Require than supermodules are processed
25 meth do_typing(tc: ToolContext)
26 do
27 var tv = new TypingVisitor(tc, self)
28 tv.visit(node)
29 end
30 end
31
32 # Typing visitor
33 # * Associate local variables to nodes
34 # * Distinguish method call and local variable access
35 # * Resolve call and attribute access
36 # * Check type conformance
37 private class TypingVisitor
38 special AbsSyntaxVisitor
39 redef meth visit(n)
40 do
41 if n != null then n.accept_typing(self)
42 end
43
44 # Current knowledge about variables names and types
45 readable writable attr _variable_ctx: VariableContext
46
47 # Type of the receiver
48 readable writable attr _self_type: MMType
49
50 # Block of the current method
51 readable writable attr _top_block: PExpr
52
53 # List of explicit invocation of constructors of super-classes
54 readable writable attr _explicit_super_init_calls: Array[MMMethod]
55
56 # Is a other constructor of the same class invoked
57 readable writable attr _explicit_other_init_call: Bool
58
59 init(tc, module) do super
60
61 private meth get_default_constructor_for(n: PNode, c: MMLocalClass, prop: MMMethod): MMMethod
62 do
63 var v = self
64 #var prop = v.local_property
65 #assert prop isa MMMethod
66 var candidates = new Array[MMMethod]
67 var false_candidates = new Array[MMMethod]
68 var parity = prop.signature.arity
69 for g in c.global_properties do
70 if not g.is_init then continue
71 if g.intro.local_class != c then continue
72 var gp = c[g]
73 assert gp isa MMMethod
74 var garity = g.intro.signature.arity
75 if prop != null and g.intro.name == prop.name then
76 if garity == 0 or garity == parity then
77 return gp
78 else
79 false_candidates.add(gp)
80 end
81 else if garity == 0 then
82 candidates.add(gp)
83 false_candidates.add(gp)
84 else
85 false_candidates.add(gp)
86 end
87 end
88 if candidates.length == 1 then
89 return candidates.first
90 else if false_candidates.is_empty then
91 v.warning(n, "Fatal error: there is no available constrctor in {c}.")
92 return null
93 #abort
94 else
95 v.error(n, "Error: Conflicting default constructor to call for {c}: {false_candidates.join(", ")}.")
96 return null
97 end
98 end
99 end
100
101 # Associate symbols to variable and variables to type
102 # Can be nested
103 private class VariableContext
104 # Look for the variable from its name
105 # Return null if nothing found
106 meth [](s: Symbol): Variable
107 do
108 if _dico.has_key(s) then
109 return _dico[s]
110 else
111 return null
112 end
113 end
114
115 # Register a new variable with its name
116 meth add(v: Variable)
117 do
118 _dico[v.name] = v
119 end
120
121
122 # The effective static type of a given variable
123 # May be different from the declaration static type
124 meth stype(v: Variable): MMType
125 do
126 return v.stype
127 end
128
129 # Variables by name (in the current context only)
130 attr _dico: Map[Symbol, Variable]
131
132 # Build a new VariableContext
133 meth sub: VariableContext
134 do
135 return new SubVariableContext.with(self, null, null)
136 end
137
138 # Build a nested VariableContext with new variable information
139 meth sub_with(v: Variable, t: MMType): VariableContext
140 do
141 return new SubVariableContext.with(self, v, t)
142 end
143
144 init
145 do
146 _dico = new HashMap[Symbol, Variable]
147 end
148 end
149
150 private class SubVariableContext
151 special VariableContext
152 readable attr _prev: VariableContext
153 attr _variable: Variable
154 attr _var_type: MMType
155
156 redef meth [](s)
157 do
158 if _dico.has_key(s) then
159 return _dico[s]
160 else
161 return prev[s]
162 end
163 end
164
165 redef meth stype(v)
166 do
167 if _variable == v then
168 return _var_type
169 end
170 return prev.stype(v)
171 end
172
173 init with(p: VariableContext, v: Variable, t: MMType)
174 do
175 init
176 _prev = p
177 _variable = v
178 _var_type =t
179 end
180 end
181
182
183 ###############################################################################
184
185 redef class PNode
186 private meth accept_typing(v: TypingVisitor)
187 do
188 accept_abs_syntax_visitor(v)
189 after_typing(v)
190 end
191 private meth after_typing(v: TypingVisitor) do end
192 end
193
194 redef class PClassdef
195 redef meth accept_typing(v)
196 do
197 v.self_type = local_class.get_type
198 super
199 end
200 end
201
202 redef class AAttrPropdef
203 redef meth accept_typing(v)
204 do
205 super
206 if n_expr != null then
207 v.check_conform(n_expr, n_expr.stype, prop.signature.return_type)
208 end
209 end
210 end
211
212 redef class AMethPropdef
213 redef meth accept_typing(v)
214 do
215 v.variable_ctx = new VariableContext
216 super
217 end
218 end
219
220 redef class AConcreteInitPropdef
221 readable attr _super_init_calls: Array[MMMethod] = new Array[MMMethod]
222 readable attr _explicit_super_init_calls: Array[MMMethod] = new Array[MMMethod]
223 redef meth accept_typing(v)
224 do
225 v.top_block = n_block
226 v.explicit_super_init_calls = explicit_super_init_calls
227 v.explicit_other_init_call = false
228 super
229 if v.explicit_other_init_call then
230 # TODO: something?
231 else
232 var i = 0
233 var l = explicit_super_init_calls.length
234 var cur_m: MMMethod
235 var cur_c: MMLocalClass
236 if i < l then
237 cur_m = explicit_super_init_calls[i]
238 cur_c = cur_m.global.intro.local_class
239 end
240 var j = 0
241 while j < v.local_class.cshe.direct_greaters.length do
242 var c = v.local_class.cshe.direct_greaters[j]
243 if cur_c != null and c.cshe <= cur_c then
244 if c == cur_c then j += 1
245 super_init_calls.add(cur_m)
246 i += 1
247 if i < l then
248 cur_m = explicit_super_init_calls[i]
249 cur_c = cur_m.global.intro.local_class
250 else
251 cur_m = null
252 cur_c = null
253 end
254 else
255 var p = v.get_default_constructor_for(self, c, method)
256 if p != null then
257 super_init_calls.add(p)
258 end
259 j += 1
260 end
261 end
262 end
263 end
264 end
265
266 redef class PParam
267 redef meth after_typing(v)
268 do
269 if v.variable_ctx != null then
270 v.variable_ctx.add(variable)
271 end
272 end
273 end
274
275 redef class PType
276 readable attr _stype: MMType
277 redef meth after_typing(v)
278 do
279 _stype = get_stype(v)
280 end
281 end
282
283 redef class PExpr
284 redef readable attr _stype: MMType
285
286 # Is the expression the implicit receiver
287 meth is_implicit_self: Bool do return false
288
289 # Is the expression the current receiver (implicit or explicit)
290 meth is_self: Bool do return false
291
292 # Is the expression a variable access
293 meth is_variable: Bool do return false
294
295 # The variable type information if current boolean expression is true
296 readable private attr _if_true_variable_ctx: VariableContext
297 end
298
299 redef class AVardeclExpr
300 # Assiociated local variable
301 readable attr _variable: Variable
302
303 redef meth after_typing(v)
304 do
305 var va = new Variable(n_id.to_symbol, self)
306 _variable = va
307 v.variable_ctx.add(va)
308
309 if n_type != null then
310 va.stype = n_type.stype
311 if n_expr != null then
312 v.check_conform(self, n_expr.stype, va.stype)
313 end
314 else
315 va.stype = n_expr.stype
316 end
317 end
318 end
319
320 redef class ABlockExpr
321 redef meth accept_typing(v)
322 do
323 var old_var_ctx = v.variable_ctx
324 v.variable_ctx = v.variable_ctx.sub
325
326 super
327
328 v.variable_ctx = old_var_ctx
329 end
330 end
331
332 redef class AReturnExpr
333 redef meth after_typing(v)
334 do
335 var t = v.local_property.signature.return_type
336 if n_expr == null and t != null then
337 v.error(self, "Error: Return without value in a function.")
338 else if n_expr != null and t == null then
339 v.error(self, "Error: Return with value in a procedure.")
340 else if n_expr != null and t != null then
341 v.check_conform(self, n_expr.stype, t)
342 end
343 end
344 end
345
346 redef class AIfExpr
347 redef meth accept_typing(v)
348 do
349 var old_var_ctx = v.variable_ctx
350 v.visit(n_expr)
351 v.check_conform(self, n_expr.stype, v.type_bool)
352
353 if n_expr.if_true_variable_ctx != null then
354 v.variable_ctx = n_expr.if_true_variable_ctx
355 end
356
357 v.visit(n_then)
358 # Restore variable ctx
359 v.variable_ctx = old_var_ctx
360
361 if n_else != null then
362 v.visit(n_else)
363 v.variable_ctx = old_var_ctx
364 end
365 end
366 end
367
368 redef class AWhileExpr
369 redef meth after_typing(v)
370 do
371 v.check_conform(self, n_expr.stype, v.type_bool)
372 end
373 end
374
375 redef class AForExpr
376 redef meth after_typing(v)
377 do
378 # pop context created in AForVardeclExpr
379 var varctx = v.variable_ctx
380 assert varctx isa SubVariableContext
381 v.variable_ctx = varctx.prev
382 end
383 end
384
385 redef class AForVardeclExpr
386 # Associated automatic local variable
387 readable attr _variable: Variable
388
389 redef meth after_typing(v)
390 do
391 v.variable_ctx = v.variable_ctx.sub
392 var variable = new Variable(n_id.to_symbol, self)
393 _variable = variable
394 v.variable_ctx.add(variable)
395
396 var expr_type = n_expr.stype
397 if not v.check_conform(self, expr_type, v.type_collection) then
398 return
399 end
400 var prop = expr_type.select_method(once ("iterator".to_symbol))
401 if prop == null then
402 v.error(self, "Error: Collection MUST have an iterate method")
403 return
404 end
405 var iter_type = prop.signature.return_type
406 var prop2 = iter_type.select_method(once ("item".to_symbol))
407 if prop2 == null then
408 v.error(self, "Error: {iter_type} MUST have an item method")
409 return
410 end
411 var t = prop2.signature.return_type
412 if not n_expr.is_self then t = t.not_for_self
413 variable.stype = t
414 end
415 end
416
417 redef class AAssertExpr
418 redef meth after_typing(v)
419 do
420 v.check_conform(self, n_expr.stype, v.type_bool)
421 if n_expr.if_true_variable_ctx != null then v.variable_ctx = n_expr.if_true_variable_ctx
422 end
423 end
424
425 redef class AVarFormExpr
426 # Associated local variable
427 readable writable attr _variable: Variable
428 end
429
430 redef class AVarExpr
431 redef meth is_variable do return true
432
433 redef meth after_typing(v)
434 do
435 _stype = v.variable_ctx.stype(variable)
436 end
437 end
438
439 redef class AVarAssignExpr
440 redef meth after_typing(v)
441 do
442 var t = v.variable_ctx.stype(variable)
443 v.check_conform(self, n_value.stype, t)
444 end
445 end
446
447 redef class AReassignFormExpr
448 # Compute and check method used through the reassigment operator
449 private meth do_lvalue_typing(v: TypingVisitor, type_lvalue: MMType)
450 do
451 if type_lvalue == null then
452 return
453 end
454 var name = n_assign_op.method_name
455 var prop = type_lvalue.select_method(name)
456 if prop == null then
457 v.error(self, "Error: Method '{name}' doesn't exists in {type_lvalue}.")
458 return
459 end
460 prop.global.check_visibility(v, self, v.module, false)
461 var psig = prop.signature
462 _assign_method = prop
463 v.check_conform(self, n_value.stype, psig[0].not_for_self)
464 v.check_conform(self, psig.return_type.not_for_self, n_value.stype)
465 end
466
467 # Method used through the reassigment operator (once computed)
468 readable attr _assign_method: MMMethod
469 end
470
471 redef class PAssignOp
472 meth method_name: Symbol is abstract
473 end
474 redef class APlusAssignOp
475 redef meth method_name do return once "+".to_symbol
476 end
477 redef class AMinusAssignOp
478 redef meth method_name do return once "-".to_symbol
479 end
480
481 redef class AVarReassignExpr
482 redef meth after_typing(v)
483 do
484 var t = v.variable_ctx.stype(variable)
485 do_lvalue_typing(v, t)
486 end
487 end
488
489 redef class ASelfExpr
490 redef meth after_typing(v)
491 do
492 assert v.self_type != null
493 _stype = v.self_type
494 end
495
496 redef meth is_self do return true
497 end
498
499 redef class AImplicitSelfExpr
500 redef meth is_implicit_self do return true
501 end
502
503 redef class AIfexprExpr
504 redef meth accept_typing(v)
505 do
506 var old_var_ctx = v.variable_ctx
507
508 v.visit(n_expr)
509 if n_expr.if_true_variable_ctx != null then v.variable_ctx = n_expr.if_true_variable_ctx
510 v.visit(n_then)
511 v.variable_ctx = old_var_ctx
512 v.visit(n_else)
513
514 v.check_conform(self, n_expr.stype, v.type_bool)
515
516 var t = n_then.stype
517 var te = n_else.stype
518 if t < te then
519 t = te
520 else if not te < t then
521 v.error(self, "Type error: {te} is not a subtype of {t}.")
522 return
523 end
524
525 _stype = t
526 end
527 end
528
529 redef class ABoolExpr
530 redef meth after_typing(v)
531 do
532 _stype = v.type_bool
533 end
534 end
535
536 redef class AOrExpr
537 redef meth after_typing(v)
538 do
539 v.check_conform(self, n_expr.stype, v.type_bool)
540 v.check_conform(self, n_expr2.stype, v.type_bool)
541 _stype = v.type_bool
542 end
543 end
544
545 redef class AAndExpr
546 redef meth accept_typing(v)
547 do
548 var old_var_ctx = v.variable_ctx
549
550 v.visit(n_expr)
551 if n_expr.if_true_variable_ctx != null then v.variable_ctx = n_expr.if_true_variable_ctx
552
553 v.visit(n_expr2)
554 if n_expr2.if_true_variable_ctx != null then
555 _if_true_variable_ctx = n_expr2.if_true_variable_ctx
556 else
557 _if_true_variable_ctx = v.variable_ctx
558 end
559
560 v.variable_ctx = old_var_ctx
561
562 v.check_conform(self, n_expr.stype, v.type_bool)
563 v.check_conform(self, n_expr2.stype, v.type_bool)
564 _stype = v.type_bool
565 end
566 end
567
568 redef class ANotExpr
569 redef meth after_typing(v)
570 do
571 v.check_conform(self, n_expr.stype, v.type_bool)
572 _stype = v.type_bool
573 end
574 end
575
576 redef class AIntExpr
577 redef meth after_typing(v)
578 do
579 _stype = v.type_int
580
581 end
582 end
583
584 redef class AFloatExpr
585 redef meth after_typing(v)
586 do
587 _stype = v.type_float
588 end
589 end
590
591 redef class ACharExpr
592 redef meth after_typing(v)
593 do
594 _stype = v.type_char
595 end
596 end
597
598 redef class AStringFormExpr
599 redef meth after_typing(v)
600 do
601 _stype = v.type_string
602 end
603 end
604
605 redef class ASuperstringExpr
606 redef meth after_typing(v)
607 do
608 _stype = v.type_string
609 end
610 end
611
612 redef class ANullExpr
613 redef meth after_typing(v)
614 do
615 _stype = v.type_none
616 end
617 end
618
619 redef class AArrayExpr
620 private meth stype=(t: MMType) do _stype = t
621
622 redef meth after_typing(v)
623 do
624 var stype: MMType
625 for n in n_exprs do
626 var ntype = n.stype
627 if stype == null or (ntype != null and stype < ntype) then
628 stype = ntype
629 end
630 end
631 for n in n_exprs do
632 v.check_conform(self, n.stype, stype)
633 end
634 _stype = v.type_array(stype)
635 end
636 end
637
638 redef class ARangeExpr
639 redef meth after_typing(v)
640 do
641 var ntype = n_expr.stype
642 var ntype2 = n_expr2.stype
643 if ntype == null or ntype == null then
644 return
645 end
646 if ntype < ntype2 then
647 ntype = ntype2
648 else if not ntype2 < ntype then
649 v.error(self, "Type error: {ntype} incompatible with {ntype2}.")
650 return
651 end
652 var dtype = v.type_discrete
653 v.check_conform(self, ntype, dtype)
654 _stype = v.type_range(ntype)
655 end
656 end
657
658 redef class ASuperExpr
659 special ASuperInitCall
660 # readable attr _prop: MMSrcMethod
661 readable attr _init_in_superclass: MMMethod
662 redef meth after_typing(v)
663 do
664 var precs: Array[MMLocalProperty] = v.local_property.cprhe.direct_greaters
665 if not precs.is_empty then
666 v.local_property.need_super = true
667 else if v.local_property.global.is_init then
668 var base_precs = v.local_class.super_methods_named(v.local_property.name)
669 for p in base_precs do
670 if not p.global.is_init then
671 v.error(self, "Error: {p.local_class}::{p} is not a constructor.")
672 else
673 precs.add(v.self_type.select_property(p.global))
674 end
675 end
676 if precs.is_empty then
677 v.error(self, "Error: No contructor named {v.local_property.name} in superclasses.")
678 return
679 else if precs.length > 1 then
680 v.error(self, "Error: Conflicting contructors named {v.local_property.name} in superclasses: {precs.join(", ")}.")
681 return
682 end
683 var p = base_precs.first
684 assert p isa MMMethod
685 _init_in_superclass = p
686 register_super_init_call(v, p)
687 if n_args.length > 0 then
688 _arguments = process_signature(v, p, true, n_args.to_a)
689 end
690 else
691 v.error(self, "Error: No super method to call for {v.local_property}.")
692 return
693 end
694
695 if precs.first.signature.return_type != null then
696 var stypes = new Array[MMType]
697 var stype: MMType
698 for prop in precs do
699 assert prop isa MMMethod
700 var t = prop.signature.return_type.for_module(v.module).adapt_to(v.local_property.signature.recv)
701 stypes.add(t)
702 if stype == null or stype < t then
703 stype = t
704 end
705 end
706 for t in stypes do
707 v.check_conform(self, t, stype)
708 end
709 _stype = stype
710 end
711 var p = v.local_property
712 assert p isa MMSrcMethod
713 _prop = p
714 end
715 end
716
717 redef class AAttrFormExpr
718 # Attribute accessed
719 readable attr _prop: MMAttribute
720
721 # Compute the attribute accessed
722 private meth do_typing(v: TypingVisitor)
723 do
724 var type_recv = n_expr.stype
725 if type_recv == null then
726 return
727 end
728 var name = n_id.to_symbol
729 var prop = type_recv.select_attribute(name)
730 if prop == null then
731 v.error(self, "Error: Attribute {name} doesn't exists in {type_recv}.")
732 return
733 else if v.module.visibility_for(prop.global.local_class.module) < 3 then
734 v.error(self, "Error: Attribute {name} from {prop.global.local_class.module} is invisible in {v.module}")
735 end
736 _prop = prop
737 end
738 end
739
740 redef class AAttrExpr
741 redef meth after_typing(v)
742 do
743 do_typing(v)
744 if prop == null then
745 return
746 end
747 var attr_type = prop.signature.return_type
748 if not n_expr.is_self then attr_type = attr_type.not_for_self
749 _stype = attr_type
750 end
751 end
752
753 redef class AAttrAssignExpr
754 redef meth after_typing(v)
755 do
756 do_typing(v)
757 if prop == null then
758 return
759 end
760 var attr_type = prop.signature.return_type
761 if not n_expr.is_self then attr_type = attr_type.not_for_self
762 v.check_conform(self, n_value.stype, attr_type)
763 end
764 end
765
766 redef class AAttrReassignExpr
767 redef meth after_typing(v)
768 do
769 do_typing(v)
770 if prop == null then
771 return
772 end
773 var attr_type = prop.signature.return_type
774 if not n_expr.is_self then attr_type = attr_type.not_for_self
775 do_lvalue_typing(v, attr_type)
776 end
777 end
778
779 class AAbsSendExpr
780 special PExpr
781 # Compute the called global property
782 private meth do_typing(v: TypingVisitor, type_recv: MMType, is_implicit_self: Bool, recv_is_self: Bool, name: Symbol, raw_args: Array[PExpr])
783 do
784 var prop = get_property(v, type_recv, is_implicit_self, name)
785 if prop == null then return
786 var args = process_signature(v, prop, recv_is_self, raw_args)
787 if args == null then return
788 _prop = prop
789 _arguments = args
790 end
791
792 private meth get_property(v: TypingVisitor, type_recv: MMType, is_implicit_self: Bool, name: Symbol): MMMethod
793 do
794 if type_recv == null then return null
795 var prop = type_recv.select_method(name)
796 if prop == null and v.local_property.global.is_init then
797 var props = type_recv.local_class.super_methods_named(name)
798 if props.length > 1 then
799 v.error(self, "Error: Ambigous method name '{name}' for {props.join(", ")}. Use explicit designation.")
800 return null
801 else if props.length == 1 then
802 var p = type_recv.select_property(props.first.global)
803 assert p isa MMMethod
804 prop = p
805 end
806
807 end
808 if prop == null then
809 if is_implicit_self then
810 v.error(self, "Error: Method or variable '{name}' unknown in {type_recv}.")
811 else
812 v.error(self, "Error: Method '{name}' doesn't exists in {type_recv}.")
813 end
814 return null
815 end
816 return prop
817 end
818
819 private meth process_signature(v: TypingVisitor, prop: MMMethod, recv_is_self: Bool, raw_args: Array[PExpr]): Array[PExpr]
820 do
821 prop.global.check_visibility(v, self, v.module, recv_is_self)
822 var psig = prop.signature
823 var par_vararg = psig.vararg_rank
824 var par_arity = psig.arity
825 var raw_arity: Int
826 if raw_args == null then raw_arity = 0 else raw_arity = raw_args.length
827 if par_arity > raw_arity or (par_arity != raw_arity and par_vararg == -1) then
828 v.error(self, "Error: Method '{prop}' arity missmatch.")
829 return null
830 end
831 var arg_idx = 0
832 var args = new Array[PExpr]
833 for par_idx in [0..par_arity[ do
834 var a: PExpr
835 var par_type = psig[par_idx]
836 if not recv_is_self then par_type = par_type.not_for_self
837 if par_idx == par_vararg then
838 var star = new Array[PExpr]
839 for i in [0..(raw_arity-par_arity)] do
840 a = raw_args[arg_idx]
841 v.check_conform(self, a.stype, par_type)
842 star.add(a)
843 arg_idx = arg_idx + 1
844 end
845 var aa = new AArrayExpr.init_aarrayexpr(star)
846 aa.stype = v.type_array(par_type)
847 a = aa
848 else
849 a = raw_args[arg_idx]
850 v.check_conform(self, a.stype, par_type)
851 arg_idx = arg_idx + 1
852 end
853 args.add(a)
854 end
855 return args
856 end
857
858 # The invoked method (once computed)
859 readable attr _prop: MMMethod
860
861 # The real arguments used (after star transformation) (once computed)
862 readable attr _arguments: Array[PExpr]
863 end
864
865 # A possible call of constructor in a super class
866 # Could be an explicit call or with the 'super' keyword
867 class ASuperInitCall
868 special AAbsSendExpr
869 private meth register_super_init_call(v: TypingVisitor, property: MMMethod)
870 do
871 if parent != v.top_block and self != v.top_block then
872 v.error(self, "Error: Constructor invocation {property} must not be in nested block.")
873 end
874 var cla = v.module[property.global.intro.local_class.global]
875 var prev_class: MMLocalClass
876 if not v.explicit_super_init_calls.is_empty then
877 prev_class = v.explicit_super_init_calls.last.global.intro.local_class
878 end
879 var order = v.local_class.cshe.reverse_linear_extension
880 if cla == v.local_class then
881 v.explicit_other_init_call = true
882 else if not order.has(cla) then
883 v.error(self, "Error: Constructor of class {cla} must be one in {order.join(", ")}.")
884 else if cla == prev_class then
885 v.error(self, "Error: Only one super constructor invocation of class {cla} is allowed.")
886 else
887 var last_is_found = prev_class == null
888 for c in order do
889 if c == prev_class then
890 last_is_found = true
891 else if c == cla then
892 if not last_is_found then
893 v.error(self, "Error: Constructor of {c} must be invoked before constructor of {prev_class}")
894 end
895 v.explicit_super_init_calls.add(property)
896 break
897 end
898 end
899 end
900 end
901
902 end
903
904 redef class ANewExpr
905 special AAbsSendExpr
906 redef meth after_typing(v)
907 do
908 var t = n_type.stype
909 if t == null then return
910 if t.local_class.global.is_abstract then
911 v.error(self, "Error: try to instantiate abstract class {t.local_class}.")
912 return
913 end
914 var name: Symbol
915 if n_id == null then
916 name = once "init".to_symbol
917 else
918 name = n_id.to_symbol
919 end
920
921 do_typing(v, t, false, false, name, n_args.to_a)
922 if not prop.global.is_init then
923 v.error(self, "Error: {prop} is not a constructor.")
924 end
925 _stype = t
926 end
927 end
928
929
930 redef class ASendExpr
931 special ASuperInitCall
932 # Name of the invoked property
933 meth name: Symbol is abstract
934
935 # Raw arguments used (withour star transformation)
936 meth raw_arguments: Array[PExpr] is abstract
937
938 redef meth after_typing(v)
939 do
940 do_all_typing(v)
941 end
942
943 private meth do_all_typing(v: TypingVisitor)
944 do
945 do_typing(v, n_expr.stype, n_expr.is_implicit_self, n_expr.is_self, name, raw_arguments)
946 if prop == null then return
947 if prop.global.is_init then
948 if not v.local_property.global.is_init then
949 v.error(self, "Error: try to invoke constructor {prop} in a method.")
950 else if not n_expr.is_self then
951 v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
952 else
953 register_super_init_call(v, prop)
954 end
955 end
956 var t = prop.signature.return_type
957 if t != null and not n_expr.is_self then t = t.not_for_self
958 _stype = t
959 end
960 end
961
962 class ASendReassignExpr
963 special ASendExpr
964 special AReassignFormExpr
965 readable attr _read_prop: MMMethod
966 redef meth do_all_typing(v)
967 do
968 var raw_args = raw_arguments
969 do_typing(v, n_expr.stype, n_expr.is_implicit_self, n_expr.is_self, name, raw_args)
970 if prop == null then return
971 if prop.global.is_init then
972 if not v.local_property.global.is_init then
973 v.error(self, "Error: try to invoke constructor {prop} in a method.")
974 else if not n_expr.is_self then
975 v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
976 end
977 end
978 var t = prop.signature.return_type
979 if not n_expr.is_self then t = t.not_for_self
980
981 do_lvalue_typing(v, t)
982
983 _read_prop = prop
984 var old_args = arguments
985 raw_args.add(n_value)
986
987 do_typing(v, n_expr.stype, n_expr.is_implicit_self, n_expr.is_self, "{name}=".to_symbol, raw_args)
988 if prop == null then return
989 if prop.global.is_init then
990 if not v.local_property.global.is_init then
991 v.error(self, "Error: try to invoke constructor {prop} in a method.")
992 else if not n_expr.is_self then
993 v.error(self, "Error: constructor {prop} is not invoken on 'self'.")
994 end
995 end
996
997 _arguments = old_args # FIXME: What if star parameters do not match betwen the two methods?
998 end
999 end
1000
1001 redef class ABinopExpr
1002 redef meth raw_arguments do return [n_expr2]
1003 end
1004 redef class AEqExpr
1005 redef meth name do return once "==".to_symbol
1006 end
1007 redef class ANeExpr
1008 redef meth name do return once "!=".to_symbol
1009 end
1010 redef class ALtExpr
1011 redef meth name do return once "<".to_symbol
1012 end
1013 redef class ALeExpr
1014 redef meth name do return once "<=".to_symbol
1015 end
1016 redef class AGtExpr
1017 redef meth name do return once ">".to_symbol
1018 end
1019 redef class AGeExpr
1020 redef meth name do return once ">=".to_symbol
1021 end
1022 redef class APlusExpr
1023 redef meth name do return once "+".to_symbol
1024 end
1025 redef class AMinusExpr
1026 redef meth name do return once "-".to_symbol
1027 end
1028 redef class AStarshipExpr
1029 redef meth name do return once "<=>".to_symbol
1030 end
1031 redef class AStarExpr
1032 redef meth name do return once "*".to_symbol
1033 end
1034 redef class ASlashExpr
1035 redef meth name do return once "/".to_symbol
1036 end
1037 redef class APercentExpr
1038 redef meth name do return once "%".to_symbol
1039 end
1040
1041 redef class AUminusExpr
1042 redef meth name do return once "unary -".to_symbol
1043 redef meth raw_arguments do return null
1044 end
1045
1046 redef class ACallFormExpr
1047 redef meth after_typing(v)
1048 do
1049 if n_expr.is_implicit_self then
1050 var name = n_id.to_symbol
1051 var variable = v.variable_ctx[name]
1052 if variable != null then
1053 if not n_args.is_empty then
1054 v.error(self, "Error: {name} is variable, not a function.")
1055 end
1056 var vform = variable_create(variable)
1057 vform.variable = variable
1058 replace_with(vform)
1059 vform.after_typing(v)
1060 return
1061 end
1062 end
1063 super
1064 end
1065
1066 # Create a variable acces corresponding to the call form
1067 meth variable_create(variable: Variable): AVarFormExpr is abstract
1068 end
1069
1070 redef class ACallExpr
1071 redef meth variable_create(variable)
1072 do
1073 return new AVarExpr.init_avarexpr(n_id)
1074 end
1075
1076 redef meth name do return n_id.to_symbol
1077 redef meth raw_arguments do return n_args.to_a
1078 end
1079
1080 redef class ACallAssignExpr
1081 redef meth variable_create(variable)
1082 do
1083 return new AVarAssignExpr.init_avarassignexpr(n_id, n_assign, n_value)
1084 end
1085
1086 redef meth name do return (n_id.text + "=").to_symbol
1087 redef meth raw_arguments do
1088 var res = n_args.to_a
1089 res.add(n_value)
1090 return res
1091 end
1092 end
1093
1094 redef class ACallReassignExpr
1095 special ASendReassignExpr
1096 redef meth variable_create(variable)
1097 do
1098 return new AVarReassignExpr.init_avarreassignexpr(n_id, n_assign_op, n_value)
1099 end
1100
1101 redef meth name do return n_id.to_symbol
1102 redef meth raw_arguments do return n_args.to_a
1103 end
1104
1105 redef class ABraExpr
1106 redef meth name do return once "[]".to_symbol
1107 redef meth raw_arguments do return n_args.to_a
1108 end
1109
1110 redef class ABraAssignExpr
1111 redef meth name do return once "[]=".to_symbol
1112 redef meth raw_arguments do
1113 var res = n_args.to_a
1114 res.add(n_value)
1115 return res
1116 end
1117 end
1118
1119 redef class ABraReassignExpr
1120 special ASendReassignExpr
1121 redef meth name do return once "[]".to_symbol
1122 redef meth raw_arguments do return n_args.to_a
1123 end
1124
1125 redef class AInitExpr
1126 redef meth name do return once "init".to_symbol
1127 redef meth raw_arguments do return n_args.to_a
1128 end
1129
1130 redef class AIsaExpr
1131 redef meth after_typing(v)
1132 do
1133 if n_expr.is_variable then
1134 var n = n_expr
1135 assert n isa AVarExpr
1136 _if_true_variable_ctx = v.variable_ctx.sub_with(n.variable, n_type.stype)
1137 end
1138 _stype = v.type_bool
1139 end
1140 end
1141
1142 redef class AProxyExpr
1143 redef meth after_typing(v)
1144 do
1145 _stype = n_expr.stype
1146 end
1147 end