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