src: update AST client to handle qualified identifiers (no semantic change)
[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 var anchor = anchor
85 if anchor == null then
86 assert not mtype.need_anchor
87 return mtype
88 end
89 return mtype.anchor_to(mmodule, anchor)
90 end
91
92 fun is_subtype(sub, sup: MType): Bool
93 do
94 return sub.is_subtype(mmodule, anchor, sup)
95 end
96
97 fun resolve_for(mtype, subtype: MType, for_self: Bool): MType
98 do
99 #print "resolve_for {mtype} sub={subtype} forself={for_self} mmodule={mmodule} anchor={anchor}"
100 var res = mtype.resolve_for(subtype, anchor, mmodule, not for_self)
101 return res
102 end
103
104 # Check that `sub` is a subtype of `sup`.
105 # If `sub` is not a valid suptype, then display an error on `node` an return null.
106 # If `sub` is a safe subtype of `sup` then return `sub`.
107 # If `sub` is an unsafe subtype (ie an implicit cast is required), then return `sup`.
108 #
109 # The point of the return type is to determinate the usable type on an expression when `autocast` is true:
110 # If the suptype is safe, then the return type is the one on the expression typed by `sub`.
111 # Is the subtype is unsafe, then the return type is the one of an implicit cast on `sup`.
112 fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
113 do
114 if self.is_subtype(sub, sup) then return sub
115 if autocast and self.is_subtype(sub, self.anchor_to(sup)) then
116 # FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
117 #node.debug("Unsafe typing: expected {sup}, got {sub}")
118 return sup
119 end
120 if sub.need_anchor then
121 var u = anchor_to(sub)
122 self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}: {u}`.")
123 else
124 self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}`.")
125 end
126 return null
127 end
128
129 # Visit an expression and do not care about the return value
130 fun visit_stmt(nexpr: nullable AExpr)
131 do
132 if nexpr == null then return
133 nexpr.accept_typing(self)
134 end
135
136 # Visit an expression and expects that it is not a statement
137 # Return the type of the expression
138 # Display an error and return null if:
139 # * the type cannot be determined or
140 # * `nexpr` is a statement
141 fun visit_expr(nexpr: AExpr): nullable MType
142 do
143 nexpr.accept_typing(self)
144 var mtype = nexpr.mtype
145 if mtype != null then return mtype
146 if not nexpr.is_typed then
147 if not self.modelbuilder.toolcontext.error_count > 0 then # check that there is really an error
148 if self.modelbuilder.toolcontext.verbose_level > 1 then
149 nexpr.debug("No return type but no error.")
150 end
151 end
152 return null # forward error
153 end
154 self.error(nexpr, "Error: expected an expression.")
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, 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 if msignature.arity == msignature.min_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 if args.length > msignature.arity then
422 modelbuilder.error(node, "Error: expected at most {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
423 return null
424 end
425 if args.length < msignature.min_arity then
426 modelbuilder.error(node, "Error: expected at least {msignature.min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
427 return null
428 end
429 end
430
431 #debug("CALL {unsafe_type}.{msignature}")
432
433 # Associate each parameter to a position in the arguments
434 var map = new SignatureMap
435
436 var setted = args.length - msignature.min_arity
437
438 # First, handle named arguments
439 for i in [0..args.length[ do
440 var e = args[i]
441 if not e isa ANamedargExpr then continue
442 var name = e.n_id.text
443 var param = msignature.mparameter_by_name(name)
444 if param == null then
445 modelbuilder.error(e.n_id, "Error: no parameter `{name}` for `{mproperty}{msignature}`.")
446 return null
447 end
448 if not param.is_default then
449 modelbuilder.error(e, "Error: parameter `{name}` is not optional 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 setted -= 1
460 e.mtype = self.visit_expr_subtype(e.n_expr, param.mtype)
461 end
462
463 # Second, associate remaining parameters
464 var vararg_decl = args.length - msignature.arity
465 var j = 0
466 for i in [0..msignature.arity[ do
467 # Skip parameters associated by name
468 if map.map.has_key(i) then continue
469
470 var param = msignature.mparameters[i]
471 if param.is_default then
472 if setted > 0 then
473 setted -= 1
474 else
475 continue
476 end
477 end
478
479 # Search the next free argument: skip named arguments since they are already associated
480 while args[j] isa ANamedargExpr do j += 1
481 var arg = args[j]
482 map.map[i] = j
483 j += 1
484
485 if i == vararg_rank then
486 j += vararg_decl
487 continue # skip the vararg
488 end
489
490 var paramtype = param.mtype
491 self.visit_expr_subtype(arg, paramtype)
492 end
493
494 # Third, check varargs
495 if vararg_rank >= 0 then
496 var paramtype = msignature.mparameters[vararg_rank].mtype
497 var first = args[vararg_rank]
498 if vararg_decl == 0 then
499 var mclass = get_mclass(node, "Array")
500 if mclass == null then return null # Forward error
501 var array_mtype = mclass.get_mtype([paramtype])
502 if first isa AVarargExpr then
503 self.visit_expr_subtype(first.n_expr, array_mtype)
504 first.mtype = first.n_expr.mtype
505 else
506 # only one vararg, maybe `...` was forgot, so be gentle!
507 var t = visit_expr(first)
508 if t == null then return null # Forward error
509 if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
510 # Not acceptable but could be a `...`
511 error(first, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
512 return null
513 end
514 # Standard valid vararg, finish the job
515 map.vararg_decl = 1
516 self.visit_expr_subtype(first, paramtype)
517 end
518 else
519 map.vararg_decl = vararg_decl + 1
520 for i in [vararg_rank..vararg_rank+vararg_decl] do
521 self.visit_expr_subtype(args[i], paramtype)
522 end
523 end
524 end
525
526 return map
527 end
528
529 fun error(node: ANode, message: String)
530 do
531 self.modelbuilder.toolcontext.error(node.hot_location, message)
532 end
533
534 fun get_variable(node: AExpr, variable: Variable): nullable MType
535 do
536 if not variable.is_adapted then return variable.declared_type
537
538 var flow = node.after_flow_context
539 if flow == null then return null # skip error
540
541 if flow.vars.has_key(variable) then
542 return flow.vars[variable]
543 else
544 #node.debug("*** START Collected for {variable}")
545 var mtypes = flow.collect_types(variable)
546 #node.debug("**** END Collected for {variable}")
547 if mtypes.length == 0 then
548 return variable.declared_type
549 else if mtypes.length == 1 then
550 return mtypes.first
551 else
552 var res = merge_types(node,mtypes)
553 if res == null then res = variable.declared_type
554 return res
555 end
556 end
557 end
558
559 # Some variables where type-adapted during the visit
560 var dirty = false
561
562 # Some loops had been visited during the visit
563 var has_loop = false
564
565 fun set_variable(node: AExpr, variable: Variable, mtype: nullable MType)
566 do
567 var flow = node.after_flow_context
568 assert flow != null
569
570 flow.set_var(self, variable, mtype)
571 end
572
573 fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
574 do
575 if col.length == 1 then return col.first
576 for t1 in col do
577 if t1 == null then continue # return null
578 var found = true
579 for t2 in col do
580 if t2 == null then continue # return null
581 if can_be_null(t2) and not can_be_null(t1) then
582 t1 = t1.as_nullable
583 end
584 if not is_subtype(t2, t1) then found = false
585 end
586 if found then
587 #print "merge {col.join(" ")} -> {t1}"
588 return t1
589 end
590 end
591 #self.modelbuilder.warning(node, "Type Error: {col.length} conflicting types: <{col.join(", ")}>")
592 return null
593 end
594 end
595
596 # Mapping between parameters and arguments in a call.
597 #
598 # Parameters and arguments are not stored in the class but referenced by their position (starting from 0)
599 #
600 # The point of this class is to help engine and other things to map arguments in the AST to parameters of the model.
601 class SignatureMap
602 # Associate a parameter to an argument
603 var map = new ArrayMap[Int, Int]
604
605 # The length of the vararg sequence
606 # 0 if no vararg or if reverse vararg (cf `AVarargExpr`)
607 var vararg_decl: Int = 0
608 end
609
610 # A specific method call site with its associated informations.
611 class CallSite
612 # The associated node for location
613 var node: ANode
614
615 # The static type of the receiver (possibly unresolved)
616 var recv: MType
617
618 # The module where the callsite is present
619 var mmodule: MModule
620
621 # The anchor to use with `recv` or `msignature`
622 var anchor: nullable MClassType
623
624 # Is the receiver self?
625 # If "for_self", virtual types of the signature are kept
626 # If "not_for_self", virtual type are erased
627 var recv_is_self: Bool
628
629 # The designated method
630 var mproperty: MMethod
631
632 # The statically designated method definition
633 # The most specif one, it is.
634 var mpropdef: MMethodDef
635
636 # The resolved signature for the receiver
637 var msignature: MSignature
638
639 # Is a implicit cast required on erasure typing policy?
640 var erasure_cast: Bool
641
642 # The mapping used on the call to associate arguments to parameters
643 # If null then no specific association is required.
644 var signaturemap: nullable SignatureMap = null
645
646 private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
647 do
648 var map = v.check_signature(self.node, args, self.mproperty, self.msignature)
649 signaturemap = map
650 return map == null
651 end
652 end
653
654 redef class Variable
655 # The declared type of the variable
656 var declared_type: nullable MType is writable
657
658 # Was the variable type-adapted?
659 # This is used to speedup type retrieval while it remains `false`
660 private var is_adapted = false
661 end
662
663 redef class FlowContext
664 # Store changes of types because of type evolution
665 private var vars = new HashMap[Variable, nullable MType]
666
667 # Adapt the variable to a static type
668 # Warning1: do not modify vars directly.
669 # Warning2: sub-flow may have cached a unadapted variable
670 private fun set_var(v: TypeVisitor, variable: Variable, mtype: nullable MType)
671 do
672 if variable.declared_type == mtype and not variable.is_adapted then return
673 if vars.has_key(variable) and vars[variable] == mtype then return
674 self.vars[variable] = mtype
675 v.dirty = true
676 variable.is_adapted = true
677 #node.debug "set {variable} to {mtype or else "X"}"
678 end
679
680 # Look in the flow and previous flow and collect all first reachable type adaptation of a local variable
681 private fun collect_types(variable: Variable): Array[nullable MType]
682 do
683 #node.debug "flow for {variable}"
684 var res = new Array[nullable MType]
685
686 var todo = [self]
687 var seen = new HashSet[FlowContext]
688 while not todo.is_empty do
689 var f = todo.pop
690 if f.is_unreachable then continue
691 if seen.has(f) then continue
692 seen.add f
693
694 if f.vars.has_key(variable) then
695 # Found something. Collect it and do not process further on this path
696 res.add f.vars[variable]
697 #f.node.debug "process {variable}: got {f.vars[variable] or else "X"}"
698 else
699 todo.add_all f.previous
700 todo.add_all f.loops
701 if f.previous.is_empty then
702 # Root flowcontext mean a parameter or something related
703 res.add variable.declared_type
704 #f.node.debug "root process {variable}: got {variable.declared_type or else "X"}"
705 end
706 end
707 end
708 #self.node.debug "##### end flow for {variable}: {res.join(" ")}"
709 return res
710 end
711 end
712
713 redef class APropdef
714 # The entry point of the whole typing analysis
715 fun do_typing(modelbuilder: ModelBuilder)
716 do
717 end
718
719 # The variable associated to the receiver (if any)
720 var selfvariable: nullable Variable
721 end
722
723 redef class AMethPropdef
724 redef fun do_typing(modelbuilder: ModelBuilder)
725 do
726 var mpropdef = self.mpropdef
727 if mpropdef == null then return # skip error
728
729 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
730 self.selfvariable = v.selfvariable
731
732 var mmethoddef = self.mpropdef.as(not null)
733 var msignature = mmethoddef.msignature
734 if msignature == null then return # skip error
735 for i in [0..msignature.arity[ do
736 var mtype = msignature.mparameters[i].mtype
737 if msignature.vararg_rank == i then
738 var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
739 if arrayclass == null then return # Skip error
740 mtype = arrayclass.get_mtype([mtype])
741 end
742 var variable = self.n_signature.n_params[i].variable
743 assert variable != null
744 variable.declared_type = mtype
745 end
746
747 var nblock = self.n_block
748 if nblock == null then return
749
750 loop
751 v.dirty = false
752 v.visit_stmt(nblock)
753 if not v.has_loop or not v.dirty then break
754 end
755
756 var post_visitor = new PostTypingVisitor(v)
757 post_visitor.enter_visit(self)
758
759 if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
760 # We reach the end of the function without having a return, it is bad
761 v.error(self, "Error: reached end of function; expected `return` with a value.")
762 end
763 end
764 end
765
766 private class PostTypingVisitor
767 super Visitor
768 var type_visitor: TypeVisitor
769 redef fun visit(n) do
770 n.visit_all(self)
771 n.accept_post_typing(type_visitor)
772 end
773 end
774
775 redef class ANode
776 private fun accept_post_typing(v: TypeVisitor) do end
777 end
778
779 redef class AAttrPropdef
780 redef fun do_typing(modelbuilder: ModelBuilder)
781 do
782 if not has_value then return
783
784 var mpropdef = self.mreadpropdef
785 if mpropdef == null or mpropdef.msignature == null then return # skip error
786
787 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
788 self.selfvariable = v.selfvariable
789
790 var nexpr = self.n_expr
791 if nexpr != null then
792 var mtype = self.mtype
793 v.visit_expr_subtype(nexpr, mtype)
794 end
795 var nblock = self.n_block
796 if nblock != null then
797 v.visit_stmt(nblock)
798 if not nblock.after_flow_context.is_unreachable then
799 # We reach the end of the init without having a return, it is bad
800 v.error(self, "Error: reached end of block; expected `return`.")
801 end
802 end
803 end
804 end
805
806 ###
807
808 redef class AExpr
809 # The static type of the expression.
810 # null if self is a statement or in case of error
811 var mtype: nullable MType = null
812
813 # Is the statement correctly typed?
814 # Used to distinguish errors and statements when `mtype == null`
815 var is_typed: Bool = false
816
817 # If required, the following implicit cast `.as(XXX)`
818 # Such a cast may by required after evaluating the expression when
819 # a unsafe operation is detected (silently accepted by the Nit language).
820 # The attribute is computed by `check_subtype`
821 var implicit_cast_to: nullable MType = null
822
823 # Return the variable read (if any)
824 # Used to perform adaptive typing
825 fun its_variable: nullable Variable do return null
826
827 private fun accept_typing(v: TypeVisitor)
828 do
829 v.error(self, "no implemented accept_typing for {self.class_name}")
830 end
831
832 # Is non-null if `self` is a leaf of a comprehension array construction.
833 # In this case, the enclosing literal array node is designated.
834 # The result of the evaluation of `self` must be
835 # stored inside the designated array (there is an implicit `push`)
836 var comprehension: nullable AArrayExpr = null
837 end
838
839 redef class ABlockExpr
840 redef fun accept_typing(v)
841 do
842 for e in self.n_expr do v.visit_stmt(e)
843 self.is_typed = true
844 end
845
846 # The type of a blockexpr is the one of the last expression (or null if empty)
847 redef fun mtype
848 do
849 if self.n_expr.is_empty then return null
850 return self.n_expr.last.mtype
851 end
852 end
853
854 redef class AVardeclExpr
855 redef fun accept_typing(v)
856 do
857 var variable = self.variable
858 if variable == null then return # Skip error
859
860 var ntype = self.n_type
861 var mtype: nullable MType
862 if ntype == null then
863 mtype = null
864 else
865 mtype = v.resolve_mtype(ntype)
866 if mtype == null then return # Skip error
867 end
868
869 var nexpr = self.n_expr
870 if nexpr != null then
871 if mtype != null then
872 var etype = v.visit_expr_subtype(nexpr, mtype)
873 if etype == mtype then
874 assert ntype != null
875 v.modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition for variable `{variable.name}`")
876 end
877 else
878 mtype = v.visit_expr(nexpr)
879 if mtype == null then return # Skip error
880 end
881 end
882
883 var decltype = mtype
884 if mtype == null or mtype isa MNullType then
885 var objclass = v.get_mclass(self, "Object")
886 if objclass == null then return # skip error
887 decltype = objclass.mclass_type.as_nullable
888 if mtype == null then mtype = decltype
889 end
890
891 variable.declared_type = decltype
892 v.set_variable(self, variable, mtype)
893
894 #debug("var {variable}: {mtype}")
895
896 self.mtype = mtype
897 self.is_typed = true
898 end
899 end
900
901 redef class AVarExpr
902 redef fun its_variable do return self.variable
903 redef fun accept_typing(v)
904 do
905 var variable = self.variable
906 if variable == null then return # Skip error
907
908 var mtype = v.get_variable(self, variable)
909 if mtype != null then
910 #debug("{variable} is {mtype}")
911 else
912 #debug("{variable} is untyped")
913 end
914
915 self.mtype = mtype
916 end
917 end
918
919 redef class AVarAssignExpr
920 redef fun accept_typing(v)
921 do
922 var variable = self.variable
923 assert variable != null
924
925 var mtype = v.visit_expr_subtype(n_value, variable.declared_type)
926
927 v.set_variable(self, variable, mtype)
928
929 self.is_typed = true
930 end
931 end
932
933 redef class AReassignFormExpr
934 # The method designed by the reassign operator.
935 var reassign_callsite: nullable CallSite
936
937 var read_type: nullable MType = null
938
939 # Determine the `reassign_property`
940 # `readtype` is the type of the reading of the left value.
941 # `writetype` is the type of the writing of the left value.
942 # (Because of `ACallReassignExpr`, both can be different.
943 # Return the static type of the value to store.
944 private fun resolve_reassignment(v: TypeVisitor, readtype, writetype: MType): nullable MType
945 do
946 var reassign_name = self.n_assign_op.operator
947
948 self.read_type = readtype
949
950 var callsite = v.get_method(self.n_assign_op, readtype, reassign_name, false)
951 if callsite == null then return null # Skip error
952 self.reassign_callsite = callsite
953
954 var msignature = callsite.msignature
955 var rettype = msignature.return_mtype
956 assert msignature.arity == 1 and rettype != null
957
958 var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
959 if value_type == null then return null # Skip error
960
961 v.check_subtype(self, rettype, writetype, false)
962 return rettype
963 end
964 end
965
966 redef class AVarReassignExpr
967 redef fun accept_typing(v)
968 do
969 var variable = self.variable
970 assert variable != null
971
972 var readtype = v.get_variable(self, variable)
973 if readtype == null then return
974
975 read_type = readtype
976
977 var writetype = variable.declared_type
978 if writetype == null then return
979
980 var rettype = self.resolve_reassignment(v, readtype, writetype)
981
982 v.set_variable(self, variable, rettype)
983
984 self.is_typed = rettype != null
985 end
986 end
987
988
989 redef class AContinueExpr
990 redef fun accept_typing(v)
991 do
992 var nexpr = self.n_expr
993 if nexpr != null then
994 v.visit_expr(nexpr)
995 end
996 self.is_typed = true
997 end
998 end
999
1000 redef class ABreakExpr
1001 redef fun accept_typing(v)
1002 do
1003 var nexpr = self.n_expr
1004 if nexpr != null then
1005 v.visit_expr(nexpr)
1006 end
1007 self.is_typed = true
1008 end
1009 end
1010
1011 redef class AReturnExpr
1012 redef fun accept_typing(v)
1013 do
1014 var nexpr = self.n_expr
1015 var ret_type
1016 var mpropdef = v.mpropdef
1017 if mpropdef isa MMethodDef then
1018 ret_type = mpropdef.msignature.return_mtype
1019 else if mpropdef isa MAttributeDef then
1020 ret_type = mpropdef.static_mtype
1021 else
1022 abort
1023 end
1024 if nexpr != null then
1025 if ret_type != null then
1026 v.visit_expr_subtype(nexpr, ret_type)
1027 else
1028 v.visit_expr(nexpr)
1029 v.error(nexpr, "Error: `return` with value in a procedure.")
1030 return
1031 end
1032 else if ret_type != null then
1033 v.error(self, "Error: `return` without value in a function.")
1034 return
1035 end
1036 self.is_typed = true
1037 end
1038 end
1039
1040 redef class AAbortExpr
1041 redef fun accept_typing(v)
1042 do
1043 self.is_typed = true
1044 end
1045 end
1046
1047 redef class AIfExpr
1048 redef fun accept_typing(v)
1049 do
1050 v.visit_expr_bool(n_expr)
1051
1052 v.visit_stmt(n_then)
1053 v.visit_stmt(n_else)
1054
1055 self.is_typed = true
1056
1057 if n_then != null and n_else == null then
1058 self.mtype = n_then.mtype
1059 end
1060 end
1061 end
1062
1063 redef class AIfexprExpr
1064 redef fun accept_typing(v)
1065 do
1066 v.visit_expr_bool(n_expr)
1067
1068 var t1 = v.visit_expr(n_then)
1069 var t2 = v.visit_expr(n_else)
1070
1071 if t1 == null or t2 == null then
1072 return # Skip error
1073 end
1074
1075 var t = v.merge_types(self, [t1, t2])
1076 if t == null then
1077 v.error(self, "Type Error: ambiguous type `{t1}` vs `{t2}`.")
1078 end
1079 self.mtype = t
1080 end
1081 end
1082
1083 redef class ADoExpr
1084 redef fun accept_typing(v)
1085 do
1086 v.visit_stmt(n_block)
1087 self.is_typed = true
1088 end
1089 end
1090
1091 redef class AWhileExpr
1092 redef fun accept_typing(v)
1093 do
1094 v.has_loop = true
1095 v.visit_expr_bool(n_expr)
1096 v.visit_stmt(n_block)
1097 self.is_typed = true
1098 end
1099 end
1100
1101 redef class ALoopExpr
1102 redef fun accept_typing(v)
1103 do
1104 v.has_loop = true
1105 v.visit_stmt(n_block)
1106 self.is_typed = true
1107 end
1108 end
1109
1110 redef class AForExpr
1111 var coltype: nullable MClassType
1112
1113 var method_iterator: nullable CallSite
1114 var method_is_ok: nullable CallSite
1115 var method_item: nullable CallSite
1116 var method_next: nullable CallSite
1117 var method_key: nullable CallSite
1118 var method_finish: nullable CallSite
1119
1120 var method_lt: nullable CallSite
1121 var method_successor: nullable CallSite
1122
1123 private fun do_type_iterator(v: TypeVisitor, mtype: MType)
1124 do
1125 if mtype isa MNullType then
1126 v.error(self, "Type Error: `for` cannot iterate over `null`.")
1127 return
1128 end
1129
1130 # get obj class
1131 var objcla = v.get_mclass(self, "Object")
1132 if objcla == null then return
1133
1134 # check iterator method
1135 var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr)
1136 if itdef == null then
1137 v.error(self, "Type Error: `for` expects a type providing an `iterator` method, got `{mtype}`.")
1138 return
1139 end
1140 self.method_iterator = itdef
1141
1142 # check that iterator return something
1143 var ittype = itdef.msignature.return_mtype
1144 if ittype == null then
1145 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1146 return
1147 end
1148
1149 # get iterator type
1150 var colit_cla = v.try_get_mclass(self, "Iterator")
1151 var mapit_cla = v.try_get_mclass(self, "MapIterator")
1152 var is_col = false
1153 var is_map = false
1154
1155 if colit_cla != null and v.is_subtype(ittype, colit_cla.get_mtype([objcla.mclass_type.as_nullable])) then
1156 # Iterator
1157 var coltype = ittype.supertype_to(v.mmodule, v.anchor, colit_cla)
1158 var variables = self.variables
1159 if variables.length != 1 then
1160 v.error(self, "Type Error: `for` expects only one variable when using `Iterator`.")
1161 else
1162 variables.first.declared_type = coltype.arguments.first
1163 end
1164 is_col = true
1165 end
1166
1167 if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
1168 # Map Iterator
1169 var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
1170 var variables = self.variables
1171 if variables.length != 2 then
1172 v.error(self, "Type Error: `for` expects two variables when using `MapIterator`.")
1173 else
1174 variables[0].declared_type = coltype.arguments[0]
1175 variables[1].declared_type = coltype.arguments[1]
1176 end
1177 is_map = true
1178 end
1179
1180 if not is_col and not is_map then
1181 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1182 return
1183 end
1184
1185 # anchor formal and virtual types
1186 if mtype.need_anchor then mtype = v.anchor_to(mtype)
1187
1188 mtype = mtype.undecorate
1189 self.coltype = mtype.as(MClassType)
1190
1191 # get methods is_ok, next, item
1192 var ikdef = v.get_method(self, ittype, "is_ok", false)
1193 if ikdef == null then
1194 v.error(self, "Type Error: `for` expects a method `is_ok` in type `{ittype}`.")
1195 return
1196 end
1197 self.method_is_ok = ikdef
1198
1199 var itemdef = v.get_method(self, ittype, "item", false)
1200 if itemdef == null then
1201 v.error(self, "Type Error: `for` expects a method `item` in type `{ittype}`.")
1202 return
1203 end
1204 self.method_item = itemdef
1205
1206 var nextdef = v.get_method(self, ittype, "next", false)
1207 if nextdef == null then
1208 v.error(self, "Type Error: `for` expects a method `next` in type {ittype}.")
1209 return
1210 end
1211 self.method_next = nextdef
1212
1213 self.method_finish = v.try_get_method(self, ittype, "finish", false)
1214
1215 if is_map then
1216 var keydef = v.get_method(self, ittype, "key", false)
1217 if keydef == null then
1218 v.error(self, "Type Error: `for` expects a method `key` in type `{ittype}`.")
1219 return
1220 end
1221 self.method_key = keydef
1222 end
1223
1224 if self.variables.length == 1 and n_expr isa ARangeExpr then
1225 var variable = variables.first
1226 var vtype = variable.declared_type.as(not null)
1227
1228 if n_expr isa AOrangeExpr then
1229 self.method_lt = v.get_method(self, vtype, "<", false)
1230 else
1231 self.method_lt = v.get_method(self, vtype, "<=", false)
1232 end
1233
1234 self.method_successor = v.get_method(self, vtype, "successor", false)
1235 end
1236 end
1237
1238 redef fun accept_typing(v)
1239 do
1240 v.has_loop = true
1241 var mtype = v.visit_expr(n_expr)
1242 if mtype == null then return
1243
1244 self.do_type_iterator(v, mtype)
1245
1246 v.visit_stmt(n_block)
1247
1248 self.mtype = n_block.mtype
1249 self.is_typed = true
1250 end
1251 end
1252
1253 redef class AWithExpr
1254 var method_start: nullable CallSite
1255 var method_finish: nullable CallSite
1256
1257 redef fun accept_typing(v: TypeVisitor)
1258 do
1259 var mtype = v.visit_expr(n_expr)
1260 if mtype == null then return
1261
1262 method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr)
1263 method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr)
1264
1265 v.visit_stmt(n_block)
1266 self.mtype = n_block.mtype
1267 self.is_typed = true
1268 end
1269 end
1270
1271 redef class AAssertExpr
1272 redef fun accept_typing(v)
1273 do
1274 v.visit_expr_bool(n_expr)
1275
1276 v.visit_stmt(n_else)
1277 self.is_typed = true
1278 end
1279 end
1280
1281 redef class AOrExpr
1282 redef fun accept_typing(v)
1283 do
1284 v.visit_expr_bool(n_expr)
1285 v.visit_expr_bool(n_expr2)
1286 self.mtype = v.type_bool(self)
1287 end
1288 end
1289
1290 redef class AImpliesExpr
1291 redef fun accept_typing(v)
1292 do
1293 v.visit_expr_bool(n_expr)
1294 v.visit_expr_bool(n_expr2)
1295 self.mtype = v.type_bool(self)
1296 end
1297 end
1298
1299 redef class AAndExpr
1300 redef fun accept_typing(v)
1301 do
1302 v.visit_expr_bool(n_expr)
1303 v.visit_expr_bool(n_expr2)
1304 self.mtype = v.type_bool(self)
1305 end
1306 end
1307
1308
1309 redef class ANotExpr
1310 redef fun accept_typing(v)
1311 do
1312 v.visit_expr_bool(n_expr)
1313 self.mtype = v.type_bool(self)
1314 end
1315 end
1316
1317 redef class AOrElseExpr
1318 redef fun accept_typing(v)
1319 do
1320 var t1 = v.visit_expr(n_expr)
1321 var t2 = v.visit_expr(n_expr2)
1322
1323 if t1 == null or t2 == null then
1324 return # Skip error
1325 end
1326
1327 if t1 isa MNullType then
1328 self.mtype = t2
1329 return
1330 else if v.can_be_null(t1) then
1331 t1 = t1.as_notnull
1332 end
1333
1334 var t = v.merge_types(self, [t1, t2])
1335 if t == null then
1336 var c = v.get_mclass(self, "Object")
1337 if c == null then return # forward error
1338 t = c.mclass_type
1339 if v.can_be_null(t2) then
1340 t = t.as_nullable
1341 end
1342 #v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
1343 end
1344 self.mtype = t
1345 end
1346
1347 redef fun accept_post_typing(v)
1348 do
1349 var t1 = n_expr.mtype
1350 if t1 == null then
1351 return
1352 else
1353 v.check_can_be_null(n_expr, t1)
1354 end
1355 end
1356 end
1357
1358 redef class ATrueExpr
1359 redef fun accept_typing(v)
1360 do
1361 self.mtype = v.type_bool(self)
1362 end
1363 end
1364
1365 redef class AFalseExpr
1366 redef fun accept_typing(v)
1367 do
1368 self.mtype = v.type_bool(self)
1369 end
1370 end
1371
1372 redef class AIntegerExpr
1373 redef fun accept_typing(v)
1374 do
1375 var mclass: nullable MClass = null
1376 if value isa Byte then
1377 mclass = v.get_mclass(self, "Byte")
1378 else if value isa Int then
1379 mclass = v.get_mclass(self, "Int")
1380 end
1381 if mclass == null then return # Forward error
1382 self.mtype = mclass.mclass_type
1383 end
1384 end
1385
1386 redef class AFloatExpr
1387 redef fun accept_typing(v)
1388 do
1389 var mclass = v.get_mclass(self, "Float")
1390 if mclass == null then return # Forward error
1391 self.mtype = mclass.mclass_type
1392 end
1393 end
1394
1395 redef class ACharExpr
1396 redef fun accept_typing(v)
1397 do
1398 var mclass = v.get_mclass(self, "Char")
1399 if mclass == null then return # Forward error
1400 self.mtype = mclass.mclass_type
1401 end
1402 end
1403
1404 redef class AStringFormExpr
1405 redef fun accept_typing(v)
1406 do
1407 var mclass = v.get_mclass(self, "String")
1408 if mclass == null then return # Forward error
1409 self.mtype = mclass.mclass_type
1410 end
1411 end
1412
1413 redef class ASuperstringExpr
1414 redef fun accept_typing(v)
1415 do
1416 var mclass = v.get_mclass(self, "String")
1417 if mclass == null then return # Forward error
1418 self.mtype = mclass.mclass_type
1419 var objclass = v.get_mclass(self, "Object")
1420 if objclass == null then return # Forward error
1421 var objtype = objclass.mclass_type
1422 for nexpr in self.n_exprs do
1423 v.visit_expr_subtype(nexpr, objtype)
1424 end
1425 end
1426 end
1427
1428 redef class AArrayExpr
1429 # The `with_capacity` method on Array
1430 var with_capacity_callsite: nullable CallSite
1431
1432 # The `push` method on arrays
1433 var push_callsite: nullable CallSite
1434
1435 # The element of each type
1436 var element_mtype: nullable MType
1437
1438 # Set that `self` is a part of comprehension array `na`
1439 # If `self` is a `for`, or a `if`, then `set_comprehension` is recursively applied.
1440 private fun set_comprehension(n: nullable AExpr)
1441 do
1442 if n == null then
1443 return
1444 else if n isa AForExpr then
1445 set_comprehension(n.n_block)
1446 else if n isa AIfExpr then
1447 set_comprehension(n.n_then)
1448 set_comprehension(n.n_else)
1449 else
1450 # is a leave
1451 n.comprehension = self
1452 end
1453 end
1454 redef fun accept_typing(v)
1455 do
1456 var mtype: nullable MType = null
1457 var ntype = self.n_type
1458 if ntype != null then
1459 mtype = v.resolve_mtype(ntype)
1460 if mtype == null then return # Skip error
1461 end
1462 var mtypes = new Array[nullable MType]
1463 var useless = false
1464 for e in self.n_exprs do
1465 var t = v.visit_expr(e)
1466 if t == null then
1467 return # Skip error
1468 end
1469 set_comprehension(e)
1470 if mtype != null then
1471 if v.check_subtype(e, t, mtype, false) == null then return # Forward error
1472 if t == mtype then useless = true
1473 else
1474 mtypes.add(t)
1475 end
1476 end
1477 if mtype == null then
1478 # Ensure monotony for type adaptation on loops
1479 if self.element_mtype != null then mtypes.add self.element_mtype
1480 mtype = v.merge_types(self, mtypes)
1481 end
1482 if mtype == null or mtype isa MNullType then
1483 v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
1484 return
1485 end
1486 if useless then
1487 assert ntype != null
1488 v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
1489 end
1490
1491 self.element_mtype = mtype
1492
1493 var mclass = v.get_mclass(self, "Array")
1494 if mclass == null then return # Forward error
1495 var array_mtype = mclass.get_mtype([mtype])
1496
1497 with_capacity_callsite = v.get_method(self, array_mtype, "with_capacity", false)
1498 push_callsite = v.get_method(self, array_mtype, "push", false)
1499
1500 self.mtype = array_mtype
1501 end
1502 end
1503
1504 redef class ARangeExpr
1505 var init_callsite: nullable CallSite
1506
1507 redef fun accept_typing(v)
1508 do
1509 var discrete_class = v.get_mclass(self, "Discrete")
1510 if discrete_class == null then return # Forward error
1511 var discrete_type = discrete_class.intro.bound_mtype
1512 var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
1513 var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
1514 if t1 == null or t2 == null then return
1515 var mclass = v.get_mclass(self, "Range")
1516 if mclass == null then return # Forward error
1517 var mtype
1518 if v.is_subtype(t1, t2) then
1519 mtype = mclass.get_mtype([t2])
1520 else if v.is_subtype(t2, t1) then
1521 mtype = mclass.get_mtype([t1])
1522 else
1523 v.error(self, "Type Error: cannot create range: `{t1}` vs `{t2}`.")
1524 return
1525 end
1526
1527 self.mtype = mtype
1528
1529 # get the constructor
1530 var callsite
1531 if self isa ACrangeExpr then
1532 callsite = v.get_method(self, mtype, "init", false)
1533 else if self isa AOrangeExpr then
1534 callsite = v.get_method(self, mtype, "without_last", false)
1535 else
1536 abort
1537 end
1538 init_callsite = callsite
1539 end
1540 end
1541
1542 redef class ANullExpr
1543 redef fun accept_typing(v)
1544 do
1545 self.mtype = v.mmodule.model.null_type
1546 end
1547 end
1548
1549 redef class AIsaExpr
1550 # The static type to cast to.
1551 # (different from the static type of the expression that is `Bool`).
1552 var cast_type: nullable MType
1553 redef fun accept_typing(v)
1554 do
1555 v.visit_expr(n_expr)
1556
1557 var mtype = v.resolve_mtype(n_type)
1558
1559 self.cast_type = mtype
1560
1561 var variable = self.n_expr.its_variable
1562 if variable != null then
1563 #var orig = self.n_expr.mtype
1564 #var from = if orig != null then orig.to_s else "invalid"
1565 #var to = if mtype != null then mtype.to_s else "invalid"
1566 #debug("adapt {variable}: {from} -> {to}")
1567 self.after_flow_context.when_true.set_var(v, variable, mtype)
1568 end
1569
1570 self.mtype = v.type_bool(self)
1571 end
1572
1573 redef fun accept_post_typing(v)
1574 do
1575 v.check_expr_cast(self, self.n_expr, self.n_type)
1576 end
1577 end
1578
1579 redef class AAsCastExpr
1580 redef fun accept_typing(v)
1581 do
1582 v.visit_expr(n_expr)
1583
1584 self.mtype = v.resolve_mtype(n_type)
1585 end
1586
1587 redef fun accept_post_typing(v)
1588 do
1589 v.check_expr_cast(self, self.n_expr, self.n_type)
1590 end
1591 end
1592
1593 redef class AAsNotnullExpr
1594 redef fun accept_typing(v)
1595 do
1596 var mtype = v.visit_expr(self.n_expr)
1597 if mtype == null then return # Forward error
1598
1599 if mtype isa MNullType then
1600 v.error(self, "Type Error: `as(not null)` on `null`.")
1601 return
1602 end
1603
1604 if v.can_be_null(mtype) then
1605 mtype = mtype.as_notnull
1606 end
1607
1608 self.mtype = mtype
1609 end
1610
1611 redef fun accept_post_typing(v)
1612 do
1613 var mtype = n_expr.mtype
1614 if mtype == null then return
1615 v.check_can_be_null(n_expr, mtype)
1616 end
1617 end
1618
1619 redef class AParExpr
1620 redef fun accept_typing(v)
1621 do
1622 self.mtype = v.visit_expr(self.n_expr)
1623 end
1624 end
1625
1626 redef class AOnceExpr
1627 redef fun accept_typing(v)
1628 do
1629 self.mtype = v.visit_expr(self.n_expr)
1630 end
1631 end
1632
1633 redef class ASelfExpr
1634 redef var its_variable: nullable Variable
1635 redef fun accept_typing(v)
1636 do
1637 if v.is_toplevel_context and not self isa AImplicitSelfExpr then
1638 v.error(self, "Error: `self` cannot be used in top-level method.")
1639 end
1640 var variable = v.selfvariable
1641 self.its_variable = variable
1642 self.mtype = v.get_variable(self, variable)
1643 end
1644 end
1645
1646 redef class AImplicitSelfExpr
1647 # Is the implicit receiver `sys`?
1648 #
1649 # By default, the implicit receiver is `self`.
1650 # But when there is not method for `self`, `sys` is used as a fall-back.
1651 # Is this case this flag is set to `true`.
1652 var is_sys = false
1653 end
1654
1655 ## MESSAGE SENDING AND PROPERTY
1656
1657 redef class ASendExpr
1658 # The property invoked by the send.
1659 var callsite: nullable CallSite
1660
1661 redef fun accept_typing(v)
1662 do
1663 var nrecv = self.n_expr
1664 var recvtype = v.visit_expr(nrecv)
1665 var name = self.property_name
1666 var node = self.property_node
1667
1668 if recvtype == null then return # Forward error
1669
1670 var callsite = null
1671 var unsafe_type = v.anchor_to(recvtype)
1672 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
1673 if mproperty == null and nrecv isa AImplicitSelfExpr then
1674 # Special fall-back search in `sys` when noting found in the implicit receiver.
1675 var sysclass = v.try_get_mclass(node, "Sys")
1676 if sysclass != null then
1677 var systype = sysclass.mclass_type
1678 mproperty = v.try_get_mproperty_by_name2(node, systype, name)
1679 if mproperty != null then
1680 callsite = v.get_method(node, systype, name, false)
1681 if callsite == null then return # Forward error
1682 # Update information, we are looking at `sys` now, not `self`
1683 nrecv.is_sys = true
1684 nrecv.its_variable = null
1685 nrecv.mtype = systype
1686 recvtype = systype
1687 end
1688 end
1689 end
1690 if callsite == null then
1691 # If still nothing, just exit
1692 callsite = v.get_method(node, recvtype, name, nrecv isa ASelfExpr)
1693 if callsite == null then return
1694 end
1695
1696 self.callsite = callsite
1697 var msignature = callsite.msignature
1698
1699 var args = compute_raw_arguments
1700
1701 callsite.check_signature(v, args)
1702
1703 if callsite.mproperty.is_init then
1704 var vmpropdef = v.mpropdef
1705 if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
1706 v.error(node, "Error: an `init` can only be called from another `init`.")
1707 end
1708 if vmpropdef isa MMethodDef and vmpropdef.mproperty.is_root_init and not callsite.mproperty.is_root_init then
1709 v.error(node, "Error: `{vmpropdef}` cannot call a factory `{callsite.mproperty}`.")
1710 end
1711 end
1712
1713 var ret = msignature.return_mtype
1714 if ret != null then
1715 self.mtype = ret
1716 else
1717 self.is_typed = true
1718 end
1719 end
1720
1721 # The name of the property
1722 # Each subclass simply provide the correct name.
1723 private fun property_name: String is abstract
1724
1725 # The node identifying the name (id, operator, etc) for messages.
1726 #
1727 # Is `self` by default
1728 private fun property_node: ANode do return self
1729
1730 # An array of all arguments (excluding self)
1731 fun raw_arguments: Array[AExpr] do return compute_raw_arguments
1732
1733 private fun compute_raw_arguments: Array[AExpr] is abstract
1734 end
1735
1736 redef class ABinopExpr
1737 redef fun compute_raw_arguments do return [n_expr2]
1738 redef fun property_name do return operator
1739 redef fun property_node do return n_op
1740 end
1741
1742 redef class AEqFormExpr
1743 redef fun accept_typing(v)
1744 do
1745 super
1746 v.null_test(self)
1747 end
1748
1749 redef fun accept_post_typing(v)
1750 do
1751 var mtype = n_expr.mtype
1752 var mtype2 = n_expr2.mtype
1753
1754 if mtype == null or mtype2 == null then return
1755
1756 if not mtype2 isa MNullType then return
1757
1758 v.check_can_be_null(n_expr, mtype)
1759 end
1760 end
1761
1762 redef class AUnaryopExpr
1763 redef fun property_name do return "unary {operator}"
1764 redef fun compute_raw_arguments do return new Array[AExpr]
1765 end
1766
1767
1768 redef class ACallExpr
1769 redef fun property_name do return n_qid.n_id.text
1770 redef fun property_node do return n_qid
1771 redef fun compute_raw_arguments do return n_args.to_a
1772 end
1773
1774 redef class ACallAssignExpr
1775 redef fun property_name do return n_qid.n_id.text + "="
1776 redef fun property_node do return n_qid
1777 redef fun compute_raw_arguments
1778 do
1779 var res = n_args.to_a
1780 res.add(n_value)
1781 return res
1782 end
1783 end
1784
1785 redef class ABraExpr
1786 redef fun property_name do return "[]"
1787 redef fun compute_raw_arguments do return n_args.to_a
1788 end
1789
1790 redef class ABraAssignExpr
1791 redef fun property_name do return "[]="
1792 redef fun compute_raw_arguments
1793 do
1794 var res = n_args.to_a
1795 res.add(n_value)
1796 return res
1797 end
1798 end
1799
1800 redef class ASendReassignFormExpr
1801 # The property invoked for the writing
1802 var write_callsite: nullable CallSite
1803
1804 redef fun accept_typing(v)
1805 do
1806 var recvtype = v.visit_expr(self.n_expr)
1807 var name = self.property_name
1808 var node = self.property_node
1809
1810 if recvtype == null then return # Forward error
1811
1812 var for_self = self.n_expr isa ASelfExpr
1813 var callsite = v.get_method(node, recvtype, name, for_self)
1814
1815 if callsite == null then return
1816 self.callsite = callsite
1817
1818 var args = compute_raw_arguments
1819
1820 callsite.check_signature(v, args)
1821
1822 var readtype = callsite.msignature.return_mtype
1823 if readtype == null then
1824 v.error(node, "Error: `{name}` is not a function.")
1825 return
1826 end
1827
1828 var wcallsite = v.get_method(node, recvtype, name + "=", self.n_expr isa ASelfExpr)
1829 if wcallsite == null then return
1830 self.write_callsite = wcallsite
1831
1832 var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
1833 if wtype == null then return
1834
1835 args = args.to_a # duplicate so raw_arguments keeps only the getter args
1836 args.add(self.n_value)
1837 wcallsite.check_signature(v, args)
1838
1839 self.is_typed = true
1840 end
1841 end
1842
1843 redef class ACallReassignExpr
1844 redef fun property_name do return n_qid.n_id.text
1845 redef fun property_node do return n_qid.n_id
1846 redef fun compute_raw_arguments do return n_args.to_a
1847 end
1848
1849 redef class ABraReassignExpr
1850 redef fun property_name do return "[]"
1851 redef fun compute_raw_arguments do return n_args.to_a
1852 end
1853
1854 redef class AInitExpr
1855 redef fun property_name do return "init"
1856 redef fun property_node do return n_kwinit
1857 redef fun compute_raw_arguments do return n_args.to_a
1858 end
1859
1860 redef class AExprs
1861 fun to_a: Array[AExpr] do return self.n_exprs.to_a
1862 end
1863
1864 ###
1865
1866 redef class ASuperExpr
1867 # The method to call if the super is in fact a 'super init call'
1868 # Note: if the super is a normal call-next-method, then this attribute is null
1869 var callsite: nullable CallSite
1870
1871 # The method to call is the super is a standard `call-next-method` super-call
1872 # Note: if the super is a special super-init-call, then this attribute is null
1873 var mpropdef: nullable MMethodDef
1874
1875 redef fun accept_typing(v)
1876 do
1877 var anchor = v.anchor
1878 assert anchor != null
1879 var recvtype = v.get_variable(self, v.selfvariable)
1880 assert recvtype != null
1881 var mproperty = v.mpropdef.mproperty
1882 if not mproperty isa MMethod then
1883 v.error(self, "Error: `super` only usable in a `method`.")
1884 return
1885 end
1886 var superprops = mproperty.lookup_super_definitions(v.mmodule, anchor)
1887 if superprops.length == 0 then
1888 if mproperty.is_init and v.mpropdef.is_intro then
1889 process_superinit(v)
1890 return
1891 end
1892 v.error(self, "Error: no super method to call for `{mproperty}`.")
1893 return
1894 end
1895 # FIXME: covariance of return type in linear extension?
1896 var superprop = superprops.first
1897
1898 var msignature = superprop.msignature.as(not null)
1899 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
1900 var args = self.n_args.to_a
1901 if args.length > 0 then
1902 signaturemap = v.check_signature(self, args, mproperty, msignature)
1903 end
1904 self.mtype = msignature.return_mtype
1905 self.is_typed = true
1906 v.mpropdef.has_supercall = true
1907 mpropdef = v.mpropdef.as(MMethodDef)
1908 end
1909
1910 # The mapping used on the call to associate arguments to parameters.
1911 # If null then no specific association is required.
1912 var signaturemap: nullable SignatureMap
1913
1914 private fun process_superinit(v: TypeVisitor)
1915 do
1916 var anchor = v.anchor
1917 assert anchor != null
1918 var recvtype = v.get_variable(self, v.selfvariable)
1919 assert recvtype != null
1920 var mpropdef = v.mpropdef
1921 assert mpropdef isa MMethodDef
1922 var mproperty = mpropdef.mproperty
1923 var superprop: nullable MMethodDef = null
1924 for msupertype in mpropdef.mclassdef.supertypes do
1925 msupertype = msupertype.anchor_to(v.mmodule, anchor)
1926 var errcount = v.modelbuilder.toolcontext.error_count
1927 var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
1928 if candidate == null then
1929 if v.modelbuilder.toolcontext.error_count > errcount then return # Forward error
1930 continue # Try next super-class
1931 end
1932 if superprop != null and candidate.is_root_init then
1933 continue
1934 end
1935 if superprop != null and superprop.mproperty != candidate and not superprop.mproperty.is_root_init then
1936 v.error(self, "Error: conflicting super constructor to call for `{mproperty}`: `{candidate.full_name}`, `{superprop.mproperty.full_name}`")
1937 return
1938 end
1939 var candidatedefs = candidate.lookup_definitions(v.mmodule, anchor)
1940 if superprop != null and superprop.mproperty == candidate then
1941 if superprop == candidatedefs.first then continue
1942 candidatedefs.add(superprop)
1943 end
1944 if candidatedefs.length > 1 then
1945 v.error(self, "Error: conflicting property definitions for property `{mproperty}` in `{recvtype}`: {candidatedefs.join(", ")}")
1946 return
1947 end
1948 superprop = candidatedefs.first
1949 end
1950 if superprop == null then
1951 v.error(self, "Error: no super method to call for `{mproperty}`.")
1952 return
1953 end
1954
1955 var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
1956 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
1957
1958 var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
1959 self.callsite = callsite
1960
1961 var args = self.n_args.to_a
1962 if args.length > 0 then
1963 callsite.check_signature(v, args)
1964 else
1965 # Check there is at least enough parameters
1966 if mpropdef.msignature.arity < msignature.arity then
1967 v.error(self, "Error: not enough implicit arguments to pass. Got `{mpropdef.msignature.arity}`, expected at least `{msignature.arity}`. Signature is `{msignature}`.")
1968 return
1969 end
1970 # Check that each needed parameter is conform
1971 var i = 0
1972 for sp in msignature.mparameters do
1973 var p = mpropdef.msignature.mparameters[i]
1974 if not v.is_subtype(p.mtype, sp.mtype) then
1975 v.error(self, "Type Error: expected argument #{i} of type `{sp.mtype}`, got implicit argument `{p.name}` of type `{p.mtype}`. Signature is {msignature}")
1976 return
1977 end
1978 i += 1
1979 end
1980 end
1981
1982 self.is_typed = true
1983 end
1984 end
1985
1986 ####
1987
1988 redef class ANewExpr
1989 # The constructor invoked by the new.
1990 var callsite: nullable CallSite
1991
1992 # The designated type
1993 var recvtype: nullable MClassType
1994
1995 redef fun accept_typing(v)
1996 do
1997 var recvtype = v.resolve_mtype(self.n_type)
1998 if recvtype == null then return
1999
2000 if not recvtype isa MClassType then
2001 if recvtype isa MNullableType then
2002 v.error(self, "Type Error: cannot instantiate the nullable type `{recvtype}`.")
2003 return
2004 else if recvtype isa MFormalType then
2005 v.error(self, "Type Error: cannot instantiate the formal type `{recvtype}`.")
2006 return
2007 else
2008 v.error(self, "Type Error: cannot instantiate the type `{recvtype}`.")
2009 return
2010 end
2011 end
2012
2013 self.recvtype = recvtype
2014 var kind = recvtype.mclass.kind
2015
2016 var name: String
2017 var nqid = self.n_qid
2018 var node: ANode
2019 if nqid != null then
2020 name = nqid.n_id.text
2021 node = nqid
2022 else
2023 name = "new"
2024 node = self.n_kwnew
2025 end
2026 if name == "intern" then
2027 if kind != concrete_kind then
2028 v.error(self, "Type Error: cannot instantiate {kind} {recvtype}.")
2029 return
2030 end
2031 if n_args.n_exprs.not_empty then
2032 v.error(n_args, "Type Error: the intern constructor expects no arguments.")
2033 return
2034 end
2035 # Our job is done
2036 self.mtype = recvtype
2037 return
2038 end
2039
2040 var callsite = v.get_method(node, recvtype, name, false)
2041 if callsite == null then return
2042
2043 if not callsite.mproperty.is_new then
2044 if kind != concrete_kind then
2045 v.error(self, "Type Error: cannot instantiate {kind} `{recvtype}`.")
2046 return
2047 end
2048 self.mtype = recvtype
2049 else
2050 self.mtype = callsite.msignature.return_mtype
2051 assert self.mtype != null
2052 end
2053
2054 self.callsite = callsite
2055
2056 if not callsite.mproperty.is_init_for(recvtype.mclass) then
2057 v.error(self, "Error: `{name}` is not a constructor.")
2058 return
2059 end
2060
2061 var args = n_args.to_a
2062 callsite.check_signature(v, args)
2063 end
2064 end
2065
2066 ####
2067
2068 redef class AAttrFormExpr
2069 # The attribute accessed.
2070 var mproperty: nullable MAttribute
2071
2072 # The static type of the attribute.
2073 var attr_type: nullable MType
2074
2075 # Resolve the attribute accessed.
2076 private fun resolve_property(v: TypeVisitor)
2077 do
2078 var recvtype = v.visit_expr(self.n_expr)
2079 if recvtype == null then return # Skip error
2080 var node = self.n_id
2081 var name = node.text
2082 if recvtype isa MNullType then
2083 v.error(node, "Error: attribute `{name}` access on `null`.")
2084 return
2085 end
2086
2087 var unsafe_type = v.anchor_to(recvtype)
2088 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
2089 if mproperty == null then
2090 v.modelbuilder.error(node, "Error: attribute `{name}` does not exist in `{recvtype}`.")
2091 return
2092 end
2093 assert mproperty isa MAttribute
2094 self.mproperty = mproperty
2095
2096 var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
2097 assert mpropdefs.length == 1
2098 var mpropdef = mpropdefs.first
2099 var attr_type = mpropdef.static_mtype
2100 if attr_type == null then return # skip error
2101 attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
2102 self.attr_type = attr_type
2103 end
2104 end
2105
2106 redef class AAttrExpr
2107 redef fun accept_typing(v)
2108 do
2109 self.resolve_property(v)
2110 self.mtype = self.attr_type
2111 end
2112 end
2113
2114
2115 redef class AAttrAssignExpr
2116 redef fun accept_typing(v)
2117 do
2118 self.resolve_property(v)
2119 var mtype = self.attr_type
2120
2121 v.visit_expr_subtype(self.n_value, mtype)
2122 self.is_typed = mtype != null
2123 end
2124 end
2125
2126 redef class AAttrReassignExpr
2127 redef fun accept_typing(v)
2128 do
2129 self.resolve_property(v)
2130 var mtype = self.attr_type
2131 if mtype == null then return # Skip error
2132
2133 var rettype = self.resolve_reassignment(v, mtype, mtype)
2134
2135 self.is_typed = rettype != null
2136 end
2137 end
2138
2139 redef class AIssetAttrExpr
2140 redef fun accept_typing(v)
2141 do
2142 self.resolve_property(v)
2143 var mtype = self.attr_type
2144 if mtype == null then return # Skip error
2145
2146 var recvtype = self.n_expr.mtype.as(not null)
2147 var bound = v.resolve_for(mtype, recvtype, false)
2148 if bound isa MNullableType then
2149 v.error(n_id, "Type Error: `isset` on a nullable attribute.")
2150 end
2151 self.mtype = v.type_bool(self)
2152 end
2153 end
2154
2155 redef class AVarargExpr
2156 redef fun accept_typing(v)
2157 do
2158 # This kind of pseudo-expression can be only processed trough a signature
2159 # See `check_signature`
2160 # Other cases are a syntax error.
2161 v.error(self, "Syntax Error: unexpected `...`.")
2162 end
2163 end
2164
2165 ###
2166
2167 redef class ADebugTypeExpr
2168 redef fun accept_typing(v)
2169 do
2170 var expr = v.visit_expr(self.n_expr)
2171 if expr == null then return
2172 var unsafe = v.anchor_to(expr)
2173 var ntype = self.n_type
2174 var mtype = v.resolve_mtype(ntype)
2175 if mtype != null and mtype != expr then
2176 var umtype = v.anchor_to(mtype)
2177 v.modelbuilder.warning(self, "debug", "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
2178 end
2179 self.is_typed = true
2180 end
2181 end