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