@@ -3465,16 +3465,7 @@ export class Compiler extends DiagnosticEmitter {
3465
3465
fromType = fromType . nonNullableType ;
3466
3466
}
3467
3467
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 )
3478
3469
}
3479
3470
if ( fromType . isAssignableTo ( toType ) ) { // downcast or same
3480
3471
assert ( fromType . kind == toType . kind ) ;
@@ -6335,6 +6326,27 @@ export class Compiler extends DiagnosticEmitter {
6335
6326
}
6336
6327
}
6337
6328
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
+
6338
6350
/** Compiles a call expression according to the specified context. */
6339
6351
private compileCallExpression (
6340
6352
/** Call expression to compile. */
@@ -6417,7 +6429,6 @@ export class Compiler extends DiagnosticEmitter {
6417
6429
// direct call: concrete function
6418
6430
case ElementKind . FUNCTION_PROTOTYPE : {
6419
6431
let functionPrototype = < FunctionPrototype > target ;
6420
-
6421
6432
// builtins handle present respectively omitted type arguments on their own
6422
6433
if ( functionPrototype . hasDecorator ( DecoratorFlags . BUILTIN ) ) {
6423
6434
return this . compileCallExpressionBuiltin ( functionPrototype , expression , contextualType ) ;
@@ -6442,23 +6453,20 @@ export class Compiler extends DiagnosticEmitter {
6442
6453
let local = < Local > target ;
6443
6454
if ( local . type . is ( TypeFlags . CLOSURE ) ) {
6444
6455
signature = new Signature ( this . program , [ ] , Type . i32 )
6445
- var closedLocals = local . type . locals ! ;
6446
- console . log ( closedLocals )
6456
+ flow . locals = local . type . locals ! ;
6457
+
6447
6458
indexArg = module . block ( null , [
6448
- module . store (
6449
- 1 ,
6459
+ this . injectClosedLocals (
6450
6460
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
6454
6462
) ,
6455
6463
module . global_set (
6456
6464
BuiltinNames . global_closure ,
6457
6465
this . module . local_get ( local . index , NativeType . I32 )
6458
6466
) ,
6459
6467
module . load (
6460
- 1 ,
6461
- true ,
6468
+ 4 ,
6469
+ local . type . is ( TypeFlags . SIGNED ) ,
6462
6470
this . module . local_get ( local . index , NativeType . I32 ) ,
6463
6471
NativeType . I32 ,
6464
6472
0
@@ -6489,7 +6497,7 @@ export class Compiler extends DiagnosticEmitter {
6489
6497
indexArg
6490
6498
) ,
6491
6499
module . load (
6492
- 1 ,
6500
+ 4 ,
6493
6501
true ,
6494
6502
indexArg ,
6495
6503
NativeType . I32 ,
@@ -7715,81 +7723,6 @@ export class Compiler extends DiagnosticEmitter {
7715
7723
var instance : Function | null ;
7716
7724
var contextualTypeArguments = makeMap ( flow . contextualTypeArguments ) ;
7717
7725
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
-
7793
7726
//compile according to context. this differs from a normal function in that omitted parameter
7794
7727
//and return types can be inferred and omitted arguments can be replaced with dummies.
7795
7728
if ( contextualSignature ) {
@@ -7900,9 +7833,51 @@ export class Compiler extends DiagnosticEmitter {
7900
7833
}
7901
7834
7902
7835
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 ) ;
7906
7881
}
7907
7882
7908
7883
/** Makes sure the enclosing source file of the specified expression has been compiled. */
@@ -8151,11 +8126,11 @@ export class Compiler extends DiagnosticEmitter {
8151
8126
let closedLocal = < ClosedLocal > target ;
8152
8127
8153
8128
return module . load (
8154
- 1 ,
8129
+ 4 ,
8155
8130
true ,
8156
8131
this . module . global_get ( BuiltinNames . global_closure , NativeType . I32 ) ,
8157
8132
NativeType . I32 ,
8158
- 4
8133
+ flow . actualFunction . closedLocals . size * 4
8159
8134
) ;
8160
8135
}
8161
8136
}
0 commit comments