Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions src/codegen/expressions/access/member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export interface MemberAccessGeneratorContext {
name: string,
): { keys: string[]; types: string[]; tsTypes: string[] } | null;
getInterfaceDeclByName(name: string): InterfaceDeclaration | null;
getAllInterfaceFields(iface: InterfaceDeclaration): InterfaceField[];
isTypeAlias(name: string): boolean;
getTypeAliasCommonProperties(
name: string,
Expand Down Expand Up @@ -1090,13 +1091,12 @@ export class MemberAccessGenerator {
const keys: string[] = [];
const tsTypes: string[] = [];
const types: string[] = [];
if (interfaceDef.fields) {
for (let i = 0; i < interfaceDef.fields.length; i++) {
const f = interfaceDef.fields[i] as { name: string; type: string };
keys.push(stripOptional(f.name));
tsTypes.push(f.type);
types.push(tsTypeToLlvm(f.type));
}
const allFields = this.ctx.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const f = allFields[i] as { name: string; type: string };
keys.push(stripOptional(f.name));
tsTypes.push(f.type);
types.push(tsTypeToLlvm(f.type));
}
this.ctx.setJsonObjectMetadata(register, { keys, types, tsTypes, interfaceType: undefined });
} else if (lookupType === "Expression" || lookupType === "Statement") {
Expand Down Expand Up @@ -1626,10 +1626,11 @@ export class MemberAccessGenerator {

const interfaceDef = interfaceDefResult as InterfaceDeclaration;
if (!interfaceDef.fields) return null;
const allFields1628 = this.ctx.getAllInterfaceFields(interfaceDef);
let propIndex = -1;
let propTsType: string | undefined;
for (let i = 0; i < interfaceDef.fields.length; i++) {
const f = interfaceDef.fields[i] as { name: string; type: string };
for (let i = 0; i < allFields1628.length; i++) {
const f = allFields1628[i] as { name: string; type: string };
const fName = stripOptional(f.name);
if (fName === expr.property) {
propIndex = i;
Expand Down Expand Up @@ -2326,33 +2327,34 @@ export class MemberAccessGenerator {
if (!interfaceDefResult) return null;
const interfaceDef = interfaceDefResult as InterfaceDeclaration;
if (!interfaceDef.fields) return null;
const allFields2328 = this.ctx.getAllInterfaceFields(interfaceDef);

const objPtr = this.ctx.generateExpression(expr.object, params);

let propIndex = -1;
for (let i = 0; i < interfaceDef.fields.length; i++) {
const f = interfaceDef.fields[i] as { name: string; type: string };
for (let i = 0; i < allFields2328.length; i++) {
const f = allFields2328[i] as { name: string; type: string };
if (f.name === expr.property) {
propIndex = i;
break;
}
}
if (propIndex === -1) {
const fieldNames: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
for (let i = 0; i < allFields2328.length; i++) {
const field = allFields2328[i] as { name: string; type: string };
fieldNames.push(field.name);
}
throw new Error(
`Unknown property: ${expr.property} on interface ${valueType}. Available properties: ${fieldNames.join(", ")}`,
);
}

const propField = interfaceDef.fields[propIndex] as { name: string; type: string };
const propField = allFields2328[propIndex] as { name: string; type: string };
const propType = tsTypeToLlvm(propField.type);
const structTypes: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
for (let i = 0; i < allFields2328.length; i++) {
const field = allFields2328[i] as { name: string; type: string };
structTypes.push(tsTypeToLlvm(field.type));
}
const structType = `{ ${structTypes.join(", ")} }`;
Expand Down
5 changes: 5 additions & 0 deletions src/codegen/infrastructure/generator-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
MapNode,
SetNode,
InterfaceDeclaration,
InterfaceField,
FunctionNode,
ClassNode,
TypeAliasDeclaration,
Expand Down Expand Up @@ -627,6 +628,7 @@ export interface IGeneratorContext {
name: string,
): { keys: string[]; types: string[]; tsTypes: string[] } | null;
getInterfaceDeclByName(name: string): InterfaceDeclaration | null;
getAllInterfaceFields(iface: InterfaceDeclaration): InterfaceField[];
isTypeAlias(name: string): boolean;
getTypeAliasCommonProperties(
name: string,
Expand Down Expand Up @@ -1113,6 +1115,9 @@ export class MockGeneratorContext implements IGeneratorContext {
getInterfaceDeclByName(_name: string): InterfaceDeclaration | null {
return null;
}
getAllInterfaceFields(iface: InterfaceDeclaration): InterfaceField[] {
return iface.fields;
}
isTypeAlias(_name: string): boolean {
return false;
}
Expand Down
5 changes: 3 additions & 2 deletions src/codegen/infrastructure/interface-allocator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,9 @@ export class InterfaceAllocator {
const keys: string[] = [];
const types: string[] = [];
const tsTypes: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down
47 changes: 28 additions & 19 deletions src/codegen/infrastructure/variable-allocator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ export class VariableAllocator {
return ret;
}

private getAllInterfaceFields(iface: InterfaceDeclaration): InterfaceField[] {
public getAllInterfaceFields(iface: InterfaceDeclaration): InterfaceField[] {
return this.interfaceAlloc.getAllInterfaceFields(iface);
}

Expand Down Expand Up @@ -651,8 +651,9 @@ export class VariableAllocator {
const keys: string[] = [];
const types: string[] = [];
const tsTypes: string[] = [];
for (let fi = 0; fi < interfaceDef.fields.length; fi++) {
const fieldRaw = interfaceDef.fields[fi];
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let fi = 0; fi < allFields.length; fi++) {
const fieldRaw = allFields[fi];
if (!fieldRaw) continue;
const field = fieldRaw as { name: string; type: string };
if (!field.name || !field.type) continue;
Expand Down Expand Up @@ -1012,8 +1013,9 @@ export class VariableAllocator {
} else {
const interfaceDefResult = this.getInterface(interfaceName);
const interfaceDef = interfaceDefResult as InterfaceDeclaration;
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down Expand Up @@ -1108,8 +1110,9 @@ export class VariableAllocator {
} else {
const interfaceDefResult = this.getInterface(interfaceName);
const interfaceDef = interfaceDefResult as InterfaceDeclaration;
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down Expand Up @@ -1153,8 +1156,9 @@ export class VariableAllocator {
const interfaceDefResult = this.getInterface(elementType);
if (interfaceDefResult) {
const interfaceDef = interfaceDefResult as InterfaceDeclaration;
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
elementKeys.push(stripOptional(field.name));
elementTypes.push(this.convertTsType(field.type));
elementTsTypes.push(field.type);
Expand Down Expand Up @@ -1264,8 +1268,9 @@ export class VariableAllocator {
const keys: string[] = [];
const types: string[] = [];
const tsTypes: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down Expand Up @@ -1656,8 +1661,9 @@ export class VariableAllocator {
const keys: string[] = [];
const tsTypes: string[] = [];
const types: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
tsTypes.push(field.type);
types.push(this.convertTsTypeJson(field.type));
Expand Down Expand Up @@ -1691,8 +1697,9 @@ export class VariableAllocator {
keys = [];
types = [];
tsTypes = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down Expand Up @@ -2252,8 +2259,9 @@ export class VariableAllocator {
const keys: string[] = [];
const types: string[] = [];
const tsTypes: string[] = [];
for (let fi = 0; fi < interfaceDef.fields.length; fi++) {
const field = interfaceDef.fields[fi] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let fi = 0; fi < allFields.length; fi++) {
const field = allFields[fi] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down Expand Up @@ -2652,8 +2660,9 @@ export class VariableAllocator {
const keys: string[] = [];
const types: string[] = [];
const tsTypes: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
types.push(this.convertTsType(field.type));
tsTypes.push(field.type);
Expand Down
9 changes: 7 additions & 2 deletions src/codegen/llvm-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,10 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
return null;
}

public getAllInterfaceFields(iface: InterfaceDeclaration): InterfaceField[] {
return this.varAllocator.getAllInterfaceFields(iface);
}

public isTypeAlias(name: string): boolean {
if (!this.ast || !this.ast.typeAliases) return false;
for (let i = 0; i < this.ast.typeAliases.length; i++) {
Expand Down Expand Up @@ -2228,8 +2232,9 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
const keys: string[] = [];
const tsTypes: string[] = [];
const types: string[] = [];
for (let i = 0; i < interfaceDef.fields.length; i++) {
const field = interfaceDef.fields[i] as { name: string; type: string };
const allFields = this.getAllInterfaceFields(interfaceDef);
for (let i = 0; i < allFields.length; i++) {
const field = allFields[i] as { name: string; type: string };
keys.push(stripOptional(field.name));
tsTypes.push(field.type);
types.push(this.tsTypeToLlvmJsonWithEnums(field.type));
Expand Down
5 changes: 3 additions & 2 deletions src/codegen/types/objects/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1442,8 +1442,9 @@ export class ClassGenerator {
const keys: string[] = [];
const types: string[] = [];
const tsTypes: string[] = [];
for (let fi = 0; fi < interfaceDef.fields.length; fi++) {
const f = interfaceDef.fields[fi] as { name: string; type: string };
const allFields = this.ctx.getAllInterfaceFields(interfaceDef);
for (let fi = 0; fi < allFields.length; fi++) {
const f = allFields[fi] as { name: string; type: string };
keys.push(stripOptional(f.name));
types.push(this.fieldTypeToLlvm(f.type));
tsTypes.push(f.type);
Expand Down
27 changes: 27 additions & 0 deletions tests/fixtures/interfaces/interface-extends.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
interface Base {
id: number;
name: string;
}

interface Extended extends Base {
extra: string;
}

function testInterfaceExtends(): void {
const obj: Extended = { id: 42, name: "Alice", extra: "bonus" };
if (obj.id !== 42) {
console.log("FAIL: id should be 42");
process.exit(1);
}
if (obj.name !== "Alice") {
console.log("FAIL: name should be Alice");
process.exit(1);
}
if (obj.extra !== "bonus") {
console.log("FAIL: extra should be bonus");
process.exit(1);
}
console.log("TEST_PASSED");
}

testInterfaceExtends();
Loading