summaryrefslogtreecommitdiff
path: root/tiger-compiler/lib/misc/error.hh
blob: cd0cc3a20b58a30bf4c30c932d7f0ff7c0bc7c8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
 ** \file misc/error.hh
 ** \brief Declare error.
 */

#pragma once

#include <iosfwd>
#include <sstream>

/// Shortcuts.
/// \{
#define ice_here() ice(__FILE__, __LINE__)
#define ice_on_error_here() ice_on_error(__FILE__, __LINE__)
/// \}

#ifndef TC_NORETURN
#  ifdef SWIG
#    define TC_NORETURN
#  else
#    define TC_NORETURN [[noreturn]]
#  endif
#endif

namespace misc
{
  /** \brief Handle errors in the whole project.
   **
   ** Each task has an error status depending on its exit code
   ** described in the enum below.
   **
   ** Several versions of operator<< are used to fill the handler.
   **
   ** A global variable is defined to centralize all the error uses.
   */

  class error
  {
  public:
    error();
    error(const error& e);

    /// Copy an error.
    error& operator=(const error& e);

    /// \name Filling the error handler.
    /// \{

    /// With what exit status should we end?
    enum class error_type : unsigned
    {
      /// Job successfully done.
      success = 0,
      /// Some unspecified error happened.
      failure = 1,
      /// Lexical error.
      scan = 2,
      /// Syntactic error.
      parse = 3,
      /// Binding error: undefined name.
      bind = 4,
      /// Type checking error.
      type = 5
    };

    /// General method: put the parameter in stream_.
    template <typename T> error& operator<<(const T& t);

    /// Set the status if \a e is lower than the current status.
    error& operator<<(error_type e);

    /// Accept std::endl etc.
    error& operator<<(std::ostream& (*f)(std::ostream&));

    /// Import errors.
    error& operator<<(const error& rhs);

    /// Member manipulator signature.
    using member_manip_type = void (error::*)();
    /// Const member manipulator signature.
    using const_member_manip_type = void (error::*)() const;

    /// Hook for member manipulators.
    error& operator<<(member_manip_type f);
    /// Hooks for const member manipulators.
    error& operator<<(const_member_manip_type f);

    /// \}

    /// \name Member manipulators.
    /// \{

    /// Throw an exception to exit.
    TC_NORETURN void exit() const;

    /// If the error status is set, throw an exception to exit.
    void exit_on_error() const;

    /// Throw an Internal Compiler Error.
    void ice(const char* file, int line) const;

    /// If the error status is set, consider that an Internal Compiler
    /// Error has happened and abort.
    void ice_on_error(const char* file, int line) const;

    /// Reset to no error.
    void clear();

    /// \}

    /// \name Accessors.
    /// \{

    /// True if an error is recorded.
    operator bool() const;

    /// Get the current status.
    error_type status_get() const;

    /// Get the current status value.
    unsigned status_get_value() const;

    /// Get the stream associated with the class.
    const std::ostringstream& stream_get() const;

    /// \}

  private:
    /// The current exit status.
    error_type status_;

    /// The current error message.
    std::ostringstream stream_;
  };

  /// Display the error message on the given ostream.
  std::ostream& operator<<(std::ostream& o, const error& e);

} // namespace misc

#include <misc/error.hxx>