lib: add Float::is_approx to compare floats
[nit.git] / lib / standard / kernel.nit
index ac3d5b6..2f2df4b 100644 (file)
 
 # Most minimal classes and methods.
 # This module is the root of the standard module hierarchy.
-package kernel
+module kernel
 
 import end # Mark this module is a top level one. (must be only one)
 
+`{
+#include <errno.h>
+`}
+
 ###############################################################################
 # System Classes                                                              #
 ###############################################################################
@@ -35,11 +39,15 @@ interface Object
        # Unless specific code, you should not use this method.
        fun is_same_type(other: Object): Bool is intern
 
+       # Return true if `self` and `other` are the same instance.
+       # Unless specific code, you should use `==` instead.
+       fun is_same_instance(other: nullable Object): Bool is intern
+
        # Have `self` and `other` the same value?
        ##
        # The exact meaning of "same value" is let to the subclasses.
-       # Implicitly, the default implementation, is `is`
-       fun ==(other: nullable Object): Bool do return self is other
+       # Implicitly, the default implementation, is `is_same_instance`
+       fun ==(other: nullable Object): Bool do return self.is_same_instance(other)
 
        # Have `self` and `other` different values?
        ##
@@ -61,11 +69,11 @@ interface Object
        # only and can be removed without any notice
        fun output_class_name is intern 
 
-       # Quit the program with a specific return code
-       protected fun exit(exit_value: Int) is intern
-
-       # Return the global sys object, the only instance of the `Sys` class.
-       protected fun sys: Sys is intern
+       # The hash code of the object.
+       # Assuming that a == b -> a.hash == b.hash
+       ##
+       # Without redefinition, it is based on the `object_id` of the instance.
+       fun hash: Int do return object_id / 8
 end
 
 # The main class of the program.
@@ -74,8 +82,25 @@ end
 class Sys
        # Instructions outside classes implicitly redefine this method.
        fun main do end
+
+       # The entry point for the execution of the whole program.
+       # Its job is to call `main` but some modules may want to refine it
+       # and inject specific work before or after the main part.
+       fun run do main
+
+       # Number of the last error
+       fun errno: Int is extern `{
+               return errno;
+       `}
 end
 
+# Quit the program with a specific return code
+fun exit(exit_value: Int) is intern
+
+# Return the global sys object, the only instance of the `Sys` class.
+fun sys: Sys is intern
+
+
 ###############################################################################
 # Abstract Classes                                                            #
 ###############################################################################
@@ -147,16 +172,10 @@ interface Discrete
        redef type OTHER: Discrete
 
        # The next element.
-       fun succ: OTHER do return self + 1
+       fun successor(i: Int): OTHER is abstract
 
        # The previous element.
-       fun prec: OTHER do return self - 1
-
-       # The `i`-th successor element.
-       fun +(i: Int): OTHER is abstract
-
-       # The `i`-th previous element.
-       fun -(i: Int): OTHER is abstract
+       fun predecessor(i: Int): OTHER is abstract
 
        # The distance between self and d.
        #
@@ -178,13 +197,64 @@ interface Discrete
 
                var nb = 0
                while cursor < stop do
-                       cursor = cursor.succ
+                       cursor = cursor.successor(1)
                        nb += 1
                end
                return nb
        end
 end
 
+# A numeric value supporting mathematical operations
+interface Numeric
+       super Comparable
+
+       redef type OTHER: Numeric
+
+       # Addition of `self` with `i`
+       fun +(i: OTHER): OTHER is abstract
+
+       # Substraction of `i` from `self`
+       fun -(i: OTHER): OTHER is abstract
+
+       # Inverse of `self`
+       fun -: OTHER is abstract
+
+       # Multiplication of `self` with `i`
+       fun *(i: OTHER): OTHER is abstract
+
+       # Division of `self` with `i`
+       fun /(i: OTHER): OTHER is abstract
+
+       # The integer part of `self`.
+       #
+       #     assert (0.0).to_i      == 0
+       #     assert (0.9).to_i      == 0
+       #     assert (-0.9).to_i     == 0
+       #     assert (9.9).to_i      == 9
+       #     assert (-9.9).to_i     == -9
+       fun to_i: Int is abstract
+
+       # The float equivalent of `self`
+       #
+       #     assert 5.to_f         == 5.0
+       #     assert 5.to_f         != 5 # Float and Int are not equals
+       fun to_f: Float is abstract
+
+       # Is this the value of zero in its domain?
+       fun is_zero: Bool do return self == zero
+
+       # The value of zero in the domain of `self`
+       fun zero: OTHER is abstract
+
+       # The value of `val` in the domain of `self`
+       #
+       #     assert 1.0.value_of(2) == 2.0
+       #     assert 1.0.value_of(2.0) == 2.0
+       #     assert 1.value_of(2) == 2
+       #     assert 1.value_of(2.0) == 2
+       fun value_of(val: Numeric): OTHER is abstract
+end
+
 ###############################################################################
 # Native classes                                                              #
 ###############################################################################
@@ -199,35 +269,115 @@ universal Bool
        redef fun ==(b) is intern
        redef fun !=(b) is intern
        redef fun output is intern
+       redef fun hash do return to_i
+
+       # 1 if true and 0 if false
+       fun to_i: Int
+       do
+               if self then
+                       return 1
+               else
+                       return 0
+               end
+       end
 end
 
 # Native floating point numbers.
 # Corresponds to C float.
 universal Float
+       super Numeric
+
+       redef type OTHER: Float
+
        redef fun object_id is intern
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
        redef fun output is intern
 
-       fun <=(i: Float): Bool is intern
-       fun <(i: Float): Bool is intern
-       fun >=(i: Float): Bool is intern
-       fun >(i: Float): Bool is intern
-       fun +(i: Float): Float is intern
-       fun -: Float is intern
-       fun -(i: Float): Float is intern
-       fun *(i: Float): Float is intern
-       fun /(i: Float): Float is intern
-       
-       # The integer part of `self`.
-       fun to_i: Int is intern
+       redef fun <=(i): Bool is intern
+       redef fun <(i): Bool is intern
+       redef fun >=(i): Bool is intern
+       redef fun >(i): Bool is intern
+
+       redef fun +(i) is intern
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       redef fun to_i is intern
+       redef fun to_f do return self
+
+       redef fun zero do return 0.0
+       redef fun value_of(val) do return val.to_f
+
+       redef fun <=>(other)
+       do
+               if self < other then
+                       return -1
+               else if other < self then
+                       return 1
+               else
+                       return 0
+               end
+       end
+
+       redef fun is_between(c, d)
+       do
+               if self < c or d < self then
+                       return false
+               else
+                       return true
+               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
+                       return other
+               else
+                       return self
+               end
+       end
+
+       redef fun min(c)
+       do
+               if c < self then
+                       return c
+               else
+                       return self
+               end
+       end
 end
 
 # Native integer numbers.
 # Correspond to C int.
 universal Int
        super Discrete
+       super Numeric
+
        redef type OTHER: Int
 
+       redef fun successor(i) do return self + i
+       redef fun predecessor(i) do return self - i
+
        redef fun object_id is intern
+       redef fun hash do return self
        redef fun ==(i) is intern
        redef fun !=(i) is intern
        redef fun output is intern
@@ -237,19 +387,29 @@ universal Int
        redef fun >=(i) is intern
        redef fun >(i) is intern
        redef fun +(i) is intern
-       fun -: Int is intern
+
+       redef fun - is intern
        redef fun -(i) is intern
-       fun *(i: Int): Int is intern
-       fun /(i: Int): Int is intern
-       fun %(i: Int): Int is intern   
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+       fun %(i: Int): Int is intern
+
+       redef fun zero do return 0
+       redef fun value_of(val) do return val.to_i
+
+       # `i` bits shift fo the left (aka <<)
+       #
+       #     assert 5.lshift(1)    == 10
        fun lshift(i: Int): Int is intern
-       fun rshift(i: Int): Int is intern   
 
-       # The float equivalent of `self`
-       fun to_f: Float is intern
+       # `i` bits shift fo the right (aka >>)
+       #
+       #     assert 5.rshift(1)    == 2
+       fun rshift(i: Int): Int is intern
+
+       redef fun to_i do return self
+       redef fun to_f is intern
 
-       redef fun succ is intern
-       redef fun prec is intern
        redef fun distance(i)
        do
                var d = self - i
@@ -259,7 +419,7 @@ universal Int
                        return -d
                end
        end
-       
+
        redef fun <=>(other)
        do
                if self < other then
@@ -299,9 +459,15 @@ universal Int
        end
 
        # The character whose ASCII value is `self`.
+       #
+       #      assert 65.ascii   == 'A'
+       #      assert 10.ascii   == '\n'
        fun ascii: Char is intern
 
        # Number of digits of an integer in base `b` (plus one if negative)
+       #
+       #     assert 123.digit_count(10) == 3
+       #     assert 123.digit_count(2) == 7 # 1111011 in binary
        fun digit_count(b: Int): Int
        do
                if b == 10 then return digit_count_base_10
@@ -349,7 +515,9 @@ universal Int
 
        # Return the corresponding digit character
        # If 0 <= `self` <= 9, return the corresponding character.
+       #     assert 5.to_c    == '5'
        # If 10 <= `self` <= 36, return the corresponding letter [a..z].
+       #     assert 15.to_c   == 'f'
        fun to_c: Char
        do
                assert self >= 0 and self <= 36 # TODO plan for this
@@ -360,29 +528,11 @@ universal Int
                end
        end
 
-       # Execute 'each' for each integer in [self..last]
-       fun enumerate_to(last: Int)
-               !each(i: Int)
-       do
-               var cur = self
-               while cur <= last do
-                       each(cur)
-                       cur += 1
-               end
-       end
-
-       # Execute 'each' for each integer in [self..after[
-       fun enumerate_before(after: Int)
-               !each(i: Int)
-       do
-               var cur = self
-               while cur < after do
-                       each(cur)
-                       cur += 1
-               end
-       end
-
        # The absolute value of self
+       #
+       #     assert (-10).abs   == 10
+       #     assert 10.abs    == 10
+       #     assert 0.abs     == 0
        fun abs: Int
        do
            if self >= 0
@@ -402,6 +552,7 @@ universal Char
        redef type OTHER: Char
 
        redef fun object_id is intern
+       redef fun hash do return ascii
        redef fun ==(o) is intern
        redef fun !=(o) is intern
        redef fun output is intern
@@ -411,8 +562,8 @@ universal Char
        redef fun >=(i) is intern
        redef fun >(i) is intern
 
-       redef fun succ is intern
-       redef fun prec is intern
+       redef fun successor(i) is intern
+       redef fun predecessor(i) is intern
 
        redef fun distance(c)
        do
@@ -425,6 +576,8 @@ universal Char
        end
 
        # If `self` is a digit then return this digit else return -1.
+       #
+       #     assert '5'.to_i    == 5
        fun to_i: Int
        do
 
@@ -433,18 +586,22 @@ universal Char
                else if is_digit then
                        return self.ascii - '0'.ascii
                else
-                       return self.to_lower.ascii - ('a'.ascii + 10)
+                       return self.to_lower.ascii - 'a'.ascii + 10
                end
        end
 
        # the ascii value of self
+       #
+       #     assert 'a'.ascii    == 97
+       #     assert '\n'.ascii   == 10
        fun ascii: Int is intern
 
-       redef fun +(i) is intern
-       redef fun -(i) is intern
-
        # Return the lower case version of self.
        # If self is not a letter, then return self
+       #
+       #     assert 'A'.to_lower  == 'a'
+       #     assert 'a'.to_lower  == 'a'
+       #     assert '$'.to_lower  == '$'
        fun to_lower: Char
        do
                if is_upper then
@@ -456,6 +613,10 @@ universal Char
 
        # Return the upper case version of self.
        # If self is not a letter, then return self
+       #
+       #     assert 'a'.to_upper  == 'A'
+       #     assert 'A'.to_upper  == 'A'
+       #     assert '$'.to_upper  == '$'
        fun to_upper: Char
        do
                if is_lower then
@@ -464,26 +625,45 @@ universal Char
                        return self
                end
        end
-       
+
        # Is self a digit? (from '0' to '9')
+       #
+       #     assert '0'.is_digit   == true
+       #     assert '9'.is_digit   == true
+       #     assert 'a'.is_digit   == false
        fun is_digit : Bool
        do
                return self >= '0' and self <= '9'
        end
-       
+
        # Is self a lower case letter? (from 'a' to 'z')
+       #
+       #     assert 'a'.is_lower   == true
+       #     assert 'z'.is_lower   == true
+       #     assert 'A'.is_lower   == false
+       #     assert '$'.is_lower   == false
        fun is_lower : Bool
        do
                return self >= 'a' and self <= 'z'
        end
-       
+
        # Is self a upper case letter? (from 'A' to 'Z')
+       #
+       #     assert 'A'.is_upper   == true
+       #     assert 'A'.is_upper   == true
+       #     assert 'z'.is_upper   == false
+       #     assert '$'.is_upper   == false
        fun is_upper : Bool
        do
                return self >= 'A' and self <= 'Z'
        end
-       
+
        # Is self a letter? (from 'A' to 'Z' and 'a' to 'z')
+       #
+       #     assert 'A'.is_letter  == true
+       #     assert 'A'.is_letter  == true
+       #     assert 'z'.is_letter  == true
+       #     assert '$'.is_letter  == false
        fun is_letter : Bool
        do
                return is_lower or is_upper
@@ -491,5 +671,10 @@ universal Char
 end
 
 # Pointer classes are used to manipulate extern C structures.
-extern Pointer
+extern class Pointer
+       # Is the address behind this Object at NULL?
+       fun address_is_null: Bool is extern "address_is_null"
+
+       # Free the memory pointed by this pointer
+       fun free `{ free(recv); `}
 end