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