• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 ECMASCRIPT_JS_NUMBER_H
17 #define ECMASCRIPT_JS_NUMBER_H
18 
19 #include "ecmascript/base/number_helper.h"
20 
21 #include "ecmascript/ecma_macros.h"
22 #include "ecmascript/js_hclass.h"
23 #include "ecmascript/js_tagged_value.h"
24 #include "ecmascript/object_factory.h"
25 
26 namespace panda {
27 namespace ecmascript {
28 class JSTaggedNumber final : public JSTaggedValue {
29 public:
30     constexpr JSTaggedNumber() = default;
JSTaggedNumber(double v)31     explicit JSTaggedNumber(double v) : JSTaggedValue(v) {}
JSTaggedNumber(int v)32     constexpr explicit JSTaggedNumber(int v) : JSTaggedValue(v) {}
JSTaggedNumber(unsigned int v)33     explicit JSTaggedNumber(unsigned int v) : JSTaggedValue(v) {}
JSTaggedNumber(JSTaggedValue v)34     explicit JSTaggedNumber(JSTaggedValue v) : JSTaggedValue(v.GetRawData())
35     {
36         ASSERT_PRINT(v.IsNumber(), "can not convert non Number JSTaggedValue to JSTaggedNumber");
37     }
38 
39     ~JSTaggedNumber() = default;
40     DEFAULT_COPY_SEMANTIC(JSTaggedNumber);
41     DEFAULT_MOVE_SEMANTIC(JSTaggedNumber);
42 
Exception()43     static inline constexpr JSTaggedNumber Exception()
44     {
45         return JSTaggedNumber(VALUE_EXCEPTION);
46     }
47 
IsException()48     inline bool IsException() const
49     {
50         return JSTaggedValue::IsException();
51     }
52 
ToInt32()53     inline int32_t ToInt32() const
54     {
55         if (IsInt()) {
56             return GetInt();
57         }
58         return base::NumberHelper::DoubleToInt(GetDouble(), base::INT32_BITS);
59     }
60 
ToUint32()61     inline uint32_t ToUint32() const
62     {
63         return ToInt32();
64     }
65 
ToInt16()66     inline int16_t ToInt16() const
67     {
68         return base::NumberHelper::DoubleToInt(GetNumber(), base::INT16_BITS);
69     }
70 
ToUint16()71     inline uint16_t ToUint16() const
72     {
73         return ToInt16();
74     }
75 
ToInt8()76     inline int8_t ToInt8() const
77     {
78         return base::NumberHelper::DoubleToInt(GetNumber(), base::INT8_BITS);
79     }
80 
ToUint8()81     inline uint8_t ToUint8() const
82     {
83         return ToInt8();
84     }
85 
ToString(const JSThread * thread)86     inline JSHandle<EcmaString> ToString(const JSThread *thread) const
87     {
88         return base::NumberHelper::NumberToString(thread, *this);
89     }
90 
91     JSTaggedNumber operator-(JSTaggedNumber number) const
92     {
93         if (IsInt() && number.IsInt()) {
94             int64_t a0 = GetInt();
95             int64_t a1 = number.GetInt();
96             int64_t res = a0 - a1;
97             if (res > INT32_MAX || res < INT32_MIN) {
98                 return JSTaggedNumber(static_cast<double>(res));
99             }
100             return JSTaggedNumber(static_cast<int>(res));
101         }
102         return JSTaggedNumber(GetNumber() - number.GetNumber());
103     }
104 
105     JSTaggedNumber operator*(JSTaggedNumber number) const
106     {
107         if (IsInt() && number.IsInt()) {
108             int64_t intA = GetInt();
109             int64_t intB = number.GetInt();
110             int64_t res = intA * intB;
111             if (res > INT32_MAX || res < INT32_MIN) {
112                 return JSTaggedNumber(static_cast<double>(res));
113             }
114             return JSTaggedNumber(static_cast<int>(res));
115         }
116         return JSTaggedNumber(GetNumber() * number.GetNumber());
117     }
118 
119     JSTaggedNumber operator++() const
120     {
121         if (IsInt()) {
122             int32_t value = GetInt();
123             if (value == INT32_MAX) {
124                 return JSTaggedNumber(static_cast<double>(value) + 1.0);
125             }
126             return JSTaggedNumber(value + 1);
127         }
128         return JSTaggedNumber(GetDouble() + 1.0);
129     }
130 
131     JSTaggedNumber operator--() const
132     {
133         if (IsInt()) {
134             int32_t value = GetInt();
135             if (value == INT32_MIN) {
136                 return JSTaggedNumber(static_cast<double>(value) - 1.0);
137             }
138             return JSTaggedNumber(value - 1);
139         }
140         return JSTaggedNumber(GetDouble() - 1.0);
141     }
142 
143     inline bool operator!=(const JSTaggedNumber &number) const
144     {
145         return GetNumber() != number.GetNumber();
146     }
147 
148     /* static */
SameValue(JSTaggedNumber x,JSTaggedNumber y)149     inline static bool SameValue(JSTaggedNumber x, JSTaggedNumber y)
150     {
151         double xValue = x.GetNumber();
152         double yValue = y.GetNumber();
153         // SameNumberValue(NaN, NaN) is true.
154         if (xValue != yValue) {
155             return std::isnan(xValue) && std::isnan(yValue);
156         }
157         // SameNumberValue(0.0, -0.0) is false.
158         return (std::signbit(xValue) == std::signbit(yValue));
159     }
160 
FromIntOrDouble(JSThread * thread,JSTaggedValue tagged)161     inline static JSTaggedNumber FromIntOrDouble(JSThread *thread, JSTaggedValue tagged)
162     {
163         if (tagged.IsInt() || tagged.IsDouble()) {
164             return JSTaggedNumber(tagged);
165         }
166         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot convert value to a number", JSTaggedNumber::Exception());
167     }
168 
169 private:
JSTaggedNumber(JSTaggedType v)170     constexpr explicit JSTaggedNumber(JSTaggedType v) : JSTaggedValue(v) {}
171 };
172 }  // namespace ecmascript
173 }  // namespace panda
174 #endif  // ECMASCRIPT_JS_NUMBER_H
175