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