From e1b27b83fb35864c8a6523018e06de9cfe4aefd9 Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 4 Mar 2022 08:01:45 +0800 Subject: [PATCH 01/44] Fixed the missing implementation of FunctionTypeNode in ast2mpl and vfy. --- src/MapleFE/ast2mpl/src/mpl_processor.cpp | 4 ++++ src/MapleFE/shared/src/vfy.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/MapleFE/ast2mpl/src/mpl_processor.cpp b/src/MapleFE/ast2mpl/src/mpl_processor.cpp index a943ae29b8..0e5cf00ed5 100644 --- a/src/MapleFE/ast2mpl/src/mpl_processor.cpp +++ b/src/MapleFE/ast2mpl/src/mpl_processor.cpp @@ -613,6 +613,10 @@ maple::BaseNode *Ast2MplBuilder::ProcessTripleSlash(StmtExprKind skind, TreeNode return nullptr; } +maple::BaseNode *Ast2MplBuilder::ProcessFunctionType(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { + return nullptr; +} + maple::BaseNode *Ast2MplBuilder::ProcessBlockDecl(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { BlockNode *ast_block = static_cast(tnode); for (int i = 0; i < ast_block->GetChildrenNum(); i++) { diff --git a/src/MapleFE/shared/src/vfy.cpp b/src/MapleFE/shared/src/vfy.cpp index 02a87ff57b..07809d0f89 100644 --- a/src/MapleFE/shared/src/vfy.cpp +++ b/src/MapleFE/shared/src/vfy.cpp @@ -572,4 +572,8 @@ void Verifier::VerifyTripleSlash(TripleSlashNode *tree){ return; } +void Verifier::VerifyFunctionType(FunctionTypeNode *tree){ + return; +} + } -- Gitee From 21ed93037d5feb2334e8c679574ce2b43b998caa Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 4 Mar 2022 08:14:30 +0800 Subject: [PATCH 02/44] Further improve the triple-slash implementation. --- .../unit_tests/triple-slash-comment.ts.result | 10 ++++++++++ src/MapleFE/typescript/src/lang_spec.cpp | 13 ++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result new file mode 100644 index 0000000000..e4afff30c0 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result @@ -0,0 +1,10 @@ +Matched 12 tokens. +Matched 19 tokens. +Matched 26 tokens. +============= Module =========== +== Sub Tree == +ts_enum: ET {TOP="top";BOTTOM="bottom" } +== Sub Tree == +js_let Decl: et=ET.TOP +== Sub Tree == +console.log(et) diff --git a/src/MapleFE/typescript/src/lang_spec.cpp b/src/MapleFE/typescript/src/lang_spec.cpp index 54a95b6c35..d51d1f312d 100644 --- a/src/MapleFE/typescript/src/lang_spec.cpp +++ b/src/MapleFE/typescript/src/lang_spec.cpp @@ -404,7 +404,18 @@ bool TypescriptLexer::FindTripleSlash() { if (line[i] == ' ') { i++; } else if (line[i] == '<') { - return true; + // Need make sure the following word is 'reference', + // or 'amd-module', or 'amd-dependency' + i++; + while(line[i] == ' ') { + i++; + } + if (!strncmp(line + i, "reference", 9) || + !strncmp(line + i, "amd-module", 10) || + !strncmp(line + i, "amd-dependency", 14)) { + if (i < current_line_size) + return true; + } } else { return false; } -- Gitee From 19650bce3c5c9cc2e29f02783bda07247131935d Mon Sep 17 00:00:00 2001 From: Ed Ching Date: Thu, 3 Mar 2022 22:15:31 -0800 Subject: [PATCH 03/44] "this" handling cleanup because current AST handles TypeScript "this" keyword" as an identfier instead of a literal (LT_ThisLiteral). --- src/MapleFE/ast2cpp/src/cpp_declaration.cpp | 12 +----------- src/MapleFE/ast2cpp/src/cpp_definition.cpp | 3 ++- src/MapleFE/ast2cpp/src/helper.cpp | 5 +++++ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp index dd59280855..b9cf304dc9 100644 --- a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp @@ -1117,17 +1117,7 @@ std::string CppDecl::EmitLiteralNode(LiteralNode *node) { mPrecedence = '\030'; str = HandleTreeNode(str, node); if (auto n = node->GetType()) { - if (str.compare("this") == 0) { - // handle special literal "this" - std::string type = EmitTreeNode(n); - if (type.compare("t2crt::JS_Val ") == 0) - // map type ANY for "this" to generic object type - str = "t2crt::Object* "s + "_this"s; - else - str = type + " _this"; - } - else - str += ": "s + EmitTreeNode(n); + str += ": "s + EmitTreeNode(n); } if (auto n = node->GetInit()) { str += " = "s + EmitTreeNode(n); diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index cd1028195a..ee40436646 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -1239,7 +1239,7 @@ std::string CppDef::GetThisParamObjType(TreeNode *node) { std::string str = "t2crt::Object"; if (static_cast(node)->GetParamsNum()) { auto n = static_cast(node)->GetParam(0); - if (n->IsIdentifier() && n->IsThis()) { + if (n->IsThis()) { TreeNode* tn = static_cast(n)->GetType(); str = mCppDecl.GetTypeString(tn, nullptr); if (str.back() == '*') @@ -1283,6 +1283,7 @@ std::string CppDef::EmitNewNode(NewNode *node) { str = fnName + "->ctor("s + newObj + ", "s; // call ctor function with new obj as this arg } } else { + // for builtins str = "new "s + EmitTreeNode(node->GetId()); str += "("s; } diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 432ed63002..782eb31bbe 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -129,6 +129,11 @@ std::string FunctionClassDecl(std::string retType, std::string funcName, unsigne // o if 1st TS func param is "this" // - rename to "_this" // - if type is Any (JS_Val), change to "ts2crt::Object*" + // + // CPP emitter Handling of "this" in AST: + // - if "this" is used as an identifier in functions, cpp emitter renames it to _this + // - if "this" is used as an identifier outside functions, cpp emitter rename it to the module obj + // - if "this" is used as a string literal, it is left unchanged. if (funcParams.size() == 0) { // TS func has no param. Insert _this for ts2cpp mapping. -- Gitee From 6517fca8fc35cbd1ee695f10cc63b33b94543def Mon Sep 17 00:00:00 2001 From: Ed Ching Date: Fri, 4 Mar 2022 04:51:09 -0800 Subject: [PATCH 04/44] Refactor to use common function header generation interface. --- src/MapleFE/ast2cpp/include/cpp_emitter.h | 2 + src/MapleFE/ast2cpp/include/helper.h | 3 +- src/MapleFE/ast2cpp/src/cpp_declaration.cpp | 2 +- src/MapleFE/ast2cpp/src/cpp_definition.cpp | 55 +------- src/MapleFE/ast2cpp/src/cpp_emitter.cpp | 37 +++++ src/MapleFE/ast2cpp/src/helper.cpp | 143 ++++++++++---------- 6 files changed, 117 insertions(+), 125 deletions(-) diff --git a/src/MapleFE/ast2cpp/include/cpp_emitter.h b/src/MapleFE/ast2cpp/include/cpp_emitter.h index a68d25a726..ec2f269dba 100644 --- a/src/MapleFE/ast2cpp/include/cpp_emitter.h +++ b/src/MapleFE/ast2cpp/include/cpp_emitter.h @@ -37,6 +37,8 @@ public: bool IsGenerator(TreeNode *node); FunctionNode* GetGeneratorFunc(TreeNode *node); void GetArrayTypeInfo(ArrayLiteralNode* node, int& numDim, std::string& type); + std::string FunctionHeader(FunctionNode* node, std::string retType); + std::string GetClassName(TreeNode* node); }; } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index 6901cda207..21a9f97100 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -44,11 +44,12 @@ extern std::string GenAnonFuncName(TreeNode* node); inline std::string ClsName(std::string func) { return "Cls_"s + func; } inline std::string GeneratorName(std::string func) { return "Generator_"s + func; } inline std::string GeneratorFuncName(std::string func) { return "GeneratorFunc_"s + func; } -extern void HandleThisParam(unsigned nParams, TreeNode* node, std::string& params, std::string&args); extern std::string hlpGetJSValTypeStr(TypeId typeId); extern std::string ArrayCtorName(int dim, std::string type); extern bool IsBuiltinObj(std::string name); extern std::string ObjectTypeStr(std::string name); +extern std::string GeneratorFuncHeader(std::string prefix, unsigned nodeId); +extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false); class FuncTable { private: diff --git a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp index b9cf304dc9..20f4128f1b 100644 --- a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp @@ -383,11 +383,11 @@ namespace )""" + module + R"""( { TreeNode *node = func->GetFuncNode(); std::string funcName = GetIdentifierName(node); + CollectFuncArgInfo(node); if (!IsClassMethod(node)) { std::string ns = GetNamespace(node); if (!ns.empty()) str += "namespace "s + ns + " {\n"s; - CollectFuncArgInfo(node); bool isGenerator = static_cast(node)->IsGenerator(); std::string generatorClassDef; if (isGenerator) { diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index ee40436646..bf0f9610c9 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -188,14 +188,6 @@ std::string CppDef::EmitXXportAsPairNode(XXportAsPairNode *node) { return std::string(); } -// Return class name from class method or class field -inline std::string GetClassName(TreeNode* node) { - TreeNode* n = node->GetParent(); - if (n && n->IsClass()) - return n->GetName(); - return ""s; -} - inline bool IsClassMethod(FunctionNode* f) { return (f && f->GetParent() && f->GetParent()->IsClass()); } @@ -266,53 +258,14 @@ std::string CppDef::EmitFuncScopeVarDecls(FunctionNode *node) { } std::string CppDef::EmitFunctionNode(FunctionNode *node) { - bool isTopLevel = hFuncTable.IsTopLevelFunc(node); if (mIsInit || node == nullptr) return std::string(); - std::string str, className, ns = GetNamespace(node); - if (!ns.empty()) - ns += "::"s; - - if (node->IsGenerator()) { - // TODO - } - if (node->IsConstructor()) { - className = ns + GetClassName(node); - str = "\n"s; - str += className + "* "s + className + "::Ctor::operator()("s + className + "* obj"s; - } else { - str = mCppDecl.GetTypeString(node->GetType(), node->GetType()); - std::string funcName = GetIdentifierName(node); - str += " "s; - - if (IsClassMethod(node)) - str += ns + GetClassName(node) + "::"s + funcName; - else if (isTopLevel) - str += ns + "Cls_"s + funcName + "::_body"s; // emit body of top level function - else - str += ns + funcName; - str += "("s; - } - - std::string params, unused; - for (unsigned i = 0; i < node->GetParamsNum(); ++i) { - if (i || node->IsConstructor()) - params += ", "s; - if (auto n = node->GetParam(i)) { - params += mCppDecl.EmitTreeNode(n); - if (isTopLevel && i == 0) { - HandleThisParam(node->GetParamsNum(), n, params, unused); - } - } - } + bool isTopLevel = hFuncTable.IsTopLevelFunc(node); + std::string str; + str += "\n"; + str += FunctionHeader(node, mCppDecl.GetTypeString(node->GetType(), node->GetType())); - if (isTopLevel && !IsClassMethod(node)) { - if (node->GetParamsNum() == 0) { - HandleThisParam(0, nullptr, params, unused); - } - } - str += params + ") "s; int bodyPos = str.size(); if (auto n = node->GetBody()) { auto varDecls = EmitFuncScopeVarDecls(node); diff --git a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp index e04128c96e..c5c92c0b04 100644 --- a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp @@ -205,4 +205,41 @@ void CppEmitter::GetArrayTypeInfo(ArrayLiteralNode* node, int& numDim, std::stri #endif } +// C++ function header for different TS function types: +// Generator: t2crt::IteratorResult [::]GeneratorFunc_::_body(t2crt::Object* _this, void*& yield[, &]...) +// Class ctor: [::]* ::Ctor::operator()(* obj[, ]...) +// Class method: [::]::([params]...) +// Function: [::]Cls_::_body(t2crt::Object|* _this[, params]...) +std::string CppEmitter::FunctionHeader(FunctionNode* node, std::string retType) { + std::string str; + std::string ns = GetNamespace(node).empty() ? ""s : GetNamespace(node)+"::"; + std::string funcName = GetIdentifierName(node); + std::string className= ns + GetClassName(node); + bool isTopLevel = hFuncTable.IsTopLevelFunc(node); + retType = retType + " "s + ns; + + if (node->IsGenerator()) // generator + str += GeneratorFuncHeader(ns+GeneratorFuncName(funcName)+"::", node->GetNodeId()); + else if (node->IsConstructor()) { // class constructor + std::string param = FunctionParams(node->GetNodeId(), false); + param = param.empty() ? ""s : (", "s+param); + str += className + "* "s + className + "::Ctor::operator()" + "(" +className+ "* obj" +param+ ") "; + } + else if (IsClassMethod(node)) // class method + str += retType + GetClassName(node) + "::" + funcName + "(" + FunctionParams(node->GetNodeId(), false) + ") "; + else if (isTopLevel) // top level function + str += retType + "Cls_" + funcName + "::_body" + "(" + FunctionParams(node->GetNodeId(), true) + ") "; + else + str += retType + funcName + "(" + FunctionParams(node->GetNodeId(), false) + ") "; + return str; +} + +// Return class name from class method or class field +std::string CppEmitter::GetClassName(TreeNode* node) { + TreeNode* n = node->GetParent(); + if (n && n->IsClass()) + return n->GetName(); + return ""s; +} + } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 782eb31bbe..2cd1e12b43 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -95,6 +95,53 @@ std::string GenClassFldAddProp(std::string objName, return str; } +// TS function paramteri mapping to C++: +// +// TS2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list +// which will be generated from AST if "this" is declared as a TS func parameter +// as required by TS strict mode. However TS funcs that do not reference 'this' +// are not required to declare it, in which case emitter has to insert one. +// +// Cases: +// if TS func has no param +// - insert param "ts2crt::Object* _this" +// if 1st TS func param is not "this" +// - insert param "ts2crt::Object* _this" +// if 1st TS func param is "this" +// - rename to "_this" +// - if type is Any (JS_Val), change to "ts2crt::Object*" +// +std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly) { + std::vector> funcParams = hFuncTable.GetArgInfo(nodeId); + std::string ObjT = "t2crt::Object*"; + std::string str; + + if (handleThis) { + if (funcParams.size() == 0) // func has no param + return argsOnly? "_this"s: (ObjT + " _this"); + } + + for (bool first=true; auto elem : funcParams) { + std::string type = elem.first, name = elem.second; + if (!first) + str += ", "s; + else { // 1st param of TS func + if (handleThis) { + if (name.compare("this") != 0) // if not "this", insert _this + str += argsOnly? ("_this, "s): (ObjT + " _this, "s); + else { // if "this" + name = "_this"; + if (type.compare("t2crt::JS_Val") == 0) + type = ObjT; // change type Any to Object* + } + } + first = false; + } + str += argsOnly? name: (type + " "s + name); + } + return str; +} + // Each first level function is instantiated from a corresponding class generated with interfaces below: // Body - user defined function code // () - functor for OrdinaryCallEvaluteBody [9.2.1.3] @@ -114,55 +161,10 @@ std::string FunctionClassDecl(std::string retType, std::string funcName, unsigne std::string t2cObjType = "t2crt::Object*"; std::string thisType = t2cObjType; - // Map TS function paramters to C++ interface args and params: - // - // TS2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list - // which will be generated from AST if "this" is declared as a TS func parameter - // as required by TS strict mode. However TS funcs that do not reference 'this' - // are not required to declare it, in which case emitter has to insert one. - // - // Cases: - // o if TS func has no param - // - insert param "ts2crt::Object* _this" - // o if 1st TS func param is not "this" - // - insert param "ts2crt::Object* _this" - // o if 1st TS func param is "this" - // - rename to "_this" - // - if type is Any (JS_Val), change to "ts2crt::Object*" - // - // CPP emitter Handling of "this" in AST: - // - if "this" is used as an identifier in functions, cpp emitter renames it to _this - // - if "this" is used as an identifier outside functions, cpp emitter rename it to the module obj - // - if "this" is used as a string literal, it is left unchanged. - - if (funcParams.size() == 0) { - // TS func has no param. Insert _this for ts2cpp mapping. - params += t2cObjType + " "s + "_this"s; - args += "_this"s; - } - for (bool firstParam=true; auto elem : funcParams) { - std::string type = elem.first, name = elem.second; - if (!firstParam) { // not 1st param - params+= ", "s; - args += ", "s; - } else { // 1st param of TS func - firstParam = false; - if (name.compare("this") != 0) { - // 1st TS param not "this" - insert _this parameter - params += t2cObjType + " "s + "_this"s + ", "s; - args += "_this"s + ", "s; - thisType = t2cObjType; - } else { - // 1st TS param is "this" - change to "_this" - name = "_this"; - if (type.compare("t2crt::JS_Val") == 0) - type = t2cObjType; // change type Any to Object* - thisType = type; - } - } - params += type + " "s + name; - args += name; - } + params = FunctionParams(nodeId, true, false); + args = FunctionParams(nodeId, true, true); + thisType = params.substr(0, params.find(" ")); + std::string str; std::string clsName = ClsName(funcName); std::string functorArgs = args; @@ -198,6 +200,26 @@ class )""" + clsName + R"""( : public t2crt::Function { return str; } +// build generator function header for _body +std::string GeneratorFuncHeader(std::string prefix, unsigned nodeId) { + std::string refArgs; + std::vector> args = hFuncTable.GetArgInfo(nodeId); + + // build parameter list + for (bool hasArg=false; auto elem : args) { + if (!hasArg) + hasArg = true; + else + refArgs += ", "; + std::string type = elem.first, name = elem.second; + refArgs += type + "& "+ name; // pass all parameters by reference + } + if (!refArgs.empty()) + refArgs = ", " + refArgs; + // return func header + return "t2crt::IteratorResult " + prefix + "_body(t2crt::Object* _this, void*& yield" + refArgs + ")"; +} + // Template for generating Generators and Generator Functions: // For each TS generator function, 2 C++ classes: generator and generator function are emitted. // The generator function has only a single instance. It is called to create generator instances. @@ -320,29 +342,6 @@ std::string GenAnonFuncName(TreeNode* node) { return "_anon_func_"s + std::to_string(node->GetNodeId()); } -// Check 1st param of top level function for "this" and do substitution. -void HandleThisParam(unsigned nParams, TreeNode* node, std::string& params, std::string&args) { - if (nParams == 0) { - // ts2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list - // which will be generated from AST if "this" is declared as a TS func parameter - // as required by TS strict mode. However TS funcs that do not reference 'this' - // are not required to declare it, so emitter has to check and insert one. - params = "t2crt::Object* _this"s; - args = "_this"s; - return; - } - - if (node->IsThis()) { - args = "_this"; - Emitter::Replace(params, "this", "_this"); // change this to _this to avoid c++ keyword - Emitter::Replace(params, "t2crt::JS_Val", "t2crt::Object*"); // change type any (JS_Val) to Object* per ts2cpp func mapping to C++ interface - } else { - // if 1st func param is not "this", insert one to work with c++ mapping for TS func - args = "_this, "s + args; - params = "t2crt::Object* _this, "s + params; - } -} - // return array constructor name of given type // format: // 1D array: t2crt::Array::ctor -- Gitee From d60a0d22eb656c4ee0ea384f5c7eb1d8a47a8715 Mon Sep 17 00:00:00 2001 From: Ed Ching Date: Fri, 4 Mar 2022 12:57:28 -0800 Subject: [PATCH 05/44] More migration to use common function header generation interface. --- src/MapleFE/ast2cpp/include/helper.h | 2 +- src/MapleFE/ast2cpp/src/helper.cpp | 64 +++++++++------------------- 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index 21a9f97100..ff92b799ff 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -49,7 +49,7 @@ extern std::string ArrayCtorName(int dim, std::string type); extern bool IsBuiltinObj(std::string name); extern std::string ObjectTypeStr(std::string name); extern std::string GeneratorFuncHeader(std::string prefix, unsigned nodeId); -extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false); +extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false, bool byRef = false); class FuncTable { private: diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 2cd1e12b43..b32adeb882 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -111,14 +111,14 @@ std::string GenClassFldAddProp(std::string objName, // - rename to "_this" // - if type is Any (JS_Val), change to "ts2crt::Object*" // -std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly) { +std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly, bool byRef) { std::vector> funcParams = hFuncTable.GetArgInfo(nodeId); std::string ObjT = "t2crt::Object*"; std::string str; if (handleThis) { if (funcParams.size() == 0) // func has no param - return argsOnly? "_this"s: (ObjT + " _this"); + return argsOnly ? "_this"s : (ObjT + " _this"); } for (bool first=true; auto elem : funcParams) { @@ -137,7 +137,7 @@ std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly) { } first = false; } - str += argsOnly? name: (type + " "s + name); + str += argsOnly? name: (type + (byRef?"\&":"") + " "s + name); } return str; } @@ -156,19 +156,15 @@ std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly) { // per TS/JS spec. std::string FunctionClassDecl(std::string retType, std::string funcName, unsigned nodeId) { - std::vector> funcParams = hFuncTable.GetArgInfo(nodeId); - std::string args, params; - std::string t2cObjType = "t2crt::Object*"; - std::string thisType = t2cObjType; + std::string str, args, params, thisType; + std::string clsName = ClsName(funcName); params = FunctionParams(nodeId, true, false); args = FunctionParams(nodeId, true, true); - thisType = params.substr(0, params.find(" ")); + thisType = params.substr(0, params.find(" ")); // extract return type of "this" parameter - std::string str; - std::string clsName = ClsName(funcName); - std::string functorArgs = args; std::string functorParams = params; + std::string functorArgs = args; functorArgs.replace(0, 5, "_thisArg"); // replace _this with _thisArg size_t pos; if ((pos = functorParams.find("_this, ")) != std::string::npos) @@ -202,22 +198,10 @@ class )""" + clsName + R"""( : public t2crt::Function { // build generator function header for _body std::string GeneratorFuncHeader(std::string prefix, unsigned nodeId) { - std::string refArgs; - std::vector> args = hFuncTable.GetArgInfo(nodeId); - - // build parameter list - for (bool hasArg=false; auto elem : args) { - if (!hasArg) - hasArg = true; - else - refArgs += ", "; - std::string type = elem.first, name = elem.second; - refArgs += type + "& "+ name; // pass all parameters by reference - } - if (!refArgs.empty()) - refArgs = ", " + refArgs; - // return func header - return "t2crt::IteratorResult " + prefix + "_body(t2crt::Object* _this, void*& yield" + refArgs + ")"; + std::string params = FunctionParams(nodeId, false, false, true); // pass params by ref into _body() + if (!params.empty()) + params = ", " + params; + return "t2crt::IteratorResult " + prefix + "_body(t2crt::Object* _this, void*& yield" + params + ")"; } // Template for generating Generators and Generator Functions: @@ -286,25 +270,17 @@ public: } std::string GeneratorClassDef(std::string ns, std::string funcName, unsigned nodeId) { - std::string str, params, ctorArgs, functorArgs; + std::string str; std::string generatorName = ns + GeneratorName(funcName); std::string generatorFuncName = ns + GeneratorFuncName(funcName); - std::vector> args = hFuncTable.GetArgInfo(nodeId); if (!ns.empty()) funcName = ns + "::" + funcName; - for (bool hasArg=false; auto elem : args) { - if (!hasArg) - hasArg = true; - else { - functorArgs += ", "s; - params += ", "s; - } - functorArgs += elem.first + " " + elem.second; //1st=type 2nd=name - params += " " + elem.second; - } - ctorArgs = functorArgs.empty()? std::string(): (", "s + functorArgs); - params = params.empty()? std::string(): (", "s + params); + + std::string params = FunctionParams(nodeId, false, false); + std::string args = FunctionParams(nodeId, false, true); + if (!args.empty()) + args = ", " + args; str = R"""( t2crt::IteratorResult )""" + generatorName + R"""(::_next(t2crt::JS_Val* arg) { @@ -316,14 +292,14 @@ t2crt::IteratorResult )""" + generatorName + R"""(::_next(t2crt::JS_Val* arg) { } // iterate by calling generation function with captures in generator - res = foo->_body(this, _yield)""" + params + R"""(); + res = foo->_body(this, _yield)""" + args + R"""(); if (res._done == true) _finished = true; return res; } -)""" + generatorName + "* "s + generatorFuncName + R"""(::operator()()""" + functorArgs + R"""() { - return new )""" + generatorName + R"""((&t2crt::Generator, foo->prototype)""" + params + R"""(); +)""" + generatorName + "* "s + generatorFuncName + R"""(::operator()()""" + params + R"""() { + return new )""" + generatorName + R"""((&t2crt::Generator, foo->prototype)""" + args + R"""(); } )"""; -- Gitee From 560afe021d508eda2ea962e8b92ad1dd97e62a6a Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 4 Mar 2022 15:00:44 -0800 Subject: [PATCH 06/44] Add 'const', 'let', 'var', 'if', 'else', 'for' and 'try' as class function names --- src/MapleFE/typescript/stmt.spec | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 4754d774aa..6c124b7dba 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -2263,6 +2263,13 @@ rule KeywordMemberFunctionName : ONEOF("return", "set", "continue", "break", + "const", + "let", + "var", + "if", + "else", + "for", + "try", "export") attr.action : BuildIdentifier() -- Gitee From 35a1faa9f96b918507bf7b0484dc160636248247 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 4 Mar 2022 15:37:35 -0800 Subject: [PATCH 07/44] Allow keyword 'if' or 'try' to be used as an identifier --- src/MapleFE/typescript/stmt.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 6c124b7dba..75a9afc1ad 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -94,6 +94,8 @@ rule KeywordIdentifier : ONEOF("type", "throw", "class", "unknown", + "if", + "try", "do", "for") ## " -- Gitee From 58df4f22991e37313146e6a001e300aadcb1395b Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 4 Mar 2022 15:48:41 -0800 Subject: [PATCH 08/44] Add a test case with missing semicolon between 'break' and 'default' --- .../typescript/unit_tests/semicolon-missing15.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts new file mode 100644 index 0000000000..a21a6ce8a1 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts @@ -0,0 +1,16 @@ +var n: number = 1; +switch (true) { + case n < 5: + console.log(n, " is less than 5"); + case n > 2 && n < 5: + console.log(n, " + 1 is equal to", n + 1); + break; + case n == 6: + console.log(n, " is equal to 6"); + break; + case n < 8: + console.log(n, " is greater than 4 and less than 8"); + break + default: + console.log(n, " is greater than 7"); +} -- Gitee From f0d5e1805df17bc11fde8d72b65a6b4e445957b5 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 4 Mar 2022 18:09:59 -0800 Subject: [PATCH 09/44] Revert "Allow keyword 'if' or 'try' to be used as an identifier" This reverts commit 35a1faa9f96b918507bf7b0484dc160636248247. --- src/MapleFE/typescript/stmt.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 75a9afc1ad..6c124b7dba 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -94,8 +94,6 @@ rule KeywordIdentifier : ONEOF("type", "throw", "class", "unknown", - "if", - "try", "do", "for") ## " -- Gitee From 5e6ef5c7768d946c43068df10fa7b73c8210bd80 Mon Sep 17 00:00:00 2001 From: Ed Ching Date: Fri, 4 Mar 2022 18:15:46 -0800 Subject: [PATCH 10/44] Cleanup emittance of Generator function declaration. --- src/MapleFE/ast2cpp/include/helper.h | 2 +- src/MapleFE/ast2cpp/src/helper.cpp | 65 +++++++++++++--------------- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index ff92b799ff..0d88829abb 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -48,7 +48,7 @@ extern std::string hlpGetJSValTypeStr(TypeId typeId); extern std::string ArrayCtorName(int dim, std::string type); extern bool IsBuiltinObj(std::string name); extern std::string ObjectTypeStr(std::string name); -extern std::string GeneratorFuncHeader(std::string prefix, unsigned nodeId); +extern std::string GeneratorFuncHeader(std::string cls, unsigned nodeId); extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false, bool byRef = false); class FuncTable { diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index b32adeb882..2c4d0a70c4 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -197,11 +197,11 @@ class )""" + clsName + R"""( : public t2crt::Function { } // build generator function header for _body -std::string GeneratorFuncHeader(std::string prefix, unsigned nodeId) { +std::string GeneratorFuncHeader(std::string cls, unsigned nodeId) { std::string params = FunctionParams(nodeId, false, false, true); // pass params by ref into _body() if (!params.empty()) params = ", " + params; - return "t2crt::IteratorResult " + prefix + "_body(t2crt::Object* _this, void*& yield" + params + ")"; + return "t2crt::IteratorResult " + cls + "_body(t2crt::Object* _this, void*& yield" + params + ")"; } // Template for generating Generators and Generator Functions: @@ -211,61 +211,56 @@ std::string GeneratorClassDecl(std::string funcName, unsigned nodeId) { std::string str; std::string generatorName = GeneratorName(funcName); std::string generatorFuncName = GeneratorFuncName(funcName); - std::vector> args = hFuncTable.GetArgInfo(nodeId); + std::vector> params = hFuncTable.GetArgInfo(nodeId); // Different formats of arg list as needed by generator and generator function interfaces: // - args for function class functor and generation class constructor // () - generator class constructor field init list // & - args passed by reference to generation function _body method // ; - generator class fields for capturing closure - std::string functorArgs, ctorArgs, refArgs, initList, captureFields; + std::string functorArgs, ctorArgs, initList, captureFields; - for (bool hasArg=false; auto elem : args) { + for (bool hasArg=false; auto elem : params) { if (!hasArg) hasArg = true; else { functorArgs += ", "s; - refArgs += ", "s; initList += ", "s; } std::string type = elem.first, name = elem.second; functorArgs += type + " " + name; - refArgs += type + "& "+ name; initList += name + "("s+ name + ")"s; captureFields += tab(1) + type + " " + name + ";\n"s; } - if (!refArgs.empty()) - refArgs = ", " + refArgs; if (!initList.empty()) initList = ", " + initList; ctorArgs = functorArgs.empty()? std::string(): (", "s + functorArgs); - str = R"""( -// )""" + funcName + R"""( generators -class )""" + generatorName + R"""( : public t2crt::GeneratorProto { -public: - )""" + generatorName + R"""((t2crt::Function* ctor, t2crt::Object* proto)""" + ctorArgs + R"""() : t2crt::GeneratorProto(ctor, proto))""" + initList + R"""( {} - ~)""" + generatorName + R"""(() {} - - // closure capture fields -)""" + captureFields + R"""( - // iterator interface (override _return and _throw when needed) - t2crt::IteratorResult _next(t2crt::JS_Val* arg = nullptr) override; -}; - -// )""" + funcName + R"""( generator function -class )""" + generatorFuncName + R"""( : public t2crt::GeneratorFuncPrototype { -public: - )""" + generatorFuncName + R"""(() : t2crt::GeneratorFuncPrototype(&t2crt::GeneratorFunction, &t2crt::Generator, t2crt::GeneratorPrototype) {} - ~)""" + generatorFuncName + R"""(() {} - - // call operator returns generator instances - )""" + generatorName + R"""(* operator()()""" + functorArgs + R"""(); - // generator function body - t2crt::IteratorResult _body(t2crt::Object* _this, void*& yield)""" + refArgs + R"""(); -}; - -)"""; + std::string genClsDecl[] = { +"// " +funcName+ " generators", +"class " +generatorName+ " : public t2crt::GeneratorProto {", +"public:", +" " +generatorName+ "(t2crt::Function* ctor, t2crt::Object* proto" +ctorArgs+ ") : t2crt::GeneratorProto(ctor, proto)" +initList+ " {}", +" ~" +generatorName+ "() {}", +" // closure capture fields", + captureFields, +" // iterator interface (override _return and _throw when needed)", +" t2crt::IteratorResult _next(t2crt::JS_Val* arg = nullptr) override;", +"};", +"// " +funcName+ " generator function", +"class " +generatorFuncName+ " : public t2crt::GeneratorFuncPrototype {", +"public:", +" " +generatorFuncName+ "() : t2crt::GeneratorFuncPrototype(&t2crt::GeneratorFunction, &t2crt::Generator, t2crt::GeneratorPrototype) {}", +" ~" +generatorFuncName+ "() {}", +" // call operator returns generator instances", +" " +generatorName+ "* operator()(" +functorArgs+ ");", +" // generator function body", +" " +GeneratorFuncHeader("", nodeId)+ ";", +"};" + }; + + for (auto elem : genClsDecl) + str += elem + "\n"; return str; } -- Gitee From ce1730a8eb3ab30aaf816c757d87ccaa985c689f Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 4 Mar 2022 18:47:42 -0800 Subject: [PATCH 11/44] Add a test case to use 'if' and 'try' as method names of a class --- .../test/typescript/unit_tests/class6.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/class6.ts diff --git a/src/MapleFE/test/typescript/unit_tests/class6.ts b/src/MapleFE/test/typescript/unit_tests/class6.ts new file mode 100644 index 0000000000..ad924fc067 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/class6.ts @@ -0,0 +1,20 @@ +class Klass { + public num: number = 1; + + if(n: number): boolean { + return this.num == n; + } + + try(n: number): void { + if(n == this.num) + console.log("EQ"); + else + console.log("NE"); + } +} + +var obj: Klass = new Klass(); +console.log(obj.if(0)); +console.log(obj.if(1)); +obj.try(0); +obj.try(1); -- Gitee From 6fcda5156113de33ff0c59a6ec5059ecd231dbe4 Mon Sep 17 00:00:00 2001 From: yehandong Date: Sat, 5 Mar 2022 14:34:33 +0800 Subject: [PATCH 12/44] Support 'try' as property name. --- .../typescript/unit_tests/class6.ts.result | 34 +++++++++++++++++++ src/MapleFE/typescript/stmt.spec | 1 + 2 files changed, 35 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/class6.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/class6.ts.result b/src/MapleFE/test/typescript/unit_tests/class6.ts.result new file mode 100644 index 0000000000..08a20f91d9 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/class6.ts.result @@ -0,0 +1,34 @@ +Matched 61 tokens. +Matched 71 tokens. +Matched 83 tokens. +Matched 95 tokens. +Matched 102 tokens. +Matched 109 tokens. +============= Module =========== +== Sub Tree == +class Klass + Fields: + num=1 + Instance Initializer: + Constructors: + Methods: + func if(n) throws: + return this.num EQ n + func try(n) throws: + cond-branch cond:n EQ this.num + true branch : + console.log("EQ") false branch : + console.log("NE") + LocalClasses: + LocalInterfaces: + +== Sub Tree == +js_var Decl: obj=new Klass() +== Sub Tree == +console.log(obj.if(0)) +== Sub Tree == +console.log(obj.if(1)) +== Sub Tree == +obj.try(0) +== Sub Tree == +obj.try(1) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 6c124b7dba..df15278a57 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -359,6 +359,7 @@ rule KeywordPropName : ONEOF("break", "export", "const", "if", + "try", "else", "continue", "implements", -- Gitee From c2fa9d6b5f80139a68709715693ed14e0ad31bd8 Mon Sep 17 00:00:00 2001 From: yehandong Date: Sat, 5 Mar 2022 16:08:31 +0800 Subject: [PATCH 13/44] Handle the NoLineTerminator feature in JS. --- src/MapleFE/autogen/reserved.spec | 1 + src/MapleFE/shared/include/rule_summary.h | 1 + src/MapleFE/shared/src/parser.cpp | 41 +++++++++++++++---- .../unit_tests/semicolon-missing15.ts.result | 8 ++++ src/MapleFE/typescript/stmt.spec | 4 +- 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result diff --git a/src/MapleFE/autogen/reserved.spec b/src/MapleFE/autogen/reserved.spec index 1832b7c5dc..cd258684dc 100644 --- a/src/MapleFE/autogen/reserved.spec +++ b/src/MapleFE/autogen/reserved.spec @@ -39,3 +39,4 @@ rule IRREGULAR_CHAR : "this_is_for_fake_rule" rule UTF8 : "this_is_for_fake_rule" rule TemplateLiteral : "this_is_for_fake_rule" rule RegularExpression : "this_is_for_fake_rule" +rule NoLineTerminator : "this_is_for_fake_rule" diff --git a/src/MapleFE/shared/include/rule_summary.h b/src/MapleFE/shared/include/rule_summary.h index 5487d3d070..014cc3ba47 100644 --- a/src/MapleFE/shared/include/rule_summary.h +++ b/src/MapleFE/shared/include/rule_summary.h @@ -28,6 +28,7 @@ extern RuleTable TblHEXDIGIT; extern RuleTable TblUTF8; extern RuleTable TblIRREGULAR_CHAR; +extern RuleTable TblNoLineTerminator; extern RuleTable TblTemplateLiteral; extern RuleTable TblRegularExpression; extern RuleTable TblExpression; diff --git a/src/MapleFE/shared/src/parser.cpp b/src/MapleFE/shared/src/parser.cpp index ea109fc5f0..a3f8139a95 100644 --- a/src/MapleFE/shared/src/parser.cpp +++ b/src/MapleFE/shared/src/parser.cpp @@ -870,6 +870,10 @@ bool Parser::LookAheadFail(RuleTable *rule_table, unsigned token) { if (curr_token->IsTempLit() || curr_token->IsRegExpr()) found = true; } + if (rule_table == &TblNoLineTerminator) { + if (!curr_token->mLineBegin) + found = true; + } } break; case LA_Identifier: @@ -1204,6 +1208,14 @@ bool Parser::TraverseRuleTableRegular(RuleTable *rule_table, AppealNode *appeal) if ((rule_table == &TblRegularExpression)) return TraverseRegularExpression(rule_table, appeal); + if (rule_table == &TblNoLineTerminator) { + Token *token = mActiveTokens.ValueAtIndex(mCurToken); + if (token->mLineBegin) + return false; + else + return true; + } + EntryType type = rule_table->mType; switch(type) { case ET_Oneof: @@ -1697,17 +1709,21 @@ bool Parser::TraverseConcatenate(RuleTable *rule_table, AppealNode *appeal) { bool turned_on_AltToken = false; for (unsigned i = 0; i < rule_table->mNum; i++) { - bool is_zeroxxx = false; + bool is_zeroxxx = false; // If the table is Zeroorxxx(), or NoLineTerminator. + bool no_line_term = false; // If the table is NoLineTerminator + bool no_line_term_met = false; // If the table is NoLineTerminator and token is no line term. bool is_asi = false; bool is_token = false; bool old_mInAltTokensMatching = mInAltTokensMatching; TableData *data = rule_table->mData + i; if (data->mType == DT_Subtable) { - RuleTable *zero_rt = data->mData.mEntry; - if (zero_rt->mType == ET_Zeroormore || zero_rt->mType == ET_Zeroorone) + RuleTable *curr_rt = data->mData.mEntry; + if (curr_rt == &TblNoLineTerminator) + no_line_term = true; + if (curr_rt->mType == ET_Zeroormore || curr_rt->mType == ET_Zeroorone) is_zeroxxx = true; - if (zero_rt->mType == ET_ASI) + if (curr_rt->mType == ET_ASI) is_asi = true; } else if (data->mType == DT_Token) { is_token = true; @@ -1749,11 +1765,18 @@ bool Parser::TraverseConcatenate(RuleTable *rule_table, AppealNode *appeal) { } } + if ((prev_succ_tokens.GetNum() == 1) && no_line_term) { + unsigned prev = prev_succ_tokens.ValueAtIndex(0); + Token *t = GetActiveToken(prev + 1); + if (!t->mLineBegin) + no_line_term_met = true; + } + // for Zeroorone/Zeroormore node it always returns true. NO matter how // many tokens it really matches, 'zero' is also a correct match. we // need take it into account so that the next rule table can try // on it. - if (!is_zeroxxx) + if (!is_zeroxxx && !no_line_term_met) prev_succ_tokens.Clear(); // is_zeroxxx seems redundant because the traversal should always be true. @@ -1887,8 +1910,10 @@ void Parser::SetIsDone(RuleTable *rt, unsigned start_token) { SuccMatch *succ = &gSucc[rt->mIndex]; bool found = succ->GetStartToken(start_token); - MASSERT(found); - succ->SetIsDone(); + if (rt != &TblNoLineTerminator) { + MASSERT(found); + succ->SetIsDone(); + } } ///////////////////////////////////////////////////////////////////////////// @@ -2276,7 +2301,7 @@ void Parser::SortOutConcatenate(AppealNode *parent) { if (!child) { if (data->mType == DT_Subtable) { RuleTable *table = data->mData.mEntry; - if (table->mType == ET_Zeroorone || table->mType == ET_Zeroormore) + if (table->mType == ET_Zeroorone || table->mType == ET_Zeroormore || table == &TblNoLineTerminator) good_child = true; if (table->mType == ET_ASI) good_child = true; diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result new file mode 100644 index 0000000000..78c460f980 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result @@ -0,0 +1,8 @@ +Matched 7 tokens. +Matched 93 tokens. +============= Module =========== +== Sub Tree == +js_var Decl: n=1 +== Sub Tree == +A switch + diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index df15278a57..0e2c8a9b1b 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -1155,9 +1155,9 @@ rule ContinueStatement : ONEOF( ## break [no LineTerminator here] LabelIdentifier[?Yield] ; rule BreakStatement : ONEOF( "break" + ZEROORONE(';'), - "break" + LabelIdentifier + ZEROORONE(';')) + "break" + NoLineTerminator + LabelIdentifier + ZEROORONE(';')) attr.action.%1 : BuildBreak() - attr.action.%2 : BuildBreak(%2) + attr.action.%2 : BuildBreak(%3) ##----------------------------------- ##rule ReturnStatement[Yield] : -- Gitee From d623e5652bd02093dba4fa68a7a3046f859ec0ad Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sun, 6 Mar 2022 16:02:23 -0500 Subject: [PATCH 14/44] combine args and return typeidx into a single vector for function type --- src/MapleFE/shared/include/ast_type.h | 6 ++---- src/MapleFE/shared/include/typetable.h | 10 ++++++++- src/MapleFE/shared/src/ast_type.cpp | 4 +--- src/MapleFE/shared/src/typetable.cpp | 28 ++++++++++++++++++++------ 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/MapleFE/shared/include/ast_type.h b/src/MapleFE/shared/include/ast_type.h index 0936dfeff5..31e78d25dd 100644 --- a/src/MapleFE/shared/include/ast_type.h +++ b/src/MapleFE/shared/include/ast_type.h @@ -172,18 +172,16 @@ public: class FunctionTypeNode : public TreeNode { private: SmallVector mParams; // type index of formal parameters - unsigned mRetType; // type index of return type + // and return which is the last one public: - FunctionTypeNode() : TreeNode(NK_FunctionType), mRetType(0) {} + FunctionTypeNode() : TreeNode(NK_FunctionType) {} ~FunctionTypeNode(){} unsigned GetParamsNum() {return mParams.GetNum();} unsigned GetParam(unsigned i) {return mParams.ValueAtIndex(i);} void SetParam(unsigned i, unsigned n) {*(mParams.RefAtIndex(i)) = n;} void AddParam(unsigned i) {mParams.PushBack(i);} - void SetRetType(unsigned i) {mRetType = i;} - unsigned GetRetType() {return mRetType;} void ClearParam() {mParams.Clear();} bool IsEqual(FunctionTypeNode *f); diff --git a/src/MapleFE/shared/include/typetable.h b/src/MapleFE/shared/include/typetable.h index c6bbcd2ca0..5f8d36d743 100644 --- a/src/MapleFE/shared/include/typetable.h +++ b/src/MapleFE/shared/include/typetable.h @@ -27,6 +27,7 @@ #include #include "massert.h" #include "ast.h" +#include "ast_type.h" namespace maplefe { @@ -53,6 +54,7 @@ private: std::unordered_map mNodeId2TypeIdxMap; std::unordered_map mTypeId2TypeMap; std::unordered_set mPrimTypeId; + std::unordered_set mFuncTypeIdx; unsigned mPrimSize; unsigned mPreBuildSize; @@ -62,16 +64,22 @@ public: unsigned size() { return mTypeTable.size(); } unsigned GetPreBuildSize() { return mPreBuildSize; } + + bool IsPrimTypeId(TypeId tid) { return mPrimTypeId.find(tid) != mPrimTypeId.end(); } unsigned GetPrimSize() { return mPrimSize; } TreeNode *CreatePrimType(std::string name, TypeId tid); TreeNode *CreateBuiltinType(std::string name, TypeId tid); + void AddPrimTypeId(TypeId tid); void AddPrimAndBuiltinTypes(); bool AddType(TreeNode *node); + TypeEntry *GetTypeEntryFromTypeIdx(unsigned tidx); TreeNode *GetTypeFromTypeIdx(unsigned tidx); TreeNode *GetTypeFromTypeId(TypeId tid) { return mTypeId2TypeMap[tid]; } - bool IsPrimTypeId(TypeId tid) { return mPrimTypeId.find(tid) != mPrimTypeId.end(); } + + unsigned GetOrCreateFunctionTypeIdx(FunctionTypeNode *type); + void Dump(); }; diff --git a/src/MapleFE/shared/src/ast_type.cpp b/src/MapleFE/shared/src/ast_type.cpp index f2c58b4ea2..ad3a113481 100644 --- a/src/MapleFE/shared/src/ast_type.cpp +++ b/src/MapleFE/shared/src/ast_type.cpp @@ -181,9 +181,7 @@ static TypeId FindPrimTypeId(const char *keyword) { bool FunctionTypeNode::IsEqual(FunctionTypeNode *node) { bool result = true; - if (node->GetRetType() != mRetType) { - result = false; - } else if (node->GetParamsNum() != GetParamsNum()) { + if (node->GetParamsNum() != GetParamsNum()) { result = false; } else { for (unsigned i = 0; i < GetParamsNum(); i++) { diff --git a/src/MapleFE/shared/src/typetable.cpp b/src/MapleFE/shared/src/typetable.cpp index 6c28e9243a..00fefcd671 100644 --- a/src/MapleFE/shared/src/typetable.cpp +++ b/src/MapleFE/shared/src/typetable.cpp @@ -83,15 +83,15 @@ TreeNode *TypeTable::CreateBuiltinType(std::string name, TypeId tid) { } bool TypeTable::AddType(TreeNode *node) { - unsigned id = node->GetNodeId(); - if (mNodeId2TypeIdxMap.find(id) != mNodeId2TypeIdxMap.end()) { + unsigned nid = node->GetNodeId(); + if (mNodeId2TypeIdxMap.find(nid) != mNodeId2TypeIdxMap.end()) { return false; } - unsigned tid = mTypeTable.size(); - mNodeId2TypeIdxMap[id] = tid; - node->SetTypeIdx(tid); + unsigned tidx = mTypeTable.size(); + mNodeId2TypeIdxMap[nid] = tidx; + node->SetTypeIdx(tidx); if (node->IsUserType()) { - static_cast(node)->GetId()->SetTypeIdx(tid); + static_cast(node)->GetId()->SetTypeIdx(tidx); } TypeEntry *entry = new TypeEntry(node); mTypeTable.push_back(entry); @@ -145,6 +145,22 @@ TreeNode *TypeTable::GetTypeFromTypeIdx(unsigned idx) { return mTypeTable[idx]->GetType(); } +unsigned TypeTable::GetOrCreateFunctionTypeIdx(FunctionTypeNode *node) { + for (auto idx: mFuncTypeIdx) { + TreeNode *type = GetTypeFromTypeIdx(idx); + FunctionTypeNode *functype = static_cast(type); + bool found = functype->IsEqual(node); + if (found) { + return idx; + } + } + bool status = AddType(node); + MASSERT(status && "failed to add a functiontype"); + unsigned idx = node->GetTypeIdx(); + mFuncTypeIdx.insert(idx); + return idx; +} + void TypeTable::Dump() { std::cout << "===================== TypeTable =====================" << std::endl; std::cout << " tid:type-name: node-kind node-id" << std::endl; -- Gitee From 5e1b4563fc6d046d6bb19621935f09d2855d732c Mon Sep 17 00:00:00 2001 From: Wen HU Date: Mon, 7 Mar 2022 13:58:34 -0500 Subject: [PATCH 15/44] setup typeidx for functions --- src/MapleFE/astopt/include/ast_info.h | 15 +++++++++++++++ src/MapleFE/astopt/src/ast_info.cpp | 22 ++++++++++++++++++++++ src/MapleFE/astopt/src/ast_ti.cpp | 11 ++++++----- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/MapleFE/astopt/include/ast_info.h b/src/MapleFE/astopt/include/ast_info.h index de56fcf645..83a0fc3712 100644 --- a/src/MapleFE/astopt/include/ast_info.h +++ b/src/MapleFE/astopt/include/ast_info.h @@ -154,6 +154,21 @@ class ClassStructVisitor : public AstVisitor { FunctionNode *VisitFunctionNode(FunctionNode *node); }; +class FunctionVisitor : public AstVisitor { + private: + Module_Handler *mHandler; + AST_INFO *mInfo; + + public: + explicit FunctionVisitor(Module_Handler *h, unsigned f, bool base = false) + : AstVisitor((f & FLG_trace_1) && base), mHandler(h) { + mInfo= mHandler->GetINFO(); + } + ~FunctionVisitor() = default; + + FunctionNode *VisitFunctionNode(FunctionNode *node); +}; + class FindStrIdxVisitor : public AstVisitor { private: Module_Handler *mHandler; diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index 650fe12dfd..1bc650be8e 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -67,6 +67,10 @@ void AST_INFO::CollectInfo() { mPass = 2; MSGNOLOC0("============== merge class/interface/struct =============="); visitor.Visit(module); + + // collect function types + FunctionVisitor func_visitor(mHandler, mFlags, true); + func_visitor.Visit(module); } void AST_INFO::AddBuiltInTypes() { @@ -936,6 +940,24 @@ FunctionNode *ClassStructVisitor::VisitFunctionNode(FunctionNode *node) { return node; } +FunctionNode *FunctionVisitor::VisitFunctionNode(FunctionNode *node) { + FunctionTypeNode *functype = mHandler->NewTreeNode(); + TreeNode *n = NULL; + for (unsigned i = 0; i < node->GetParamsNum(); i++) { + n = node->GetParam(i); + functype->AddParam(n ? n->GetTypeIdx() : 0); + } + + // add return + n = node->GetType(); + functype->AddParam(n ? n->GetTypeIdx() : 0); + + unsigned tidx = gTypeTable.GetOrCreateFunctionTypeIdx(functype); + node->SetTypeIdx(tidx); + + return node; +} + IdentifierNode *FindStrIdxVisitor::VisitIdentifierNode(IdentifierNode *node) { (void) AstVisitor::VisitIdentifierNode(node); if (node->GetStrIdx() == mStrIdx) { diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 3d75298fa6..c4813dc972 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -1185,13 +1185,17 @@ CastNode *TypeInferVisitor::VisitCastNode(CastNode *node) { AsTypeNode *TypeInferVisitor::VisitAsTypeNode(AsTypeNode *node) { (void) AstVisitor::VisitAsTypeNode(node); TreeNode *dest = node->GetType(); - SetTypeId(node, dest); + if (node->GetTypeIdx() == 0) { + SetTypeId(node, dest); + } TreeNode *parent = node->GetParent(); if (parent) { // pass to parent, need refine if multiple AsTypeNode if (parent->GetAsTypesNum() == 1 && parent->GetAsTypeAtIndex(0) == node) { - SetTypeId(parent, dest); + if (parent->GetTypeIdx() == 0) { + SetTypeId(parent, dest); + } } } return node; @@ -1532,9 +1536,6 @@ FunctionNode *TypeInferVisitor::VisitFunctionNode(FunctionNode *node) { if (node->GetFuncName()) { SetTypeId(node->GetFuncName(), node->GetTypeId()); } - if (node->GetType()) { - SetTypeIdx(node, node->GetType()->GetTypeIdx()); - } return node; } -- Gitee From 558e9988e9c5458b5e6d9ef640c2b02518531e70 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Mon, 7 Mar 2022 13:59:30 -0500 Subject: [PATCH 16/44] add dummy emiter for function type --- src/MapleFE/ast2cpp/include/emitter.h | 1 + src/MapleFE/ast2cpp/src/emitter.cpp | 9 +++++++++ src/MapleFE/shared/include/ast_type.h | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/MapleFE/ast2cpp/include/emitter.h b/src/MapleFE/ast2cpp/include/emitter.h index 59178b2881..f8447db756 100644 --- a/src/MapleFE/ast2cpp/include/emitter.h +++ b/src/MapleFE/ast2cpp/include/emitter.h @@ -124,6 +124,7 @@ public: virtual std::string EmitModuleNode(ModuleNode *node); virtual std::string EmitAttrNode(AttrNode *node); virtual std::string EmitArrayTypeNode(ArrayTypeNode *node); + virtual std::string EmitFunctionTypeNode(FunctionTypeNode *node); virtual std::string EmitPrimTypeNode(PrimTypeNode *node); virtual std::string EmitPrimArrayTypeNode(PrimArrayTypeNode *node); diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index 3ae234f9db..506370f991 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -1973,6 +1973,12 @@ std::string Emitter::EmitArrayTypeNode(ArrayTypeNode *node) { return str; } +std::string Emitter::EmitFunctionTypeNode(FunctionTypeNode *node) { + // TODO + std::string str = ""; + return str; +} + std::string Emitter::EmitPrimTypeNode(PrimTypeNode *node) { if (node == nullptr) return std::string(); @@ -2055,6 +2061,9 @@ std::string Emitter::EmitTreeNode(TreeNode *node) { case NK_ArrayType: return EmitArrayTypeNode(static_cast(node)); break; + case NK_FunctionType: + return EmitFunctionTypeNode(static_cast(node)); + break; case NK_UserType: return EmitUserTypeNode(static_cast(node)); break; diff --git a/src/MapleFE/shared/include/ast_type.h b/src/MapleFE/shared/include/ast_type.h index 31e78d25dd..8186eabd80 100644 --- a/src/MapleFE/shared/include/ast_type.h +++ b/src/MapleFE/shared/include/ast_type.h @@ -167,7 +167,7 @@ public: /////////////////////////////////////////////////////////////////////////////// // FunctionTypeNode -// It is used to specify function types with its signature and return type +// It is used to specify function types with its parameters and return type /////////////////////////////////////////////////////////////////////////////// class FunctionTypeNode : public TreeNode { private: -- Gitee From 17223b12047f287b3e7bd3ec42a8cf8372b486fe Mon Sep 17 00:00:00 2001 From: Ed Ching Date: Mon, 7 Mar 2022 11:33:47 -0800 Subject: [PATCH 17/44] Use common func param emit code in emitting generator function decl. --- src/MapleFE/ast2cpp/include/helper.h | 2 +- src/MapleFE/ast2cpp/src/helper.cpp | 79 +++++++++++++--------------- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index 0d88829abb..d7b566c0de 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -49,7 +49,7 @@ extern std::string ArrayCtorName(int dim, std::string type); extern bool IsBuiltinObj(std::string name); extern std::string ObjectTypeStr(std::string name); extern std::string GeneratorFuncHeader(std::string cls, unsigned nodeId); -extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false, bool byRef = false); +extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false, bool byRef = false, bool fdInit = false, bool capture = false); class FuncTable { private: diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 2c4d0a70c4..46b926f960 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -95,27 +95,35 @@ std::string GenClassFldAddProp(std::string objName, return str; } -// TS function paramteri mapping to C++: +// From TS func param info, generate param and arg list for corresponding mapped C++ func. // -// TS2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list -// which will be generated from AST if "this" is declared as a TS func parameter -// as required by TS strict mode. However TS funcs that do not reference 'this' -// are not required to declare it, in which case emitter has to insert one. +// Different formats of arg list as needed by C++ mapping of function/class/generators +// - args for function class functor and generation class constructor +// () - generator class constructor field init list +// & - args passed by reference to generation function _body method +// ; - generator class fields for capturing closure // -// Cases: -// if TS func has no param -// - insert param "ts2crt::Object* _this" -// if 1st TS func param is not "this" -// - insert param "ts2crt::Object* _this" -// if 1st TS func param is "this" -// - rename to "_this" -// - if type is Any (JS_Val), change to "ts2crt::Object*" -// -std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly, bool byRef) { +std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly, bool byRef, bool fdInit, bool capture) { std::vector> funcParams = hFuncTable.GetArgInfo(nodeId); std::string ObjT = "t2crt::Object*"; std::string str; + // "this" in TS function paramter mapping to C++: + // + // TS2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list + // which will be generated from AST if "this" is declared as a TS func parameter + // as required by TS strict mode. However TS funcs that do not reference 'this' + // are not required to declare it, in which case emitter has to insert one. + // + // Cases: + // if TS func has no param + // - insert param "ts2crt::Object* _this" + // if 1st TS func param is not "this" + // - insert param "ts2crt::Object* _this" + // if 1st TS func param is "this" + // - rename to "_this" + // - if type is Any (JS_Val), change to "ts2crt::Object*" + // if (handleThis) { if (funcParams.size() == 0) // func has no param return argsOnly ? "_this"s : (ObjT + " _this"); @@ -130,14 +138,19 @@ std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly, bool if (name.compare("this") != 0) // if not "this", insert _this str += argsOnly? ("_this, "s): (ObjT + " _this, "s); else { // if "this" - name = "_this"; + name = "_this"; // rename to "_this" if (type.compare("t2crt::JS_Val") == 0) type = ObjT; // change type Any to Object* } } first = false; } - str += argsOnly? name: (type + (byRef?"\&":"") + " "s + name); + if (fdInit) + str += name + "(" + name + ")"; + else if (capture) + str += type + " " + name + ";\n"; + else + str += argsOnly? name: (type + (byRef?"\&":"") + " "s + name); } return str; } @@ -204,37 +217,19 @@ std::string GeneratorFuncHeader(std::string cls, unsigned nodeId) { return "t2crt::IteratorResult " + cls + "_body(t2crt::Object* _this, void*& yield" + params + ")"; } -// Template for generating Generators and Generator Functions: +// Generating Generators and Generator Functions: // For each TS generator function, 2 C++ classes: generator and generator function are emitted. // The generator function has only a single instance. It is called to create generator instances. std::string GeneratorClassDecl(std::string funcName, unsigned nodeId) { std::string str; std::string generatorName = GeneratorName(funcName); std::string generatorFuncName = GeneratorFuncName(funcName); - std::vector> params = hFuncTable.GetArgInfo(nodeId); - - // Different formats of arg list as needed by generator and generator function interfaces: - // - args for function class functor and generation class constructor - // () - generator class constructor field init list - // & - args passed by reference to generation function _body method - // ; - generator class fields for capturing closure - std::string functorArgs, ctorArgs, initList, captureFields; - - for (bool hasArg=false; auto elem : params) { - if (!hasArg) - hasArg = true; - else { - functorArgs += ", "s; - initList += ", "s; - } - std::string type = elem.first, name = elem.second; - functorArgs += type + " " + name; - initList += name + "("s+ name + ")"s; - captureFields += tab(1) + type + " " + name + ";\n"s; - } - if (!initList.empty()) - initList = ", " + initList; - ctorArgs = functorArgs.empty()? std::string(): (", "s + functorArgs); + + std::string functorArgs = FunctionParams(nodeId, false, false); + std::string initList = FunctionParams(nodeId, false, false, false, true) ; + std::string captureFields = FunctionParams(nodeId, false, false, false, false, true); + std::string ctorArgs = functorArgs.empty()? std::string(): (", "s + functorArgs); + initList = initList.empty()? "": (", "s + initList); std::string genClsDecl[] = { "// " +funcName+ " generators", -- Gitee From 8e6ff62941795c2b81e33da4428658de575eade7 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Mon, 7 Mar 2022 17:12:55 -0500 Subject: [PATCH 18/44] add target ast2cpp.a --- src/MapleFE/ast2cpp/src/Makefile | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/MapleFE/ast2cpp/src/Makefile b/src/MapleFE/ast2cpp/src/Makefile index 32bb62fbc3..084bcad114 100644 --- a/src/MapleFE/ast2cpp/src/Makefile +++ b/src/MapleFE/ast2cpp/src/Makefile @@ -27,10 +27,12 @@ SRCG := $(wildcard $(BUILDGEN)/gen*.cpp) OBJG := $(patsubst %.cpp, %.o, $(SRCG)) DEPG := $(patsubst %.cpp, %.d, $(SRCG)) -OBJS :=$(foreach obj,$(OBJ), $(BUILD)/$(obj)) $(OBJG) -DEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) $(DEPG) +LOCALOBJS :=$(foreach obj,$(OBJ), $(BUILD)/$(obj)) +LOCALDEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) +OBJS :=$(LOCALOBJS) $(OBJG) +DEPS :=$(LOCALDEPS) $(DEPG) -LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(OBJS)) +LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(LOCALOBJS)) GENDIR:=${BUILDDIR}/ast_gen/shared @@ -45,6 +47,8 @@ INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ INCLUDEGEN := -I $(MAPLEFE_ROOT)/shared/include -I $(BUILDDIR)/gen -I $(BUILDASTGEN) TARGET=ast2cpp +TARGET_A=ast2cpp.a + SHAREDLIB = $(BUILDDIR)/astopt/astopt.a $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a LANGSPEC=$(BUILDDIR)/typescript/lang_spec.o @@ -78,9 +82,12 @@ $(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) +$(BUILD)/$(TARGET_A): $(LIBOBJS) + /usr/bin/ar rcs $(BUILD)/$(TARGET_A) $(LIBOBJS) + +$(BUILDBIN)/$(TARGET): $(BUILD)/$(TARGET_A) $(OBJS) $(SHAREDLIB) @mkdir -p $(BUILDBIN) - $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(LANGSPEC) $(SHAREDLIB) + $(LD) -o $(BUILDBIN)/$(TARGET) $(BUILD)/main.o $(BUILD)/$(TARGET_A) $(OBJG) $(LANGSPEC) $(SHAREDLIB) clean: rm -rf $(BUILD) -- Gitee From ccecdfb96e96e4192e1510fa95b3d6facabc0e5c Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Mon, 7 Mar 2022 16:42:04 -0800 Subject: [PATCH 19/44] Add a test case for template literal type --- .../typescript/unit_tests/template-literal-type.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/template-literal-type.ts diff --git a/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts new file mode 100644 index 0000000000..073bae7598 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts @@ -0,0 +1,12 @@ +class Num { + neg: boolean = false; + val: number = 0; +} + +function func(v: Num): `${string}n` | `-${string}n` { + return `${v.neg ? '-' : ''}${v.val}n`; +} + +var obj : Num = {neg: true, val: 123}; +console.log(func(obj)); +console.log(typeof func(obj)); -- Gitee From 79845c32096606023545896282528eced38b646e Mon Sep 17 00:00:00 2001 From: Wen HU Date: Tue, 8 Mar 2022 09:38:47 -0500 Subject: [PATCH 20/44] pass IsGeneratorUsed from decl to identifier node --- 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 c4813dc972..6b25880245 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -1627,6 +1627,8 @@ IdentifierNode *TypeInferVisitor::VisitIdentifierNode(IdentifierNode *node) { UpdateTypeId(node, decl); UpdateTypeIdx(node, decl); } + // pass IsGeneratorUsed + mHandler->UpdateGeneratorUsed(node->GetNodeId(), decl->GetNodeId()); } else { NOTYETIMPL("node not declared"); MSGNOLOC0(node->GetName()); -- Gitee From 28f9f4f973d6d065afcf3d9a5fd02902f84e02ae Mon Sep 17 00:00:00 2001 From: Wen HU Date: Tue, 8 Mar 2022 10:53:03 -0500 Subject: [PATCH 21/44] add tools/obfuscate --- src/MapleFE/Makefile | 7 +- src/MapleFE/tools/obfuscate/Makefile | 27 ++++ .../tools/obfuscate/include/obfuscate.h | 52 +++++++ src/MapleFE/tools/obfuscate/src/Makefile | 90 +++++++++++ src/MapleFE/tools/obfuscate/src/main.cpp | 108 +++++++++++++ src/MapleFE/tools/obfuscate/src/obfuscate.cpp | 147 ++++++++++++++++++ 6 files changed, 429 insertions(+), 2 deletions(-) create mode 100644 src/MapleFE/tools/obfuscate/Makefile create mode 100644 src/MapleFE/tools/obfuscate/include/obfuscate.h create mode 100644 src/MapleFE/tools/obfuscate/src/Makefile create mode 100644 src/MapleFE/tools/obfuscate/src/main.cpp create mode 100644 src/MapleFE/tools/obfuscate/src/obfuscate.cpp diff --git a/src/MapleFE/Makefile b/src/MapleFE/Makefile index a0d1730fdc..f1dbcac61d 100644 --- a/src/MapleFE/Makefile +++ b/src/MapleFE/Makefile @@ -14,7 +14,7 @@ include Makefile.in -TARGS = autogen shared recdetect ladetect astopt java2mpl ast2mpl ts2ast ast2cpp c2ast +TARGS = autogen shared recdetect ladetect astopt java2mpl ast2mpl ts2ast ast2cpp c2ast obfuscate # create BUILDDIR first $(shell $(MKDIR_P) $(BUILDDIR)) @@ -22,7 +22,7 @@ $(shell $(MKDIR_P) $(BUILDDIR)) ifeq ($(SRCLANG),java) TARGET := java2ast ast2mpl else ifeq ($(SRCLANG),typescript) - TARGET := ts2ast ast2cpp + TARGET := ts2ast ast2cpp obfuscate else ifeq ($(SRCLANG),c) TARGET := c2ast endif @@ -53,6 +53,9 @@ astopt: shared recdetect ladetect ast2cpp: astopt ts2ast $(MAKE) -C ast2cpp +obfuscate: astopt ts2ast ast2cpp + $(MAKE) -C tools/obfuscate + shared: autogen $(MAKE) -C shared diff --git a/src/MapleFE/tools/obfuscate/Makefile b/src/MapleFE/tools/obfuscate/Makefile new file mode 100644 index 0000000000..41d43c8f5c --- /dev/null +++ b/src/MapleFE/tools/obfuscate/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +# +# OpenArkFE is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# +# http://license.coscl.org.cn/MulanPSL2 +# +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +# FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +# + +include ../../Makefile.in + +all: + $(MAKE) -C src + +clean: + rm -rf $(BUILDDIR)/tools/obfuscate + +test: + $(MAKE) -C ../test p + +.PHONY: $(TARGS) + diff --git a/src/MapleFE/tools/obfuscate/include/obfuscate.h b/src/MapleFE/tools/obfuscate/include/obfuscate.h new file mode 100644 index 0000000000..63574ba6d0 --- /dev/null +++ b/src/MapleFE/tools/obfuscate/include/obfuscate.h @@ -0,0 +1,52 @@ +/* +* Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +* +* OpenArkFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +////////////////////////////////////////////////////////////////////////////////////////////// +// This is the interface to translate AST to C++ +////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __OBFUSCATE_HEADER__ +#define __OBFUSCATE_HEADER__ + +#include "astopt.h" +#include "ast_handler.h" +#include "ast_module.h" + +namespace maplefe { + +class Obfuscate : public AstOpt { +private: + AST_Handler *mASTHandler; + unsigned mFlags; + unsigned mIndexImported; + +public: + explicit Obfuscate(AST_Handler *h, unsigned flags) : + AstOpt(h, flags), + mASTHandler(h), + mFlags(flags), + mIndexImported(0) {} + ~Obfuscate() = default; + + void EmitTS(); + bool LoadImportedModules(); + + // return 0 if successful + // return non-zero if failed + int ProcessAST(); +}; + +} +#endif diff --git a/src/MapleFE/tools/obfuscate/src/Makefile b/src/MapleFE/tools/obfuscate/src/Makefile new file mode 100644 index 0000000000..f8453d6a3e --- /dev/null +++ b/src/MapleFE/tools/obfuscate/src/Makefile @@ -0,0 +1,90 @@ +# Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +# +# OpenArkFE is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# +# http://license.coscl.org.cn/MulanPSL2 +# +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +# FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +# + +include ../../../Makefile.in +BUILDBIN=$(BUILDDIR)/bin +BUILD=$(BUILDDIR)/tools/obfuscate +BUILDGEN=$(BUILDDIR)/gen +BUILDASTGEN=$(BUILDDIR)/ast_gen/shared +$(shell $(MKDIR_P) $(BUILD)) + +SRC=$(wildcard *.cpp) +OBJ :=$(patsubst %.cpp,%.o,$(SRC)) +DEP :=$(patsubst %.cpp,%.d,$(SRC)) + +SRCG := $(wildcard $(BUILDGEN)/gen*.cpp) +OBJG := $(patsubst %.cpp, %.o, $(SRCG)) +DEPG := $(patsubst %.cpp, %.d, $(SRCG)) + +LOCALOBJS :=$(foreach obj,$(OBJ), $(BUILD)/$(obj)) +LOCALDEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) +OBJS :=$(LOCALOBJS) $(OBJG) +DEPS :=$(LOCALDEPS) $(DEPG) + +LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(LOCALOBJS)) + +GENDIR:=${BUILDDIR}/ast_gen/shared + +INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ + -I $(MAPLEFE_ROOT)/astopt/include \ + -I $(MAPLEFE_ROOT)/tools/obfuscate/include \ + -I $(MAPLEFE_ROOT)/ast2cpp/include \ + -I $(MAPLEFE_ROOT)/autogen/include \ + -I $(MAPLEFE_ROOT)/shared/include \ + -I $(MAPLEFE_ROOT)/typescript/include \ + $(MAPLEALL_INC) -I ${GENDIR} + +INCLUDEGEN := -I $(MAPLEFE_ROOT)/shared/include -I $(BUILDDIR)/gen -I $(BUILDASTGEN) + +TARGET=obfuscate + +SHAREDLIB = $(BUILDDIR)/ast2cpp/ast2cpp.a $(BUILDDIR)/astopt/astopt.a $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a +LANGSPEC=$(BUILDDIR)/typescript/lang_spec.o + +.PHONY: all +all: $(BUILDBIN)/$(TARGET) + +-include $(DEPS) +.PHONY: clean + +vpath %.o $(BUILD) +vpath %.d $(BUILD) + +#Pattern Rules +$(BUILD)/%.o : %.cpp + $(CXX) $(CXXFLAGS) -fpermissive $(INCLUDES) -w -c $< -o $@ + +$(BUILD)/%.d : %.cpp + @$(CXX) $(CXXFLAGS) -MM $(INCLUDES) $< > $@ + @mv -f $(BUILD)/$*.d $(BUILD)/$*.d.tmp + @sed -e 's|.*:|$(BUILD)/$*.o:|' < $(BUILD)/$*.d.tmp > $(BUILD)/$*.d + @rm -f $(BUILD)/$*.d.tmp + +$(BUILDGEN)/%.o : $(BUILDGEN)/%.cpp $(BUILDGEN)/%.d + $(CXX) $(CXXFLAGS) -fpermissive $(INCLUDEGEN) -w -c $< -o $@ + +$(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp + @$(CXX) $(CXXFLAGS) -std=c++11 -MM $(INCLUDEGEN) $< > $@ + @mv -f $(BUILDGEN)/$*.d $(BUILDGEN)/$*.d.tmp + @sed -e 's|.*:|$(BUILDGEN)/$*.o:|' < $(BUILDGEN)/$*.d.tmp > $(BUILDGEN)/$*.d + @rm -f $(BUILDGEN)/$*.d.tmp + +# TARGET depends on OBJS and shared OBJS from shared directory +# as well as mapleall libraries +$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) + @mkdir -p $(BUILDBIN) + $(LD) -o $(BUILDBIN)/$(TARGET) $(LOCALOBJS) $(OBJG) $(LANGSPEC) $(SHAREDLIB) + +clean: + rm -rf $(BUILD) diff --git a/src/MapleFE/tools/obfuscate/src/main.cpp b/src/MapleFE/tools/obfuscate/src/main.cpp new file mode 100644 index 0000000000..7eb882bd04 --- /dev/null +++ b/src/MapleFE/tools/obfuscate/src/main.cpp @@ -0,0 +1,108 @@ +/* +* Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +* +* OpenArkFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#include +#include +#include +#include "gen_astload.h" +#include "ast_handler.h" +#include "obfuscate.h" + +static void help() { + std::cout << "ast2cpp a.ast[,b.ast] [options]:" << std::endl; + std::cout << " --out=x.cpp : cpp output file" << std::endl; + std::cout << " --help : print this help" << std::endl; + std::cout << " --trace=n : Emit trace with 4-bit combo levels 1...15" << std::endl; + std::cout << " 1 : Emit ast tree visits" << std::endl; + std::cout << " 2 : Emit graph" << std::endl; + std::cout << " --emit-ts-only : Emit ts code only" << std::endl; + std::cout << " --emit-ts : Emit ts code" << std::endl; + std::cout << " --format-cpp : Format cpp" << std::endl; + std::cout << " --no-imported : Do not process the imported modules" << std::endl; + std::cout << "default out name uses the first input name: a.cpp" << std::endl; +} + +int main (int argc, char *argv[]) { + if (argc == 1 || (!strncmp(argv[1], "--help", 6) && (strlen(argv[1]) == 6))) { + help(); + exit(-1); + } + + unsigned flags; + // one or more input .ast files separated by ',' + const char *inputname = argv[1]; + // output .cpp file + const char *outputname = nullptr; + + // Parse the argument + for (unsigned i = 2; i < argc; i++) { + if (!strncmp(argv[i], "--trace=", 8)) { + int val = atoi(argv[i] + 8); + if (val < 1 || val > 15) { + help(); + exit(-1); + } + flags |= val; + } else if (!strncmp(argv[i], "--emit-ts-only", 14)) { + flags |= maplefe::FLG_emit_ts_only; + } else if (!strncmp(argv[i], "--emit-ts", 9)) { + flags |= maplefe::FLG_emit_ts; + } else if (!strncmp(argv[i], "--format-cpp", 12)) { + flags |= maplefe::FLG_format_cpp; + } else if (!strncmp(argv[i], "--no-imported", 13)) { + flags |= maplefe::FLG_no_imported; + } else if (!strncmp(argv[i], "--in=", 5)) { + inputname = argv[i]+5; + } else if (!strncmp(argv[i], "--out=", 6)) { + outputname = argv[i]+6; + } else { + std::cerr << "unknown option " << argv[i] << std::endl; + exit(-1); + } + } + + // input ast files + std::vector inputfiles; + if (inputname) { + std::stringstream ss; + ss.str(inputname); + std::string item; + while (std::getline(ss, item, ',')) { + // std::cout << "item " << item << " xxx"<< std::endl; + inputfiles.push_back(item); + } + } + + unsigned trace = (flags & maplefe::FLG_trace); + maplefe::AST_Handler handler(trace); + for (auto astfile: inputfiles) { + std::ifstream input(astfile, std::ifstream::binary); + input >> std::noskipws; + std::istream_iterator s(input), e; + maplefe::AstBuffer vec(s, e); + maplefe::AstLoad loadAst; + maplefe::ModuleNode *mod = loadAst.LoadFromAstBuf(vec); + // add mod to the vector + while(mod) { + handler.AddModule(mod); + mod = loadAst.Next(); + } + } + + maplefe::Obfuscate *obfuscate = new maplefe::Obfuscate(&handler, flags); + int res = obfuscate->ProcessAST(); + + return res; +} diff --git a/src/MapleFE/tools/obfuscate/src/obfuscate.cpp b/src/MapleFE/tools/obfuscate/src/obfuscate.cpp new file mode 100644 index 0000000000..1b23546bb9 --- /dev/null +++ b/src/MapleFE/tools/obfuscate/src/obfuscate.cpp @@ -0,0 +1,147 @@ +/* +* Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +* +* OpenArkFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#include +#include +#include +#include +#include + +#include "obfuscate.h" +#include "ast_handler.h" +#include "gen_astdump.h" +#include "gen_astgraph.h" +#include "gen_aststore.h" +#include "gen_astload.h" +#include "cpp_definition.h" +#include "cpp_declaration.h" +#include "a2c_util.h" + +namespace maplefe { + +bool Obfuscate::LoadImportedModules() { + std::queue queue; + for (HandlerIndex i = 0; i < GetModuleNum(); i++) { + Module_Handler *handler = mASTHandler->GetModuleHandler(i); + ModuleNode *module = handler->GetASTModule(); + ImportedFiles imported(module); + imported.VisitTreeNode(module); + for(const auto &e: imported.mFilenames) + queue.push(e); + } + + bool err = false; + while(!queue.empty()) { + std::string filename = queue.front(); + queue.pop(); + if(mASTHandler->GetHandlerIndex(filename.c_str()) == HandlerNotFound) { + std::ifstream input(filename, std::ifstream::binary); + if(input.fail()) { + std::cerr << "Error: File " << filename << " not found for imported module" << std::endl; + err = true; + continue; + } + input >> std::noskipws; + std::istream_iterator s(input), e; + maplefe::AstBuffer vec(s, e); + maplefe::AstLoad loadAst; + maplefe::ModuleNode *mod = loadAst.LoadFromAstBuf(vec); + // add mod to the vector + while(mod) { + mASTHandler->AddModule(mod); + ImportedFiles imported(mod); + imported.VisitTreeNode(mod); + for(const auto &e: imported.mFilenames) + queue.push(e); + mod = loadAst.Next(); + } + } + } + return err; +} + +// starting point of AST +int Obfuscate::ProcessAST() { + mIndexImported = GetModuleNum(); + + // load all imported modules + if (!(mFlags & FLG_no_imported)) { + if (LoadImportedModules()) { + return 1; + } + } + + // loop through module handlers + for (HandlerIndex i = 0; i < GetModuleNum(); i++) { + Module_Handler *handler = mASTHandler->GetModuleHandler(i); + ModuleNode *module = handler->GetASTModule(); + + if (mFlags & FLG_trace_1) { + std::cout << "============= in ProcessAST ===========" << std::endl; + std::cout << "srcLang : " << module->GetSrcLangString() << std::endl; + + for(unsigned k = 0; k < module->GetTreesNum(); k++) { + TreeNode *tnode = module->GetTree(k); + if (mFlags & FLG_trace_1) { + tnode->Dump(0); + std::cout << std::endl; + } + } + } + + if (mFlags & FLG_trace_2) { + std::cout << "============= AstGraph ===========" << std::endl; + AstGraph graph(module); + graph.DumpGraph("After LoadFromAstBuf()", &std::cout); + } + } + + // build dependency of modules + PreprocessModules(); + + // loop through module handlers in import/export dependency order + for (auto handler: mHandlersInOrder) { + ModuleNode *module = handler->GetASTModule(); + + // basic analysis + handler->BasicAnalysis(); + + if (mFlags & FLG_trace_2) { + std::cout << "============= After BasicAnalysis ===========" << std::endl; + for(unsigned k = 0; k < module->GetTreesNum(); k++) { + TreeNode *tnode = module->GetTree(k); + if (mFlags & FLG_trace_1) { + tnode->Dump(0); + std::cout << std::endl; + } + } + AstGraph graph(module); + graph.DumpGraph("After BasicAnalysis()", &std::cout); + } + } + + for (auto handler: mHandlersInOrder) { + ModuleNode *module = handler->GetASTModule(); + + std::cout << "============= Emitter ===========" << std::endl; + maplefe::Emitter emitter(handler); + std::string code = emitter.Emit("Convert AST to TypeScript code"); + std::cout << code; + } + + return 0; +} + +} // namespace maplefe -- Gitee From 18a9519a03f20c237fb560eb377529f3908ae6e9 Mon Sep 17 00:00:00 2001 From: eching Date: Tue, 8 Mar 2022 13:33:21 -0800 Subject: [PATCH 22/44] CPP emiter with support for generator function with while loop. --- src/MapleFE/ast2cpp/include/cpp_definition.h | 9 +- src/MapleFE/ast2cpp/include/helper.h | 22 +++++ .../ast2cpp/runtime/include/builtins.h | 27 +++--- src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp | 2 + src/MapleFE/ast2cpp/src/cpp_definition.cpp | 82 +++++++++++++++++++ src/MapleFE/ast2cpp/src/helper.cpp | 33 +++++--- 6 files changed, 148 insertions(+), 27 deletions(-) diff --git a/src/MapleFE/ast2cpp/include/cpp_definition.h b/src/MapleFE/ast2cpp/include/cpp_definition.h index ff6b0c1b0c..ab4c1b0773 100644 --- a/src/MapleFE/ast2cpp/include/cpp_definition.h +++ b/src/MapleFE/ast2cpp/include/cpp_definition.h @@ -26,8 +26,9 @@ class CppDef : public CppEmitter { public: CppDecl &mCppDecl; bool mIsInit; + bool mIsGenerator; - CppDef(Module_Handler *h, CppDecl &d) : CppEmitter(h), mCppDecl(d), mIsInit(false) {} + CppDef(Module_Handler *h, CppDecl &d) : CppEmitter(h), mCppDecl(d), mIsInit(false), mIsGenerator(false) {} std::string Emit() { return EmitTreeNode(GetASTModule()); @@ -64,12 +65,14 @@ public: std::string EmitAsTypeNode(AsTypeNode *node) override; std::string EmitNamespaceNode(NamespaceNode *node) override; std::string EmitRegExprNode(RegExprNode *node); + std::string EmitStructNode(StructNode *node) override; + std::string EmitStructLiteralNode(StructLiteralNode* node) override; + std::string EmitWhileLoopNode(WhileLoopNode *node) override; + std::string EmitYieldNode(YieldNode *node) override; std::string& HandleTreeNode(std::string &str, TreeNode *node) override; std::string EmitClassProps(TreeNode *node); std::string EmitFuncScopeVarDecls(FunctionNode *node); - std::string EmitStructNode(StructNode *node); - std::string EmitStructLiteralNode(StructLiteralNode* node); std::string EmitCppCtor(ClassNode* node); std::string EmitCtorInstance(ClassNode *c); std::string EmitDefaultCtor(ClassNode *c); diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index d7b566c0de..0eb8e89843 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -29,6 +29,8 @@ using namespace std::string_literals; namespace maplefe { +extern std::string GeneratorFn_start; +extern std::string GeneratorFn_return; extern std::unordered_mapTypeIdToJSType; extern std::unordered_mapTypeIdToJSTypeCXX; @@ -51,6 +53,25 @@ extern std::string ObjectTypeStr(std::string name); extern std::string GeneratorFuncHeader(std::string cls, unsigned nodeId); extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false, bool byRef = false, bool fdInit = false, bool capture = false); +class GeneratorLabels { +private: + unsigned GenLoopId = 0; + unsigned GenYieldId= 0; +public: + std::string NextLoopLabel(void) { + std::string label = "_loop_" + std::to_string(++GenLoopId); + return label; + } + std::string NextYieldLabel(void) { + std::string label = "_yield_" + std::to_string(++GenYieldId); + return label; + } + void ResetLabels(void) { + GenLoopId = 0; + GenYieldId = 0; + } +}; + class FuncTable { private: std::unordered_map TopLevelFunc; // map nodeId to TreeNode* @@ -115,6 +136,7 @@ public: }; extern FuncTable hFuncTable; +extern GeneratorLabels GenFnLabels; } #endif // __HELPER_H__ diff --git a/src/MapleFE/ast2cpp/runtime/include/builtins.h b/src/MapleFE/ast2cpp/runtime/include/builtins.h index 8acac0e030..371a508b1d 100644 --- a/src/MapleFE/ast2cpp/runtime/include/builtins.h +++ b/src/MapleFE/ast2cpp/runtime/include/builtins.h @@ -133,12 +133,12 @@ class Error : public Object { // ecma-262 section references are based on ecma-262 edition 12.0 // ecma262 27.1.1.5 IteratorResult interface: -struct IteratorResult { - bool _done; // status of iterator next() call - JS_Val _value; // done=false: current iteration element value - // done=true: return value of the iterator, undefined if none returned - IteratorResult() : _done(true), _value(undefined) { } - IteratorResult(bool done, JS_Val val) : _done(done), _value(val) { } +struct IteratorResult : public Object { + bool done; // status of iterator next() call + JS_Val value; // done=false: current iteration element value + // done=true: return value of the iterator, undefined if none returned + IteratorResult() : done(true), value(undefined) { } + IteratorResult(bool done, JS_Val val) : done(done), value(val) { } ~IteratorResult() { } }; @@ -159,12 +159,13 @@ struct IteratorResult { // 3) %IteratorPrototype%[Symbol.iterator]() = this (current iterator instance) - used in for loops class IteratorProto : public Object { public: + IteratorResult _res; IteratorProto(Function* ctor, Object* proto) : Object(ctor, proto) { } ~IteratorProto() { } // note: the arg on an iterator's 1st next() call is ignored per spec 27.5.1.2 - virtual IteratorResult _next (JS_Val* arg = nullptr) { return IteratorResult(); } - virtual IteratorResult _return(JS_Val* val = nullptr) { return IteratorResult(); } - virtual IteratorResult _throw(Error exception) { return IteratorResult(); } + virtual IteratorResult* next (JS_Val* arg = nullptr) { return &_res; } + virtual IteratorResult* _return(JS_Val* val = nullptr) { return &_res; } + virtual IteratorResult* _throw(Error exception) { return &_res; } // TODO: %IteratorPrototype%[Symbol.iterator]() = this (current iterator instance) }; @@ -176,19 +177,19 @@ public: // Label corrected in version at tc39. class GeneratorProto : public IteratorProto { public: + IteratorResult _res; GeneratorProto(Function* ctor, Object* proto) : IteratorProto(ctor, proto) { } ~GeneratorProto() { } void* _yield = nullptr; // pointer to yield label to resume execution bool _finished = false; // flag if generator is in finished state bool _firstNext = true; // flag if first next has been called on iterator (27.5.1.2) - IteratorResult _return(JS_Val* arg = nullptr) override { - IteratorResult res; + IteratorResult* _return(JS_Val* arg = nullptr) override { _finished = true; if (arg != nullptr) { - res._value = *arg; + _res.value = *arg; } - return res; + return &_res; } }; diff --git a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp index dc0177419d..eed2b6a484 100644 --- a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp +++ b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp @@ -32,6 +32,8 @@ std::ostream& operator<< (std::ostream& out, const t2crt::JS_Val& v) { } std::ostream& operator<< (std::ostream& out, t2crt::Object *obj) { + if (obj == nullptr) + return out; out << obj->Dump(); return out; } diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index bf0f9610c9..c16661fe6e 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -257,6 +257,72 @@ std::string CppDef::EmitFuncScopeVarDecls(FunctionNode *node) { return str; } +std::string CppDef::EmitYieldNode(YieldNode *node) { + if (node == nullptr) + return std::string(); + //std::string str(node->IsTransfer() ? "yield* " : "yield "); + std::string str, res; + if (auto n = node->GetResult()) + res = EmitTreeNode(n); + else + res = "undefined"; + + std::string yieldLabel = GenFnLabels.NextYieldLabel(); + str += " yield = &&" + yieldLabel + ";\n"; // save yp + str += " res.value = t2crt::JS_Val(" +res+ ");\n"; // init value and return + str += " res.done = false;\n"; + str += " return res;\n"; + str += yieldLabel + ":\n"; // label for this yp + + mPrecedence = '\024'; + return str; +} + +std::string CppDef::EmitWhileLoopNode(WhileLoopNode *node) { +// return(Emitter::EmitWhileLoopNode(node)); + + if (node == nullptr) + return std::string(); + std::string str; + std::string loopLabel; + + if(auto n = node->GetLabel()) { + str = EmitTreeNode(n) + ":\n"s; + } + + if (mIsGenerator) { // insert label and loop cond check + loopLabel = GenFnLabels.NextLoopLabel(); + str += loopLabel + ":\n"; + if (auto n = node->GetCond()) { + std::string cond = EmitTreeNode(n); + str += " if (!(" +cond+ "))\n"; + str += " goto " +loopLabel+ "_exit;\n"; + } + } else { // normal while loop + str += "while("s; + if (auto n = node->GetCond()) { + str += EmitTreeNode(n); + } + str += ')'; + } + + if (auto n = node->GetBody()) { + str += EmitTreeNode(n) + GetEnding(n); + if (mIsGenerator) { + str.insert(str.find_first_of("{"), " "); + str.insert(str.find_last_of("}"), " "); + } + } + + if (mIsGenerator) { // insert loop back and label at loop exit + str += " goto " +loopLabel+ ";\n"; + str += loopLabel + "_exit:"; + } + + return HandleTreeNode(str, node); +} + + std::string CppDef::EmitFunctionNode(FunctionNode *node) { if (mIsInit || node == nullptr) return std::string(); @@ -265,6 +331,7 @@ std::string CppDef::EmitFunctionNode(FunctionNode *node) { std::string str; str += "\n"; str += FunctionHeader(node, mCppDecl.GetTypeString(node->GetType(), node->GetType())); + mIsGenerator = node->IsGenerator(); int bodyPos = str.size(); if (auto n = node->GetBody()) { @@ -280,6 +347,11 @@ std::string CppDef::EmitFunctionNode(FunctionNode *node) { } else str += "{}\n"s; + if (mIsGenerator) { + str.insert(str.find_first_of("{")+1, GeneratorFn_start); + str.insert(str.find_last_of("}"), GeneratorFn_return); + } + if (node->IsConstructor()) { Emitter::Replace(str, "this->", "obj->", 0); std::string ctorBody; @@ -288,6 +360,10 @@ std::string CppDef::EmitFunctionNode(FunctionNode *node) { str += EmitCtorInstance(static_cast(node->GetParent())); } + if (mIsGenerator) { + mIsGenerator = false; + GenFnLabels.ResetLabels(); + } return str; } @@ -683,9 +759,11 @@ std::string CppDef::EmitFieldNode(FieldNode *node) { std::string upper, field, propType; bool isRhs = false; // indicate if field is rhs (val) or lhs (ref) auto upnode = node->GetUpper(); + bool upperIsGenerator = false; if (upnode) { upper = EmitTreeNode(upnode); isRhs = !mHandler->IsDef(upnode); + upperIsGenerator = IsGenerator(upnode); // TODO: await TI fix for generator3.ts } if (auto n = node->GetField()) { if (isRhs) { @@ -745,6 +823,10 @@ std::string CppDef::EmitBlockNode(BlockNode *node) { for (unsigned i = 0; i < node->GetChildrenNum(); ++i) { if (auto n = node->GetChildAtIndex(i)) { std::string s = EmitTreeNode(n); + if (n->IsYield()) { + str += s; + continue; + } if (!s.empty()) str += " "s + s + GetEnding(n); } diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 46b926f960..f2543aaf58 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -16,6 +16,9 @@ namespace maplefe { +FuncTable hFuncTable; +GeneratorLabels GenFnLabels; + std::unordered_mapTypeIdToJSTypeCXX = { // AST TypeId to t2crt JS_Type mapping for JS_Val type of obj props that pts to CXX class fields {TY_Object, "t2crt::TY_CXX_Object"}, @@ -30,7 +33,18 @@ std::unordered_mapTypeIdToJSTypeCXX = { {TY_Any, "t2crt::TY_CXX_Any"}, }; -FuncTable hFuncTable; +std::string GeneratorFn_start = R"""( + t2crt::IteratorResult res; + + if (yield != nullptr) + goto *yield; +)"""; + +std::string GeneratorFn_return = R"""( + res.value = undefined; + res.done = true; + return res; +)"""; // Used to build GetProp for calls to get Object (class Object in ts2cpp.h) property std::string hlpGetJSValTypeStr(TypeId typeId) { @@ -240,7 +254,7 @@ std::string GeneratorClassDecl(std::string funcName, unsigned nodeId) { " // closure capture fields", captureFields, " // iterator interface (override _return and _throw when needed)", -" t2crt::IteratorResult _next(t2crt::JS_Val* arg = nullptr) override;", +" t2crt::IteratorResult* next(t2crt::JS_Val* arg = nullptr) override;", "};", "// " +funcName+ " generator function", "class " +generatorFuncName+ " : public t2crt::GeneratorFuncPrototype {", @@ -273,19 +287,16 @@ std::string GeneratorClassDef(std::string ns, std::string funcName, unsigned nod args = ", " + args; str = R"""( -t2crt::IteratorResult )""" + generatorName + R"""(::_next(t2crt::JS_Val* arg) { - t2crt::IteratorResult res; - +t2crt::IteratorResult* )""" + generatorName + R"""(::next(t2crt::JS_Val* arg) { if (_finished) { - res._done = true; - return res; + _res.done = true; + return &_res; } - // iterate by calling generation function with captures in generator - res = foo->_body(this, _yield)""" + args + R"""(); - if (res._done == true) + _res = foo->_body(this, _yield)""" + args + R"""(); + if (_res.done == true) _finished = true; - return res; + return &_res; } )""" + generatorName + "* "s + generatorFuncName + R"""(::operator()()""" + params + R"""() { -- Gitee From 4571af431885478aca467a95511f3121857b4416 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Tue, 8 Mar 2022 14:40:15 -0800 Subject: [PATCH 23/44] Update astdump.sh to compile original code when ts2ast fails with formatted code --- src/MapleFE/test/astdump.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MapleFE/test/astdump.sh b/src/MapleFE/test/astdump.sh index db62279ca8..02a440fad7 100755 --- a/src/MapleFE/test/astdump.sh +++ b/src/MapleFE/test/astdump.sh @@ -134,7 +134,7 @@ for ts in $LIST; do cp $ts $ts.tmp.ts clang-format-10 -i --style="{ColumnLimit: 120, JavaScriptWrapImports: false, AlignOperands: false, JavaScriptQuotes: Double}" $ts.tmp.ts sed -i 's/?? =/??=/g' $ts.tmp.ts - $TS2AST $ts.tmp.ts + $TS2AST $ts.tmp.ts || { cp $ts $ts.tmp.ts; $TS2AST $ts.tmp.ts; } if [ $? -eq 0 ]; then $AST2CPP $ts.tmp.ts.ast $TREEDIFF | sed -n '/^AstDump:/,/^}/p' | sed 's/\(mStrIdx: unsigned int, \)[0-9]* =>/\1=>/' fi > $ts.orig -- Gitee From 6b51abbe34bc7417281d3ae03c000c9e2dca4a87 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Wed, 9 Mar 2022 17:47:33 -0800 Subject: [PATCH 24/44] Minor change to eliminate unnecessary endings for ConditionalTypeNode --- src/MapleFE/ast2cpp/src/emitter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index 506370f991..207fd64679 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -704,6 +704,7 @@ std::string Emitter::EmitConditionalTypeNode(ConditionalTypeNode *node) { precd = mPrecedence; } if (auto n = node->GetTypeB()) { + str = Clean(str); if (precd < '\024') str = '(' + str + ')'; str += " extends "s + EmitTreeNode(n); -- Gitee From b05b3c80d96e8b0eb32473c05c1cffce1738b9c6 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Wed, 9 Mar 2022 21:18:40 -0800 Subject: [PATCH 25/44] Do not use clang-format-10 to format TypeScript source code --- src/MapleFE/test/astdump.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/MapleFE/test/astdump.sh b/src/MapleFE/test/astdump.sh index 02a440fad7..2260c58f95 100755 --- a/src/MapleFE/test/astdump.sh +++ b/src/MapleFE/test/astdump.sh @@ -110,8 +110,6 @@ for ts in $LIST; do T=$(sed -e "s/\(.*\)\(\.d\)\(\.ts-$PROCID.out\)/\1\2\3\2/" <<< "$ts-$PROCID.out.ts") eval $cmd <<< "$out" > "$T" [ -z "$NAME" ] || sed -i 's/__v[0-9][0-9]*//g' "$T" - clang-format-10 -i --style="{ColumnLimit: 120, JavaScriptWrapImports: false, AlignOperands: false}" "$T" - sed -i -e 's/?? =/??=/g' -e 's/ int\[/ number[/g' "$T" echo -e "\n====== TS Reformatted ======\n" $HIGHLIGHT "$T" echo TREEDIFF=$TREEDIFF @@ -132,9 +130,7 @@ for ts in $LIST; do [ -n "$KEEP" ] || rm -f "$T" else cp $ts $ts.tmp.ts - clang-format-10 -i --style="{ColumnLimit: 120, JavaScriptWrapImports: false, AlignOperands: false, JavaScriptQuotes: Double}" $ts.tmp.ts - sed -i 's/?? =/??=/g' $ts.tmp.ts - $TS2AST $ts.tmp.ts || { cp $ts $ts.tmp.ts; $TS2AST $ts.tmp.ts; } + $TS2AST $ts.tmp.ts if [ $? -eq 0 ]; then $AST2CPP $ts.tmp.ts.ast $TREEDIFF | sed -n '/^AstDump:/,/^}/p' | sed 's/\(mStrIdx: unsigned int, \)[0-9]* =>/\1=>/' fi > $ts.orig -- Gitee From 2bdf55497d41008819b92b0e7de627fe59b51fb1 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Wed, 9 Mar 2022 21:37:29 -0800 Subject: [PATCH 26/44] Add parentheses to the method expression of TerOperatorNode for CallNode --- src/MapleFE/ast2cpp/src/emitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index 207fd64679..35608da63f 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -1538,7 +1538,7 @@ std::string Emitter::EmitCallNode(CallNode *node) { bool optional = n->IsOptional(); if (optional && !s.empty() && s.back() == '?') s.pop_back(); - if(n->IsFunction() || n->IsLambda()) + if(n->IsFunction() || n->IsLambda() || n->IsTerOperator()) str += '(' + s + ')'; else str += s; -- Gitee From fd7eea143b7eabe0e1debcf90efb513d17ca0680 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Wed, 9 Mar 2022 22:12:54 -0800 Subject: [PATCH 27/44] Add a test case with 'var' as a property name --- .../test/typescript/unit_tests/var-as-prop-name.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts diff --git a/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts new file mode 100644 index 0000000000..bd97f5cab3 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts @@ -0,0 +1,10 @@ +const obj = { + else() { + return this; + }, + var() { + console.log("var"); + } +} + +obj.else().var(); -- Gitee From 70f6b9e445f4da540819f34a2618dfc665ba3abe Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Wed, 9 Mar 2022 22:20:14 -0800 Subject: [PATCH 28/44] Add a test case with 'else' as a property name --- src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts diff --git a/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts new file mode 100644 index 0000000000..dd9965a57c --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts @@ -0,0 +1,6 @@ +class Klass { + else: number = 0; +} + +var obj: Klass = new Klass(); +console.log(obj, obj.else); -- Gitee From 72a61d1008b233e072fe2bda141538bcaf5281de Mon Sep 17 00:00:00 2001 From: eching Date: Thu, 10 Mar 2022 08:04:42 -0800 Subject: [PATCH 29/44] Add IteratorResult fields to proplist. Handle JS_Val holding a type any value (i.e. a HS_Val) in output operator. --- src/MapleFE/ast2cpp/runtime/include/builtins.h | 5 ++++- src/MapleFE/ast2cpp/runtime/include/ts2cpp.h | 3 ++- src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/MapleFE/ast2cpp/runtime/include/builtins.h b/src/MapleFE/ast2cpp/runtime/include/builtins.h index 371a508b1d..8a226880ad 100644 --- a/src/MapleFE/ast2cpp/runtime/include/builtins.h +++ b/src/MapleFE/ast2cpp/runtime/include/builtins.h @@ -137,7 +137,10 @@ struct IteratorResult : public Object { bool done; // status of iterator next() call JS_Val value; // done=false: current iteration element value // done=true: return value of the iterator, undefined if none returned - IteratorResult() : done(true), value(undefined) { } + IteratorResult() : done(true), value(undefined) { + this->AddProp("done", t2crt::ClassFld(&IteratorResult::done).NewProp(this, t2crt::TY_CXX_Bool)); + this->AddProp("value", t2crt::ClassFld(&IteratorResult::value).NewProp(this, t2crt::TY_CXX_Any)); + } IteratorResult(bool done, JS_Val val) : done(done), value(val) { } ~IteratorResult() { } }; diff --git a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h index c94ea6fd2d..cdf48d2d55 100644 --- a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h +++ b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h @@ -52,6 +52,7 @@ typedef enum JS_Type : uint8_t { TY_Function, // "function" TY_Object, // "object" TY_Array, + TY_Any, // JS_Val::x.field points to a JS_Val TY_LAST, TY_CXX_Undef = TY_Undef | TY_CXX, TY_CXX_Null, @@ -64,7 +65,7 @@ typedef enum JS_Type : uint8_t { TY_CXX_Function, TY_CXX_Object, TY_CXX_Array, - TY_CXX_Any, //indicate JS_Val::x.field pointing to a JS_Val + TY_CXX_Any, // JS_Val::x.field points to a JS_Val TY_CXX_LAST, } JS_Type; diff --git a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp index eed2b6a484..50fecb38bc 100644 --- a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp +++ b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp @@ -16,6 +16,7 @@ std::ostream& operator<< (std::ostream& out, const t2crt::JS_Val& v) { case t2crt::TY_Symbol: out << "symbol"; break; case t2crt::TY_Function: out << "function"; break; case t2crt::TY_Object: out << v.x.val_obj; break; + case t2crt::TY_Any: out << *(t2crt::JS_Val*)v.x.field; break; case t2crt::TY_CXX_Undef: out << "undefined"; break; case t2crt::TY_CXX_Null: out << "null"; break; @@ -27,6 +28,7 @@ std::ostream& operator<< (std::ostream& out, const t2crt::JS_Val& v) { case t2crt::TY_CXX_Symbol: out << "symbol"; break; case t2crt::TY_CXX_Function: out << "function"; break; case t2crt::TY_CXX_Object: out << *(Object**)v.x.field; break; + case t2crt::TY_CXX_Any: out << *(t2crt::JS_Val*)v.x.field; break; } return out; } -- Gitee From 684ac6280d127e785af49cd25ea1dd700a9bf155 Mon Sep 17 00:00:00 2001 From: eching Date: Thu, 10 Mar 2022 13:58:51 -0800 Subject: [PATCH 30/44] Generate correct GetProp call for property type Any (TY_Any). Use iterator result field in InteratorProto class for returning generator results from generator functions to ensure result object returned is persistent without allocating memory or copying. Case generator3.ts pass with these last changes. --- src/MapleFE/ast2cpp/runtime/include/builtins.h | 1 - src/MapleFE/ast2cpp/src/cpp_definition.cpp | 5 ++++- src/MapleFE/ast2cpp/src/helper.cpp | 17 +++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/MapleFE/ast2cpp/runtime/include/builtins.h b/src/MapleFE/ast2cpp/runtime/include/builtins.h index 8a226880ad..af0fe8f50d 100644 --- a/src/MapleFE/ast2cpp/runtime/include/builtins.h +++ b/src/MapleFE/ast2cpp/runtime/include/builtins.h @@ -180,7 +180,6 @@ public: // Label corrected in version at tc39. class GeneratorProto : public IteratorProto { public: - IteratorResult _res; GeneratorProto(Function* ctor, Object* proto) : IteratorProto(ctor, proto) { } ~GeneratorProto() { } void* _yield = nullptr; // pointer to yield label to resume execution diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index c16661fe6e..ad65c9994f 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -271,7 +271,7 @@ std::string CppDef::EmitYieldNode(YieldNode *node) { str += " yield = &&" + yieldLabel + ";\n"; // save yp str += " res.value = t2crt::JS_Val(" +res+ ");\n"; // init value and return str += " res.done = false;\n"; - str += " return res;\n"; + str += " return;\n"; str += yieldLabel + ":\n"; // label for this yp mPrecedence = '\024'; @@ -1044,6 +1044,9 @@ std::string CppDef::EmitBracketNotationProp(ArrayElementNode* ae, OprId binOpId, case TY_Object: str = objName + "->GetPropObj("s + propKey + ")"s; break; + case TY_Any: + str = objName + "->GetProp("s + propKey + ")"s; + break; default: str = "(*"s + objName + ")["s + propKey + ']'; } diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index f2543aaf58..1222f23418 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -34,8 +34,6 @@ std::unordered_mapTypeIdToJSTypeCXX = { }; std::string GeneratorFn_start = R"""( - t2crt::IteratorResult res; - if (yield != nullptr) goto *yield; )"""; @@ -43,7 +41,7 @@ std::string GeneratorFn_start = R"""( std::string GeneratorFn_return = R"""( res.value = undefined; res.done = true; - return res; + return; )"""; // Used to build GetProp for calls to get Object (class Object in ts2cpp.h) property @@ -51,8 +49,9 @@ std::string hlpGetJSValTypeStr(TypeId typeId) { switch(typeId) { case TY_Object: case TY_Class: - case TY_Any: return "Obj"; + case TY_Any: + return ""; case TY_Function: return "Func"; case TY_Boolean: @@ -228,7 +227,7 @@ std::string GeneratorFuncHeader(std::string cls, unsigned nodeId) { std::string params = FunctionParams(nodeId, false, false, true); // pass params by ref into _body() if (!params.empty()) params = ", " + params; - return "t2crt::IteratorResult " + cls + "_body(t2crt::Object* _this, void*& yield" + params + ")"; + return "void " + cls + "_body(t2crt::Object* _this, void*& yield, t2crt::IteratorResult& res" + params + ")"; } // Generating Generators and Generator Functions: @@ -252,7 +251,7 @@ std::string GeneratorClassDecl(std::string funcName, unsigned nodeId) { " " +generatorName+ "(t2crt::Function* ctor, t2crt::Object* proto" +ctorArgs+ ") : t2crt::GeneratorProto(ctor, proto)" +initList+ " {}", " ~" +generatorName+ "() {}", " // closure capture fields", - captureFields, +" " +captureFields, " // iterator interface (override _return and _throw when needed)", " t2crt::IteratorResult* next(t2crt::JS_Val* arg = nullptr) override;", "};", @@ -265,9 +264,11 @@ std::string GeneratorClassDecl(std::string funcName, unsigned nodeId) { " " +generatorName+ "* operator()(" +functorArgs+ ");", " // generator function body", " " +GeneratorFuncHeader("", nodeId)+ ";", -"};" +"};", +"" }; + str += "\n"; for (auto elem : genClsDecl) str += elem + "\n"; return str; @@ -293,7 +294,7 @@ t2crt::IteratorResult* )""" + generatorName + R"""(::next(t2crt::JS_Val* arg) { return &_res; } // iterate by calling generation function with captures in generator - _res = foo->_body(this, _yield)""" + args + R"""(); + )""" + funcName + R"""(->_body(this, _yield, _res)""" + args + R"""(); if (_res.done == true) _finished = true; return &_res; -- Gitee From 081969f6259446ccdd2f3510325a28228c007ce6 Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 11 Mar 2022 08:30:46 +0800 Subject: [PATCH 31/44] support 'else' as property name. --- .../unit_tests/else-as-prop-name.ts.result | 18 ++++++++++++++++++ src/MapleFE/typescript/stmt.spec | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result new file mode 100644 index 0000000000..b14f7e7d22 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result @@ -0,0 +1,18 @@ +Matched 10 tokens. +Matched 20 tokens. +Matched 31 tokens. +============= Module =========== +== Sub Tree == +class Klass + Fields: + else=0 + Instance Initializer: + Constructors: + Methods: + LocalClasses: + LocalInterfaces: + +== Sub Tree == +js_var Decl: obj=new Klass() +== Sub Tree == +console.log(obj,obj.else) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 0e2c8a9b1b..ea1ab8152b 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -2223,11 +2223,11 @@ rule PropertyMemberDeclaration: ONEOF(MemberVariableDeclaration, ## MemberVariableDeclaration: AccessibilityModifieropt staticopt PropertyName TypeAnnotationopt Initializeropt ; rule MemberVariableDeclaration: ONEOF( - ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertyName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), - ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertyName + '?' + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), + ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertySignatureName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), + ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertySignatureName + '?' + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + "get" + '=' + ArrowFunction + ZEROORONE(';'), ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + "set" + '=' + ArrowFunction + ZEROORONE(';'), - '#' + PropertyName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), + '#' + PropertySignatureName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), '#' + "private" + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + "if" + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';')) attr.action.%1: AddInitTo(%3, %5) -- Gitee From 49ac481e374bc43d38becadd8895bd06f9d92412 Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 11 Mar 2022 08:38:08 +0800 Subject: [PATCH 32/44] support var as prop name --- .../typescript/unit_tests/var-as-prop-name.ts.result | 11 +++++++++++ src/MapleFE/typescript/stmt.spec | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result new file mode 100644 index 0000000000..7fcef6b23a --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result @@ -0,0 +1,11 @@ +Matched 26 tokens. +Matched 36 tokens. +============= Module =========== +== Sub Tree == +js_const Decl: obj= {else:func else() throws: + return this +, var:func var() throws: + console.log("var") +} +== Sub Tree == +obj.else().var() diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index ea1ab8152b..4c15f27b4a 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -473,7 +473,8 @@ rule CallExpression : ONEOF( "set" + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), "get" + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), CallExpression + "?." + Arguments + ZEROORMORE(AsType), - ImportFunction) + ImportFunction, + CallExpression + '.' + KeywordPropName + ZEROORMORE(AsType)) attr.action.%1,%3,%10,%11 : BuildCall(%1) attr.action.%1,%10,%11 : AddAsType(%4) attr.action.%1,%10,%11 : AddTypeGenerics(%2) @@ -482,8 +483,8 @@ rule CallExpression : ONEOF( attr.action.%3 : AddAsType(%3) attr.action.%4 : BuildArrayElement(%1, %3) attr.action.%4 : AddAsType(%5) - attr.action.%5 : BuildField(%1, %3) - attr.action.%5 : AddAsType(%4) + attr.action.%5,%14 : BuildField(%1, %3) + attr.action.%5,%14 : AddAsType(%4) attr.action.%7 : SetIsNonNull(%1) attr.action.%7 : AddAsType(%1, %3) attr.action.%8 : SetIsOptional(%1) -- Gitee From 3bbd44d630693611e51e05da4bcc6f2db8d9f2d1 Mon Sep 17 00:00:00 2001 From: yehandong Date: Fri, 11 Mar 2022 14:37:13 +0800 Subject: [PATCH 33/44] support TemplateLiteral in union type --- src/MapleFE/shared/src/ast_type.cpp | 1 + .../template-literal-type.ts.result | 30 +++++++++++++++++++ src/MapleFE/typescript/stmt.spec | 5 ++-- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result diff --git a/src/MapleFE/shared/src/ast_type.cpp b/src/MapleFE/shared/src/ast_type.cpp index ad3a113481..1ac736af93 100644 --- a/src/MapleFE/shared/src/ast_type.cpp +++ b/src/MapleFE/shared/src/ast_type.cpp @@ -42,6 +42,7 @@ void UserTypeNode::AddUnionInterType(TreeNode *args) { args->IsKeyOf() || args->IsImport() || args->IsField() || + args->IsTemplateLiteral() || args->IsStruct()) { mUnionInterTypes.PushBack(args); SETPARENT(args); diff --git a/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result new file mode 100644 index 0000000000..70ca48c63f --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result @@ -0,0 +1,30 @@ +Matched 16 tokens. +Matched 32 tokens. +Matched 47 tokens. +Matched 57 tokens. +Matched 68 tokens. +Matched 69 tokens. +Matched 70 tokens. +Matched 77 tokens. +Matched 80 tokens. +============= Module =========== +== Sub Tree == +class Num + Fields: + neg=false val=0 + Instance Initializer: + Constructors: + Methods: + LocalClasses: + LocalInterfaces: + +== Sub Tree == +func func(v) throws: + return template-literal: NULL,v.neg ? "-" : "",NULL,v.val,"n",NULL + +== Sub Tree == +js_var Decl: obj= {neg:true, val:123} +== Sub Tree == +console.log(func(obj)) +== Sub Tree == +console.log( typeof func(obj)) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 4c15f27b4a..fceeac1e85 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -1856,9 +1856,10 @@ rule TupleElementType: ONEOF(ZEROORONE(JSIdentifier + ':') + Type, rule UnionType : ONEOF(ZEROORONE('|') + UnionOrIntersectionOrPrimaryType + '|' + IntersectionOrPrimaryType, UnionOrIntersectionOrPrimaryType + '|' + KeyOf, KeyOf + '|' + UnionOrIntersectionOrPrimaryType, - TypeQuery + '|' + UnionOrIntersectionOrPrimaryType) + TypeQuery + '|' + UnionOrIntersectionOrPrimaryType, + TemplateLiteral + '|' + TemplateLiteral) attr.action.%1 : BuildUnionUserType(%2, %4) - attr.action.%2,%3,%4 : BuildUnionUserType(%1, %3) + attr.action.%2,%3,%4,%5 : BuildUnionUserType(%1, %3) ## rule IntersectionType: IntersectionOrPrimaryType & PrimaryType rule IntersectionType: ONEOF(IntersectionOrPrimaryType + '&' + PrimaryType, -- Gitee From b551070149f38596a8a84647d2633a29b764d854 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 11 Mar 2022 09:57:28 -0800 Subject: [PATCH 34/44] Add a test case with missing semicolon after return statement --- .../test/typescript/unit_tests/semicolon-missing16.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts b/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts new file mode 100644 index 0000000000..3caad616a6 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts @@ -0,0 +1,8 @@ +function func(arg: number): number | undefined { + if(arg < 1) return + for(let i = 0; i < arg; i++) + console.log(i); + return arg * 10; +} +console.log(func(3)); + -- Gitee From 9946d52aaf7ee5416ba7f5de968ffe7ad5c8aefe Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 11 Mar 2022 10:02:26 -0800 Subject: [PATCH 35/44] Add a test case with missing semicolon after continue statement --- .../test/typescript/unit_tests/semicolon-missing17.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts new file mode 100644 index 0000000000..f5c4aff91f --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts @@ -0,0 +1,9 @@ +function func(arg: number): number | undefined { + for(let i = 0; i < arg; i++) { + if(i % 2 > 0) continue + console.log(i); + } + return arg * 10; +} +console.log(func(5)); + -- Gitee From 9c139cbf341deb3c4c4cb22460ab0400ea9e87e3 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Fri, 11 Mar 2022 15:28:57 -0800 Subject: [PATCH 36/44] Enable the NoLineTerminator feature for continue stmt --- .../unit_tests/semicolon-missing17.ts.result | 17 +++++++++++++++++ src/MapleFE/typescript/stmt.spec | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result new file mode 100644 index 0000000000..6de52c4b72 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result @@ -0,0 +1,17 @@ +Matched 50 tokens. +Matched 60 tokens. +============= Module =========== +== Sub Tree == +func func(arg) throws: + for ( ) + cond-branch cond:i Mod 2 GT 0 + true branch : + continue: + false branch : + + console.log(i) + + return arg Mul 10 + +== Sub Tree == +console.log(func(5)) diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index fceeac1e85..a37f858835 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -1146,9 +1146,9 @@ rule ForBinding : ONEOF(BindingIdentifier, ## continue [no LineTerminator here] LabelIdentifier[?Yield] ; rule ContinueStatement : ONEOF( "continue" + ZEROORONE(';'), - "continue" + LabelIdentifier + ZEROORONE(';')) + "continue" + NoLineTerminator + LabelIdentifier + ZEROORONE(';')) attr.action.%1 : BuildContinue() - attr.action.%2 : BuildContinue(%2) + attr.action.%2 : BuildContinue(%3) ##----------------------------------- ##rule BreakStatement[Yield] : -- Gitee From 8e1c26d5ccc155554287603f4f044a5242a8aa92 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sat, 12 Mar 2022 11:04:38 -0500 Subject: [PATCH 37/44] add AltStrIdxSet and AltStrIdxMap to stringpool --- src/MapleFE/shared/include/stringpool.h | 22 +++++++-- src/MapleFE/shared/src/stringpool.cpp | 64 +++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/MapleFE/shared/include/stringpool.h b/src/MapleFE/shared/include/stringpool.h index 259e33e620..15d2c15cb1 100644 --- a/src/MapleFE/shared/include/stringpool.h +++ b/src/MapleFE/shared/include/stringpool.h @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include "massert.h" @@ -45,18 +47,32 @@ private: StringMap *mMap; std::vector mBlocks; int mFirstAvail; // -1 means no available. + bool mUseAltStr; // use alter string std::vector mLongStrings; // for strings longer than block size, // we allocate them by malloc. std::vector mStringTable; + // alternate string which can be used for obfuscation + std::unordered_set mAltStrIdxSet; + std::unordered_map mAltStrIdxMap; + friend class StringMap; public: StringPool(); ~StringPool(); + void SetUseAltStr(bool b) { mUseAltStr = b; } + void AddAltStrIdx(unsigned idx) { mAltStrIdxSet.insert(idx); } + unsigned GetAltStrSize() { return mAltStrIdxSet.size(); } + bool IsAltStrIdx(unsigned idx) { + return mAltStrIdxSet.find(idx) != mAltStrIdxSet.end(); + } + void AddAltStrIdxMap(unsigned orig, unsigned alt) { mAltStrIdxMap[orig] = alt; } + void SetAltStrIdxMap(); + char* AllocBlock(); char* Alloc(const size_t); char* Alloc(const std::string&); @@ -71,12 +87,10 @@ public: unsigned GetStrIdx(const char*); unsigned GetStrIdx(const char*, size_t); - const char *GetStringFromStrIdx(unsigned idx) { - MASSERT(idx < mStringTable.size() && "string index out of range"); - return mStringTable[idx]; - } + const char *GetStringFromStrIdx(unsigned idx); void Dump(); + void DumpAlt(); }; // Lexing, Parsing, AST Building and IR Building all share one global diff --git a/src/MapleFE/shared/src/stringpool.cpp b/src/MapleFE/shared/src/stringpool.cpp index 1c96f4553e..65b0ede44c 100644 --- a/src/MapleFE/shared/src/stringpool.cpp +++ b/src/MapleFE/shared/src/stringpool.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "stringpool.h" #include "stringmap.h" @@ -31,6 +32,7 @@ namespace maplefe { StringPool gStringPool; StringPool::StringPool() { + mUseAltStr = false; mMap = new StringMap(); mMap->SetPool(this); mFirstAvail = -1; @@ -173,11 +175,73 @@ unsigned StringPool::GetStrIdx(const char *str, size_t len) { return mMap->LookupEntryFor(s)->GetStrIdx(); } +const char *StringPool::GetStringFromStrIdx(unsigned idx) { + MASSERT(idx < mStringTable.size() && "string index out of range"); + if (mUseAltStr) { + if (mAltStrIdxMap.find(idx) != mAltStrIdxMap.end()) { + idx = mAltStrIdxMap[idx]; + } + } + return mStringTable[idx]; +} + +// This is the public interface to setup AltStrIdxMap used for obfuscation +// a name is mapped to a fixed length random unused name. +// two letters, [a-zA-Z] [a-zA-Z], which will cover over 2K names +// AA Aa AB Ab, ...., zz +#define LEN 2 +// +#define KIND 52 +#define SIZE KIND*KIND +void StringPool::SetAltStrIdxMap() { + unsigned size = mAltStrIdxSet.size(); + bool done = false; + char *A = (char*)malloc(LEN+1); + *(A+LEN) = 0; + for (auto stridx : mAltStrIdxSet) { + done = false; + while (!done) { + int r = rand() % (SIZE); + int t = r/KIND; + int s = r%KIND; + + // first char, use upper case for odd number + bool odd = t%2; + *A = (odd ? 'A' : 'a') + t/2; + + // second char, use upper case for odd number + odd = s%2; + *(A+1) = (odd ? 'A' : 'a') + s/2; + + unsigned alt = GetStrIdx(A); + // make sure alt is a new string + if (stridx != mStringTable.size()) { + mAltStrIdxMap[stridx] = alt; + done = true; + } + } + } +} + void StringPool::Dump() { std::cout << "===================== StringTable =====================" << std::endl; for (unsigned idx = 1; idx < mStringTable.size(); idx++) { std::cout << " " << idx << " : " << mStringTable[idx] << std::endl; } } + +void StringPool::DumpAlt() { + std::cout << "================= Alt String Map ======================" << std::endl; + unsigned count = 0; + for (auto stridx : mAltStrIdxSet) { + unsigned alt = mAltStrIdxMap[stridx]; + std::cout << "count #" << stridx + << " str " << GetStringFromStrIdx(stridx) + << " --> " + << " alt " << GetStringFromStrIdx(alt) + << std::endl; + } +} + } -- Gitee From e281edf3aad04b53c4e9fafde9d48ad2df950d52 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sat, 12 Mar 2022 11:05:21 -0500 Subject: [PATCH 38/44] enable renameing for obfuscate --- src/MapleFE/astopt/src/ast_adj.cpp | 12 ++++++++++++ src/MapleFE/astopt/src/ast_scp.cpp | 1 + src/MapleFE/astopt/src/ast_ti.cpp | 2 +- src/MapleFE/tools/obfuscate/src/obfuscate.cpp | 13 +++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index 12de84bcec..539cf0d570 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -53,6 +53,7 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { (void) AstVisitor::VisitClassNode(node); CheckAndRenameCppKeywords(node); AssignPseudoName(node); + gStringPool.AddAltStrIdx(node->GetStrIdx()); // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperClassesNum() || node->GetSuperInterfacesNum() || node->GetSuperClassesNum() || node->GetTypeParamsNum()) { @@ -76,6 +77,7 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { InterfaceNode *AdjustASTVisitor::VisitInterfaceNode(InterfaceNode *node) { (void) AstVisitor::VisitInterfaceNode(node); CheckAndRenameCppKeywords(node); + gStringPool.AddAltStrIdx(node->GetStrIdx()); // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperInterfacesNum()) { return node; @@ -108,6 +110,7 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n } TreeNode *newnode = mInfo->GetCanonicStructNode(node); + gStringPool.AddAltStrIdx(newnode->GetStrIdx()); if (newnode != node) { node->SetTypeIdx(newnode->GetTypeIdx()); } @@ -118,6 +121,7 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n StructNode *AdjustASTVisitor::VisitStructNode(StructNode *node) { (void) AstVisitor::VisitStructNode(node); CheckAndRenameCppKeywords(node); + gStringPool.AddAltStrIdx(node->GetStrIdx()); // skip getting canonical type for TypeAlias TreeNode *parent_orig = node->GetParent(); TreeNode *p = parent_orig; @@ -284,6 +288,13 @@ FunctionNode *AdjustASTVisitor::VisitFunctionNode(FunctionNode *node) { (void) AstVisitor::VisitFunctionNode(node); CheckAndRenameCppKeywords(node); + gStringPool.AddAltStrIdx(node->GetStrIdx()); + + for(unsigned i = 0; i < node->GetParamsNum(); i++) { + TreeNode *it = node->GetParam(i); + gStringPool.AddAltStrIdx(it->GetStrIdx()); + } + TreeNode *type = node->GetType(); if (type && type->IsUserType()) { type->SetParent(node); @@ -314,6 +325,7 @@ DeclNode *AdjustASTVisitor::VisitDeclNode(DeclNode *node) { unsigned stridx = inode->GetStrIdx(); if (stridx) { node->SetStrIdx(stridx); + gStringPool.AddAltStrIdx(stridx); mUpdated = true; } diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index 7a87e6f256..fe8ea9ad78 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -761,6 +761,7 @@ void AST_SCP::RenameVar() { str += std::to_string(size); visitor.mOldStrIdx = stridx; visitor.mNewStrIdx = gStringPool.GetStrIdx(str); + gStringPool.AddAltStrIdx(visitor.mNewStrIdx); TreeNode *tn = mHandler->GetAstOpt()->GetNodeFromNodeId(nid); ASTScope *scope = tn->GetScope(); tn = scope->GetTree(); diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 6b25880245..63cb423d36 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -501,7 +501,7 @@ void TypeInferVisitor::UpdateTypeUseNode(TreeNode *target, TreeNode *input) { TypeId new_elemTypeId = GetArrayElemTypeId(target); TreeNode *type = static_cast(target)->GetType(); MASSERT(target->IsIdentifier() && "target node not identifier"); - if (type->IsPrimArrayType()) { + if (type && type->IsPrimArrayType()) { unsigned nid = target->GetNodeId(); mParam2ArgArrayDeclMap[nid].insert(decl); if (old_elemTypeId != new_elemTypeId) { diff --git a/src/MapleFE/tools/obfuscate/src/obfuscate.cpp b/src/MapleFE/tools/obfuscate/src/obfuscate.cpp index 1b23546bb9..17c750339a 100644 --- a/src/MapleFE/tools/obfuscate/src/obfuscate.cpp +++ b/src/MapleFE/tools/obfuscate/src/obfuscate.cpp @@ -132,6 +132,19 @@ int Obfuscate::ProcessAST() { } } + if (mFlags & FLG_trace_3) { + gStringPool.Dump(); + } + + gStringPool.SetAltStrIdxMap(); + + if (mFlags & FLG_trace_3) { + gStringPool.Dump(); + gStringPool.DumpAlt(); + } + + gStringPool.SetUseAltStr(true); + for (auto handler: mHandlersInOrder) { ModuleNode *module = handler->GetASTModule(); -- Gitee From 1bdff18eac6ec9f3600059c7f10faf4dd9d1b646 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sat, 12 Mar 2022 12:00:52 -0500 Subject: [PATCH 39/44] update type inference for Object related cases --- src/MapleFE/astopt/src/ast_ti.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 63cb423d36..86715f045a 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -320,11 +320,11 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } unsigned TypeInferVisitor::MergeTypeIdx(unsigned tia, unsigned tib) { - if (tia == tib || tib == 0) { + if (tia == tib || tib <= 1) { return tia; } - if (tia == 0) { + if (tia <= 1) { return tib; } @@ -433,7 +433,11 @@ PrimTypeNode *TypeInferVisitor::GetOrClonePrimTypeNode(PrimTypeNode *pt, TypeId new_pt->SetPrimType(pt->GetPrimType()); } SetTypeId(new_pt, tid); - SetTypeIdx(new_pt, tid); + if (IsPrimTypeId(tid)) { + SetTypeIdx(new_pt, tid); + } else { + SetTypeIdx(new_pt, gTypeTable.GetTypeFromTypeId(tid)->GetTypeIdx()); + } SetUpdated(); } return new_pt; @@ -1152,6 +1156,13 @@ CallNode *TypeInferVisitor::VisitCallNode(CallNode *node) { } } else if (decl->IsLiteral()) { NOTYETIMPL("VisitCallNode literal node"); + } else if (decl->IsTypeIdClass()) { + // object + if (node->GetArgsNum()) { + TreeNode *arg = node->GetArg(0); + SetTypeId(arg, TY_Object); + SetTypeIdx(arg, decl->GetTypeIdx()); + } } else { NOTYETIMPL("VisitCallNode not function node"); } -- Gitee From 9ba42b06f1cf5f5938b977ee676c0042cedc4997 Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sat, 12 Mar 2022 13:10:00 -0500 Subject: [PATCH 40/44] make sure alt is a new string --- src/MapleFE/shared/src/stringpool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/MapleFE/shared/src/stringpool.cpp b/src/MapleFE/shared/src/stringpool.cpp index 65b0ede44c..757774eef7 100644 --- a/src/MapleFE/shared/src/stringpool.cpp +++ b/src/MapleFE/shared/src/stringpool.cpp @@ -213,9 +213,10 @@ void StringPool::SetAltStrIdxMap() { odd = s%2; *(A+1) = (odd ? 'A' : 'a') + s/2; + unsigned size = mStringTable.size(); unsigned alt = GetStrIdx(A); // make sure alt is a new string - if (stridx != mStringTable.size()) { + if (alt == size) { mAltStrIdxMap[stridx] = alt; done = true; } -- Gitee From 5ab307d5284e83616c40571ee775ccfb2ebc64ed Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sat, 12 Mar 2022 13:19:20 -0500 Subject: [PATCH 41/44] collect names of class/interface/struct fields and methods --- src/MapleFE/astopt/src/ast_adj.cpp | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index 539cf0d570..700de269f3 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -53,7 +53,18 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { (void) AstVisitor::VisitClassNode(node); CheckAndRenameCppKeywords(node); AssignPseudoName(node); + + // record names gStringPool.AddAltStrIdx(node->GetStrIdx()); + for (unsigned i = 0; i < node->GetFieldsNum(); i++) { + TreeNode *n = node->GetField(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + for (unsigned i = 0; i < node->GetMethodsNum(); i++) { + TreeNode *n = node->GetMethod(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperClassesNum() || node->GetSuperInterfacesNum() || node->GetSuperClassesNum() || node->GetTypeParamsNum()) { @@ -77,7 +88,18 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { InterfaceNode *AdjustASTVisitor::VisitInterfaceNode(InterfaceNode *node) { (void) AstVisitor::VisitInterfaceNode(node); CheckAndRenameCppKeywords(node); + + // record names gStringPool.AddAltStrIdx(node->GetStrIdx()); + for (unsigned i = 0; i < node->GetFieldsNum(); i++) { + TreeNode *n = node->GetField(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + for (unsigned i = 0; i < node->GetMethodsNum(); i++) { + TreeNode *n = node->GetMethod(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperInterfacesNum()) { return node; @@ -121,7 +143,18 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n StructNode *AdjustASTVisitor::VisitStructNode(StructNode *node) { (void) AstVisitor::VisitStructNode(node); CheckAndRenameCppKeywords(node); + + // record names gStringPool.AddAltStrIdx(node->GetStrIdx()); + for (unsigned i = 0; i < node->GetFieldsNum(); i++) { + TreeNode *n = node->GetField(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + for (unsigned i = 0; i < node->GetMethodsNum(); i++) { + TreeNode *n = node->GetMethod(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + // skip getting canonical type for TypeAlias TreeNode *parent_orig = node->GetParent(); TreeNode *p = parent_orig; -- Gitee From 9b75b1842d3096eacc197018ae41523da59c2034 Mon Sep 17 00:00:00 2001 From: yehandong Date: Sun, 13 Mar 2022 10:52:33 +0800 Subject: [PATCH 42/44] add free after malloc in SetAltStrIdxMap --- src/MapleFE/shared/src/stringpool.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MapleFE/shared/src/stringpool.cpp b/src/MapleFE/shared/src/stringpool.cpp index 757774eef7..d941ea540f 100644 --- a/src/MapleFE/shared/src/stringpool.cpp +++ b/src/MapleFE/shared/src/stringpool.cpp @@ -222,6 +222,8 @@ void StringPool::SetAltStrIdxMap() { } } } + + free(A); } void StringPool::Dump() { -- Gitee From 4df09df9ae22011157b76d2252eb041e6bcf76af Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sun, 13 Mar 2022 12:47:15 -0400 Subject: [PATCH 43/44] add name for function type; create same named class once --- src/MapleFE/astopt/include/ast_scp.h | 2 +- src/MapleFE/astopt/src/ast_info.cpp | 2 +- src/MapleFE/astopt/src/ast_scp.cpp | 30 +++++++++++-------- src/MapleFE/shared/include/stringpool.h | 2 ++ src/MapleFE/shared/include/typetable.h | 1 + src/MapleFE/shared/src/stringpool.cpp | 2 +- src/MapleFE/shared/src/typetable.cpp | 40 +++++++++++++++++-------- 7 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/MapleFE/astopt/include/ast_scp.h b/src/MapleFE/astopt/include/ast_scp.h index fd2dcb485d..1a9a7124a2 100644 --- a/src/MapleFE/astopt/include/ast_scp.h +++ b/src/MapleFE/astopt/include/ast_scp.h @@ -93,7 +93,7 @@ class BuildScopeVisitor : public BuildScopeBaseVisitor { void SetRunIt(bool b) { mRunIt = b; } void InitInternalTypes(); - ClassNode *AddClass(std::string name, unsigned tyidx = 0); + ClassNode *AddClass(unsigned stridx, unsigned tyidx = 0); FunctionNode *AddFunction(std::string name); void AddType(ASTScope *scope, TreeNode *node); diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index 1bc650be8e..c7e3cb41ac 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -507,7 +507,7 @@ StructNode *AST_INFO::CreateStructFromStructLiteral(StructLiteralNode *node) { } unsigned AST_INFO::GetAnonymousName() { - std::string str("AnonymousStruct_"); + std::string str("AnonymousStruct__"); str += std::to_string(mNum++); unsigned stridx = gStringPool.GetStrIdx(str); return stridx; diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index fe8ea9ad78..33882e994f 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -140,20 +140,24 @@ void BuildScopeVisitor::InitInternalTypes() { } // add dummpy console.log() - ClassNode *console = AddClass("console"); - ASTScope *scp = NewScope(scope, console); - mStrIdx2ScopeMap[console->GetStrIdx()] = scp; - FunctionNode *log = AddFunction("log"); - log->SetTypeIdx(TY_Void); - console->AddMethod(log); - log->SetScope(scp); - AddDecl(scp, log); -} - -ClassNode *BuildScopeVisitor::AddClass(std::string name, unsigned tyidx) { + unsigned size = gStringPool.GetSize(); + unsigned stridx = gStringPool.GetStrIdx("console"); + TreeNode *type = gTypeTable.GetTypeFromStrIdx(stridx); + if (!type) { + ClassNode *console = AddClass(stridx); + ASTScope *scp = NewScope(scope, console); + mStrIdx2ScopeMap[console->GetStrIdx()] = scp; + FunctionNode *log = AddFunction("log"); + log->SetTypeIdx(TY_Void); + console->AddMethod(log); + log->SetScope(scp); + AddDecl(scp, log); + } +} + +ClassNode *BuildScopeVisitor::AddClass(unsigned stridx, unsigned tyidx) { ClassNode *node = mHandler->NewTreeNode(); - unsigned idx = gStringPool.GetStrIdx(name); - node->SetStrIdx(idx); + node->SetStrIdx(stridx); node->SetTypeIdx(tyidx); ModuleNode *module = mHandler->GetASTModule(); diff --git a/src/MapleFE/shared/include/stringpool.h b/src/MapleFE/shared/include/stringpool.h index 15d2c15cb1..fd8dfee8ab 100644 --- a/src/MapleFE/shared/include/stringpool.h +++ b/src/MapleFE/shared/include/stringpool.h @@ -87,6 +87,8 @@ public: unsigned GetStrIdx(const char*); unsigned GetStrIdx(const char*, size_t); + unsigned GetSize() {return mStringTable.size();} + const char *GetStringFromStrIdx(unsigned idx); void Dump(); diff --git a/src/MapleFE/shared/include/typetable.h b/src/MapleFE/shared/include/typetable.h index 5f8d36d743..d53b177191 100644 --- a/src/MapleFE/shared/include/typetable.h +++ b/src/MapleFE/shared/include/typetable.h @@ -77,6 +77,7 @@ public: TypeEntry *GetTypeEntryFromTypeIdx(unsigned tidx); TreeNode *GetTypeFromTypeIdx(unsigned tidx); TreeNode *GetTypeFromTypeId(TypeId tid) { return mTypeId2TypeMap[tid]; } + TreeNode *GetTypeFromStrIdx(unsigned strid); unsigned GetOrCreateFunctionTypeIdx(FunctionTypeNode *type); diff --git a/src/MapleFE/shared/src/stringpool.cpp b/src/MapleFE/shared/src/stringpool.cpp index d941ea540f..046555147f 100644 --- a/src/MapleFE/shared/src/stringpool.cpp +++ b/src/MapleFE/shared/src/stringpool.cpp @@ -213,7 +213,7 @@ void StringPool::SetAltStrIdxMap() { odd = s%2; *(A+1) = (odd ? 'A' : 'a') + s/2; - unsigned size = mStringTable.size(); + unsigned size = GetSize(); unsigned alt = GetStrIdx(A); // make sure alt is a new string if (alt == size) { diff --git a/src/MapleFE/shared/src/typetable.cpp b/src/MapleFE/shared/src/typetable.cpp index 00fefcd671..8a1d8a93e9 100644 --- a/src/MapleFE/shared/src/typetable.cpp +++ b/src/MapleFE/shared/src/typetable.cpp @@ -135,30 +135,46 @@ void TypeTable::AddPrimAndBuiltinTypes() { return; } -TypeEntry *TypeTable::GetTypeEntryFromTypeIdx(unsigned idx) { - MASSERT(idx < mTypeTable.size() && "type index out of range"); - return mTypeTable[idx]; +TypeEntry *TypeTable::GetTypeEntryFromTypeIdx(unsigned tidx) { + MASSERT(tidx < mTypeTable.size() && "type index out of range"); + return mTypeTable[tidx]; } -TreeNode *TypeTable::GetTypeFromTypeIdx(unsigned idx) { - MASSERT(idx < mTypeTable.size() && "type index out of range"); - return mTypeTable[idx]->GetType(); +TreeNode *TypeTable::GetTypeFromTypeIdx(unsigned tidx) { + MASSERT(tidx < mTypeTable.size() && "type index out of range"); + return mTypeTable[tidx]->GetType(); +} + +TreeNode *TypeTable::GetTypeFromStrIdx(unsigned stridx) { + for (auto entry : mTypeTable) { + TreeNode *node = entry->GetType(); + if (node && node->GetStrIdx() == stridx) { + return node; + } + } + return NULL; } unsigned TypeTable::GetOrCreateFunctionTypeIdx(FunctionTypeNode *node) { - for (auto idx: mFuncTypeIdx) { - TreeNode *type = GetTypeFromTypeIdx(idx); + for (auto tidx: mFuncTypeIdx) { + TreeNode *type = GetTypeFromTypeIdx(tidx); FunctionTypeNode *functype = static_cast(type); bool found = functype->IsEqual(node); if (found) { - return idx; + return tidx; } } bool status = AddType(node); MASSERT(status && "failed to add a functiontype"); - unsigned idx = node->GetTypeIdx(); - mFuncTypeIdx.insert(idx); - return idx; + unsigned tidx = node->GetTypeIdx(); + mFuncTypeIdx.insert(tidx); + + std::string str("FuncType__"); + str += std::to_string(tidx); + unsigned stridx = gStringPool.GetStrIdx(str); + node->SetStrIdx(stridx); + + return tidx; } void TypeTable::Dump() { -- Gitee From d4fae42b830ee948e41f90aeea17a6ae417bec6f Mon Sep 17 00:00:00 2001 From: Wen HU Date: Sun, 13 Mar 2022 15:01:22 -0400 Subject: [PATCH 44/44] rename return type mType to mRetType for function and lambda nodes --- src/MapleFE/ast2cpp/src/cpp_declaration.cpp | 4 ++-- src/MapleFE/ast2cpp/src/cpp_definition.cpp | 2 +- src/MapleFE/ast2cpp/src/emitter.cpp | 6 +++--- src/MapleFE/ast2mpl/src/mpl_processor.cpp | 2 +- src/MapleFE/astopt/src/ast_adj.cpp | 8 ++++---- src/MapleFE/astopt/src/ast_info.cpp | 6 +++--- src/MapleFE/astopt/src/ast_scp.cpp | 2 +- src/MapleFE/astopt/src/ast_ti.cpp | 16 ++++++++-------- src/MapleFE/shared/include/ast.h | 14 +++++++------- src/MapleFE/shared/src/ast.cpp | 4 ++-- src/MapleFE/shared/src/ast_builder.cpp | 4 ++-- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp index 20f4128f1b..315c8624b6 100644 --- a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp @@ -397,7 +397,7 @@ namespace )""" + module + R"""( { } else { // gen function class for each top level function - str += FunctionClassDecl(GetTypeString(static_cast(node)->GetType(), nullptr), GetIdentifierName(node), node->GetNodeId()); + str += FunctionClassDecl(GetTypeString(static_cast(node)->GetRetType(), nullptr), GetIdentifierName(node), node->GetNodeId()); } if (!mHandler->IsFromLambda(node)) { // top level funcs instantiated here as function objects from their func class @@ -441,7 +441,7 @@ namespace )""" + module + R"""( { std::string CppDecl::EmitFunctionNode(FunctionNode *node) { if (node == nullptr) return std::string(); - std::string str(GetTypeString(node->GetType(), node->GetType())); + std::string str(GetTypeString(node->GetRetType(), node->GetRetType())); if(node->GetStrIdx()) str += " "s + node->GetName(); str += "("s; diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index ad65c9994f..d6b1935446 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -330,7 +330,7 @@ std::string CppDef::EmitFunctionNode(FunctionNode *node) { bool isTopLevel = hFuncTable.IsTopLevelFunc(node); std::string str; str += "\n"; - str += FunctionHeader(node, mCppDecl.GetTypeString(node->GetType(), node->GetType())); + str += FunctionHeader(node, mCppDecl.GetTypeString(node->GetRetType(), node->GetRetType())); mIsGenerator = node->IsGenerator(); int bodyPos = str.size(); diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index 35608da63f..fbf695857e 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -285,7 +285,7 @@ std::string Emitter::EmitFunctionNode(FunctionNode *node) { str += " : asserts "s + EmitTreeNode(n); auto body = node->GetBody(); - if (auto n = node->GetType()) { + if (auto n = node->GetRetType()) { std::string s = EmitTreeNode(n); if(!s.empty()) { str += (body || has_name || inside ? " : "s : " => "s) + s; @@ -1766,7 +1766,7 @@ std::string Emitter::EmitLambdaNode(LambdaNode *node) { str += ')'; if (auto n = node->GetBody()) { - if (auto t = node->GetType()) { + if (auto t = node->GetRetType()) { str += ": "s + EmitTreeNode(t); } std::string s = EmitTreeNode(n); @@ -1776,7 +1776,7 @@ std::string Emitter::EmitLambdaNode(LambdaNode *node) { str += " => "s + s; } else { - if (auto t = node->GetType()) { + if (auto t = node->GetRetType()) { str += " => "s + EmitTreeNode(t); } } diff --git a/src/MapleFE/ast2mpl/src/mpl_processor.cpp b/src/MapleFE/ast2mpl/src/mpl_processor.cpp index 0e5cf00ed5..378c18860f 100644 --- a/src/MapleFE/ast2mpl/src/mpl_processor.cpp +++ b/src/MapleFE/ast2mpl/src/mpl_processor.cpp @@ -658,7 +658,7 @@ maple::BaseNode *Ast2MplBuilder::ProcessFuncDecl(StmtExprKind skind, TreeNode *t // SmallVector mAttrs; // SmallVector mAnnotations; //annotation or pragma // SmallVector mThrows; // exceptions it can throw - TreeNode *ast_rettype = ast_func->GetType(); // return type + TreeNode *ast_rettype = ast_func->GetRetType(); // return type // SmallVector mParams; // BlockNode *ast_body = ast_func->GetBody(); // DimensionNode *mDims; diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index 700de269f3..64b8e82bf1 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -328,7 +328,7 @@ FunctionNode *AdjustASTVisitor::VisitFunctionNode(FunctionNode *node) { gStringPool.AddAltStrIdx(it->GetStrIdx()); } - TreeNode *type = node->GetType(); + TreeNode *type = node->GetRetType(); if (type && type->IsUserType()) { type->SetParent(node); } @@ -554,7 +554,7 @@ LambdaNode *AdjustASTVisitor::VisitLambdaNode(LambdaNode *node) { if (tn) { if (tn->IsBlock()) { func->SetBody(static_cast(tn)); - func->SetType(node->GetType()); + func->SetRetType(node->GetRetType()); } else { BlockNode *blk = mHandler->NewTreeNode(); ReturnNode *ret = mHandler->NewTreeNode(); @@ -566,8 +566,8 @@ LambdaNode *AdjustASTVisitor::VisitLambdaNode(LambdaNode *node) { } // func return type - if (node->GetType()) { - func->SetType(node->GetType()); + if (node->GetRetType()) { + func->SetRetType(node->GetRetType()); } mUpdated = true; diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index c7e3cb41ac..5c8ef881ec 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -686,7 +686,7 @@ IdentifierNode *FillNodeInfoVisitor::VisitIdentifierNode(IdentifierNode *node) { FunctionNode *FillNodeInfoVisitor::VisitFunctionNode(FunctionNode *node) { (void) AstVisitor::VisitFunctionNode(node); - TreeNode *type = node->GetType(); + TreeNode *type = node->GetRetType(); if (type) { mInfo->SetTypeId(node, type->GetTypeId()); mInfo->SetTypeIdx(node, type->GetTypeIdx()); @@ -694,7 +694,7 @@ FunctionNode *FillNodeInfoVisitor::VisitFunctionNode(FunctionNode *node) { unsigned stridx = gStringPool.GetStrIdx("Generator"); unsigned tidx = mInfo->GetBuiltInTypeIdx(stridx); UserTypeNode *ut = mInfo->CreateUserTypeNode(stridx); - node->SetType(ut); + node->SetRetType(ut); } return node; } @@ -949,7 +949,7 @@ FunctionNode *FunctionVisitor::VisitFunctionNode(FunctionNode *node) { } // add return - n = node->GetType(); + n = node->GetRetType(); functype->AddParam(n ? n->GetTypeIdx() : 0); unsigned tidx = gTypeTable.GetOrCreateFunctionTypeIdx(functype); diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index 33882e994f..fe472ccd5e 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -492,7 +492,7 @@ UserTypeNode *BuildScopeVisitor::VisitUserTypeNode(UserTypeNode *node) { if (p->IsFunction()) { // exclude function return type FunctionNode *f = static_cast(p); - if (f->GetType() == node) { + if (f->GetRetType() == node) { return node; } } else if (p->IsTypeAlias()) { diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 86715f045a..99439b59de 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -574,13 +574,13 @@ void TypeInferVisitor::UpdateFuncRetTypeId(FunctionNode *node, TypeId tid, unsig if (!node || (node->GetTypeId() == tid && node->GetTypeIdx() == tidx)) { return; } - TreeNode *type = node->GetType(); + TreeNode *type = node->GetRetType(); // create new return type node if it was shared if (type) { if (type->IsPrimType() && type->IsTypeIdNone()) { type = GetOrClonePrimTypeNode((PrimTypeNode *)type, tid); - node->SetType(type); + node->SetRetType(type); } tid = MergeTypeId(type->GetTypeId(), tid); SetTypeId(type, tid); @@ -1093,8 +1093,8 @@ CallNode *TypeInferVisitor::VisitCallNode(CallNode *node) { mHandler->AddGeneratorUsed(node->GetNodeId(), func); } // update call's return type - if (func->GetType()) { - UpdateTypeId(node, func->GetType()->GetTypeId()); + if (func->GetRetType()) { + UpdateTypeId(node, func->GetRetType()->GetTypeId()); } // skip imported and exported functions as they are generic // so should not restrict their types @@ -1664,7 +1664,7 @@ IsNode *TypeInferVisitor::VisitIsNode(IsNode *node) { TreeNode *parent = node->GetParent(); if (parent->IsFunction()) { FunctionNode *func = static_cast(parent); - if (func->GetType() == node) { + if (func->GetRetType() == node) { TreeNode *right = node->GetRight(); if (right->IsUserType()) { TreeNode *id = static_cast(right)->GetId(); @@ -1781,16 +1781,16 @@ ReturnNode *TypeInferVisitor::VisitReturnNode(ReturnNode *node) { if (tn) { FunctionNode *func = static_cast(tn); // use dummy PrimTypeNode as return type of function if not set to carry return TypeId - if (!func->GetType()) { + if (!func->GetRetType()) { PrimTypeNode *type = mHandler->NewTreeNode(); type->SetPrimType(TY_None); - func->SetType(type); + func->SetRetType(type); } if (!func->IsGenerator() && !func->IsIterator()) { UpdateFuncRetTypeId(func, node->GetTypeId(), node->GetTypeIdx()); if (res) { // use res to update function's return type - UpdateTypeUseNode(func->GetType(), res); + UpdateTypeUseNode(func->GetRetType(), res); } } } diff --git a/src/MapleFE/shared/include/ast.h b/src/MapleFE/shared/include/ast.h index 4ef9361c73..347f8d4434 100644 --- a/src/MapleFE/shared/include/ast.h +++ b/src/MapleFE/shared/include/ast.h @@ -1830,7 +1830,7 @@ private: SmallVector mThrows; // exceptions it can throw SmallVector mTypeParams; TreeNode *mFuncName; // function name, usually an identifier - TreeNode *mType; // return type + TreeNode *mRetType; // return type SmallVector mParams; // BlockNode *mBody; DimensionNode *mDims; @@ -1909,8 +1909,8 @@ public: void SetTypeParamAtIndex(unsigned i, TreeNode* n) {*(mTypeParams.RefAtIndex(i)) = n; SETPARENT(n);} void AddTypeParam(TreeNode *); - void SetType(TreeNode *t) {mType = t; SETPARENT(t);} - TreeNode* GetType(){return mType;} + void SetRetType(TreeNode *t) {mRetType = t; SETPARENT(t);} + TreeNode* GetRetType(){return mRetType;} DimensionNode* GetDims() {return mDims;} void SetDims(DimensionNode *t) {mDims = t;} @@ -2120,7 +2120,7 @@ enum LambdaProperty { class LambdaNode : public TreeNode { private: LambdaProperty mProperty; - TreeNode *mType; // The return type. nullptr as Java Lambda. + TreeNode *mRetType; // The return type. nullptr as Java Lambda. SmallVector mParams; // A param could be an IdentifierNode or DeclNode. TreeNode *mBody; // the body could be an expression, or block. // nullptr as TS FunctionType and ConstructorType @@ -2128,7 +2128,7 @@ private: SmallVector mAttrs; public: LambdaNode() : TreeNode(NK_Lambda), - mBody(nullptr), mProperty(LP_JSArrowFunction), mType(nullptr) {} + mBody(nullptr), mProperty(LP_JSArrowFunction), mRetType(nullptr) {} ~LambdaNode(){Release();} @@ -2138,8 +2138,8 @@ public: LambdaProperty GetProperty() {return mProperty;} void SetProperty(LambdaProperty p) {mProperty = p;} - TreeNode* GetType() {return mType;} - void SetType(TreeNode* t) {mType = t; SETPARENT(t);} + TreeNode* GetRetType() {return mRetType;} + void SetRetType(TreeNode* t) {mRetType = t; SETPARENT(t);} unsigned GetParamsNum() {return mParams.GetNum();} TreeNode* GetParam(unsigned i) {return mParams.ValueAtIndex(i);} diff --git a/src/MapleFE/shared/src/ast.cpp b/src/MapleFE/shared/src/ast.cpp index 937d6431c5..f42e21d7ff 100644 --- a/src/MapleFE/shared/src/ast.cpp +++ b/src/MapleFE/shared/src/ast.cpp @@ -1775,7 +1775,7 @@ void ClassNode::Dump(unsigned indent) { ////////////////////////////////////////////////////////////////////////////////////// FunctionNode::FunctionNode() : TreeNode(NK_Function), - mFuncName(NULL), mType(NULL), mBody(NULL), mDims(NULL), + mFuncName(NULL), mRetType(NULL), mBody(NULL), mDims(NULL), mIsConstructor(false), mIsGenerator(false), mIsIterator(false), mIsGetAccessor(false), mIsSetAccessor(false), mIsCallSignature(false), mIsConstructSignature(false), mAssert(NULL) {} @@ -1797,7 +1797,7 @@ void FunctionNode::AddTypeParam(TreeNode *param) { // and parameter types. So languages require Type Erasure at first, like Java. // Type erasure should be done earlier in language specific process. bool FunctionNode::OverrideEquivalent(FunctionNode *fun) { - if (!mType->TypeEquivalent(fun->GetType())) + if (!mRetType->TypeEquivalent(fun->GetRetType())) return false; if (GetStrIdx() != fun->GetStrIdx()) return false; diff --git a/src/MapleFE/shared/src/ast_builder.cpp b/src/MapleFE/shared/src/ast_builder.cpp index e715baa5a1..707f0e13e6 100644 --- a/src/MapleFE/shared/src/ast_builder.cpp +++ b/src/MapleFE/shared/src/ast_builder.cpp @@ -176,14 +176,14 @@ static void add_type_to(TreeNode *tree, TreeNode *type) { lit->SetType(type); } else if (tree->IsLambda()) { LambdaNode *lam = (LambdaNode*)tree; - lam->SetType(type); + lam->SetRetType(type); } else if (tree->IsVarList()) { VarListNode *vl = (VarListNode*)tree; for (unsigned i = 0; i < vl->GetVarsNum(); i++) vl->GetVarAtIndex(i)->SetType(type); } else if (tree->IsFunction()) { FunctionNode *func = (FunctionNode*)tree; - func->SetType(type); + func->SetRetType(type); } else if (tree->IsBindingPattern()) { BindingPatternNode *bp = (BindingPatternNode*)tree; bp->SetType(type); -- Gitee