Skip to content

Commit e4c6bff

Browse files
committed
Better IR type names and mismatched type error messages
1 parent d930acc commit e4c6bff

File tree

4 files changed

+66
-16
lines changed

4 files changed

+66
-16
lines changed

demos/ir.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function displayObject(parent: HTMLElement, key: string, obj: any): void {
3838
const [id, idNew] = getId(obj);
3939
li.classList.add(`objID${id}`);
4040
if (idNew) li.id = `objID${id}`;
41-
li.innerHTML = `<span class="key">${key}:</span> <code>${obj instanceof CArithmetic ? obj.name : Object.getPrototypeOf(obj).constructor.name}</code>`;
41+
li.innerHTML = `<span class="key">${key}:</span> <code>${obj instanceof CArithmetic ? obj.typeName : Object.getPrototypeOf(obj).constructor.name}</code>`;
4242
if (obj instanceof CArithmetic && !(obj as any).qualifier) return; // reduce tree clutter
4343

4444
if (idNew) {

src/ir/expressions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class CConstant {
3838
newValue = Number(this.value);
3939
} else {
4040
if (this.value > type.maxValue || this.value < type.minValue) {
41-
throw new checks.ExpressionTypeError(this.node, `value which fits in ${type.name}`, this.value.toString());
41+
throw new checks.ExpressionTypeError(this.node, `value which fits in ${type.typeName}`, this.value.toString());
4242
}
4343
newValue = BigInt(this.value);
4444
}

src/ir/types.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ export class CFuncType {
3636
}
3737

3838
export class CPointer {
39-
readonly typeName = "pointer";
4039
readonly bytes = 4;
4140
readonly alignment = 4;
4241
readonly incomplete = false;
@@ -57,10 +56,13 @@ export class CPointer {
5756
get pointerGeneration(): this {
5857
return this; // no pointer generation (already a pointer!)
5958
}
59+
60+
get typeName(): string {
61+
return this.type.typeName + "*" + (this.qualifier ? " " + this.qualifier : "");
62+
}
6063
}
6164

6265
export class CArray {
63-
readonly typeName = "array";
6466
readonly alignment: number;
6567

6668
constructor(readonly node: ParseNode | undefined, readonly type: CType, public length?: number) {
@@ -84,6 +86,14 @@ export class CArray {
8486
get pointerGeneration(): CPointer {
8587
return addQualifier(new CPointer(this.node, this.type, false, this), getQualifier(this));
8688
}
89+
90+
get typeName(): string {
91+
if (this.length) {
92+
return this.type.typeName + "[" + this.length + "]";
93+
} else {
94+
return this.type.typeName + "[]";
95+
}
96+
}
8797
}
8898

8999
export type CCompound = CStruct | CUnion | CEnum;
@@ -93,7 +103,6 @@ export class CCompoundMember {
93103
}
94104

95105
export class CStruct {
96-
readonly typeName = "struct";
97106
private _members: ReadonlyArray<CCompoundMember> | undefined;
98107

99108
constructor(public node: ParseNode | undefined, readonly name: string | undefined) {
@@ -155,10 +164,17 @@ export class CStruct {
155164
get pointerGeneration(): this {
156165
return this; // no pointer generation
157166
}
167+
168+
get typeName(): string {
169+
if (this.name) {
170+
return "struct " + this.name;
171+
} else {
172+
return "struct {" + this.members.map(x => x.type.typeName + " " + x.name + ";").join(" ") + "}";
173+
}
174+
}
158175
}
159176

160177
export class CUnion {
161-
readonly typeName = "union";
162178
private _members: ReadonlyArray<CCompoundMember> | undefined;
163179

164180
constructor(public node: ParseNode | undefined, readonly name: string | undefined) {
@@ -212,6 +228,14 @@ export class CUnion {
212228
get pointerGeneration(): this {
213229
return this; // no pointer generation
214230
}
231+
232+
get typeName(): string {
233+
if (this.name) {
234+
return "union " + this.name;
235+
} else {
236+
return "union {" + this.members.map(x => x.type.typeName + " " + x.name + ";").join(" ") + "}";
237+
}
238+
}
215239
}
216240

217241
export type CEnumValue = {name: string, value: bigint};
@@ -260,17 +284,16 @@ export class CVoid {
260284
}
261285

262286
export class CArithmetic {
263-
readonly typeName = "arithmetic";
264287
readonly incomplete = false;
265288
readonly node = undefined;
266289
readonly alignment: number;
267290

268-
private constructor(readonly name: string, readonly bytes: number, readonly type: "float" | "signed" | "unsigned") {
291+
private constructor(readonly typeName: string, readonly bytes: number, readonly type: "float" | "signed" | "unsigned") {
269292
this.alignment = bytes;
270293
}
271294

272295
equals(t: object): boolean {
273-
return t instanceof CArithmetic && t.name === this.name && t.type === this.type && t.bytes === this.bytes;
296+
return t instanceof CArithmetic && t.typeName === this.typeName && t.type === this.type && t.bytes === this.bytes;
274297
}
275298

276299
get minValue(): bigint | number {
@@ -347,13 +370,6 @@ export function addQualifier<T extends CType>(t: T, qualifier?: TypeQualifier):
347370
return type;
348371
}
349372

350-
function withoutQualifiers<T extends CType>(t: T): T {
351-
if (Object.prototype.hasOwnProperty.call(t, "qualifier")) {
352-
return (t as CQualifiedType<T>)._base ?? t;
353-
}
354-
return t;
355-
}
356-
357373
export function getQualifier(t: CQualifiedType<CType>): TypeQualifier | undefined {
358374
return t?.qualifier;
359375
}

tests/other/errors.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import test from "ava";
2+
import {compile} from "../../src/compile";
3+
4+
test("basic type error", t => {
5+
t.throws(() => compile(`
6+
void f(int* ptr);
7+
8+
void main() {
9+
f(42);
10+
}
11+
`), {message: / int\* .* int /});
12+
});
13+
14+
test("pointer type error", t => {
15+
t.throws(() => compile(`
16+
void f(int** ptr);
17+
18+
void main() {
19+
signed x;
20+
f(&x);
21+
}
22+
`), {message: / int\*\* .* int\* /});
23+
});
24+
25+
test("struct type error", t => {
26+
t.throws(() => compile(`
27+
void f(struct {int x, y;} point);
28+
29+
void main() {
30+
union {int i; float f;} x;
31+
f(x);
32+
}
33+
`), {message: / struct {int x; int y;} .* union {int i; float f;} /});
34+
});

0 commit comments

Comments
 (0)