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