nit: Added link to `CONTRIBUTING.md` from the README
[nit.git] / lib / core / error.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
9 # another product.
10
11 # Standard error-management infrastructure.
12 #
13 module error
14
15 import text
16
17 # Standard class for error messages
18 class Error
19 # A short human-readable error message.
20 #
21 # This message is short and informative and could be displayed on the console, a dialog-box
22 # or written in a log file.
23 #
24 # Message should be explicative, autonomous and do not depend on contextual information.
25 #
26 # Eg. instead of "Fatal error: cannot open file",
27 # something like "File error, cannot open /some/path/document.ext, file not found." is preferred,
28 # where the message is informative as it, and the severity of the error is not assumed:
29 # while fatal for the library, it could be something benign for the program.
30 var message: String
31
32 # An original error that caused the creation of this error, if any.
33 #
34 # This is used to chain errors and track the implication of various sub-systems for a given error.
35 #
36 # When displaying an error the end user, causes can be recursively displayed.
37 var cause: nullable Error = null is writable
38
39 redef fun to_s do return message
40 end
41
42 # Helper class used as a return value of methods that may give errors instead of values.
43 #
44 # Functions that return useful values or errors could use it to simulate an easy-to use multiple-return.
45 #
46 # ~~~
47 # fun division(a,b: Int): MaybeError[Int, Error]
48 # do
49 # if b == 0 then return new MaybeError[Int, Error](null, new Error("Arithmetic Error: try to divide {a} by 0"))
50 # return new MaybeError[Int, Error](a / b, null)
51 # end
52 #
53 # assert division(10, 2).is_error == false
54 # assert division(10, 0).is_error == true
55 # ~~~
56 #
57 # Clients has to handle the error:
58 #
59 # ~~~
60 # var res = division(10, 2)
61 # if res.is_error then
62 # print res.error
63 # exit 1
64 # end
65 # print res.value
66 # assert res.value == 5
67 # ~~~
68 class MaybeError[V, E: Error]
69 # The value, if any
70 var maybe_value: nullable V
71
72 # The error, if any
73 var maybe_error: nullable E
74
75 # It there an error?
76 fun is_error: Bool do return maybe_error != null
77
78 # The value
79 # REQUIRE: `not is_error`
80 fun value: V do return maybe_value.as(V)
81
82 # The error
83 # REQUIRE: `is_error`
84 fun error: E do return maybe_error.as(E)
85
86 redef fun to_s do
87 var e = maybe_error
88 if e != null then return e.to_s
89 return value.to_s
90 end
91 end