diff --git a/src/MapleFE/ast2cpp/include/cpp_definition.h b/src/MapleFE/ast2cpp/include/cpp_definition.h index 73953d592d096be4b46f1a33f7420d497b6b869c..f4721648df952dae5ecb4f24f4247058cff65438 100644 --- a/src/MapleFE/ast2cpp/include/cpp_definition.h +++ b/src/MapleFE/ast2cpp/include/cpp_definition.h @@ -63,14 +63,13 @@ public: std::string EmitDeclareNode(DeclareNode *node) override; std::string EmitAsTypeNode(AsTypeNode *node) override; std::string EmitNamespaceNode(NamespaceNode *node) override; + std::string EmitRegExprNode(RegExprNode *node); 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 EmitObjPropInit(TreeNode* var, std::string varName, TreeNode* idType, StructLiteralNode* n); - std::string EmitDirectFieldInit(std::string varName, StructLiteralNode* node); std::string EmitCppCtor(ClassNode* node); std::string EmitCtorInstance(ClassNode *c); std::string EmitDefaultCtor(ClassNode *c); @@ -82,6 +81,9 @@ public: std::string GetTypeForTemplateArg(TreeNode* node); TreeNode* FindDeclType(TreeNode* node); std::string GetThisParamObjType(TreeNode *node); + std::string GenArrayOfAny(TreeNode* node); + std::string GenObjectLiteral(TreeNode* var, std::string varName, TreeNode* idType, StructLiteralNode* n); + std::string GenDirectFieldInit(std::string varName, StructLiteralNode* node); }; } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/include/cpp_emitter.h b/src/MapleFE/ast2cpp/include/cpp_emitter.h index 1ec4ffe9270f04ca5084d9b548d33cca6712e4ea..601d341cd85340c407824d8d353017967b6e59ca 100644 --- a/src/MapleFE/ast2cpp/include/cpp_emitter.h +++ b/src/MapleFE/ast2cpp/include/cpp_emitter.h @@ -33,6 +33,7 @@ public: std::string GetQualifiedName(IdentifierNode *node); bool IsClassId(TreeNode *node); bool IsVarTypeClass(TreeNode* var); + void InsertEscapes(std::string& str); }; } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/include/emitter.h b/src/MapleFE/ast2cpp/include/emitter.h index 75374981e7edca57b40cfae7393d59f70e584d89..99046a87056031f271c8d74c913dd23bad6ea2ad 100644 --- a/src/MapleFE/ast2cpp/include/emitter.h +++ b/src/MapleFE/ast2cpp/include/emitter.h @@ -124,6 +124,7 @@ public: virtual std::string EmitAttrNode(AttrNode *node); virtual std::string EmitPrimTypeNode(PrimTypeNode *node); virtual std::string EmitPrimArrayTypeNode(PrimArrayTypeNode *node); + virtual std::string EmitArrayTypeNode(ArrayTypeNode *node); virtual std::string EmitTreeNode(TreeNode *node); virtual std::string& HandleTreeNode(std::string &str, TreeNode *node); diff --git a/src/MapleFE/ast2cpp/runtime/include/builtins.h b/src/MapleFE/ast2cpp/runtime/include/builtins.h index 70f4f09ce5a0db6dfb25997836697f5063278f03..8eea79172d8fdbd248775f8b05e69930648a06e5 100644 --- a/src/MapleFE/ast2cpp/runtime/include/builtins.h +++ b/src/MapleFE/ast2cpp/runtime/include/builtins.h @@ -42,7 +42,7 @@ class Array : public Object { long size() { return elements.size(); } // Output array to string (recurses if multi-dim array via ostream output operator overload in t2cpp.cpp) - virtual std::string Dump(void) { + std::string Dump (void) override { std::stringstream ss; std::streambuf* old = std::cout.rdbuf(ss.rdbuf()); if (elements.empty()) @@ -75,11 +75,6 @@ class Array : public Object { static Ctor ctor; }; -// Return pointer to Array object as JS_Val -inline JS_Val Arr2JsVal(Object* o, bool isCxx = false) { - return JS_Val(o, isCxx? TY_CXX_Array: TY_Array); -} - // Create ctor func for 1,2,3 dimension array of given type // note: must be in sync with format generated by ArrayCtorName in helper.h #define ARR_CTOR_DEF(type) \ @@ -96,6 +91,20 @@ class JSON : public Object { class RegExp : public Object { // TODO +public: + RegExp(Function* ctor, Object* proto): Object(ctor, proto) { } + RegExp(Function* ctor, Object* proto, std::string src): Object(ctor, proto) { source = src; } + ~RegExp(){} + std::string source; // text of the pattern + std::string Dump(void) override { return source; } + + class Ctor : public Function { + public: + Ctor(Function* ctor, Object* proto, Object* prototype_proto) : Function(ctor, proto, prototype_proto) { } + RegExp* _new(std::string src) {return new RegExp(this, this->prototype, src);} + virtual const char* __GetClassName() const {return "RegExp ";} + }; + static Ctor ctor; }; class Number : public Object { diff --git a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h index 91291117955b5fd6ecc585ea8d168b9221d12987..e88bce6fca22e7f7a4cea07c11b6da50188d81e9 100644 --- a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h +++ b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h @@ -216,7 +216,7 @@ class Object { virtual ~Object() {} class Ctor; static Ctor ctor; - virtual std::string Dump(void) { return("Object"); } + virtual std::string Dump(void); JS_Val& operator[] (std::string key) { @@ -492,7 +492,7 @@ std::ostream& operator<< (std::ostream& out, const t2crt::Array& v) { return out; } extern std::ostream& operator<< (std::ostream& out, const t2crt::JS_Val& v); -extern std::ostream& operator<< (std::ostream& out, const t2crt::Object* obj); +extern std::ostream& operator<< (std::ostream& out, t2crt::Object* obj); extern const t2crt::JS_Val undefined; extern const t2crt::JS_Val null; #define debugger (0) diff --git a/src/MapleFE/ast2cpp/runtime/src/builtins.cpp b/src/MapleFE/ast2cpp/runtime/src/builtins.cpp index 55c1546d93296baeba56befe504021a0e258f366..8537db12950b5d2f5376514acd2b19844e5b5a59 100644 --- a/src/MapleFE/ast2cpp/runtime/src/builtins.cpp +++ b/src/MapleFE/ast2cpp/runtime/src/builtins.cpp @@ -5,6 +5,7 @@ namespace t2crt { Object::Ctor Object::ctor (&Function::ctor, Function::ctor.prototype); Function::Ctor Function::ctor(&Function::ctor, Function::ctor.prototype, Object::ctor.prototype); Number::Ctor Number::ctor (&Function::ctor, Function::ctor.prototype, Object::ctor.prototype); +RegExp::Ctor RegExp::ctor (&Function::ctor, Function::ctor.prototype, Object::ctor.prototype); IteratorProto IteratorPrototype(&Object::ctor, Object::ctor.prototype); GeneratorFunctionPrototype Generator(&GeneratorFunction, Function::ctor.prototype, &IteratorPrototype); diff --git a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp index 9a7ef93cf7af157e38501c4a1ff69b8e135dc8a3..dc0177419dadae333d0bdc07177ff59f42d093d4 100644 --- a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp +++ b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp @@ -16,7 +16,6 @@ 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_Array: out << v.x.val_obj->Dump(); break; case t2crt::TY_CXX_Undef: out << "undefined"; break; case t2crt::TY_CXX_Null: out << "null"; break; @@ -28,15 +27,25 @@ 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_Array: out << (*(Object**)v.x.field)->Dump(); break; } return out; } -std::ostream& operator<< (std::ostream& out, const t2crt::Object *obj) { - out << obj->constructor->__GetClassName(); - if (obj->IsEmpty()) - out << "{}"; +std::ostream& operator<< (std::ostream& out, t2crt::Object *obj) { + out << obj->Dump(); + return out; +} + +const t2crt::JS_Val undefined = { 0, t2crt::TY_Undef, false }; +const t2crt::JS_Val null = { 0, t2crt::TY_Null, false }; + +namespace t2crt { + +std::string Object::Dump(void) { + std::string str; + str += this->constructor->__GetClassName(); + if (this->IsEmpty()) + str += "{}"; else { std::vector vec; unsigned cnt = 0; @@ -44,7 +53,7 @@ std::ostream& operator<< (std::ostream& out, const t2crt::Object *obj) { buf << std::boolalpha; // non-object fields go first for (bool flag: { false, true }) { - for (auto it = obj->propList.begin(); it != obj->propList.end(); it++) { + for (auto it = this->propList.begin(); it != this->propList.end(); it++) { auto k = it->second.type; auto b = k == t2crt::TY_Object || k == t2crt::TY_CXX_Object; if (b == flag) { @@ -72,19 +81,14 @@ std::ostream& operator<< (std::ostream& out, const t2crt::Object *obj) { } const char *p = "{ "; for (auto prop: vec) { - out << p << prop; + str += p + prop; p = ", "; } - out << " }"; + str += " }"; } - return out; + return str; } -const t2crt::JS_Val undefined = { 0, t2crt::TY_Undef, false }; -const t2crt::JS_Val null = { 0, t2crt::TY_Null, false }; - -namespace t2crt { - bool InstanceOf(JS_Val val, Function* ctor) { if (val.type != TY_Object || val.x.val_obj == nullptr || ctor == nullptr) return false; diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index 3531572c726b56cb82983b1597a7edbe044f3ce2..f8d5691caffa58373b68a748f38d1f4abc2110a1 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -345,10 +345,15 @@ std::string CppDef::EmitIdentifierNode(IdentifierNode *node) { return str; } -// Generate vector of t2crt::ObjectProp to be passed to t2crt::Object constructor. +// Generate code to create object instance that was declared using +// an object literal. First process the object literals in the +// StructLiteralNode argument to build the proplist list (vector of +// type ObjectProp) to be used as initializer, then generate call to +// the builtin Object constructor with initializer as parameter. std::string CppDef::EmitStructLiteralNode(StructLiteralNode* node) { std::string str; int stops = 2; + // Build proplist to be used as initializer str += "\n"s + tab(stops) + "std::vector({\n"s; for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { if (i) @@ -365,7 +370,8 @@ std::string CppDef::EmitStructLiteralNode(StructLiteralNode* node) { case TY_Function: break; case TY_Array: - //str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val(t2crt::Object*("s + fieldVal + ")))"s; + fieldVal = EmitArrayLiteral(nullptr, lit); + str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val("s + fieldVal + "))"s; break; case TY_Boolean: str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val(bool("s + fieldVal + ")))"s; @@ -373,6 +379,9 @@ std::string CppDef::EmitStructLiteralNode(StructLiteralNode* node) { case TY_None: if (fieldVal.compare("true") == 0 || fieldVal.compare("false") == 0) str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val(bool("s + fieldVal + ")))"s; + else + // if no type info, use type any (JS_Val) + str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val("s + fieldVal + "))"s; break; case TY_Int: str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val(int64_t("s + fieldVal + ")))"s; @@ -388,17 +397,19 @@ std::string CppDef::EmitStructLiteralNode(StructLiteralNode* node) { // Handle embedded t2crt::ObjectLiterals recursively if (lit->IsStructLiteral()) { std::string props = EmitStructLiteralNode(static_cast(lit)); - str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val(t2crt::Object::ctor._new("s + props + ")))"s; + str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val("s + props + "))"s; } break; } } } str += " })"s; + // Generate code to call builtin Object constructor with the initializer proplist. + str = "t2crt::Object::ctor._new("s + str + ")"s; return str; } -std::string CppDef::EmitDirectFieldInit(std::string varName, StructLiteralNode* node) { +std::string CppDef::GenDirectFieldInit(std::string varName, StructLiteralNode* node) { std::string str; //str += ";\n"s; for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { @@ -415,7 +426,7 @@ std::string CppDef::EmitDirectFieldInit(std::string varName, StructLiteralNode* return str; } -std::string CppDef::EmitObjPropInit(TreeNode* var, std::string varName, TreeNode* varIdType, StructLiteralNode* node) { +std::string CppDef::GenObjectLiteral(TreeNode* var, std::string varName, TreeNode* varIdType, StructLiteralNode* node) { if (varName.empty()) return std::string(); @@ -425,25 +436,50 @@ std::string CppDef::EmitObjPropInit(TreeNode* var, std::string varName, TreeNode if (userType == nullptr) { // no type info - create instance of builtin t2crt::Object with proplist - str = varName+ " = t2crt::Object::ctor._new("s + EmitTreeNode(node) + ")"s; + str = varName+ " = "s + EmitTreeNode(node); } else if (IsVarTypeClass(var)) { // init var of type TS class // - create obj instance of user defined class and do direct field access init // - todo: handle class with generics str = varName+ " = "s +userType->GetId()->GetName()+ "::ctor._new();\n"s; - str += EmitDirectFieldInit(varName, node); + str += GenDirectFieldInit(varName, node); } else { // type is builtin (e.g. t2crt::Record) and StructNode types (e.g. TSInterface) // create instance of type but set constructor to the builtin t2crt::Object. str = varName+ " = new "s +EmitUserTypeNode(userType)+ "(&t2crt::Object::ctor, t2crt::Object::ctor.prototype);\n"s; auto n = mHandler->FindDecl(static_cast(userType->GetId())); if (n && n->IsStruct() && static_cast(n)->GetProp() == SProp_TSInterface) { - str += EmitDirectFieldInit(varName, node); // do direct field init + str += GenDirectFieldInit(varName, node); // do direct field init } } return str; } +// Generate code to construct an array of type any from an ArrayLiteral. +std::string CppDef::GenArrayOfAny(TreeNode *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) { + if (i) + literals += ", "s; + if (auto n = static_cast(node)->GetLiteral(i)) { + if (n->IsArrayLiteral()) + // Recurse to handle array elements that are arrays + literals += GenArrayOfAny(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; + } + } + } + std::string str = ArrayCtorName(1, "t2crt::JS_Val") + "._new({"s + literals + "})"s; + return str; +} + std::string CppDef::EmitArrayLiterals(TreeNode *node, int dim, std::string type) { if (node == nullptr || !node->IsArrayLiteral()) return std::string(); @@ -470,10 +506,13 @@ std::string CppDef::EmitArrayLiterals(TreeNode *node, int dim, std::string type) 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 (arrType == nullptr || arrLiteral == nullptr) + if (arrLiteral == nullptr) return "nullptr"s; - if (arrType->IsUserType()) { // array of usertyp + 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()) { @@ -487,7 +526,7 @@ std::string CppDef::EmitArrayLiteral(TreeNode* arrType, TreeNode* arrLiteral) { dims = static_cast(arrType)->GetDims()->GetDimensionsNum(); type= EmitPrimTypeNode(static_cast(arrType)->GetPrim()); str = EmitArrayLiterals(arrLiteral, dims, type); - } + } return str; } @@ -500,11 +539,14 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { std::string str, varStr; TreeNode* idType = nullptr; + TypeId varType = TY_None; + //std::string str(Emitter::GetEnumDeclProp(node->GetProp())); // For func var of JS_Var and global vars, emit var name // For func var of JS_Let/JS_Const, emit both var type & name if (auto n = node->GetVar()) { + varType = n->GetTypeId(); 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()) @@ -521,7 +563,7 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { if (n->IsArrayLiteral()) str += varStr + " = " + EmitArrayLiteral(idType, n); else if (n->IsStructLiteral()) - str += EmitObjPropInit(node->GetVar(), varStr, idType, static_cast(n)); + 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 else if (n->IsFunction()) { @@ -529,8 +571,14 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { str += varStr + " = new "s + "Cls_" + n->GetName() + "()"s; hFuncTable.AddNameIsTopLevelFunc(varStr); } - } else - str += varStr + " = "s + EmitTreeNode(n); + } else { + // if no type info, assume type is any and wrap initializer in JS_Val. + str += varStr + " = "; + if (varType == TY_None) + str += "t2crt::JS_Val("s + EmitTreeNode(n) + ")"s; + else + str += EmitTreeNode(n); + } } else { str = varStr; } @@ -1490,4 +1538,12 @@ std::string &CppDef::HandleTreeNode(std::string &str, TreeNode *node) { return str; } +std::string CppDef::EmitRegExprNode(RegExprNode *node) { + if (node == nullptr) + return std::string(); + std::string source = Emitter::EmitRegExprNode(node); + InsertEscapes(source); + return "RegExp::ctor._new(\""s + source + "\")"s; +} + } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp index efdf178a6cc0e5a65bd1f1dc6c733d8485a5193d..ba77a9c75c7426bfff3a90d19ebe10b36612825e 100644 --- a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp @@ -121,5 +121,9 @@ bool CppEmitter::IsVarTypeClass(TreeNode* var) { return false; } +void CppEmitter::InsertEscapes(std::string& str) { + Emitter::Replace(str, "\\", "\\\\", 0); + Emitter::Replace(str, "\"", "\\\"", 0); +} } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index 5711512895c30024d9181670b7ab09870e685092..5de29d991dc6f1556651d74fe0fbdc115bd62373 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -1986,6 +1986,12 @@ std::string Emitter::EmitPrimArrayTypeNode(PrimArrayTypeNode *node) { return HandleTreeNode(str, node); } +std::string Emitter::EmitArrayTypeNode(ArrayTypeNode *node) { + // TODO + std::string str = ""; + return str; +} + std::string Emitter::EmitTreeNode(TreeNode *node) { if (node == nullptr) return std::string(); @@ -2032,6 +2038,9 @@ std::string Emitter::EmitTreeNode(TreeNode *node) { case NK_PrimArrayType: return EmitPrimArrayTypeNode(static_cast(node)); break; + case NK_ArrayType: + return EmitArrayTypeNode(static_cast(node)); + break; case NK_UserType: return EmitUserTypeNode(static_cast(node)); break; diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index d44400fd3415f456e8ffe715fb43a241f0aaa2bd..281e3558b85c392e5bd83b10641316d8ec561d24 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -25,7 +25,7 @@ std::unordered_mapTypeIdToJSTypeCXX = { {TY_String, "t2crt::TY_CXX_String"}, {TY_Number, "t2crt::TY_CXX_Double"}, {TY_Double, "t2crt::TY_CXX_Double"}, - {TY_Array, "t2crt::TY_CXX_Array"}, + {TY_Array, "t2crt::TY_CXX_Object"}, {TY_Class, "t2crt::TY_CXX_Object"}, {TY_Any, "t2crt::TY_CXX_Any"}, }; diff --git a/src/MapleFE/ast2mpl/src/mpl_processor.cpp b/src/MapleFE/ast2mpl/src/mpl_processor.cpp index 01f24456e1e0a188101befa6bcfc1d32c5f7baf9..e66c75643e45e1dd2d50e92777fdf1c50cf68cb8 100644 --- a/src/MapleFE/ast2mpl/src/mpl_processor.cpp +++ b/src/MapleFE/ast2mpl/src/mpl_processor.cpp @@ -994,6 +994,10 @@ maple::BaseNode *Ast2MplBuilder::ProcessYield(StmtExprKind skind, TreeNode *tnod return nullptr; } +maple::BaseNode *Ast2MplBuilder::ProcessArrayType(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { + return nullptr; +} + maple::BaseNode *Ast2MplBuilder::ProcessCondBranch(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { CondBranchNode *node = static_cast(tnode); maple::BaseNode *cond = ProcessNode(SK_Expr, node->GetCond(), block); diff --git a/src/MapleFE/astopt/include/ast_handler.h b/src/MapleFE/astopt/include/ast_handler.h index 90949a367f3df6af64b5b7e7aa4eea98d1da6794..d9e629b6bf005718531d54a729d7e8c4bd0a2546 100644 --- a/src/MapleFE/astopt/include/ast_handler.h +++ b/src/MapleFE/astopt/include/ast_handler.h @@ -129,6 +129,8 @@ class Module_Handler { std::unordered_map mNodeId2Decl; // array's element type: decl node id to typeid std::unordered_map mArrayDeclId2EleTypeIdMap; + // array literal's dim: decl node id to dim + std::unordered_map mArrayDeclId2DimMap; // fields' nodeid set std::unordered_set mDirectFieldSet; // alias type, identifier node id @@ -234,6 +236,31 @@ class Module_Handler { Module_Handler *GetModuleHandler(unsigned i) {return mASTHandler->GetModuleHandler(i);} Module_Handler *GetModuleHandler(TreeNode *node) {return mASTHandler->GetModuleHandler(node);} + // array's element typeid + TypeId GetArrayElemTypeId(unsigned nid) { + TypeId tid = TY_None; + if (mArrayDeclId2EleTypeIdMap.find(nid) != mArrayDeclId2EleTypeIdMap.end()) { + tid = mArrayDeclId2EleTypeIdMap[nid]; + } + return tid; + } + + void SetArrayElemTypeId(unsigned nid, TypeId tid) { + mArrayDeclId2EleTypeIdMap[nid] = tid; + } + + DimensionNode *GetArrayDim(unsigned nid) { + DimensionNode *dim = NULL; + if (mArrayDeclId2DimMap.find(nid) != mArrayDeclId2DimMap.end()) { + dim = mArrayDeclId2DimMap[nid]; + } + return dim; + } + + void SetArrayDim(unsigned nid, DimensionNode *dim) { + mArrayDeclId2DimMap[nid] = dim; + } + // API to check a node is c++ field which satisfy both: // 1. direct field // 2. its name is valid in c++ diff --git a/src/MapleFE/astopt/include/ast_ti.h b/src/MapleFE/astopt/include/ast_ti.h index 79b28276a02a355a26ab2072625d2d2016de58e2..cbe5faa95b82a0538d003da12ede3beaeee54172 100644 --- a/src/MapleFE/astopt/include/ast_ti.h +++ b/src/MapleFE/astopt/include/ast_ti.h @@ -147,6 +147,7 @@ class TypeInferVisitor : public TypeInferBaseVisitor { void UpdateTypeUseNode(TreeNode *target, TreeNode *input); void UpdateArgArrayDecls(unsigned nid, TypeId tid); void UpdateArrayElemTypeIdMap(TreeNode *node, TypeId tid); + void UpdateArrayDimMap(TreeNode *node, DimensionNode *dim); bool UpdateVarTypeWithInit(TreeNode *var, TreeNode *init); TypeId GetArrayElemTypeId(TreeNode *node); diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index b2acfe0ab663a694b2b861237647d698d5b738b2..01078cd8671829385e9a37730f9769ee432b87a0 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -107,23 +107,11 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n } } - TreeNode *parent = node->GetParent(); - - // create anonymous struct for structliteral in decl init - if (parent && parent->IsDecl()) { - DeclNode *decl = static_cast(parent); - TreeNode *var = decl->GetVar(); - if (var->IsIdentifier()) { - IdentifierNode *id = static_cast(var); - if (!id->GetType()) { - TreeNode *newnode = mInfo->GetCanonicStructNode(node); - if (newnode != node) { - UserTypeNode *utype = mInfo->CreateUserTypeNode(newnode->GetStrIdx()); - static_cast(var)->SetType(utype); - } - } - } + TreeNode *newnode = mInfo->GetCanonicStructNode(node); + if (newnode != node) { + node->SetTypeIdx(newnode->GetTypeIdx()); } + return node; } diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index 52e02bb829f6765ff366f67e49cd37de31b324ed..484be4784d5cc38cfab4648768953c1f3341b841 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -306,7 +306,7 @@ bool AST_INFO::IsFieldCompatibleTo(TreeNode *field, TreeNode *target) { else if (field->IsFieldLiteral()) { FieldLiteralNode *fln = static_cast(field); TreeNode *name = fln->GetFieldName(); - if (name->IsIdentifier()) { + if (name && name->IsIdentifier()) { stridx_field = name->GetStrIdx(); } if (stridx_field != stridx_target) { @@ -359,6 +359,7 @@ TreeNode *AST_INFO::GetCanonicStructNode(TreeNode *node) { } if (match) { + node->SetTypeIdx(s->GetTypeIdx()); return s; } } @@ -377,6 +378,7 @@ TreeNode *AST_INFO::GetCanonicStructNode(TreeNode *node) { if (!anony) { return node; } else { + node->SetTypeIdx(anony->GetTypeIdx()); node = anony; } } @@ -477,6 +479,7 @@ TreeNode *AST_INFO::GetAnonymousStruct(TreeNode *node) { IdentifierNode *id = snode->GetStructId(); if (!id) { id = CreateIdentifierNode(0); + id->SetScope(snode->GetScope()); snode->SetStructId(id); } @@ -485,6 +488,7 @@ TreeNode *AST_INFO::GetAnonymousStruct(TreeNode *node) { } ModuleNode *module = mHandler->GetASTModule(); + module->GetScope()->AddType(newnode); module->AddTreeFront(newnode); return newnode; } @@ -719,6 +723,13 @@ StructLiteralNode *ClassStructVisitor::VisitStructLiteralNode(StructLiteralNode } // sort fields mInfo->SortFields(node); + } else if (mInfo->GetPass() == 2) { + // create a anonymous struct for it + mInfo->SetNameAnonyStruct(true); + TreeNode *csn = mInfo->GetCanonicStructNode(node); + if (csn && csn != node) { + VisitTreeNode(csn); + } } return node; } diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index 1ec23032d1fc34e5e3c794150b80472cec80de27..a1473f8a744ae4131a396f120c95dde9b3433ea3 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -380,11 +380,6 @@ StructNode *BuildScopeVisitor::VisitStructNode(StructNode *node) { StructLiteralNode *BuildScopeVisitor::VisitStructLiteralNode(StructLiteralNode *node) { ASTScope *parent = mScopeStack.top(); - // struct is a decl - if (parent) { - AddDecl(parent, node); - AddType(parent, node); - } ASTScope *scope = NewScope(parent, node); diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index dacabfb01ff81b7030ec78d49ad4d3c4cd697d37..28c7af296b38bf3ae13ad9a54374fd14593a6fef 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -424,7 +424,7 @@ bool static IsScalar(TypeId tid) { // caller arguments to be consistent with the array type parameter void TypeInferVisitor::UpdateArgArrayDecls(unsigned nid, TypeId tid) { for (auto id: mParam2ArgArrayDeclMap[nid]) { - mHandler->mArrayDeclId2EleTypeIdMap[nid] = tid; + mHandler->SetArrayElemTypeId(nid, tid); if (id && id->IsDecl()) { id = static_cast(id)->GetVar(); } @@ -549,13 +549,8 @@ void TypeInferVisitor::UpdateFuncRetTypeId(FunctionNode *node, TypeId tid, unsig } TypeId TypeInferVisitor::GetArrayElemTypeId(TreeNode *node) { - TypeId tid = TY_None; - unsigned nodeid = node->GetNodeId(); - auto it = mHandler->mArrayDeclId2EleTypeIdMap.find(nodeid); - if (it != mHandler->mArrayDeclId2EleTypeIdMap.end()) { - tid = mHandler->mArrayDeclId2EleTypeIdMap[nodeid]; - } - return tid; + unsigned nid = node->GetNodeId(); + return mHandler->GetArrayElemTypeId(nid); } void TypeInferVisitor::UpdateArrayElemTypeIdMap(TreeNode *node, TypeId tid) { @@ -563,12 +558,10 @@ void TypeInferVisitor::UpdateArrayElemTypeIdMap(TreeNode *node, TypeId tid) { return; } unsigned nodeid = node->GetNodeId(); - auto it = mHandler->mArrayDeclId2EleTypeIdMap.find(nodeid); - if (it != mHandler->mArrayDeclId2EleTypeIdMap.end()) { - tid = MergeTypeId(tid, mHandler->mArrayDeclId2EleTypeIdMap[nodeid]); - } - if (mHandler->mArrayDeclId2EleTypeIdMap[nodeid] != tid) { - mHandler->mArrayDeclId2EleTypeIdMap[node->GetNodeId()] = tid; + TypeId currtid = mHandler->GetArrayElemTypeId(nodeid); + tid = MergeTypeId(tid, currtid); + if (currtid != tid) { + mHandler->SetArrayElemTypeId(node->GetNodeId(), tid); SetUpdated(); // update array's PrimType node with a new node @@ -580,6 +573,7 @@ void TypeInferVisitor::UpdateArrayElemTypeIdMap(TreeNode *node, TypeId tid) { IdentifierNode *in = static_cast(node); node = in->GetType(); } + if (node->IsPrimArrayType()) { PrimArrayTypeNode *pat = static_cast(node); PrimTypeNode *pt = pat->GetPrim(); @@ -589,6 +583,10 @@ void TypeInferVisitor::UpdateArrayElemTypeIdMap(TreeNode *node, TypeId tid) { } } +void TypeInferVisitor::UpdateArrayDimMap(TreeNode *node, DimensionNode *dim) { + mHandler->SetArrayDim(node->GetNodeId(), dim); +} + // return true if identifier is constructor bool TypeInferVisitor::UpdateVarTypeWithInit(TreeNode *var, TreeNode *init) { bool result = var->IsFunction(); @@ -629,23 +627,24 @@ bool TypeInferVisitor::UpdateVarTypeWithInit(TreeNode *var, TreeNode *init) { PrimArrayTypeNode *pat = mHandler->NewTreeNode(); pat->SetPrim(pt); - DimensionNode *dims = mHandler->NewTreeNode(); + DimensionNode *dims = mHandler->GetArrayDim(init->GetNodeId()); pat->SetDims(dims); - // add each dimension - TreeNode *n = init; - while (n->IsArrayLiteral()) { - ArrayLiteralNode *al = static_cast(n); - if (al->GetLiteralsNum()) { - //dims->AddDimension(al->GetLiteralsNum()); - dims->AddDimension(0); // Do not specify its length for an array type - n = al->GetLiteral(0); - } else { - dims->AddDimension(0); - break; - } + pat->SetParent(idnode); + idnode->SetType(pat); + SetUpdated(); + } else { + TreeNode *t = gTypeTable.GetTypeFromTypeIdx(init->GetTypeIdx()); + if (!t) { + t = gTypeTable.GetTypeFromTypeId(tid); } + ArrayTypeNode *pat = mHandler->NewTreeNode(); + pat->SetElemType(t); + + DimensionNode *dims = mHandler->GetArrayDim(init->GetNodeId()); + pat->SetDims(dims); + pat->SetParent(idnode); idnode->SetType(pat); SetUpdated(); @@ -772,7 +771,7 @@ ArrayElementNode *TypeInferVisitor::VisitArrayElementNode(ArrayElementNode *node UpdateTypeId(array, TY_Array); UpdateTypeId(decl, array); UpdateArrayElemTypeIdMap(decl, node->GetTypeId()); - UpdateTypeId(node, mHandler->mArrayDeclId2EleTypeIdMap[decl->GetNodeId()]); + UpdateTypeId(node, mHandler->GetArrayElemTypeId(decl->GetNodeId())); } } else { NOTYETIMPL("array not declared"); @@ -809,20 +808,59 @@ ArrayLiteralNode *TypeInferVisitor::VisitArrayLiteralNode(ArrayLiteralNode *node UpdateTypeId(node, TY_Array); (void) AstVisitor::VisitArrayLiteralNode(node); ArrayLiteralNode *al = node; - TreeNode *n = node; - while (n->IsArrayLiteral()) { - al = static_cast(n); - if (al->GetLiteralsNum()) { - n = al->GetLiteral(0); - } else { - break; + if (node->IsArrayLiteral()) { + al = static_cast(node); + unsigned size = al->GetLiteralsNum(); + TypeId tid = TY_None; + bool allElemArray = true; + for (unsigned i = 0; i < size; i++) { + TreeNode *n = al->GetLiteral(i); + TypeId id = n->GetTypeId(); + tid = MergeTypeId(tid, id); + if (tid != TY_Array) { + allElemArray = false; + } + } + + DimensionNode *dim = mHandler->NewTreeNode(); + dim->AddDimension(size); + + // n-D array: elements are all arrays + if (allElemArray) { + unsigned elemdim = DEFAULTVALUE; + // recalculate element typeid + tid = TY_None; + for (unsigned i = 0; i < size; i++) { + TreeNode *n = al->GetLiteral(i); + if (n->IsArrayLiteral()) { + DimensionNode * dn = mHandler->GetArrayDim(n->GetNodeId()); + unsigned currdim = dn ? dn->GetDimensionsNum() : 0; + // find min dim of all elements + if (elemdim == DEFAULTVALUE) { + elemdim = currdim; + tid = mHandler->GetArrayElemTypeId(n->GetNodeId()); + } else if (currdim < elemdim) { + elemdim = currdim; + tid = TY_Merge; + } else if (currdim > elemdim) { + tid = TY_Merge; + } else { + tid = MergeTypeId(tid, mHandler->GetArrayElemTypeId(n->GetNodeId())); + } + } + } + if (elemdim != DEFAULTVALUE) { + for (unsigned i = 0; i < elemdim; i++) { + // with unspecified length, can add details later + dim->AddDimension(0); + } + } } - } - if (al->GetLiteralsNum()) { - TypeId tid = al->GetLiteral(0)->GetTypeId(); UpdateArrayElemTypeIdMap(node, tid); + UpdateArrayDimMap(node, dim); } + return node; } diff --git a/src/MapleFE/docs/readme b/src/MapleFE/docs/readme index d6c4be8b8801d025a05f92a17d0f502d02fa0e47..732f9f3725c3049fc9bbad1ecaa4016af160b2d0 100644 --- a/src/MapleFE/docs/readme +++ b/src/MapleFE/docs/readme @@ -5,6 +5,10 @@ git clone https://gitee.com/openarkcompiler/OpenArkCompiler -b dev_MapleFE 2. ENVIRONMENT ============== +System software versions used: + Ubuntu: 20.04 + Typescript: 4.5.5 + Nodejs: 14.7.0 export MFE=~/OpenArkCompiler/src/MapleFE export tsbin=$MFE/output/typescript/bin diff --git a/src/MapleFE/docs/utils/proto.js b/src/MapleFE/docs/utils/proto.js index 341305e1cf729fb918ff977ae4f32cf42560308f..6115e6d550e9b98a8657ae0ac7a7482e2d9ebcec 100644 --- a/src/MapleFE/docs/utils/proto.js +++ b/src/MapleFE/docs/utils/proto.js @@ -12,6 +12,7 @@ class MyCar extends Car { let car = new Car("A car"); let myCar = new MyCar("My car"); let arr = [1, 2, 3] +let regexpr = /ab+c/i function* generator() { yield 1; } const gpt = generator.prototype.__proto__; @@ -36,7 +37,7 @@ let graphData = { Class : ["Array", "arr", "myCar", "car"], Generator: ["generator", [generator(), "generator_instance"], [gpt, "GeneratorPrototype"], [gpt.__proto__, "IteratorPrototype"], [generator.__proto__, "Generator"]], - Builtin : ["Symbol", "Math", "JSON", "Promise"], + Builtin : ["Symbol", "Math", "JSON", "Promise", "RegExp", "regexpr"], Closure : ["makeClosure", "closure"], Iterator : ["myMap", "myMapIterator", "MapIteratorPrototype", [gpt.__proto__, "IteratorPrototype"]], Async : ["asyncFunction", "asyncGenerator", [asyncGenerator(), "asyncGenerator_instance"], [agpt, "AsyncGeneratorPrototype"], diff --git a/src/MapleFE/shared/include/ast_nk.def b/src/MapleFE/shared/include/ast_nk.def index 0ea8f092c8898960cec53c7e86ada503b68e3870..57c1e2b35160cbde4d5c732c3a0a3659d444c664 100644 --- a/src/MapleFE/shared/include/ast_nk.def +++ b/src/MapleFE/shared/include/ast_nk.def @@ -36,6 +36,7 @@ NODEKIND(NameTypePair) // Type related NODEKIND(PrimType) NODEKIND(PrimArrayType) +NODEKIND(ArrayType) NODEKIND(UserType) NODEKIND(TypeParameter) NODEKIND(AsType) diff --git a/src/MapleFE/shared/include/ast_type.h b/src/MapleFE/shared/include/ast_type.h index 641839f80166518c81625386f9abde6cb51be37f..89254ee2402a7d2e9bb943b14da7362dffea9f31 100644 --- a/src/MapleFE/shared/include/ast_type.h +++ b/src/MapleFE/shared/include/ast_type.h @@ -136,6 +136,30 @@ public: void Dump(unsigned); }; +class ArrayTypeNode : public TreeNode { +private: + TreeNode *mElemType; + DimensionNode *mDims; + SmallVector mAttrs; + +public: + ArrayTypeNode() : TreeNode(NK_ArrayType), mElemType(NULL), mDims(NULL) {} + ~ArrayTypeNode(){} + + void SetElemType(TreeNode *n) {mElemType = n; SETPARENT(n);} + void SetDims(DimensionNode *d) {mDims = d; SETPARENT(d);} + TreeNode* GetElemType() {return mElemType;} + DimensionNode* GetDims() {return mDims;} + + // Attributes related + unsigned GetAttrsNum() const {return mAttrs.GetNum();} + void AddAttr(AttrId a) {mAttrs.PushBack(a);} + AttrId GetAttrAtIndex(unsigned i) {return mAttrs.ValueAtIndex(i);} + void SetAttrAtIndex(unsigned i, AttrId n) {*(mAttrs.RefAtIndex(i)) = n;} + + 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 56151183177fa51cc691113ff40f3f2d076b9555..fa63b6548222b875d2be4f9b48741cbe6d5e917d 100644 --- a/src/MapleFE/shared/include/typetable.h +++ b/src/MapleFE/shared/include/typetable.h @@ -50,6 +50,7 @@ class TypeTable { private: std::vector mTypeTable; std::unordered_map mNodeId2TypeIdxMap; + std::unordered_map mTypeId2TypeMap; unsigned mPrimSize; unsigned mPreBuildSize; @@ -60,12 +61,13 @@ public: unsigned size() { return mTypeTable.size(); } unsigned GetPreBuildSize() { return mPreBuildSize; } unsigned GetPrimSize() { return mPrimSize; } - TreeNode *CreatePrimType(std::string name, TypeId tyid); - TreeNode *CreateBuiltinType(std::string name, TypeId tyid); + TreeNode *CreatePrimType(std::string name, TypeId tid); + TreeNode *CreateBuiltinType(std::string name, TypeId tid); void AddPrimAndBuiltinTypes(); bool AddType(TreeNode *node); - TypeEntry *GetTypeEntryFromTypeIdx(unsigned idx); - TreeNode *GetTypeFromTypeIdx(unsigned idx); + TypeEntry *GetTypeEntryFromTypeIdx(unsigned tidx); + TreeNode *GetTypeFromTypeIdx(unsigned tidx); + TreeNode *GetTypeFromTypeId(TypeId tid) { return mTypeId2TypeMap[tid]; } void Dump(); }; diff --git a/src/MapleFE/shared/src/ast_scope.cpp b/src/MapleFE/shared/src/ast_scope.cpp index 0c2d5a8c8d5c78fbc2ba691f34a242b542920f37..fc907786e9527c1285954eaab705319b3d4527c1 100644 --- a/src/MapleFE/shared/src/ast_scope.cpp +++ b/src/MapleFE/shared/src/ast_scope.cpp @@ -208,7 +208,7 @@ void ASTScope::Dump(unsigned indent) { TreeNode *node = GetType(i); node->DumpIndentation(indent); std::string name = node->GetStrIdx() ? node->GetName() : "-"; - std::cout << " type: " << name << " " << node->GetNodeId() << std::endl; + std::cout << " type: " << name << " " << node->GetTypeIdx() << std::endl; } for (unsigned i = 0; i < GetChildrenNum(); i++) { diff --git a/src/MapleFE/shared/src/ast_type.cpp b/src/MapleFE/shared/src/ast_type.cpp index a7374f0ec52e5dd23c65fca7f3ff3db27448d39e..3a4d3774689e67efed66ebdde1262c2c29d14240 100644 --- a/src/MapleFE/shared/src/ast_type.cpp +++ b/src/MapleFE/shared/src/ast_type.cpp @@ -138,6 +138,14 @@ void UserTypeNode::Dump(unsigned ind) { } } +////////////////////////////////////////////////////////////////////////// +// ArrayTypeNode // +////////////////////////////////////////////////////////////////////////// + +void ArrayTypeNode::Dump(unsigned ind) { + DUMP0_NORETURN("array-TBD"); +} + ////////////////////////////////////////////////////////////////////////// // PrimArrayTypeNode // ////////////////////////////////////////////////////////////////////////// diff --git a/src/MapleFE/shared/src/typetable.cpp b/src/MapleFE/shared/src/typetable.cpp index 7595d6f9ddc0af7d0183e5c25a3c1686a89602d3..90b0e4ac608b030c1073a273593c6fb511977483 100644 --- a/src/MapleFE/shared/src/typetable.cpp +++ b/src/MapleFE/shared/src/typetable.cpp @@ -55,25 +55,29 @@ TypeEntry::TypeEntry(TreeNode *node) { TreeNode *TypeTable::CreatePrimType(std::string name, TypeId tid) { unsigned stridx = gStringPool.GetStrIdx(name); - PrimTypeNode *node = (PrimTypeNode*)gTreePool.NewTreeNode(sizeof(PrimTypeNode)); - new (node) PrimTypeNode(); - node->SetStrIdx(stridx); - node->SetPrimType(tid); - node->SetTypeId(tid); - return node; + PrimTypeNode *ptype = (PrimTypeNode*)gTreePool.NewTreeNode(sizeof(PrimTypeNode)); + new (ptype) PrimTypeNode(); + ptype->SetStrIdx(stridx); + ptype->SetPrimType(tid); + ptype->SetTypeId(tid); + + mTypeId2TypeMap[tid] = ptype; + return ptype; } TreeNode *TypeTable::CreateBuiltinType(std::string name, TypeId tid) { unsigned stridx = gStringPool.GetStrIdx(name); - IdentifierNode *node = (IdentifierNode*)gTreePool.NewTreeNode(sizeof(IdentifierNode)); - new (node) IdentifierNode(stridx); - node->SetTypeId(tid); + IdentifierNode *id = (IdentifierNode*)gTreePool.NewTreeNode(sizeof(IdentifierNode)); + new (id) IdentifierNode(stridx); + id->SetTypeId(tid); UserTypeNode *utype = (UserTypeNode*)gTreePool.NewTreeNode(sizeof(UserTypeNode)); - new (utype) UserTypeNode(node); + new (utype) UserTypeNode(id); utype->SetStrIdx(stridx); utype->SetTypeId(TY_Class); - node->SetParent(utype); + id->SetParent(utype); + + mTypeId2TypeMap[tid] = utype; return utype; } @@ -82,9 +86,9 @@ bool TypeTable::AddType(TreeNode *node) { if (mNodeId2TypeIdxMap.find(id) != mNodeId2TypeIdxMap.end()) { return false; } - unsigned tyidx = mTypeTable.size(); - mNodeId2TypeIdxMap[id] = tyidx; - node->SetTypeIdx(tyidx); + unsigned tid = mTypeTable.size(); + mNodeId2TypeIdxMap[id] = tid; + node->SetTypeIdx(tid); TypeEntry *entry = new TypeEntry(node); mTypeTable.push_back(entry); return true; @@ -147,8 +151,10 @@ void TypeTable::Dump() { } std::cout << " " << idx << " : " << node->GetName() << " : " << AstDump::GetEnumNodeKind(node->GetKind()) << " " << - AstDump::GetEnumTypeId(tid) << " " << tid << " " << - node->GetNodeId() << std::endl; + AstDump::GetEnumTypeId(tid) << " " << + "(typeid " << tid << ") " << + "(typeidx " << node->GetTypeIdx() << ") " << + "(nodeid " << node->GetNodeId() << ")" << std::endl; } std::cout << "===================== End TypeTable =====================" << std::endl; } diff --git a/src/MapleFE/shared/src/vfy.cpp b/src/MapleFE/shared/src/vfy.cpp index 1968ae9674257ce97a658717d36bf81c1c65011c..4f771a5a7d6267780412eb8314d8e5553b18dce3 100644 --- a/src/MapleFE/shared/src/vfy.cpp +++ b/src/MapleFE/shared/src/vfy.cpp @@ -563,4 +563,9 @@ void Verifier::VerifyStructLiteral(StructLiteralNode *tree){ void Verifier::VerifyFieldLiteral(FieldLiteralNode *tree){ return; } + +void Verifier::VerifyArrayType(ArrayTypeNode *tree){ + return; +} + } diff --git a/src/MapleFE/test/typescript/unit_tests/class-extends3.ts.result b/src/MapleFE/test/typescript/unit_tests/class-extends3.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..5368fc30da365058f5d1934d73ee3dfecd5b2e61 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/class-extends3.ts.result @@ -0,0 +1,38 @@ +Matched 36 tokens. +Matched 88 tokens. +Matched 101 tokens. +Matched 118 tokens. +============= Module =========== +== Sub Tree == +class Car + Fields: + _make + Instance Initializer: + Constructors: + constructor (make) throws: + this._make Assign make + Methods: + func getMake() throws: + return this._make + LocalClasses: + LocalInterfaces: + +== Sub Tree == +class Model + Fields: + _model + Instance Initializer: + Constructors: + constructor (make,model) throws: + super(make) + this._model Assign super.getMake() Add model + Methods: + func getModel() throws: + return this._model + LocalClasses: + LocalInterfaces: + +== Sub Tree == +js_let Decl: passat=new Model("VW","Passat") +== Sub Tree == +console.log(passat.getMake(),passat.getModel()) diff --git a/src/MapleFE/typescript/src/lang_spec.cpp b/src/MapleFE/typescript/src/lang_spec.cpp index 4c216945a18693c2c6cf4477fdc50a0a6a34d711..b585ae76c752976d78ae3ef568af7d242c5b64c6 100644 --- a/src/MapleFE/typescript/src/lang_spec.cpp +++ b/src/MapleFE/typescript/src/lang_spec.cpp @@ -582,6 +582,31 @@ bool TypescriptParser::TraverseASI(RuleTable *rule_table, // {foo()} <-- , is missed before } if (curr_token->IsSeparator() && (curr_token->GetSepId() == SEP_Rbrace)) return true; + + // case 3. This is a special case we want to catch: + // foo(x) a=b; <-- , is missing before a=b + // There could be many more similar cases, but we just match this special one in our + // unit test. We don't encourage people write weird code. + if ( (curr_token->IsIdentifier() || curr_token->IsKeyword()) && + (prev_token->IsSeparator() && (prev_token->GetSepId() == SEP_Rparen)) ){ + Token *prev_2_token = GetActiveToken(mCurToken - 2); + Token *prev_3_token = GetActiveToken(mCurToken - 3); + Token *prev_4_token = GetActiveToken(mCurToken - 4); + if ( prev_4_token->mLineBegin && + (prev_4_token->IsIdentifier() || prev_4_token->IsKeyword()) && + (prev_2_token->IsIdentifier() || prev_2_token->IsKeyword()) && + (prev_3_token->IsSeparator() && (prev_3_token->GetSepId() == SEP_Lparen)) ){ + // NOTE: Need make sure foo(x) is not if(x) or while(x). + found = true; + if (prev_4_token->IsKeyword() && + (!strncmp(prev_4_token->GetName(), "if", 2) || + !strncmp(prev_4_token->GetName(), "while", 5)) ) + found = false; + + if (found) + return true; + } + } } if (child) {