Merge: Improve documentation of kernel
authorJean Privat <jean@pryen.org>
Sat, 25 Jul 2015 01:17:47 +0000 (21:17 -0400)
committerJean Privat <jean@pryen.org>
Sat, 25 Jul 2015 01:17:47 +0000 (21:17 -0400)
Improve the documentation of Object and Sys.
Also experiments with the new nitdoc features #1447

Some issues I discovered while writing and using the doc while thinking about nitdoc.

* micro-picking classes and methods to include in the README is not fun
* headings (`###`) in the markdown might not have the right level in the generated HTML
* having reified property groups (#1413) should help to organize thing and have automatic feedback on it trough the doc
* maybe the `[[list:]]` directive should no list entities not already included by `[[doc:]]` (or a new `[[list_other:]]` directive?)
* having a way to generate a full linear and strucuted documentation in a single page could simplify the job of the writer when checking the doc.

Pull-Request: #1584
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

1  2 
lib/standard/kernel.nit
tests/sav/error_class_glob.res

diff --combined lib/standard/kernel.nit
  # You  are  allowed  to  redistribute it and sell it, alone or is a part of
  # another product.
  
- # Most minimal classes and methods.
- # This module is the root of the standard module hierarchy.
+ # Most basic classes and methods.
+ #
+ # This module is the root of the module hierarchy.
+ # It provides a very minimal set of classes and services used as a
+ # foundation to define other classes and methods.
  module kernel
  
  import end # Mark this module is a top level one. (must be only one)
@@@ -27,9 -30,13 +30,13 @@@ in "C" `
  ###############################################################################
  
  # The root of the class hierarchy.
- # Each class implicitly specialize Object.
  #
- # Currently, Object is also used to collect all top-level methods.
+ # Each other class implicitly specializes Object,
+ # therefore the services of Object are inherited by every other class and are usable
+ # on each value, including primitive types like integers (`Int`), strings (`String`) and arrays (`Array`).
+ #
+ # Note that `nullable Object`, not `Object`, is the root of the type hierarchy
+ # since the special value `null` is not considered as an instance of Object.
  interface Object
        # Type of this instance, automatically specialized in every class
        #
        # `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.
+       # An internal hash code for the object based on its identity.
+       #
+       # Unless specific code, you should not use this method but
+       # use `hash` instead.
+       #
+       # As its name hints it, the internal hash code, is used internally
+       # to provide a hash value.
+       # It is also used by the `inspect` method to loosely identify objects
+       # and helps debugging.
+       #
+       # ~~~
+       # var a = "Hello"
+       # var b = a
+       # assert a.object_id == b.object_id
+       # ~~~
+       #
+       # The specific details of the internal hash code it let to the specific
+       # engine. The rules are the following:
+       #
+       # * The `object_id` MUST be invariant for the whole life of the object.
+       # * Two living instances of the same classes SHOULD NOT share the same `object_id`.
+       # * Two instances of different classes MIGHT share the same `object_id`.
+       # * The `object_id` of a garbage-collected instance MIGHT be reused by new instances.
+       # * The `object_id` of an object MIGHT be non constant across different executions.
+       #
+       # For instance, the `nitc` compiler uses the address of the object in memory
+       # as its `object_id`.
+       #
+       # TODO rename in something like `internal_hash_code`
        fun object_id: Int is intern
  
        # Return true if `self` and `other` have the same dynamic type.
-       # Unless specific code, you should not use this method.
+       #
+       # ~~~
+       # assert 1.is_same_type(2)
+       # assert "Hello".is_same_type("World")
+       # assert not "Hello".is_same_type(2)
+       # ~~~
+       #
+       # The method returns false if the dynamic type of `other` is a subtype of the dynamic type of `self`
+       # (or the other way around).
+       #
+       # Unless specific code, you should not use this method because it is inconsistent
+       # with the fact that a subclass can be used in lieu of a superclass.
        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.
+       # Return true if `self` and `other` are the same instance (i.e. same identity).
+       #
+       # ~~~
+       # var a = new Buffer
+       # var b = a
+       # var c = new Buffer
+       # assert a.is_same_instance(b)
+       # assert not a.is_same_instance(c)
+       # assert a == c # because both buffers are empty
+       # ~~~
+       #
+       # Obviously, the identity of an object is preserved even if the object is mutated.
+       #
+       # ~~~
+       # var x = [1]
+       # var y = x
+       # x.add 2
+       # assert x.is_same_instance(y)
+       # ~~~
+       #
+       # Unless specific code, you should use `==` instead of `is_same_instance` because
+       # most of the time is it the semantic (and user-defined) comparison that make sense.
+       #
+       # Moreover, relying on `is_same_instance` on objects you do not control
+       # might have unexpected effects when libraries reuse objects or intern them.
        fun is_same_instance(other: nullable Object): Bool is intern
  
        # Have `self` and `other` the same value?
        #
-       # The exact meaning of "same value" is left to the subclasses.
-       # Implicitly, the default implementation, is `is_same_instance`
+       # ~~~
+       # assert 1 + 1 == 2
+       # assert not 1 == "1"
+       # assert 1.to_s == "1"
+       # ~~~
+       #
+       # The exact meaning of *same value* is left to the subclasses.
+       # Implicitly, the default implementation, is `is_same_instance`.
+       #
+       # The laws of `==` are the following:
+       #
+       # * reflexivity `a.is_same_instance(b) implies a == b`
+       # * symmetry: `(a == b) == (b == a)`
+       # * transitivity: `(a == b) and (b == c) implies (a == c)`
+       #
+       # `==` might not be constant on some objects overtime because of their evolution.
+       #
+       # ~~~
+       # var a = [1]
+       # var b = [1]
+       # var c = [1,2]
+       # assert a == b and not a == c
+       # a.add 2
+       # assert not a == b and a == c
+       # ~~~
+       #
+       # Lastly, `==` is highly linked with `hash` and a specific redefinition of `==` should
+       # usually be associated with a specific redefinition of `hash`.
+       #
+       # ENSURE `result implies self.hash == other.hash`
        fun ==(other: nullable Object): Bool do return self.is_same_instance(other)
  
        # Have `self` and `other` different values?
        #
-       # != is equivalent with "not ==".
+       # `!=` is equivalent with `not ==`.
        fun !=(other: nullable Object): Bool do return not (self == other)
  
        # Display self 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
+       # only and can be removed without any notice.
+       #
+       # TODO: rename to avoid blocking a good identifier like `output`.
        fun output
        do
                '<'.output
        end
  
        # 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
+       # only and can be removed without any notice.
+       #
+       # TODO: rename to avoid blocking a good identifier like `output`.
        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.
+       # The hash code is used in many data-structures and algorithms to identify objects that might be equal.
+       # Therefore, the precise semantic of `hash` is highly linked with the semantic of `==`
+       # and the only law of `hash` is that `a == b implies a.hash == b.hash`.
+       #
+       # ~~~
+       # assert (1+1).hash == 2.hash
+       # assert 1.to_s.hash == "1".hash
+       # ~~~
+       #
+       # `hash` (like `==`) might not be constant on some objects over time because of their evolution.
+       #
+       # ~~~
+       # var a = [1]
+       # var b = [1]
+       # var c = [1,2]
+       # assert a.hash == b.hash
+       # a.add 2
+       # assert a.hash == c.hash
+       # # There is a very high probability that `b.hash != c.hash`
+       # ~~~
+       #
+       # A specific redefinition of `==` should usually be associated with a specific redefinition of `hash`.
+       # Note that, unfortunately, a correct definition of `hash` that is lawful with `==` is sometime tricky
+       # and a cause of bugs.
+       #
+       # Without redefinition, `hash` is based on the `object_id` of the instance.
        fun hash: Int do return object_id / 8
  end
  
  # The main class of the program.
- # `Sys` is a singleton class, its only instance is `sys` defined in `Object`.
- # `sys` is used to invoke methods on the program on the system.
+ #
+ # `Sys` is a singleton class, its only instance is accessible from everywhere with `sys`.
+ #
+ # Because of this, methods that should be accessible from everywhere, like `print` or `exit`,
+ # are defined in `Sys`.
+ # Moreover, unless there is an ambiguity with `self`, the receiver of a call to these methods is implicitly `sys`.
+ # Basically it means that the two following instructions are equivalent.
+ #
+ # ~~~nit
+ # print "Hello World"
+ # sys.print "Hello World"
+ # ~~~
+ #
+ # ## Methods Implicitly Defined in Sys
+ #
+ # `Sys` is the class where are defined top-level methods,
+ # i.e. those defined outside of any class like in a procedural language.
+ # Basically it means that
+ #
+ # ~~~nitish
+ # redef class Sys
+ #    fun foo do print "hello"
+ # end
+ # ~~~
+ #
+ # is equivalent with
+ #
+ # ~~~nitish
+ # fun foo print "hello"
+ # ~~~
+ #
+ # As a corollary, in a top-level method, `self` (the current receiver) is always `sys`.
  class Sys
-       # Instructions outside classes implicitly redefine this method.
+       # The main method of a program.
+       #
+       # In a module, the instructions defined outside any classes or methods
+       # (usually called the *main* of the module) is
+       # an implicit definition of this `main` method.
+       # Basically it means that the following program
+       #
+       # ~~~nit
+       # print "Hello World"
+       # ~~~
+       #
+       # is equivalent with
+       #
+       # ~~~nit
+       # redef class Sys
+       #    redef fun main do
+       #       print "Hello World"
+       #    end
+       # end
+       # ~~~
        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
+       #
+       # When a program starts, the following implicit sequence of instructions is executed
+       #
+       # ~~~nitish
+       # sys = new Sys
+       # sys.run
+       # ~~~
+       #
+       # Whereas the job of the `run` method is just to execute `main`.
+       #
+       # The only reason of the existence of `run` is to allow modules to refine it
        # and inject specific work before or after the main part.
        fun run do main
  
@@@ -719,23 -903,10 +903,23 @@@ universal Cha
        redef type OTHER: Char
  
        redef fun object_id is intern
 +      redef fun output `{
 +              if(self < 128){
 +                      printf("%c", self);
 +              }else if(self < 2048){
 +                      printf("%c%c", 0xC0 | ((0x7C0 & self) >> 6), 0x80 | (0x3F & self));
 +              }else if(self < 65536){
 +                      printf("%c%c%c", 0xE0 | ((0xF000 & self) >> 12), 0x80 | ((0xFC0 & self) >> 6) ,0x80 | (0x3F & self));
 +              }else if(self < 2097152){
 +                      printf("%c%c%c%c", 0xF0 | ((0x1C0000 & self) >> 18), 0x80 | ((0x3F000 & self) >> 12), 0x80 | ((0xFC0 & self) >> 6), 0x80 | (0x3F & self));
 +              }else{
 +                      // Bad char
 +                      printf("%c", self);
 +              }
 +      `}
        redef fun hash do return ascii
        redef fun ==(o) is intern
        redef fun !=(o) is intern
 -      redef fun output is intern
  
        redef fun <=(i) is intern
        redef fun <(i) is intern
@@@ -1,12 -1,12 +1,12 @@@
- ../lib/standard/kernel.nit:29,1--100,3: Error: `kernel#Object` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:102,1--116,3: Error: `kernel#Sys` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:129,1--187,3: Error: `kernel#Comparable` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:189,1--226,3: Error: `kernel#Discrete` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:228,1--245,3: Error: `kernel#Cloneable` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:247,1--302,3: Error: `kernel#Numeric` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:308,1--331,3: Error: `kernel#Bool` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:333,1--415,3: Error: `kernel#Float` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:417,1--519,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:521,1--712,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:714,1--867,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
- ../lib/standard/kernel.nit:869,1--876,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:32,1--225,3: Error: `kernel#Object` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:227,1--300,3: Error: `kernel#Sys` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:313,1--371,3: Error: `kernel#Comparable` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:373,1--410,3: Error: `kernel#Discrete` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:412,1--429,3: Error: `kernel#Cloneable` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:431,1--486,3: Error: `kernel#Numeric` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:492,1--515,3: Error: `kernel#Bool` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:517,1--599,3: Error: `kernel#Float` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:601,1--703,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+ ../lib/standard/kernel.nit:705,1--896,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
 -../lib/standard/kernel.nit:898,1--1038,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
 -../lib/standard/kernel.nit:1040,1--1047,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
++../lib/standard/kernel.nit:898,1--1051,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
++../lib/standard/kernel.nit:1053,1--1060,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?