diff --git a/src/MapleFE/ast2cpp/include/cpp_declaration.h b/src/MapleFE/ast2cpp/include/cpp_declaration.h index 9a5c3690e3be0f9bd17865c27c256252fad0157a..352a0006bc51c858d06c97b5bd1a24562cb4e327 100644 --- a/src/MapleFE/ast2cpp/include/cpp_declaration.h +++ b/src/MapleFE/ast2cpp/include/cpp_declaration.h @@ -58,7 +58,6 @@ public: std::string EmitCallNode(CallNode *node) override; std::string EmitFunctionNode(FunctionNode *node) override; std::string EmitPrimTypeNode(PrimTypeNode *node) override; - std::string EmitPrimArrayTypeNode(PrimArrayTypeNode *node) override; std::string EmitModuleNode(ModuleNode *node) override; std::string EmitClassNode(ClassNode *node) override; @@ -69,13 +68,15 @@ public: std::string EmitStructNode(StructNode *node) override; std::string EmitTypeAliasNode(TypeAliasNode* node) override; std::string EmitLiteralNode(LiteralNode* node) override; + std::string EmitArrayTypeNode(ArrayTypeNode *node) override; std::string GetTypeString(TreeNode *node, TreeNode *child = nullptr); - std::string EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::string type); std::string EmitTSEnum(StructNode *node); std::string EmitInterface(StructNode *node); void CollectFuncArgInfo(TreeNode* node); + std::string ConstructArray(ArrayLiteralNode* node, int dim, std::string type); + std::string ConstructArrayAny(ArrayLiteralNode* node); }; inline bool IsVarInitStructLiteral(DeclNode* node) { @@ -90,8 +91,6 @@ inline bool IsVarInitClass(DeclNode* node) { node->GetInit()->IsIdentifier(); } -bool IsBuiltinObj(std::string name); - template bool HasAttrStatic(T* node) { for (unsigned i = 0; i < node->GetAttrsNum(); ++i) { diff --git a/src/MapleFE/ast2cpp/include/cpp_definition.h b/src/MapleFE/ast2cpp/include/cpp_definition.h index 07dfec249ed6cc74b436aac3a7d428f40a6bcd12..ff6b0c1b0c21f50d75a83bf6da8f3761a1cd6312 100644 --- a/src/MapleFE/ast2cpp/include/cpp_definition.h +++ b/src/MapleFE/ast2cpp/include/cpp_definition.h @@ -74,14 +74,14 @@ public: std::string EmitCtorInstance(ClassNode *c); std::string EmitDefaultCtor(ClassNode *c); std::string EmitBracketNotationProp(ArrayElementNode* ae, OprId binOpId, bool isLhs, bool& isDynProp); - std::string EmitArrayLiteral(TreeNode* arrType, TreeNode* arrLiteral); - std::string EmitArrayLiterals(TreeNode* arrLiteral, int dim, std::string type); TypeId GetTypeIdFromDecl(TreeNode* id); bool IsClassField(ArrayElementNode* node, std::string propKey); std::string GetTypeForTemplateArg(TreeNode* node); TreeNode* FindDeclType(TreeNode* node); std::string GetThisParamObjType(TreeNode *node); - std::string GenArrayOfAny(TreeNode* node); + + std::string ConstructArray(ArrayLiteralNode* node, int dim, std::string type); + std::string ConstructArrayAny(ArrayLiteralNode* node); std::string GenObjectLiteral(TreeNode* var, std::string varName, TreeNode* idType, StructLiteralNode* n); std::string GenDirectFieldInit(std::string varName, StructLiteralNode* node); }; diff --git a/src/MapleFE/ast2cpp/include/cpp_emitter.h b/src/MapleFE/ast2cpp/include/cpp_emitter.h index 6de63255253141a10d91f861eccc9f23f35aae56..a68d25a726857bf06ddc956611121f528e3e9bfd 100644 --- a/src/MapleFE/ast2cpp/include/cpp_emitter.h +++ b/src/MapleFE/ast2cpp/include/cpp_emitter.h @@ -36,6 +36,7 @@ public: void InsertEscapes(std::string& str); bool IsGenerator(TreeNode *node); FunctionNode* GetGeneratorFunc(TreeNode *node); + void GetArrayTypeInfo(ArrayLiteralNode* node, int& numDim, std::string& type); }; } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index 47c543d71e16d5c1ff17d6c21634858bf0bbbec6..6901cda2070f7d4f5bdf1d0b648e3403075f25b8 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -47,6 +47,8 @@ inline std::string GeneratorFuncName(std::string func) { return "GeneratorFunc_" 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); class FuncTable { private: diff --git a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp index 8119e39ff33404d5e09efa148247eb630bac2495..dd59280855a63b9f32db81a548775f713f86762d 100644 --- a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp @@ -513,6 +513,11 @@ std::string CppDecl::EmitIdentifierNode(IdentifierNode *node) { if (HasAttrStatic(node)) str = "static "s + str; + else if (auto n = node->GetInit()) { + // emit init for non static class field + if (node->GetParent() && node->GetParent()->IsClass()) + str += " = "s + EmitTreeNode(n); + } return str; } @@ -557,25 +562,36 @@ std::string CppDecl::EmitAssertNode(AssertNode *node) { return std::string(); } -std::string CppDecl::EmitArrayLiteralNode(ArrayLiteralNode *node) { - if (node == nullptr) +// Generate code to construct an array of type any from an ArrayLiteral. TODO: merge with similar in cppdef +std::string CppDecl::ConstructArrayAny(ArrayLiteralNode *node) { + if (node == nullptr || !node->IsArrayLiteral()) return std::string(); - std::string str("{"s); + + // Generate array ctor call to instantiate array + std::string literals; for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) - str += ", "s; + literals += ", "s; if (auto n = node->GetLiteral(i)) { - str += EmitTreeNode(n); + if (n->IsArrayLiteral()) + // Recurse to handle array elements that are arrays + literals += ConstructArrayAny(static_cast(n)); + else { + // Wrap element in JS_Val. C++ class constructor of JS_Val + // will set tupe tag in JS_Val according to element type. + literals += "t2crt::JS_Val("s + EmitTreeNode(n) + ")"s; + } } } - str += "}"s; + std::string str = ArrayCtorName(1, "t2crt::JS_Val") + "._new({"s + literals + "})"s; return str; } -std::string CppDecl::EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::string type) { - if (node == nullptr) - return std::string(); - +// Generate code to construct an array object with brace-enclosed initializer list TODO: merge with similar in cppdef +std::string CppDecl::ConstructArray(ArrayLiteralNode *node, int dim, std::string type) { + if (type.empty()) { + return ConstructArrayAny(node); // proceed as array of type any if no type info + } // Generate array ctor call to instantiate array std::string str = ArrayCtorName(dim, type) + "._new({"s; for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { @@ -583,7 +599,7 @@ std::string CppDecl::EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::stri str += ", "s; if (auto n = node->GetLiteral(i)) { if (n->IsArrayLiteral()) - str += EmitArrayLiteral(static_cast(n), dim-1, type); + str += ConstructArray(static_cast(n), dim-1, type); else str += EmitTreeNode(n); } @@ -592,7 +608,35 @@ std::string CppDecl::EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::stri return str; } -std::string GetArrayTypeString(int dim, std::string typeStr) { +std::string CppDecl::EmitArrayLiteralNode(ArrayLiteralNode *node) { // TODO: merge with similar in cppdef + if (node == nullptr) + return std::string(); + if (node->GetParent() && + node->GetParent()->IsDecl() || // for var decl init + node->GetParent()->IsIdentifier() || // for default val init in class field decl + node->GetParent()->IsFieldLiteral()) { // for obj decl with struct literal init + // emit code to construct array object with brace-enclosed initializer list + int dim; + std::string str, type; + GetArrayTypeInfo(node, dim, type); + str = ConstructArray(node, dim, type); + return str; + } + + // emit code to build a brace-enclosed intializer list (for rhs of array var assignment op) + std::string str("{"s); + for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { + if (i) + str += ", "s; + if (auto n = node->GetLiteral(i)) { + str += EmitTreeNode(n); + } + } + str += "}"s; + return str; +} + +std::string BuildArrayType(int dim, std::string typeStr) { std::string str; str = "t2crt::Array<"s + typeStr + ">*"s;; for (unsigned i = 1; i < dim; ++i) { @@ -601,20 +645,16 @@ std::string GetArrayTypeString(int dim, std::string typeStr) { return str; } -std::string CppDecl::EmitPrimArrayTypeNode(PrimArrayTypeNode *node) { +std::string CppDecl::EmitArrayTypeNode(ArrayTypeNode *node) { if (node == nullptr) return std::string(); std::string str; - if (node->GetPrim() && node->GetDims()) { - str = GetArrayTypeString( - static_cast(node->GetDims())->GetDimensionsNum(), - EmitPrimTypeNode(node->GetPrim())); - } - /* - if (auto n = node->GetDims()) { - str += EmitDimensionNode(n); + + if (node->GetElemType() && node->GetDims()) { + str = BuildArrayType( + node->GetDims()->GetDimensionsNum(), + EmitTreeNode(node->GetElemType())); } - */ return str; } @@ -622,24 +662,6 @@ std::string CppDecl::EmitFieldNode(FieldNode *node) { return std::string(); } -// note: entries below are to match values from ast nodes. Do not prepend with "t2crt::" -std::vectorbuiltins = {"Object", "Function", "Number", "Array", "Record"}; - -bool IsBuiltinObj(std::string name) { - return std::find(builtins.begin(), builtins.end(), name) != builtins.end(); -} - -std::string GetUserTypeString(UserTypeNode* n) { - std::string str=""; - if (n->GetId()->IsTypeIdClass()) - str = n->GetId()->GetName() + "*"s; - else if (IsBuiltinObj(n->GetId()->GetName())) - str = "t2crt::"s + n->GetId()->GetName() + "*"s; - else // TypeAlias Id - str = n->GetId()->GetName(); - return str; -} - std::string CppDecl::GetTypeString(TreeNode *node, TreeNode *child) { std::string str; if (node) { @@ -725,11 +747,7 @@ std::string CppDecl::EmitUserTypeNode(UserTypeNode *node) { else // TypeAlias Id gets returned here usrType = n->GetName(); - if (node->GetDims()) { - return GetArrayTypeString(node->GetDims()->GetDimensionsNum(), usrType); - } else { - str = usrType; - } + str = usrType; // note: array dimension now come from ArrayTypeNode auto num = node->GetTypeGenericsNum(); if(num) { std::string lastChar = ""; @@ -787,26 +805,13 @@ std::string CppDecl::EmitClassNode(ClassNode *node) { // class field decl and init. TODO: handle private, protected attrs. for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { auto n = node->GetField(i); - if (n->IsIdentifier() && GetIdentifierName(n).compare("private")==0) - continue; str += " "s + EmitTreeNode(n); if (n->IsIdentifier()) { - IdentifierNode* id = static_cast(n); - if (HasAttrStatic(id)) { + if (HasAttrStatic(static_cast(n))) { // static field - add field to ctor prop and init later at field def in cpp staticProps += tab(3) + "this->AddProp(\""s + clsName + "\", t2crt::JS_Val("s + - TypeIdToJSTypeCXX[n->GetTypeId()] + ", &"s + clsName + "::"s + id->GetName() + "));\n"s; - } else if (auto init = id->GetInit()) { - if (init->IsArrayLiteral() && id->GetType() && id->GetType()->IsPrimArrayType()) { - // Generate initializer for t2crt::Array member field decl in header file - PrimArrayTypeNode* mtype = static_cast(id->GetType()); - str += " = "s + EmitArrayLiteral(static_cast(init), - mtype->GetDims()->GetDimensionsNum(), - EmitPrimTypeNode(mtype->GetPrim())); - } else { - str += " = "s + EmitTreeNode(init); - } + TypeIdToJSTypeCXX[n->GetTypeId()] + ", &"s + clsName + "::"s + GetIdentifierName(n) + "));\n"s; } } str += ";\n"; diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index 098ffd00b031d62662e59cedf8c6f5dd3670a943..cd1028195a0134383352a7c693f09ab3455ea839 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -236,7 +236,7 @@ std::string CppDef::EmitClassProps(TreeNode* node) { // a decl list with unique names for insert into function definition. // // The var may be initialized to different values in different -// blocks which will done in the individual DeclNodes (re: var-dup.ts) +// blocks which will be done in the individual DeclNodes (re: var-dup.ts) std::string CppDef::EmitFuncScopeVarDecls(FunctionNode *node) { std::unordered_mapvarDeclsInScope; ASTScope* s = node->GetScope(); @@ -258,8 +258,8 @@ std::string CppDef::EmitFuncScopeVarDecls(FunctionNode *node) { } std::string str; for (auto const&[key, val] : varDeclsInScope) { - // Emit decl for the var (just type, name - init part emitted - // when corresponding DeclNode processed + // Emit decl for the var (just type and name). The init part + // to be emitted when corresponding DeclNode is processed str += tab(1) + mCppDecl.EmitTreeNode(val->GetVar()) + ";\n"s; } return str; @@ -374,7 +374,7 @@ std::string CppDef::EmitStructLiteralNode(StructLiteralNode* node) { case TY_Function: break; case TY_Array: - fieldVal = EmitArrayLiteral(nullptr, lit); + fieldVal = EmitTreeNode(lit); // ArrayLiteralNode str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val("s + fieldVal + "))"s; break; case TY_Boolean: @@ -460,19 +460,19 @@ std::string CppDef::GenObjectLiteral(TreeNode* var, std::string varName, TreeNod } // Generate code to construct an array of type any from an ArrayLiteral. -std::string CppDef::GenArrayOfAny(TreeNode *node) { +std::string CppDef::ConstructArrayAny(ArrayLiteralNode *node) { if (node == nullptr || !node->IsArrayLiteral()) return std::string(); // Generate array ctor call to instantiate array std::string literals; - for (unsigned i = 0; i < static_cast(node)->GetLiteralsNum(); ++i) { + for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) literals += ", "s; - if (auto n = static_cast(node)->GetLiteral(i)) { + if (auto n = node->GetLiteral(i)) { if (n->IsArrayLiteral()) // Recurse to handle array elements that are arrays - literals += GenArrayOfAny(n); + literals += ConstructArrayAny(static_cast(n)); else { // Wrap element in JS_Val. C++ class constructor of JS_Val // will set tupe tag in JS_Val according to element type. @@ -484,21 +484,19 @@ std::string CppDef::GenArrayOfAny(TreeNode *node) { return str; } -std::string CppDef::EmitArrayLiterals(TreeNode *node, int dim, std::string type) { - if (node == nullptr || !node->IsArrayLiteral()) - return std::string(); - - if (type.back() == ' ') - type.pop_back(); - +// Generate code to construct an array object with brace-enclosed initializer list +std::string CppDef::ConstructArray(ArrayLiteralNode *node, int dim, std::string type) { + if (type.empty()) { + return ConstructArrayAny(node); // proceed as array of type any if no type info + } // Generate array ctor call to instantiate array std::string str = ArrayCtorName(dim, type) + "._new({"s; - for (unsigned i = 0; i < static_cast(node)->GetLiteralsNum(); ++i) { + for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) str += ", "s; - if (auto n = static_cast(node)->GetLiteral(i)) { + if (auto n = node->GetLiteral(i)) { if (n->IsArrayLiteral()) - str += EmitArrayLiterals(static_cast(n), dim-1, type); + str += ConstructArray(static_cast(n), dim-1, type); else str += EmitTreeNode(n); } @@ -507,36 +505,19 @@ std::string CppDef::EmitArrayLiterals(TreeNode *node, int dim, std::string type) return str; } -std::string CppDef::EmitArrayLiteral(TreeNode* arrType, TreeNode* arrLiteral) { - std::string str, type; - int dims = 1; // default to 1 dim array if no Dims info - if (arrLiteral == nullptr) - return "nullptr"s; - - if (arrType == nullptr) { - // if no arrary type info proceed as array of type any (JS_Val) - str = GenArrayOfAny(arrLiteral); - } else if (arrType->IsUserType()) { // array of usertyp - if (static_cast(arrType)->GetDims()) - dims = static_cast(arrType)->GetDimsNum(); - if (auto id = static_cast(arrType)->GetId()) { - type = id->GetName(); - if (type.compare("t2crt::Object") == 0 || type.compare("Object") == 0) - type = "t2crt::Object*"; - } - str = EmitArrayLiterals(arrLiteral, dims, type); - } else if (arrType->IsPrimArrayType()) { // array of prim type - if (static_cast(arrType)->GetDims()) - dims = static_cast(arrType)->GetDims()->GetDimensionsNum(); - type= EmitPrimTypeNode(static_cast(arrType)->GetPrim()); - str = EmitArrayLiterals(arrLiteral, dims, type); - } - return str; -} - // decl of global var is handled by EmitDeclNode in cpp_declaration // decl of function vars of type JS_Var is handled in EmitFuncSCopeVarDecls // This function handles init of global/func var, and decl/init of func let/const. +// +// Declaration of Javascript "var", "let" an "const" variables: +// - "var" decls are function/global scoped +// - "let" and "const" are block scoped +// TS/JS allows duplicate "var" declarations in global scope as well as +// function scope. Duplicate global scope var decls are resolved +// by the front end which make only 1 decl for the dup and changes any inits +// in the dup decls to assigments. Duplicate function scope var decls are +// handled in CppDef::EmitFuncScopeVarDecls. +// std::string CppDef::EmitDeclNode(DeclNode *node) { if (node == nullptr) return std::string(); @@ -551,13 +532,6 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { // For func var of JS_Let/JS_Const, emit both var type & name if (auto n = node->GetVar()) { varType = n->GetTypeId(); -#if 1 - if (varType == TY_None) { - // TODO: remove this workaround when the var type is corrected in AST - if (IsGenerator(n)) - varType = TY_Class; - } -#endif if (mIsInit || node->GetProp() == JS_Var) { // handle declnode inside for-of/for-in (uses GetSet() and has null GetInit()) if (!node->GetInit() && node->GetParent() && !node->GetParent()->IsForLoop()) @@ -571,9 +545,7 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { } } if (auto n = node->GetInit()) { - if (n->IsArrayLiteral()) - str += varStr + " = " + EmitArrayLiteral(idType, n); - else if (n->IsStructLiteral()) + if (n->IsStructLiteral()) str += GenObjectLiteral(node->GetVar(), varStr, idType, static_cast(n)); else if (node->GetVar()->IsIdentifier() && n->IsIdentifier() && n->IsTypeIdClass()) str += varStr + "= &"s + n->GetName() + "::ctor"s; // init with ctor address @@ -723,9 +695,23 @@ std::string CppDef::EmitArrayElementNode(ArrayElementNode *node) { return HandleTreeNode(str, node); } + std::string CppDef::EmitArrayLiteralNode(ArrayLiteralNode *node) { if (node == nullptr) return std::string(); + if (node->GetParent() && + node->GetParent()->IsDecl() || // for var decl init + node->GetParent()->IsIdentifier() || // for default val init in class field decl + node->GetParent()->IsFieldLiteral()) { // for obj decl with struct literal init + // emit code to construct array object with brace-enclosed initializer list + int dim; + std::string str, type; + GetArrayTypeInfo(node, dim, type); + str = ConstructArray(node, dim, type); + return str; + } + + // emit code to build a brace-enclosed intializer list (for rhs of array var assignment op) std::string str("{"s); for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) diff --git a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp index b791306fa2702a556ad1650550f80900ce318429..e04128c96e0c937e82b34af3b383de3af7a54b93 100644 --- a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp @@ -30,7 +30,7 @@ std::string CppEmitter::GetIdentifierName(TreeNode *node) { // anonymous name by frontend and can be accessed using node mStrIdx // through node GetName() interface. if (auto n = static_cast(node)->GetStructId()) - return GetIdentifierName(n); + return GetIdentifierName(n); else return node->GetName(); // for anonomyous name case NK_Function: @@ -140,4 +140,69 @@ FunctionNode* CppEmitter::GetGeneratorFunc(TreeNode* node) { return mHandler->GetGeneratorUsed(node->GetNodeId()); } +// +// Interface to get array type and dimension interface for an ArrayLiteral +// (should be just a wrapper to call TI interfaces GetArrayElemTypeId() +// and GetArrayDim(), but until the usage of those 2 interface can cover all +// use caes, this interface encaps any additional work to get array type info. +// +void CppEmitter::GetArrayTypeInfo(ArrayLiteralNode* node, int& numDim, std::string& type) { + TypeId typeId = mHandler->GetArrayElemTypeId(node->GetNodeId()); + DimensionNode* dim = mHandler->GetArrayDim(node->GetNodeId()); + if (dim) + numDim = dim->GetDimensionsNum(); + switch(typeId) { + case TY_Class: { + unsigned tIdx = mHandler->GetArrayElemTypeIdx(node->GetNodeId()); + TreeNode* tp = gTypeTable.GetTypeFromTypeIdx(tIdx); + type = ObjectTypeStr(tp->GetName()); + break; + } + case TY_Int: + type = "long"; + break; + case TY_String: + type = "std::string"; + break; + case TY_Double: + type = "double"; + break; + case TY_None: + type = "t2crt::JS_Val"; + break; +#if 0 + case TY_Array: + type = "t2crt::Array*"; + break; +#endif + case TY_Function: + default: + // TODO + dim = 0; + type = "TBD"; + break; + } + return; + +#if 0 + if (!node->GetParent()) + return; + + switch(node->GetParent()->GetKind()) { + case NK_Decl: + // e.g. var arr: number[]=[1,2,3]; + //GetArrInfoByVarId(node, dim, type); + break; + case NK_Identifier: + // e.g. class Foo { arr: number[]=[1,2,3]; } + //GetArrInfoByClassFieldId(node, dim, type); + break; + case NK_FieldLiteral: + // e.g. var: {arr:number[]} = { n:[1,2,3] }; + //GetArrInfoByObjLiteralClassField(node, dim, type); + break; + } +#endif +} + } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 4b01b7891b65e157f2dc5596a41f1d46d9bba5fa..432ed630020e44b89acbec32a9a90728e05a650f 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -356,4 +356,18 @@ std::string ArrayCtorName(int dim, std::string type) { return str; } +// note: entries below are to match values from ast nodes. Do not prepend with "t2crt::" +std::vectorbuiltins = {"Object", "Function", "Number", "Array", "Record"}; + +bool IsBuiltinObj(std::string name) { + return std::find(builtins.begin(), builtins.end(), name) != builtins.end(); +} + +std::string ObjectTypeStr(std::string name) { + if (IsBuiltinObj(name)) + return "t2crt::" + name + "*"; + else + return name + "*"; +} + } // namespace maplefe diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index d7015ef214abb17ceabce1118442277c042c16e6..12de84bcec91e2ccefe2bd83343c3a7062849631 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -214,6 +214,7 @@ UserTypeNode *AdjustASTVisitor::VisitUserTypeNode(UserTypeNode *node) { ArrayTypeNode *arr = mHandler->NewTreeNode(); arr->SetDims(dim); arr->SetElemType(etype); + node->SetDims(NULL); node = (UserTypeNode *)arr; } diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index 14b560d3a48d1280409a3d898ee1e80e6d36f4ff..650fe12dfdc4290c2e33914a4940653d7b1b43a2 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -746,7 +746,15 @@ LiteralNode *FillNodeInfoVisitor::VisitLiteralNode(LiteralNode *node) { PrimTypeNode *FillNodeInfoVisitor::VisitPrimTypeNode(PrimTypeNode *node) { (void) AstVisitor::VisitPrimTypeNode(node); - mInfo->SetTypeIdx(node, node->GetPrimType()); + TypeId prim = node->GetPrimType(); + bool isprim = gTypeTable.IsPrimTypeId(prim); + + if (isprim) { + mInfo->SetTypeIdx(node, prim); + } else { + TreeNode *type = gTypeTable.GetTypeFromTypeId(prim); + mInfo->SetTypeIdx(node, type->GetTypeIdx()); + } return node; } diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 13c0256111e65804dae3b020bbc2f8924f486be1..3d75298fa66fb555aa1c5e65c3d4b0d31546547a 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -85,7 +85,7 @@ IdentifierNode *BuildIdNodeToDeclVisitor::VisitIdentifierNode(IdentifierNode *no (void) AstVisitor::VisitIdentifierNode(node); // mHandler->FindDecl() will use/add entries to mNodeId2Decl TreeNode *decl = mHandler->FindDecl(node); - if (decl) { + if (decl && decl != node) { mHandler->GetUtil()->SetTypeId(node, decl->GetTypeId()); mHandler->GetUtil()->SetTypeIdx(node, decl->GetTypeIdx()); } @@ -93,8 +93,10 @@ IdentifierNode *BuildIdNodeToDeclVisitor::VisitIdentifierNode(IdentifierNode *no if (type && type->IsPrimType()) { PrimTypeNode *ptn = static_cast(type); TypeId tid = ptn->GetPrimType(); - // mHandler->GetUtil()->SetTypeId(node, tid); - mHandler->GetUtil()->SetTypeIdx(node, tid); + if (gTypeTable.IsPrimTypeId(tid)) { + // mHandler->GetUtil()->SetTypeId(node, tid); + mHandler->GetUtil()->SetTypeIdx(node, tid); + } } return node; } @@ -236,19 +238,32 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { case TY_Function: case TY_Array: result = TY_Merge; break; + case TY_Number: { + switch (tib) { + case TY_Int: + case TY_Long: + case TY_Float: + case TY_Double: result = tib; break; + default: result = TY_Merge; break; + } + break; + } + case TY_Boolean: { switch (tib) { case TY_Int: case TY_Long: case TY_Float: case TY_Double: result = tib; break; + case TY_Number: result = tia; break; default: result = TY_Merge; break; } break; } case TY_Int: { switch (tib) { - case TY_Boolean: result = TY_Int; break; + case TY_Number: + case TY_Boolean: result = tia; break; case TY_Long: case TY_Float: case TY_Double: result = tib; break; @@ -258,8 +273,9 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } case TY_Long: { switch (tib) { + case TY_Number: case TY_Boolean: - case TY_Int: result = TY_Long; break; + case TY_Int: result = tia; break; case TY_Float: case TY_Double: result = TY_Double; break; default: result = TY_Merge; break; @@ -268,8 +284,9 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } case TY_Float: { switch (tib) { + case TY_Number: case TY_Boolean: - case TY_Int: result = TY_Float; break; + case TY_Int: result = tia; break; case TY_Long: case TY_Double: result = TY_Double; break; default: result = TY_Merge; break; @@ -278,10 +295,11 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } case TY_Double: { switch (tib) { + case TY_Number: case TY_Boolean: case TY_Int: case TY_Long: - case TY_Double: result = TY_Double; break; + case TY_Double: result = tia; break; default: result = TY_Merge; break; } break; @@ -625,7 +643,7 @@ bool TypeInferVisitor::UpdateVarTypeWithInit(TreeNode *var, TreeNode *init) { IdentifierNode *idnode = static_cast(var); TreeNode *type = idnode->GetType(); // use init NewNode to set decl type - if (!type && init) { + if (init) { if (init->IsNew()) { NewNode *n = static_cast(init); if (n->GetId()) { @@ -647,28 +665,39 @@ bool TypeInferVisitor::UpdateVarTypeWithInit(TreeNode *var, TreeNode *init) { result = true; } } + } else if (init->IsStructLiteral()) { + if (!type && init->GetTypeIdx() != 0) { + type = gTypeTable.GetTypeFromTypeIdx(init->GetTypeIdx()); + UserTypeNode *utype = mInfo->CreateUserTypeNode(type->GetStrIdx(), var->GetScope()); + utype->SetParent(idnode); + idnode->SetType(utype); + SetUpdated(); + } } else if (init->IsArrayLiteral()) { TypeId tid = GetArrayElemTypeId(init); unsigned tidx = GetArrayElemTypeIdx(init); - if (IsPrimTypeId(tid)) { - PrimTypeNode *pt = mHandler->NewTreeNode(); - pt->SetPrimType(tid); - - PrimArrayTypeNode *pat = mHandler->NewTreeNode(); - pat->SetPrim(pt); - - DimensionNode *dims = mHandler->GetArrayDim(init->GetNodeId()); - pat->SetDims(dims); + if (type) { + if (type->IsArrayType()) { + ArrayTypeNode *pat = static_cast(type); + // update array element type + SetTypeId(pat->GetElemType(), tid); + SetTypeIdx(pat->GetElemType(), tidx); + SetUpdated(); + } else { + NOTYETIMPL("array type not ArrayTypeNode"); + } + return result; + } - pat->SetParent(idnode); - idnode->SetType(pat); - SetUpdated(); + TreeNode *elemtype = NULL; + if (IsPrimTypeId(tid)) { + elemtype = gTypeTable.GetTypeFromTypeId(tid); } else if (tidx != 0) { - TreeNode *t = gTypeTable.GetTypeFromTypeIdx(tidx); - UserTypeNode *utype = mInfo->CreateUserTypeNode(t->GetStrIdx(), var->GetScope()); - + elemtype = gTypeTable.GetTypeFromTypeIdx(tidx); + } + if (elemtype) { ArrayTypeNode *pat = mHandler->NewTreeNode(); - pat->SetElemType(utype); + pat->SetElemType(elemtype); DimensionNode *dims = mHandler->GetArrayDim(init->GetNodeId()); pat->SetDims(dims); @@ -835,15 +864,13 @@ FieldLiteralNode *TypeInferVisitor::VisitFieldLiteralNode(FieldLiteralNode *node ArrayLiteralNode *TypeInferVisitor::VisitArrayLiteralNode(ArrayLiteralNode *node) { UpdateTypeId(node, TY_Array); (void) AstVisitor::VisitArrayLiteralNode(node); - ArrayLiteralNode *al = node; if (node->IsArrayLiteral()) { - al = static_cast(node); - unsigned size = al->GetLiteralsNum(); + unsigned size = node->GetLiteralsNum(); TypeId tid = TY_None; unsigned tidx = 0; bool allElemArray = true; for (unsigned i = 0; i < size; i++) { - TreeNode *n = al->GetLiteral(i); + TreeNode *n = node->GetLiteral(i); TypeId id = n->GetTypeId(); unsigned idx = n->GetTypeIdx(); tid = MergeTypeId(tid, id); @@ -861,9 +888,9 @@ ArrayLiteralNode *TypeInferVisitor::VisitArrayLiteralNode(ArrayLiteralNode *node unsigned elemdim = DEFAULTVALUE; // recalculate element typeid tid = TY_None; - unsigned tidx = 0; + tidx = 0; for (unsigned i = 0; i < size; i++) { - TreeNode *n = al->GetLiteral(i); + TreeNode *n = node->GetLiteral(i); if (n->IsArrayLiteral()) { DimensionNode * dn = mHandler->GetArrayDim(n->GetNodeId()); unsigned currdim = dn ? dn->GetDimensionsNum() : 0; @@ -1532,14 +1559,26 @@ IdentifierNode *TypeInferVisitor::VisitIdentifierNode(IdentifierNode *node) { SetUpdated(); } } - if (node->GetInit()) { + TreeNode *init = node->GetInit(); + if (init) { if (node->GetTypeId() == TY_None) { - SetTypeId(node, node->GetInit()->GetTypeId()); + SetTypeId(node, init->GetTypeId()); } if (node->GetTypeIdx() == 0) { - SetTypeIdx(node, node->GetInit()->GetTypeIdx()); + SetTypeIdx(node, init->GetTypeIdx()); } SetUpdated(); + if (init->IsArrayLiteral()) { + // pass array element info + TypeId tid = mHandler->GetArrayElemTypeId(init->GetNodeId()); + unsigned tidx = mHandler->GetArrayElemTypeIdx(init->GetNodeId()); + UpdateArrayElemTypeMap(node, tid, tidx); + if (type && type->IsArrayType()) { + TreeNode *et = static_cast(type)->GetElemType(); + et->SetTypeId(tid); + et->SetTypeIdx(tidx); + } + } return node; } TreeNode *parent = node->GetParent(); diff --git a/src/MapleFE/docs/builtin-constructors.md b/src/MapleFE/docs/builtin-constructors.md index d5936b12a4d8ab368fab159c07d039a85774ef72..aa844737710707a03f7a67d1b7751fb919b9b24c 100644 --- a/src/MapleFE/docs/builtin-constructors.md +++ b/src/MapleFE/docs/builtin-constructors.md @@ -49,28 +49,27 @@ of corresponding built-in type: 20 Int8Array 21 InternalError (Mozilla only) 22 Map - 23 Math - 24 Number - 25 Object - 26 Promise - 27 Proxy - 28 RangeError - 29 ReferenceError - 30 RegExp - 31 Set - 32 SharedArrayBuffer - 33 String - 34 Symbol - 35 SyntaxError - 36 TypeError - 37 Uint16Array - 38 Uint32Array - 39 Uint8Array - 40 Uint8ClampedArray - 41 URIError - 42 WeakMap - 43 WeakRef - 44 WeakSet + 23 Number + 24 Object + 25 Promise + 26 Proxy + 27 RangeError + 28 ReferenceError + 29 RegExp + 30 Set + 31 SharedArrayBuffer + 32 String + 33 Symbol + 34 SyntaxError + 35 TypeError + 36 Uint16Array + 37 Uint32Array + 38 Uint8Array + 39 Uint8ClampedArray + 40 URIError + 41 WeakMap + 42 WeakRef + 43 WeakSet ``` ### 2. JavaScript builtin String/Number/Boolean object constructor and string/number/boolean primitive diff --git a/src/MapleFE/shared/include/ast_nk.def b/src/MapleFE/shared/include/ast_nk.def index e6c720c14006f403b4b22198267c15217799b57e..091b6931090a7a6a88b7c0b802624032fbf30ddc 100644 --- a/src/MapleFE/shared/include/ast_nk.def +++ b/src/MapleFE/shared/include/ast_nk.def @@ -43,6 +43,7 @@ NODEKIND(AsType) NODEKIND(TypeAlias) NODEKIND(ConditionalType) // Conditional types in Typescript NODEKIND(TupleType) // tuple types in Typescript +NODEKIND(FunctionType) // NODEKIND(Cast) diff --git a/src/MapleFE/shared/include/ast_type.h b/src/MapleFE/shared/include/ast_type.h index d120eafa87e479250a90ad64622fc82126e45fbc..0936dfeff560a8baf7d6007498e9ef21a1d9a5f9 100644 --- a/src/MapleFE/shared/include/ast_type.h +++ b/src/MapleFE/shared/include/ast_type.h @@ -136,6 +136,11 @@ public: void Dump(unsigned); }; +/////////////////////////////////////////////////////////////////////////////// +// ArrayTypeNode +// It is used to specify Array types, including element type and dimensions +/////////////////////////////////////////////////////////////////////////////// + class ArrayTypeNode : public TreeNode { private: TreeNode *mElemType; @@ -160,6 +165,31 @@ public: void Dump(unsigned); }; +/////////////////////////////////////////////////////////////////////////////// +// FunctionTypeNode +// It is used to specify function types with its signature and return type +/////////////////////////////////////////////////////////////////////////////// +class FunctionTypeNode : public TreeNode { +private: + SmallVector mParams; // type index of formal parameters + unsigned mRetType; // type index of return type + +public: + FunctionTypeNode() : TreeNode(NK_FunctionType), mRetType(0) {} + ~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); + void Dump(unsigned); +}; + /////////////////////////////////////////////////////////////////////////////// // PrimTypeNode & PrimTypePool // The size of PrimTypeNode is fixed, so it's good to use container for the storage. diff --git a/src/MapleFE/shared/include/typetable.h b/src/MapleFE/shared/include/typetable.h index 2817fadd4efbb22a9dd34536abdabc411f503f5d..c6bbcd2ca049a8b3b6b166d31cd2888bee595adb 100644 --- a/src/MapleFE/shared/include/typetable.h +++ b/src/MapleFE/shared/include/typetable.h @@ -22,6 +22,7 @@ #define __TYPETABLE_H__ #include +#include #include #include #include "massert.h" @@ -51,6 +52,7 @@ private: std::vector mTypeTable; std::unordered_map mNodeId2TypeIdxMap; std::unordered_map mTypeId2TypeMap; + std::unordered_set mPrimTypeId; unsigned mPrimSize; unsigned mPreBuildSize; @@ -63,11 +65,13 @@ public: 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(); } void Dump(); }; diff --git a/src/MapleFE/shared/src/ast_type.cpp b/src/MapleFE/shared/src/ast_type.cpp index 48744a1850407b0574586ad28d1e4eb1a7da73e7..f2c58b4ea231c0bc834da0322a5b47788ee82a61 100644 --- a/src/MapleFE/shared/src/ast_type.cpp +++ b/src/MapleFE/shared/src/ast_type.cpp @@ -175,6 +175,31 @@ static TypeId FindPrimTypeId(const char *keyword) { return TY_NA; } +////////////////////////////////////////////////////////////////////////// +// FunctionTypeNode // +////////////////////////////////////////////////////////////////////////// + +bool FunctionTypeNode::IsEqual(FunctionTypeNode *node) { + bool result = true; + if (node->GetRetType() != mRetType) { + result = false; + } else if (node->GetParamsNum() != GetParamsNum()) { + result = false; + } else { + for (unsigned i = 0; i < GetParamsNum(); i++) { + if (node->GetParam(i) != GetParam(i)) { + result = false; + break; + } + } + } + return result; +} + +void FunctionTypeNode::Dump(unsigned ind) { + DUMP0_NORETURN("functiontype-TBD"); +} + ////////////////////////////////////////////////////////////////////////// // PrimTypeNode // ////////////////////////////////////////////////////////////////////////// diff --git a/src/MapleFE/shared/src/typetable.cpp b/src/MapleFE/shared/src/typetable.cpp index c528450f355fa108fbe9af320fb24b12b24a2ca5..6c28e9243a8ab59d94d9f0f8efc43a481087968b 100644 --- a/src/MapleFE/shared/src/typetable.cpp +++ b/src/MapleFE/shared/src/typetable.cpp @@ -69,7 +69,8 @@ TreeNode *TypeTable::CreateBuiltinType(std::string name, TypeId tid) { unsigned stridx = gStringPool.GetStrIdx(name); IdentifierNode *id = (IdentifierNode*)gTreePool.NewTreeNode(sizeof(IdentifierNode)); new (id) IdentifierNode(stridx); - id->SetTypeId(tid); + // use TY_Class for Object type + (tid == TY_Object) ? id->SetTypeId(TY_Class) : id->SetTypeId(tid); UserTypeNode *utype = (UserTypeNode*)gTreePool.NewTreeNode(sizeof(UserTypeNode)); new (utype) UserTypeNode(id); @@ -97,6 +98,10 @@ bool TypeTable::AddType(TreeNode *node) { return true; } +void TypeTable::AddPrimTypeId(TypeId tid) { + mPrimTypeId.insert(tid); +} + #undef TYPE #undef PRIMTYPE void TypeTable::AddPrimAndBuiltinTypes() { @@ -112,7 +117,7 @@ void TypeTable::AddPrimAndBuiltinTypes() { // first are primitive types, and their typeid TY_Xyz is their typeidx as well #define TYPE(T) -#define PRIMTYPE(T) node = CreatePrimType(#T, TY_##T); AddType(node); +#define PRIMTYPE(T) node = CreatePrimType(#T, TY_##T); AddType(node); AddPrimTypeId(TY_##T); #include "supported_types.def" // add additional primitive types for number and string PRIMTYPE(Number); diff --git a/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result b/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result index 73efc592e98fb5a4c189e1b0bf162db5ebfcec9a..06e1681196983bfca57f375df768dced69a0d430 100644 --- a/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result +++ b/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result @@ -1,10 +1,13 @@ Matched 16 tokens. Matched 24 tokens. Matched 32 tokens. +Matched 40 tokens. ============= Module =========== == Sub Tree == ts_interface: JQueryEventObjectTest {data;which;metaKey } == Sub Tree == +trip-slash reference path = "jquery.d.ts" +== Sub Tree == ts_interface: SecondEvent {data } == Sub Tree == ts_interface: Third { } diff --git a/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts new file mode 100644 index 0000000000000000000000000000000000000000..29e5a31ca3b3a3ba94f49fbc89206d3bd06ec68c --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts @@ -0,0 +1,10 @@ +enum ET { + TOP = "top", /// < top string + BOTTOM = "bottom", ///< bottom string +} + +/// +/// + +let et = ET.TOP; +console.log(et); diff --git a/src/MapleFE/typescript/include/lang_builtin.def b/src/MapleFE/typescript/include/lang_builtin.def index 3b529b2cbb3922b4cb24343f2f10422991afe1ee..791452525da5c9d65a88608d27840c712bfd885e 100644 --- a/src/MapleFE/typescript/include/lang_builtin.def +++ b/src/MapleFE/typescript/include/lang_builtin.def @@ -37,7 +37,6 @@ BUILTIN(Int32Array) BUILTIN(Int8Array) BUILTIN(InternalError (Mozilla only)) BUILTIN(Map) -BUILTIN(Math) BUILTIN(Number) BUILTIN(Object) BUILTIN(Promise)