Merge: SELF type
authorJean Privat <jean@pryen.org>
Tue, 25 Nov 2014 01:04:13 +0000 (20:04 -0500)
committerJean Privat <jean@pryen.org>
Tue, 25 Nov 2014 01:04:13 +0000 (20:04 -0500)
If Object defines a virtual type SELF, redefines it automatically in all subclasses. Also checks for some conditions on the declaration of SELF: it must be public, it must not be fixed and it must be declared on Object (or not declared at all). These conditions ensures that its refinements are valid.

The error messages when trying to redefining SELF could be improved. Maybe adding a special case preventing any redef of SELF?

Pull-Request: #902
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Etienne M. Gagnon <egagnon@j-meg.com>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

1  2 
lib/java/java.nit
lib/standard/kernel.nit
tests/sav/nitg-e/fixme/base_gen_reassign_alt4.res
tests/sav/nitg-e/fixme/base_gen_reassign_alt5.res
tests/sav/nitg-e/fixme/base_gen_reassign_alt6.res

diff --combined lib/java/java.nit
@@@ -27,7 -27,7 +27,7 @@@
  # most of JNI functions. You can use it to further customize the behavior
  # of your code.
  module java is
 -      c_compiler_option("-I $(JAVA_HOME)/include/")
 +      c_compiler_option "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
        c_linker_option("-L $(JNI_LIB_PATH) -ljvm")
        new_annotation extra_java_files
  end
@@@ -98,8 -98,6 +98,6 @@@ en
  extern class JavaString in "Java" `{ java.lang.String `}
        super JavaObject
  
-       redef type SELF: JavaString
        # Get the string from Java and copy it to Nit memory
        fun to_cstring: NativeString import sys, Sys.jni_env `{
                Sys sys = JavaString_sys(recv);
@@@ -140,7 -138,6 +138,6 @@@ redef class Tex
  end
  
  redef extern class JavaObject
-       type SELF: JavaObject
  
        # Returns a global reference to the Java object behind this reference
        #
diff --combined lib/standard/kernel.nit
@@@ -30,6 -30,28 +30,28 @@@ import end # Mark this module is a top 
  #
  # Currently, Object is also used to collect all top-level methods.
  interface Object
+       # Type of this instance, automatically specialized in every class
+       #
+       # A common use case of the virtual type `SELF` is to type an attribute and
+       # store another instance of the same type as `self`. It can also be used as as
+       # return type to a method producing a copy of `self` or returning an instance
+       # expected to be the exact same type as self.
+       #
+       # This virtual type must be used with caution as it can hinder specialization.
+       # In fact, it imposes strict restrictions on all sub-classes and their usage.
+       # For example, using `SELF` as a return type of a method `foo`
+       # forces all subclasses to ensure that `foo` returns the correct and updated
+       # type.
+       # A dangerous usage take the form of a method typed by `SELF` which creates
+       # and returns a new instance.
+       # If not correctly specialized, this method would break when invoked on a
+       # sub-class.
+       #
+       # A general rule for safe usage of `SELF` is to ensure that inputs typed
+       # `SELF` are stored in attributes typed `SELF` and returned by methods typed
+       # `SELF`, pretty much the same things as you would do with parameter types.
+       type SELF: Object
        # The unique object identifier in the class.
        # Unless specific code, you should not use this method.
        # The identifier is used internally to provide a hash value.
@@@ -331,21 -353,6 +353,21 @@@ universal Floa
                end
        end
  
 +      # Compare float numbers with a given precision.
 +      #
 +      # Because of the loss of precision in floating numbers,
 +      # the `==` method is often not the best way to compare them.
 +      #
 +      # ~~~
 +      # assert 0.01.is_approx(0.02, 0.1)   == true
 +      # assert 0.01.is_approx(0.02, 0.001) == false
 +      # ~~~
 +      fun is_approx(other, precision: Float): Bool
 +      do
 +              assert precision >= 0.0
 +              return self <= other + precision and self >= other - precision
 +      end
 +
        redef fun max(other)
        do
                if self < other then
@@@ -1,4 -1,4 +1,4 @@@
- Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:389)
 -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:396)
++Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:411)
  11
  21
  31
@@@ -1,4 -1,4 +1,4 @@@
- Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:389)
 -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:396)
++Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:411)
  11
  21
  31
@@@ -1,4 -1,4 +1,4 @@@
- Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:389)
 -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:396)
++Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:411)
  11
  21
  31