Skip to content

Commit 044a9d5

Browse files
committed
compiles
1 parent 0c742fe commit 044a9d5

File tree

8 files changed

+274
-27
lines changed

8 files changed

+274
-27
lines changed

src/ast.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,10 @@ export abstract class Node {
10631063

10641064
// types
10651065

1066+
interface Comparable {
1067+
equals(other: Comparable): bool;
1068+
}
1069+
10661070
export abstract class TypeNode extends Node {
10671071
// kind varies
10681072

@@ -1099,6 +1103,15 @@ export abstract class TypeNode extends Node {
10991103
}
11001104
return false;
11011105
}
1106+
1107+
abstract equals(node: TypeNode): bool;
1108+
1109+
static arrayEquals(node: Comparable[] | null, other: Comparable[] | null): bool {
1110+
if (node == null && other == null) return true;
1111+
if (node == null || other == null) return false;
1112+
if (node.length != other.length) return false;
1113+
return node.map((value, i) => value.equals(other[i])).every(x => x);
1114+
}
11021115
}
11031116

11041117
/** Represents a type name. */
@@ -1109,6 +1122,13 @@ export class TypeName extends Node {
11091122
identifier: IdentifierExpression;
11101123
/** Next part of the type name or `null` if this is the last part. */
11111124
next: TypeName | null;
1125+
1126+
equals(node: TypeName): bool {
1127+
if (node.identifier.symbol !== this.identifier.symbol) return false;
1128+
if (node.next == null && this.next == null) return true;
1129+
if (node.next == null || this.next == null) return false;
1130+
return this.next.equals(node.next);
1131+
}
11121132
}
11131133

11141134
/** Represents a named type. */
@@ -1119,6 +1139,12 @@ export class NamedTypeNode extends TypeNode {
11191139
name: TypeName;
11201140
/** Type argument references. */
11211141
typeArguments: TypeNode[] | null;
1142+
1143+
equals(node: NamedTypeNode): bool {
1144+
if (!this.name.equals(node.name)) return false;
1145+
return TypeNode.arrayEquals(this.typeArguments, node.typeArguments);
1146+
1147+
}
11221148
}
11231149

11241150
/** Represents a function type. */
@@ -1131,6 +1157,18 @@ export class FunctionTypeNode extends TypeNode {
11311157
returnType: TypeNode;
11321158
/** Explicitly provided this type, if any. */
11331159
explicitThisType: NamedTypeNode | null; // can't be a function
1160+
1161+
equals(node: FunctionTypeNode): bool {
1162+
if (!TypeNode.arrayEquals(this.parameterTypes, node.parameterTypes)) return false;
1163+
if (!this.returnType.equals(node.returnType)) return false;
1164+
if ((this.explicitThisType == null && node.explicitThisType == null)) return true;
1165+
if (this.explicitThisType == null || node.explicitThisType == null) return false;
1166+
return true;
1167+
}
1168+
1169+
get parameterTypes(): TypeNode[] {
1170+
return this.parameters.map(param => param.type);
1171+
}
11341172
}
11351173

11361174
/** Represents a type parameter. */
@@ -1143,6 +1181,13 @@ export class TypeParameterNode extends Node {
11431181
extendsType: NamedTypeNode | null; // can't be a function
11441182
/** Default type if omitted, if any. */
11451183
defaultType: NamedTypeNode | null; // can't be a function
1184+
1185+
equals(node: TypeParameterNode): bool {
1186+
if (this.name != node.name) return false;
1187+
if ((this.extendsType == null && node.extendsType == null)) return true;
1188+
if (this.extendsType == null || node.extendsType == null) return false;
1189+
return true;
1190+
}
11461191
}
11471192

11481193
/** Represents the kind of a parameter. */

src/compiler.ts

Lines changed: 108 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ export class Compiler extends DiagnosticEmitter {
307307
runtimeFeatures: RuntimeFeatures = RuntimeFeatures.NONE;
308308
/** Expressions known to have skipped an autorelease. Usually function returns. */
309309
skippedAutoreleases: Set<ExpressionRef> = new Set();
310+
/** Classes that implement an interface */
311+
implementers: Class[] = [];
310312

311313
/** Compiles a {@link Program} to a {@link Module} using the specified options. */
312314
static compile(program: Program, options: Options | null = null): Module {
@@ -447,6 +449,10 @@ export class Compiler extends DiagnosticEmitter {
447449
// import memory if requested (default memory is named '0' by Binaryen)
448450
if (options.importMemory) module.addMemoryImport("0", "env", "memory", isSharedMemory);
449451

452+
// set up virtual table
453+
this.compileVirtualTable();
454+
455+
450456
// set up function table
451457
var functionTable = this.functionTable;
452458
module.setFunctionTable(functionTable.length, 0xffffffff, functionTable);
@@ -459,6 +465,7 @@ export class Compiler extends DiagnosticEmitter {
459465
for (let file of this.program.filesByName.values()) {
460466
if (file.source.sourceKind == SourceKind.USER_ENTRY) this.ensureModuleExports(file);
461467
}
468+
console.log(functionTable.join(",\n"));
462469
return module;
463470
}
464471

@@ -1305,7 +1312,58 @@ export class Compiler extends DiagnosticEmitter {
13051312
typesToNativeTypes(instance.additionalLocals),
13061313
flatten(module, stmts, instance.signature.returnType.toNativeType())
13071314
);
1315+
// Virtual Methods
1316+
} else if (instance.is( CommonFlags.VIRTUAL)) {
1317+
let func: Function = instance;
1318+
let signature = func.signature;
1319+
let typeRef = this.ensureFunctionType(
1320+
signature.parameterTypes,
1321+
signature.returnType,
1322+
signature.thisType
1323+
);
1324+
let loadMethodID = module.i32(signature.id);
1325+
// let target = this.compiler.program.instancesByName("virtual");
1326+
let loadClass = module.load(
1327+
4,
1328+
false,
1329+
module.binary(
1330+
BinaryOp.SubI32,
1331+
module.local_get(0, NativeType.I32),
1332+
module.i32(8)
1333+
),
1334+
NativeType.I32
1335+
);
1336+
let callVirtual = module.call(
1337+
"~lib/virtual",
1338+
[loadMethodID, loadClass],
1339+
NativeType.I32
1340+
);
1341+
// module.removeFunction(member.internalName);
13081342

1343+
let callIndirect = module.call_indirect(
1344+
callVirtual,
1345+
func.localsByIndex.map<number>(local =>
1346+
module.local_get(local.index, local.type.toNativeType())
1347+
),
1348+
1349+
Signature.makeSignatureString(
1350+
func.signature.parameterTypes,
1351+
func.signature.returnType,
1352+
func.signature.thisType
1353+
)
1354+
);
1355+
1356+
let body = module.block(
1357+
null,
1358+
[callIndirect],
1359+
func.signature.returnType.toNativeType()
1360+
);
1361+
1362+
funcRef = module.addFunction(instance.internalName,
1363+
typeRef,
1364+
null,
1365+
body
1366+
);
13091367
// imported function
13101368
} else {
13111369
if (!instance.is(CommonFlags.AMBIENT)) {
@@ -1314,18 +1372,21 @@ export class Compiler extends DiagnosticEmitter {
13141372
instance.identifierNode.range
13151373
);
13161374
}
1317-
1375+
13181376
instance.set(CommonFlags.MODULE_IMPORT);
13191377
mangleImportName(instance, instance.declaration); // TODO: check for duplicates
1320-
1378+
13211379
// create the import
13221380
module.addFunctionImport(
13231381
instance.internalName,
13241382
mangleImportName_moduleName,
13251383
mangleImportName_elementName,
13261384
typeRef
1327-
);
1328-
funcRef = module.getFunction(instance.internalName);
1385+
);
1386+
}
1387+
funcRef = module.getFunction(instance.internalName);
1388+
if (instance.prototype.isBound && (<Class>instance.parent).prototype.implementsNodes) {
1389+
this.ensureFunctionTableEntry(instance);
13291390
}
13301391

13311392
instance.finalize(module, funcRef);
@@ -1436,6 +1497,9 @@ export class Compiler extends DiagnosticEmitter {
14361497
}
14371498
}
14381499
}
1500+
if (instance.prototype.implementsNodes) {
1501+
this.implementers.push(instance);
1502+
}
14391503
return true;
14401504
}
14411505

@@ -1445,11 +1509,11 @@ export class Compiler extends DiagnosticEmitter {
14451509
contextualTypeArguments: Map<string,Type> | null = null,
14461510
alternativeReportNode: Node | null = null
14471511
): void {
1448-
// TODO
1449-
this.error(
1450-
DiagnosticCode.Operation_not_supported,
1451-
declaration.range
1452-
);
1512+
// TODO Compile functions to use
1513+
// this.error(
1514+
// DiagnosticCode.Operation_not_supported,
1515+
// declaration.range
1516+
// );
14531517
}
14541518

14551519
// === Memory ===================================================================================
@@ -6196,6 +6260,11 @@ export class Compiler extends DiagnosticEmitter {
61966260
}
61976261
var parameterTypes = signature.parameterTypes;
61986262
for (let i = 0; i < numArguments; ++i, ++index) {
6263+
if (parameterTypes[i].is(TypeFlags.REFERENCE)){
6264+
6265+
}
6266+
let arg_type = this.resolver.resolveExpression(argumentExpressions[i], this.currentFlow);
6267+
61996268
operands[index] = this.compileExpression(argumentExpressions[i], parameterTypes[i],
62006269
Constraints.CONV_IMPLICIT
62016270
);
@@ -9117,6 +9186,35 @@ export class Compiler extends DiagnosticEmitter {
91179186
return module.block(label, conditions, NativeType.I32);
91189187
}
91199188

9189+
compileVirtualTable(): void {
9190+
const interfaces = this.program.interfaces;
9191+
const implementers: ClassPrototype[] = this.program.queuedImplements;
9192+
const program: Program = this.program;
9193+
const getFunc = (funcP: FunctionPrototype): Function => {
9194+
if (!program.instancesByName.has(funcP.internalName)) {
9195+
this.compileElement(funcP);
9196+
}
9197+
return <Function> program.instancesByName.get(funcP.internalName)!;
9198+
};
9199+
const methods: Function[] = [];
9200+
debugger;
9201+
// for (const _class of implementers) {
9202+
// methods.concat(_class.instanceMethods.map(getFunc)
9203+
// .filter(func => {
9204+
// return interfaces.some(_interface => {
9205+
// return _interface.prototype.instanceMethods.map(getFunc)
9206+
// .some(ifunc => func.signature.id == ifunc.signature.id )
9207+
// })
9208+
// }))
9209+
// }
9210+
const relooper = this.module.createRelooper();
9211+
var typeRef = this.ensureFunctionType([Type.u32, Type.u32], Type.u32, null);
9212+
9213+
9214+
// let body = this.module.
9215+
// this.module.addFunction("~lib/_virtual", typeRef, null, );
9216+
9217+
}
91209218
}
91219219

91229220
// helpers
@@ -9197,3 +9295,4 @@ export function flatten(module: Module, stmts: ExpressionRef[], type: NativeType
91979295
: type
91989296
);
91999297
}
9298+

0 commit comments

Comments
 (0)