• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "util/diagnosticEngine.h"
20 #include "util/ustring.h"
21 #include "util/enumbitops.h"
22 
23 namespace ark::es2panda::lexer {
24 
25 using ENUMBITOPS_OPERATORS;
26 
27 enum class NumberFlags : uint32_t {
28     NONE,
29     BIGINT = 1U << 0U,
30     DECIMAL_POINT = 1U << 1U,
31     EXPONENT = 1U << 2U,
32     ERROR = 1U << 3U,
33 };
34 
35 }  // namespace ark::es2panda::lexer
36 
37 template <>
38 struct enumbitops::IsAllowedType<ark::es2panda::lexer::NumberFlags> : std::true_type {
39 };
40 
41 namespace ark::es2panda::lexer {
42 
43 // NOLINTBEGIN(readability-identifier-naming)
44 // NOLINTBEGIN(fuchsia-multiple-inheritance)
45 template <class... Ts>
46 struct overloaded : Ts... {
47     using Ts::operator()...;
48 };
49 
50 template <class... Ts>
51 overloaded(Ts...) -> overloaded<Ts...>;
52 // NOLINTEND(fuchsia-multiple-inheritance)
53 
54 template <typename>
55 inline constexpr bool dependent_false_v = false;
56 // NOLINTEND(readability-identifier-naming)
57 
58 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
59 class Number {
60 public:
61     // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
62     explicit Number() noexcept : num_(static_cast<int32_t>(0)) {};
63     explicit Number(util::StringView str) noexcept : str_(str) {}
64     // NOLINTNEXTLINE(bugprone-exception-escape)
65     explicit Number(util::StringView str, NumberFlags flags) noexcept;
66     explicit Number(util::StringView str, double num) noexcept : str_(str), num_(num) {}
67     explicit Number(uint32_t num) noexcept : Number(static_cast<int32_t>(num)) {}
68     explicit Number(int32_t num) noexcept : num_(num) {}
69     explicit Number(uint64_t num) noexcept : Number(static_cast<int64_t>(num)) {}
70     explicit Number(int64_t num) noexcept : num_(num) {}
71     explicit Number(float num) noexcept : num_(num) {}
72     explicit Number(double num) noexcept : num_(num) {}
73     DEFAULT_COPY_SEMANTIC(Number);
74     DEFAULT_MOVE_SEMANTIC(Number);
75     ~Number() = default;
76     // NOLINTEND(cppcoreguidelines-pro-type-member-init)
77 
78     bool IsInt() const noexcept
79     {
80         return std::holds_alternative<int32_t>(num_);
81     }
82 
83     bool IsLong() const noexcept
84     {
85         return std::holds_alternative<int64_t>(num_);
86     }
87 
88     bool IsInteger() const noexcept
89     {
90         return IsInt() || IsLong();
91     }
92 
93     bool IsFloat() const noexcept
94     {
95         return std::holds_alternative<float>(num_);
96     }
97 
98     bool IsDouble() const noexcept
99     {
100         return std::holds_alternative<double>(num_);
101     }
102 
103     bool IsReal() const noexcept
104     {
105         return IsFloat() || IsDouble();
106     }
107 
108     bool ConversionError() const
109     {
110         return (flags_ & NumberFlags::ERROR) != 0;
111     }
112 
113     int32_t GetInt() const
114     {
115         ES2PANDA_ASSERT(IsInt());
116         return std::get<int32_t>(num_);
117     }
118 
119     int64_t GetLong() const
120     {
121         return std::visit(overloaded {[](int64_t value) { return value; },
122                                       [](int32_t value) { return static_cast<int64_t>(value); },
123                                       []([[maybe_unused]] auto value) {
124                                           ES2PANDA_ASSERT(false);
125                                           return static_cast<int64_t>(0);
126                                       }},
127                           num_);
128     }
129 
130     float GetFloat() const
131     {
132         ES2PANDA_ASSERT(IsFloat());
133         return std::get<float>(num_);
134     }
135 
136     double GetDouble() const
137     {
138         return std::visit(
139             overloaded {[](double value) { return value; }, [](auto value) { return static_cast<double>(value); }},
140             num_);
141     }
142 
143     const util::StringView &Str() const
144     {
145         return str_;
146     }
147 
148     void Negate()
149     {
150         std::visit(overloaded {[](auto &value) { value = -value; }}, num_);
151         if (std::holds_alternative<int64_t>(num_)) {
152             int64_t num = std::get<int64_t>(num_);
153             if (num == INT32_MIN) {
154                 SetValue<int32_t>(num);
155             }
156         }
157     }
158 
159     template <typename RT>
160     bool CanGetValue() const noexcept
161     {
162         using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>;
163 
164         if constexpr (std::is_same_v<T, int64_t>) {
165             return IsInteger();
166         } else if constexpr (std::is_same_v<T, int32_t>) {
167             return IsInt();
168         } else if constexpr (std::is_same_v<T, double>) {
169             return true;
170         } else if constexpr (std::is_same_v<T, float>) {
171             return IsFloat();
172         } else {
173             return false;
174         }
175     }
176 
177     template <typename RT>
178     auto GetValue() const
179     {
180         using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>;
181 
182         if constexpr (std::is_same_v<T, int64_t>) {
183             return GetLong();
184         } else if constexpr (std::is_same_v<T, int32_t>) {
185             return GetInt();
186         } else if constexpr (std::is_same_v<T, double>) {
187             return GetDouble();
188         } else if constexpr (std::is_same_v<T, float>) {
189             return GetFloat();
190         } else {
191             static_assert(dependent_false_v<T>, "Invalid value type was requested for Number.");
192         }
193     }
194 
195     template <typename RT>
196     void SetValue(RT &&value)
197     {
198         using T = typename std::remove_cv_t<typename std::remove_reference_t<RT>>;
199 
200         if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, int32_t> || std::is_same_v<T, double> ||
201                       std::is_same_v<T, float>) {
202             num_ = std::forward<RT>(value);
203         } else {
204             static_assert(dependent_false_v<T>, "Invalid value type was requested for Number.");
205         }
206     }
207 
208 private:
209     util::StringView str_ {};
210     std::variant<int32_t, int64_t, float, double> num_;
211     NumberFlags flags_ {NumberFlags::NONE};
212 };
213 }  // namespace ark::es2panda::lexer
214 
215 #endif
216