1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
11 # Automatic derivable implementation of standard basic methods.
13 # This module introduce `Derivable` as the main interface to implement (or auto-implement) and
14 # provides additional mixin-interfaces with specific default behavior of standard basic methods based
15 # on the services of this interface.
17 # The name *deriving* is inspired from the deriving mechanism of Haskell.
19 # This module also introduce a new annotation `auto_derive`. See `Derivable` for details.
21 new_annotation auto_derive
24 # Interface of objects that expose some kind of internal representation in a very unreliable way.
26 # The point of this interface is to allow objects to give a basic representation of
27 # themselves within a simple key-value dictionary.
28 # The specific semantic of each key and value is let unspecified.
30 # Moreover the class annotation `auto_derive` will automatically implements the
31 # interface with the attributes locally defined in the class.
37 # var a_string: String
40 # var a = new A(5, "five")
41 # var map = a.derive_to_map
42 # assert map.length == 2
43 # assert map["an_int"] == 5
44 # assert map["a_string"] == "five"
47 # Returns a map that loosely represents the object `self`.
49 # Warning: by default the method returns an empty Map.
50 # It is done this way so that subclasses can just call `super` and add their own attributes.
52 # Forgetting to redefine `derive_to_map` will broke the expectation of the user of the class
53 # Since an empty map is not POLA.
55 # Note that the semantic of keys and values is let unspecified.
56 # Moreover, there is no specification nor mechanism to avoid key collision.
57 fun derive_to_map
: Map[String, nullable Object]
59 return new HashMap[String, nullable Object]
63 # Implementation of `to_s` for `Derivable` objects.
65 # The implementation uses `to_s` for each value of `attributes_to_map`.
72 # var a_string: String
75 # var a = new A(5, "five")
76 # assert a.to_s == "an_int:5; a_string:five"
79 # Warning: the method may go in an infinite recursion if there is a circuit in
80 # the implementation of `to_s`.
83 redef fun to_s
do return derive_to_map
.join
("; ", ":")
86 # Implementation of `==` and `hash` for `Derivable` objects.
88 # The implementations just call `==` and `hash` on `derive_to_map`.
95 # var a_string: String
98 # var a = new A(5, "five")
99 # var b = new A(5, "five")
100 # var c = new A(6, "six")
102 # assert a.hash == b.hash
106 # Warning: the method may go in an infinite recursion if there is a circuit in
107 # the implementation of `==` or `hash`.
108 interface DeriveEqual
110 redef fun ==(other
) do
111 if not other
isa Derivable then return false
112 return derive_to_map
== other
.derive_to_map
115 return derive_to_map
.hash