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