astbuilder: `make_new` and `make_call` require a CallSite
[nit.git] / src / typing.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 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 # Intraprocedural resolution of static types and OO-services
18 # By OO-services we mean message sending, attribute access, instantiation, etc.
19 module typing
20
21 import flow
22 import modelize_property
23 import phase
24 import local_var_init
25
26 redef class ToolContext
27 var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
28 end
29
30 private class TypingPhase
31 super Phase
32 redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
33 end
34
35 private class TypeVisitor
36 var modelbuilder: ModelBuilder
37 var nclassdef: AClassdef
38 var mpropdef: MPropDef
39
40 var selfvariable: Variable = new Variable("self")
41
42 init(modelbuilder: ModelBuilder, nclassdef: AClassdef, mpropdef: MPropDef)
43 do
44 self.modelbuilder = modelbuilder
45 self.nclassdef = nclassdef
46 self.mpropdef = mpropdef
47
48 var mclass = nclassdef.mclassdef.mclass
49
50 var selfvariable = new Variable("self")
51 self.selfvariable = selfvariable
52 selfvariable.declared_type = mclass.mclass_type
53 end
54
55 fun mmodule: MModule do return self.nclassdef.mclassdef.mmodule
56
57 fun anchor: MClassType do return self.nclassdef.mclassdef.bound_mtype
58
59 fun anchor_to(mtype: MType): MType
60 do
61 var mmodule = self.nclassdef.mclassdef.mmodule
62 var anchor = self.nclassdef.mclassdef.bound_mtype
63 return mtype.anchor_to(mmodule, anchor)
64 end
65
66 fun is_subtype(sub, sup: MType): Bool
67 do
68 var mmodule = self.nclassdef.mclassdef.mmodule
69 var anchor = self.nclassdef.mclassdef.bound_mtype
70 return sub.is_subtype(mmodule, anchor, sup)
71 end
72
73 fun resolve_for(mtype, subtype: MType, for_self: Bool): MType
74 do
75 var mmodule = self.nclassdef.mclassdef.mmodule
76 var anchor = self.nclassdef.mclassdef.bound_mtype
77 #print "resolve_for {mtype} sub={subtype} forself={for_self} mmodule={mmodule} anchor={anchor}"
78 var res = mtype.resolve_for(subtype, anchor, mmodule, not for_self)
79 return res
80 end
81
82 # Check that `sub` is a subtype of `sup`.
83 # If `sub` is not a valud suptype, then display an error on `node` an return null.
84 # If `sub` is a safe subtype of `sup` then return `sub`.
85 # If `sub` is an insafe subtype (ie an imlicit cast is required), then return `sup`.
86 #
87 # The point of the return type is to determinate the usable type on an expression:
88 # If the suptype is safe, then the return type is the one on the expression typed by `sub`.
89 # Is the subtype is unsafe, then the return type is the one of an implicit cast on `sup`.
90 fun check_subtype(node: ANode, sub, sup: MType): nullable MType
91 do
92 if self.is_subtype(sub, sup) then return sub
93 if self.is_subtype(sub, self.anchor_to(sup)) then
94 # FIXME workarround to the current unsafe typing policy. To remove once fixed virtual types exists.
95 #node.debug("Unsafe typing: expected {sup}, got {sub}")
96 return sup
97 end
98 self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}")
99 return null
100 end
101
102 # Visit an expression and do not care about the return value
103 fun visit_stmt(nexpr: nullable AExpr)
104 do
105 if nexpr == null then return
106 nexpr.accept_typing(self)
107 end
108
109 # Visit an expression and expects that it is not a statement
110 # Return the type of the expression
111 # Display an error and return null if:
112 # * the type cannot be determined or
113 # * `nexpr` is a statement
114 fun visit_expr(nexpr: AExpr): nullable MType
115 do
116 nexpr.accept_typing(self)
117 var mtype = nexpr.mtype
118 if mtype != null then return mtype
119 if not nexpr.is_typed then
120 if not self.modelbuilder.toolcontext.error_count > 0 then # check that there is really an error
121 if self.modelbuilder.toolcontext.verbose_level > 1 then
122 nexpr.debug("No return type but no error.")
123 end
124 end
125 return null # forward error
126 end
127 self.error(nexpr, "Type error: expected expression.")
128 return null
129 end
130
131 # Visit an expression and expect its static type is a least a `sup`
132 # Return the type of the expression or null if
133 # * the type cannot be determined or
134 # * `nexpr` is a statement or
135 # * `nexpr` is not a `sup`
136 fun visit_expr_subtype(nexpr: AExpr, sup: nullable MType): nullable MType
137 do
138 var sub = visit_expr(nexpr)
139 if sub == null then return null # Forward error
140
141 if sup == null then return null # Forward error
142
143 var res = check_subtype(nexpr, sub, sup)
144 if res != sub then
145 nexpr.implicit_cast_to = res
146 end
147 return res
148 end
149
150 # Visit an expression and expect its static type is a `Bool`
151 # Return the type of the expression or null if
152 # * the type cannot be determined or
153 # * `nexpr` is a statement or
154 # * `nexpr` is not a `Bool`
155 fun visit_expr_bool(nexpr: AExpr): nullable MType
156 do
157 return self.visit_expr_subtype(nexpr, self.type_bool(nexpr))
158 end
159
160
161 private fun visit_expr_cast(node: ANode, nexpr: AExpr, ntype: AType): nullable MType
162 do
163 var sub = visit_expr(nexpr)
164 if sub == null then return null # Forward error
165
166 var sup = self.resolve_mtype(ntype)
167 if sup == null then return null # Forward error
168
169 var mmodule = self.nclassdef.mclassdef.mmodule
170 var anchor = self.nclassdef.mclassdef.bound_mtype
171 if sup == sub then
172 self.modelbuilder.warning(node, "Warning: Expression is already a {sup}.")
173 else if self.is_subtype(sub, sup) and not sup.need_anchor then
174 self.modelbuilder.warning(node, "Warning: Expression is already a {sup} since it is a {sub}.")
175 end
176 return sup
177 end
178
179 fun try_get_mproperty_by_name2(anode: ANode, mtype: MType, name: String): nullable MProperty
180 do
181 return self.modelbuilder.try_get_mproperty_by_name2(anode, self.nclassdef.mclassdef.mmodule, mtype, name)
182 end
183
184 fun resolve_mtype(node: AType): nullable MType
185 do
186 return self.modelbuilder.resolve_mtype(self.nclassdef, node)
187 end
188
189 fun try_get_mclass(node: ANode, name: String): nullable MClass
190 do
191 var mmodule = self.nclassdef.mclassdef.mmodule
192 var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
193 return mclass
194 end
195
196 fun get_mclass(node: ANode, name: String): nullable MClass
197 do
198 var mmodule = self.nclassdef.mclassdef.mmodule
199 var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
200 if mclass == null then
201 self.modelbuilder.error(node, "Type Error: missing primitive class `{name}'.")
202 end
203 return mclass
204 end
205
206 fun type_bool(node: ANode): nullable MType
207 do
208 var mclass = self.get_mclass(node, "Bool")
209 if mclass == null then return null
210 return mclass.mclass_type
211 end
212
213 fun get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
214 do
215 var unsafe_type = self.anchor_to(recvtype)
216
217 #debug("recv: {recvtype} (aka {unsafe_type})")
218 if recvtype isa MNullType then
219 self.error(node, "Error: Method '{name}' call on 'null'.")
220 return null
221 end
222
223 var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
224 if mproperty == null then
225 #self.modelbuilder.error(node, "Type error: property {name} not found in {unsafe_type} (ie {recvtype})")
226 if recv_is_self then
227 self.modelbuilder.error(node, "Error: Method or variable '{name}' unknown in {recvtype}.")
228 else
229 self.modelbuilder.error(node, "Error: Method '{name}' doesn't exists in {recvtype}.")
230 end
231 return null
232 end
233
234 assert mproperty isa MMethod
235 if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility and not modelbuilder.toolcontext.opt_ignore_visibility.value then
236 self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self.")
237 return null
238 end
239
240 var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
241 var mpropdef
242 if propdefs.length == 0 then
243 self.modelbuilder.error(node, "Type error: no definition found for property {name} in {unsafe_type}")
244 return null
245 else if propdefs.length == 1 then
246 mpropdef = propdefs.first
247 else
248 self.modelbuilder.warning(node, "Warning: confliting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
249 mpropdef = mproperty.intro
250 end
251
252
253 var msignature = mpropdef.msignature.as(not null)
254 msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
255
256 var erasure_cast = false
257 var rettype = mpropdef.msignature.return_mtype
258 if not recv_is_self and rettype != null then
259 if rettype isa MNullableType then rettype = rettype.mtype
260 if rettype isa MParameterType then
261 var erased_rettype = msignature.return_mtype
262 assert erased_rettype != null
263 #node.debug("Erasure cast: Really a {rettype} but unsafely a {erased_rettype}")
264 erasure_cast = true
265 end
266 end
267
268 var callsite = new CallSite(node, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
269 return callsite
270 end
271
272 # Visit the expressions of args and cheik their conformity with the corresponding typi in signature
273 # The point of this method is to handle varargs correctly
274 # Note: The signature must be correctly adapted
275 fun check_signature(node: ANode, args: Array[AExpr], name: String, msignature: MSignature): Bool
276 do
277 var vararg_rank = msignature.vararg_rank
278 if vararg_rank >= 0 then
279 if args.length < msignature.arity then
280 #self.modelbuilder.error(node, "Error: Incorrect number of parameters. Got {args.length}, expected at least {msignature.arity}. Signature is {msignature}")
281 self.modelbuilder.error(node, "Error: arity mismatch; prototype is '{name}{msignature}'")
282 return false
283 end
284 else if args.length != msignature.arity then
285 self.modelbuilder.error(node, "Error: Incorrect number of parameters. Got {args.length}, expected {msignature.arity}. Signature is {msignature}")
286 return false
287 end
288
289 #debug("CALL {unsafe_type}.{msignature}")
290
291 var vararg_decl = args.length - msignature.arity
292 for i in [0..msignature.arity[ do
293 var j = i
294 if i == vararg_rank then continue # skip the vararg
295 if i > vararg_rank then
296 j = i + vararg_decl
297 end
298 var paramtype = msignature.mparameters[i].mtype
299 self.visit_expr_subtype(args[j], paramtype)
300 end
301 if vararg_rank >= 0 then
302 var varargs = new Array[AExpr]
303 var paramtype = msignature.mparameters[vararg_rank].mtype
304 for j in [vararg_rank..vararg_rank+vararg_decl] do
305 varargs.add(args[j])
306 self.visit_expr_subtype(args[j], paramtype)
307 end
308 end
309 return true
310 end
311
312 fun error(node: ANode, message: String)
313 do
314 self.modelbuilder.toolcontext.error(node.hot_location, message)
315 end
316
317 fun get_variable(node: AExpr, variable: Variable): nullable MType
318 do
319 var flow = node.after_flow_context
320 if flow == null then
321 self.error(node, "No context!")
322 return null
323 end
324
325 if flow.vars.has_key(variable) then
326 return flow.vars[variable]
327 else
328 #node.debug("*** START Collected for {variable}")
329 var mtypes = flow.collect_types(variable)
330 #node.debug("**** END Collected for {variable}")
331 if mtypes == null or mtypes.length == 0 then
332 return variable.declared_type
333 else if mtypes.length == 1 then
334 return mtypes.first
335 else
336 var res = merge_types(node,mtypes)
337 if res == null then res = variable.declared_type
338 return res
339 end
340 end
341 end
342
343 fun set_variable(node: AExpr, variable: Variable, mtype: nullable MType)
344 do
345 var flow = node.after_flow_context
346 assert flow != null
347
348 flow.set_var(variable, mtype)
349 end
350
351 fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
352 do
353 if col.length == 1 then return col.first
354 var res = new Array[nullable MType]
355 for t1 in col do
356 if t1 == null then continue # return null
357 var found = true
358 for t2 in col do
359 if t2 == null then continue # return null
360 if t2 isa MNullableType or t2 isa MNullType then
361 t1 = t1.as_nullable
362 end
363 if not is_subtype(t2, t1) then found = false
364 end
365 if found then
366 #print "merge {col.join(" ")} -> {t1}"
367 return t1
368 end
369 end
370 #self.modelbuilder.warning(node, "Type Error: {col.length} conflicting types: <{col.join(", ")}>")
371 return null
372 end
373 end
374
375 # A specific method call site with its associated informations.
376 class CallSite
377 # The assiciated node for location
378 var node: ANode
379
380 # The static type of the receiver (possibly unresolved)
381 var recv: MType
382
383 # The module where the callsite is present
384 var mmodule: MModule
385
386 # The anchor to use with `recv` or `msignature`
387 var anchor: nullable MClassType
388
389 # Is the receiver self?
390 # If "for_self", virtual types of the signature are keeped
391 # If "not_for_self", virtual type are erased
392 var recv_is_self: Bool
393
394 # The designated method
395 var mproperty: MMethod
396
397 # The statically designated method definition
398 # The most specif one, it is.
399 var mpropdef: MMethodDef
400
401 # The resolved signature for the receiver
402 var msignature: MSignature
403
404 # Is a implicit cast required on erasure typing policy?
405 var erasure_cast: Bool
406
407 private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
408 do
409 return v.check_signature(self.node, args, self.mproperty.name, self.msignature)
410 end
411 end
412
413 redef class Variable
414 # The declared type of the variable
415 var declared_type: nullable MType
416 end
417
418 redef class FlowContext
419 # Store changes of types because of type evolution
420 private var vars: HashMap[Variable, nullable MType] = new HashMap[Variable, nullable MType]
421 private var cache: HashMap[Variable, nullable Array[nullable MType]] = new HashMap[Variable, nullable Array[nullable MType]]
422
423 # Adapt the variable to a static type
424 # Warning1: do not modify vars directly.
425 # Warning2: sub-flow may have cached a unadapted variabial
426 private fun set_var(variable: Variable, mtype: nullable MType)
427 do
428 self.vars[variable] = mtype
429 self.cache.keys.remove(variable)
430 end
431
432 private fun collect_types(variable: Variable): nullable Array[nullable MType]
433 do
434 if cache.has_key(variable) then
435 return cache[variable]
436 end
437 var res: nullable Array[nullable MType] = null
438 if vars.has_key(variable) then
439 var mtype = vars[variable]
440 res = [mtype]
441 else if self.previous.is_empty then
442 # Root flow
443 res = [variable.declared_type]
444 else
445 for flow in self.previous do
446 if flow.is_unreachable then continue
447 var r2 = flow.collect_types(variable)
448 if r2 == null then continue
449 if res == null then
450 res = r2.to_a
451 else
452 for t in r2 do
453 if not res.has(t) then res.add(t)
454 end
455 end
456 end
457 end
458 cache[variable] = res
459 return res
460 end
461 end
462
463 redef class APropdef
464 # The entry point of the whole typing analysis
465 fun do_typing(modelbuilder: ModelBuilder)
466 do
467 end
468
469 # The variable associated to the reciever (if any)
470 var selfvariable: nullable Variable
471 end
472
473 redef class AMethPropdef
474 redef fun do_typing(modelbuilder: ModelBuilder)
475 do
476 var nblock = self.n_block
477 if nblock == null then return
478
479 var nclassdef = self.parent.as(AClassdef)
480 var mpropdef = self.mpropdef.as(not null)
481 var v = new TypeVisitor(modelbuilder, nclassdef, mpropdef)
482 self.selfvariable = v.selfvariable
483
484 var mmethoddef = self.mpropdef.as(not null)
485 for i in [0..mmethoddef.msignature.arity[ do
486 var mtype = mmethoddef.msignature.mparameters[i].mtype
487 if mmethoddef.msignature.vararg_rank == i then
488 var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
489 if arrayclass == null then return # Skip error
490 mtype = arrayclass.get_mtype([mtype])
491 end
492 var variable = self.n_signature.n_params[i].variable
493 assert variable != null
494 variable.declared_type = mtype
495 end
496 v.visit_stmt(nblock)
497
498 if not nblock.after_flow_context.is_unreachable and mmethoddef.msignature.return_mtype != null then
499 # We reach the end of the function without having a return, it is bad
500 v.error(self, "Control error: Reached end of function (a 'return' with a value was expected).")
501 end
502 end
503 end
504
505 redef class AAttrPropdef
506 redef fun do_typing(modelbuilder: ModelBuilder)
507 do
508 var nclassdef = self.parent.as(AClassdef)
509 var v = new TypeVisitor(modelbuilder, nclassdef, self.mpropdef.as(not null))
510 self.selfvariable = v.selfvariable
511
512 var nexpr = self.n_expr
513 if nexpr != null then
514 var mtype = self.mpropdef.static_mtype
515 v.visit_expr_subtype(nexpr, mtype)
516 end
517 end
518 end
519
520 ###
521
522 redef class AExpr
523 # The static type of the expression.
524 # null if self is a statement or in case of error
525 var mtype: nullable MType = null
526
527 # Is the statement correctly typed?
528 # Used to distinguish errors and statements when `mtype == null`
529 var is_typed: Bool = false
530
531 # If required, the following implicit cast `.as(XXX)`
532 # Such a cast may by required after evaluating the expression when
533 # a unsafe operation is detected (silently accepted by the Nit language).
534 # The attribute is computed by `check_subtype`
535 var implicit_cast_to: nullable MType = null
536
537 # Return the variable read (if any)
538 # Used to perform adaptive typing
539 fun its_variable: nullable Variable do return null
540
541 private fun accept_typing(v: TypeVisitor)
542 do
543 v.error(self, "no implemented accept_typing for {self.class_name}")
544 end
545 end
546
547 redef class ABlockExpr
548 redef fun accept_typing(v)
549 do
550 for e in self.n_expr do v.visit_stmt(e)
551 self.is_typed = true
552 end
553
554 # The type of a blockexpr is the one of the last expression (or null if empty)
555 redef fun mtype
556 do
557 if self.n_expr.is_empty then return null
558 return self.n_expr.last.mtype
559 end
560 end
561
562 redef class AVardeclExpr
563 redef fun accept_typing(v)
564 do
565 var variable = self.variable
566 if variable == null then return # Skip error
567
568 var ntype = self.n_type
569 var mtype: nullable MType
570 if ntype == null then
571 mtype = null
572 else
573 mtype = v.resolve_mtype(ntype)
574 if mtype == null then return # Skip error
575 end
576
577 var nexpr = self.n_expr
578 if nexpr != null then
579 if mtype != null then
580 v.visit_expr_subtype(nexpr, mtype)
581 else
582 mtype = v.visit_expr(nexpr)
583 if mtype == null then return # Skip error
584 end
585 end
586
587 var decltype = mtype
588 if mtype == null or mtype isa MNullType then
589 decltype = v.get_mclass(self, "Object").mclass_type.as_nullable
590 if mtype == null then mtype = decltype
591 end
592
593 variable.declared_type = decltype
594 v.set_variable(self, variable, mtype)
595
596 #debug("var {variable}: {mtype}")
597
598 self.is_typed = true
599 end
600 end
601
602 redef class AVarExpr
603 redef fun its_variable do return self.variable
604 redef fun accept_typing(v)
605 do
606 var variable = self.variable
607 if variable == null then return # Skip error
608
609 var mtype = v.get_variable(self, variable)
610 if mtype != null then
611 #debug("{variable} is {mtype}")
612 else
613 #debug("{variable} is untyped")
614 end
615
616 self.mtype = mtype
617 end
618 end
619
620 redef class AVarAssignExpr
621 redef fun accept_typing(v)
622 do
623 var variable = self.variable
624 assert variable != null
625
626 var mtype = v.visit_expr_subtype(n_value, variable.declared_type)
627
628 v.set_variable(self, variable, mtype)
629
630 self.is_typed = true
631 end
632 end
633
634 redef class AReassignFormExpr
635 # The method designed by the reassign operator.
636 var reassign_callsite: nullable CallSite
637
638 var read_type: nullable MType = null
639
640 # Determine the `reassign_property`
641 # `readtype` is the type of the reading of the left value.
642 # `writetype` is the type of the writing of the left value.
643 # (Because of `ACallReassignExpr`, both can be different.
644 # Return the static type of the value to store.
645 private fun resolve_reassignment(v: TypeVisitor, readtype, writetype: MType): nullable MType
646 do
647 var reassign_name: String
648 if self.n_assign_op isa APlusAssignOp then
649 reassign_name = "+"
650 else if self.n_assign_op isa AMinusAssignOp then
651 reassign_name = "-"
652 else
653 abort
654 end
655
656 self.read_type = readtype
657
658 if readtype isa MNullType then
659 v.error(self, "Error: Method '{reassign_name}' call on 'null'.")
660 return null
661 end
662
663 var callsite = v.get_method(self, readtype, reassign_name, false)
664 if callsite == null then return null # Skip error
665 self.reassign_callsite = callsite
666
667 var msignature = callsite.msignature
668 var rettype = msignature.return_mtype
669 assert msignature.arity == 1 and rettype != null
670
671 var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
672 if value_type == null then return null # Skip error
673
674 v.check_subtype(self, rettype, writetype)
675 return rettype
676 end
677 end
678
679 redef class AVarReassignExpr
680 redef fun accept_typing(v)
681 do
682 var variable = self.variable
683 assert variable != null
684
685 var readtype = v.get_variable(self, variable)
686 if readtype == null then return
687
688 read_type = readtype
689
690 var writetype = variable.declared_type
691 if writetype == null then return
692
693 var rettype = self.resolve_reassignment(v, readtype, writetype)
694
695 v.set_variable(self, variable, rettype)
696
697 self.is_typed = true
698 end
699 end
700
701
702 redef class AContinueExpr
703 redef fun accept_typing(v)
704 do
705 var nexpr = self.n_expr
706 if nexpr != null then
707 var mtype = v.visit_expr(nexpr)
708 end
709 self.is_typed = true
710 end
711 end
712
713 redef class ABreakExpr
714 redef fun accept_typing(v)
715 do
716 var nexpr = self.n_expr
717 if nexpr != null then
718 var mtype = v.visit_expr(nexpr)
719 end
720 self.is_typed = true
721 end
722 end
723
724 redef class AReturnExpr
725 redef fun accept_typing(v)
726 do
727 var nexpr = self.n_expr
728 var ret_type = v.mpropdef.as(MMethodDef).msignature.return_mtype
729 if nexpr != null then
730 if ret_type != null then
731 var mtype = v.visit_expr_subtype(nexpr, ret_type)
732 else
733 var mtype = v.visit_expr(nexpr)
734 v.error(self, "Error: Return with value in a procedure.")
735 end
736 else if ret_type != null then
737 v.error(self, "Error: Return without value in a function.")
738 end
739 self.is_typed = true
740 end
741 end
742
743 redef class AAbortExpr
744 redef fun accept_typing(v)
745 do
746 self.is_typed = true
747 end
748 end
749
750 redef class AIfExpr
751 redef fun accept_typing(v)
752 do
753 v.visit_expr_bool(n_expr)
754
755 v.visit_stmt(n_then)
756 v.visit_stmt(n_else)
757 self.is_typed = true
758 end
759 end
760
761 redef class AIfexprExpr
762 redef fun accept_typing(v)
763 do
764 v.visit_expr_bool(n_expr)
765
766 var t1 = v.visit_expr(n_then)
767 var t2 = v.visit_expr(n_else)
768
769 if t1 == null or t2 == null then
770 return # Skip error
771 end
772
773 var t = v.merge_types(self, [t1, t2])
774 if t == null then
775 v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
776 end
777 self.mtype = t
778 end
779 end
780
781 redef class ADoExpr
782 redef fun accept_typing(v)
783 do
784 v.visit_stmt(n_block)
785 self.is_typed = true
786 end
787 end
788
789 redef class AWhileExpr
790 redef fun accept_typing(v)
791 do
792 v.visit_expr_bool(n_expr)
793
794 v.visit_stmt(n_block)
795 self.is_typed = true
796 end
797 end
798
799 redef class ALoopExpr
800 redef fun accept_typing(v)
801 do
802 v.visit_stmt(n_block)
803 self.is_typed = true
804 end
805 end
806
807 redef class AForExpr
808 var coltype: nullable MClassType
809
810 var method_iterator: nullable CallSite
811 var method_is_ok: nullable CallSite
812 var method_item: nullable CallSite
813 var method_next: nullable CallSite
814 var method_key: nullable CallSite
815
816 private fun do_type_iterator(v: TypeVisitor, mtype: MType)
817 do
818 if mtype isa MNullType then
819 v.error(self, "Type error: 'for' cannot iterate over 'null'")
820 return
821 end
822
823 # get obj class
824 var objcla = v.get_mclass(self, "Object")
825 if objcla == null then return
826
827 # check iterator method
828 var itdef = v.get_method(self, mtype, "iterator", true)
829 if itdef == null then
830 v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
831 return
832 end
833 self.method_iterator = itdef
834
835 # check that iterator return something
836 var ittype = itdef.msignature.return_mtype
837 if ittype == null then
838 v.error(self, "Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.")
839 return
840 end
841
842 # get iterator type
843 var colit_cla = v.try_get_mclass(self, "Iterator")
844 var mapit_cla = v.try_get_mclass(self, "MapIterator")
845 var is_col = false
846 var is_map = false
847
848 if colit_cla != null and v.is_subtype(ittype, colit_cla.get_mtype([objcla.mclass_type.as_nullable])) then
849 # Iterator
850 var coltype = ittype.supertype_to(v.mmodule, v.anchor, colit_cla)
851 var variables = self.variables
852 if variables.length != 1 then
853 v.error(self, "Type Error: 'for' expects only one variable when using 'Iterator'.")
854 else
855 variables.first.declared_type = coltype.arguments.first
856 end
857 is_col = true
858 end
859
860 if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type, objcla.mclass_type.as_nullable])) then
861 # Map Iterator
862 var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
863 var variables = self.variables
864 if variables.length != 2 then
865 v.error(self, "Type Error: 'for' expects two variables when using 'MapIterator'.")
866 else
867 variables[0].declared_type = coltype.arguments[0]
868 variables[1].declared_type = coltype.arguments[1]
869 end
870 is_map = true
871 end
872
873 if not is_col and not is_map then
874 v.error(self, "Type Error: 'for' expects method 'iterator' to return an 'Iterator' or 'MapIterator' type'.")
875 return
876 end
877
878 # anchor formal and virtual types
879 if mtype.need_anchor then mtype = v.anchor_to(mtype)
880
881 if mtype isa MNullableType then mtype = mtype.mtype
882 self.coltype = mtype.as(MClassType)
883
884 # get methods is_ok, next, item
885 var ikdef = v.get_method(self, ittype, "is_ok", false)
886 if ikdef == null then
887 v.error(self, "Type Error: 'for' expects a method 'is_ok' in 'Iterator' type {ittype}.")
888 return
889 end
890 self.method_is_ok = ikdef
891
892 var itemdef = v.get_method(self, ittype, "item", false)
893 if itemdef == null then
894 v.error(self, "Type Error: 'for' expects a method 'item' in 'Iterator' type {ittype}.")
895 return
896 end
897 self.method_item = itemdef
898
899 var nextdef = v.get_method(self, ittype, "next", false)
900 if nextdef == null then
901 v.error(self, "Type Error: 'for' expects a method 'next' in 'Iterator' type {ittype}.")
902 return
903 end
904 self.method_next = nextdef
905
906 if is_map then
907 var keydef = v.get_method(self, ittype, "key", false)
908 if keydef == null then
909 v.error(self, "Type Error: 'for' expects a method 'key' in 'Iterator' type {ittype}.")
910 return
911 end
912 self.method_key = keydef
913 end
914 end
915
916 redef fun accept_typing(v)
917 do
918 var mtype = v.visit_expr(n_expr)
919 if mtype == null then return
920
921 self.do_type_iterator(v, mtype)
922
923 v.visit_stmt(n_block)
924 self.is_typed = true
925 end
926 end
927
928 redef class AAssertExpr
929 redef fun accept_typing(v)
930 do
931 v.visit_expr_bool(n_expr)
932
933 v.visit_stmt(n_else)
934 self.is_typed = true
935 end
936 end
937
938 redef class AOrExpr
939 redef fun accept_typing(v)
940 do
941 v.visit_expr_bool(n_expr)
942 v.visit_expr_bool(n_expr2)
943 self.mtype = v.type_bool(self)
944 end
945 end
946
947 redef class AImpliesExpr
948 redef fun accept_typing(v)
949 do
950 v.visit_expr_bool(n_expr)
951 v.visit_expr_bool(n_expr2)
952 self.mtype = v.type_bool(self)
953 end
954 end
955
956 redef class AAndExpr
957 redef fun accept_typing(v)
958 do
959 v.visit_expr_bool(n_expr)
960 v.visit_expr_bool(n_expr2)
961 self.mtype = v.type_bool(self)
962 end
963 end
964
965
966 redef class ANotExpr
967 redef fun accept_typing(v)
968 do
969 v.visit_expr_bool(n_expr)
970 self.mtype = v.type_bool(self)
971 end
972 end
973
974 redef class AOrElseExpr
975 redef fun accept_typing(v)
976 do
977 var t1 = v.visit_expr(n_expr)
978 var t2 = v.visit_expr(n_expr2)
979
980 if t1 == null or t2 == null then
981 return # Skip error
982 end
983
984 if t1 isa MNullableType then
985 t1 = t1.mtype
986 end
987
988 var t = v.merge_types(self, [t1, t2])
989 if t == null then
990 t = v.mmodule.object_type
991 if t2 isa MNullableType then
992 t = t.as_nullable
993 end
994 #v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
995 end
996 self.mtype = t
997 end
998 end
999
1000 redef class ATrueExpr
1001 redef fun accept_typing(v)
1002 do
1003 self.mtype = v.type_bool(self)
1004 end
1005 end
1006
1007 redef class AFalseExpr
1008 redef fun accept_typing(v)
1009 do
1010 self.mtype = v.type_bool(self)
1011 end
1012 end
1013
1014 redef class AIntExpr
1015 redef fun accept_typing(v)
1016 do
1017 var mclass = v.get_mclass(self, "Int")
1018 if mclass == null then return # Forward error
1019 self.mtype = mclass.mclass_type
1020 end
1021 end
1022
1023 redef class AFloatExpr
1024 redef fun accept_typing(v)
1025 do
1026 var mclass = v.get_mclass(self, "Float")
1027 if mclass == null then return # Forward error
1028 self.mtype = mclass.mclass_type
1029 end
1030 end
1031
1032 redef class ACharExpr
1033 redef fun accept_typing(v)
1034 do
1035 var mclass = v.get_mclass(self, "Char")
1036 if mclass == null then return # Forward error
1037 self.mtype = mclass.mclass_type
1038 end
1039 end
1040
1041 redef class AStringFormExpr
1042 redef fun accept_typing(v)
1043 do
1044 var mclass = v.get_mclass(self, "String")
1045 if mclass == null then return # Forward error
1046 self.mtype = mclass.mclass_type
1047 end
1048 end
1049
1050 redef class ASuperstringExpr
1051 redef fun accept_typing(v)
1052 do
1053 var mclass = v.get_mclass(self, "String")
1054 if mclass == null then return # Forward error
1055 self.mtype = mclass.mclass_type
1056 for nexpr in self.n_exprs do
1057 var t = v.visit_expr(nexpr)
1058 end
1059 end
1060 end
1061
1062 redef class AArrayExpr
1063 var with_capacity_callsite: nullable CallSite
1064 var push_callsite: nullable CallSite
1065
1066 redef fun accept_typing(v)
1067 do
1068 var mtypes = new Array[nullable MType]
1069 for e in self.n_exprs.n_exprs do
1070 var t = v.visit_expr(e)
1071 if t == null then
1072 return # Skip error
1073 end
1074 mtypes.add(t)
1075 end
1076 var mtype = v.merge_types(self, mtypes)
1077 if mtype == null then
1078 v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
1079 return
1080 end
1081 var mclass = v.get_mclass(self, "Array")
1082 if mclass == null then return # Forward error
1083 var array_mtype = mclass.get_mtype([mtype])
1084
1085 with_capacity_callsite = v.get_method(self, array_mtype, "with_capacity", false)
1086 push_callsite = v.get_method(self, array_mtype, "push", false)
1087
1088 self.mtype = array_mtype
1089 end
1090 end
1091
1092 redef class ARangeExpr
1093 var init_callsite: nullable CallSite
1094
1095 redef fun accept_typing(v)
1096 do
1097 var discrete_class = v.get_mclass(self, "Discrete")
1098 if discrete_class == null then return # Forward error
1099 var discrete_type = discrete_class.intro.bound_mtype
1100 var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
1101 var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
1102 if t1 == null or t2 == null then return
1103 var mclass = v.get_mclass(self, "Range")
1104 if mclass == null then return # Forward error
1105 var mtype
1106 if v.is_subtype(t1, t2) then
1107 mtype = mclass.get_mtype([t2])
1108 else if v.is_subtype(t2, t1) then
1109 mtype = mclass.get_mtype([t1])
1110 else
1111 v.error(self, "Type Error: Cannot create range: {t1} vs {t2}")
1112 return
1113 end
1114
1115 self.mtype = mtype
1116
1117 # get the constructor
1118 var callsite
1119 if self isa ACrangeExpr then
1120 callsite = v.get_method(self, mtype, "init", false)
1121 else if self isa AOrangeExpr then
1122 callsite = v.get_method(self, mtype, "without_last", false)
1123 else
1124 abort
1125 end
1126 init_callsite = callsite
1127 end
1128 end
1129
1130 redef class ANullExpr
1131 redef fun accept_typing(v)
1132 do
1133 self.mtype = v.mmodule.model.null_type
1134 end
1135 end
1136
1137 redef class AIsaExpr
1138 # The static type to cast to.
1139 # (different from the static type of the expression that is `Bool`).
1140 var cast_type: nullable MType
1141 redef fun accept_typing(v)
1142 do
1143 var mtype = v.visit_expr_cast(self, self.n_expr, self.n_type)
1144 self.cast_type = mtype
1145
1146 var variable = self.n_expr.its_variable
1147 if variable != null then
1148 var orig = self.n_expr.mtype
1149 var from = if orig != null then orig.to_s else "invalid"
1150 var to = if mtype != null then mtype.to_s else "invalid"
1151 #debug("adapt {variable}: {from} -> {to}")
1152 self.after_flow_context.when_true.set_var(variable, mtype)
1153 end
1154
1155 self.mtype = v.type_bool(self)
1156 end
1157 end
1158
1159 redef class AAsCastExpr
1160 redef fun accept_typing(v)
1161 do
1162 self.mtype = v.visit_expr_cast(self, self.n_expr, self.n_type)
1163 end
1164 end
1165
1166 redef class AAsNotnullExpr
1167 redef fun accept_typing(v)
1168 do
1169 var mtype = v.visit_expr(self.n_expr)
1170 if mtype isa MNullType then
1171 v.error(self, "Type error: as(not null) on null")
1172 return
1173 end
1174 if mtype isa MNullableType then
1175 self.mtype = mtype.mtype
1176 return
1177 end
1178 # TODO: warn on useless as not null
1179 self.mtype = mtype
1180 end
1181 end
1182
1183 redef class AProxyExpr
1184 redef fun accept_typing(v)
1185 do
1186 self.mtype = v.visit_expr(self.n_expr)
1187 end
1188 end
1189
1190 redef class ASelfExpr
1191 redef var its_variable: nullable Variable
1192 redef fun accept_typing(v)
1193 do
1194 var variable = v.selfvariable
1195 self.its_variable = variable
1196 self.mtype = v.get_variable(self, variable)
1197 end
1198 end
1199
1200 ## MESSAGE SENDING AND PROPERTY
1201
1202 redef class ASendExpr
1203 # The property invoked by the send.
1204 var callsite: nullable CallSite
1205
1206 redef fun accept_typing(v)
1207 do
1208 var recvtype = v.visit_expr(self.n_expr)
1209 var name = self.property_name
1210
1211 if recvtype == null then return # Forward error
1212 if recvtype isa MNullType then
1213 v.error(self, "Error: Method '{name}' call on 'null'.")
1214 return
1215 end
1216
1217 var callsite = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
1218 if callsite == null then return
1219 self.callsite = callsite
1220 var msignature = callsite.msignature
1221
1222 var args = compute_raw_arguments
1223
1224 callsite.check_signature(v, args)
1225
1226 if callsite.mproperty.is_init then
1227 var vmpropdef = v.mpropdef
1228 if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
1229 v.error(self, "Can call a init only in another init")
1230 end
1231 end
1232
1233 var ret = msignature.return_mtype
1234 if ret != null then
1235 self.mtype = ret
1236 else
1237 self.is_typed = true
1238 end
1239 end
1240
1241 # The name of the property
1242 # Each subclass simply provide the correct name.
1243 private fun property_name: String is abstract
1244
1245 # An array of all arguments (excluding self)
1246 fun raw_arguments: Array[AExpr] do return compute_raw_arguments
1247
1248 private fun compute_raw_arguments: Array[AExpr] is abstract
1249 end
1250
1251 redef class ABinopExpr
1252 redef fun compute_raw_arguments do return [n_expr2]
1253 end
1254 redef class AEqExpr
1255 redef fun property_name do return "=="
1256 redef fun accept_typing(v)
1257 do
1258 super
1259
1260 var variable = self.n_expr.its_variable
1261 if variable == null then return
1262 var mtype = self.n_expr2.mtype
1263 if not mtype isa MNullType then return
1264 var vartype = v.get_variable(self, variable)
1265 if not vartype isa MNullableType then return
1266 self.after_flow_context.when_true.set_var(variable, mtype)
1267 self.after_flow_context.when_false.set_var(variable, vartype.mtype)
1268 #debug("adapt {variable}:{vartype} ; true->{mtype} false->{vartype.mtype}")
1269 end
1270 end
1271 redef class ANeExpr
1272 redef fun property_name do return "!="
1273 redef fun accept_typing(v)
1274 do
1275 super
1276
1277 var variable = self.n_expr.its_variable
1278 if variable == null then return
1279 var mtype = self.n_expr2.mtype
1280 if not mtype isa MNullType then return
1281 var vartype = v.get_variable(self, variable)
1282 if not vartype isa MNullableType then return
1283 self.after_flow_context.when_false.set_var(variable, mtype)
1284 self.after_flow_context.when_true.set_var(variable, vartype.mtype)
1285 #debug("adapt {variable}:{vartype} ; true->{vartype.mtype} false->{mtype}")
1286 end
1287 end
1288 redef class ALtExpr
1289 redef fun property_name do return "<"
1290 end
1291 redef class ALeExpr
1292 redef fun property_name do return "<="
1293 end
1294 redef class ALlExpr
1295 redef fun property_name do return "<<"
1296 end
1297 redef class AGtExpr
1298 redef fun property_name do return ">"
1299 end
1300 redef class AGeExpr
1301 redef fun property_name do return ">="
1302 end
1303 redef class AGgExpr
1304 redef fun property_name do return ">>"
1305 end
1306 redef class APlusExpr
1307 redef fun property_name do return "+"
1308 end
1309 redef class AMinusExpr
1310 redef fun property_name do return "-"
1311 end
1312 redef class AStarshipExpr
1313 redef fun property_name do return "<=>"
1314 end
1315 redef class AStarExpr
1316 redef fun property_name do return "*"
1317 end
1318 redef class ASlashExpr
1319 redef fun property_name do return "/"
1320 end
1321 redef class APercentExpr
1322 redef fun property_name do return "%"
1323 end
1324
1325 redef class AUminusExpr
1326 redef fun property_name do return "unary -"
1327 redef fun compute_raw_arguments do return new Array[AExpr]
1328 end
1329
1330
1331 redef class ACallExpr
1332 redef fun property_name do return n_id.text
1333 redef fun compute_raw_arguments do return n_args.to_a
1334 end
1335
1336 redef class ACallAssignExpr
1337 redef fun property_name do return n_id.text + "="
1338 redef fun compute_raw_arguments
1339 do
1340 var res = n_args.to_a
1341 res.add(n_value)
1342 return res
1343 end
1344 end
1345
1346 redef class ABraExpr
1347 redef fun property_name do return "[]"
1348 redef fun compute_raw_arguments do return n_args.to_a
1349 end
1350
1351 redef class ABraAssignExpr
1352 redef fun property_name do return "[]="
1353 redef fun compute_raw_arguments
1354 do
1355 var res = n_args.to_a
1356 res.add(n_value)
1357 return res
1358 end
1359 end
1360
1361 redef class ASendReassignFormExpr
1362 # The property invoked for the writing
1363 var write_callsite: nullable CallSite
1364
1365 redef fun accept_typing(v)
1366 do
1367 var recvtype = v.visit_expr(self.n_expr)
1368 var name = self.property_name
1369
1370 if recvtype == null then return # Forward error
1371 if recvtype isa MNullType then
1372 v.error(self, "Error: Method '{name}' call on 'null'.")
1373 return
1374 end
1375
1376 var for_self = self.n_expr isa ASelfExpr
1377 var callsite = v.get_method(self, recvtype, name, for_self)
1378
1379 if callsite == null then return
1380 self.callsite = callsite
1381
1382 var args = compute_raw_arguments
1383
1384 callsite.check_signature(v, args)
1385
1386 var readtype = callsite.msignature.return_mtype
1387 if readtype == null then
1388 v.error(self, "Error: {name} is not a function")
1389 return
1390 end
1391
1392 var wcallsite = v.get_method(self, recvtype, name + "=", self.n_expr isa ASelfExpr)
1393 if wcallsite == null then return
1394 self.write_callsite = wcallsite
1395
1396 var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
1397 if wtype == null then return
1398
1399 args = args.to_a # duplicate so raw_arguments keeps only the getter args
1400 args.add(self.n_value)
1401 wcallsite.check_signature(v, args)
1402
1403 self.is_typed = true
1404 end
1405 end
1406
1407 redef class ACallReassignExpr
1408 redef fun property_name do return n_id.text
1409 redef fun compute_raw_arguments do return n_args.to_a
1410 end
1411
1412 redef class ABraReassignExpr
1413 redef fun property_name do return "[]"
1414 redef fun compute_raw_arguments do return n_args.to_a
1415 end
1416
1417 redef class AInitExpr
1418 redef fun property_name do return "init"
1419 redef fun compute_raw_arguments do return n_args.to_a
1420 end
1421
1422 redef class AExprs
1423 fun to_a: Array[AExpr] do return self.n_exprs.to_a
1424 end
1425
1426 ###
1427
1428 redef class ASuperExpr
1429 # The method to call if the super is in fact a 'super init call'
1430 # Note: if the super is a normal call-next-method, then this attribute is null
1431 var callsite: nullable CallSite
1432
1433 # The method to call is the super is a standard `call-next-method` super-call
1434 # Note: if the super is a special super-init-call, then this attribute is null
1435 var mpropdef: nullable MMethodDef
1436
1437 redef fun accept_typing(v)
1438 do
1439 var recvtype = v.nclassdef.mclassdef.bound_mtype
1440 var mproperty = v.mpropdef.mproperty
1441 if not mproperty isa MMethod then
1442 v.error(self, "Error: super only usable in a method")
1443 return
1444 end
1445 var superprops = mproperty.lookup_super_definitions(v.mmodule, recvtype)
1446 if superprops.length == 0 then
1447 if mproperty.is_init and v.mpropdef.is_intro then
1448 process_superinit(v)
1449 return
1450 end
1451 v.error(self, "Error: No super method to call for {mproperty}.")
1452 return
1453 end
1454 # FIXME: covariance of return type in linear extension?
1455 var superprop = superprops.first
1456
1457 var msignature = superprop.msignature.as(not null)
1458 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
1459 var args = self.n_args.to_a
1460 if args.length > 0 then
1461 v.check_signature(self, args, mproperty.name, msignature)
1462 end
1463 self.mtype = msignature.return_mtype
1464 self.is_typed = true
1465 v.mpropdef.has_supercall = true
1466 mpropdef = v.mpropdef.as(MMethodDef)
1467 end
1468
1469 private fun process_superinit(v: TypeVisitor)
1470 do
1471 var recvtype = v.nclassdef.mclassdef.bound_mtype
1472 var mpropdef = v.mpropdef
1473 assert mpropdef isa MMethodDef
1474 var mproperty = mpropdef.mproperty
1475 var superprop: nullable MMethodDef = null
1476 for msupertype in v.nclassdef.mclassdef.supertypes do
1477 msupertype = msupertype.anchor_to(v.mmodule, recvtype)
1478 var errcount = v.modelbuilder.toolcontext.error_count
1479 var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
1480 if candidate == null then
1481 if v.modelbuilder.toolcontext.error_count > errcount then return # Forard error
1482 continue # Try next super-class
1483 end
1484 if superprop != null and superprop.mproperty != candidate then
1485 v.error(self, "Error: conflicting super constructor to call for {mproperty}: {candidate.full_name}, {superprop.mproperty.full_name}")
1486 return
1487 end
1488 var candidatedefs = candidate.lookup_definitions(v.mmodule, recvtype)
1489 if superprop != null then
1490 if superprop == candidatedefs.first then continue
1491 candidatedefs.add(superprop)
1492 end
1493 if candidatedefs.length > 1 then
1494 v.error(self, "Error: confliting property definitions for property {mproperty} in {recvtype}: {candidatedefs.join(", ")}")
1495 return
1496 end
1497 superprop = candidatedefs.first
1498 end
1499 if superprop == null then
1500 v.error(self, "Error: No super method to call for {mproperty}.")
1501 return
1502 end
1503
1504 var msignature = superprop.msignature.as(not null)
1505 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
1506
1507 var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
1508 self.callsite = callsite
1509
1510 var args = self.n_args.to_a
1511 if args.length > 0 then
1512 callsite.check_signature(v, args)
1513 else
1514 # Check there is at least enough parameters
1515 if mpropdef.msignature.arity < msignature.arity then
1516 v.error(self, "Error: Not enough implicit arguments to pass. Got {mpropdef.msignature.arity}, expected at least {msignature.arity}. Signature is {msignature}")
1517 return
1518 end
1519 # Check that each needed parameter is conform
1520 var i = 0
1521 for sp in msignature.mparameters do
1522 var p = mpropdef.msignature.mparameters[i]
1523 if not v.is_subtype(p.mtype, sp.mtype) then
1524 v.error(self, "Type error: expected argument #{i} of type {sp.mtype}, got implicit argument {p.name} of type {p.mtype}. Signature is {msignature}")
1525 return
1526 end
1527 i += 1
1528 end
1529 end
1530
1531 self.is_typed = true
1532 end
1533 end
1534
1535 ####
1536
1537 redef class ANewExpr
1538 # The constructor invoked by the new.
1539 var callsite: nullable CallSite
1540
1541 redef fun accept_typing(v)
1542 do
1543 var recvtype = v.resolve_mtype(self.n_type)
1544 if recvtype == null then return
1545 self.mtype = recvtype
1546
1547 if not recvtype isa MClassType then
1548 if recvtype isa MNullableType then
1549 v.error(self, "Type error: cannot instantiate the nullable type {recvtype}.")
1550 return
1551 else
1552 v.error(self, "Type error: cannot instantiate the formal type {recvtype}.")
1553 return
1554 end
1555 else
1556 if recvtype.mclass.kind == abstract_kind then
1557 v.error(self, "Cannot instantiate abstract class {recvtype}.")
1558 return
1559 else if recvtype.mclass.kind == interface_kind then
1560 v.error(self, "Cannot instantiate interface {recvtype}.")
1561 return
1562 end
1563 end
1564
1565 var name: String
1566 var nid = self.n_id
1567 if nid != null then
1568 name = nid.text
1569 else
1570 name = "init"
1571 end
1572 var callsite = v.get_method(self, recvtype, name, false)
1573 if callsite == null then return
1574
1575 self.callsite = callsite
1576
1577 if not callsite.mproperty.is_init_for(recvtype.mclass) then
1578 v.error(self, "Error: {name} is not a constructor.")
1579 return
1580 end
1581
1582 var args = n_args.to_a
1583 callsite.check_signature(v, args)
1584 end
1585 end
1586
1587 ####
1588
1589 redef class AAttrFormExpr
1590 # The attribute acceded.
1591 var mproperty: nullable MAttribute
1592
1593 # The static type of the attribute.
1594 var attr_type: nullable MType
1595
1596 # Resolve the attribute acceded.
1597 private fun resolve_property(v: TypeVisitor)
1598 do
1599 var recvtype = v.visit_expr(self.n_expr)
1600 if recvtype == null then return # Skip error
1601 var name = self.n_id.text
1602 if recvtype isa MNullType then
1603 v.error(self, "Error: Attribute '{name}' access on 'null'.")
1604 return
1605 end
1606
1607 var unsafe_type = v.anchor_to(recvtype)
1608 var mproperty = v.try_get_mproperty_by_name2(self, unsafe_type, name)
1609 if mproperty == null then
1610 v.modelbuilder.error(self, "Error: Attribute {name} doesn't exists in {recvtype}.")
1611 return
1612 end
1613 assert mproperty isa MAttribute
1614 self.mproperty = mproperty
1615
1616 var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
1617 assert mpropdefs.length == 1
1618 var mpropdef = mpropdefs.first
1619 var attr_type = mpropdef.static_mtype.as(not null)
1620 attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
1621 self.attr_type = attr_type
1622 end
1623 end
1624
1625 redef class AAttrExpr
1626 redef fun accept_typing(v)
1627 do
1628 self.resolve_property(v)
1629 self.mtype = self.attr_type
1630 end
1631 end
1632
1633
1634 redef class AAttrAssignExpr
1635 redef fun accept_typing(v)
1636 do
1637 self.resolve_property(v)
1638 var mtype = self.attr_type
1639
1640 v.visit_expr_subtype(self.n_value, mtype)
1641 self.is_typed = true
1642 end
1643 end
1644
1645 redef class AAttrReassignExpr
1646 redef fun accept_typing(v)
1647 do
1648 self.resolve_property(v)
1649 var mtype = self.attr_type
1650 if mtype == null then return # Skip error
1651
1652 self.resolve_reassignment(v, mtype, mtype)
1653
1654 self.is_typed = true
1655 end
1656 end
1657
1658 redef class AIssetAttrExpr
1659 redef fun accept_typing(v)
1660 do
1661 self.resolve_property(v)
1662 var mtype = self.attr_type
1663 if mtype == null then return # Skip error
1664
1665 var recvtype = self.n_expr.mtype.as(not null)
1666 var bound = v.resolve_for(mtype, recvtype, false)
1667 if bound isa MNullableType then
1668 v.error(self, "Error: isset on a nullable attribute.")
1669 end
1670 self.mtype = v.type_bool(self)
1671 end
1672 end
1673
1674 ###
1675
1676 redef class ADebugTypeExpr
1677 redef fun accept_typing(v)
1678 do
1679 var expr = v.visit_expr(self.n_expr)
1680 if expr == null then return
1681 var unsafe = v.anchor_to(expr)
1682 var ntype = self.n_type
1683 var mtype = v.resolve_mtype(ntype)
1684 if mtype != null and mtype != expr then
1685 var umtype = v.anchor_to(mtype)
1686 v.modelbuilder.warning(self, "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
1687 end
1688 self.is_typed = true
1689 end
1690 end