1/*
2 * Copyright (c) 2023-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
16// test transformation of trailing lambda
17let x: int = 1;
18const y: int = 3;
19
20function f1(callback: ()=>void) {
21    callback();
22}
23
24function f2() {
25    x = x + 1
26}
27
28function f3(callback: ()=>void) :int {
29    callback();
30    return y;
31}
32
33function test_transform() {
34    x = 1
35    f1() {  // Test '{' at the same line as call expression, block statement can be transformed to trailing lambda
36        x++
37    }
38    assert x == 2: "expected: " + 2 + " actual: " + x;
39
40    f1()
41    {  // Test '{' not the same line as call expression, block statement can be transformed to trailing lambda
42        x++
43    }
44    assert x == 3: "expected: " + 3 + " actual: " + x;
45
46    f2()
47    {  // Test this block run as a standalone code block
48        x++
49    }
50    assert x == 5: "expected: " + 5 + " actual: " + x;
51
52    let b = f3()
53    { x++ }
54    assert x == 6: "expected: " + 6 + " actual: " + x;
55    assert b == y: "expected: " + y + " actual: " + b;
56
57    let a = f3() { x++ }
58    assert x == 7: "expected: " + 7 + " actual: " + x;
59    assert a == y: "expected: " + y + " actual: " + a;
60
61    assert y == f3(){}
62    assert y == f3(()=>{})
63    {
64    }
65}
66
67// test signature matches of trailing lambda
68function f_overload(num: Int, callback: ()=>void): Int {
69    return 0;
70}
71
72function f_overload(num: Int): Int {
73    return num;
74}
75
76function test_overload() {
77    let num = f_overload(1)
78    {
79        // This block will be transform to a trailing lambda
80    }
81    assert num == 0: "expected: " + 0 + " actual: " + num;
82}
83
84// test class methods using trailing lambda
85class A {
86    set_n(callback: ()=>void) {
87        callback();
88    }
89
90    public static set_n_static(callback: ()=>void): void {
91        callback();
92    }
93
94    static n: int = 1;
95}
96
97function test_class_method() {
98    let a = new A();
99    A.n = 1;
100    a.set_n() {
101        A.n++;
102    }
103    assert A.n == 2: "expected: " + 2 + " actual: " + A.n;
104
105    A.set_n_static() {
106        A.n++;
107    }
108    assert A.n == 3: "expected: " + 3 + " actual: " + A.n;
109}
110
111// test scenarios involving scope
112function foo(c: () => void): void {
113    c();
114}
115
116function foo2(a: int) : int {
117    a++;
118    return a;
119}
120
121class B {
122    constructor (b: int) {
123        this.b = b;
124    }
125
126    get_b(): int {
127        return this.b
128    }
129
130    b: int = 0;
131}
132
133function test_scope(): void {
134    foo() {
135       let num: int = 3;
136       assert num == 3: "expected: " + 3 + " actual: " + num;
137       {
138            num++;
139            assert num == 4: "expected: " + 4 + " actual: " + num;
140            {
141                num++;
142                assert num == 5: "expected: " + 5 + " actual: " + num;
143            }
144       }
145
146       let a = foo2(num);
147       assert a == 6: "expected: " + 6 + " actual: " + a;
148
149       let b = new B(num);
150       assert b.get_b() == 5: "expected: " + 5 + " actual: " + b.get_b();
151
152       foo() {
153          let k = 1
154          assert k == 1: "expected: " + 1 + " actual: " + k;
155       }
156    };
157}
158
159// test recovery of trailing block
160function test_recover_trailing_block() {
161    let a = 100;
162    foo(()=>{})
163    {
164        let k = a;
165        let b = new B(k);
166        assert b.get_b() == k: "expected: " + k + " actual: " + b.get_b();
167
168        a++;
169    };
170    assert a == 101: "expected: " + 101 + " actual: " + a;
171}
172
173function main() {
174    test_transform();
175    test_recover_trailing_block();
176    test_overload();
177    test_class_method();
178    test_scope();
179}
180