@@ -162,12 +162,13 @@ function Compiler:compile(ast)
162162 self .upvaluesGcFunctionVar = self .scope :addVariable ();
163163 self .freeUpvalueFunc = self .scope :addVariable ();
164164
165-
166- self .createClosureVar = self .scope :addVariable ();
165+ self . createClosureVars = {};
166+ self .createVarargClosureVar = self .scope :addVariable ();
167167 local createClosureScope = Scope :new (self .scope );
168168 local createClosurePosArg = createClosureScope :addVariable ();
169169 local createClosureUpvalsArg = createClosureScope :addVariable ();
170170 local createClosureProxyObject = createClosureScope :addVariable ();
171+ local createClosureFuncVar = createClosureScope :addVariable ();
171172
172173 local createClosureSubScope = Scope :new (createClosureScope );
173174
@@ -190,16 +191,16 @@ function Compiler:compile(ast)
190191 return uid ;
191192 end
192193
193- -- Invoke Compiler
194- self :compileTopNode (ast );
195-
196194 -- Reference to Higher Scopes
197195 createClosureSubScope :addReferenceToHigherScope (self .scope , self .containerFuncVar );
198196 createClosureSubScope :addReferenceToHigherScope (createClosureScope , createClosurePosArg )
199197 createClosureSubScope :addReferenceToHigherScope (createClosureScope , createClosureUpvalsArg , 1 )
200198 createClosureScope :addReferenceToHigherScope (self .scope , self .upvaluesProxyFunctionVar )
201199 createClosureSubScope :addReferenceToHigherScope (createClosureScope , createClosureProxyObject );
202200
201+ -- Invoke Compiler
202+ self :compileTopNode (ast );
203+
203204 local functionNodeAssignments = {
204205 {
205206 var = Ast .AssignmentVariable (self .scope , self .containerFuncVar ),
@@ -210,7 +211,7 @@ function Compiler:compile(ast)
210211 Ast .VariableExpression (self .containerFuncScope , self .detectGcCollectVar )
211212 }, self :emitContainerFuncBody ());
212213 }, {
213- var = Ast .AssignmentVariable (self .scope , self .createClosureVar ),
214+ var = Ast .AssignmentVariable (self .scope , self .createVarargClosureVar ),
214215 val = Ast .FunctionLiteralExpression ({
215216 Ast .VariableExpression (createClosureScope , createClosurePosArg ),
216217 Ast .VariableExpression (createClosureScope , createClosureUpvalsArg ),
@@ -223,7 +224,7 @@ function Compiler:compile(ast)
223224 Ast .VariableExpression (createClosureScope , createClosureUpvalsArg )
224225 })
225226 }),
226- Ast .ReturnStatement {
227+ Ast .LocalVariableDeclaration ( createClosureScope , { createClosureFuncVar }, {
227228 Ast .FunctionLiteralExpression ({
228229 Ast .VarargExpression ();
229230 },
@@ -238,7 +239,8 @@ function Compiler:compile(ast)
238239 }
239240 }, createClosureSubScope )
240241 );
241- }
242+ });
243+ Ast .ReturnStatement {Ast .VariableExpression (createClosureScope , createClosureFuncVar )};
242244 }, createClosureScope )
243245 );
244246 }, {
@@ -262,9 +264,25 @@ function Compiler:compile(ast)
262264 }, {
263265 var = Ast .AssignmentVariable (self .scope , self .freeUpvalueFunc ),
264266 val = self :createFreeUpvalueFunc (),
265- }
267+ },
266268 }
267269
270+ local tbl = {
271+ Ast .VariableExpression (self .scope , self .containerFuncVar ),
272+ Ast .VariableExpression (self .scope , self .createVarargClosureVar ),
273+ Ast .VariableExpression (self .scope , self .upvaluesTable ),
274+ Ast .VariableExpression (self .scope , self .upvaluesReferenceCountsTable ),
275+ Ast .VariableExpression (self .scope , self .allocUpvalFunction ),
276+ Ast .VariableExpression (self .scope , self .currentUpvalId ),
277+ Ast .VariableExpression (self .scope , self .upvaluesProxyFunctionVar ),
278+ Ast .VariableExpression (self .scope , self .upvaluesGcFunctionVar ),
279+ Ast .VariableExpression (self .scope , self .freeUpvalueFunc ),
280+ };
281+ for i , entry in pairs (self .createClosureVars ) do
282+ table.insert (functionNodeAssignments , entry );
283+ table.insert (tbl , Ast .VariableExpression (entry .var .scope , entry .var .id ));
284+ end
285+
268286 util .shuffle (functionNodeAssignments );
269287 local assignmentStatLhs , assignmentStatRhs = {}, {};
270288 for i , v in ipairs (functionNodeAssignments ) do
@@ -281,21 +299,11 @@ function Compiler:compile(ast)
281299 Ast .VariableExpression (self .scope , self .getmetatableVar ),
282300 Ast .VariableExpression (self .scope , self .selectVar ),
283301 Ast .VariableExpression (self .scope , argVar ),
284- unpack (util .shuffle ({
285- Ast .VariableExpression (self .scope , self .containerFuncVar ),
286- Ast .VariableExpression (self .scope , self .createClosureVar ),
287- Ast .VariableExpression (self .scope , self .upvaluesTable ),
288- Ast .VariableExpression (self .scope , self .upvaluesReferenceCountsTable ),
289- Ast .VariableExpression (self .scope , self .allocUpvalFunction ),
290- Ast .VariableExpression (self .scope , self .currentUpvalId ),
291- Ast .VariableExpression (self .scope , self .upvaluesProxyFunctionVar ),
292- Ast .VariableExpression (self .scope , self .upvaluesGcFunctionVar ),
293- Ast .VariableExpression (self .scope , self .freeUpvalueFunc )
294- }))
302+ unpack (util .shuffle (tbl ))
295303 }, Ast .Block ({
296304 Ast .AssignmentStatement (assignmentStatLhs , assignmentStatRhs );
297305 Ast .ReturnStatement {
298- Ast .FunctionCallExpression (Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .createClosureVar ), {
306+ Ast .FunctionCallExpression (Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .createVarargClosureVar ), {
299307 Ast .NumberExpression (self .startBlockId );
300308 Ast .TableConstructorExpression (upvalEntries );
301309 }), {Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .unpackVar ), {Ast .VariableExpression (self .scope , argVar )})});
@@ -317,6 +325,69 @@ function Compiler:compile(ast)
317325 }, psc ), newGlobalScope );
318326end
319327
328+ function Compiler :getCreateClosureVar (argCount )
329+ if not self .createClosureVars [argCount ] then
330+ local var = Ast .AssignmentVariable (self .scope , self .scope :addVariable ());
331+ local createClosureScope = Scope :new (self .scope );
332+ local createClosureSubScope = Scope :new (createClosureScope );
333+
334+ local createClosurePosArg = createClosureScope :addVariable ();
335+ local createClosureUpvalsArg = createClosureScope :addVariable ();
336+ local createClosureProxyObject = createClosureScope :addVariable ();
337+ local createClosureFuncVar = createClosureScope :addVariable ();
338+
339+ createClosureSubScope :addReferenceToHigherScope (self .scope , self .containerFuncVar );
340+ createClosureSubScope :addReferenceToHigherScope (createClosureScope , createClosurePosArg )
341+ createClosureSubScope :addReferenceToHigherScope (createClosureScope , createClosureUpvalsArg , 1 )
342+ createClosureScope :addReferenceToHigherScope (self .scope , self .upvaluesProxyFunctionVar )
343+ createClosureSubScope :addReferenceToHigherScope (createClosureScope , createClosureProxyObject );
344+
345+ local argsTb , argsTb2 = {}, {};
346+ for i = 1 , argCount do
347+ local arg = createClosureSubScope :addVariable ()
348+ argsTb [i ] = Ast .VariableExpression (createClosureSubScope , arg );
349+ argsTb2 [i ] = Ast .TableEntry (Ast .VariableExpression (createClosureSubScope , arg ));
350+ end
351+
352+ local val = Ast .FunctionLiteralExpression ({
353+ Ast .VariableExpression (createClosureScope , createClosurePosArg ),
354+ Ast .VariableExpression (createClosureScope , createClosureUpvalsArg ),
355+ }, Ast .Block ({
356+ Ast .LocalVariableDeclaration (createClosureScope , {
357+ createClosureProxyObject
358+ }, {
359+ Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .upvaluesProxyFunctionVar ), {
360+ Ast .VariableExpression (createClosureScope , createClosureUpvalsArg )
361+ })
362+ }),
363+ Ast .LocalVariableDeclaration (createClosureScope , {createClosureFuncVar },{
364+ Ast .FunctionLiteralExpression (argsTb ,
365+ Ast .Block ({
366+ Ast .ReturnStatement {
367+ Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .containerFuncVar ), {
368+ Ast .VariableExpression (createClosureScope , createClosurePosArg ),
369+ Ast .TableConstructorExpression (argsTb2 ),
370+ Ast .VariableExpression (createClosureScope , createClosureUpvalsArg ), -- Upvalues
371+ Ast .VariableExpression (createClosureScope , createClosureProxyObject )
372+ })
373+ }
374+ }, createClosureSubScope )
375+ );
376+ });
377+ Ast .ReturnStatement {Ast .VariableExpression (createClosureScope , createClosureFuncVar )}
378+ }, createClosureScope )
379+ );
380+ self .createClosureVars [argCount ] = {
381+ var = var ,
382+ val = val ,
383+ }
384+ end
385+
386+
387+ local var = self .createClosureVars [argCount ].var ;
388+ return var .scope , var .id ;
389+ end
390+
320391function Compiler :pushRegisterUsageInfo ()
321392 table.insert (self .registerUsageStack , {
322393 usedRegisters = self .usedRegisters ;
@@ -1025,11 +1096,23 @@ function Compiler:compileFunction(node, funcDepth)
10251096
10261097 local retReg = self :allocRegister (false );
10271098
1028- scope :addReferenceToHigherScope (self .scope , self .createClosureVar );
1029- local retrieveExpression = Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .createClosureVar ), {
1030- Ast .NumberExpression (block .id ),
1031- Ast .TableConstructorExpression (upvalueExpressions )
1032- });
1099+ local isVarargFunction = # node .args > 0 and node .args [# node .args ].kind == AstKind .VarargExpression ;
1100+
1101+ local retrieveExpression
1102+ if isVarargFunction then
1103+ scope :addReferenceToHigherScope (self .scope , self .createVarargClosureVar );
1104+ retrieveExpression = Ast .FunctionCallExpression (Ast .VariableExpression (self .scope , self .createVarargClosureVar ), {
1105+ Ast .NumberExpression (block .id ),
1106+ Ast .TableConstructorExpression (upvalueExpressions )
1107+ });
1108+ else
1109+ local varScope , var = self :getCreateClosureVar (# node .args + math.random (0 , 5 ));
1110+ scope :addReferenceToHigherScope (varScope , var );
1111+ retrieveExpression = Ast .FunctionCallExpression (Ast .VariableExpression (varScope , var ), {
1112+ Ast .NumberExpression (block .id ),
1113+ Ast .TableConstructorExpression (upvalueExpressions )
1114+ });
1115+ end
10331116
10341117 self :addStatement (self :setRegister (scope , retReg , retrieveExpression ), {retReg }, usedRegs , false );
10351118 return retReg ;
0 commit comments