From 97e55197c8051c87e2bdd2d71b903fe1751ebd20 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Thu, 13 Jan 2022 16:25:13 -0800 Subject: [PATCH 01/17] Add a test case with 'if' as a method name --- src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts diff --git a/src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts b/src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts new file mode 100644 index 0000000000..a9cdaf09c6 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts @@ -0,0 +1,2 @@ +const obj = { if() { console.log("if"); } } +obj.if(); -- Gitee From 3d4cf7355c3e08405ace6de2cd7224ac40a8f5f0 Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 14 Jan 2022 12:22:46 -0800 Subject: [PATCH 02/17] Support 'if' in PropertyDefinition. --- .../typescript/unit_tests/if-as-prop-name3.ts.result | 9 +++++++++ src/MapleFE/typescript/stmt.spec | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts.result b/src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts.result new file mode 100644 index 0000000000..171ccc1b72 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/if-as-prop-name3.ts.result @@ -0,0 +1,9 @@ +Matched 17 tokens. +Matched 23 tokens. +============= Module =========== +== Sub Tree == +js_const Decl: obj= {if:func if() throws: + console.log("if") +} +== Sub Tree == +obj.if() diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index a1e3b72575..2ff07df409 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -2000,6 +2000,7 @@ rule IndexSignature: ONEOF( rule KeywordMethodName : ONEOF("return", "throw", "continue", + "if", "import", "export") attr.action : BuildIdentifier() @@ -2036,7 +2037,7 @@ rule AllPropertyName : ONEOF(PropertyName, KeywordPropName) rule PropertyDefinition: ONEOF(IdentifierReference, CoverInitializedName, AllPropertyName + ':' + AssignmentExpression, - ZEROORONE(AccessibilityModifier) + PropertyName + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(AccessibilityModifier) + AllPropertyName + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + '{' + FunctionBody + '}', GetAccessor, SetAccessor, -- Gitee From cd1ea5333a1a1b64a5688fb85907a8f3dfc4707c Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 14 Jan 2022 12:58:00 -0800 Subject: [PATCH 03/17] More support of ASI. --- src/MapleFE/typescript/src/lang_spec.cpp | 6 ++++++ src/MapleFE/typescript/stmt.spec | 5 +---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/MapleFE/typescript/src/lang_spec.cpp b/src/MapleFE/typescript/src/lang_spec.cpp index 99b61265fe..4c216945a1 100644 --- a/src/MapleFE/typescript/src/lang_spec.cpp +++ b/src/MapleFE/typescript/src/lang_spec.cpp @@ -549,6 +549,7 @@ bool TypescriptParser::TraverseASI(RuleTable *rule_table, // To simplify the code, I reused TraverseToken(). found = TraverseToken(semicolon, appeal, child); } else { + // case 1. We are crossing lines. if (curr_token->mLineBegin && prev_token->mLineEnd) { // If prev token (line end) is a separator if (prev_token->IsSeparator() && @@ -576,6 +577,11 @@ bool TypescriptParser::TraverseASI(RuleTable *rule_table, if (found) return found; } + + // case 2. like: + // {foo()} <-- , is missed before } + if (curr_token->IsSeparator() && (curr_token->GetSepId() == SEP_Rbrace)) + return true; } if (child) { diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 2ff07df409..aa54dde176 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -818,10 +818,7 @@ rule Statement : ONEOF( LabelledStatement, ThrowStatement, TryStatement, - SpecialStatement, -## I suppose to include CallExpression in ExpressionStatement, but due to the -## complexity of auto-insert-semicolon of TS, I put CallExpression here. - CallExpression) + SpecialStatement) # DebuggerStatement attr.property : Top attr.property : Single # This is extremely important to give CallExpression the -- Gitee From 16cf9a695440b89fe390a54d5963a679a4205ed4 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Fri, 14 Jan 2022 19:49:29 -0500 Subject: [PATCH 04/17] restrict equivalent class match to ones without super class --- src/MapleFE/astopt/include/ast_info.h | 2 ++ src/MapleFE/astopt/src/ast_info.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/MapleFE/astopt/include/ast_info.h b/src/MapleFE/astopt/include/ast_info.h index 763884bd06..e94aeaf224 100644 --- a/src/MapleFE/astopt/include/ast_info.h +++ b/src/MapleFE/astopt/include/ast_info.h @@ -99,6 +99,8 @@ class AST_INFO { void InsertWithThisFunc(TreeNode *node) { mWithThisFuncSet.insert(node->GetNodeId()); } bool IsFuncBodyUseThis(TreeNode *node) { return mWithThisFuncSet.find(node->GetNodeId())!= mWithThisFuncSet.end(); } + bool WithSuper(TreeNode *node); + void SetTypeId(TreeNode *node, TypeId tid); void SetTypeIdx(TreeNode *node, unsigned tidx); diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index 41ae37a99e..471515d5c6 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -326,6 +326,11 @@ bool AST_INFO::IsFieldCompatibleTo(TreeNode *field, TreeNode *target) { } TreeNode *AST_INFO::GetCanonicStructNode(TreeNode *node) { + // node with super does not map to others + if (WithSuper(node)) { + return node; + } + unsigned size = GetFieldsSize(node); bool isI0 = IsInterface(node); @@ -334,6 +339,12 @@ TreeNode *AST_INFO::GetCanonicStructNode(TreeNode *node) { if (node == s) { return s; } + + // s can not have super + if (WithSuper(s)) { + return node; + } + bool isI = IsInterface(s); if (!node->IsStructLiteral()) { // skip if one is interface but other is not @@ -512,6 +523,21 @@ bool AST_INFO::WithTypeParamFast(TreeNode *node) { return (mWithTypeParamNodeSet.find(node->GetNodeId()) != mWithTypeParamNodeSet.end()); } +bool AST_INFO::WithSuper(TreeNode *node) { + unsigned supernum = 0; + switch (node->GetKind()) { + case NK_Class: + supernum = static_cast(node)->GetSuperClassesNum(); + break; + case NK_Interface: + supernum = static_cast(node)->GetSuperInterfacesNum(); + break; + default: + break; + } + return (supernum != 0); +} + template void AST_INFO::ExtendFields(T1 *node, TreeNode *sup) { if (sup == NULL) { -- Gitee From c60277bb3a833be8e3534820cea5c487bd8c56d5 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Fri, 14 Jan 2022 19:54:03 -0500 Subject: [PATCH 05/17] no need to check s since s wont be in the mFieldNum2StructNodeMap at all --- src/MapleFE/astopt/src/ast_info.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index 471515d5c6..52e02bb829 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -340,11 +340,6 @@ TreeNode *AST_INFO::GetCanonicStructNode(TreeNode *node) { return s; } - // s can not have super - if (WithSuper(s)) { - return node; - } - bool isI = IsInterface(s); if (!node->IsStructLiteral()) { // skip if one is interface but other is not -- Gitee From fce09ac8638a62a4979b2e7cce84684bdccdfc0d Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Sun, 16 Jan 2022 09:30:33 -0800 Subject: [PATCH 06/17] Add a test case with a template literal as an argument of 'import()' --- src/MapleFE/test/typescript/unit_tests/import-promise2.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/import-promise2.ts diff --git a/src/MapleFE/test/typescript/unit_tests/import-promise2.ts b/src/MapleFE/test/typescript/unit_tests/import-promise2.ts new file mode 100644 index 0000000000..5426f510ae --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/import-promise2.ts @@ -0,0 +1,6 @@ +const m : string = "./M"; +import(`${m}`).then(() => { + console.log("Completed") +}).catch(() => { + console.log("Failed") +}); -- Gitee From 39ed4c6350c1330f1b1624eb814aafbed99d5926 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Sun, 16 Jan 2022 09:52:09 -0800 Subject: [PATCH 07/17] Update the tsc target option to es2017 in order to support dynamic import with async/await --- src/MapleFE/test/typescript/tsc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MapleFE/test/typescript/tsc.sh b/src/MapleFE/test/typescript/tsc.sh index b5998acf90..1b2579cc6a 100755 --- a/src/MapleFE/test/typescript/tsc.sh +++ b/src/MapleFE/test/typescript/tsc.sh @@ -12,7 +12,7 @@ function ReleaseLock { } rm -rf -- tsc-lock-* *-tsc.out tsc.summary.out tsc.failures*.out -OPT="--target es6 \ +OPT="--target es2017 \ --lib es2015,es2017,dom \ --module commonjs \ --downlevelIteration \ -- Gitee From 83fe279453f655b483d75c4a6090c7c45b9b11b1 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Sun, 16 Jan 2022 09:53:09 -0800 Subject: [PATCH 08/17] Add a test case with dynamic import in an async function --- src/MapleFE/test/typescript/unit_tests/await-import.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/await-import.ts diff --git a/src/MapleFE/test/typescript/unit_tests/await-import.ts b/src/MapleFE/test/typescript/unit_tests/await-import.ts new file mode 100644 index 0000000000..47ea739291 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/await-import.ts @@ -0,0 +1,6 @@ +(async () => { + const { default: myX, getx, setx } = await import("./M"); + console.log(myX, getx()); + setx(3); + console.log(myX, getx()); +})(); -- Gitee From c6ae5b9d396d17960b12857a8237b12f2823060e Mon Sep 17 00:00:00 2001 From: Wen HU Date: Tue, 18 Jan 2022 16:59:15 -0500 Subject: [PATCH 09/17] handle known calls --- src/MapleFE/astopt/src/ast_ti.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index e60c63ad59..6778e9e59f 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -1051,6 +1051,8 @@ CallNode *TypeInferVisitor::VisitCallNode(CallNode *node) { } else { NOTYETIMPL("VisitCallNode null decl"); } + } else if (mAstOpt->IsLangKeyword(mid)) { + // known calls } else { // calling constructor like Array(...) could also end up here TreeNode *type = mHandler->FindType(mid); -- Gitee From 3e6cbe5f6ad50b4c544be10f3c3eda647ecd036b Mon Sep 17 00:00:00 2001 From: Wen HU Date: Tue, 18 Jan 2022 17:08:54 -0500 Subject: [PATCH 10/17] do not update type use node for UserType --- src/MapleFE/astopt/src/ast_ti.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 6778e9e59f..ba09cc287a 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -520,6 +520,8 @@ void TypeInferVisitor::UpdateTypeUseNode(TreeNode *target, TreeNode *input) { } break; } + case TY_User: + break; default: NOTYETIMPL("TypeId not handled"); break; -- Gitee From 77879c9e8aca7eba144440b7c56314e2d123c0c0 Mon Sep 17 00:00:00 2001 From: yehandong Date: Tue, 18 Jan 2022 14:33:57 -0800 Subject: [PATCH 11/17] Support TemplateLiteral in import() --- .../typescript/unit_tests/import-promise2.ts.result | 10 ++++++++++ src/MapleFE/typescript/stmt.spec | 7 ++++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/import-promise2.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/import-promise2.ts.result b/src/MapleFE/test/typescript/unit_tests/import-promise2.ts.result new file mode 100644 index 0000000000..919ef976f9 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/import-promise2.ts.result @@ -0,0 +1,10 @@ +Matched 7 tokens. +Matched 42 tokens. +Matched 43 tokens. +============= Module =========== +== Sub Tree == +js_const Decl: m="./M" +== Sub Tree == +import template-literal: NULL,m.then(() -> console.log("Completed") +).catch(() -> console.log("Failed") +) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index aa54dde176..fa655a1462 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -1714,9 +1714,10 @@ rule TypeArray : ONEOF(PrimaryType + '[' + PrimaryExpression + ']', PrimaryType + '[' + TypeArray + ']') attr.action.%1,%2,%3,%4,%5 : BuildArrayElement(%1, %3) -rule ImportedType : "import" + '(' + Literal + ')' - attr.action : BuildImport() - attr.action : SetFromModule(%3) +rule ImportedType : ONEOF("import" + '(' + Literal + ')', + "import" + '(' + TemplateLiteral + ')') + attr.action.%1,%2 : BuildImport() + attr.action.%1,%2 : SetFromModule(%3) rule PrimaryTypeKeyOf : PrimaryType + '[' + KeyOf + ']' attr.action : BuildArrayElement(%1, %3) -- Gitee From d5f12c9c4d4d03ded0d68b6decfb200aa6b4f4ef Mon Sep 17 00:00:00 2001 From: yehandong Date: Tue, 18 Jan 2022 15:56:35 -0800 Subject: [PATCH 12/17] Support import() as general function. --- .../unit_tests/await-import.ts.result | 8 +++++ src/MapleFE/typescript/stmt.spec | 29 +++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/await-import.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/await-import.ts.result b/src/MapleFE/test/typescript/unit_tests/await-import.ts.result new file mode 100644 index 0000000000..3fa7f89a3b --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/await-import.ts.result @@ -0,0 +1,8 @@ +Matched 55 tokens. +============= Module =========== +== Sub Tree == +() -> js_const Decl: {default:myX, :getx, :setx} +console.log(myX,getx()) +setx(3) +console.log(myX,getx()) +() diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index fa655a1462..9e9f222ae6 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -454,6 +454,11 @@ rule NewExpression : ONEOF(MemberExpression, ## CallExpression[?Yield] . IdentifierName ## CallExpression[?Yield] TemplateLiteral[?Yield] +rule ImportFunction : ONEOF("import" + '(' + Literal + ')', + "import" + '(' + TemplateLiteral + ')') + attr.action.%1,%2 : BuildImport() + attr.action.%1,%2 : SetFromModule(%3) + rule CallExpression : ONEOF( MemberExpression + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), SuperCall, @@ -466,7 +471,8 @@ rule CallExpression : ONEOF( MemberExpression + "?." + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), "set" + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), "get" + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), - CallExpression + "?." + Arguments + ZEROORMORE(AsType)) + CallExpression + "?." + Arguments + ZEROORMORE(AsType), + ImportFunction) attr.action.%1,%3,%10,%11 : BuildCall(%1) attr.action.%1,%10,%11 : AddAsType(%4) attr.action.%1,%10,%11 : AddTypeGenerics(%2) @@ -801,9 +807,6 @@ rule Expression : ONEOF( ## TryStatement[?Yield, ?Return] ## DebuggerStatement -rule SpecialStatement : ONEOF( ImportedType + '.' + Expression + ASI(';') ) - attr.action.%1 : BuildField(%1, %3) - rule Statement : ONEOF( BlockStatement, VariableStatement, @@ -817,8 +820,7 @@ rule Statement : ONEOF( # WithStatement[?Yield, ?Return] LabelledStatement, ThrowStatement, - TryStatement, - SpecialStatement) + TryStatement) # DebuggerStatement attr.property : Top attr.property : Single # This is extremely important to give CallExpression the @@ -1714,11 +1716,6 @@ rule TypeArray : ONEOF(PrimaryType + '[' + PrimaryExpression + ']', PrimaryType + '[' + TypeArray + ']') attr.action.%1,%2,%3,%4,%5 : BuildArrayElement(%1, %3) -rule ImportedType : ONEOF("import" + '(' + Literal + ')', - "import" + '(' + TemplateLiteral + ')') - attr.action.%1,%2 : BuildImport() - attr.action.%1,%2 : SetFromModule(%3) - rule PrimaryTypeKeyOf : PrimaryType + '[' + KeyOf + ']' attr.action : BuildArrayElement(%1, %3) @@ -1738,8 +1735,8 @@ rule Type : ONEOF(UnionOrIntersectionOrPrimaryType, IsExpression, PrimaryType + '[' + TypeQuery + ']', TemplateLiteral, - ImportedType, - ImportedType + '.' + TypeReference) + ImportFunction, + ImportFunction + '.' + TypeReference) attr.action.%7,%11 : BuildArrayElement(%1, %3) attr.action.%14 : BuildField(%1, %3) @@ -1764,8 +1761,8 @@ rule PrimaryType: ONEOF(ParenthesizedType, NeverArrayType, Literal, ArrayLiteral, - ImportedType, - ImportedType + '.' + TypeReference) + ImportFunction, + ImportFunction + '.' + TypeReference) attr.action.%13 : BuildField(%1, %3) rule NeverArrayType : '[' + ']' @@ -1882,7 +1879,7 @@ rule TypeQuery: ONEOF("typeof" + TypeQueryExpression, rule TypeQueryExpression: ONEOF(IdentifierReference, TypeQueryExpression + '.' + JSIdentifier, UnaryExpression, - ImportedType) + ImportFunction) attr.action.%2 : BuildField(%1, %3) ## rule ThisType: this -- Gitee From 2b8ab46850a02f05bb1c11c533ff4d11adb12935 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Tue, 18 Jan 2022 23:30:10 -0800 Subject: [PATCH 13/17] Set parent nodes and handle ImportNode as a child node of AwaitNode properly --- src/MapleFE/ast2cpp/src/emitter.cpp | 2 +- src/MapleFE/shared/include/ast.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index 91d66224c3..5711512895 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -594,7 +594,7 @@ std::string Emitter::EmitImportNode(ImportNode *node) { str += " from "s + s; else { auto p = node->GetParent(); - if (p && (p->IsField() || p->IsTypeOf())) + if (p && (p->IsField() || p->IsTypeOf() || p->IsAwait())) str += '(' + s + ')'; else str += s; diff --git a/src/MapleFE/shared/include/ast.h b/src/MapleFE/shared/include/ast.h index b4ea8b7059..6c3dd0640c 100644 --- a/src/MapleFE/shared/include/ast.h +++ b/src/MapleFE/shared/include/ast.h @@ -393,7 +393,7 @@ public: void SetProperty(ImportProperty p) {mProperty = p;} ImportProperty GetProperty() {return mProperty;} - void SetTarget(TreeNode *t) {mTarget = t;} + void SetTarget(TreeNode *n) {mTarget = n; SETPARENT(n);} TreeNode* GetTarget() {return mTarget;} void SetImportType() {mProperty |= ImpType;} @@ -2345,7 +2345,7 @@ public: ~AwaitNode() {} TreeNode* GetExpr() {return mExpr;} - void SetExpr(TreeNode *t) {mExpr = t;} + void SetExpr(TreeNode *n) {mExpr = n; SETPARENT(n);} void Dump(unsigned); }; -- Gitee From 771d197816cefb06d0937a0b7b3ee0dfdd5926bd Mon Sep 17 00:00:00 2001 From: eching Date: Wed, 19 Jan 2022 17:34:56 -0800 Subject: [PATCH 14/17] Added readme for instructions to build and test, and notes on modeling Javacript inheritance in C++. --- src/MapleFE/docs/readme | 179 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 src/MapleFE/docs/readme diff --git a/src/MapleFE/docs/readme b/src/MapleFE/docs/readme new file mode 100644 index 0000000000..d6c4be8b88 --- /dev/null +++ b/src/MapleFE/docs/readme @@ -0,0 +1,179 @@ +1. SOURCE CODE +============== + +git clone https://gitee.com/openarkcompiler/OpenArkCompiler -b dev_MapleFE + +2. ENVIRONMENT +============== + +export MFE=~/OpenArkCompiler/src/MapleFE +export tsbin=$MFE/output/typescript/bin +export rtsrc=$MFE/ast2cpp/runtime/src +export unit=$MFE/test/typescript/unit_tests +export rtsrc=$MFE/ast2cpp/runtime/src +alias runbld='cd $MFE;source envsetup.sh typescript;make -j16;cd -' +alias runtest='rm cxx.log; ../ts2cxx-test.sh +alias goutil='cd $MFE/test/typescript/utils' +alias gofe='cd $MFE' +alias gocpp='cd $MFE/ast2cpp/src' +alias gort='cd $MFE/ast2cpp/runtime/include' +alias gounit='cd $unit' + +- To build everything: runbld +- To run unit tests: cd $unit; runtest +- To run single test: cd $unit; ../ts2cxx-test.sh +- To run TSC compile and nodejs execute of JS only for specific testcase: cd $unit; ../tsc.sh +- CPP emitter source code: $MFE/ast2cpp/src +- MapleFe compiler toolsfor TSC: + o xxx.ts -> [ast2cpp] -> xxx.ts.ast -> [ast2cpp] -> xxx.h xxx.cpp + o $tsbin/ts2ast - Compile .ts into .ts.ast + o $tsbin/ast2cpp - Compiles .ts.ast into .cpp or back into .ts (for verification) + o $MFE/test/astdump.sh - Dump AST tree from .ts.ast. Output can be text or graph. + o run each of above cmds to see parameters and options, e.g. $tsbin/ast2cpp will display: + ast2cpp a.ast[,b.ast] [options]: + --out=x.cpp : cpp output file + --help : print this help + --trace=n : Emit trace with 4-bit combo levels 1...15 + 1 : Emit ast tree visits + 2 : Emit graph + --emit-ts-only : Emit ts code only + --emit-ts : Emit ts code + --format-cpp : Format cpp + ... +- For graphic view of JavaScript object inheritance relations: + o cd $MFE/docs/util; node proto.js | ./viewdot.sh + +3. TypeScript/JavaScript inheritance modeling in C++ +==================================================== + +3.1 JavaScript Object Properties + +JavaScript objects have both instance properties and inherited +properties. Instance properties are held in the object's own property +list. Inherited properties are held in an object pointed to by the +instance property __proto__. + +The chain of __proto__ between objects forms a hierarchical prototype +chain used in the lookup for an object's inherited properties. Inherited +properites have only a single copy and is shared by all objects that +inherits the property. + +In Javascript, object property lookup order is: +- first lookup instance property (from property list of current object) +- then lookup inherited property (from property list of object pointed to + by chain of __proto__ starting from __proto__ of current object + +3.2 TypeScript/JavaScript inheritance modeling in C++ + +The inheritance relationship of TS/JS objects is mapped to C++ as +classes derived hierarchically along the __proto__ chain. This allows +accessing inherited properties directly as C++ fields and methods of +parent classess, instead of having to traverse the __proto__ chain. + +To maintain continued support of property lookup by __proto__ chain +traversal, each object has a proplist which is a C++ map of the object's +property name and value pairs. + +Proplist entries for runtime created instance properties holds the +actual property value. Proplist entries for properties generated as +C++ class fields and methods at compile time holds pointers to class +fields and methods. + +This guarantees continued functioning of run time property lookup +using prop list and __proto__ chain traversal. This is necessary not +only because of compatibility but also because TS objects can have +instance properties created at runtime which can only be accessed +through prop list because they cannot be generated as C++ class fields +at compile time. + +To ensure inherited properties have only a single copy, all properties +in prototype objects are generated at compile time as C++ static class +fields and methods and accessed either via direct C++ object field +reference, or via pointers from the prototype object's proplist. + +Note that where __proto__ points to a JavaScript function constructor +instead of a prototype object, there is still only a single copy of +inheited properties, because in JavaScript, there is only 1 single +instance of each function constructor. + +3.3 Property inheritance with __proto__ chain + +See environment section in readme for instruction to view graphic +display of JavaScript object inheritance relationship. The following +graphs will be displayed: + + Graph Id. Graph Name + 1. Class Graph with Constructor Edges + 2. Generator Graph with Constructor Edges + 3. Builtin Graph with Constructor Edges + 4. Closure Graph with Constructor Edges + 5. Iterator Graph with Constructor Edges + 6. Async Graph with Constructor Edges + 7. Class Graph + 8. Generator Graph + 9. Builtin Graph + 10. Closure Graph + 11. Iterator Graph + 12. Async Graph + +The CPP emitter optimises property access with static compilation by: +- Generate C++ class fields and methods for JS properties of an object and +- Generate code to access JS properties directly as C++ object fields/method +- Disallow runtime modification of __proto__ property. +- Disallow runtime modification of inheritable properties in prototype objects. + +All JavaScript objects have a __proto__ property. Depending on what the +kind of JS object, its __proto__ may point to different kinds of JS objects: +note: (graph x: node x) cross refs example objects by id of graph above and node within graph. + +JS object What the object's __proto__ is set to +========= ===================================== +1) Object instances (What .__proto__ is set to) + a) Created by user defined or + builtin JS ctor functions, Prototype of the object's ctor function + e.g. myCar, car (graph 1: node 7, 14) (graph 1: node 8, 9) + including builtin objects: + - JSON (graph 3: node 7) (graph 3: node 1) + - Math (graph 3: node 6) + b) Special object instances: + - user defined generators The builtin "Generator" (renamed GeneratorFunction.prototype in 2022 spec) + (graph 2: node 4) (graph 2: node 8) + - generator instances returned by Prototype of user defined generator that returned the instance + user defined generators (graph 2: node 5) + (graph 2: node 10) + +2) Prototype object of ctor function which is: (What .prototype.__proto__ is set to) + a) ctor of a JS class Prototype of ctor of class it extends + (graph 1: node 8) (graph 1: node 9) + b) ctor of top level func or class Prototype of the builtin "Object" (Object.prototype) + (graph 1: node 10) (graph 1: node 1) + includes builtin functions + - Symbol (graph 3: node 5) (graph 3: node 1) + - Promise (graph 3: node 9) (graph 3: node 1) + +3) Special Prototype objects + a) prototype of user defined generators The builtin "GeneratorPrototype" + (graph 2: node 5) (graph 2: node 6) + b) the builtin "Generator" Prototype of the builtin "Function" (Function.prototype) + (graph 2: node 8) (graph 2: node 2) + (GeneratorFunction.prototype in 2022 spec) + c) the builtin "GeneratorPrototype" The builtin "IteratorPrototype" + (graph 2: node 6) (graph 2: node 7) + (renamed GeneratorFunction.prototype.prototype in 2022 spec) + d) the builtin "IteratorPrototype" Prototype of the builtin "Object" (Object.prototype) + (graph 2: node 7) (graph 2: node 1) + note: A prototype object is usaually the prototype object of its constructor + but IteraorPrototype is an exception. Its constructor is "Object" but + it is not the prototype object of "Object", or any other ctor function. + It's an independent prototype object that does not belong to any constructor + +4) Ctor function (What .__proto__ is set to) + a) ctor for a JS class Ctor of class it extends (i.e parent class) + (graph 1: node 13) (graph 1: node 12) + b) top level func or class Prototype of the builtin "Function" (Function.prototype) + (graph 1: node 11) (graph 1: node 2) + includes builtin functions + - Symbol (graph 3: node 4) (graph 3: node 2) + - Promise (graph 3: node 8) + c) the builtin "GeneratorFunction" Ctor of "Function" ("GeneratorFunction extends Function" - so use rule a) + (graph 2: node 9) (graph 2: node 3) -- Gitee From 4118f8d75e25eadd3a070993d37fcdacc66f0757 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Thu, 20 Jan 2022 10:57:14 -0800 Subject: [PATCH 15/17] Add a test case with a missing semicolon --- .../typescript/unit_tests/class-extends3.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/class-extends3.ts diff --git a/src/MapleFE/test/typescript/unit_tests/class-extends3.ts b/src/MapleFE/test/typescript/unit_tests/class-extends3.ts new file mode 100644 index 0000000000..356bf07792 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/class-extends3.ts @@ -0,0 +1,22 @@ +class Car { + private _make: string; + constructor(make: string) { + this._make = make; + } + public getMake(): string { + return this._make; + } +} + +class Model extends Car { + private _model: string; + constructor(make: string, model: string) { + super(make) this._model = super.getMake() + model; + } + public getModel(): string { + return this._model; + } +} + +let passat: Model = new Model("VW", "Passat"); +console.log(passat.getMake(), passat.getModel()); -- Gitee From eca3dc291860cc2e55c62cce013b52ecb426c148 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Thu, 20 Jan 2022 16:49:11 -0500 Subject: [PATCH 16/17] add try/catch/finally as scope --- src/MapleFE/astopt/include/ast_scp.h | 3 +++ src/MapleFE/astopt/src/ast_scp.cpp | 34 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/MapleFE/astopt/include/ast_scp.h b/src/MapleFE/astopt/include/ast_scp.h index 9ceb8f05f6..ba864fdd57 100644 --- a/src/MapleFE/astopt/include/ast_scp.h +++ b/src/MapleFE/astopt/include/ast_scp.h @@ -115,6 +115,9 @@ class BuildScopeVisitor : public BuildScopeBaseVisitor { InterfaceNode *VisitInterfaceNode(InterfaceNode *node); NamespaceNode *VisitNamespaceNode(NamespaceNode *node); ForLoopNode *VisitForLoopNode(ForLoopNode *node); + TryNode *VisitTryNode(TryNode *node); + CatchNode *VisitCatchNode(CatchNode *node); + FinallyNode *VisitFinallyNode(FinallyNode *node); FieldNode *VisitFieldNode(FieldNode *node); TypeParameterNode *VisitTypeParameterNode(TypeParameterNode *node); diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index 1a6ffa8e76..0fe4d3271c 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -660,6 +660,40 @@ ExportNode *BuildScopeVisitor::VisitExportNode(ExportNode *node) { return node; } +TryNode *BuildScopeVisitor::VisitTryNode(TryNode *node) { + ASTScope *parent = mScopeStack.top(); + ASTScope *scope = NewScope(parent, node); + mScopeStack.push(scope); + BuildScopeBaseVisitor::VisitTryNode(node); + mScopeStack.pop(); + return node; +} + +CatchNode *BuildScopeVisitor::VisitCatchNode(CatchNode *node) { + ASTScope *parent = mScopeStack.top(); + ASTScope *scope = NewScope(parent, node); + + // add params as decl + for (unsigned i = 0; i < node->GetParamsNum(); i++) { + TreeNode *n = node->GetParamAtIndex(i); + AddDecl(scope, n); + } + + mScopeStack.push(scope); + BuildScopeBaseVisitor::VisitCatchNode(node); + mScopeStack.pop(); + return node; +} + +FinallyNode *BuildScopeVisitor::VisitFinallyNode(FinallyNode *node) { + ASTScope *parent = mScopeStack.top(); + ASTScope *scope = NewScope(parent, node); + mScopeStack.push(scope); + BuildScopeBaseVisitor::VisitFinallyNode(node); + mScopeStack.pop(); + return node; +} + // rename var with same name, i --> i__vN where N is 1, 2, 3 ... void AST_SCP::RenameVar() { MSGNOLOC0("============== RenameVar =============="); -- Gitee From 491d1fd72077545e346cd3a0a0566bcdb8819e1b Mon Sep 17 00:00:00 2001 From: Wen HU Date: Thu, 20 Jan 2022 17:05:58 -0500 Subject: [PATCH 17/17] add key in StrIndexSigNode as decl --- src/MapleFE/astopt/src/ast_scp.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index 0fe4d3271c..1ec23032d1 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -286,9 +286,12 @@ ClassNode *BuildScopeVisitor::VisitClassNode(ClassNode *node) { for(unsigned i = 0; i < node->GetFieldsNum(); i++) { TreeNode *fld = node->GetField(i); if (fld->IsStrIndexSig()) { - continue; - } - if (fld->IsIdentifier()) { + StrIndexSigNode *sis = static_cast(fld); + TreeNode *key = sis->GetKey(); + if (key) { + AddDecl(scope, key); + } + } else if (fld->IsIdentifier()) { AddDecl(scope, fld); } else { NOTYETIMPL("new type of class field"); -- Gitee