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
16interface B<T> {
17  f2(v: B<T>): B<T>; 
18}
19
20class C<T extends Numeric|string, Z, T1 = string> implements B<T> {
21
22  f1(v: T): T { 
23    return v; 
24  }
25
26  f2(v: C<T, Z>): C<T, Z> { 
27     return new C<T, Z>(); 
28  }
29
30  f2(v: B<T>): B<T> {
31     return this.f2(v as C<T, Z>);
32  }
33
34  f3(v: T|string): string {
35    return "C.f3";
36  }
37
38  f4(v: C<T, Z>|Numeric): string {
39    return "C.f4";
40  }
41
42  f5(x: T1|Z|C<T, Z, T1>[]): string {
43    return "C.f5"; 
44  }
45
46  f6(x: C<T, Z>, y: C<T, Z>): string { 
47    return "C.f6"; 
48  }
49
50  f7(x: T, y: C<T, Z>): string { 
51    return "C.f7"; 
52  }
53
54  f8(x: string): string {
55    return "C.f8";
56  }
57
58  f9(z: Z, y: T1): string {
59    return "C.f9";
60  }
61}
62
63class D<W> extends C<string, W> {
64  f1(v: string): string { 
65    return "D.f1"; 
66  }
67  
68  f1(v: Numeric|string|C<Int, W>): string { 
69    return this.f1(v as string); 
70  } 
71
72  f1(v: Int): Int { 
73    return 7; 
74  }
75
76  f2(v: D<W>): D<W> { 
77    return new D<W>(); 
78  }
79
80  f3(v: string): string {
81    return "D.f3";
82  }
83
84  f4(v: D<W>): string {
85    return "D.f4";
86  }
87
88  f4 (x: int, y: int): int { 
89    return x + y; 
90  }
91
92  f5(x: string|W|C<string, W>[]): string {
93    return "D.f5";
94  }
95
96  f6(): string { 
97    return "D.f6"; 
98  }
99
100  f7(x: string, y: D<W>): string { 
101    return "D.f7"; 
102  }
103
104  f8(x: string): string {
105    return "D.f8";
106  }
107
108  f9(z: W, y: string): string {
109    return "D.f9-1";
110  }
111
112  f9(z: W, y: Int): string {
113    return "D.f9-2";
114  }
115}
116
117class F extends D<string> {}
118
119class G<U extends Numeric|string> extends C<U, string, Int> {}
120
121class E<U extends Integral> extends C<U, string> {
122
123  f1(v: U): Integral { 
124    if (v instanceof Int) {
125      return new Int(7);
126    } else if (v instanceof Long) {
127      return new Long(8);
128    } else {
129      return new Int(-1);
130    }
131  }
132
133  f2(v: E<U>): E<U> { 
134     return new E<U>(); 
135  }
136
137  f3(){}
138
139  f4(x:int, y: int): int { return x + y; }
140
141  f7(x: U, y: E<U>): string { 
142    return "E.f7"; 
143  }
144}
145
146function foo1(c: C<Int, string>) {
147  assert (c.f1(0) == 7);
148  assert (c.f2(c).f1(0) == 7);
149  assert (c.f5("") == "C.f5"); 
150  assert (c.f6(c, c) == "C.f6");
151}
152
153function foo2(c: C<Long, string>) {
154 assert (c.f1(0) == 8);
155 assert (c.f2(c).f1(0) == 8);
156 assert (c.f5("") == "C.f5");
157 assert (c.f7(3, c) == "E.f7");
158}
159
160function ttt(c: C<string, string>): void {
161  assert (c.f1("ah") == "D.f1"); 
162  assert (c.f2(c).f1("ah") == "D.f1");
163  assert(((c.f2(c as B<string>)) as C<string, string>).f1("ah") == "D.f1");
164  assert(c.f3("ah") == "D.f3");
165  assert (c.f4(c) == "D.f4");
166  assert (c.f5("ah") == "D.f5");
167  assert (c.f6(c, c) == "C.f6");;
168  assert ((c as D<string>).f6() == "D.f6");
169  assert (c.f7("ah", c) == "D.f7");
170  assert (c.f8("") == "D.f8");
171  assert (c.f9("", "") == "C.f9");
172  assert ((c as D<string>).f9("", 0) == "D.f9-2");
173}
174
175function main() {
176  ttt(new D<string>())
177  let c: C<Int, string> = new E<Int>();
178  foo1(c);
179  foo2(new E<Long>());
180}
181