Merge: Option --keep-going
authorJean Privat <jean@pryen.org>
Sat, 18 Apr 2015 09:47:09 +0000 (16:47 +0700)
committerJean Privat <jean@pryen.org>
Sat, 18 Apr 2015 09:47:09 +0000 (16:47 +0700)
Follow up of #959 and #1241. Now an option is exposed so people can happily try to use it on various tools that will turn them berserk and make them want to kill you.

Pull-Request: #1270
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>

lib/standard/collection/array.nit
src/compiler/abstract_compiler.nit
src/interpreter/naive_interpreter.nit
src/modelize/modelize_property.nit
src/semantize/typing.nit
tests/error_operators.nit [new file with mode: 0644]
tests/sav/error_operators.res [new file with mode: 0644]
tests/sav/test_ffi_c_operators.res
tests/sav/test_new_native_alt1.res
tests/test_ffi_c_operators.nit

index 3cc0b57..cdb5242 100644 (file)
@@ -147,6 +147,55 @@ abstract class AbstractArrayRead[E]
        private var free_iterator: nullable ArrayIterator[E] = null
 
        redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
+
+       # Returns a sub-array containing `count` elements starting from `from`.
+       #
+       # For most cases (see other case bellow),
+       # the first element is `from` and
+       # the last element is `from+count-1`.
+       #
+       # ~~~
+       # var a = [10, 20, 30, 40, 50]
+       # assert a.sub(0, 3) == [10, 20, 30]
+       # assert a.sub(3, 2) == [40, 50]
+       # assert a.sub(3, 1) == [40]
+       # ~~~
+       #
+       # If `count` is 0 or negative then an empty array is returned
+       #
+       # ~~~
+       # assert a.sub(3,0).is_empty
+       # assert a.sub(3,-1).is_empty
+       # ~~~
+       #
+       # If `from < 0` or `from+count>length` then inexistent elements are ignored.
+       # In this case the length of the result is lower than count.
+       #
+       # ~~~
+       # assert a.sub(-2, 4)  == [10, 20]
+       # assert a.sub(4, 99)  == [50]
+       # assert a.sub(-9, 99) == [10,20,30,40,50]
+       # assert a.sub(-99, 9).is_empty
+       # ~~~
+       fun sub(from: Int, count: Int): Array[E] do
+               if from < 0 then
+                       count += from
+                       from = 0
+               end
+               if count < 0 then
+                       count = 0
+               end
+               var to = from + count
+               if to > length then
+                       to = length
+               end
+               var res = new Array[E].with_capacity(to - from)
+               while from < to do
+                       res.add(self[from])
+                       from += 1
+               end
+               return res
+       end
 end
 
 # Resizable one dimension array of objects.
index 2359c7d..1b8bf6a 100644 (file)
@@ -1146,40 +1146,43 @@ abstract class AbstractCompilerVisitor
        # Evaluate `args` as expressions in the call of `mpropdef` on `recv`.
        # This method is used to manage varargs in signatures and returns the real array
        # of runtime variables to use in the call.
-       fun varargize(mpropdef: MMethodDef, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]
+       fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]
        do
                var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
                var res = new Array[RuntimeVariable]
                res.add(recv)
 
-               if args.is_empty then return res
+               if msignature.arity == 0 then return res
 
-               var vararg_rank = msignature.vararg_rank
-               var vararg_len = args.length - msignature.arity
-               if vararg_len < 0 then vararg_len = 0
+               if map == null then
+                       assert args.length == msignature.arity
+                       for ne in args do
+                               res.add self.expr(ne, null)
+                       end
+                       return res
+               end
+
+               # Eval in order of arguments, not parameters
+               var exprs = new Array[RuntimeVariable].with_capacity(args.length)
+               for ne in args do
+                       exprs.add self.expr(ne, null)
+               end
 
+               # Fill `res` with the result of the evaluation according to the mapping
                for i in [0..msignature.arity[ do
-                       if i == vararg_rank then
-                               var ne = args[i]
-                               if ne isa AVarargExpr then
-                                       var e = self.expr(ne.n_expr, null)
-                                       res.add(e)
-                                       continue
-                               end
-                               var vararg = new Array[RuntimeVariable]
-                               for j in [vararg_rank..vararg_rank+vararg_len] do
-                                       var e = self.expr(args[j], null)
-                                       vararg.add(e)
-                               end
-                               var elttype = msignature.mparameters[vararg_rank].mtype
+                       var param = msignature.mparameters[i]
+                       var j = map.map.get_or_null(i)
+                       if j == null then
+                               continue
+                       end
+                       if param.is_vararg and map.vararg_decl > 0 then
+                               var vararg = exprs.sub(j, map.vararg_decl)
+                               var elttype = param.mtype
                                var arg = self.vararg_instance(mpropdef, recv, vararg, elttype)
                                res.add(arg)
-                       else
-                               var j = i
-                               if i > vararg_rank then j += vararg_len
-                               var e = self.expr(args[j], null)
-                               res.add(e)
+                               continue
                        end
+                       res.add exprs[j]
                end
                return res
        end
@@ -2975,7 +2978,7 @@ redef class ASendExpr
        do
                var recv = v.expr(self.n_expr, null)
                var callsite = self.callsite.as(not null)
-               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
                return v.compile_callsite(callsite, args)
        end
 end
@@ -2985,7 +2988,7 @@ redef class ASendReassignFormExpr
        do
                var recv = v.expr(self.n_expr, null)
                var callsite = self.callsite.as(not null)
-               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
 
                var value = v.expr(self.n_value, null)
 
@@ -3007,26 +3010,33 @@ redef class ASuperExpr
 
                var callsite = self.callsite
                if callsite != null then
-                       var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+                       var args
 
-                       # Add additional arguments for the super init call
-                       if args.length == 1 then
+                       if self.n_args.n_exprs.is_empty then
+                               # Add automatic arguments for the super init call
+                               args = [recv]
                                for i in [0..callsite.msignature.arity[ do
                                        args.add(v.frame.arguments[i+1])
                                end
+                       else
+                               args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
                        end
+
                        # Super init call
                        var res = v.compile_callsite(callsite, args)
                        return res
                end
 
                var mpropdef = self.mpropdef.as(not null)
-               var args = v.varargize(mpropdef, recv, self.n_args.n_exprs)
-               if args.length == 1 then
+
+               var args
+               if self.n_args.n_exprs.is_empty then
                        args = v.frame.arguments
+               else
+                       args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
                end
 
-               # stantard call-next-method
+               # Standard call-next-method
                return v.supercall(mpropdef, recv.mtype.as(MClassType), args)
        end
 end
@@ -3050,7 +3060,7 @@ redef class ANewExpr
                var callsite = self.callsite
                if callsite == null then return recv
 
-               var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+               var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
                var res2 = v.compile_callsite(callsite, args)
                if res2 != null then
                        #self.debug("got {res2} from {mproperty}. drop {recv}")
@@ -3102,6 +3112,13 @@ redef class AIssetAttrExpr
        end
 end
 
+redef class AVarargExpr
+       redef fun expr(v)
+       do
+               return v.expr(self.n_expr, null)
+       end
+end
+
 redef class ADebugTypeExpr
        redef fun stmt(v)
        do
index 7d7cab9..c1bd59b 100644 (file)
@@ -370,42 +370,48 @@ class NaiveInterpreter
        # This method is used to manage varargs in signatures and returns the real array
        # of instances to use in the call.
        # Return `null` if one of the evaluation of the arguments return null.
-       fun varargize(mpropdef: MMethodDef, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance]
+       fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance]
        do
                var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
                var res = new Array[Instance]
                res.add(recv)
 
-               if args.is_empty then return res
+               if msignature.arity == 0 then return res
+
+               if map == null then
+                       assert args.length == msignature.arity else debug("Expected {msignature.arity} args, got {args.length}")
+                       for ne in args do
+                               var e = self.expr(ne)
+                               if e == null then return null
+                               res.add e
+                       end
+                       return res
+               end
+
+               # Eval in order of arguments, not parameters
+               var exprs = new Array[Instance].with_capacity(args.length)
+               for ne in args do
+                       var e = self.expr(ne)
+                       if e == null then return null
+                       exprs.add e
+               end
 
-               var vararg_rank = msignature.vararg_rank
-               var vararg_len = args.length - msignature.arity
-               if vararg_len < 0 then vararg_len = 0
 
+               # Fill `res` with the result of the evaluation according to the mapping
                for i in [0..msignature.arity[ do
-                       if i == vararg_rank then
-                               var ne = args[i]
-                               if ne isa AVarargExpr then
-                                       var e = self.expr(ne.n_expr)
-                                       if e == null then return null
-                                       res.add(e)
-                                       continue
-                               end
-                               var vararg = new Array[Instance]
-                               for j in [vararg_rank..vararg_rank+vararg_len] do
-                                       var e = self.expr(args[j])
-                                       if e == null then return null
-                                       vararg.add(e)
-                               end
-                               var elttype = msignature.mparameters[vararg_rank].mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType))
-                               res.add(self.array_instance(vararg, elttype))
-                       else
-                               var j = i
-                               if i > vararg_rank then j += vararg_len
-                               var e = self.expr(args[j])
-                               if e == null then return null
-                               res.add(e)
+                       var param = msignature.mparameters[i]
+                       var j = map.map.get_or_null(i)
+                       if j == null then
+                               continue
+                       end
+                       if param.is_vararg and map.vararg_decl > 0 then
+                               var vararg = exprs.sub(j, map.vararg_decl)
+                               var elttype = param.mtype.anchor_to(self.mainmodule, recv.mtype.as(MClassType))
+                               var arg = self.array_instance(vararg, elttype)
+                               res.add(arg)
+                               continue
                        end
+                       res.add exprs[j]
                end
                return res
        end
@@ -1740,7 +1746,7 @@ redef class ASendExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return null
-               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
                if args == null then return null
 
                var res = v.callsite(callsite, args)
@@ -1753,7 +1759,7 @@ redef class ASendReassignFormExpr
        do
                var recv = v.expr(self.n_expr)
                if recv == null then return
-               var args = v.varargize(callsite.mpropdef, recv, self.raw_arguments)
+               var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.raw_arguments)
                if args == null then return
                var value = v.expr(self.n_value)
                if value == null then return
@@ -1777,29 +1783,35 @@ redef class ASuperExpr
 
                var callsite = self.callsite
                if callsite != null then
-                       var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
-                       if args == null then return null
-                       # Add additional arguments for the super init call
-                       if args.length == 1 then
+                       var args
+                       if self.n_args.n_exprs.is_empty then
+                               # Add automatic arguments for the super init call
+                               args = [recv]
                                for i in [0..callsite.msignature.arity[ do
                                        args.add(v.frame.arguments[i+1])
                                end
+                       else
+                               args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
+                               if args == null then return null
                        end
+
                        # Super init call
                        var res = v.callsite(callsite, args)
                        return res
                end
 
-               # standard call-next-method
+               # Standard call-next-method
                var mpropdef = self.mpropdef
                mpropdef = mpropdef.lookup_next_definition(v.mainmodule, recv.mtype)
 
-               var args = v.varargize(mpropdef, recv, self.n_args.n_exprs)
-               if args == null then return null
-
-               if args.length == 1 then
+               var args
+               if self.n_args.n_exprs.is_empty then
                        args = v.frame.arguments
+               else
+                       args = v.varargize(mpropdef, signaturemap, recv, self.n_args.n_exprs)
+                       if args == null then return null
                end
+
                var res = v.call(mpropdef, args)
                return res
        end
@@ -1814,7 +1826,7 @@ redef class ANewExpr
                var callsite = self.callsite
                if callsite == null then return recv
 
-               var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
+               var args = v.varargize(callsite.mpropdef, callsite.signaturemap, recv, self.n_args.n_exprs)
                if args == null then return null
                var res2 = v.callsite(callsite, args)
                if res2 != null then
@@ -1876,6 +1888,13 @@ redef class AIssetAttrExpr
        end
 end
 
+redef class AVarargExpr
+       redef fun expr(v)
+       do
+               return v.expr(self.n_expr)
+       end
+end
+
 redef class ADebugTypeExpr
        redef fun stmt(v)
        do
index 9cc9580..c0d3890 100644 (file)
@@ -790,11 +790,17 @@ redef class AMethPropdef
                        name = amethodid.collect_text
                        name_node = amethodid
 
-                       if name == "+" and self.n_signature.n_params.length == 0 then
+                       var arity = self.n_signature.n_params.length
+                       if name == "+" and arity == 0 then
                                name = "unary +"
-                       end
-                       if name == "-" and self.n_signature.n_params.length == 0 then
+                       else if name == "-" and arity == 0 then
                                name = "unary -"
+                       else
+                               if amethodid.is_binary and arity != 1 then
+                                       modelbuilder.error(self.n_signature, "Syntax Error: binary operator `{name}` requires exactly one parameter; got {arity}.")
+                               else if amethodid.min_arity > arity then
+                                       modelbuilder.error(self.n_signature, "Syntax Error: `{name}` requires at least {amethodid.min_arity} parameter(s); got {arity}.")
+                               end
                        end
                end
 
@@ -868,6 +874,9 @@ redef class AMethPropdef
                        end
                end
 
+               var accept_special_last_parameter = self.n_methid == null or self.n_methid.accept_special_last_parameter
+               var return_is_mandatory = self.n_methid != null and self.n_methid.return_is_mandatory
+
                # Retrieve info from the signature AST
                var param_names = new Array[String] # Names of parameters from the AST
                var param_types = new Array[MType] # Types of parameters from the AST
@@ -941,6 +950,14 @@ redef class AMethPropdef
                # In `new`-factories, the return type is by default the classtype.
                if ret_type == null and mpropdef.mproperty.is_new then ret_type = mclassdef.mclass.mclass_type
 
+               # Special checks for operator methods
+               if not accept_special_last_parameter and mparameters.not_empty and mparameters.last.is_vararg then
+                       modelbuilder.error(self.n_signature.n_params.last, "Error: illegal variadic parameter `{mparameters.last}` for `{mpropdef.mproperty.name}`.")
+               end
+               if ret_type == null and return_is_mandatory then
+                       modelbuilder.error(self.n_methid, "Error: mandatory return type for `{mpropdef.mproperty.name}`.")
+               end
+
                msignature = new MSignature(mparameters, ret_type)
                mpropdef.msignature = msignature
                mpropdef.is_abstract = self.get_single_annotation("abstract", modelbuilder) != null
@@ -1022,6 +1039,56 @@ redef class AMethPropdef
        end
 end
 
+redef class AMethid
+       # Is a return required?
+       #
+       # * True for operators and brackets.
+       # * False for id and assignment.
+       fun return_is_mandatory: Bool do return true
+
+       # Can the last parameter be special like a vararg?
+       #
+       # * False for operators: the last one is in fact the only one.
+       # * False for assignments: it is the right part of the assignment.
+       # * True for ids and brackets.
+       fun accept_special_last_parameter: Bool do return false
+
+       # The minimum required number of parameters.
+       #
+       # * 1 for binary operators
+       # * 1 for brackets
+       # * 1 for assignments
+       # * 2 for bracket assignments
+       # * 0 for ids
+       fun min_arity: Int do return 1
+
+       # Is the `self` a binary operator?
+       fun is_binary: Bool do return true
+end
+
+redef class AIdMethid
+       redef fun return_is_mandatory do return false
+       redef fun accept_special_last_parameter do return true
+       redef fun min_arity do return 0
+       redef fun is_binary do return false
+end
+
+redef class ABraMethid
+       redef fun accept_special_last_parameter do return true
+       redef fun is_binary do return false
+end
+
+redef class ABraassignMethid
+       redef fun return_is_mandatory do return false
+       redef fun min_arity do return 2
+       redef fun is_binary do return false
+end
+
+redef class AAssignMethid
+       redef fun return_is_mandatory do return false
+       redef fun is_binary do return false
+end
+
 redef class AAttrPropdef
        redef type MPROPDEF: MAttributeDef
 
index 7ef06e0..8fe169d 100644 (file)
@@ -398,47 +398,58 @@ private class TypeVisitor
        # Visit the expressions of args and check their conformity with the corresponding type in signature
        # The point of this method is to handle varargs correctly
        # Note: The signature must be correctly adapted
-       fun check_signature(node: ANode, args: Array[AExpr], mproperty: MProperty, msignature: MSignature): Bool
+       fun check_signature(node: ANode, args: Array[AExpr], mproperty: MProperty, msignature: MSignature): nullable SignatureMap
        do
                var vararg_rank = msignature.vararg_rank
                if vararg_rank >= 0 then
                        if args.length < msignature.arity then
                                modelbuilder.error(node, "Error: expected at least {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
-                               return false
+                               return null
                        end
                else if args.length != msignature.arity then
                        modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
-                       return false
+                       return null
                end
 
                #debug("CALL {unsafe_type}.{msignature}")
 
+               # Associate each parameter to a position in the arguments
+               var map = new SignatureMap
+
                var vararg_decl = args.length - msignature.arity
+               var j = 0
                for i in [0..msignature.arity[ do
-                       var j = i
-                       if i == vararg_rank then continue # skip the vararg
-                       if i > vararg_rank then
-                               j = i + vararg_decl
+                       var param = msignature.mparameters[i]
+                       var arg = args[j]
+                       map.map[i] = j
+                       j += 1
+
+                       if i == vararg_rank then
+                               j += vararg_decl
+                               continue # skip the vararg
                        end
-                       var paramtype = msignature.mparameters[i].mtype
-                       self.visit_expr_subtype(args[j], paramtype)
+
+                       var paramtype = param.mtype
+                       self.visit_expr_subtype(arg, paramtype)
                end
                if vararg_rank >= 0 then
                        var paramtype = msignature.mparameters[vararg_rank].mtype
                        var first = args[vararg_rank]
                        if vararg_decl == 0 and first isa AVarargExpr then
                                var mclass = get_mclass(node, "Array")
-                               if mclass == null then return false # Forward error
+                               if mclass == null then return null # Forward error
                                var array_mtype = mclass.get_mtype([paramtype])
                                self.visit_expr_subtype(first.n_expr, array_mtype)
                                first.mtype  = first.n_expr.mtype
                        else
-                               for j in [vararg_rank..vararg_rank+vararg_decl] do
-                                       self.visit_expr_subtype(args[j], paramtype)
+                               map.vararg_decl = vararg_decl + 1
+                               for i in [vararg_rank..vararg_rank+vararg_decl] do
+                                       self.visit_expr_subtype(args[i], paramtype)
                                end
                        end
                end
-               return true
+
+               return map
        end
 
        fun error(node: ANode, message: String)
@@ -508,6 +519,20 @@ private class TypeVisitor
        end
 end
 
+# Mapping between parameters and arguments in a call.
+#
+# Parameters and arguments are not stored in the class but referenced by their position (starting from 0)
+#
+# The point of this class is to help engine and other things to map arguments in the AST to parameters of the model.
+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.
 class CallSite
        # The associated node for location
@@ -540,9 +565,15 @@ class CallSite
        # Is a implicit cast required on erasure typing policy?
        var erasure_cast: Bool
 
+       # The mapping used on the call to associate arguments to parameters
+       # If null then no specific association is required.
+       var signaturemap: nullable SignatureMap = null
+
        private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
        do
-               return v.check_signature(self.node, args, self.mproperty, self.msignature)
+               var map = v.check_signature(self.node, args, self.mproperty, self.msignature)
+               signaturemap = map
+               return map == null
        end
 end
 
@@ -1737,7 +1768,7 @@ redef class ASuperExpr
                msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
                var args = self.n_args.to_a
                if args.length > 0 then
-                       v.check_signature(self, args, mproperty, msignature)
+                       signaturemap = v.check_signature(self, args, mproperty, msignature)
                end
                self.mtype = msignature.return_mtype
                self.is_typed = true
@@ -1745,6 +1776,10 @@ redef class ASuperExpr
                mpropdef = v.mpropdef.as(MMethodDef)
        end
 
+       # The mapping used on the call to associate arguments to parameters.
+       # If null then no specific association is required.
+       var signaturemap: nullable SignatureMap
+
        private fun process_superinit(v: TypeVisitor)
        do
                var anchor = v.anchor
diff --git a/tests/error_operators.nit b/tests/error_operators.nit
new file mode 100644 (file)
index 0000000..db94029
--- /dev/null
@@ -0,0 +1,91 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# no return
+class A
+       fun + do abort
+       fun +(a: A) do abort
+       fun - do abort
+       fun -(a: A) do abort
+       fun *(a: A) do abort
+       fun /(a: A) do abort
+       fun %(a: A) do abort
+       fun <(a: A) do abort
+       fun >(a: A) do abort
+       fun <=(a: A) do abort
+       fun >=(a: A) do abort
+       fun <=>(a: A) do abort
+       fun <<(a: A) do abort
+       fun >>(a: A) do abort
+       fun foo=(a: A) do abort # should be fine
+       fun [](a: A) do abort
+       fun []=(a, b: A) do abort # should be fine
+end
+
+# not enough parameters
+class B
+       fun +: A do abort # should be fine
+       fun -: A do abort # should be fine
+       fun *: A do abort
+       fun /: A do abort
+       fun %: A do abort
+       fun <: A do abort
+       fun >: A do abort
+       fun <=: A do abort
+       fun >=: A do abort
+       fun <=>: A do abort
+       fun <<: A do abort
+       fun >>: A do abort
+       fun foo= do abort
+       fun []: A do abort
+       fun []=(a: A) do abort
+end
+
+# too much parameters
+class C
+       fun +(a,b,c:A): A do abort
+       fun -(a,b,c:A): A do abort
+       fun *(a,b,c:A): A do abort
+       fun /(a,b,c:A): A do abort
+       fun %(a,b,c:A): A do abort
+       fun <(a,b,c:A): A do abort
+       fun >(a,b,c:A): A do abort
+       fun <=(a,b,c:A): A do abort
+       fun >=(a,b,c:A): A do abort
+       fun <=>(a,b,c:A): A do abort
+       fun <<(a,b,c:A): A do abort
+       fun >>(a,b,c:A): A do abort
+       fun foo=(a,b,c:A) do abort # should be fine
+       fun [](a,b,c:A): A do abort # should be fine
+       fun []=(a,b,c:A) do abort # should be fine
+end
+
+# bad vararg
+class D
+       fun +(a:A...): A do abort
+       fun -(a:A...): A do abort
+       fun *(a:A...): A do abort
+       fun /(a:A...): A do abort
+       fun %(a:A...): A do abort
+       fun <(a:A...): A do abort
+       fun >(a:A...): A do abort
+       fun <=(a:A...): A do abort
+       fun >=(a:A...): A do abort
+       fun <=>(a:A...): A do abort
+       fun <<(a:A...): A do abort
+       fun >>(a:A...): A do abort
+       fun foo=(a,b,c:A, d:A...) do abort
+       fun [](a,b,c:A, d:A...): A do abort # should be fine
+       fun []=(a,b,c:A, d:A...) do abort
+end
diff --git a/tests/sav/error_operators.res b/tests/sav/error_operators.res
new file mode 100644 (file)
index 0000000..1949e18
--- /dev/null
@@ -0,0 +1,54 @@
+error_operators.nit:17,6: Error: mandatory return type for `unary +`.
+error_operators.nit:18,6: Error: mandatory return type for `+`.
+error_operators.nit:19,6: Error: mandatory return type for `unary -`.
+error_operators.nit:20,6: Error: mandatory return type for `-`.
+error_operators.nit:21,6: Error: mandatory return type for `*`.
+error_operators.nit:22,6: Error: mandatory return type for `/`.
+error_operators.nit:23,6: Error: mandatory return type for `%`.
+error_operators.nit:24,6: Error: mandatory return type for `<`.
+error_operators.nit:25,6: Error: mandatory return type for `>`.
+error_operators.nit:26,6--7: Error: mandatory return type for `<=`.
+error_operators.nit:27,6--7: Error: mandatory return type for `>=`.
+error_operators.nit:28,6--8: Error: mandatory return type for `<=>`.
+error_operators.nit:29,6--7: Error: mandatory return type for `<<`.
+error_operators.nit:30,6--7: Error: mandatory return type for `>>`.
+error_operators.nit:32,6--7: Error: mandatory return type for `[]`.
+error_operators.nit:40,9: Syntax Error: binary operator `*` requires exactly one parameter; got 0.
+error_operators.nit:41,9: Syntax Error: binary operator `/` requires exactly one parameter; got 0.
+error_operators.nit:42,9: Syntax Error: binary operator `%` requires exactly one parameter; got 0.
+error_operators.nit:43,9: Syntax Error: binary operator `<` requires exactly one parameter; got 0.
+error_operators.nit:44,9: Syntax Error: binary operator `>` requires exactly one parameter; got 0.
+error_operators.nit:45,10: Syntax Error: binary operator `<=` requires exactly one parameter; got 0.
+error_operators.nit:46,10: Syntax Error: binary operator `>=` requires exactly one parameter; got 0.
+error_operators.nit:47,11: Syntax Error: binary operator `<=>` requires exactly one parameter; got 0.
+error_operators.nit:48,10: Syntax Error: binary operator `<<` requires exactly one parameter; got 0.
+error_operators.nit:49,10: Syntax Error: binary operator `>>` requires exactly one parameter; got 0.
+error_operators.nit:50,14: Syntax Error: `foo=` requires at least 1 parameter(s); got 0.
+error_operators.nit:51,10: Syntax Error: `[]` requires at least 1 parameter(s); got 0.
+error_operators.nit:52,9--14: Syntax Error: `[]=` requires at least 2 parameter(s); got 1.
+error_operators.nit:57,7--18: Syntax Error: binary operator `+` requires exactly one parameter; got 3.
+error_operators.nit:58,7--18: Syntax Error: binary operator `-` requires exactly one parameter; got 3.
+error_operators.nit:59,7--18: Syntax Error: binary operator `*` requires exactly one parameter; got 3.
+error_operators.nit:60,7--18: Syntax Error: binary operator `/` requires exactly one parameter; got 3.
+error_operators.nit:61,7--18: Syntax Error: binary operator `%` requires exactly one parameter; got 3.
+error_operators.nit:62,7--18: Syntax Error: binary operator `<` requires exactly one parameter; got 3.
+error_operators.nit:63,7--18: Syntax Error: binary operator `>` requires exactly one parameter; got 3.
+error_operators.nit:64,8--19: Syntax Error: binary operator `<=` requires exactly one parameter; got 3.
+error_operators.nit:65,8--19: Syntax Error: binary operator `>=` requires exactly one parameter; got 3.
+error_operators.nit:66,9--20: Syntax Error: binary operator `<=>` requires exactly one parameter; got 3.
+error_operators.nit:67,8--19: Syntax Error: binary operator `<<` requires exactly one parameter; got 3.
+error_operators.nit:68,8--19: Syntax Error: binary operator `>>` requires exactly one parameter; got 3.
+error_operators.nit:76,8--13: Error: illegal variadic parameter `a: A...` for `+`.
+error_operators.nit:77,8--13: Error: illegal variadic parameter `a: A...` for `-`.
+error_operators.nit:78,8--13: Error: illegal variadic parameter `a: A...` for `*`.
+error_operators.nit:79,8--13: Error: illegal variadic parameter `a: A...` for `/`.
+error_operators.nit:80,8--13: Error: illegal variadic parameter `a: A...` for `%`.
+error_operators.nit:81,8--13: Error: illegal variadic parameter `a: A...` for `<`.
+error_operators.nit:82,8--13: Error: illegal variadic parameter `a: A...` for `>`.
+error_operators.nit:83,9--14: Error: illegal variadic parameter `a: A...` for `<=`.
+error_operators.nit:84,9--14: Error: illegal variadic parameter `a: A...` for `>=`.
+error_operators.nit:85,10--15: Error: illegal variadic parameter `a: A...` for `<=>`.
+error_operators.nit:86,9--14: Error: illegal variadic parameter `a: A...` for `<<`.
+error_operators.nit:87,9--14: Error: illegal variadic parameter `a: A...` for `>>`.
+error_operators.nit:88,20--25: Error: illegal variadic parameter `d: A...` for `foo=`.
+error_operators.nit:90,19--24: Error: illegal variadic parameter `d: A...` for `[]=`.
index e80f5de..893e1ea 100644 (file)
@@ -20,6 +20,8 @@ false
 false
 true
 true
+32
+8
 52
 456
 123
index 5789941..43e3636 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:911)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:960)
 NativeString
 N
 Nit
index 271589e..5261b5e 100644 (file)
@@ -102,14 +102,16 @@ class A
                return A_value( recv ) <= A_value( other );
        `}
 
-       fun >>( other : A ) import value, value=, A `{
+       fun >>( other : A ): A import value, value=, A `{
                int new_val = A_value( recv ) >> A_value( other );
                A_value__assign( recv, new_val );
+               return recv;
        `}
 
-       fun <<( other : A ) import value, A `{
+       fun <<( other : A ): A import value, A `{
                int new_val = A_value( recv ) << A_value( other );
                A_value__assign( recv, new_val );
+               return recv;
        `}
 
        fun []( index : Int ) : A import A `{
@@ -154,13 +156,13 @@ print new A( 1 ) >= new A( 100 ) # false
 print new A( 100 ) >= new A( 100 ) # true
 print new A( 100 ) >= new A( 1 ) # true
 
-#var x = new A( 1 )
-#x << new A( 5 )
-#print x # 16
+var x = new A( 1 )
+x = x << new A( 5 )
+print x # 32
 
-#var y = new A( 32 )
-#y >> new A( 2 )
-#print y # 8
+var y = new A( 32 )
+y = y >> new A( 2 )
+print y # 8
 
 var a = new A( 456 )
 print a[ 52 ] # 52