diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index a4027cacb97450e3d2eff5e76f4721372e53279d..2d4d3b050a10efb7ece63405f43cfa2d296edc5c 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -210,7 +210,7 @@ export class Compiler { } }); if (!hasAFChild) { - return ; + return; } this.storeSpecialArg2LexEnv("4newTarget"); this.storeSpecialArg2LexEnv("arguments"); @@ -226,12 +226,14 @@ export class Compiler { private storeSpecialArg2LexEnv(arg: string) { let variableInfo = this.scope.find(arg); + let enclosingFuncScope = this.scope.getNearestVariableScope(); + let isLeaf = enclosingFuncScope.getChildVariableScope().length == 0 ? true : false; let v = variableInfo.v; let pandaGen = this.pandaGen; if (CmdOptions.isDebugMode()) { variableInfo.scope!.setLexVar(v!, this.scope); - pandaGen.storeLexicalVar(this.rootNode, variableInfo.level, + pandaGen.storeLexicalVar(this.rootNode, isLeaf ? variableInfo.level - 1 : variableInfo.level, (variableInfo.v).idxLex, pandaGen.getVregForVariable(variableInfo.v)); } else { @@ -241,7 +243,8 @@ export class Compiler { } let vreg = "4funcObj" === arg ? getVregisterCache(pandaGen, CacheList.FUNC) : pandaGen.getVregForVariable(variableInfo.v); - pandaGen.storeLexicalVar(this.rootNode, variableInfo.level, v.idxLex, vreg); + pandaGen.storeLexicalVar(this.rootNode, isLeaf ? variableInfo.level - 1 : variableInfo.level, + v.idxLex, vreg); } } } @@ -1006,6 +1009,8 @@ export class Compiler { checkValidUseSuperBeforeSuper(this, node); let { scope, level, v } = this.scope.find("this"); + let enclosingFuncScope = this.scope.getNearestVariableScope(); + let isLeaf = enclosingFuncScope.getChildVariableScope().length == 0 ? true : false; if (!v) { throw new Error("\"this\" not found"); @@ -1028,7 +1033,7 @@ export class Compiler { } } CmdOptions.isWatchEvaluateExpressionMode() ? pandaGen.loadByNameViaDebugger(node, "this", CacheList.True) - : pandaGen.loadAccFromLexEnv(node, scope!, level, v); + : pandaGen.loadAccFromLexEnv(node, scope!, isLeaf ? level - 1 : level, v); } else { throw new Error("\"this\" must be a local variable"); } @@ -1427,7 +1432,9 @@ export class Compiler { if (v.isLexVar) { let slot = v.idxLex; - pandaGen.loadLexicalVar(node, level, slot); + let enclosingFuncScope = this.getCurrentScope().getNearestVariableScope(); + let isLeaf = enclosingFuncScope.getChildVariableScope().length == 0 ? true : false; + pandaGen.loadLexicalVar(node, isLeaf ? thisInfo.level - 1 : thisInfo.level, slot); pandaGen.storeAccumulator(node, res); } else { pandaGen.moveVreg(node, res, pandaGen.getVregForVariable(v)); @@ -1442,7 +1449,9 @@ export class Compiler { let slot = (thisInfo.v).idxLex; let value = pandaGen.getTemp(); pandaGen.storeAccumulator(node, value); - pandaGen.storeLexicalVar(node, thisInfo.level, slot, value); + let enclosingFuncScope = this.getCurrentScope().getNearestVariableScope(); + let isLeaf = enclosingFuncScope.getChildVariableScope().length == 0 ? true : false; + pandaGen.storeLexicalVar(node, isLeaf ? thisInfo.level - 1 : thisInfo.level, slot, value); pandaGen.freeTemps(value); } else { pandaGen.storeAccumulator(node, pandaGen.getVregForVariable(thisInfo.v)) @@ -1505,8 +1514,10 @@ export class Compiler { variable.scope.setLexVar(variable.v, this.scope); } } + let enclosingFuncScope = this.scope.getNearestVariableScope(); + let isLeaf = enclosingFuncScope.getChildVariableScope().length == 0 ? true : false; // storeAcc must after setLexVar, because next statement will emit bc intermediately - this.pandaGen.storeAccToLexEnv(node, variable.scope!, variable.level, variable.v, isDeclaration); + this.pandaGen.storeAccToLexEnv(node, variable.scope!, isLeaf ? variable.level - 1 : variable.level, variable.v, isDeclaration); } else if (variable.v instanceof GlobalVariable) { if (variable.v.isNone() && isStrictMode(node)) { this.pandaGen.tryStoreGlobalByName(node, variable.v.getName()); @@ -1560,6 +1571,7 @@ export class Compiler { if (variable.scope && variable.level >= 0) { // leaf function will load outer env instead of new a lex env let scope = this.scope; let needSetLexVar: boolean = false; + while (scope != variable.scope) { if (scope instanceof VariableScope) { needSetLexVar = true; @@ -1573,7 +1585,9 @@ export class Compiler { } } - this.pandaGen.loadAccFromLexEnv(node, variable.scope!, variable.level, (variable.v)); + let enclosingFuncScope = this.scope.getNearestVariableScope(); + let isLeaf = enclosingFuncScope.getChildVariableScope().length == 0 ? true : false; + this.pandaGen.loadAccFromLexEnv(node, variable.scope!, isLeaf ? variable.level - 1 : variable.level, (variable.v)); } else if (variable.v instanceof GlobalVariable) { if (variable.v.isNone()) { let parent = findOuterNodeOfParenthesis(node); diff --git a/ts2panda/src/scope.ts b/ts2panda/src/scope.ts index 637dc19b6cb07c071b68b62f40e3179a75d522ff..fc6efc55f7d7f55538ef345fde60af10f3a3c7e6 100644 --- a/ts2panda/src/scope.ts +++ b/ts2panda/src/scope.ts @@ -350,7 +350,14 @@ export abstract class VariableScope extends Scope { LOGD(this.debugTag, "VariableScope.setLexVar(" + v.idxLex + ")"); // set all chain to create env let scope: Scope | undefined = refScope; + let nearestRefVariableScope = refScope.getNearestVariableScope(); + let isLeaf = nearestRefVariableScope.getChildVariableScope().length == 0 ? true : false; while (scope && scope != this) { + if (scope == nearestRefVariableScope && isLeaf) { + scope = scope.getParent(); + continue; + } + if (scope instanceof VariableScope || (scope instanceof LoopScope && scope.need2CreateLexEnv())) { scope.pendingCreateEnv(); } @@ -536,7 +543,14 @@ export class LoopScope extends LocalScope { LOGD(this.debugTag, "LoopScope.setLexVar(" + v.idxLex + ")"); let scope: Scope | undefined = refScope; + let nearestRefVariableScope = refScope.getNearestVariableScope(); + let isLeaf = nearestRefVariableScope.getChildVariableScope().length == 0 ? true : false; while (scope && scope != this) { + if (scope == nearestRefVariableScope && isLeaf) { + scope = scope.getParent(); + continue; + } + if (scope instanceof VariableScope || (scope instanceof LoopScope && scope.need2CreateLexEnv())) { scope.pendingCreateEnv(); } diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index 3b4368dbcff4b822021647b93817a9f5f4350f81..e50ac1399fbeba172244fc4b57d07e7be89fa280 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -407,6 +407,8 @@ function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { let recorder = compiler.getRecorder(); let pandaGen = compiler.getPandaGen(); let nearestFunc = jshelpers.getContainingFunctionDeclaration(node); + let nearestFuncScope = compiler.getCurrentScope().getNearestVariableScope(); + let isLeaf = nearestFuncScope.getChildVariableScope().length == 0 ? true : false; if (!nearestFunc) { return; } @@ -433,7 +435,7 @@ function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { let funcObj = outerFuncScope.findLocal("4funcObj"); outerFuncScope.setLexVar(funcObj, outerFuncScope); let slot = funcObj.idxLex; - pandaGen.loadLexicalVar(node, level, slot); + pandaGen.loadLexicalVar(node, isLeaf ? level - 1 : level, slot); } }