lib/standard: Introduce Byte type in kernel
[nit.git] / lib / standard / kernel.nit
index 6d2e4c6..c596bb3 100644 (file)
@@ -5,7 +5,7 @@
 #
 # This file is free software, which comes along with NIT.  This software is
 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A 
+# without  even  the implied warranty of  MERCHANTABILITY or  FITNESS FOR A
 # PARTICULAR PURPOSE.  You can modify it is you want,  provided this header
 # is kept unaltered, and a notification of the changes is added.
 # You  are  allowed  to  redistribute it and sell it, alone or is a part of
@@ -17,10 +17,6 @@ module kernel
 
 import end # Mark this module is a top level one. (must be only one)
 
-`{
-#include <errno.h>
-`}
-
 ###############################################################################
 # System Classes                                                              #
 ###############################################################################
@@ -66,13 +62,13 @@ interface Object
        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.
+       #
+       # The exact meaning of "same value" is left to the subclasses.
        # 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?
-       ##
+       #
        # != is equivalent with "not ==".
        fun !=(other: nullable Object): Bool do return not (self == other)
 
@@ -89,11 +85,11 @@ interface Object
        # Display class name on stdout (debug only).
        # This method MUST not be used by programs, it is here for debugging
        # only and can be removed without any notice
-       fun output_class_name is intern 
+       fun output_class_name 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
@@ -111,9 +107,7 @@ class Sys
        fun run do main
 
        # Number of the last error
-       fun errno: Int is extern `{
-               return errno;
-       `}
+       fun errno: Int is extern "sys_errno"
 end
 
 # Quit the program with a specific return code
@@ -134,7 +128,7 @@ interface Comparable
        type OTHER: Comparable
 
        # Is `self` lesser than `other`?
-       fun <(other: OTHER): Bool is abstract 
+       fun <(other: OTHER): Bool is abstract
 
        # not `other` < `self`
        # Note, the implementation must ensure that: `(x<=y) == (x<y or x==y)`
@@ -226,6 +220,25 @@ interface Discrete
        end
 end
 
+# Something that can be cloned
+#
+# This interface introduces the `clone` method used to duplicate an instance
+# Its specific semantic is left to the subclasses.
+interface Cloneable
+       # Duplicate `self`
+       #
+       # The specific semantic of this method is left to the subclasses;
+       # Especially, if (and how) attributes are cloned (depth vs. shallow).
+       #
+       # As a rule of thumb, the principle of least astonishment should
+       # be used to guide the semantic.
+       #
+       # Note that as the returned clone depends on the semantic,
+       # the `==` method, if redefined, should ensure the equality
+       # between an object and its clone.
+       fun clone: SELF is abstract
+end
+
 # A numeric value supporting mathematical operations
 interface Numeric
        super Comparable
@@ -262,6 +275,12 @@ interface Numeric
        #     assert 5.to_f         != 5 # Float and Int are not equals
        fun to_f: Float is abstract
 
+       # The byte equivalent of `self`
+       #
+       #     assert (-1).to_b == 0xFF.to_b
+       #     assert (1.9).to_b == 1.to_b
+       fun to_b: Byte is abstract
+
        # Is this the value of zero in its domain?
        fun is_zero: Bool do return self == zero
 
@@ -283,8 +302,10 @@ end
 
 # Native Booleans.
 # `true` and `false` are the only instances.
+#
 # Boolean are manipulated trough three special operators:
-#       `and`, `or`, `not`.
+# `and`, `or`, `not`.
+#
 # Booleans are mainly used by conditional statement and loops.
 universal Bool
        redef fun object_id is intern
@@ -316,10 +337,10 @@ universal Float
        redef fun !=(i) is intern
        redef fun output 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 <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
 
        redef fun +(i) is intern
        redef fun - is intern
@@ -329,6 +350,7 @@ universal Float
 
        redef fun to_i is intern
        redef fun to_f do return self
+       redef fun to_b is intern
 
        redef fun zero do return 0.0
        redef fun value_of(val) do return val.to_f
@@ -353,6 +375,125 @@ universal Float
                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 bytes.
+# Same as a C `unsigned char`
+universal Byte
+       super Discrete
+       super Numeric
+
+       redef type OTHER: Byte
+
+       redef fun successor(i) do return self + i.to_b
+       redef fun predecessor(i) do return self - i.to_b
+
+       redef fun object_id is intern
+       redef fun hash do return self.to_i
+       redef fun ==(i) is intern
+       redef fun !=(i) is intern
+       redef fun output is intern
+
+       redef fun <=(i) is intern
+       redef fun <(i) is intern
+       redef fun >=(i) is intern
+       redef fun >(i) is intern
+       redef fun +(i) is intern
+
+       # On an Byte, unary minus will return `(256 - self) % 256`
+       #
+       #     assert -(1.to_b) == 0xFF.to_b
+       #     assert -(0.to_b) == 0x00.to_b
+       redef fun - is intern
+       redef fun -(i) is intern
+       redef fun *(i) is intern
+       redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Finds the remainder of division of `self` by `i`.
+       #
+       #     assert 5.to_b % 2.to_b            == 1.to_b
+       #     assert 10.to_b % 2.to_b           == 0.to_b
+       fun %(i: Byte): Byte is intern
+
+       redef fun zero do return 0.to_b
+       redef fun value_of(val) do return val.to_b
+
+       # `i` bits shift fo the left (aka <<)
+       #
+       #     assert 5.to_b.lshift(1)    == 10.to_b
+       fun lshift(i: Int): Byte is intern
+
+       # alias of `lshift`
+       fun <<(i: Int): Byte do return lshift(i)
+
+       # `i` bits shift fo the right (aka >>)
+       #
+       #     assert 5.to_b.rshift(1)    == 2.to_b
+       fun rshift(i: Int): Byte is intern
+
+       # alias of `rshift`
+       fun >>(i: Int): Byte do return rshift(i)
+
+       redef fun to_i is intern
+       redef fun to_f is intern
+       redef fun to_b do return self
+
+       redef fun distance(i) do return (self - i).to_i
+
+       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
+
        redef fun max(other)
        do
                if self < other then
@@ -399,6 +540,13 @@ universal Int
        redef fun -(i) is intern
        redef fun *(i) is intern
        redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Finds the remainder of division of `self` by `i`.
+       #
+       #     assert 5 % 2                      == 1
+       #     assert 10 % 2                     == 0
        fun %(i: Int): Int is intern
 
        redef fun zero do return 0
@@ -409,13 +557,20 @@ universal Int
        #     assert 5.lshift(1)    == 10
        fun lshift(i: Int): Int is intern
 
+       # alias of `lshift`
+       fun <<(i: Int): Int do return lshift(i)
+
        # `i` bits shift fo the right (aka >>)
        #
        #     assert 5.rshift(1)    == 2
        fun rshift(i: Int): Int is intern
 
+       # alias of `rshift`
+       fun >>(i: Int): Int do return rshift(i)
+
        redef fun to_i do return self
        redef fun to_f is intern
+       redef fun to_b is intern
 
        redef fun distance(i)
        do
@@ -440,9 +595,9 @@ universal Int
 
        redef fun is_between(c, d)
        do
-               if self < c or d < self then 
+               if self < c or d < self then
                        return false
-               else 
+               else
                        return true
                end
        end
@@ -467,8 +622,8 @@ universal Int
 
        # The character whose ASCII value is `self`.
        #
-       #      assert 65.ascii   == 'A'
-       #      assert 10.ascii   == '\n'
+       #     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)
@@ -493,7 +648,7 @@ universal Int
                # count digits
                while n > 0 do
                        d += 1
-                       n = n / b       # euclidian division /
+                       n = n / b       # euclidian division /
                end
                return d
        end
@@ -675,6 +830,22 @@ universal Char
        do
                return is_lower or is_upper
        end
+
+       # Is self a whitespace character?
+       #
+       # These correspond to the "Other" and "Separator" groups of the Unicode.
+       #
+       # In the ASCII encoding, this is those <= to space (0x20) plus delete (0x7F).
+       #
+       #     assert 'A'.is_whitespace  == false
+       #     assert ','.is_whitespace  == false
+       #     assert ' '.is_whitespace  == true
+       #     assert '\t'.is_whitespace == true
+       fun is_whitespace: Bool
+       do
+               var i = ascii
+               return i <= 0x20 or i == 0x7F
+       end
 end
 
 # Pointer classes are used to manipulate extern C structures.
@@ -683,5 +854,5 @@ extern class Pointer
        fun address_is_null: Bool is extern "address_is_null"
 
        # Free the memory pointed by this pointer
-       fun free `{ free(recv); `}
+       fun free is extern "free"
 end