model: Make the `anchor` parameter of `MType::anchor_to` nullable
[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 import literal
24
25 redef class ToolContext
26 var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
27 end
28
29 private class TypingPhase
30 super Phase
31 redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
32 end
33
34 private class TypeVisitor
35 var modelbuilder: ModelBuilder
36
37 # The module of the analysis
38 # Used to correctly query the model
39 var mmodule: MModule
40
41 # The static type of the receiver
42 # Mainly used for type tests and type resolutions
43 var anchor: nullable MClassType = null
44
45 # The analyzed mclassdef
46 var mclassdef: nullable MClassDef = null
47
48 # The analyzed property
49 var mpropdef: nullable MPropDef
50
51 var selfvariable = new Variable("self")
52
53 # Is `self` use restricted?
54 # * no explicit `self`
55 # * method called on the implicit self must be top-level
56 # Currently only used for `new` factory since there is no valid receiver inside
57 var is_toplevel_context = false
58
59 init
60 do
61 var mpropdef = self.mpropdef
62
63 if mpropdef != null then
64 self.mpropdef = mpropdef
65 var mclassdef = mpropdef.mclassdef
66 self.mclassdef = mclassdef
67 self.anchor = mclassdef.bound_mtype
68
69 var mclass = mclassdef.mclass
70
71 var selfvariable = new Variable("self")
72 self.selfvariable = selfvariable
73 selfvariable.declared_type = mclass.mclass_type
74
75 var mprop = mpropdef.mproperty
76 if mprop isa MMethod and mprop.is_new then
77 is_toplevel_context = true
78 end
79 end
80 end
81
82 fun anchor_to(mtype: MType): MType
83 do
84 return mtype.anchor_to(mmodule, anchor)
85 end
86
87 fun is_subtype(sub, sup: MType): Bool
88 do
89 return sub.is_subtype(mmodule, anchor, sup)
90 end
91
92 fun resolve_for(mtype, subtype: MType, for_self: Bool): MType
93 do
94 #print "resolve_for {mtype} sub={subtype} forself={for_self} mmodule={mmodule} anchor={anchor}"
95 var res = mtype.resolve_for(subtype, anchor, mmodule, not for_self)
96 return res
97 end
98
99 # Check that `sub` is a subtype of `sup`.
100 # If `sub` is not a valid suptype, then display an error on `node` and return `null`.
101 # If `sub` is a safe subtype of `sup`, then return `sub`.
102 # If `sub` is an unsafe subtype (i.e., an implicit cast is required), then return `sup`.
103 #
104 # The point of the return type is to determinate the usable type on an expression when `autocast` is true:
105 # If the suptype is safe, then the return type is the one on the expression typed by `sub`.
106 # Is the subtype is unsafe, then the return type is the one of an implicit cast on `sup`.
107 fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
108 do
109 if self.is_subtype(sub, sup) then return sub
110 if autocast and self.is_subtype(sub, self.anchor_to(sup)) then
111 # FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
112 #node.debug("Unsafe typing: expected {sup}, got {sub}")
113 return sup
114 end
115 if sup isa MErrorType then return null # Skip error
116 if sub.need_anchor then
117 var u = anchor_to(sub)
118 self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}: {u}`.")
119 else
120 self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}`.")
121 end
122 return null
123 end
124
125 # Visit an expression and do not care about the return value
126 fun visit_stmt(nexpr: nullable AExpr)
127 do
128 if nexpr == null then return
129 nexpr.accept_typing(self)
130 end
131
132 # Visit an expression and expects that it is not a statement
133 # Return the type of the expression
134 # Display an error and return null if:
135 # * the type cannot be determined or
136 # * `nexpr` is a statement
137 fun visit_expr(nexpr: AExpr): nullable MType
138 do
139 nexpr.accept_typing(self)
140 var mtype = nexpr.mtype
141 if mtype != null then return mtype
142 if not nexpr.is_typed then
143 if not self.modelbuilder.toolcontext.error_count > 0 then # check that there is really an error
144 if self.modelbuilder.toolcontext.verbose_level > 1 then
145 nexpr.debug("No return type but no error.")
146 end
147 end
148 return null # forward error
149 end
150 var more_message = null
151 var p = nexpr.parent
152 if p != null then more_message = p.bad_expr_message(nexpr)
153 if more_message == null then more_message = "" else more_message = " " + more_message
154 self.error(nexpr, "Error: expected an expression{more_message}.")
155 return null
156 end
157
158 # Visit an expression and expect its static type is a least a `sup`
159 # Return the type of the expression or null if
160 # * the type cannot be determined or
161 # * `nexpr` is a statement or
162 # * `nexpr` is not a `sup`
163 fun visit_expr_subtype(nexpr: AExpr, sup: nullable MType): nullable MType
164 do
165 var sub = visit_expr(nexpr)
166 if sub == null then return null # Forward error
167
168 if sup == null then return null # Forward error
169
170 var res = check_subtype(nexpr, sub, sup, true)
171 if res != sub then
172 nexpr.implicit_cast_to = res
173 end
174 return res
175 end
176
177 # Visit an expression and expect its static type is a `Bool`
178 # Return the type of the expression or null if
179 # * the type cannot be determined or
180 # * `nexpr` is a statement or
181 # * `nexpr` is not a `Bool`
182 fun visit_expr_bool(nexpr: AExpr): nullable MType
183 do
184 return self.visit_expr_subtype(nexpr, self.type_bool(nexpr))
185 end
186
187
188 fun check_expr_cast(node: ANode, nexpr: AExpr, ntype: AType): nullable MType
189 do
190 var sub = nexpr.mtype
191 if sub == null then return null # Forward error
192
193 var sup = ntype.mtype
194 if sup == null then return null # Forward error
195
196 if sup == sub then
197 self.modelbuilder.warning(node, "useless-type-test", "Warning: expression is already a `{sup}`.")
198 else if self.is_subtype(sub, sup) then
199 self.modelbuilder.warning(node, "useless-type-test", "Warning: expression is already a `{sup}` since it is a `{sub}`.")
200 end
201 return sup
202 end
203
204 # Can `mtype` be null (up to the current knowledge)?
205 fun can_be_null(mtype: MType): Bool
206 do
207 if mtype isa MNullableType or mtype isa MNullType then return true
208 if mtype isa MFormalType then
209 var x = anchor_to(mtype)
210 if x isa MNullableType or x isa MNullType then return true
211 end
212 return false
213 end
214
215 # Check that `mtype` can be null (up to the current knowledge).
216 #
217 # If not then display a `useless-null-test` warning on node and return false.
218 # Else return true.
219 fun check_can_be_null(anode: ANode, mtype: MType): Bool
220 do
221 if mtype isa MNullType then
222 modelbuilder.warning(anode, "useless-null-test", "Warning: expression is always `null`.")
223 return true
224 end
225 if can_be_null(mtype) then return true
226
227 if mtype isa MFormalType then
228 var res = anchor_to(mtype)
229 modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}: {res}`.")
230 else
231 modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
232 end
233 return false
234 end
235
236 # Special verification on != and == for null
237 # Return true
238 fun null_test(anode: ABinopExpr)
239 do
240 var mtype = anode.n_expr.mtype
241 var mtype2 = anode.n_expr2.mtype
242
243 if mtype == null or mtype2 == null then return
244
245 if not mtype2 isa MNullType then return
246
247 # Check of useless null
248 if not can_be_null(mtype) then return
249
250 if mtype isa MNullType then
251 # Because of type adaptation, we cannot just stop here
252 # so return use `null` as a bottom type that will be merged easily (cf) `merge_types`
253 mtype = null
254 else
255 mtype = mtype.as_notnull
256 end
257
258 # Check for type adaptation
259 var variable = anode.n_expr.its_variable
260 if variable == null then return
261
262 # One is null (mtype2 see above) the other is not null
263 if anode isa AEqExpr then
264 anode.after_flow_context.when_true.set_var(self, variable, mtype2)
265 anode.after_flow_context.when_false.set_var(self, variable, mtype)
266 else if anode isa ANeExpr then
267 anode.after_flow_context.when_false.set_var(self, variable, mtype2)
268 anode.after_flow_context.when_true.set_var(self, variable, mtype)
269 else
270 abort
271 end
272 end
273
274 fun try_get_mproperty_by_name2(anode: ANode, mtype: MType, name: String): nullable MProperty
275 do
276 return self.modelbuilder.try_get_mproperty_by_name2(anode, mmodule, mtype, name)
277 end
278
279 fun resolve_mtype(node: AType): nullable MType
280 do
281 return self.modelbuilder.resolve_mtype(mmodule, mclassdef, node)
282 end
283
284 fun try_get_mclass(node: ANode, name: String): nullable MClass
285 do
286 var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
287 return mclass
288 end
289
290 fun get_mclass(node: ANode, name: String): nullable MClass
291 do
292 var mclass = modelbuilder.get_mclass_by_name(node, mmodule, name)
293 return mclass
294 end
295
296 fun type_bool(node: ANode): nullable MType
297 do
298 var mclass = self.get_mclass(node, "Bool")
299 if mclass == null then return null
300 return mclass.mclass_type
301 end
302
303 fun get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
304 do
305 var unsafe_type = self.anchor_to(recvtype)
306
307 #debug("recv: {recvtype} (aka {unsafe_type})")
308 if recvtype isa MNullType then
309 var objclass = get_mclass(node, "Object")
310 if objclass == null then return null # Forward error
311 unsafe_type = objclass.mclass_type
312 end
313
314 var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
315 if name == "new" and mproperty == null then
316 name = "init"
317 mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
318 end
319
320 if mproperty == null then
321 if recv_is_self then
322 self.modelbuilder.error(node, "Error: method or variable `{name}` unknown in `{recvtype}`.")
323 else if recvtype.need_anchor then
324 self.modelbuilder.error(node, "Error: method `{name}` does not exists in `{recvtype}: {unsafe_type}`.")
325 else
326 self.modelbuilder.error(node, "Error: method `{name}` does not exists in `{recvtype}`.")
327 end
328 return null
329 end
330
331 assert mproperty isa MMethod
332
333 # `null` only accepts some methods of object.
334 if recvtype isa MNullType and not mproperty.is_null_safe then
335 self.error(node, "Error: method `{name}` called on `null`.")
336 return null
337 else if unsafe_type isa MNullableType and not mproperty.is_null_safe then
338 modelbuilder.advice(node, "call-on-nullable", "Warning: method call on a nullable receiver `{recvtype}`.")
339 end
340
341 if is_toplevel_context and recv_is_self and not mproperty.is_toplevel then
342 error(node, "Error: `{name}` is not a top-level method, thus need a receiver.")
343 end
344 if not recv_is_self and mproperty.is_toplevel then
345 error(node, "Error: cannot call `{name}`, a top-level method, with a receiver.")
346 end
347
348 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
349 self.modelbuilder.error(node, "Error: method `{name}` is protected and can only accessed by `self`.")
350 return null
351 end
352
353 var info = mproperty.deprecation
354 if info != null and self.mpropdef.mproperty.deprecation == null then
355 var mdoc = info.mdoc
356 if mdoc != null then
357 self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: method `{name}` is deprecated: {mdoc.content.first}")
358 else
359 self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: method `{name}` is deprecated.")
360 end
361 end
362
363 var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
364 var mpropdef
365 if propdefs.length == 0 then
366 self.modelbuilder.error(node, "Type Error: no definition found for property `{name}` in `{unsafe_type}`.")
367 return null
368 else if propdefs.length == 1 then
369 mpropdef = propdefs.first
370 else
371 self.modelbuilder.warning(node, "property-conflict", "Warning: conflicting property definitions for property `{name}` in `{unsafe_type}`: {propdefs.join(" ")}")
372 mpropdef = mproperty.intro
373 end
374
375
376 var msignature = mpropdef.new_msignature or else mpropdef.msignature
377 if msignature == null then return null # skip error
378 msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
379
380 var erasure_cast = false
381 var rettype = mpropdef.msignature.return_mtype
382 if not recv_is_self and rettype != null then
383 rettype = rettype.undecorate
384 if rettype isa MParameterType then
385 var erased_rettype = msignature.return_mtype
386 assert erased_rettype != null
387 #node.debug("Erasure cast: Really a {rettype} but unsafely a {erased_rettype}")
388 erasure_cast = true
389 end
390 end
391
392 var callsite = new CallSite(node.hot_location, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
393 return callsite
394 end
395
396 fun try_get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
397 do
398 var unsafe_type = self.anchor_to(recvtype)
399 var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
400 if mproperty == null then return null
401 return get_method(node, recvtype, name, recv_is_self)
402 end
403
404
405 # Visit the expressions of args and check their conformity with the corresponding type in signature
406 # The point of this method is to handle varargs correctly
407 # Note: The signature must be correctly adapted
408 fun check_signature(node: ANode, args: Array[AExpr], mproperty: MProperty, msignature: MSignature): nullable SignatureMap
409 do
410 var vararg_rank = msignature.vararg_rank
411 if vararg_rank >= 0 then
412 if args.length < msignature.arity then
413 modelbuilder.error(node, "Error: expected at least {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
414 return null
415 end
416 else if args.length != msignature.arity then
417 # Too much argument
418 if args.length > msignature.arity then
419 modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
420 return null
421 end
422 # Other cases are managed later
423 end
424
425
426 #debug("CALL {unsafe_type}.{msignature}")
427
428 # Associate each parameter to a position in the arguments
429 var map = new SignatureMap
430
431 # Special case for the isolated last argument
432 # TODO: reify this method characteristics (where? the param, the signature, the method?)
433 var last_is_padded = mproperty.name.chars.last == '='
434 var nbargs = args.length
435 if last_is_padded then
436 nbargs -= 1
437 assert not args.last isa ANamedargExpr
438 map.map[msignature.arity - 1] = args.length - 1
439 self.visit_expr_subtype(args.last, msignature.mparameters.last.mtype)
440 end
441
442 # First, handle named arguments
443 for i in [0..args.length[ do
444 var e = args[i]
445 if not e isa ANamedargExpr then continue
446 var name = e.n_id.text
447 var param = msignature.mparameter_by_name(name)
448 if param == null then
449 modelbuilder.error(e.n_id, "Error: no parameter `{name}` for `{mproperty}{msignature}`.")
450 return null
451 end
452 var idx = msignature.mparameters.index_of(param)
453 var prev = map.map.get_or_null(idx)
454 if prev != null then
455 modelbuilder.error(e, "Error: parameter `{name}` already associated with argument #{prev} for `{mproperty}{msignature}`.")
456 return null
457 end
458 map.map[idx] = i
459 e.mtype = self.visit_expr_subtype(e.n_expr, param.mtype)
460 end
461
462 # Number of minimum mandatory remaining parameters
463 var min_arity = 0
464
465 # Second, associate remaining parameters
466 var vararg_decl = args.length - msignature.arity
467 var j = 0
468 for i in [0..msignature.arity[ do
469 # Skip parameters associated by name
470 if map.map.has_key(i) then continue
471
472 var param = msignature.mparameters[i]
473
474 # Search the next free argument: skip named arguments since they are already associated
475 while j < nbargs and args[j] isa ANamedargExpr do j += 1
476 if j >= nbargs then
477 if not param.mtype isa MNullableType then
478 min_arity = j + 1
479 end
480 j += 1
481 continue
482 end
483 var arg = args[j]
484 map.map[i] = j
485 j += 1
486
487 if i == vararg_rank then
488 j += vararg_decl
489 continue # skip the vararg
490 end
491
492 if not param.is_vararg then
493 var paramtype = param.mtype
494 self.visit_expr_subtype(arg, paramtype)
495 else
496 check_one_vararg(arg, param)
497 end
498 end
499
500 if min_arity > 0 then
501 if last_is_padded then min_arity += 1
502 if min_arity < msignature.arity then
503 modelbuilder.error(node, "Error: expected at least {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
504 else
505 modelbuilder.error(node, "Error: expected {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
506 end
507 return null
508 end
509
510 # Third, check varargs
511 if vararg_rank >= 0 then
512 var paramtype = msignature.mparameters[vararg_rank].mtype
513 var first = args[vararg_rank]
514 if vararg_decl == 0 then
515 if not check_one_vararg(first, msignature.mparameters[vararg_rank]) then return null
516 else
517 first.vararg_decl = vararg_decl + 1
518 for i in [vararg_rank..vararg_rank+vararg_decl] do
519 self.visit_expr_subtype(args[i], paramtype)
520 end
521 end
522 end
523
524 return map
525 end
526
527 # Check an expression as a single vararg.
528 # The main point of the method if to handle the case of reversed vararg (see `AVarargExpr`)
529 fun check_one_vararg(arg: AExpr, param: MParameter): Bool
530 do
531 var paramtype = param.mtype
532 var mclass = get_mclass(arg, "Array")
533 if mclass == null then return false # Forward error
534 var array_mtype = mclass.get_mtype([paramtype])
535 if arg isa AVarargExpr then
536 self.visit_expr_subtype(arg.n_expr, array_mtype)
537 arg.mtype = arg.n_expr.mtype
538 else
539 # only one vararg, maybe `...` was forgot, so be gentle!
540 var t = visit_expr(arg)
541 if t == null then return false # Forward error
542 if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
543 # Not acceptable but could be a `...`
544 error(arg, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
545 return false
546 end
547 # Standard valid vararg, finish the job
548 arg.vararg_decl = 1
549 self.visit_expr_subtype(arg, paramtype)
550 end
551 return true
552 end
553
554 fun error(node: ANode, message: String)
555 do
556 self.modelbuilder.error(node, message)
557 end
558
559 fun get_variable(node: AExpr, variable: Variable): nullable MType
560 do
561 if not variable.is_adapted then return variable.declared_type
562
563 var flow = node.after_flow_context
564 if flow == null then return null # skip error
565
566 if flow.vars.has_key(variable) then
567 return flow.vars[variable]
568 else
569 #node.debug("*** START Collected for {variable}")
570 var mtypes = flow.collect_types(variable)
571 #node.debug("**** END Collected for {variable}")
572 if mtypes.length == 0 then
573 return variable.declared_type
574 else if mtypes.length == 1 then
575 return mtypes.first
576 else
577 var res = merge_types(node,mtypes)
578 if res == null then
579 res = variable.declared_type
580 # Try to fallback to a non-null version
581 if res != null and can_be_null(res) then do
582 for t in mtypes do
583 if t != null and can_be_null(t) then break label
584 end
585 res = res.as_notnull
586 end label
587 end
588 return res
589 end
590 end
591 end
592
593 # Some variables where type-adapted during the visit
594 var dirty = false
595
596 # Some loops had been visited during the visit
597 var has_loop = false
598
599 fun set_variable(node: AExpr, variable: Variable, mtype: nullable MType)
600 do
601 var flow = node.after_flow_context
602 assert flow != null
603
604 flow.set_var(self, variable, mtype)
605 end
606
607 # Find the exact representable most specific common super-type in `col`.
608 #
609 # Try to find the most specific common type that is a super-type of each types
610 # in `col`.
611 # In most cases, the result is simply the most general type in `col`.
612 # If nullables types are involved, then the nullable information is correctly preserved.
613 # If incomparable super-types exists in `col`, them no solution is given and the `null`
614 # value is returned (since union types are non representable in Nit)
615 #
616 # The `null` values in `col` are ignored, nulltypes (MNullType) are considered.
617 #
618 # Returns the `null` value if:
619 #
620 # * `col` is empty
621 # * `col` only have null values
622 # * there is a conflict
623 #
624 # Example (with a diamond A,B,C,D):
625 #
626 # * merge(A,B,C) -> A, because A is the most general type in {A,B,C}
627 # * merge(C,B) -> null, there is conflict, because `B or C` cannot be represented
628 # * merge(A,nullable B) -> nullable A, because A is the most general type and
629 # the nullable information is preserved
630 fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
631 do
632 if col.length == 1 then return col.first
633 for t1 in col do
634 if t1 == null then continue # return null
635 var found = true
636 for t2 in col do
637 if t2 == null then continue # return null
638 if can_be_null(t2) and not can_be_null(t1) then
639 t1 = t1.as_nullable
640 end
641 if not is_subtype(t2, t1) then found = false
642 end
643 if found then
644 #print "merge {col.join(" ")} -> {t1}"
645 return t1
646 end
647 end
648 #self.modelbuilder.warning(node, "Type Error: {col.length} conflicting types: <{col.join(", ")}>")
649 return null
650 end
651
652 # Find a most general common subtype between `type1` and `type2`.
653 #
654 # Find the most general type that is a subtype of `type2` and, if possible, a subtype of `type1`.
655 # Basically, this return the most specific type between `type1` and `type2`.
656 # If nullable types are involved, the information is correctly preserved.
657 # If `type1` and `type2` are incomparable then `type2` is preferred (since intersection types
658 # are not representable in Nit).
659 #
660 # The `null` value is returned if both `type1` and `type2` are null.
661 #
662 # Examples (with diamond A,B,C,D):
663 #
664 # * intersect_types(A,B) -> B, because B is a subtype of A
665 # * intersect_types(B,A) -> B, because B is a subtype of A
666 # * intersect_types(B,C) -> C, B and C are incomparable,
667 # `type2` is then preferred (`B and C` cannot be represented)
668 # * intersect_types(nullable B,A) -> B, because B<:A and the non-null information is preserved
669 # * intersect_types(B,nullable C) -> C, `type2` is preferred and the non-null information is preserved
670 fun intersect_types(node: ANode, type1, type2: nullable MType): nullable MType
671 do
672 if type1 == null then return type2
673 if type2 == null then return type1
674
675 if not can_be_null(type2) or not can_be_null(type1) then
676 type1 = type1.as_notnull
677 type2 = type2.as_notnull
678 end
679
680 var res
681 if is_subtype(type1, type2) then
682 res = type1
683 else
684 res = type2
685 end
686 return res
687 end
688
689 # Find a most general type that is a subtype of `type1` but not one of `type2`.
690 #
691 # Basically, this returns `type1`-`type2` but since there is no substraction type
692 # in Nit this just returns `type1` most of the case.
693 #
694 # The few other cases are if `type2` is a super-type and if some nullable information
695 # is present.
696 #
697 # The `null` value is returned if `type1` is null.
698 #
699 # Examples (with diamond A,B,C,D):
700 #
701 # * diff_types(A,B) -> A, because the notB cannot be represented
702 # * diff_types(B,A) -> None (absurd type), because B<:A
703 # * diff_types(nullable A, nullable B) -> A, because null is removed
704 # * diff_types(nullable B, A) -> Null, because anything but null is removed
705 fun diff_types(node: ANode, type1, type2: nullable MType): nullable MType
706 do
707 if type1 == null then return null
708 if type2 == null then return type1
709
710 # if t1 <: t2 then t1-t2 = bottom
711 if is_subtype(type1, type2) then
712 return modelbuilder.model.null_type.as_notnull
713 end
714
715 # else if t1 <: nullable t2 then t1-t2 = nulltype
716 if is_subtype(type1, type2.as_nullable) then
717 return modelbuilder.model.null_type
718 end
719
720 # else t2 can be null and type2 must accept null then null is excluded in t1
721 if can_be_null(type1) and (type2 isa MNullableType or type2 isa MNullType) then
722 return type1.as_notnull
723 end
724
725 return type1
726 end
727 end
728
729 # Mapping between parameters and arguments in a call.
730 #
731 # Parameters and arguments are not stored in the class but referenced by their position (starting from 0)
732 #
733 # The point of this class is to help engine and other things to map arguments in the AST to parameters of the model.
734 class SignatureMap
735 # Associate a parameter to an argument
736 var map = new ArrayMap[Int, Int]
737 end
738
739 # A specific method call site with its associated informations.
740 class CallSite
741 super MEntity
742
743 redef var location: Location
744
745 # The static type of the receiver (possibly unresolved)
746 var recv: MType
747
748 # The module where the callsite is present
749 var mmodule: MModule
750
751 # The anchor to use with `recv` or `msignature`
752 var anchor: nullable MClassType
753
754 # Is the receiver self?
755 # If "for_self", virtual types of the signature are kept
756 # If "not_for_self", virtual type are erased
757 var recv_is_self: Bool
758
759 # The designated method
760 var mproperty: MMethod
761
762 # The statically designated method definition
763 # The most specif one, it is.
764 var mpropdef: MMethodDef
765
766 # The resolved signature for the receiver
767 var msignature: MSignature
768
769 # Is a implicit cast required on erasure typing policy?
770 var erasure_cast: Bool
771
772 # The mapping used on the call to associate arguments to parameters
773 # If null then no specific association is required.
774 var signaturemap: nullable SignatureMap = null
775
776 private fun check_signature(v: TypeVisitor, node: ANode, args: Array[AExpr]): Bool
777 do
778 var map = v.check_signature(node, args, self.mproperty, self.msignature)
779 signaturemap = map
780 if map == null then is_broken = true
781 return map == null
782 end
783
784 # Information about the callsite to display on a node
785 fun dump_info(v: ASTDump): String do
786 return "{recv}.{mpropdef}{msignature}"
787 end
788 end
789
790 redef class Variable
791 # The declared type of the variable
792 var declared_type: nullable MType is writable
793
794 # Was the variable type-adapted?
795 # This is used to speedup type retrieval while it remains `false`
796 private var is_adapted = false
797 end
798
799 redef class FlowContext
800 # Store changes of types because of type evolution
801 private var vars = new HashMap[Variable, nullable MType]
802
803 # Adapt the variable to a static type
804 # Warning1: do not modify vars directly.
805 # Warning2: sub-flow may have cached a unadapted variable
806 private fun set_var(v: TypeVisitor, variable: Variable, mtype: nullable MType)
807 do
808 if variable.declared_type == mtype and not variable.is_adapted then return
809 if vars.has_key(variable) and vars[variable] == mtype then return
810 self.vars[variable] = mtype
811 v.dirty = true
812 variable.is_adapted = true
813 #node.debug "set {variable} to {mtype or else "X"}"
814 end
815
816 # Look in the flow and previous flow and collect all first reachable type adaptation of a local variable
817 private fun collect_types(variable: Variable): Array[nullable MType]
818 do
819 #node.debug "flow for {variable}"
820 var res = new Array[nullable MType]
821
822 var todo = [self]
823 var seen = new HashSet[FlowContext]
824 while not todo.is_empty do
825 var f = todo.pop
826 if f.is_unreachable then continue
827 if seen.has(f) then continue
828 seen.add f
829
830 if f.vars.has_key(variable) then
831 # Found something. Collect it and do not process further on this path
832 res.add f.vars[variable]
833 #f.node.debug "process {variable}: got {f.vars[variable] or else "X"}"
834 else
835 todo.add_all f.previous
836 todo.add_all f.loops
837 if f.previous.is_empty then
838 # Root flowcontext mean a parameter or something related
839 res.add variable.declared_type
840 #f.node.debug "root process {variable}: got {variable.declared_type or else "X"}"
841 end
842 end
843 end
844 #self.node.debug "##### end flow for {variable}: {res.join(" ")}"
845 return res
846 end
847 end
848
849 redef class APropdef
850 # The entry point of the whole typing analysis
851 fun do_typing(modelbuilder: ModelBuilder)
852 do
853 end
854
855 # The variable associated to the receiver (if any)
856 var selfvariable: nullable Variable
857 end
858
859 redef class AMethPropdef
860 redef fun do_typing(modelbuilder: ModelBuilder)
861 do
862 var mpropdef = self.mpropdef
863 if mpropdef == null then return # skip error
864
865 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
866 self.selfvariable = v.selfvariable
867
868 var mmethoddef = self.mpropdef.as(not null)
869 var msignature = mmethoddef.msignature
870 if msignature == null then return # skip error
871 for i in [0..msignature.arity[ do
872 var mtype = msignature.mparameters[i].mtype
873 if msignature.vararg_rank == i then
874 var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
875 if arrayclass == null then return # Skip error
876 mtype = arrayclass.get_mtype([mtype])
877 end
878 var variable = self.n_signature.n_params[i].variable
879 assert variable != null
880 variable.declared_type = mtype
881 end
882
883 var nblock = self.n_block
884 if nblock == null then return
885
886 loop
887 v.dirty = false
888 v.visit_stmt(nblock)
889 if not v.has_loop or not v.dirty then break
890 end
891
892 var post_visitor = new PostTypingVisitor(v)
893 post_visitor.enter_visit(self)
894
895 if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
896 # We reach the end of the function without having a return, it is bad
897 v.error(self, "Error: reached end of function; expected `return` with a value.")
898 end
899 end
900 end
901
902 private class PostTypingVisitor
903 super Visitor
904 var type_visitor: TypeVisitor
905 redef fun visit(n) do
906 n.visit_all(self)
907 n.accept_post_typing(type_visitor)
908 if n isa AExpr and n.mtype == null and not n.is_typed then
909 n.is_broken = true
910 end
911 end
912 end
913
914 redef class ANode
915 private fun accept_post_typing(v: TypeVisitor) do end
916
917 # An additional information message to explain the role of a child expression.
918 #
919 # The point of the method is to allow some kind of double dispatch so the parent
920 # choose how to describe its children.
921 private fun bad_expr_message(child: AExpr): nullable String do return null
922 end
923
924 redef class AAttrPropdef
925 redef fun do_typing(modelbuilder: ModelBuilder)
926 do
927 if not has_value then return
928
929 var mpropdef = self.mreadpropdef
930 if mpropdef == null or mpropdef.msignature == null then return # skip error
931
932 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
933 self.selfvariable = v.selfvariable
934
935 var nexpr = self.n_expr
936 if nexpr != null then
937 var mtype = self.mtype
938 v.visit_expr_subtype(nexpr, mtype)
939 end
940 var nblock = self.n_block
941 if nblock != null then
942 v.visit_stmt(nblock)
943 if not nblock.after_flow_context.is_unreachable then
944 # We reach the end of the init without having a return, it is bad
945 v.error(self, "Error: reached end of block; expected `return`.")
946 end
947 end
948 end
949 end
950
951 ###
952
953 redef class AExpr
954 # The static type of the expression.
955 # null if self is a statement or in case of error
956 var mtype: nullable MType = null
957
958 # Is the statement correctly typed?
959 # Used to distinguish errors and statements when `mtype == null`
960 var is_typed: Bool = false
961
962 # If required, the following implicit cast `.as(XXX)`
963 # Such a cast may by required after evaluating the expression when
964 # a unsafe operation is detected (silently accepted by the Nit language).
965 # The attribute is computed by `check_subtype`
966 var implicit_cast_to: nullable MType = null
967
968 # Return the variable read (if any)
969 # Used to perform adaptive typing
970 fun its_variable: nullable Variable do return null
971
972 private fun accept_typing(v: TypeVisitor)
973 do
974 v.error(self, "no implemented accept_typing for {self.class_name}")
975 end
976
977 # Is non-null if `self` is a leaf of a comprehension array construction.
978 # In this case, the enclosing literal array node is designated.
979 # The result of the evaluation of `self` must be
980 # stored inside the designated array (there is an implicit `push`)
981 var comprehension: nullable AArrayExpr = null
982
983 # It indicates the number of arguments collected as a vararg.
984 #
985 # When 0, the argument is used as is, without transformation.
986 # When 1, the argument is transformed into an singleton array.
987 # Above 1, the arguments and the next ones are transformed into a common array.
988 #
989 # This attribute is meaning less on expressions not used as attributes.
990 var vararg_decl: Int = 0
991
992 redef fun dump_info(v) do
993 var res = super
994 var mtype = self.mtype
995 if mtype != null then
996 res += v.yellow(":{mtype}")
997 end
998 var ict = self.implicit_cast_to
999 if ict != null then
1000 res += v.yellow("(.as({ict}))")
1001 end
1002 return res
1003 end
1004 end
1005
1006 redef class ABlockExpr
1007 redef fun accept_typing(v)
1008 do
1009 for e in self.n_expr do v.visit_stmt(e)
1010 self.is_typed = true
1011 end
1012
1013 # The type of a blockexpr is the one of the last expression (or null if empty)
1014 redef fun mtype
1015 do
1016 if self.n_expr.is_empty then return null
1017 return self.n_expr.last.mtype
1018 end
1019 end
1020
1021 redef class AVardeclExpr
1022 redef fun accept_typing(v)
1023 do
1024 var variable = self.variable
1025 if variable == null then return # Skip error
1026
1027 var ntype = self.n_type
1028 var mtype: nullable MType
1029 if ntype == null then
1030 mtype = null
1031 else
1032 mtype = v.resolve_mtype(ntype)
1033 if mtype == null then return # Skip error
1034 end
1035
1036 var nexpr = self.n_expr
1037 if nexpr != null then
1038 if mtype != null then
1039 var etype = v.visit_expr_subtype(nexpr, mtype)
1040 if etype == mtype then
1041 assert ntype != null
1042 v.modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition for variable `{variable.name}`")
1043 end
1044 else
1045 mtype = v.visit_expr(nexpr)
1046 if mtype == null then return # Skip error
1047 end
1048 end
1049
1050 var decltype = mtype
1051 if mtype == null or mtype isa MNullType then
1052 var objclass = v.get_mclass(self, "Object")
1053 if objclass == null then return # skip error
1054 decltype = objclass.mclass_type.as_nullable
1055 if mtype == null then mtype = decltype
1056 end
1057
1058 variable.declared_type = decltype
1059 v.set_variable(self, variable, mtype)
1060
1061 #debug("var {variable}: {mtype}")
1062
1063 self.mtype = mtype
1064 self.is_typed = true
1065 end
1066 end
1067
1068 redef class AVarExpr
1069 redef fun its_variable do return self.variable
1070 redef fun accept_typing(v)
1071 do
1072 var variable = self.variable
1073 if variable == null then return # Skip error
1074
1075 var mtype = v.get_variable(self, variable)
1076 if mtype != null then
1077 #debug("{variable} is {mtype}")
1078 else
1079 #debug("{variable} is untyped")
1080 end
1081
1082 self.mtype = mtype
1083 end
1084 end
1085
1086 redef class AVarAssignExpr
1087 redef fun accept_typing(v)
1088 do
1089 var variable = self.variable
1090 assert variable != null
1091
1092 var mtype = v.visit_expr_subtype(n_value, variable.declared_type)
1093
1094 v.set_variable(self, variable, mtype)
1095
1096 self.is_typed = true
1097 end
1098 end
1099
1100 redef class AReassignFormExpr
1101 # The method designed by the reassign operator.
1102 var reassign_callsite: nullable CallSite
1103
1104 var read_type: nullable MType = null
1105
1106 # Determine the `reassign_property`
1107 # `readtype` is the type of the reading of the left value.
1108 # `writetype` is the type of the writing of the left value.
1109 # (Because of `ACallReassignExpr`, both can be different.
1110 # Return the static type of the value to store.
1111 private fun resolve_reassignment(v: TypeVisitor, readtype, writetype: MType): nullable MType
1112 do
1113 var reassign_name = self.n_assign_op.operator
1114
1115 self.read_type = readtype
1116
1117 var callsite = v.get_method(self.n_assign_op, readtype, reassign_name, false)
1118 if callsite == null then return null # Skip error
1119 self.reassign_callsite = callsite
1120
1121 var msignature = callsite.msignature
1122 var rettype = msignature.return_mtype
1123 assert msignature.arity == 1 and rettype != null
1124
1125 var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
1126 if value_type == null then return null # Skip error
1127
1128 v.check_subtype(self, rettype, writetype, false)
1129 return rettype
1130 end
1131 end
1132
1133 redef class AVarReassignExpr
1134 redef fun accept_typing(v)
1135 do
1136 var variable = self.variable
1137 assert variable != null
1138
1139 var readtype = v.get_variable(self, variable)
1140 if readtype == null then return
1141
1142 read_type = readtype
1143
1144 var writetype = variable.declared_type
1145 if writetype == null then return
1146
1147 var rettype = self.resolve_reassignment(v, readtype, writetype)
1148
1149 v.set_variable(self, variable, rettype)
1150
1151 self.is_typed = rettype != null
1152 end
1153 end
1154
1155
1156 redef class AContinueExpr
1157 redef fun accept_typing(v)
1158 do
1159 var nexpr = self.n_expr
1160 if nexpr != null then
1161 v.visit_expr(nexpr)
1162 end
1163 self.is_typed = true
1164 end
1165 end
1166
1167 redef class ABreakExpr
1168 redef fun accept_typing(v)
1169 do
1170 var nexpr = self.n_expr
1171 if nexpr != null then
1172 v.visit_expr(nexpr)
1173 end
1174 self.is_typed = true
1175 end
1176 end
1177
1178 redef class AReturnExpr
1179 redef fun accept_typing(v)
1180 do
1181 var nexpr = self.n_expr
1182 var ret_type
1183 var mpropdef = v.mpropdef
1184 if mpropdef isa MMethodDef then
1185 ret_type = mpropdef.msignature.return_mtype
1186 else if mpropdef isa MAttributeDef then
1187 ret_type = mpropdef.static_mtype
1188 else
1189 abort
1190 end
1191 if nexpr != null then
1192 if ret_type != null then
1193 v.visit_expr_subtype(nexpr, ret_type)
1194 else
1195 v.visit_expr(nexpr)
1196 v.error(nexpr, "Error: `return` with value in a procedure.")
1197 return
1198 end
1199 else if ret_type != null then
1200 v.error(self, "Error: `return` without value in a function.")
1201 return
1202 end
1203 self.is_typed = true
1204 end
1205 end
1206
1207 redef class AAbortExpr
1208 redef fun accept_typing(v)
1209 do
1210 self.is_typed = true
1211 end
1212 end
1213
1214 redef class AIfExpr
1215 redef fun accept_typing(v)
1216 do
1217 v.visit_expr_bool(n_expr)
1218
1219 v.visit_stmt(n_then)
1220 v.visit_stmt(n_else)
1221
1222 self.is_typed = true
1223
1224 if n_then != null and n_else == null then
1225 self.mtype = n_then.mtype
1226 end
1227 end
1228 end
1229
1230 redef class AIfexprExpr
1231 redef fun accept_typing(v)
1232 do
1233 v.visit_expr_bool(n_expr)
1234
1235 var t1 = v.visit_expr(n_then)
1236 var t2 = v.visit_expr(n_else)
1237
1238 if t1 == null or t2 == null then
1239 return # Skip error
1240 end
1241
1242 var t = v.merge_types(self, [t1, t2])
1243 if t == null then
1244 v.error(self, "Type Error: ambiguous type `{t1}` vs `{t2}`.")
1245 end
1246 self.mtype = t
1247 end
1248 end
1249
1250 redef class ADoExpr
1251 redef fun accept_typing(v)
1252 do
1253 v.visit_stmt(n_block)
1254 v.visit_stmt(n_catch)
1255 self.is_typed = true
1256 end
1257 end
1258
1259 redef class AWhileExpr
1260 redef fun accept_typing(v)
1261 do
1262 v.has_loop = true
1263 v.visit_expr_bool(n_expr)
1264 v.visit_stmt(n_block)
1265 self.is_typed = true
1266 end
1267 end
1268
1269 redef class ALoopExpr
1270 redef fun accept_typing(v)
1271 do
1272 v.has_loop = true
1273 v.visit_stmt(n_block)
1274 self.is_typed = true
1275 end
1276 end
1277
1278 redef class AForExpr
1279 redef fun accept_typing(v)
1280 do
1281 v.has_loop = true
1282
1283 for g in n_groups do
1284 var mtype = v.visit_expr(g.n_expr)
1285 if mtype == null then return
1286 g.do_type_iterator(v, mtype)
1287 if g.is_broken then is_broken = true
1288 end
1289
1290 v.visit_stmt(n_block)
1291
1292 self.mtype = n_block.mtype
1293 self.is_typed = true
1294 end
1295 end
1296
1297 redef class AForGroup
1298 var coltype: nullable MClassType
1299
1300 var method_iterator: nullable CallSite
1301 var method_is_ok: nullable CallSite
1302 var method_item: nullable CallSite
1303 var method_next: nullable CallSite
1304 var method_key: nullable CallSite
1305 var method_finish: nullable CallSite
1306
1307 var method_lt: nullable CallSite
1308 var method_successor: nullable CallSite
1309
1310 private fun do_type_iterator(v: TypeVisitor, mtype: MType)
1311 do
1312 if mtype isa MNullType then
1313 v.error(self, "Type Error: `for` cannot iterate over `null`.")
1314 return
1315 end
1316
1317 # get obj class
1318 var objcla = v.get_mclass(self, "Object")
1319 if objcla == null then return
1320
1321 # check iterator method
1322 var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr)
1323 if itdef == null then
1324 v.error(self, "Type Error: `for` expects a type providing an `iterator` method, got `{mtype}`.")
1325 return
1326 end
1327 self.method_iterator = itdef
1328
1329 # check that iterator return something
1330 var ittype = itdef.msignature.return_mtype
1331 if ittype == null then
1332 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1333 return
1334 end
1335
1336 # get iterator type
1337 var colit_cla = v.try_get_mclass(self, "Iterator")
1338 var mapit_cla = v.try_get_mclass(self, "MapIterator")
1339 var is_col = false
1340 var is_map = false
1341
1342 if colit_cla != null and v.is_subtype(ittype, colit_cla.get_mtype([objcla.mclass_type.as_nullable])) then
1343 # Iterator
1344 var coltype = ittype.supertype_to(v.mmodule, v.anchor, colit_cla)
1345 var variables = self.variables
1346 if variables.length != 1 then
1347 v.error(self, "Type Error: `for` expects only one variable when using `Iterator`.")
1348 else
1349 variables.first.declared_type = coltype.arguments.first
1350 end
1351 is_col = true
1352 end
1353
1354 if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
1355 # Map Iterator
1356 var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
1357 var variables = self.variables
1358 if variables.length != 2 then
1359 v.error(self, "Type Error: `for` expects two variables when using `MapIterator`.")
1360 else
1361 variables[0].declared_type = coltype.arguments[0]
1362 variables[1].declared_type = coltype.arguments[1]
1363 end
1364 is_map = true
1365 end
1366
1367 if not is_col and not is_map then
1368 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1369 return
1370 end
1371
1372 # anchor formal and virtual types
1373 if mtype.need_anchor then mtype = v.anchor_to(mtype)
1374
1375 mtype = mtype.undecorate
1376 self.coltype = mtype.as(MClassType)
1377
1378 # get methods is_ok, next, item
1379 var ikdef = v.get_method(self, ittype, "is_ok", false)
1380 if ikdef == null then
1381 v.error(self, "Type Error: `for` expects a method `is_ok` in type `{ittype}`.")
1382 return
1383 end
1384 self.method_is_ok = ikdef
1385
1386 var itemdef = v.get_method(self, ittype, "item", false)
1387 if itemdef == null then
1388 v.error(self, "Type Error: `for` expects a method `item` in type `{ittype}`.")
1389 return
1390 end
1391 self.method_item = itemdef
1392
1393 var nextdef = v.get_method(self, ittype, "next", false)
1394 if nextdef == null then
1395 v.error(self, "Type Error: `for` expects a method `next` in type {ittype}.")
1396 return
1397 end
1398 self.method_next = nextdef
1399
1400 self.method_finish = v.try_get_method(self, ittype, "finish", false)
1401
1402 if is_map then
1403 var keydef = v.get_method(self, ittype, "key", false)
1404 if keydef == null then
1405 v.error(self, "Type Error: `for` expects a method `key` in type `{ittype}`.")
1406 return
1407 end
1408 self.method_key = keydef
1409 end
1410
1411 if self.variables.length == 1 and n_expr isa ARangeExpr then
1412 var variable = variables.first
1413 var vtype = variable.declared_type.as(not null)
1414
1415 if n_expr isa AOrangeExpr then
1416 self.method_lt = v.get_method(self, vtype, "<", false)
1417 else
1418 self.method_lt = v.get_method(self, vtype, "<=", false)
1419 end
1420
1421 self.method_successor = v.get_method(self, vtype, "successor", false)
1422 end
1423 end
1424 end
1425
1426 redef class AWithExpr
1427 var method_start: nullable CallSite
1428 var method_finish: nullable CallSite
1429
1430 redef fun accept_typing(v: TypeVisitor)
1431 do
1432 var mtype = v.visit_expr(n_expr)
1433 if mtype == null then return
1434
1435 method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr)
1436 method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr)
1437
1438 v.visit_stmt(n_block)
1439 self.mtype = n_block.mtype
1440 self.is_typed = true
1441 end
1442 end
1443
1444 redef class AAssertExpr
1445 redef fun accept_typing(v)
1446 do
1447 v.visit_expr_bool(n_expr)
1448
1449 v.visit_stmt(n_else)
1450 self.is_typed = true
1451 end
1452 end
1453
1454 redef class AOrExpr
1455 redef fun accept_typing(v)
1456 do
1457 v.visit_expr_bool(n_expr)
1458 v.visit_expr_bool(n_expr2)
1459 self.mtype = v.type_bool(self)
1460 end
1461 end
1462
1463 redef class AImpliesExpr
1464 redef fun accept_typing(v)
1465 do
1466 v.visit_expr_bool(n_expr)
1467 v.visit_expr_bool(n_expr2)
1468 self.mtype = v.type_bool(self)
1469 end
1470 end
1471
1472 redef class AAndExpr
1473 redef fun accept_typing(v)
1474 do
1475 v.visit_expr_bool(n_expr)
1476 v.visit_expr_bool(n_expr2)
1477 self.mtype = v.type_bool(self)
1478 end
1479 end
1480
1481
1482 redef class ANotExpr
1483 redef fun accept_typing(v)
1484 do
1485 v.visit_expr_bool(n_expr)
1486 self.mtype = v.type_bool(self)
1487 end
1488 end
1489
1490 redef class AOrElseExpr
1491 redef fun accept_typing(v)
1492 do
1493 var t1 = v.visit_expr(n_expr)
1494 var t2 = v.visit_expr(n_expr2)
1495
1496 if t1 == null or t2 == null then
1497 return # Skip error
1498 end
1499
1500 if t1 isa MNullType then
1501 self.mtype = t2
1502 return
1503 else if v.can_be_null(t1) then
1504 t1 = t1.as_notnull
1505 end
1506
1507 var t = v.merge_types(self, [t1, t2])
1508 if t == null then
1509 var c = v.get_mclass(self, "Object")
1510 if c == null then return # forward error
1511 t = c.mclass_type
1512 if v.can_be_null(t2) then
1513 t = t.as_nullable
1514 end
1515 #v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
1516 end
1517 self.mtype = t
1518 end
1519
1520 redef fun accept_post_typing(v)
1521 do
1522 var t1 = n_expr.mtype
1523 if t1 == null then
1524 return
1525 else
1526 v.check_can_be_null(n_expr, t1)
1527 end
1528 end
1529 end
1530
1531 redef class ATrueExpr
1532 redef fun accept_typing(v)
1533 do
1534 self.mtype = v.type_bool(self)
1535 end
1536 end
1537
1538 redef class AFalseExpr
1539 redef fun accept_typing(v)
1540 do
1541 self.mtype = v.type_bool(self)
1542 end
1543 end
1544
1545 redef class AIntegerExpr
1546 redef fun accept_typing(v)
1547 do
1548 var mclass: nullable MClass = null
1549 if value isa Byte then
1550 mclass = v.get_mclass(self, "Byte")
1551 else if value isa Int then
1552 mclass = v.get_mclass(self, "Int")
1553 else if value isa Int8 then
1554 mclass = v.get_mclass(self, "Int8")
1555 else if value isa Int16 then
1556 mclass = v.get_mclass(self, "Int16")
1557 else if value isa UInt16 then
1558 mclass = v.get_mclass(self, "UInt16")
1559 else if value isa Int32 then
1560 mclass = v.get_mclass(self, "Int32")
1561 else if value isa UInt32 then
1562 mclass = v.get_mclass(self, "UInt32")
1563 end
1564 if mclass == null then return # Forward error
1565 self.mtype = mclass.mclass_type
1566 end
1567 end
1568
1569 redef class AFloatExpr
1570 redef fun accept_typing(v)
1571 do
1572 var mclass = v.get_mclass(self, "Float")
1573 if mclass == null then return # Forward error
1574 self.mtype = mclass.mclass_type
1575 end
1576 end
1577
1578 redef class ACharExpr
1579 redef fun accept_typing(v) do
1580 var mclass: nullable MClass = null
1581 if is_ascii then
1582 mclass = v.get_mclass(self, "Byte")
1583 else if is_code_point then
1584 mclass = v.get_mclass(self, "Int")
1585 else
1586 mclass = v.get_mclass(self, "Char")
1587 end
1588 if mclass == null then return # Forward error
1589 self.mtype = mclass.mclass_type
1590 end
1591 end
1592
1593 redef class AugmentedStringFormExpr
1594 super AExpr
1595
1596 # Text::to_re, used for prefix `re`
1597 var to_re: nullable CallSite = null
1598 # Regex::ignore_case, used for suffix `i` on `re`
1599 var ignore_case: nullable CallSite = null
1600 # Regex::newline, used for suffix `m` on `re`
1601 var newline: nullable CallSite = null
1602 # Regex::extended, used for suffix `b` on `re`
1603 var extended: nullable CallSite = null
1604 # CString::to_bytes_with_copy, used for prefix `b`
1605 var to_bytes_with_copy: nullable CallSite = null
1606
1607 redef fun accept_typing(v) do
1608 var mclass = v.get_mclass(self, "String")
1609 if mclass == null then return # Forward error
1610 if is_bytestring then
1611 to_bytes_with_copy = v.get_method(self, v.mmodule.c_string_type, "to_bytes_with_copy", false)
1612 mclass = v.get_mclass(self, "Bytes")
1613 else if is_re then
1614 to_re = v.get_method(self, mclass.mclass_type, "to_re", false)
1615 for i in suffix.chars do
1616 mclass = v.get_mclass(self, "Regex")
1617 if mclass == null then
1618 v.error(self, "Error: `Regex` class unknown")
1619 return
1620 end
1621 var service = ""
1622 if i == 'i' then
1623 service = "ignore_case="
1624 ignore_case = v.get_method(self, mclass.mclass_type, service, false)
1625 else if i == 'm' then
1626 service = "newline="
1627 newline = v.get_method(self, mclass.mclass_type, service, false)
1628 else if i == 'b' then
1629 service = "extended="
1630 extended = v.get_method(self, mclass.mclass_type, service, false)
1631 else
1632 v.error(self, "Type Error: Unrecognized suffix {i} in prefixed Regex")
1633 abort
1634 end
1635 end
1636 end
1637 if mclass == null then return # Forward error
1638 mtype = mclass.mclass_type
1639 end
1640 end
1641
1642 redef class ASuperstringExpr
1643 redef fun accept_typing(v)
1644 do
1645 super
1646 var objclass = v.get_mclass(self, "Object")
1647 if objclass == null then return # Forward error
1648 var objtype = objclass.mclass_type
1649 for nexpr in self.n_exprs do
1650 v.visit_expr_subtype(nexpr, objtype)
1651 end
1652 end
1653 end
1654
1655 redef class AArrayExpr
1656 # The `with_capacity` method on Array
1657 var with_capacity_callsite: nullable CallSite
1658
1659 # The `push` method on arrays
1660 var push_callsite: nullable CallSite
1661
1662 # The element of each type
1663 var element_mtype: nullable MType
1664
1665 # Set that `self` is a part of comprehension array `na`
1666 # If `self` is a `for`, or a `if`, then `set_comprehension` is recursively applied.
1667 private fun set_comprehension(n: nullable AExpr)
1668 do
1669 if n == null then
1670 return
1671 else if n isa AForExpr then
1672 set_comprehension(n.n_block)
1673 else if n isa AIfExpr then
1674 set_comprehension(n.n_then)
1675 set_comprehension(n.n_else)
1676 else
1677 # is a leave
1678 n.comprehension = self
1679 end
1680 end
1681 redef fun accept_typing(v)
1682 do
1683 var mtype: nullable MType = null
1684 var ntype = self.n_type
1685 if ntype != null then
1686 mtype = v.resolve_mtype(ntype)
1687 if mtype == null then return # Skip error
1688 end
1689 var mtypes = new Array[nullable MType]
1690 var useless = false
1691 for e in self.n_exprs do
1692 var t = v.visit_expr(e)
1693 if t == null then
1694 return # Skip error
1695 end
1696 set_comprehension(e)
1697 if mtype != null then
1698 if v.check_subtype(e, t, mtype, false) == null then return # Forward error
1699 if t == mtype then useless = true
1700 else
1701 mtypes.add(t)
1702 end
1703 end
1704 if mtype == null then
1705 # Ensure monotony for type adaptation on loops
1706 if self.element_mtype != null then mtypes.add self.element_mtype
1707 mtype = v.merge_types(self, mtypes)
1708 end
1709 if mtype == null or mtype isa MNullType then
1710 v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
1711 return
1712 end
1713 if useless then
1714 assert ntype != null
1715 v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
1716 end
1717
1718 self.element_mtype = mtype
1719
1720 var mclass = v.get_mclass(self, "Array")
1721 if mclass == null then return # Forward error
1722 var array_mtype = mclass.get_mtype([mtype])
1723
1724 with_capacity_callsite = v.get_method(self, array_mtype, "with_capacity", false)
1725 push_callsite = v.get_method(self, array_mtype, "push", false)
1726
1727 self.mtype = array_mtype
1728 end
1729 end
1730
1731 redef class ARangeExpr
1732 var init_callsite: nullable CallSite
1733
1734 redef fun accept_typing(v)
1735 do
1736 var discrete_class = v.get_mclass(self, "Discrete")
1737 if discrete_class == null then return # Forward error
1738 var discrete_type = discrete_class.intro.bound_mtype
1739 var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
1740 var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
1741 if t1 == null or t2 == null then return
1742 var mclass = v.get_mclass(self, "Range")
1743 if mclass == null then return # Forward error
1744 var mtype
1745 if v.is_subtype(t1, t2) then
1746 mtype = mclass.get_mtype([t2])
1747 else if v.is_subtype(t2, t1) then
1748 mtype = mclass.get_mtype([t1])
1749 else
1750 v.error(self, "Type Error: cannot create range: `{t1}` vs `{t2}`.")
1751 return
1752 end
1753
1754 self.mtype = mtype
1755
1756 # get the constructor
1757 var callsite
1758 if self isa ACrangeExpr then
1759 callsite = v.get_method(self, mtype, "init", false)
1760 else if self isa AOrangeExpr then
1761 callsite = v.get_method(self, mtype, "without_last", false)
1762 else
1763 abort
1764 end
1765 init_callsite = callsite
1766 end
1767 end
1768
1769 redef class ANullExpr
1770 redef fun accept_typing(v)
1771 do
1772 self.mtype = v.mmodule.model.null_type
1773 end
1774 end
1775
1776 redef class AIsaExpr
1777 # The static type to cast to.
1778 # (different from the static type of the expression that is `Bool`).
1779 var cast_type: nullable MType
1780 redef fun accept_typing(v)
1781 do
1782 v.visit_expr(n_expr)
1783
1784 var mtype = v.resolve_mtype(n_type)
1785
1786 self.cast_type = mtype
1787
1788 var variable = self.n_expr.its_variable
1789 if variable != null then
1790 var orig = self.n_expr.mtype
1791 #var from = if orig != null then orig.to_s else "invalid"
1792 #var to = if mtype != null then mtype.to_s else "invalid"
1793 #debug("adapt {variable}: {from} -> {to}")
1794
1795 var thentype = v.intersect_types(self, orig, mtype)
1796 if thentype != orig then
1797 self.after_flow_context.when_true.set_var(v, variable, thentype)
1798 #debug "{variable}:{orig or else "?"} isa {mtype or else "?"} -> then {thentype or else "?"}"
1799 end
1800
1801 var elsetype = v.diff_types(self, orig, mtype)
1802 if elsetype != orig then
1803 self.after_flow_context.when_false.set_var(v, variable, elsetype)
1804 #debug "{variable}:{orig or else "?"} isa {mtype or else "?"} -> else {elsetype or else "?"}"
1805 end
1806 end
1807
1808 self.mtype = v.type_bool(self)
1809 end
1810
1811 redef fun accept_post_typing(v)
1812 do
1813 v.check_expr_cast(self, self.n_expr, self.n_type)
1814 end
1815
1816 redef fun dump_info(v) do
1817 var res = super
1818 var mtype = self.cast_type
1819 if mtype != null then
1820 res += v.yellow(".as({mtype})")
1821 end
1822 return res
1823 end
1824
1825 end
1826
1827 redef class AAsCastExpr
1828 redef fun accept_typing(v)
1829 do
1830 v.visit_expr(n_expr)
1831
1832 self.mtype = v.resolve_mtype(n_type)
1833 end
1834
1835 redef fun accept_post_typing(v)
1836 do
1837 v.check_expr_cast(self, self.n_expr, self.n_type)
1838 end
1839 end
1840
1841 redef class AAsNotnullExpr
1842 redef fun accept_typing(v)
1843 do
1844 var mtype = v.visit_expr(self.n_expr)
1845 if mtype == null then return # Forward error
1846
1847 if mtype isa MNullType then
1848 v.error(self, "Type Error: `as(not null)` on `null`.")
1849 return
1850 end
1851
1852 if v.can_be_null(mtype) then
1853 mtype = mtype.as_notnull
1854 end
1855
1856 self.mtype = mtype
1857 end
1858
1859 redef fun accept_post_typing(v)
1860 do
1861 var mtype = n_expr.mtype
1862 if mtype == null then return
1863 v.check_can_be_null(n_expr, mtype)
1864 end
1865 end
1866
1867 redef class AParExpr
1868 redef fun accept_typing(v)
1869 do
1870 self.mtype = v.visit_expr(self.n_expr)
1871 end
1872 end
1873
1874 redef class AOnceExpr
1875 redef fun accept_typing(v)
1876 do
1877 self.mtype = v.visit_expr(self.n_expr)
1878 end
1879 end
1880
1881 redef class ASelfExpr
1882 redef var its_variable: nullable Variable
1883 redef fun accept_typing(v)
1884 do
1885 if v.is_toplevel_context and not self isa AImplicitSelfExpr then
1886 v.error(self, "Error: `self` cannot be used in top-level method.")
1887 end
1888 var variable = v.selfvariable
1889 self.its_variable = variable
1890 self.mtype = v.get_variable(self, variable)
1891 end
1892 end
1893
1894 redef class AImplicitSelfExpr
1895 # Is the implicit receiver `sys`?
1896 #
1897 # By default, the implicit receiver is `self`.
1898 # But when there is not method for `self`, `sys` is used as a fall-back.
1899 # Is this case this flag is set to `true`.
1900 var is_sys = false
1901 end
1902
1903 ## MESSAGE SENDING AND PROPERTY
1904
1905 redef class ASendExpr
1906 # The property invoked by the send.
1907 var callsite: nullable CallSite
1908
1909 redef fun bad_expr_message(child)
1910 do
1911 if child == self.n_expr then
1912 return "to be the receiver of `{self.property_name}`"
1913 end
1914 return null
1915 end
1916
1917 redef fun accept_typing(v)
1918 do
1919 var nrecv = self.n_expr
1920 var recvtype = v.visit_expr(nrecv)
1921 var name = self.property_name
1922 var node = self.property_node
1923
1924 if recvtype == null then return # Forward error
1925
1926 var callsite = null
1927 var unsafe_type = v.anchor_to(recvtype)
1928 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
1929 if mproperty == null and nrecv isa AImplicitSelfExpr then
1930 # Special fall-back search in `sys` when noting found in the implicit receiver.
1931 var sysclass = v.try_get_mclass(node, "Sys")
1932 if sysclass != null then
1933 var systype = sysclass.mclass_type
1934 mproperty = v.try_get_mproperty_by_name2(node, systype, name)
1935 if mproperty != null then
1936 callsite = v.get_method(node, systype, name, false)
1937 if callsite == null then return # Forward error
1938 # Update information, we are looking at `sys` now, not `self`
1939 nrecv.is_sys = true
1940 nrecv.its_variable = null
1941 nrecv.mtype = systype
1942 recvtype = systype
1943 end
1944 end
1945 end
1946 if callsite == null then
1947 # If still nothing, just exit
1948 callsite = v.get_method(node, recvtype, name, nrecv isa ASelfExpr)
1949 if callsite == null then return
1950 end
1951
1952 self.callsite = callsite
1953 var msignature = callsite.msignature
1954
1955 var args = compute_raw_arguments
1956
1957 callsite.check_signature(v, node, args)
1958
1959 if callsite.mproperty.is_init then
1960 var vmpropdef = v.mpropdef
1961 if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
1962 v.error(node, "Error: an `init` can only be called from another `init`.")
1963 end
1964 if vmpropdef isa MMethodDef and vmpropdef.mproperty.is_root_init and not callsite.mproperty.is_root_init then
1965 v.error(node, "Error: `{vmpropdef}` cannot call a factory `{callsite.mproperty}`.")
1966 end
1967 end
1968
1969 var ret = msignature.return_mtype
1970 if ret != null then
1971 self.mtype = ret
1972 else
1973 self.is_typed = true
1974 end
1975 end
1976
1977 # The name of the property
1978 # Each subclass simply provide the correct name.
1979 private fun property_name: String is abstract
1980
1981 # The node identifying the name (id, operator, etc) for messages.
1982 #
1983 # Is `self` by default
1984 private fun property_node: ANode do return self
1985
1986 # An array of all arguments (excluding self)
1987 fun raw_arguments: Array[AExpr] do return compute_raw_arguments
1988
1989 private fun compute_raw_arguments: Array[AExpr] is abstract
1990
1991 redef fun dump_info(v) do
1992 var res = super
1993 var callsite = self.callsite
1994 if callsite != null then
1995 res += v.yellow(" call="+callsite.dump_info(v))
1996 end
1997 return res
1998 end
1999 end
2000
2001 redef class ABinopExpr
2002 redef fun compute_raw_arguments do return [n_expr2]
2003 redef fun property_name do return operator
2004 redef fun property_node do return n_op
2005 end
2006
2007 redef class AEqFormExpr
2008 redef fun accept_typing(v)
2009 do
2010 super
2011 v.null_test(self)
2012 end
2013
2014 redef fun accept_post_typing(v)
2015 do
2016 var mtype = n_expr.mtype
2017 var mtype2 = n_expr2.mtype
2018
2019 if mtype == null or mtype2 == null then return
2020
2021 if not mtype2 isa MNullType then return
2022
2023 v.check_can_be_null(n_expr, mtype)
2024 end
2025 end
2026
2027 redef class AUnaryopExpr
2028 redef fun property_name do return "unary {operator}"
2029 redef fun compute_raw_arguments do return new Array[AExpr]
2030 end
2031
2032
2033 redef class ACallExpr
2034 redef fun property_name do return n_qid.n_id.text
2035 redef fun property_node do return n_qid
2036 redef fun compute_raw_arguments do return n_args.to_a
2037 end
2038
2039 redef class ACallAssignExpr
2040 redef fun property_name do return n_qid.n_id.text + "="
2041 redef fun property_node do return n_qid
2042 redef fun compute_raw_arguments
2043 do
2044 var res = n_args.to_a
2045 res.add(n_value)
2046 return res
2047 end
2048 end
2049
2050 redef class ABraExpr
2051 redef fun property_name do return "[]"
2052 redef fun compute_raw_arguments do return n_args.to_a
2053 end
2054
2055 redef class ABraAssignExpr
2056 redef fun property_name do return "[]="
2057 redef fun compute_raw_arguments
2058 do
2059 var res = n_args.to_a
2060 res.add(n_value)
2061 return res
2062 end
2063 end
2064
2065 redef class ASendReassignFormExpr
2066 # The property invoked for the writing
2067 var write_callsite: nullable CallSite
2068
2069 redef fun accept_typing(v)
2070 do
2071 var recvtype = v.visit_expr(self.n_expr)
2072 var name = self.property_name
2073 var node = self.property_node
2074
2075 if recvtype == null then return # Forward error
2076
2077 var for_self = self.n_expr isa ASelfExpr
2078 var callsite = v.get_method(node, recvtype, name, for_self)
2079
2080 if callsite == null then return
2081 self.callsite = callsite
2082
2083 var args = compute_raw_arguments
2084
2085 callsite.check_signature(v, node, args)
2086
2087 var readtype = callsite.msignature.return_mtype
2088 if readtype == null then
2089 v.error(node, "Error: `{name}` is not a function.")
2090 return
2091 end
2092
2093 var wcallsite = v.get_method(node, recvtype, name + "=", self.n_expr isa ASelfExpr)
2094 if wcallsite == null then return
2095 self.write_callsite = wcallsite
2096
2097 var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
2098 if wtype == null then return
2099
2100 args = args.to_a # duplicate so raw_arguments keeps only the getter args
2101 args.add(self.n_value)
2102 wcallsite.check_signature(v, node, args)
2103
2104 self.is_typed = true
2105 end
2106 end
2107
2108 redef class ACallReassignExpr
2109 redef fun property_name do return n_qid.n_id.text
2110 redef fun property_node do return n_qid.n_id
2111 redef fun compute_raw_arguments do return n_args.to_a
2112 end
2113
2114 redef class ABraReassignExpr
2115 redef fun property_name do return "[]"
2116 redef fun compute_raw_arguments do return n_args.to_a
2117 end
2118
2119 redef class AInitExpr
2120 redef fun property_name do return "init"
2121 redef fun property_node do return n_kwinit
2122 redef fun compute_raw_arguments do return n_args.to_a
2123 end
2124
2125 redef class AExprs
2126 fun to_a: Array[AExpr] do return self.n_exprs.to_a
2127 end
2128
2129 ###
2130
2131 redef class ASuperExpr
2132 # The method to call if the super is in fact a 'super init call'
2133 # Note: if the super is a normal call-next-method, then this attribute is null
2134 var callsite: nullable CallSite
2135
2136 # The method to call is the super is a standard `call-next-method` super-call
2137 # Note: if the super is a special super-init-call, then this attribute is null
2138 var mpropdef: nullable MMethodDef
2139
2140 redef fun accept_typing(v)
2141 do
2142 var anchor = v.anchor
2143 assert anchor != null
2144 var recvtype = v.get_variable(self, v.selfvariable)
2145 assert recvtype != null
2146 var mproperty = v.mpropdef.mproperty
2147 if not mproperty isa MMethod then
2148 v.error(self, "Error: `super` only usable in a `method`.")
2149 return
2150 end
2151 var superprops = mproperty.lookup_super_definitions(v.mmodule, anchor)
2152 if superprops.length == 0 then
2153 if mproperty.is_init and v.mpropdef.is_intro then
2154 process_superinit(v)
2155 return
2156 end
2157 v.error(self, "Error: no super method to call for `{mproperty}`.")
2158 return
2159 end
2160 # FIXME: covariance of return type in linear extension?
2161 var superprop = superprops.first
2162
2163 var msignature = superprop.msignature.as(not null)
2164 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
2165 var args = self.n_args.to_a
2166 if args.length > 0 then
2167 signaturemap = v.check_signature(self, args, mproperty, msignature)
2168 end
2169 self.mtype = msignature.return_mtype
2170 self.is_typed = true
2171 v.mpropdef.has_supercall = true
2172 mpropdef = v.mpropdef.as(MMethodDef)
2173 end
2174
2175 # The mapping used on the call to associate arguments to parameters.
2176 # If null then no specific association is required.
2177 var signaturemap: nullable SignatureMap
2178
2179 private fun process_superinit(v: TypeVisitor)
2180 do
2181 var anchor = v.anchor
2182 assert anchor != null
2183 var recvtype = v.get_variable(self, v.selfvariable)
2184 assert recvtype != null
2185 var mpropdef = v.mpropdef
2186 assert mpropdef isa MMethodDef
2187 var mproperty = mpropdef.mproperty
2188 var superprop: nullable MMethodDef = null
2189 for msupertype in mpropdef.mclassdef.supertypes do
2190 msupertype = msupertype.anchor_to(v.mmodule, anchor)
2191 var errcount = v.modelbuilder.toolcontext.error_count
2192 var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
2193 if candidate == null then
2194 if v.modelbuilder.toolcontext.error_count > errcount then return # Forward error
2195 continue # Try next super-class
2196 end
2197 if superprop != null and candidate.is_root_init then
2198 continue
2199 end
2200 if superprop != null and superprop.mproperty != candidate and not superprop.mproperty.is_root_init then
2201 v.error(self, "Error: conflicting super constructor to call for `{mproperty}`: `{candidate.full_name}`, `{superprop.mproperty.full_name}`")
2202 return
2203 end
2204 var candidatedefs = candidate.lookup_definitions(v.mmodule, anchor)
2205 if superprop != null and superprop.mproperty == candidate then
2206 if superprop == candidatedefs.first then continue
2207 candidatedefs.add(superprop)
2208 end
2209 if candidatedefs.length > 1 then
2210 v.error(self, "Error: conflicting property definitions for property `{mproperty}` in `{recvtype}`: {candidatedefs.join(", ")}")
2211 return
2212 end
2213 superprop = candidatedefs.first
2214 end
2215 if superprop == null then
2216 v.error(self, "Error: no super method to call for `{mproperty}`.")
2217 return
2218 end
2219
2220 var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
2221 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
2222
2223 var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
2224 self.callsite = callsite
2225
2226 var args = self.n_args.to_a
2227 if args.length > 0 then
2228 callsite.check_signature(v, self, args)
2229 else
2230 # Check there is at least enough parameters
2231 if mpropdef.msignature.arity < msignature.arity then
2232 v.error(self, "Error: not enough implicit arguments to pass. Got `{mpropdef.msignature.arity}`, expected at least `{msignature.arity}`. Signature is `{msignature}`.")
2233 return
2234 end
2235 # Check that each needed parameter is conform
2236 var i = 0
2237 for sp in msignature.mparameters do
2238 var p = mpropdef.msignature.mparameters[i]
2239 if not v.is_subtype(p.mtype, sp.mtype) then
2240 v.error(self, "Type Error: expected argument #{i} of type `{sp.mtype}`, got implicit argument `{p.name}` of type `{p.mtype}`. Signature is {msignature}")
2241 return
2242 end
2243 i += 1
2244 end
2245 end
2246
2247 self.is_typed = true
2248 end
2249
2250 redef fun dump_info(v) do
2251 var res = super
2252 var callsite = self.callsite
2253 if callsite != null then
2254 res += v.yellow(" super-init="+callsite.dump_info(v))
2255 end
2256 var mpropdef = self.mpropdef
2257 if mpropdef != null then
2258 res += v.yellow(" call-next-method="+mpropdef.to_s)
2259 end
2260 return res
2261 end
2262 end
2263
2264 ####
2265
2266 redef class ANewExpr
2267 # The constructor invoked by the new.
2268 var callsite: nullable CallSite
2269
2270 # The designated type
2271 var recvtype: nullable MClassType
2272
2273 redef fun accept_typing(v)
2274 do
2275 var recvtype = v.resolve_mtype(self.n_type)
2276 if recvtype == null then return
2277
2278 if not recvtype isa MClassType then
2279 if recvtype isa MNullableType then
2280 v.error(self, "Type Error: cannot instantiate the nullable type `{recvtype}`.")
2281 return
2282 else if recvtype isa MFormalType then
2283 v.error(self, "Type Error: cannot instantiate the formal type `{recvtype}`.")
2284 return
2285 else
2286 v.error(self, "Type Error: cannot instantiate the type `{recvtype}`.")
2287 return
2288 end
2289 end
2290
2291 self.recvtype = recvtype
2292 var kind = recvtype.mclass.kind
2293
2294 var name: String
2295 var nqid = self.n_qid
2296 var node: ANode
2297 if nqid != null then
2298 name = nqid.n_id.text
2299 node = nqid
2300 else
2301 name = "new"
2302 node = self.n_kwnew
2303 end
2304 if name == "intern" then
2305 if kind != concrete_kind then
2306 v.error(self, "Type Error: cannot instantiate {kind} {recvtype}.")
2307 return
2308 end
2309 if n_args.n_exprs.not_empty then
2310 v.error(n_args, "Type Error: the intern constructor expects no arguments.")
2311 return
2312 end
2313 # Our job is done
2314 self.mtype = recvtype
2315 return
2316 end
2317
2318 var callsite = v.get_method(node, recvtype, name, false)
2319 if callsite == null then return
2320
2321 if not callsite.mproperty.is_new then
2322 if kind != concrete_kind then
2323 v.error(self, "Type Error: cannot instantiate {kind} `{recvtype}`.")
2324 return
2325 end
2326 self.mtype = recvtype
2327 else
2328 self.mtype = callsite.msignature.return_mtype
2329 assert self.mtype != null
2330 end
2331
2332 self.callsite = callsite
2333
2334 if not callsite.mproperty.is_init_for(recvtype.mclass) then
2335 v.error(self, "Error: `{name}` is not a constructor.")
2336 return
2337 end
2338
2339 var args = n_args.to_a
2340 callsite.check_signature(v, node, args)
2341 end
2342
2343 redef fun dump_info(v) do
2344 var res = super
2345 var callsite = self.callsite
2346 if callsite != null then
2347 res += v.yellow(" call="+callsite.dump_info(v))
2348 end
2349 return res
2350 end
2351 end
2352
2353 ####
2354
2355 redef class AAttrFormExpr
2356 # The attribute accessed.
2357 var mproperty: nullable MAttribute
2358
2359 # The static type of the attribute.
2360 var attr_type: nullable MType
2361
2362 # Resolve the attribute accessed.
2363 private fun resolve_property(v: TypeVisitor)
2364 do
2365 var recvtype = v.visit_expr(self.n_expr)
2366 if recvtype == null then return # Skip error
2367 var node = self.n_id
2368 var name = node.text
2369 if recvtype isa MNullType then
2370 v.error(node, "Error: attribute `{name}` access on `null`.")
2371 return
2372 end
2373
2374 var unsafe_type = v.anchor_to(recvtype)
2375 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
2376 if mproperty == null then
2377 v.modelbuilder.error(node, "Error: attribute `{name}` does not exist in `{recvtype}`.")
2378 return
2379 end
2380 assert mproperty isa MAttribute
2381 self.mproperty = mproperty
2382
2383 var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
2384 assert mpropdefs.length == 1
2385 var mpropdef = mpropdefs.first
2386 var attr_type = mpropdef.static_mtype
2387 if attr_type == null then return # skip error
2388 attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
2389 self.attr_type = attr_type
2390 end
2391
2392 redef fun dump_info(v) do
2393 var res = super
2394 var mproperty = self.mproperty
2395 var attr_type = self.attr_type
2396 if mproperty != null then
2397 res += v.yellow(" attr={mproperty}:{attr_type or else "BROKEN"}")
2398 end
2399 return res
2400 end
2401 end
2402
2403 redef class AAttrExpr
2404 redef fun accept_typing(v)
2405 do
2406 self.resolve_property(v)
2407 self.mtype = self.attr_type
2408 end
2409 end
2410
2411
2412 redef class AAttrAssignExpr
2413 redef fun accept_typing(v)
2414 do
2415 self.resolve_property(v)
2416 var mtype = self.attr_type
2417
2418 v.visit_expr_subtype(self.n_value, mtype)
2419 self.is_typed = mtype != null
2420 end
2421 end
2422
2423 redef class AAttrReassignExpr
2424 redef fun accept_typing(v)
2425 do
2426 self.resolve_property(v)
2427 var mtype = self.attr_type
2428 if mtype == null then return # Skip error
2429
2430 var rettype = self.resolve_reassignment(v, mtype, mtype)
2431
2432 self.is_typed = rettype != null
2433 end
2434 end
2435
2436 redef class AIssetAttrExpr
2437 redef fun accept_typing(v)
2438 do
2439 self.resolve_property(v)
2440 var mtype = self.attr_type
2441 if mtype == null then return # Skip error
2442
2443 var recvtype = self.n_expr.mtype.as(not null)
2444 var bound = v.resolve_for(mtype, recvtype, false)
2445 if bound isa MNullableType then
2446 v.error(n_id, "Type Error: `isset` on a nullable attribute.")
2447 end
2448 self.mtype = v.type_bool(self)
2449 end
2450 end
2451
2452 redef class AVarargExpr
2453 redef fun accept_typing(v)
2454 do
2455 # This kind of pseudo-expression can be only processed trough a signature
2456 # See `check_signature`
2457 # Other cases are a syntax error.
2458 v.error(self, "Syntax Error: unexpected `...`.")
2459 end
2460 end
2461
2462 ###
2463
2464 redef class ADebugTypeExpr
2465 redef fun accept_typing(v)
2466 do
2467 var expr = v.visit_expr(self.n_expr)
2468 if expr == null then return
2469 var unsafe = v.anchor_to(expr)
2470 var ntype = self.n_type
2471 var mtype = v.resolve_mtype(ntype)
2472 if mtype != null and mtype != expr then
2473 var umtype = v.anchor_to(mtype)
2474 v.modelbuilder.warning(self, "debug", "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
2475 end
2476 self.is_typed = true
2477 end
2478 end