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