nitg-s: fix call to super in primitive types and add test
authorAlexis Laferrière <alexis.laf@xymus.net>
Mon, 20 Jan 2014 23:13:08 +0000 (18:13 -0500)
committerAlexis Laferrière <alexis.laf@xymus.net>
Wed, 22 Jan 2014 21:15:58 +0000 (16:15 -0500)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

src/abstract_compiler.nit
src/separate_compiler.nit
tests/sav/test_linex_int.res [new file with mode: 0644]
tests/test_linex_int.nit [new file with mode: 0644]

index 6467c57..dc364ad 100644 (file)
@@ -677,6 +677,14 @@ abstract class AbstractCompilerVisitor
                return self.call(propdef, t, args)
        end
 
+       # Generate a monomorphic super send from the method `m`, the type `t` and the arguments `args`
+       fun monomorphic_super_send(m: MMethodDef, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+       do
+               assert t isa MClassType
+               m = m.lookup_next_definition(self.compiler.mainmodule, t)
+               return self.call(m, t, args)
+       end
+
        # Attributes handling
 
        # Generate a polymorphic attribute is_set test
index c80749a..ada994e 100644 (file)
@@ -974,11 +974,7 @@ class SeparateCompilerVisitor
        redef fun send(mmethod, arguments)
        do
                self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
-               return table_send(mmethod, arguments, mmethod.const_color)
-       end
 
-       private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
-       do
                if arguments.first.mcasttype.ctype != "val*" then
                        # In order to shortcut the primitive, we need to find the most specific method
                        # Howverr, because of performance (no flattening), we always work on the realmainmodule
@@ -989,6 +985,11 @@ class SeparateCompilerVisitor
                        return res
                end
 
+               return table_send(mmethod, arguments, mmethod.const_color)
+       end
+
+       private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
+       do
                var res: nullable RuntimeVariable
                var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true)
                var ret = msignature.return_mtype
@@ -1128,6 +1129,15 @@ class SeparateCompilerVisitor
 
        redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
+               if arguments.first.mcasttype.ctype != "val*" then
+                       # In order to shortcut the primitive, we need to find the most specific method
+                       # However, because of performance (no flattening), we always work on the realmainmodule
+                       var main = self.compiler.mainmodule
+                       self.compiler.mainmodule = self.compiler.realmainmodule
+                       var res = self.monomorphic_super_send(m, recvtype, arguments)
+                       self.compiler.mainmodule = main
+                       return res
+               end
                return table_send(m.mproperty, arguments, m.const_color)
        end
 
diff --git a/tests/sav/test_linex_int.res b/tests/sav/test_linex_int.res
new file mode 100644 (file)
index 0000000..63893fa
--- /dev/null
@@ -0,0 +1,3 @@
+Int < 123
+Int
+Object
diff --git a/tests/test_linex_int.nit b/tests/test_linex_int.nit
new file mode 100644 (file)
index 0000000..44be897
--- /dev/null
@@ -0,0 +1,22 @@
+redef class Object
+       fun foo do print "Object"
+end
+
+redef enum Int
+       redef fun to_s
+       do
+               var s = "Int"
+               return "{s} < {super}"
+       end
+       redef fun foo
+       do
+               print "Int"
+               super
+       end
+end
+
+# call local::to_s and then standard::to_s
+print 123.to_s
+
+# call Int::foo and then Object::foo
+123.foo