• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ES2PANDA_LEXER_TOKEN_NUMBER_H
17 #define ES2PANDA_LEXER_TOKEN_NUMBER_H
18 
19 #include "macros.h"
20 #include "util/ustring.h"
21 #include "util/enumbitops.h"
22 
23 #include <cstdint>
24 #include <type_traits>
25 #include <utility>
26 
27 namespace panda::es2panda::lexer {
28 enum class NumberFlags : uint32_t {
29     NONE,
30     BIGINT = 1U << 0U,
31     DECIMAL_POINT = 1U << 1U,
32     EXPONENT = 1U << 2U,
33     ERROR = 1U << 3U,
34 };
35 
36 DEFINE_BITOPS(NumberFlags)
37 
38 // NOLINTBEGIN(readability-identifier-naming)
39 // NOLINTBEGIN(fuchsia-multiple-inheritance)
40 template <class... Ts>
41 struct overloaded : Ts... {
42     using Ts::operator()...;
43 };
44 
45 template <class... Ts>
46 overloaded(Ts...) -> overloaded<Ts...>;
47 // NOLINTEND(fuchsia-multiple-inheritance)
48 
49 template <typename>
50 inline constexpr bool dependent_false_v = false;
51 // NOLINTEND(readability-identifier-naming)
52 
53 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
54 class Number {
55 public:
56     // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
Number()57     explicit Number() noexcept : num_(static_cast<int32_t>(0)) {};
Number(util::StringView str)58     explicit Number(util::StringView str) noexcept : str_(str) {}
59     // NOLINTNEXTLINE(bugprone-exception-escape)
60     explicit Number(util::StringView str, const std::string &utf8, NumberFlags flags) noexcept;
Number(util::StringView str,double num)61     explicit Number(util::StringView str, double num) noexcept : str_(str), num_(num) {}
Number(uint32_t num)62     explicit Number(uint32_t num) noexcept : Number(static_cast<int32_t>(num)) {}
Number(int32_t num)63     explicit Number(int32_t num) noexcept : num_(num) {}
Number(uint64_t num)64     explicit Number(uint64_t num) noexcept : Number(static_cast<int64_t>(num)) {}
Number(int64_t num)65     explicit Number(int64_t num) noexcept : num_(num) {}
Number(float num)66     explicit Number(float num) noexcept : num_(num) {}
Number(double num)67     explicit Number(double num) noexcept : num_(num) {}
68     DEFAULT_COPY_SEMANTIC(Number);
69     DEFAULT_MOVE_SEMANTIC(Number);
70     ~Number() = default;
71     // NOLINTEND(cppcoreguidelines-pro-type-member-init)
72 
IsInt()73     bool IsInt() const noexcept
74     {
75         return std::holds_alternative<int32_t>(num_);
76     }
77 
IsLong()78     bool IsLong() const noexcept
79     {
80         return std::holds_alternative<int64_t>(num_);
81     }
82 
IsInteger()83     bool IsInteger() const noexcept
84     {
85         return IsInt() || IsLong();
86     }
87 
IsFloat()88     bool IsFloat() const noexcept
89     {
90         return std::holds_alternative<float>(num_);
91     }
92 
IsDouble()93     bool IsDouble() const noexcept
94     {
95         return std::holds_alternative<double>(num_);
96     }
97 
IsReal()98     bool IsReal() const noexcept
99     {
100         return IsFloat() || IsDouble();
101     }
102 
ConversionError()103     bool ConversionError() const
104     {
105         return (flags_ & NumberFlags::ERROR) != 0;
106     }
107 
GetInt()108     int32_t GetInt() const
109     {
110         ASSERT(IsInt());
111         return std::get<int32_t>(num_);
112     }
113 
GetLong()114     int64_t GetLong() const
115     {
116         return std::visit(overloaded {[](int64_t value) { return value; },
117                                       [](int32_t value) { return static_cast<int64_t>(value); },
118                                       []([[maybe_unused]] auto value) {
119                                           ASSERT(false);
120                                           return static_cast<int64_t>(0);
121                                       }},
122                           num_);
123     }
124 
GetFloat()125     float GetFloat() const
126     {
127         ASSERT(IsFloat());
128         return std::get<float>(num_);
129     }
130 
GetDouble()131     double GetDouble() const
132     {
133         return std::visit(
134             overloaded {[](double value) { return value; }, [](auto value) { return static_cast<double>(value); }},
135             num_);
136     }
137 
Str()138     const util::StringView &Str() const
139     {
140         return str_;
141     }
142 
Negate()143     void Negate()
144     {
145         std::visit(overloaded {[](auto &value) { value = -value; }}, num_);
146     }
147 
148     template <typename RT>
CanGetValue()149     bool CanGetValue() const noexcept
150     {
151         using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>;
152 
153         if constexpr (std::is_same_v<T, int64_t>) {
154             return IsInteger();
155         } else if constexpr (std::is_same_v<T, int32_t>) {
156             return IsInt();
157         } else if constexpr (std::is_same_v<T, double>) {
158             return true;
159         } else if constexpr (std::is_same_v<T, float>) {
160             return IsFloat();
161         } else {
162             return false;
163         }
164     }
165 
166     template <typename RT>
GetValue()167     auto GetValue() const
168     {
169         using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>;
170 
171         if constexpr (std::is_same_v<T, int64_t>) {
172             return GetLong();
173         } else if constexpr (std::is_same_v<T, int32_t>) {
174             return GetInt();
175         } else if constexpr (std::is_same_v<T, double>) {
176             return GetDouble();
177         } else if constexpr (std::is_same_v<T, float>) {
178             return GetFloat();
179         } else {
180             static_assert(dependent_false_v<T>, "Invalid value type was requested for Number.");
181         }
182     }
183 
184     template <typename RT>
SetValue(RT && value)185     void SetValue(RT &&value)
186     {
187         using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>;
188 
189         if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, int32_t> || std::is_same_v<T, double> ||
190                       std::is_same_v<T, float>) {
191             num_ = std::forward<RT>(value);
192         } else {
193             static_assert(dependent_false_v<T>, "Invalid value type was requested for Number.");
194         }
195     }
196 
197 private:
198     util::StringView str_ {};
199     std::variant<int32_t, int64_t, float, double> num_;
200     NumberFlags flags_ {NumberFlags::NONE};
201 };
202 }  // namespace panda::es2panda::lexer
203 
204 #endif
205