Merge: Derive all the things
authorJean Privat <jean@pryen.org>
Wed, 18 Mar 2015 05:41:23 +0000 (12:41 +0700)
committerJean Privat <jean@pryen.org>
Wed, 18 Mar 2015 05:41:23 +0000 (12:41 +0700)
This PR is crazy and inspired by https://github.com/privat/nit/pull/1202#discussion_r26359435
Basically, you will find here some hackish user-level pseudo meta-programming with optional unsafe support from the execution engines trough injection of code in the AST.

The idea is a generalization (and a basic simplification) of the approach or @xymus for serialization.
If fact, there is 2 level of generalizations.

In the compiler, a new phase `deriving` offers a static deriving mechanism. For instance, the annotation `auto_inspect` will implements the `inspect` method with a simple recursive inspection of attributes.

In the standard library, a new module `deriving` offers a general mechanism with a new standard `derive_to_map` method that is expected to dump attributes in a simple HashMap.

This basic low-level method is used to provide user-defined deriving methods.
For instance, the module provide basic derived implementation of `==`, `to_s` and `hash` in pure Nit at the user-level.

Moreover, the compiler phase `deriving` is extended to provide `auto_derive` that statically implements `derive_to_map`

Here an example from the code:

~~~nit
class A
   auto_derive
   super DeriveToS
   var an_int: Int
   var a_string: String
end

var a = new A(5, "five")
assert a.to_s == "an_int:5; a_string:five"
~~~

Pull-Request: #1204
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

1  2 
lib/standard/collection/abstract_collection.nit

@@@ -203,7 -203,7 +203,7 @@@ en
  #
  # Used to pass arguments by reference.
  #
 -# Also used when one want to give asingle element when a full
 +# Also used when one want to give a single element when a full
  # collection is expected
  class Container[E]
        super Collection[E]
@@@ -497,6 -497,25 +497,25 @@@ interface MapRead[K, V
                end
                return true
        end
+       # A hashcode based on the hashcode of the keys and the values.
+       #
+       # ~~~
+       # var a = new HashMap[String, Int]
+       # var b = new ArrayMap[Object, Numeric]
+       # a["one"] = 1
+       # b["one"] = 1
+       # assert a.hash == b.hash
+       # ~~~
+       redef fun hash
+       do
+               var res = length
+               for k, v in self do
+                       if k != null then res += k.hash * 7
+                       if v != null then res += v.hash * 11
+               end
+               return res
+       end
  end
  
  # Maps are associative collections: `key` -> `item`.