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