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