1/*
2 * Copyright (c) 2021-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
16function main(): void {
17    let intType: TypeGetter<Int> = new TypeGetter<Int>();
18    let testInt: Int = 2;
19    let testDouble: Double = 3.0;
20    let doubleType: TypeGetter<Double> = new TypeGetter<Double>();
21    intType.SetType(testInt);
22    doubleType.SetType(testDouble);
23    assert intType.GetType() == 2;
24    assert doubleType.GetType() == 3.0;
25
26    let aType: TypeGetter<A> = new TypeGetter<A>();
27    let aClass: A = new A();
28    aType.SetType(aClass);
29    assert aType.GetType().aValue() == 1;
30
31    let ext1Class: Ext1 = new Ext1();
32    let ext2Class: Ext2 = new Ext2();
33    assert bar(ext1Class, ext2Class) == 7;
34    assert bar(ext2Class, ext1Class) == -7;
35
36    let bc: B = new B();
37    let cc : C = new C();
38    let dc: D = new D();
39    assert bc.bMet(cc).cMet() == 17;
40    assert bc.bMet(cc).ifaceMet() == 10;
41    assert bc.bMet(dc).dMet() == 8;
42}
43
44interface ifaceExt {
45  ifmet(other: Object): int;
46}
47
48function ifaceType<T extends ifaceExt>(x: T, y: T): int {
49  return x.ifmet(y);
50}
51
52class TypeGetter<TT> {
53    tVar: TT;
54
55    GetType(): TT{
56        return this.tVar;
57    }
58
59    SetType(a0: TT): void{
60        this.tVar = a0;
61    }
62}
63
64class A {
65    aValue(): int {
66        return 1;
67    }
68}
69
70class AConstraint<T extends A>{
71    cVar: T;
72
73    getVal(): void {
74        this.cVar.aValue();
75    }
76}
77
78interface iface2<T>{
79    ifaceMet(): int;
80}
81
82class C implements iface2<Object>{
83    public override ifaceMet(): int{
84        return 10;
85    }
86    public cMet(): int {
87        return 17;
88    }
89}
90
91class D extends C{
92    public dMet(): int {
93        return 8;
94    }
95}
96
97class B {
98    public bMet<LU extends C>(a: LU): LU {
99        let b: int = 2;
100        a.ifaceMet();
101        return a;
102    }
103}
104
105interface ifaceExt2 {
106  imet1(other: Object): int;
107  imet2(): int;
108}
109
110function bar<T extends impExt>(x: T, y: T): int {
111  let a = x.imet2();
112  let b = y.imet2();
113  return a - b;
114}
115
116class impExt implements ifaceExt2{
117    override imet1(other: Object): int{
118        return 20;
119    }
120    override imet2(): int{
121        return 21;
122    }
123}
124
125class Ext1 extends impExt{
126    override imet1(other: Object): int{
127        return 11;
128    }
129    override imet2(): int {
130        return 14;
131    }
132}
133
134class Ext2 extends impExt{
135    override imet1(other: Object): int{
136        return 22;
137    }
138    override imet2(): int {
139        return 7;
140    }
141}
142
143interface inter3<T>{
144    met1(a0: T): int;
145    met2(a1: T): T;
146    met3(a3: T): inter3<T>;
147}
148
149class ImplInter3<T> implements inter3<Int>{
150    public override met1(a0: Int): int {
151        return 1;
152    }
153
154    public override met2(a0: Int): Int {
155        return 2;
156    }
157
158    public override met3(a0: Int): inter3<Int> {
159        let a: inter3<Int> = new ImplInter3<Int>();
160        return a;
161    }
162}
163