diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index dfba18218434a271d88aee22aa319e438128611b..8d65f686c1b414aea8763f32e298db82c7ca911c 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -15,6 +15,7 @@ import * as ts from "typescript"; import { isBindingPattern } from "./base/util"; +import { CmdOptions } from "./cmdOptions"; import * as jshelpers from "./jshelpers"; import { Recorder } from "./recorder"; import { @@ -76,14 +77,13 @@ function addInnerArgs(node: ts.Node, scope: VariableScope, enableTypeRecord: boo addParameters(funcNode, scope, enableTypeRecord); } - if (scope.getUseArgs()) { + if (scope.getUseArgs() || CmdOptions.isDebugMode()) { if (ts.isArrowFunction(node)) { let parentVariableScope = scope.getParentVariableScope(); parentVariableScope.add("arguments", VarDeclarationKind.CONST, InitStatus.INITIALIZED); parentVariableScope.setUseArgs(true); - scope.setUseArgs(false); - } else { + } else if (scope.getUseArgs()){ if (!scope.findLocal("arguments")) { scope.add("arguments", VarDeclarationKind.CONST, InitStatus.INITIALIZED); } diff --git a/ts2panda/src/base/bcGenUtil.ts b/ts2panda/src/base/bcGenUtil.ts old mode 100755 new mode 100644 index 04dd4d9de377616e249bc7539649bb0bbbd5445c..3a841712106c3699266fe940552ce99ec81140c6 --- a/ts2panda/src/base/bcGenUtil.ts +++ b/ts2panda/src/base/bcGenUtil.ts @@ -57,12 +57,16 @@ import { EcmaLdsuperbyname, EcmaLdsuperbyvalue, EcmaNewlexenvdyn, + EcmaNewlexenvwithnamedyn, EcmaNewobjdynrange, EcmaPoplexenvdyn, EcmaReturnundefined, EcmaSetobjectwithproto, EcmaStarrayspread, + EcmaStclasstoglobalrecord, + EcmaStconsttoglobalrecord, EcmaStglobalvar, + EcmaStlettoglobalrecord, EcmaStlexvardyn, EcmaStmodulevar, EcmaStobjbyindex, @@ -70,8 +74,8 @@ import { EcmaStobjbyvalue, EcmaStownbyindex, EcmaStownbyname, - EcmaStownbyvalue, EcmaStownbynamewithnameset, + EcmaStownbyvalue, EcmaStownbyvaluewithnameset, EcmaStsuperbyname, EcmaStsuperbyvalue, @@ -97,9 +101,6 @@ import { LdaStr, MovDyn, StaDyn, - EcmaStclasstoglobalrecord, - EcmaStconsttoglobalrecord, - EcmaStlettoglobalrecord, VReg } from "../irnodes"; @@ -159,8 +160,11 @@ export function throwDeleteSuperProperty() { return new EcmaThrowdeletesuperproperty(); } -export function newLexicalEnv(numVars: number) { - return new EcmaNewlexenvdyn(new Imm(numVars)); +export function newLexicalEnv(numVars: number, scopeInfoIdx: number | undefined) { + if (scopeInfoIdx == undefined) { + return new EcmaNewlexenvdyn(new Imm(numVars)); + } + return new EcmaNewlexenvwithnamedyn(new Imm(numVars), new Imm(scopeInfoIdx)); } export function loadLexicalEnv() { @@ -418,14 +422,14 @@ export function createRegExpWithLiteral(pattern: string, flags: number) { return new EcmaCreateregexpwithliteral(pattern, new Imm(flags)); } -export function stLetToGlobalRecord (name: string) { +export function stLetToGlobalRecord(name: string) { return new EcmaStlettoglobalrecord(name); } -export function stConstToGlobalRecord (name: string) { +export function stConstToGlobalRecord(name: string) { return new EcmaStconsttoglobalrecord(name); } -export function stClassToGlobalRecord (name: string) { +export function stClassToGlobalRecord(name: string) { return new EcmaStclasstoglobalrecord(name); } \ No newline at end of file diff --git a/ts2panda/src/base/lexEnv.ts b/ts2panda/src/base/lexEnv.ts old mode 100755 new mode 100644 index 7a01c4bb58491ddfafae9cdaa29a4b166ce95ae6..c52373900c631a4319a79b37151209193043fcf2 --- a/ts2panda/src/base/lexEnv.ts +++ b/ts2panda/src/base/lexEnv.ts @@ -13,6 +13,7 @@ * limitations under the License. */ +import { CmdOptions } from "../cmdOptions"; import { IRNode } from "../irnodes"; @@ -28,9 +29,14 @@ import { CacheList, getVregisterCache } from "./vregisterCache"; function createLexEnv(pandaGen: PandaGen, scope: VariableScope): IRNode[] { let lexEnvVars = scope.getNumLexEnv(); let insns: IRNode[] = []; + let scopeInfoIdx: number | undefined = undefined; + let lexVarInfo = scope.getLexVarInfo(); + if (CmdOptions.isDebugMode()) { + scopeInfoIdx = pandaGen.appendScopeInfo(lexVarInfo); + } insns.push( - newLexicalEnv(lexEnvVars), + newLexicalEnv(lexEnvVars, scopeInfoIdx), storeAccumulator(getVregisterCache(pandaGen, CacheList.LexEnv)) ); diff --git a/ts2panda/src/base/vregisterCache.ts b/ts2panda/src/base/vregisterCache.ts index e4b3082acf658539c8f00ab43d2599c4d3189263..b9a4cb34d1c2ebf8a78900d0bf762ca227db1421 100755 --- a/ts2panda/src/base/vregisterCache.ts +++ b/ts2panda/src/base/vregisterCache.ts @@ -44,15 +44,8 @@ export enum CacheList { FUNC, // load function Infinity, undefined, - // Boolean, - // Number, - // String, - // BigInt, Symbol, - // RegExp, Null, - // Object, - // Function, Global, LexEnv, // Lex Env must come before True and False, because LexEnv depends on True and False True, @@ -64,15 +57,8 @@ let cacheExpandHandlers = new Map([ [CacheList.NaN, expandNaN], [CacheList.Infinity, expandInfinity], [CacheList.undefined, expandUndefined], - // [CacheList.Boolean, expandBoolean], - // [CacheList.Number, expandNumber], - // [CacheList.String, expandString], - // [CacheList.BigInt, expandBigInt], [CacheList.Symbol, expandSymbol], - // [CacheList.RegExp, expandRegExp], [CacheList.Null, expandNull], - // [CacheList.Object, expandObject], - // [CacheList.Function, expandFunction], [CacheList.Global, expandGlobal], [CacheList.LexEnv, expandLexEnv], [CacheList.True, expandTrue], diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index a8057b1eca6f3467d787544167fcda5fe9479204..d9619b894068cd474609184b3800b168457f13dc 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -147,7 +147,7 @@ export class Compiler { // spare v3 to save the currrent lexcial env getVregisterCache(this.pandaGen, CacheList.LexEnv); - this.envUnion.push(getVregisterCache(this.pandaGen, CacheList.LexEnv)) + this.envUnion.push(getVregisterCache(this.pandaGen, CacheList.LexEnv)); this.pandaGen.loadAccFromArgs(this.rootNode); } @@ -257,18 +257,25 @@ export class Compiler { private storeSpecialArg2LexEnv(arg: string) { let variableInfo = this.scope.find(arg); let v = variableInfo.v; + let pandaGen = this.pandaGen; - if (v && v.isLexVar) { - if ((arg === "this" || arg === "4newTarget") && variableInfo.scope instanceof FunctionScope) { - variableInfo.scope.setCallOpt(arg); - } - if (arg === "arguments" && variableInfo.scope instanceof FunctionScope) { - variableInfo.scope.setArgumentsOrRestargs(); + if (CmdOptions.isDebugMode()) { + variableInfo.scope!.setLexVar(v!, this.scope); + pandaGen.storeLexicalVar(this.rootNode, variableInfo.level, + (variableInfo.v).idxLex, + pandaGen.getVregForVariable(variableInfo.v)); + } else { + if (v && v.isLexVar) { + if ((arg === "this" || arg === "4newTarget") && variableInfo.scope instanceof FunctionScope) { + variableInfo.scope.setCallOpt(arg); + } + if (arg === "arguments" && variableInfo.scope instanceof FunctionScope) { + variableInfo.scope.setArgumentsOrRestargs(); + } + let vreg = "4funcObj" === arg ? getVregisterCache(pandaGen, CacheList.FUNC) : + pandaGen.getVregForVariable(variableInfo.v); + pandaGen.storeLexicalVar(this.rootNode, variableInfo.level, v.idxLex, vreg); } - let pandaGen = this.pandaGen; - let vreg = "4funcObj" === arg ? getVregisterCache(pandaGen, CacheList.FUNC) : pandaGen.getVregForVariable(variableInfo.v); - let slot = (variableInfo.v).idxLex; - pandaGen.storeLexicalVar(this.rootNode, variableInfo.level, slot, vreg); } } @@ -1499,7 +1506,7 @@ export class Compiler { } } - if (variable.scope && variable.level >= 0) { // inner most function will load outer env instead of new a lex env + 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) { diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index a40bbe240d0609df4d9f18ff8674f4b5fa60ae91..22c11bf961d0611a19fc2ca241460a9ed96ce6e3 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -63,7 +63,6 @@ import { loadAccumulatorString, loadGlobalVar, loadHomeObject, - loadLexicalEnv, loadLexicalVar, loadModuleVarByName, loadObjByIndex, @@ -103,13 +102,19 @@ import { tryLoadGlobalByName, tryStoreGlobalByName } from "./base/bcGenUtil"; -import { LiteralBuffer } from "./base/literal"; +import { + Literal, + LiteralBuffer, + LiteralTag +} from "./base/literal"; +import { BaseType } from "./base/typeSystem"; import { getParamLengthOfFunc } from "./base/util"; import { CacheList, getVregisterCache, VregisterCache } from "./base/vregisterCache"; +import { CmdOptions } from "./cmdOptions"; import { DebugInfo, NodeKind, @@ -178,11 +183,8 @@ import { VariableScope } from "./scope"; import { CatchTable } from "./statement/tryStatement"; -import { - Variable -} from "./variable"; -import { BaseType } from "./base/typeSystem"; import { TypeRecorder } from "./typeRecorder"; +import { Variable } from "./variable"; export class PandaGen { // @ts-ignore @@ -212,6 +214,25 @@ export class PandaGen { this.vregisterCache = new VregisterCache(); } + public appendScopeInfo(lexVarInfo: Map): number | undefined { + if (lexVarInfo.size == 0) { + return undefined; + } + + let scopeInfoIdx: number | undefined = undefined; + scopeInfoIdx = PandaGen.getLiteralArrayBuffer().length; + let scopeInfo = new LiteralBuffer(); + let scopeInfoLiterals = new Array(); + scopeInfoLiterals.push(new Literal(LiteralTag.INTEGER, lexVarInfo.size)); + lexVarInfo.forEach((slot: number, name: string) => { + scopeInfoLiterals.push(new Literal(LiteralTag.STRING, name)); + scopeInfoLiterals.push(new Literal(LiteralTag.INTEGER, slot)); + }); + scopeInfo.addLiterals(...scopeInfoLiterals); + PandaGen.getLiteralArrayBuffer().push(scopeInfo); + return scopeInfoIdx; + } + public setCallType(callType: number) { this.callType = callType; } @@ -219,7 +240,7 @@ export class PandaGen { public getCallType(): number { return this.callType; } - + static getExportedTypes() { if (TypeRecorder.getInstance()) { return TypeRecorder.getInstance().getExportedType(); @@ -414,21 +435,18 @@ export class PandaGen { } createLexEnv(node: ts.Node, env: VReg, scope: VariableScope | LoopScope) { - let needCreateNewEnv = scope.need2CreateLexEnv(); let numVars = scope.getNumLexEnv(); - if (needCreateNewEnv) { - this.add( - node, - newLexicalEnv(numVars), - storeAccumulator(env) - ) - } else { - this.add( - node, - loadLexicalEnv(), - storeAccumulator(env) - ) + let scopeInfoIdx: number | undefined = undefined; + let lexVarInfo = scope.getLexVarInfo(); + if (CmdOptions.isDebugMode()) { + scopeInfoIdx = this.appendScopeInfo(lexVarInfo); } + + this.add( + node, + newLexicalEnv(numVars, scopeInfoIdx), + storeAccumulator(env) + ) } popLexicalEnv(node: ts.Node) { diff --git a/ts2panda/src/scope.ts b/ts2panda/src/scope.ts index 79a59c04865401021aba827a91071010202e6d23..82d101fc3cca9feb557bbd644806a0b72b4397e8 100644 --- a/ts2panda/src/scope.ts +++ b/ts2panda/src/scope.ts @@ -259,6 +259,11 @@ export abstract class VariableScope extends Scope { protected node: ts.Node | undefined = undefined; protected parentVariableScope: VariableScope | null = null; protected childVariableScope: VariableScope[] = []; + protected lexVarInfo: Map = new Map(); + + getLexVarInfo() { + return this.lexVarInfo; + } getBindingNode() { return this.node; @@ -322,7 +327,8 @@ export abstract class VariableScope extends Scope { setLexVar(v: Variable, refScope: Scope) { if (!v.isLexVar) { - v.setLexVar(this); + let slot = v.setLexVar(this); + this.lexVarInfo.set(v.getName(), slot); } LOGD(this.debugTag, "VariableScope.setLexVar(" + v.idxLex + ")"); @@ -472,8 +478,8 @@ export class LocalScope extends Scope { } setLexVar(v: Variable, srcScope: Scope) { - let variableScope = this.getNearestLexicalScope(); - variableScope.setLexVar(v, srcScope); + let lexicalScope = this.getNearestLexicalScope(); + lexicalScope.setLexVar(v, srcScope); } @@ -511,13 +517,15 @@ export class LocalScope extends Scope { export class LoopScope extends LocalScope { protected startLexIdx: number = 0; protected needCreateLexEnv: boolean = false; + protected lexVarInfo: Map = new Map(); constructor(parent: Scope) { super(parent); } setLexVar(v: Variable, refScope: Scope) { if (!v.isLexVar) { - v.setLexVar(this); + let idxLex = v.setLexVar(this); + this.lexVarInfo.set(v.getName(), idxLex); } LOGD(this.debugTag, "LoopScope.setLexVar(" + v.idxLex + ")"); @@ -531,6 +539,10 @@ export class LoopScope extends LocalScope { } } + getLexVarInfo() { + return this.lexVarInfo; + } + need2CreateLexEnv(): boolean { return this.needCreateLexEnv; } diff --git a/ts2panda/src/statement/forOfStatement.ts b/ts2panda/src/statement/forOfStatement.ts index 31710788804e7aebe386846b697c81ff4a963bab..a6bbe5feb7cf94dd7a7ee33720c0b733911f5e83 100644 --- a/ts2panda/src/statement/forOfStatement.ts +++ b/ts2panda/src/statement/forOfStatement.ts @@ -64,7 +64,7 @@ export function compileForOfStatement(stmt: ts.ForOfStatement, compiler: Compile let object = pandaGen.getTemp(); let loopScope = compiler.getRecorder().getScopeOfNode(stmt); - let needCreateLoopEnv: boolean = loopScope.need2CreateLexEnv() ? true : false; + let needCreateLoopEnv: boolean = loopScope.need2CreateLexEnv(); let loopEnv = pandaGen.getTemp(); // for now Async is not handled. @@ -80,7 +80,8 @@ export function compileForOfStatement(stmt: ts.ForOfStatement, compiler: Compile LabelTarget.pushLabelTarget(labelTarget); LabelTarget.updateName2LabelTarget(stmt.parent, labelTarget); - let tryBuilderWithForOf = new TryBuilderWithForOf(compiler, pandaGen, stmt, doneReg, iterator, labelTarget, needCreateLoopEnv, needCreateLoopEnv ? loopEnv : undefined); + let tryBuilderWithForOf = new TryBuilderWithForOf(compiler, pandaGen, stmt, doneReg, iterator, labelTarget, + needCreateLoopEnv, needCreateLoopEnv ? loopEnv : undefined); compiler.constructTry(stmt, tryBuilderWithForOf, nextLabel); pandaGen.label(stmt, endLabel); diff --git a/ts2panda/src/statement/loopStatement.ts b/ts2panda/src/statement/loopStatement.ts index fc6b1247ae11b3acfc6137728e5dc897c5c83c58..e8cafffd82d42eb9e74f0d0b16f3ab180edc45a4 100644 --- a/ts2panda/src/statement/loopStatement.ts +++ b/ts2panda/src/statement/loopStatement.ts @@ -121,7 +121,7 @@ export function compileForStatement(stmt: ts.ForStatement, compiler: Compiler) { // determine if loopenv need to be created let loopScope = compiler.getRecorder().getScopeOfNode(stmt); - let needCreateLoopEnv: boolean = loopScope.need2CreateLexEnv() ? true : false; + let needCreateLoopEnv: boolean = loopScope.need2CreateLexEnv(); let loopEnv = pandaGen.getTemp(); let createEnvAtBegining: boolean = false; if (needCreateLoopEnv) { diff --git a/ts2panda/src/variable.ts b/ts2panda/src/variable.ts index 5563f6dfead7b6694efec3e7d6c0ad4f026be703..d06957d00bca95c7999b6d241f209db060f1d46f 100644 --- a/ts2panda/src/variable.ts +++ b/ts2panda/src/variable.ts @@ -78,6 +78,7 @@ export abstract class Variable { this.idxLex = scope.getLexVarIdx() scope.pendingCreateEnv(); this.isLexVar = true; + return this.idxLex; } clearLexVar() {