model: remove `new_msignature` and special call as the new signature is the method...
[nit.git] / src / semantize / typing.nit
index b4599d0..4824cb4 100644 (file)
@@ -314,8 +314,12 @@ private class TypeVisitor
 
                var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
                if name == "new" and mproperty == null then
-                       name = "init"
+                       name = "autoinit"
                        mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
+                       if mproperty == null then
+                               name = "init"
+                               mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
+                       end
                end
 
                if mproperty == null then
@@ -374,7 +378,7 @@ private class TypeVisitor
                end
 
 
-               var msignature = mpropdef.new_msignature or else mpropdef.msignature
+               var msignature = mpropdef.msignature
                if msignature == null then return null # skip error
                msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
 
@@ -490,8 +494,12 @@ private class TypeVisitor
                                continue # skip the vararg
                        end
 
-                       var paramtype = param.mtype
-                       self.visit_expr_subtype(arg, paramtype)
+                       if not param.is_vararg then
+                               var paramtype = param.mtype
+                               self.visit_expr_subtype(arg, paramtype)
+                       else
+                               check_one_vararg(arg, param)
+                       end
                end
 
                if min_arity > 0 then
@@ -509,27 +517,9 @@ private class TypeVisitor
                        var paramtype = msignature.mparameters[vararg_rank].mtype
                        var first = args[vararg_rank]
                        if vararg_decl == 0 then
-                               var mclass = get_mclass(node, "Array")
-                               if mclass == null then return null # Forward error
-                               var array_mtype = mclass.get_mtype([paramtype])
-                               if first isa AVarargExpr then
-                                       self.visit_expr_subtype(first.n_expr, array_mtype)
-                                       first.mtype  = first.n_expr.mtype
-                               else
-                                       # only one vararg, maybe `...` was forgot, so be gentle!
-                                       var t = visit_expr(first)
-                                       if t == null then return null # Forward error
-                                       if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
-                                               # Not acceptable but could be a `...`
-                                               error(first, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
-                                               return null
-                                       end
-                                       # Standard valid vararg, finish the job
-                                       map.vararg_decl = 1
-                                       self.visit_expr_subtype(first, paramtype)
-                               end
+                               if not check_one_vararg(first, msignature.mparameters[vararg_rank]) then return null
                        else
-                               map.vararg_decl = vararg_decl + 1
+                               first.vararg_decl = vararg_decl + 1
                                for i in [vararg_rank..vararg_rank+vararg_decl] do
                                        self.visit_expr_subtype(args[i], paramtype)
                                end
@@ -539,6 +529,33 @@ private class TypeVisitor
                return map
        end
 
+       # Check an expression as a single vararg.
+       # The main point of the method if to handle the case of reversed vararg (see `AVarargExpr`)
+       fun check_one_vararg(arg: AExpr, param: MParameter): Bool
+       do
+               var paramtype = param.mtype
+               var mclass = get_mclass(arg, "Array")
+               if mclass == null then return false # Forward error
+               var array_mtype = mclass.get_mtype([paramtype])
+               if arg isa AVarargExpr then
+                       self.visit_expr_subtype(arg.n_expr, array_mtype)
+                       arg.mtype  = arg.n_expr.mtype
+               else
+                       # only one vararg, maybe `...` was forgot, so be gentle!
+                       var t = visit_expr(arg)
+                       if t == null then return false # Forward error
+                       if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
+                               # Not acceptable but could be a `...`
+                               error(arg, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
+                               return false
+                       end
+                       # Standard valid vararg, finish the job
+                       arg.vararg_decl = 1
+                       self.visit_expr_subtype(arg, paramtype)
+               end
+               return true
+       end
+
        fun error(node: ANode, message: String)
        do
                self.modelbuilder.error(node, message)
@@ -614,10 +631,6 @@ end
 class SignatureMap
        # Associate a parameter to an argument
        var map = new ArrayMap[Int, Int]
-
-       # The length of the vararg sequence
-       # 0 if no vararg or if reverse vararg (cf `AVarargExpr`)
-       var vararg_decl: Int = 0
 end
 
 # A specific method call site with its associated informations.
@@ -853,6 +866,15 @@ redef class AExpr
        # The result of the evaluation of `self` must be
        # stored inside the designated array (there is an implicit `push`)
        var comprehension: nullable AArrayExpr = null
+
+       # It indicates the number of arguments collected as a vararg.
+       #
+       # When 0, the argument is used as is, without transformation.
+       # When 1, the argument is transformed into an singleton array.
+       # Above 1, the arguments and the next ones are transformed into a common array.
+       #
+       # This attribute is meaning less on expressions not used as attributes.
+       var vararg_decl: Int = 0
 end
 
 redef class ABlockExpr
@@ -1563,7 +1585,7 @@ redef class ARangeExpr
                # get the constructor
                var callsite
                if self isa ACrangeExpr then
-                       callsite = v.get_method(self, mtype, "init", false)
+                       callsite = v.get_method(self, mtype, "autoinit", false)
                else if self isa AOrangeExpr then
                        callsite = v.get_method(self, mtype, "without_last", false)
                else
@@ -1886,7 +1908,7 @@ redef class ABraReassignExpr
 end
 
 redef class AInitExpr
-       redef fun property_name do return "init"
+       redef fun property_name do if n_args.n_exprs.is_empty then return "init" else return "autoinit"
        redef fun property_node do return n_kwinit
        redef fun compute_raw_arguments do return n_args.to_a
 end
@@ -1986,7 +2008,7 @@ redef class ASuperExpr
                        return
                end
 
-               var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
+               var msignature = superprop.msignature.as(not null)
                msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
 
                var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)