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 function print(arg : any) : string;
17declare interface ArkTools {
18    isAOTCompiled(args : any) : boolean;
19}
20
21function replace(a : number)
22{
23    return a;
24}
25
26function doTrunc(x : any) : number {
27    return Math.trunc(x);
28}
29
30function printTrunc(x : any) {
31    try {
32        print(doTrunc(x));
33    } finally {
34    }
35}
36
37// Check without params
38//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
39print(Math.trunc()); //: NaN
40
41// Check with special float params
42//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
43print(Math.trunc(NaN)); //: NaN
44//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
45print(Math.trunc(Infinity)); //: Infinity
46//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
47print(Math.trunc(-Infinity)); //: -Infinity
48//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
49print(Math.trunc(+0)); //: 0
50//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
51print("1/x: " + 1 / Math.trunc(-0)); //: 1/x: -Infinity
52
53// Check with single integer param
54//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
55print(Math.trunc(1)); //: 1
56//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
57print(Math.trunc(-12)); //: -12
58
59// Check with single float param
60//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
61print(Math.trunc(1.15613251)); //: 1
62//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
63print(Math.trunc(2.5)); //: 2
64//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
65print(Math.trunc(3.84556546)); //: 3
66//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
67print(Math.trunc(-1.124212)); //: -1
68//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
69print("1/x: " + 1 / Math.trunc(-8.5e-80)); //: 1/x: -Infinity
70//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
71print(Math.trunc(-4.5)); //: -4
72
73// Check with 2 params
74//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
75print(Math.trunc(2.4, 10.5)); //: 2
76
77// Check with 3 params
78//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
79print(Math.trunc(3.123, 10, 1e-39)); //: 3
80
81// Check with 4 params
82//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
83print(Math.trunc(4.89, 10.5, 0, 11)); //: 4
84
85// Replace standart builtin
86let true_trunc = Math.trunc
87Math.trunc = replace
88print(Math.trunc(111.09)); //: 111.09
89Math.trunc = true_trunc
90
91// Call standart builtin with non-number param
92//aot: [trace] aot inline builtin: Math.trunc, caller function name:#*#doTrunc@builtinMathTrunc
93//aot: [trace] Check Type: NotNumber2
94printTrunc("abc"); //: NaN
95//aot: [trace] aot inline builtin: Math.trunc, caller function name:#*#doTrunc@builtinMathTrunc
96//aot: [trace] Check Type: NotNumber2
97printTrunc("2.45"); //: 2
98
99if (ArkTools.isAOTCompiled(printTrunc)) {
100    // Replace standard builtin after call to standard builtin was profiled
101    Math.trunc = replace
102}
103printTrunc(-12.1); //pgo: -12
104//aot: [trace] Check Type: NotCallTarget1
105//aot: -12.1
106
107printTrunc("abc"); //pgo: NaN
108//aot: [trace] Check Type: NotCallTarget1
109//aot: abc
110
111Math.trunc = true_trunc
112
113// Checl IR correctness inside try-block
114try {
115    //aot: [trace] aot inline builtin: Math.trunc, caller function name:#*#doTrunc@builtinMathTrunc
116    printTrunc(-48.12); //: -48
117    //aot: [trace] aot inline builtin: Math.trunc, caller function name:#*#doTrunc@builtinMathTrunc
118    //aot: [trace] Check Type: NotNumber2
119    printTrunc("abc"); //: NaN
120} catch (e) {
121}
122
123let obj = {
124    valueOf: () => { return -35.121; }
125};
126//aot: [trace] aot inline builtin: Math.trunc, caller function name:func_main_0@builtinMathTrunc
127//aot: [trace] Check Type: NotNumber2
128print(Math.trunc(obj)); //: -35
129
130function Throwing() {
131    this.value = -14.12;
132}
133Throwing.prototype.valueOf = function() {
134    if (this.value > 0) {
135        throw new Error("already positive");
136    }
137    return this.value;
138}
139let throwingObj = new Throwing();
140
141try {
142    print(Math.trunc(throwingObj)); //: -14
143    throwingObj.value = 10;
144    print(Math.trunc(throwingObj)); //: Error: already positive
145} catch(e) {
146    print(e);
147} finally {
148    print(Math.trunc(obj)); //: -35
149}
150