typing: change specification about default arguments. everything is done here
authorJean Privat <jean@pryen.org>
Thu, 6 Aug 2015 18:32:14 +0000 (14:32 -0400)
committerJean Privat <jean@pryen.org>
Mon, 10 Aug 2015 13:57:43 +0000 (09:57 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/semantize/typing.nit

index 1b53f65..9b0d841 100644 (file)
@@ -414,26 +414,30 @@ private class TypeVisitor
                                return null
                        end
                else if args.length != msignature.arity then
-                       if msignature.arity == msignature.min_arity then
-                               modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
-                               return null
-                       end
+                       # Too much argument
                        if args.length > msignature.arity then
-                               modelbuilder.error(node, "Error: expected at most {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
-                               return null
-                       end
-                       if args.length < msignature.min_arity then
-                               modelbuilder.error(node, "Error: expected at least {msignature.min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
+                               modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
                                return null
                        end
+                       # Other cases are managed later
                end
 
+
                #debug("CALL {unsafe_type}.{msignature}")
 
                # Associate each parameter to a position in the arguments
                var map = new SignatureMap
 
-               var setted = args.length - msignature.min_arity
+               # Special case for the isolated last argument
+               # TODO: reify this method characteristics (where? the param, the signature, the method?)
+               var last_is_padded = mproperty.name.chars.last == '='
+               var nbargs = args.length
+               if last_is_padded then
+                       nbargs -= 1
+                       assert not args.last isa ANamedargExpr
+                       map.map[msignature.arity - 1] = args.length - 1
+                       self.visit_expr_subtype(args.last, msignature.mparameters.last.mtype)
+               end
 
                # First, handle named arguments
                for i in [0..args.length[ do
@@ -445,10 +449,6 @@ private class TypeVisitor
                                modelbuilder.error(e.n_id, "Error: no parameter `{name}` for `{mproperty}{msignature}`.")
                                return null
                        end
-                       if not param.is_default then
-                               modelbuilder.error(e, "Error: parameter `{name}` is not optional for `{mproperty}{msignature}`.")
-                               return null
-                       end
                        var idx = msignature.mparameters.index_of(param)
                        var prev = map.map.get_or_null(idx)
                        if prev != null then
@@ -456,10 +456,12 @@ private class TypeVisitor
                                return null
                        end
                        map.map[idx] = i
-                       setted -= 1
                        e.mtype = self.visit_expr_subtype(e.n_expr, param.mtype)
                end
 
+               # Number of minimum mandatory remaining parameters
+               var min_arity = 0
+
                # Second, associate remaining parameters
                var vararg_decl = args.length - msignature.arity
                var j = 0
@@ -468,16 +470,16 @@ private class TypeVisitor
                        if map.map.has_key(i) then continue
 
                        var param = msignature.mparameters[i]
-                       if param.is_default then
-                               if setted > 0 then
-                                       setted -= 1
-                               else
-                                       continue
-                               end
-                       end
 
                        # Search the next free argument: skip named arguments since they are already associated
-                       while args[j] isa ANamedargExpr do j += 1
+                       while j < nbargs and args[j] isa ANamedargExpr do j += 1
+                       if j >= nbargs then
+                               if not param.mtype isa MNullableType then
+                                       min_arity = j + 1
+                               end
+                               j += 1
+                               continue
+                       end
                        var arg = args[j]
                        map.map[i] = j
                        j += 1
@@ -491,6 +493,16 @@ private class TypeVisitor
                        self.visit_expr_subtype(arg, paramtype)
                end
 
+               if min_arity > 0 then
+                       if last_is_padded then min_arity += 1
+                       if min_arity < msignature.arity then
+                               modelbuilder.error(node, "Error: expected at least {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
+                       else
+                               modelbuilder.error(node, "Error: expected {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
+                       end
+                       return null
+               end
+
                # Third, check varargs
                if vararg_rank >= 0 then
                        var paramtype = msignature.mparameters[vararg_rank].mtype