typing: remove `raw_arguments` as a cache
[nit.git] / src / typing.nit
index 6838784..9cae36f 100644 (file)
@@ -27,11 +27,6 @@ redef class ToolContext
        var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
 end
 
-redef class MPropDef
-       # Does the MPropDef contains a call to super or a call of a super-constructor?
-       var has_supercall: Bool = false
-end
-
 private class TypingPhase
        super Phase
        redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
@@ -247,8 +242,8 @@ private class TypeVisitor
                end
 
                assert mproperty isa MMethod
-               if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility then
-                       self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self. {mproperty.intro_mclassdef.mmodule.visibility_for(self.mmodule)}")
+               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
+                       self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self.")
                        return null
                end
 
@@ -279,7 +274,7 @@ private class TypeVisitor
                        end
                end
 
-               var callsite = new CallSite(node, recvtype, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
+               var callsite = new CallSite(node, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
                return callsite
        end
 
@@ -391,9 +386,15 @@ class CallSite
        # The assiciated node for location
        var node: ANode
 
-       # The statis type of the receiver
+       # The static type of the receiver (possibly unresolved)
        var recv: MType
 
+       # The module where the callsite is present
+       var mmodule: MModule
+
+       # The anchor to use with `recv` or `msignature`
+       var anchor: nullable MClassType
+
        # Is the receiver self?
        # If "for_self", virtual types of the signature are keeped
        # If "not_for_self", virtual type are erased
@@ -529,7 +530,7 @@ end
 
 redef class AExpr
        # The static type of the expression.
-       # null if self is a statement of in case of error
+       # null if self is a statement or in case of error
        var mtype: nullable MType = null
 
        # Is the statement correctly typed?
@@ -815,11 +816,11 @@ end
 redef class AForExpr
        var coltype: nullable MClassType
 
-       var method_iterator: nullable MMethod
-       var method_is_ok: nullable MMethod
-       var method_item: nullable MMethod
-       var method_next: nullable MMethod
-       var method_key: nullable MMethod
+       var method_iterator: nullable CallSite
+       var method_is_ok: nullable CallSite
+       var method_item: nullable CallSite
+       var method_next: nullable CallSite
+       var method_key: nullable CallSite
 
        private fun do_type_iterator(v: TypeVisitor, mtype: MType)
        do
@@ -833,22 +834,12 @@ redef class AForExpr
                if objcla == null then return
 
                # check iterator method
-               var unsafe_type = v.anchor_to(mtype)
-               if v.try_get_mproperty_by_name2(self, unsafe_type, "iterator") == null then
-                       if v.try_get_mproperty_by_name2(self, unsafe_type, "iterate") == null then
-                               v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
-                       else
-                               v.modelbuilder.error(self, "NOT YET IMPLEMENTED: Do 'for' on {mtype}")
-                       end
-                       return
-               end
-
                var itdef = v.get_method(self, mtype, "iterator", true)
                if itdef == null then
                        v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.")
                        return
                end
-               self.method_iterator = itdef.mproperty
+               self.method_iterator = itdef
 
                # check that iterator return something
                var ittype = itdef.msignature.return_mtype
@@ -905,21 +896,21 @@ redef class AForExpr
                        v.error(self, "Type Error: 'for' expects a method 'is_ok' in 'Iterator' type {ittype}.")
                        return
                end
-               self.method_is_ok = ikdef.mproperty
+               self.method_is_ok = ikdef
 
                var itemdef = v.get_method(self, ittype, "item", false)
                if itemdef == null then
                        v.error(self, "Type Error: 'for' expects a method 'item' in 'Iterator' type {ittype}.")
                        return
                end
-               self.method_item = itemdef.mproperty
+               self.method_item = itemdef
 
                var nextdef = v.get_method(self, ittype, "next", false)
                if nextdef == null then
                        v.error(self, "Type Error: 'for' expects a method 'next' in 'Iterator' type {ittype}.")
                        return
                end
-               self.method_next = nextdef.mproperty
+               self.method_next = nextdef
 
                if is_map then
                        var keydef = v.get_method(self, ittype, "key", false)
@@ -927,7 +918,7 @@ redef class AForExpr
                                v.error(self, "Type Error: 'for' expects a method 'key' in 'Iterator' type {ittype}.")
                                return
                        end
-                       self.method_key = keydef.mproperty
+                       self.method_key = keydef
                end
        end
 
@@ -1100,6 +1091,8 @@ redef class AArrayExpr
 end
 
 redef class ARangeExpr
+       var init_callsite: nullable CallSite
+
        redef fun accept_typing(v)
        do
                var discrete_class = v.get_mclass(self, "Discrete")
@@ -1110,13 +1103,28 @@ redef class ARangeExpr
                if t1 == null or t2 == null then return
                var mclass = v.get_mclass(self, "Range")
                if mclass == null then return # Forward error
+               var mtype
                if v.is_subtype(t1, t2) then
-                       self.mtype = mclass.get_mtype([t2])
+                       mtype = mclass.get_mtype([t2])
                else if v.is_subtype(t2, t1) then
-                       self.mtype = mclass.get_mtype([t1])
+                       mtype = mclass.get_mtype([t1])
                else
                        v.error(self, "Type Error: Cannot create range: {t1} vs {t2}")
+                       return
                end
+
+               self.mtype = mtype
+
+               # get the constructor
+               var callsite
+               if self isa ACrangeExpr then
+                       callsite = v.get_method(self, mtype, "init", false)
+               else if self isa AOrangeExpr then
+                       callsite = v.get_method(self, mtype, "without_last", false)
+               else
+                       abort
+               end
+               init_callsite = callsite
        end
 end
 
@@ -1213,7 +1221,6 @@ redef class ASendExpr
                var msignature = callsite.msignature
 
                var args = compute_raw_arguments
-               self.raw_arguments = args
 
                callsite.check_signature(v, args)
 
@@ -1237,7 +1244,7 @@ redef class ASendExpr
        private fun property_name: String is abstract
 
        # An array of all arguments (excluding self)
-       var raw_arguments: nullable Array[AExpr]
+       fun raw_arguments: Array[AExpr] do return compute_raw_arguments
 
        private fun compute_raw_arguments: Array[AExpr] is abstract
 end
@@ -1374,7 +1381,6 @@ redef class ASendReassignFormExpr
                self.callsite = callsite
 
                var args = compute_raw_arguments
-               self.raw_arguments = args
 
                callsite.check_signature(v, args)
 
@@ -1425,6 +1431,10 @@ redef class ASuperExpr
        # Note: if the super is a normal call-next-method, then this attribute is null
        var callsite: nullable CallSite
 
+       # The method to call is the super is a standard `call-next-method` super-call
+       # Note: if the super is a special super-init-call, then this attribute is null
+       var mpropdef: nullable MMethodDef
+
        redef fun accept_typing(v)
        do
                var recvtype = v.nclassdef.mclassdef.bound_mtype
@@ -1453,6 +1463,7 @@ redef class ASuperExpr
                self.mtype = msignature.return_mtype
                self.is_typed = true
                v.mpropdef.has_supercall = true
+               mpropdef = v.mpropdef.as(MMethodDef)
        end
 
        private fun process_superinit(v: TypeVisitor)
@@ -1491,7 +1502,7 @@ redef class ASuperExpr
                end
 
                var msignature = v.resolve_signature_for(superprop, recvtype, true)
-               var callsite = new CallSite(self, recvtype, true, superprop.mproperty, superprop, msignature, false)
+               var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
                self.callsite = callsite
 
                var args = self.n_args.to_a