Skip to content

Commit 9c1c3da

Browse files
committed
temp
1 parent 1b8c510 commit 9c1c3da

File tree

5 files changed

+139
-108
lines changed

5 files changed

+139
-108
lines changed

src/compiler.ts

Lines changed: 76 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -3465,16 +3465,7 @@ export class Compiler extends DiagnosticEmitter {
34653465
fromType = fromType.nonNullableType;
34663466
}
34673467
if(fromType.is(TypeFlags.CLOSURE)) {
3468-
return module.block(null, [
3469-
module.store(
3470-
1,
3471-
expr,
3472-
this.module.local_get(fromType.locals![0].index, this.options.nativeSizeType),
3473-
NativeType.I32,
3474-
4
3475-
),
3476-
expr
3477-
], NativeType.I32)
3468+
return module.block(null, [this.injectClosedLocals(expr, fromType), expr], NativeType.I32)
34783469
}
34793470
if (fromType.isAssignableTo(toType)) { // downcast or same
34803471
assert(fromType.kind == toType.kind);
@@ -6335,6 +6326,27 @@ export class Compiler extends DiagnosticEmitter {
63356326
}
63366327
}
63376328

6329+
private injectClosedLocals(
6330+
expr: ExpressionRef,
6331+
type: Type
6332+
): ExpressionRef {
6333+
var module = this.module;
6334+
var locals = type.locals!;
6335+
var exprs = new Array<ExpressionRef>();
6336+
for (let _values = Map_values(locals), i = 0, k = _values.length; i < k; ++i) {
6337+
let local = unchecked(_values[i]);
6338+
exprs.push(module.store(
6339+
local.type.byteSize,
6340+
expr,
6341+
this.module.local_get(local.index, NativeType.I32),
6342+
NativeType.I32,
6343+
(i + 1) * 4
6344+
))
6345+
}
6346+
//exprs.push(module.unreachable())
6347+
return module.block(null, exprs)
6348+
}
6349+
63386350
/** Compiles a call expression according to the specified context. */
63396351
private compileCallExpression(
63406352
/** Call expression to compile. */
@@ -6417,7 +6429,6 @@ export class Compiler extends DiagnosticEmitter {
64176429
// direct call: concrete function
64186430
case ElementKind.FUNCTION_PROTOTYPE: {
64196431
let functionPrototype = <FunctionPrototype>target;
6420-
64216432
// builtins handle present respectively omitted type arguments on their own
64226433
if (functionPrototype.hasDecorator(DecoratorFlags.BUILTIN)) {
64236434
return this.compileCallExpressionBuiltin(functionPrototype, expression, contextualType);
@@ -6442,23 +6453,20 @@ export class Compiler extends DiagnosticEmitter {
64426453
let local = <Local>target;
64436454
if(local.type.is(TypeFlags.CLOSURE)) {
64446455
signature = new Signature(this.program, [], Type.i32)
6445-
var closedLocals = local.type.locals!;
6446-
console.log(closedLocals)
6456+
flow.locals = local.type.locals!;
6457+
64476458
indexArg = module.block(null, [
6448-
module.store(
6449-
1,
6459+
this.injectClosedLocals(
64506460
this.module.local_get(local.index, this.options.nativeSizeType),
6451-
this.module.local_get(closedLocals[0].index, NativeType.I32),
6452-
NativeType.I32,
6453-
4
6461+
local.type
64546462
),
64556463
module.global_set(
64566464
BuiltinNames.global_closure,
64576465
this.module.local_get(local.index, NativeType.I32)
64586466
),
64596467
module.load(
6460-
1,
6461-
true,
6468+
4,
6469+
local.type.is(TypeFlags.SIGNED),
64626470
this.module.local_get(local.index, NativeType.I32),
64636471
NativeType.I32,
64646472
0
@@ -6489,7 +6497,7 @@ export class Compiler extends DiagnosticEmitter {
64896497
indexArg
64906498
),
64916499
module.load(
6492-
1,
6500+
4,
64936501
true,
64946502
indexArg,
64956503
NativeType.I32,
@@ -7715,81 +7723,6 @@ export class Compiler extends DiagnosticEmitter {
77157723
var instance: Function | null;
77167724
var contextualTypeArguments = makeMap(flow.contextualTypeArguments);
77177725

7718-
if(prototype.name.startsWith("anonymous")) {
7719-
console.log("compiling " + prototype.name + " as a closure")
7720-
let generatedClosureType = new Type(
7721-
TypeKind.U32,
7722-
TypeFlags.CLOSURE | TypeFlags.REFERENCE | TypeFlags.POINTER, //flags
7723-
64
7724-
)
7725-
7726-
this.currentType = generatedClosureType;
7727-
7728-
assert(!contextualSignature)
7729-
7730-
instance = this.resolver.resolveFunction(prototype, null, contextualTypeArguments);
7731-
if (!instance) return this.module.unreachable();
7732-
this.compileFunction(instance);
7733-
//this.currentType = instance.signature.type;
7734-
7735-
//create function
7736-
var index = this.ensureFunctionTableEntry(instance!); // reports
7737-
console.log("closure " + prototype.name + " was assigned func table entry " + index.toString())
7738-
7739-
var closedLocals = instance.closedLocals
7740-
7741-
7742-
var names = ["fn","scopeI32"];
7743-
var numNames = names.length;
7744-
var values = [
7745-
this.module.i32(index),
7746-
this.module.local_get(closedLocals[0].index, NativeType.I32)
7747-
];
7748-
var exprs = new Array<ExpressionRef>(numNames + 2);
7749-
var flow = this.currentFlow;
7750-
//var tempLocal = flow.getAutoreleaseLocal(generatedClosureType);
7751-
var tempLocal = flow.getTempLocal(generatedClosureType);
7752-
7753-
generatedClosureType.locals = closedLocals;
7754-
7755-
for (let i = 0, k = numNames; i < k; ++i) {
7756-
exprs[i + 1] = this.module.store( // TODO: handle setters as well
7757-
1,
7758-
this.module.local_get(tempLocal.index, this.options.nativeSizeType),
7759-
values[i],
7760-
NativeType.I32,
7761-
i * 4
7762-
);
7763-
}
7764-
//this.currentType = classReference.type.nonNullableType;
7765-
this.currentType = generatedClosureType;
7766-
7767-
// allocate a new instance first and assign 'this' to the temp. local
7768-
exprs[0] = this.module.local_set(
7769-
tempLocal.index,
7770-
this.module.call(this.program.allocInstance.internalName, [
7771-
this.module.i32(2),
7772-
this.module.i32(0)
7773-
], NativeType.I32)
7774-
);
7775-
7776-
//Set closure global
7777-
//exprs[exprs.length - 2] = this.module.global_set(
7778-
//BuiltinNames.global_closure,
7779-
//this.module.local_get(tempLocal.index, NativeType.I32)
7780-
//)
7781-
//exprs[exprs.length - 2] = this.module.global_set("GLOBAL_CLOSURE", this.module.i32(1))
7782-
7783-
// once all field values have been set, return 'this'
7784-
exprs[exprs.length - 1] = this.module.local_get(tempLocal.index, this.options.nativeSizeType);
7785-
7786-
return this.module.flatten(exprs, this.options.nativeSizeType);
7787-
7788-
//return index < 0
7789-
//? this.module.unreachable()
7790-
//: this.module.i32(index);
7791-
}
7792-
77937726
//compile according to context. this differs from a normal function in that omitted parameter
77947727
//and return types can be inferred and omitted arguments can be replaced with dummies.
77957728
if (contextualSignature) {
@@ -7900,9 +7833,51 @@ export class Compiler extends DiagnosticEmitter {
79007833
}
79017834

79027835
var index = this.ensureFunctionTableEntry(instance); // reports
7903-
return index < 0
7904-
? this.module.unreachable()
7905-
: this.module.i32(index);
7836+
console.log("function index" + index)
7837+
7838+
if(index < 0) return this.module.unreachable();
7839+
7840+
if(instance.closedLocals.size > 0) {
7841+
var members = Array<DeclarationStatement>(instance.closedLocals.size + 1);
7842+
members[0] = this.program.makeNativeMember("__functionPtr", "u32")
7843+
for (let _values = Map_values(instance.closedLocals), i = 0, k = _values.length; i < k; ++i) {
7844+
let local = unchecked(_values[i]);
7845+
members[i + 1] = this.program.makeNativeMember(local.name, "i32") //todo, support non-i32
7846+
}
7847+
7848+
var closureClassPrototype = this.program.makeNativeClassPrototype(
7849+
"closure|" + actualFunction.nextAnonymousId.toString(),
7850+
members
7851+
)!;
7852+
var closureClass = this.resolver.resolveClass(closureClassPrototype, null)!;
7853+
this.compileClass(closureClass);
7854+
//set the current type to be the generated type
7855+
this.currentType = closureClass.type.asClosure(instance.signature)//generatedClosureType;
7856+
//create local to hold closure
7857+
var tempLocal = flow.getTempLocal(this.currentType);
7858+
//copied closed locals into type
7859+
this.currentType.locals = instance.closedLocals;
7860+
7861+
return this.module.flatten([
7862+
this.module.local_set( //Allocate memory for the closure
7863+
tempLocal.index,
7864+
this.module.call(this.program.allocInstance.internalName, [
7865+
this.module.i32(closureClass.type.byteSize),
7866+
this.module.i32(closureClass.id)
7867+
], NativeType.I32)
7868+
),
7869+
this.module.store( //Store the function pointer at the first index
7870+
4,
7871+
this.module.local_get(tempLocal.index, this.options.nativeSizeType),
7872+
this.module.i32(index),
7873+
NativeType.I32,
7874+
0
7875+
),
7876+
this.module.local_get(tempLocal.index, this.options.nativeSizeType) //load the closure locals index
7877+
], this.options.nativeSizeType);
7878+
}
7879+
7880+
return this.module.i32(index);
79067881
}
79077882

79087883
/** Makes sure the enclosing source file of the specified expression has been compiled. */
@@ -8151,11 +8126,11 @@ export class Compiler extends DiagnosticEmitter {
81518126
let closedLocal = <ClosedLocal>target;
81528127

81538128
return module.load(
8154-
1,
8129+
4,
81558130
true,
81568131
this.module.global_get(BuiltinNames.global_closure, NativeType.I32),
81578132
NativeType.I32,
8158-
4
8133+
flow.actualFunction.closedLocals.size * 4
81598134
);
81608135
}
81618136
}

src/flow.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ export class Flow {
204204
inlineFunction: Function | null;
205205
/** The label we break to when encountering a return statement, when inlining. */
206206
inlineReturnLabel: string | null;
207+
locals: Map<string, Local> | null;
207208

208209
/** Creates the parent flow of the specified function. */
209210
static create(parentFunction: Function): Flow {
@@ -218,6 +219,7 @@ export class Flow {
218219
flow.localFlags = [];
219220
flow.inlineFunction = null;
220221
flow.inlineReturnLabel = null;
222+
flow.locals = null;
221223
return flow;
222224
}
223225

@@ -505,9 +507,6 @@ export class Flow {
505507

506508
/** Sets the specified flag or flags on the local at the specified index. */
507509
setLocalFlag(index: i32, flag: LocalFlags): void {
508-
if(flag == LocalFlags.RETAINED) {
509-
assert(false)
510-
}
511510
if (index < 0) return;
512511
var localFlags = this.localFlags;
513512
var flags = index < localFlags.length ? unchecked(localFlags[index]) : 0;

src/program.ts

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,47 @@ export class Program extends DiagnosticEmitter {
670670
);
671671
}
672672

673+
makeNativeMember(
674+
name: string,
675+
type: string
676+
): DeclarationStatement {
677+
return Node.createFieldDeclaration(
678+
Node.createIdentifierExpression(name, this.nativeSource.range), //name: IdentifierExpression,
679+
Node.createNamedType(
680+
Node.createSimpleTypeName(type, this.nativeSource.range), //name: TypeName,
681+
null,//typeArguments: TypeNode[] | null,
682+
false,//isNullable: bool,
683+
this.nativeSource.range,//range: Range
684+
), //type: TypeNode | null,
685+
null,//initializer: Expression | null,
686+
null,//decorators: DecoratorNode[] | null,
687+
CommonFlags.INSTANCE,//flags: CommonFlags,
688+
this.nativeSource.range//range: Range
689+
)
690+
}
691+
692+
makeNativeClassDeclaration(name: string, members: DeclarationStatement[]): ClassDeclaration {
693+
return Node.createClassDeclaration(
694+
Node.createIdentifierExpression(name, this.nativeSource.range), //identifier: IdentifierExpression,
695+
null,//typeParameters: TypeParameterNode[] | null,
696+
null,//extendsType: NamedTypeNode | null, // can't be a function
697+
null,//implementsTypes: NamedTypeNode[] | null, // can't be functions
698+
members,//members: DeclarationStatement[],
699+
null,//decorators: DecoratorNode[] | null,
700+
0,//flags: CommonFlags,
701+
this.nativeSource.range//range: Range
702+
)
703+
}
704+
705+
makeNativeClassPrototype(name: string, members: DeclarationStatement[]): ClassPrototype | null {
706+
return this.initializeClass(
707+
this.makeNativeClassDeclaration(name, members),
708+
this.nativeFile,
709+
[],
710+
[]
711+
)
712+
}
713+
673714
/** Gets the (possibly merged) program element linked to the specified declaration. */
674715
getElementByDeclaration(declaration: DeclarationStatement): DeclaredElement | null {
675716
var elementsByDeclaration = this.elementsByDeclaration;
@@ -950,6 +991,7 @@ export class Program extends DiagnosticEmitter {
950991
//this.closureInstance = this.requireClass("Closure");
951992
//assert(this.closureInstance.id == 3);
952993

994+
953995
// register classes backing basic types
954996
this.registerWrapperClass(Type.i8, CommonNames.I8);
955997
this.registerWrapperClass(Type.i16, CommonNames.I16);
@@ -2876,6 +2918,7 @@ export class ClosedLocal extends VariableLikeElement {
28762918
local,
28772919
<VariableLikeDeclarationStatement>local.declaration
28782920
);
2921+
this.type = local.type;
28792922
}
28802923
}
28812924

@@ -2995,7 +3038,7 @@ export class Function extends TypedElement {
29953038
localsByIndex: Local[] = [];
29963039
/** List of additional non-parameter locals. */
29973040
additionalLocals: Type[] = [];
2998-
closedLocals: Local[] = [];
3041+
closedLocals: Map<string, Local> = new Map();
29993042
/** Contextual type arguments. */
30003043
contextualTypeArguments: Map<string,Type> | null;
30013044
/** Default control flow. */
@@ -3104,7 +3147,7 @@ export class Function extends TypedElement {
31043147
var parentResult = this.parent.lookup(name);
31053148
if(parentResult && this.parent.kind == ElementKind.FUNCTION) {
31063149
let local = changetype<Local>(parentResult)
3107-
this.closedLocals.push(local)
3150+
this.closedLocals.set(local.name, local)
31083151
return local.close()
31093152
}
31103153
return parentResult;
@@ -3952,7 +3995,7 @@ export class Interface extends Class { // FIXME
39523995

39533996
/** Registers a concrete element with a program. */
39543997
function registerConcreteElement(program: Program, element: Element): void {
3955-
assert(!program.instancesByName.has(element.internalName));
3998+
//assert(!program.instancesByName.has(element.internalName));
39563999
program.instancesByName.set(element.internalName, element);
39574000
}
39584001

0 commit comments

Comments
 (0)