diff --git a/testTs/instype/recordexport-expected.txt b/testTs/instype/recordexport-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..a4dc1e4491367ff96a814e4c0c918896a4a827a5 --- /dev/null +++ b/testTs/instype/recordexport-expected.txt @@ -0,0 +1,10 @@ +Handle types for function: hello +(instruction order, type): (-1, 101), +Handle types for function: #1#Calculator +(instruction order, type): (-2, 105), +Handle types for function: add +(instruction order, type): (-1, 103), +Handle types for function: minus +(instruction order, type): (-1, 104), +Handle types for function: func_main_0 +(instruction order, type): (8, 101), (10, 1), (12, 103), (14, 104), (16, 1), (18, 1), (20, 1), (22, 4), (27, 102), (59, 105), diff --git a/testTs/instype/recordexport.ts b/testTs/instype/recordexport.ts new file mode 100644 index 0000000000000000000000000000000000000000..5328134355b26623feed8a8e7b24c58730b8ca72 --- /dev/null +++ b/testTs/instype/recordexport.ts @@ -0,0 +1,29 @@ +export default function hello(str: string) { + return str; +} + +export var a: number = 1; +export let b: number = 2; +export const c: number = 3; +export let d: string = "world"; + +export class Calculator{} + +export function add(x: number, y: number) { + return x + y; +} + +export function minus(x: number, y: number) { + return x - y; +} + +export type A = number; +export interface B { + name: string; + ids: number[]; +} + +hello(d); +hello("test"); +let ret: A = minus(add(a, b), c); +let cal = new Calculator(); diff --git a/testTs/instype/recordimport-expected.txt b/testTs/instype/recordimport-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..5faeeb0a8e65b52a50e3754ed198f18d540cecab --- /dev/null +++ b/testTs/instype/recordimport-expected.txt @@ -0,0 +1,12 @@ +Handle types for function: hello +(instruction order, type): (-1, 101), +Handle types for function: #1#Calculator +(instruction order, type): (-2, 105), +Handle types for function: add +(instruction order, type): (-1, 103), +Handle types for function: minus +(instruction order, type): (-1, 104), +Handle types for function: func_main_0 +(instruction order, type): (8, 101), (10, 1), (12, 103), (14, 104), (16, 1), (18, 1), (20, 1), (22, 4), (27, 102), (59, 105), +Handle types for function: func_main_0 +(instruction order, type): (5, 101), (12, 105), (27, 107), (34, 102), (41, 103), (51, 104), (61, 106), (69, 106), diff --git a/testTs/instype/recordimport.ts b/testTs/instype/recordimport.ts new file mode 100644 index 0000000000000000000000000000000000000000..08dc666cfbb529c1faf2509a5514c4675b3e8d67 --- /dev/null +++ b/testTs/instype/recordimport.ts @@ -0,0 +1,8 @@ +import hello from "./recordexport" +import {a as x, b as y, c, d, Calculator, add} from "./recordexport" +import * as calculator from "./recordexport" +import {A, B} from "./recordexport" + +let greeting = hello(d); +let ret: A = calculator.minus(add(x, y), c); +let cal = new Calculator(); diff --git a/testTs/instype/recordthis-expected.txt b/testTs/instype/recordthis-expected.txt index fbc6352221170d523957ace40e9a9d9abc92ed7c..e50eb0cd9d2a78c382034ddc56348eb412f54675 100644 --- a/testTs/instype/recordthis-expected.txt +++ b/testTs/instype/recordthis-expected.txt @@ -19,4 +19,4 @@ Handle types for function: testwiththis Handle types for function: add (instruction order, type): (-1, 112), (9, 1), Handle types for function: func_main_0 -(instruction order, type): +(instruction order, type): (10, 112), (95, 101), diff --git a/testTs/run_testTs.py b/testTs/run_testTs.py index 1485329a4d7324fc84eae4ec5939be9d98afa771..ed167f235657a8de2e9bf15244a1d7b57db25efb 100755 --- a/testTs/run_testTs.py +++ b/testTs/run_testTs.py @@ -294,7 +294,8 @@ def test_instype(args): fail_list = [] for file in files: abc_file = os.path.abspath(os.path.join(outpath, '%s.abc' % os.path.splitext(os.path.basename(file))[0])) - cmd = ['node', '--expose-gc', ark_frontend_tool, os.path.abspath(file), '--display-typeinfo', '-o', abc_file]; + cmd = ['node', '--expose-gc', ark_frontend_tool, os.path.abspath(file), + '--modules', '--display-typeinfo', '-o', abc_file]; process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: out, err = process.communicate(timeout=10) diff --git a/ts2panda/src/addVariable2Scope.ts b/ts2panda/src/addVariable2Scope.ts index b3b0f87bbf5dbb5ab0269b94fa94a0e1b126bc4c..0f64f618bd98e704a544007959ff3287c266fc62 100644 --- a/ts2panda/src/addVariable2Scope.ts +++ b/ts2panda/src/addVariable2Scope.ts @@ -14,6 +14,7 @@ */ import * as ts from "typescript"; +import { PrimitiveType } from "./base/typeSystem"; import { isBindingPattern } from "./base/util"; import { CmdOptions } from "./cmdOptions"; import * as jshelpers from "./jshelpers"; @@ -44,6 +45,9 @@ import { function setVariableOrParameterType(node: ts.Node, v: Variable | undefined) { if (v) { let typeIndex = TypeRecorder.getInstance().tryGetVariable2Type(ts.getOriginalNode(node)); + if (typeIndex === PrimitiveType.ANY) { + typeIndex = TypeRecorder.getInstance().tryGetTypeIndex(ts.getOriginalNode(node)); + } v.setTypeIndex(typeIndex); } } diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index 72fc09ceb2a28722fac8a23699b5ce283e42a54d..29eea7514b10fb206bb0490c2f87422c3d6af368 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -739,8 +739,8 @@ export class Compiler { private compileExportAssignment(stmt: ts.ExportAssignment) { this.compileExpression(stmt.expression); - this.pandaGen.storeModuleVariable( - stmt, (this.pandaGen.getScope().findLocal("*default*")).getIndex()); + let defaultV: ModuleVariable = (this.pandaGen.getScope().findLocal("*default*")); + this.pandaGen.storeModuleVariable(stmt, defaultV); } compileCondition(expr: ts.Expression, ifFalseLabel: Label) { @@ -1473,7 +1473,7 @@ export class Compiler { let holeReg = this.pandaGen.getTemp(); let nameReg = this.pandaGen.getTemp(); this.pandaGen.storeAccumulator(node, valueReg); - this.pandaGen.loadModuleVariable(node, variable.v.getIndex(), true); + this.pandaGen.loadModuleVariable(node, variable.v, true); this.pandaGen.storeAccumulator(node, holeReg); this.pandaGen.loadAccumulatorString(node, variable.v.getName()); this.pandaGen.storeAccumulator(node, nameReg); @@ -1482,7 +1482,7 @@ export class Compiler { this.pandaGen.freeTemps(valueReg, holeReg, nameReg); } - this.pandaGen.storeModuleVariable(node, variable.v.getIndex()); + this.pandaGen.storeModuleVariable(node, variable.v); } else { throw new Error("invalid lhsRef to store"); } @@ -1514,7 +1514,7 @@ export class Compiler { } } else if (variable.v instanceof ModuleVariable) { let isLocal: boolean = variable.v.isExportVar() ? true : false; - this.pandaGen.loadModuleVariable(node, variable.v.getIndex(), isLocal); + this.pandaGen.loadModuleVariable(node, variable.v, isLocal); if ((variable.v.isLetOrConst() || variable.v.isClass()) && !variable.v.isInitialized()) { let valueReg = this.pandaGen.getTemp(); let nameReg = this.pandaGen.getTemp(); diff --git a/ts2panda/src/hoisting.ts b/ts2panda/src/hoisting.ts index 71c31e57580176fa208e89241fc374913c877e59..e544b95c25568d21b38e409e2c2fcc74426d9850 100644 --- a/ts2panda/src/hoisting.ts +++ b/ts2panda/src/hoisting.ts @@ -57,10 +57,10 @@ export function hoistVar(decl: VarDecl, scope: Scope, pandaGen: PandaGen) { pandaGen.loadAccumulator(decl.node, getVregisterCache(pandaGen, CacheList.undefined)); pandaGen.storeGlobalVar(decl.node, name); } else if (scope instanceof FunctionScope || scope instanceof ModuleScope) { - let v = scope.findLocal(name)!; + let v: ModuleVariable = (scope.findLocal(name)!); pandaGen.loadAccumulator(NodeKind.FirstNodeOfFunction, getVregisterCache(pandaGen, CacheList.undefined)); if (decl.isModule !== ModuleVarKind.NOT) { - pandaGen.storeModuleVariable(NodeKind.FirstNodeOfFunction, (v).getIndex()); + pandaGen.storeModuleVariable(NodeKind.FirstNodeOfFunction, v); } else { pandaGen.storeAccToLexEnv(NodeKind.FirstNodeOfFunction, scope, 0, v, true); } @@ -78,10 +78,10 @@ export function hoistFunction(decl: FuncDecl, scope: Scope, pandaGen: PandaGen, pandaGen.defineFunction(NodeKind.FirstNodeOfFunction, decl.node, internalName); pandaGen.storeGlobalVar(NodeKind.FirstNodeOfFunction, funcName); } else if ((scope instanceof FunctionScope) || (scope instanceof LocalScope) || (scope instanceof ModuleScope)) { - let v = scope.findLocal(funcName)!; + let v: ModuleVariable = (scope.findLocal(funcName)!); pandaGen.defineFunction(NodeKind.FirstNodeOfFunction, decl.node, internalName); if (decl.isModule !== ModuleVarKind.NOT) { - pandaGen.storeModuleVariable(NodeKind.FirstNodeOfFunction, (v).getIndex()); + pandaGen.storeModuleVariable(NodeKind.FirstNodeOfFunction, v); } else { pandaGen.storeAccToLexEnv(NodeKind.FirstNodeOfFunction, scope, 0, v, true); } diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 10669581180dda673f014dd7b9f47e3f7c350765..55d6ed1f4bb6cec4bdcb1bbddb660bcd47742192 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -186,7 +186,11 @@ import { } from "./scope"; import { CatchTable } from "./statement/tryStatement"; import { TypeRecorder } from "./typeRecorder"; -import { MandatoryArguments, Variable } from "./variable"; +import { + MandatoryArguments, + ModuleVariable, + Variable +} from "./variable"; import * as jshelpers from "./jshelpers"; import { CompilerDriver } from "./compilerDriver"; import { getLiteralKey } from "./base/util"; @@ -1249,16 +1253,28 @@ export class PandaGen { ) } - loadModuleVariable(node: ts.Node, index: number, isLocal: boolean) { + loadModuleVariable(node: ts.Node, v: ModuleVariable, isLocal: boolean) { + let index: number = v.getIndex(); + let typeIndex: number = v.getTypeIndex(); + // For local module variable, we bind type with storeModuleVariable instruction + // instead of loadLocalModuleVariable instruction to avoid duplicate recording when load multi times. + // For external module variable, we can only bind type with loadExternalModuleVariable instruction + // because there is no storeModuleVariable instruction of the corrsponding variable in the same file. if (isLocal) { this.add(node, loadLocalModuleVariable(index)); } else { - this.add(node, loadExternalModuleVariable(index)); + let ldModuleVarInst: IRNode = loadExternalModuleVariable(index); + this.setInstType(ldModuleVarInst, typeIndex); + this.add(node, ldModuleVarInst); } } - storeModuleVariable(node: ts.Node | NodeKind, index: number) { - this.add(node, storeModuleVariable(index)); + storeModuleVariable(node: ts.Node | NodeKind, v: ModuleVariable) { + let index: number = v.getIndex(); + let typeIndex: number = v.getTypeIndex(); + let stModuleVarInst: IRNode = storeModuleVariable(index); + this.setInstType(stModuleVarInst, typeIndex); + this.add(node, stModuleVarInst); } getModuleNamespace(node: ts.Node, moduleRequestIdx: number) { diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index dcd010e08d82f9e705c0a9c90ff817c0fb62a12e..e455b1a3aec5fefd714f375439a291a7115a1ca5 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -128,11 +128,12 @@ export function compileClassDeclaration(compiler: Compiler, stmt: ts.ClassLikeDe if (hasExportKeywordModifier(stmt)) { if (stmt.name) { let className = jshelpers.getTextOfIdentifierOrLiteral(stmt.name); - let v = pandaGen.getScope().findLocal(className); - (v).initialize(); - pandaGen.storeModuleVariable(stmt, (v).getIndex()); + let v: ModuleVariable = (pandaGen.getScope().findLocal(className)); + v.initialize(); + pandaGen.storeModuleVariable(stmt, v); } else if (hasDefaultKeywordModifier(stmt)) { - pandaGen.storeModuleVariable(stmt, (pandaGen.getScope().findLocal("*default*")).getIndex()); + let defaultV: ModuleVariable = (pandaGen.getScope().findLocal("*default*")); + pandaGen.storeModuleVariable(stmt, defaultV); } else { // throw SyntaxError in Recorder } @@ -145,7 +146,8 @@ export function compileClassDeclaration(compiler: Compiler, stmt: ts.ClassLikeDe let classInfo = classScope.find(className); (classInfo.v).initialize(); if (classInfo.v instanceof ModuleVariable) { - pandaGen.storeModuleVariable(stmt, (pandaGen.getScope().findLocal(className)).getIndex()); + let v: ModuleVariable = (pandaGen.getScope().findLocal(className)); + pandaGen.storeModuleVariable(stmt, v); } else { pandaGen.storeAccToLexEnv(stmt, classInfo.scope!, classInfo.level, classInfo.v!, true); } diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index 66c5afc095dd6e85007ad7372b27db934c5db9f8..a760ffc08c2b5bb409c42a1a88ee9cc4a14c70d5 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -190,7 +190,7 @@ export class TypeRecorder { moduleStmt.getBindingNodeMap().forEach((localNode, externalNode) => { let exportedName = jshelpers.getTextOfIdentifierOrLiteral(externalNode); let nodeType = TypeChecker.getInstance().getTypeAtLocation(localNode); - let typeNode = nodeType.getSymbol()?.valueDeclaration; + let typeNode = nodeType?.getSymbol()?.valueDeclaration; if (typeNode) { this.addNonReExportedType(exportedName, typeNode!, localNode); }