@@ -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 }
0 commit comments