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