lib: rename `standard` as `core`
[nit.git] / lib / core / error.nit
diff --git a/lib/core/error.nit b/lib/core/error.nit
new file mode 100644 (file)
index 0000000..b1e96e2
--- /dev/null
@@ -0,0 +1,91 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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
+# 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
+# another product.
+
+# Standard error-management infrastructure.
+#
+module error
+
+import text
+
+# Standard class for error messages
+class Error
+       # A short human-readable error message.
+       #
+       # This message is short and informative and could be displayed on the console, a dialog-box
+       # or written in a log file.
+       #
+       # Message should be explicative, autonomous and do not depend on contextual information.
+       #
+       # Eg. instead of "Fatal error: cannot open file",
+       # something like "File error, cannot open /some/path/document.ext, file not found." is preferred,
+       # where the message is informative as it, and the severity of the error is not assumed:
+       # while fatal for the library, it could be something benign for the program.
+       var message: String
+
+       # An original error that caused the creation of this error, if any.
+       #
+       # This is used to chain errors and track the implication of various sub-systems for a given error.
+       #
+       # When displaying an error the end user, causes can be recursively displayed.
+       var cause: nullable Error = null is writable
+
+       redef fun to_s do return message
+end
+
+# Helper class used as a return value of methods that may give errors instead of values.
+#
+# Functions that return useful values or errors could use it to simulate an easy-to use multiple-return.
+#
+# ~~~
+# fun division(a,b: Int): MaybeError[Int, Error]
+# do
+#   if b == 0 then return new MaybeError[Int, Error](null, new Error("Arithmetic Error: try to divide {a} by 0"))
+#   return new MaybeError[Int, Error](a / b, null)
+# end
+#
+# assert division(10, 2).is_error  == false
+# assert division(10, 0).is_error  == true
+# ~~~
+#
+# Clients has to handle the error:
+#
+# ~~~
+# var res = division(10, 2)
+# if res.is_error then
+#   print res.error
+#   exit 1
+# end
+# print res.value
+# assert res.value == 5
+# ~~~
+class MaybeError[V, E: Error]
+       # The value, if any
+       var maybe_value: nullable V
+
+       # The error, if any
+       var maybe_error: nullable E
+
+       # It there an error?
+       fun is_error: Bool do return maybe_error != null
+
+       # The value
+       # REQUIRE: `not is_error`
+       fun value: V do return maybe_value.as(V)
+
+       # The require
+       # REQUIRE: `is_error`
+       fun error: E do return maybe_error.as(E)
+
+       redef fun to_s do
+               var e = maybe_error
+               if e != null then return e.to_s
+               return value.to_s
+       end
+end