1/*
2 * Copyright (c) 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
16declare interface ArkTools {
17    isAOTCompiled(args: any): boolean;
18}
19declare function print(arg:any):string;
20function replace(a, b)
21{
22    return a;
23}
24
25function doAsUintN(bits: number, b : bigint) {
26    return BigInt.asUintN(bits, b);
27}
28
29function tryDoAsUintNEmpty() {
30    try {
31        print(BigInt.asUintN());
32    } catch(e) {
33        print(e);
34    }
35}
36
37function tryDoAsUintNSingle(a) {
38    try {
39        print(BigInt.asUintN(a));
40    } catch(e) {
41        print(e);
42    }
43}
44
45function tryDoAsUintN(bits: number, b : bigint) {
46    try {
47        print(doAsUintN(bits, b));
48    } catch(e) {
49        print(e);
50    }
51}
52
53function printAsUintN(bits: number, b : bigint) {
54    try {
55        print(doAsUintN(bits, b));
56    } finally {
57    }
58}
59
60// Check standart behaviour
61// 25n = 00011001
62//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
63print(BigInt.asUintN(3, 25n)); //: 1
64//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
65print(BigInt.asUintN(4, 25n)); //: 9
66
67// Check without params
68tryDoAsUintNEmpty(); //: TypeError: Cannot convert a undefine or null value to a BigInt
69
70// Check with 1 param
71tryDoAsUintNSingle(15); //: TypeError: Cannot convert a undefine or null value to a BigInt
72tryDoAsUintNSingle(23n); //: TypeError: Cannot convert a BigInt value to a number
73
74// Check with 2 params
75// 100n = 01100100
76//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
77print(BigInt.asUintN(4, 100n)); //: 4
78
79// Check with 3 params
80//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
81print(BigInt.asUintN(8, 100n, undefined)); //: 100
82
83// Check with 4 params
84//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
85print(BigInt.asUintN(16, 100n, -20000, "abc")); //: 100
86
87// Check some corner cases
88//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
89print(BigInt.asUintN(0, 10000n)); //: 0
90//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
91print(BigInt.asUintN(32, 0n)); //: 0
92//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
93//aot: [trace] Check Type: RangeError
94tryDoAsUintN(-2, 10000n); //: RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER
95//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
96//aot: [trace] Check Type: RangeError
97tryDoAsUintN(2 ** 53, 100000n); //: RangeError: integerIndex < 0 or integerIndex > SAFE_NUMBER
98
99// bits > kMaxLengthBits => return bigint
100//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
101print(BigInt.asUintN(2 ** 35, 2n ** 75n)); //: 37778931862957161709568
102//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
103print(BigInt.asUintN(2 ** 35, 65531n)); //: 65531
104
105// Check maximum and minimum values
106const max32 = 2n ** 32n - 1n; // UINT32_MAX = 4294967295
107const max64 = 2n ** 64n - 1n; // UINT64_MAX = 18446744073709551615
108
109//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
110print(BigInt.asUintN(32, max32)); //: 4294967295
111//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
112print(BigInt.asUintN(32, max32 + 1n)); //: 0
113//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
114print(BigInt.asUintN(64, max64)); //: 18446744073709551615
115//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
116print(BigInt.asUintN(64, max64 + 1n)); //: 0
117//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
118print(BigInt.asUintN(32, -max32)); //: 1
119//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
120print(BigInt.asUintN(32, -max32 - 1n)); //: 0
121//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
122print(BigInt.asUintN(32, -max32 - 2n)); //: 4294967295
123//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
124print(BigInt.asUintN(64, -max64)); //: 1
125//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
126print(BigInt.asUintN(64, -max64 - 1n)); //: 0
127//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
128print(BigInt.asUintN(64, -max64 - 2n)); //: 18446744073709551615
129
130// Replace standard builtin
131let true_asUintN = BigInt.asUintN
132BigInt.asUintN = replace
133print(BigInt.asUintN(-1.001, 26n)); //: -1.001
134BigInt.asUintN = true_asUintN
135//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
136printAsUintN(3, 25n); //: 1
137//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
138print(true_asUintN(3, 25n)); //: 1
139
140// Call standard builtin with non-number param
141//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
142//aot: [trace] Check Type: NotNumber1
143tryDoAsUintN("abc", "abc"); //: SyntaxError: Cannot convert string to a BigInt,because not allow Infinity, decimal points, or exponents
144//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
145//aot: [trace] Check Type: NotNumber1
146printAsUintN("3", 25n); //: 1
147
148if (ArkTools.isAOTCompiled(printAsUintN)) {
149    // Replace standard builtin after call to standard builtin was profiled
150    BigInt.asUintN = replace
151}
152
153printAsUintN(3, 25n); //pgo: 1
154//aot: [trace] Check Type: NotCallTarget1
155//aot: 3
156
157tryDoAsUintN("abc", "abc"); //pgo: SyntaxError: Cannot convert string to a BigInt,because not allow Infinity, decimal points, or exponents
158//aot: [trace] Check Type: NotCallTarget1
159//aot: abc
160
161BigInt.asUintN = true_asUintN
162
163// Check IR correctness inside try-block
164try {
165    //aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
166    printAsUintN(3, 25n); //: 1
167    //aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:#*#doAsUintN@builtinBigIntAsUintN
168    //aot: [trace] Check Type: NotNumber1
169    printAsUintN("abc", "abc");
170} catch (e) {
171}
172
173let obj = {
174    valueOf: () => { return 5; }
175};
176
177// 25n = 00011001
178//aot: [trace] aot inline builtin: BigInt.asUintN, caller function name:func_main_0@builtinBigIntAsUintN
179//aot: [trace] Check Type: NotNumber1
180print(BigInt.asUintN(obj, 25n)); //: 25
181
182function Throwing() {
183    this.value = 5;
184}
185Throwing.prototype.valueOf = function() {
186    if (this.value < 0) {
187        throw new Error("negative bitness");
188    }
189    return this.value;
190}
191let throwingObj = new Throwing();
192
193try {
194    // 42n = 00101010
195    print(BigInt.asUintN(throwingObj, 42n)); //: 10
196    throwingObj.value = -8;
197    print(BigInt.asUintN(throwingObj, 42n));
198} catch(e) {
199    print(e); //: Error: negative bitness
200} finally {
201    // 15n = 00001111
202    print(BigInt.asUintN(obj, 15n)); //: 15
203}
204