Skip to content

Commit 099cb11

Browse files
author
Willem Wyndham
committed
Better type checking and virtual table works
Still need to move logic into the interface methods.
1 parent 839aa13 commit 099cb11

File tree

4 files changed

+232
-49
lines changed

4 files changed

+232
-49
lines changed

src/compiler.ts

+26-22
Original file line numberDiff line numberDiff line change
@@ -2956,7 +2956,15 @@ export class Compiler extends DiagnosticEmitter {
29562956
fromType.toString(),
29572957
toType.toString());
29582958
} else {
2959-
this.checkInterfaceImplementation(toType, fromType, reportNode);
2959+
if (this.checkInterfaceImplementation(toType, fromType, reportNode)){
2960+
(<Interface>toType.classReference).implementers.add(fromType.classReference);
2961+
} else {
2962+
this.error(
2963+
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
2964+
reportNode.range,
2965+
fromType.toString(),
2966+
toType.toString());
2967+
}
29602968
}
29612969
}
29622970
else if (!fromType.isAssignableTo(toType)) {
@@ -9274,30 +9282,23 @@ export class Compiler extends DiagnosticEmitter {
92749282
return module.addFunction(func.internalName, typeRef, null, body);
92759283
}
92769284

9277-
checkInterfaceImplementation(toType: Type, fromType: Type, reportNode: Node): void {
9285+
checkInterfaceImplementation(toType: Type, fromType: Type, reportNode: Node): bool {
92789286
const _interface = (<Interface>toType.classReference!);
92799287
const _class = fromType.classReference!;
92809288
var imems: Map<string, Element>;
9281-
var mems: Map<string, Element>;
9289+
var mems: Map<string, Element> | null;
92829290
if (_interface.prototype.instanceMembers == null) {
9283-
return;
9284-
} else {
9285-
imems = _interface.prototype.instanceMembers;
9286-
if (_class.prototype.instanceMembers == null) {
9287-
// All members missing
9288-
9289-
return;
9290-
} else {
9291-
mems = _class.prototype.instanceMembers;
9292-
}
9291+
return true;
92939292
}
9293+
imems = _interface.prototype.instanceMembers;
9294+
mems = _class.prototype.instanceMembers;
9295+
92949296
var error = false;
92959297
var incorrectMember = false;
92969298
for (const [name, imem] of imems.entries()) {
92979299
error = error || incorrectMember;
92989300
incorrectMember = true;
9299-
let mem = mems.get(name);
9300-
if (mem == null) {
9301+
if (mems == null || mems.get(name) == null) {
93019302
// Error!
93029303
this.error(
93039304
DiagnosticCode.Property_0_is_missing_in_type_1_but_required_in_type_2,
@@ -9308,6 +9309,7 @@ export class Compiler extends DiagnosticEmitter {
93089309
);
93099310
continue;
93109311
}
9312+
let mem = mems.get(name)!;
93119313
if (imem.kind != mem.kind) {
93129314
// Interfaces can't have properties
93139315
if (!(mem.kind == ElementKind.PROPERTY_PROTOTYPE && imem.kind == ElementKind.FIELD_PROTOTYPE)) {
@@ -9378,19 +9380,21 @@ export class Compiler extends DiagnosticEmitter {
93789380
from.toString(),
93799381
to.toString()
93809382
);
9381-
continue;
9382-
// Error
9383-
}
9384-
incorrectMember = false;
9383+
continue;
9384+
// Error
9385+
}
9386+
incorrectMember = false;
93859387
}
9388+
error = error || incorrectMember;// case where contiune skips the last check.
93869389
if (error) {
93879390
this.error(
93889391
DiagnosticCode.Class_0_incorrectly_implements_interface_1,
93899392
_class.identifierNode.range,
9390-
fromType.toString(),
9391-
toType.toString()
9392-
);
9393+
fromType.toString(),
9394+
toType.toString()
9395+
);
93939396
}
9397+
return !error;
93949398
}
93959399
}
93969400

tests/compiler/interface-fail.json

+34-14
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,42 @@
33
"--runtime none"
44
],
55
"stderr": [
6-
"TS2322: Type 'interface-fail/BadFoo' is not assignable to type 'interface-fail/IFoo'.",
7-
"const aBadFoo: IFoo = new BadFoo();",
8-
"TS2420: Class 'interface-fail/BadFoo' incorrectly implements interface 'interface-fail/IFoo'.",
9-
"class BadFoo implements IFoo {",
10-
"TS2741: Property 'foo' is missing in type 'interface-fail/BadFoo' but required in type 'interface-fail/IFoo'.",
11-
"class BadFoo implements IFoo {",
12-
"TS2322: Type 'BadFoo.faa' is not assignable to type 'IFoo.faa'.",
13-
"faa(i: i32, i2: i32): i32 {",
14-
"TS2322: Type 'interface-fail/AnotherBadFoo' is not assignable to type 'interface-fail/IFoo'.",
15-
"const anotherBadFoo: IFoo = new AnotherBadFoo();",
16-
"TS2420: Class 'interface-fail/AnotherBadFoo' incorrectly implements interface 'interface-fail/IFoo'.",
6+
"TS2741: Property 'foo' is missing in type 'BadFoo' but required in type 'IFoo'.",
7+
"class BadFoo implements IFoo {",
8+
9+
"TS2322: Type '(i: i32, i2: i32) => i32' is not assignable to type '(i: i32, i2: i32) => ~lib/string/String'.",
10+
"class BadFoo implements IFoo {",
11+
12+
"TS2420: Class 'interface-fail/BadFoo' incorrectly implements interface 'interface-fail/IFoo'.",
13+
"class BadFoo implements IFoo {",
14+
15+
"TS2322: Type 'interface-fail/BadFoo' is not assignable to type 'interface-fail/IFoo'.",
16+
"const aBadFoo: IFoo = new BadFoo();",
17+
18+
"TS2741: Property 'foo' is missing in type 'AnotherBadFoo' but required in type 'IFoo'.",
1719
"class AnotherBadFoo {}",
18-
"TS2741: Property 'foo' is missing in type 'interface-fail/AnotherBadFoo' but required in type 'interface-fail/IFoo'.",
20+
21+
"TS2741: Property 'faa' is missing in type 'AnotherBadFoo' but required in type 'IFoo'.",
1922
"class AnotherBadFoo {}",
20-
"TS2741: Property 'faa' is missing in type 'interface-fail/AnotherBadFoo' but required in type 'interface-fail/IFoo'.",
23+
24+
"TS2420: Class 'interface-fail/AnotherBadFoo' incorrectly implements interface 'interface-fail/IFoo'.",
2125
"class AnotherBadFoo {}",
26+
27+
"TS2322: Type 'interface-fail/AnotherBadFoo' is not assignable to type 'interface-fail/IFoo'.",
28+
"const anotherBadFoo: IFoo = new AnotherBadFoo();",
29+
2230
"TS2322: Type 'i32' is not assignable to type 'interface-fail/IFoo'.",
23-
"const intFoo: IFoo = <i32>5;"]
31+
"const intFoo: IFoo = <i32>5;",
32+
33+
"TS2741: Property 'get val' is missing in type 'BadProps' but required in type 'Properties'.",
34+
"class BadProps implements Properties {",
35+
36+
"TS2420: Class 'interface-fail/BadProps' incorrectly implements interface 'interface-fail/Properties'.",
37+
"class BadProps implements Properties {",
38+
39+
"TS2322: Type 'interface-fail/BadProps' is not assignable to type 'interface-fail/Properties'.",
40+
"const badProp = <Properties> new BadProps();"
41+
42+
43+
]
2444
}

tests/compiler/interface.optimized.wat

+98-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
(module
2+
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
23
(type $FUNCSIG$vi (func (param i32)))
4+
(type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
5+
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
36
(type $FUNCSIG$v (func))
47
(type $FUNCSIG$ii (func (param i32) (result i32)))
8+
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
59
(memory $0 1)
610
(data (i32.const 8) "\18\00\00\00\01\00\00\00\01\00\00\00\18\00\00\00i\00n\00t\00e\00r\00f\00a\00c\00e\00.\00t\00s")
11+
(table $0 5 funcref)
12+
(elem (i32.const 0) $null $interface/AFoo#foo $interface/AFoo#foo $interface/AFoo#faa $interface/AFoo#faa)
713
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
814
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
915
(global $interface/aFoo (mut i32) (i32.const 0))
1016
(global $interface/sFoo (mut i32) (i32.const 0))
1117
(export "memory" (memory $0))
1218
(start $start)
13-
(func $~lib/rt/stub/maybeGrowMemory (; 0 ;) (type $FUNCSIG$vi) (param $0 i32)
19+
(func $~lib/rt/stub/maybeGrowMemory (; 1 ;) (type $FUNCSIG$vi) (param $0 i32)
1420
(local $1 i32)
1521
(local $2 i32)
1622
local.get $0
@@ -52,7 +58,7 @@
5258
local.get $0
5359
global.set $~lib/rt/stub/offset
5460
)
55-
(func $~lib/rt/stub/__alloc (; 1 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
61+
(func $~lib/rt/stub/__alloc (; 2 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
5662
(local $1 i32)
5763
(local $2 i32)
5864
global.get $~lib/rt/stub/offset
@@ -79,15 +85,48 @@
7985
i32.store offset=12
8086
local.get $2
8187
)
82-
(func $interface/passAnInterface (; 2 ;) (type $FUNCSIG$vi) (param $0 i32)
88+
(func $interface/passAnInterface (; 3 ;) (type $FUNCSIG$vi) (param $0 i32)
89+
local.get $0
90+
i32.const 1
91+
i32.const 0
8392
local.get $0
8493
i32.const 8
8594
i32.sub
8695
i32.load
87-
drop
88-
unreachable
96+
call $~virtual
97+
call_indirect (type $FUNCSIG$iii)
98+
i32.const 42
99+
i32.ne
100+
if
101+
i32.const 0
102+
i32.const 24
103+
i32.const 37
104+
i32.const 2
105+
call $~lib/builtins/abort
106+
unreachable
107+
end
108+
local.get $0
109+
i32.const 1
110+
i32.const 3
111+
i32.const 1
112+
local.get $0
113+
i32.const 8
114+
i32.sub
115+
i32.load
116+
call $~virtual
117+
call_indirect (type $FUNCSIG$iiii)
118+
i32.const 4
119+
i32.ne
120+
if
121+
i32.const 0
122+
i32.const 24
123+
i32.const 38
124+
i32.const 2
125+
call $~lib/builtins/abort
126+
unreachable
127+
end
89128
)
90-
(func $start (; 3 ;) (type $FUNCSIG$v)
129+
(func $start (; 4 ;) (type $FUNCSIG$v)
91130
(local $0 i32)
92131
i32.const 48
93132
global.set $~lib/rt/stub/startOffset
@@ -112,7 +151,59 @@
112151
global.get $interface/sFoo
113152
call $interface/passAnInterface
114153
)
115-
(func $null (; 4 ;) (type $FUNCSIG$v)
154+
(func $interface/AFoo#foo (; 5 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
155+
local.get $0
156+
i32.load
157+
local.get $1
158+
i32.add
159+
)
160+
(func $interface/AFoo#faa (; 6 ;) (type $FUNCSIG$iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
161+
local.get $1
162+
local.get $2
163+
i32.add
164+
)
165+
(func $~virtual (; 7 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
166+
block $block$2$break
167+
block $switch$1$case$6
168+
block $switch$1$case$3
169+
local.get $0
170+
br_table $switch$1$case$3 $switch$1$case$6 $block$2$break
171+
end
172+
local.get $1
173+
i32.const 3
174+
i32.eq
175+
if
176+
i32.const 1
177+
return
178+
else
179+
local.get $1
180+
i32.const 4
181+
i32.ne
182+
br_if $block$2$break
183+
i32.const 2
184+
return
185+
end
186+
unreachable
187+
end
188+
local.get $1
189+
i32.const 3
190+
i32.eq
191+
if
192+
i32.const 3
193+
return
194+
else
195+
local.get $1
196+
i32.const 4
197+
i32.eq
198+
if
199+
i32.const 4
200+
return
201+
end
202+
end
203+
end
204+
unreachable
205+
)
206+
(func $null (; 8 ;) (type $FUNCSIG$v)
116207
nop
117208
)
118209
)

0 commit comments

Comments
 (0)