@@ -805,7 +805,7 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
805
805
806
806
if len (c .Flattened ) != 0 {
807
807
c .localVars = append (c .localVars , "$s" )
808
- prefix = prefix + " $s = 0;"
808
+ prefix = prefix + " $s = $s || 0;"
809
809
}
810
810
811
811
if c .HasDefer {
@@ -816,17 +816,27 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
816
816
}
817
817
}
818
818
819
+ localVarDefs := "" // Function-local var declaration at the top.
820
+
819
821
if len (c .Blocking ) != 0 {
820
- c .localVars = append (c .localVars , "$r" )
822
+ localVars := append ([]string {}, c .localVars ... )
823
+ // $r is sometimes used as a temporary variable to store blocking call result.
824
+ // $c indicates that a function is being resumed after a blocking call when set to true.
825
+ // $f is an object used to save and restore function context for blocking calls.
826
+ localVars = append (localVars , "$r" , "$c" , "$f" )
827
+ // If a blocking function is being resumed, initialize local variables from the saved context.
828
+ localVarDefs = fmt .Sprintf ("var {%s} = $restore(this, {%s});\n " , strings .Join (localVars , ", " ), strings .Join (params , ", " ))
829
+ // If the function gets blocked, save local variables for future.
830
+ saveContext := fmt .Sprintf ("$f = {...$f, $r, %s};" , strings .Join (c .localVars , ", " ))
831
+
821
832
if funcRef == "" {
822
833
funcRef = "$b"
823
834
functionName = " $b"
824
835
}
825
- var stores , loads string
826
- loads = fmt .Sprintf ("({%s} = $f); " , strings .Join (c .localVars , ", " ))
827
- stores = fmt .Sprintf ("$f = {...$f, %s};" , strings .Join (c .localVars , ", " ))
828
- prefix = prefix + " var $f, $c = false; if (this !== undefined && this.$blk !== undefined) { $f = this; $c = true; " + loads + "}"
829
- suffix = " if ($f === undefined) { $f = { $blk: " + funcRef + " }; } " + stores + "return $f;" + suffix
836
+ suffix = " if ($f === undefined) { $f = { $blk: " + funcRef + " }; } " + saveContext + "return $f;" + suffix
837
+ } else if len (c .localVars ) > 0 {
838
+ // Non-blocking functions simply declare local variables with no need for restore support.
839
+ localVarDefs = fmt .Sprintf ("var %s;\n " , strings .Join (c .localVars , ", " ))
830
840
}
831
841
832
842
if c .HasDefer {
@@ -863,8 +873,8 @@ func translateFunction(typ *ast.FuncType, recv *ast.Ident, body *ast.BlockStmt,
863
873
if suffix != "" {
864
874
bodyOutput = bodyOutput + strings .Repeat ("\t " , c .pkgCtx .indentation + 1 ) + "/* */" + suffix + "\n "
865
875
}
866
- if len ( c . localVars ) != 0 {
867
- bodyOutput = fmt . Sprintf ( "%svar %s; \n " , strings .Repeat ("\t " , c .pkgCtx .indentation + 1 ), strings . Join ( c . localVars , ", " )) + bodyOutput
876
+ if localVarDefs != "" {
877
+ bodyOutput = strings .Repeat ("\t " , c .pkgCtx .indentation + 1 ) + localVarDefs + bodyOutput
868
878
}
869
879
870
880
c .pkgCtx .escapingVars = prevEV
0 commit comments