diff --git a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h index 6cd956c2e1d6ff5353c4bfc2c8cdd855d0ff1b6d..5a5cd376fd09a3569d811ee550735576223aedf4 100644 --- a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h +++ b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h @@ -24,6 +24,9 @@ #include #include +// Copied from astopt/include/ast_adj.h +#define RENAMINGSUFFIX "__RENAMED" + using namespace std::string_literals; namespace t2crt { diff --git a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp index e91cba6627982038c4cd48f09ca2cb2e8f36564e..7c9ae38db3c05dbddd3cf27326bf8c690b7c63a7 100644 --- a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp +++ b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp @@ -46,10 +46,17 @@ std::ostream& operator<< (std::ostream& out, const t2crt::Object *obj) { auto b = k == t2crt::TY_Object || k == t2crt::TY_CXX_Object; if (b == flag) { buf.str(std::string()); - if (isdigit(it->first.front())) - buf << '\'' << it->first << "': "; - else - buf << it->first << ": "; + const std::string &prop = it->first; + if (isdigit(prop.front())) + buf << '\'' << prop << "': "; + else { + auto len = prop.length(); + constexpr auto suffixlen = sizeof(RENAMINGSUFFIX) - 1; + if (len > suffixlen && prop.substr(len - suffixlen) == RENAMINGSUFFIX) + buf << prop.substr(0, len - suffixlen) << ": "; + else + buf << prop << ": "; + } if (k == t2crt::TY_String || k == t2crt::TY_CXX_String) buf << '\'' << it->second << '\''; else diff --git a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp index a1c09f9ea05635488bfa2ebb9951d7a63b76da2d..bc293c367068449b0f70422bad2aef85da465b7f 100644 --- a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp @@ -18,6 +18,7 @@ #include #include #include "helper.h" +#include "ast_adj.h" namespace maplefe { @@ -155,7 +156,7 @@ class ImportExportModules : public AstVisitor { auto b = x->GetBefore(); std::string target = mCppDecl->GetIdentifierName(b); bool emit = true; - if (target == "default") { + if (target == "default" RENAMINGSUFFIX) { target = module + "::__export::__default"; mExports += "namespace __export { inline const decltype("s + target + ") &"s + "__"s + "default" + " = "s + target + "; }\n"s; @@ -166,7 +167,7 @@ class ImportExportModules : public AstVisitor { emit = false; } if (emit) - mExports += "namespace __export { using "s + module + "::"s + "default; }\n"s; + mExports += "namespace __export { using "s + module + "::"s + "default" RENAMINGSUFFIX "; }\n"s; } else { if (auto n = x->GetBefore()) { std::string v = mEmitter->EmitTreeNode(n); @@ -214,10 +215,10 @@ class ImportExportModules : public AstVisitor { bool emit = true; if (auto a = x->GetAfter()) { std::string after = mCppDecl->GetIdentifierName(a); - if (target == "default") { + if (target == "default" RENAMINGSUFFIX) { target = module + "::__export::__default"; mExports += "namespace __export { inline const decltype("s + target + ") &"s - + (after == "default" ? "__"s + after : after) + " = "s + target + "; }\n"s; + + (after == "default" RENAMINGSUFFIX ? "__"s + after : after) + " = "s + target + "; }\n"s; emit = false; } else if (target != after) { diff --git a/src/MapleFE/astopt/include/ast_adj.h b/src/MapleFE/astopt/include/ast_adj.h index 0d9783dbcde8b16cee9f614db6314a362923ba0d..cc85af13414c6e23b87d37071d19b4dd731566f0 100644 --- a/src/MapleFE/astopt/include/ast_adj.h +++ b/src/MapleFE/astopt/include/ast_adj.h @@ -24,6 +24,7 @@ #include "ast.h" #include "ast_type.h" #include "gen_astvisitor.h" +#include "ast_info.h" namespace maplefe { @@ -39,21 +40,29 @@ class AST_ADJ { void AdjustAST(); }; +// If you change RENAMINGSUFFIX, you have to update ast2cpp/runtime/include/ts2cpp.h as well +#define RENAMINGSUFFIX "__RENAMED" + class AdjustASTVisitor : public AstVisitor { private: Module_Handler *mHandler; AST_INFO *mInfo; + AST_Util *mUtil; unsigned mFlags; bool mUpdated; public: explicit AdjustASTVisitor(Module_Handler *h, unsigned f, bool base = false) : mHandler(h), mFlags(f), mUpdated(false), AstVisitor((f & FLG_trace_1) && base) { - mInfo = mHandler->GetINFO(); + mInfo = h->GetINFO(); mInfo->SetNameAnonyStruct(true); + mUtil = h->GetUtil(); } ~AdjustASTVisitor() = default; + std::unordered_map mRenameMap; + void CheckAndRenameCppKeywords(TreeNode *node); + DeclNode *VisitDeclNode(DeclNode *node); ImportNode *VisitImportNode(ImportNode *node); ExportNode *VisitExportNode(ExportNode *node); diff --git a/src/MapleFE/astopt/include/ast_handler.h b/src/MapleFE/astopt/include/ast_handler.h index d8cf14ec827a0b5841275a82c540bdcdc9913748..a6d6dedec6d5cae76ff708c1e5c02101e9e4c277 100644 --- a/src/MapleFE/astopt/include/ast_handler.h +++ b/src/MapleFE/astopt/include/ast_handler.h @@ -115,6 +115,7 @@ class Module_Handler { unsigned mHidx; // handler index in AST_Handler unsigned mFlags; + bool mIsTS; std::unordered_map mNodeId2BbMap; @@ -194,6 +195,7 @@ class Module_Handler { void SetSCP(AST_SCP *p) {mSCP = p;} void SetTI(TypeInfer *p) {mTI = p;} void SetUtil(AST_Util *p) {mUtil = p;} + void SetIsTS(bool b) {mIsTS = b;} // deep true : find Decl in imported module as well // false : find Decl in current module only @@ -207,6 +209,7 @@ class Module_Handler { bool IsFromLambda(TreeNode *node); bool IsDef(TreeNode *node); + bool IsTS() {return mIsTS;} void AddNodeId2DeclMap(unsigned nid, TreeNode *node) { mNodeId2Decl[nid] = node; diff --git a/src/MapleFE/astopt/include/astopt.h b/src/MapleFE/astopt/include/astopt.h index 4485a040232333306e311d0d02eb3b66979e5763..5e355b789fd80159bd035a31384a7926d16b2d22 100644 --- a/src/MapleFE/astopt/include/astopt.h +++ b/src/MapleFE/astopt/include/astopt.h @@ -74,8 +74,6 @@ class BuildNodeIdToNodeVisitor : public AstVisitor { Module_Handler *mHandler; unsigned mFlags; - std::unordered_map mRenameMap; - public: explicit BuildNodeIdToNodeVisitor(AstOpt *opt, unsigned f, bool base = false) : mAstOpt(opt), mFlags(f), AstVisitor((f & FLG_trace_1) && base) {} diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index e83ccb9ea6d855229076967c60536c6b679c41f0..25c1ee682d44e05ce48bd1b4c1acbf8dd40857b7 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -20,6 +20,7 @@ #include "typetable.h" #include "ast_info.h" #include "ast_adj.h" +#include "ast_util.h" namespace maplefe { @@ -39,39 +40,18 @@ void AST_ADJ::AdjustAST() { // set parent for some identifier's type IdentifierNode *AdjustASTVisitor::VisitIdentifierNode(IdentifierNode *node) { (void) AstVisitor::VisitIdentifierNode(node); - // MASSERT(node->GetParent() && "identifier with NULL parent"); + CheckAndRenameCppKeywords(node); + TreeNode *type = node->GetType(); if (type && type->IsUserType()) { type->SetParent(node); } - // rename return() function to return__fixed() - unsigned stridx = node->GetStrIdx(); - if (stridx == gStringPool.GetStrIdx("return")) { - unsigned idx = gStringPool.GetStrIdx("return__fixed"); - node->SetStrIdx(idx); - TreeNode *parent = node->GetParent(); - if (parent && parent->IsFunction()) { - FunctionNode *func = static_cast(parent); - MASSERT(func->GetFuncName() == node && "return not function name"); - func->SetStrIdx(idx); - } - } - // rename throw() function to throw__fixed() - else if (stridx == gStringPool.GetStrIdx("throw")) { - unsigned idx = gStringPool.GetStrIdx("throw__fixed"); - node->SetStrIdx(idx); - TreeNode *parent = node->GetParent(); - if (parent && parent->IsFunction()) { - FunctionNode *func = static_cast(parent); - MASSERT(func->GetFuncName() == node && "throw not function name"); - func->SetStrIdx(idx); - } - } return node; } ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { (void) AstVisitor::VisitClassNode(node); + CheckAndRenameCppKeywords(node); // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperClassesNum() || node->GetSuperInterfacesNum() || node->GetSuperClassesNum() || node->GetTypeParamsNum()) { @@ -94,6 +74,7 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { InterfaceNode *AdjustASTVisitor::VisitInterfaceNode(InterfaceNode *node) { (void) AstVisitor::VisitInterfaceNode(node); + CheckAndRenameCppKeywords(node); // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperInterfacesNum()) { return node; @@ -147,6 +128,7 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n StructNode *AdjustASTVisitor::VisitStructNode(StructNode *node) { (void) AstVisitor::VisitStructNode(node); + CheckAndRenameCppKeywords(node); // skip getting canonical type for TypeAlias TreeNode *parent_orig = node->GetParent(); TreeNode *p = parent_orig; @@ -270,6 +252,8 @@ UnaOperatorNode *AdjustASTVisitor::VisitUnaOperatorNode(UnaOperatorNode *node) { FunctionNode *AdjustASTVisitor::VisitFunctionNode(FunctionNode *node) { (void) AstVisitor::VisitFunctionNode(node); + CheckAndRenameCppKeywords(node); + TreeNode *type = node->GetType(); if (type && type->IsUserType()) { type->SetParent(node); @@ -294,6 +278,7 @@ DeclNode *AdjustASTVisitor::VisitDeclNode(DeclNode *node) { TreeNode *var = node->GetVar(); if (var->IsIdentifier()) { IdentifierNode *inode = static_cast(var); + (void) AstVisitor::VisitIdentifierNode(inode); // copy stridx from Identifier to Decl unsigned stridx = inode->GetStrIdx(); @@ -518,4 +503,23 @@ LambdaNode *AdjustASTVisitor::VisitLambdaNode(LambdaNode *node) { return (LambdaNode*)func; } +void AdjustASTVisitor::CheckAndRenameCppKeywords(TreeNode *node) { + if (!mHandler->IsTS() || node->GetStrIdx() == 0) { + return; + } + + unsigned stridx = node->GetStrIdx(); + if (mRenameMap.find(stridx) != mRenameMap.end()) { + node->SetStrIdx(mRenameMap[stridx]); + return; + } + + if (mUtil->IsCppKeyWord(stridx)) { + std::string name = gStringPool.GetStringFromStrIdx(stridx); + unsigned newidx = gStringPool.GetStrIdx(name + RENAMINGSUFFIX); + node->SetStrIdx(newidx); + mRenameMap[stridx] = newidx; + } +} + } diff --git a/src/MapleFE/astopt/src/ast_handler.cpp b/src/MapleFE/astopt/src/ast_handler.cpp index 907dfbc34828e18fc91e39d12c3876ec1dc2a103..dbaf931df4c4f6e427413733b3be03a16510a5c1 100644 --- a/src/MapleFE/astopt/src/ast_handler.cpp +++ b/src/MapleFE/astopt/src/ast_handler.cpp @@ -79,6 +79,7 @@ bool AST_Handler::AddModule(ModuleNode *m) { Module_Handler *handler = new(mMemPool.Alloc(sizeof(Module_Handler))) Module_Handler(mFlags); handler->SetASTModule(m); + handler->SetIsTS(m->GetSrcLang() == SrcLangTypeScript); handler->SetASTHandler(this); mModuleHandlers.PushBack(handler); mSize++; diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index b86ee85d5a427176e168065dfc0d55acd9b335e8..33253c3e25bb6edd31ef412e7ba0de74db8a3d6b 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -395,6 +395,10 @@ void TypeInferVisitor::UpdateArgArrayDecls(unsigned nid, TypeId tid) { // use input node's type info to update target node's type info void TypeInferVisitor::UpdateTypeUseNode(TreeNode *target, TreeNode *input) { + // this functionality is reserved for typescript + if (!mHandler->IsTS()) { + return; + } TypeId tid = target->GetTypeId(); TypeId iid = input->GetTypeId(); if ((tid == iid && IsScalar(tid)) || (iid == TY_Array && tid != iid)) { diff --git a/src/MapleFE/docs/utils/proto-ctor.png b/src/MapleFE/docs/utils/proto-ctor.png new file mode 100644 index 0000000000000000000000000000000000000000..d6fa7cff21607b69e556bb167f278d20c3d31c9b Binary files /dev/null and b/src/MapleFE/docs/utils/proto-ctor.png differ diff --git a/src/MapleFE/docs/utils/proto.js b/src/MapleFE/docs/utils/proto.js new file mode 100644 index 0000000000000000000000000000000000000000..8686cd8bdffecf4e68bc1922348a63cbe2e3dde7 --- /dev/null +++ b/src/MapleFE/docs/utils/proto.js @@ -0,0 +1,49 @@ +// Command line to get graphs: nodejs proto.js | ./viewdot.sh +class Vehicle { + constructor (name) { this.name = name; } +} +class Car extends Vehicle { + constructor (name) { super(name); } +} +class MyCar extends Car { + constructor (name) { super(name); } +} + +let car = new Car("A car"); +let mycar = new MyCar("My car"); +let arr = [] + +// Dump graphs with edges for prototype, __proto__ and constructor properties of each objects +for(let g = 0; g < 2; ++g) { + let objs = [ arr, Array, Vehicle, Car, MyCar, car, mycar, Function, Object, ]; + let names = [ "arr", "Array", "Vehicle", "Car", "MyCar", "car", "mycar", "Function", "Object", ]; + console.log("digraph JS" + g + " {\nranksep=0.6;\nnodesep=0.6;\n" + (g == 0 ? "newrank=true;\n" : "")); + let num = objs.length; + let k = num; + // Add prototype objects and edges for them + for(let i = 0; i < num; ++i) { + let x = typeof objs[i].prototype; + if(x === "function" || x === "object") { + objs[k] = objs[i].prototype; + names[k] = names[i] + "_prototype"; + console.log(g == 0 ? "subgraph cluster_" + names[i] + " {\nrank=same;\ncolor=white;\n" + + names[i] + ";\n" + names[k] + "[label=\"" + names[i] + ".prototype\", shape=box];\n }" + : names[k] + "[label=\"" + names[i] + ".prototype\", shape=box];"); + console.log(names[i] + " -> " + names[k] + " [label=\"prototype\", color=blue, fontcolor=blue];"); + k++; + } + } + // Add edges for __proto__ and constructor properties of each objects + num = objs.length; + for(let i = 0; i < num; ++i) { + for(let j = 0; j < num; ++j) { + // Edges for constructor properties in the second graph only + if(g > 0 && objs[i].constructor === objs[j]) + console.log(names[i] + " -> " + names[j] + " [label=\"ctor\", color=darkgreen, fontcolor=darkgreen];"); + // Edges for __proto__ properties + if(objs[i].__proto__ === objs[j]) + console.log(names[i] + " -> " + names[j] + " [label=\"__proto__\", color=red, fontcolor=red];"); + } + } + console.log("}"); +} diff --git a/src/MapleFE/docs/utils/proto.png b/src/MapleFE/docs/utils/proto.png new file mode 100644 index 0000000000000000000000000000000000000000..b938c09f413a08ffcc3f90c994bf171a8320244b Binary files /dev/null and b/src/MapleFE/docs/utils/proto.png differ diff --git a/src/MapleFE/shared/include/ast.h b/src/MapleFE/shared/include/ast.h index 7317ecb201cc823a32dc4192f6ba4d0722a380b6..08531cf8c17d8707990d9698ce6683a8965b11e9 100644 --- a/src/MapleFE/shared/include/ast.h +++ b/src/MapleFE/shared/include/ast.h @@ -1844,6 +1844,7 @@ private: bool mIsGetAccessor; bool mIsSetAccessor; bool mIsGenerator; // JS/TS generator + bool mIsIterator; // JS/TS iterator bool mIsCallSignature; // no func name, no func body bool mIsConstructSignature; // no func name, no func body, and is a construct sig in TS @@ -1868,6 +1869,8 @@ public: void SetIsConstructor(bool b = true) {mIsConstructor = b;} bool IsGenerator() {return mIsGenerator;} void SetIsGenerator(bool b = true) {mIsGenerator = b;} + bool IsIterator() {return mIsIterator;} + void SetIsIterator(bool b = true) {mIsIterator = b;} bool IsGetAccessor() {return mIsGetAccessor;} void SetIsGetAccessor(bool b = true) {mIsGetAccessor = b;} bool IsSetAccessor() {return mIsSetAccessor;} diff --git a/src/MapleFE/shared/include/supported_actions.def b/src/MapleFE/shared/include/supported_actions.def index e1138be5f870b34fd01b93d90b401219653c7a22..1b3f48505e78db1c50ff16b47ee3e1e016e44553 100644 --- a/src/MapleFE/shared/include/supported_actions.def +++ b/src/MapleFE/shared/include/supported_actions.def @@ -130,6 +130,7 @@ ACTION(SetSetAccessor) // TS 'set' accessor ACTION(SetCallSignature) // TS call signature ACTION(SetConstructSignature) // TS construct signature ACTION(SetIsGenerator) // JS generator +ACTION(SetIsIterator) // JS iterator ACTION(AddAssert) // For callsite diff --git a/src/MapleFE/shared/src/ast.cpp b/src/MapleFE/shared/src/ast.cpp index ab24c87d4eada899dd1dec066a8c4e7c0925ac6b..d0772ef4090bbd156e7069f79e4068d715da7edf 100644 --- a/src/MapleFE/shared/src/ast.cpp +++ b/src/MapleFE/shared/src/ast.cpp @@ -1776,7 +1776,7 @@ void ClassNode::Dump(unsigned indent) { FunctionNode::FunctionNode() : TreeNode(NK_Function), mFuncName(NULL), mType(NULL), mBody(NULL), mDims(NULL), - mIsConstructor(false), mIsGenerator(false), mIsGetAccessor(false), + mIsConstructor(false), mIsGenerator(false), mIsIterator(false), mIsGetAccessor(false), mIsSetAccessor(false), mIsCallSignature(false), mIsConstructSignature(false), mAssert(NULL) {} diff --git a/src/MapleFE/shared/src/ast_builder.cpp b/src/MapleFE/shared/src/ast_builder.cpp index 6cf25e79eec15c45bc2f97ebff9ca713ea22f048..22aedf5317db34e3e62d785d9820ba003ffa0472 100644 --- a/src/MapleFE/shared/src/ast_builder.cpp +++ b/src/MapleFE/shared/src/ast_builder.cpp @@ -3285,7 +3285,8 @@ TreeNode* ASTBuilder::BuildFunction() { node_name = BuildIdentifier(node_name); } else if (!node_name->IsIdentifier() && !node_name->IsComputedName() && - !node_name->IsLiteral()) + !node_name->IsLiteral() && + !node_name->IsField()) MERROR("The function name should be an indentifier node. Not?"); } else { node_name = BuildIdentifier(p_name.mData.mToken); @@ -3379,6 +3380,15 @@ TreeNode* ASTBuilder::SetIsGenerator() { return mLastTreeNode; } +// It take no arugment. It uses mLastTreeNode which is +// a function node. +TreeNode* ASTBuilder::SetIsIterator() { + MASSERT(mLastTreeNode->IsFunction()); + FunctionNode *node = (FunctionNode*)mLastTreeNode; + node->SetIsIterator(); + return mLastTreeNode; +} + // It take no arugment. It uses mLastTreeNode which is // a yield node. TreeNode* ASTBuilder::SetIsTransfer() { diff --git a/src/MapleFE/shared/src/vfy.cpp b/src/MapleFE/shared/src/vfy.cpp index d9e22cdd5f009e367fe5e9774f12365431b12604..d70a03ebb893db124be554891f31b64963117acb 100644 --- a/src/MapleFE/shared/src/vfy.cpp +++ b/src/MapleFE/shared/src/vfy.cpp @@ -125,15 +125,18 @@ void Verifier::VerifyIdentifier(IdentifierNode *inode) { if (!decl) { mLog.MissDecl(inode); } else { - // Replace the temp IdentifierNode with the found Decl. - // Sometimes inode and decl are the same, which happens for the declaration statement. - // We will verify decl statement as the others, so its inode is the same as decl. - if (inode != decl) { - // TODO : There are many complicated cases which we will handle in the furture. - // Right now I just put a simple check of mTempParent. - if (mTempParent) - mTempParent->ReplaceChild(inode, decl); - } + // We disabled this part to keep the integerity of TREE. We don't want + // a graph. + // + // // Replace the temp IdentifierNode with the found Decl. + // // Sometimes inode and decl are the same, which happens for the declaration statement. + // // We will verify decl statement as the others, so its inode is the same as decl. + // if (inode != decl) { + // // TODO : There are many complicated cases which we will handle in the furture. + // // Right now I just put a simple check of mTempParent. + // if (mTempParent) + // mTempParent->ReplaceChild(inode, decl); + // } } } diff --git a/src/MapleFE/test/typescript/unit_tests/generator4.ts.result b/src/MapleFE/test/typescript/unit_tests/generator4.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..b09da6af24a7c4b6cb26f6b81171329ead8cb5d8 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/generator4.ts.result @@ -0,0 +1,35 @@ +Matched 68 tokens. +Matched 76 tokens. +Matched 83 tokens. +Matched 90 tokens. +Matched 106 tokens. +============= Module =========== +== Sub Tree == +class IterableClass + Fields: + elements + Instance Initializer: + Constructors: + constructor () throws: + this.elements Assign [] + Methods: + func add(element) throws: + this.elements.push(element) + func () throws: + js_let Decl: element + for ( ) + yield element + + LocalClasses: + LocalInterfaces: + +== Sub Tree == +js_let Decl: obj=new IterableClass() +== Sub Tree == +obj.add(123) +== Sub Tree == +obj.add(456) +== Sub Tree == +for ( ) + console.log(e) + diff --git a/src/MapleFE/typescript/stmt.spec b/src/MapleFE/typescript/stmt.spec index 8fac435a969f3fd89624437d32bcb37fb507752d..7eb9be59d025f4498bfe9b0b794516c276cd9da7 100644 --- a/src/MapleFE/typescript/stmt.spec +++ b/src/MapleFE/typescript/stmt.spec @@ -2244,6 +2244,11 @@ rule MemberVariableDeclaration: ONEOF( attr.action.%7 : AddInitTo(%5) attr.action.%7 : BuildDecl() +rule KeywordMemberFunctionName : ONEOF("return", + "get", + "set", + "export") + attr.action : BuildIdentifier() ## MemberFunctionDeclaration: AccessibilityModifieropt staticopt PropertyName CallSignature { FunctionBody } AccessibilityModifieropt staticopt PropertyName CallSignature ; #NOTE: I inlined CallSignature to make it easier for building function. @@ -2256,19 +2261,17 @@ rule MemberFunctionDeclaration: ONEOF( ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertyName + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ':' + IsExpression + '{' + FunctionBody + '}', ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertyName + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ':' + IsExpression + ZEROORONE(';'), - ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + "return" + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + '{' + FunctionBody + '}', - ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + "get" + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + '{' + FunctionBody + '}', - ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + "set" + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + '{' + FunctionBody + '}', - ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + "export" + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + '{' + FunctionBody + '}', - - ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + "export" + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + ZEROORONE(';')) - attr.action.%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11 : BuildFunction(%3) - attr.action.%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11 : AddModifier(%2) - attr.action.%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11 : AddModifier(%1) - attr.action.%1,%2,%5,%6,%7,%8,%9,%10,%11 : AddTypeGenerics(%4) - attr.action.%1,%2,%5,%6,%7,%8,%9,%10,%11 : AddParams(%6) - attr.action.%1,%2,%7,%8,%9,%10,%11 : AddType(%8) - attr.action.%1,%7,%8,%9,%10 : AddFunctionBody(%10) + ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + KeywordMemberFunctionName + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + '{' + FunctionBody + '}', + + ZEROORONE(Annotation) + ZEROORMORE(AccessibilityModifier) + KeywordMemberFunctionName + ZEROORONE(TypeParameters) + '(' + ZEROORONE(ParameterList) + ')' + ZEROORONE(TypeAnnotation) + ZEROORONE(';'), + '*' + '[' + MemberExpression + ']' + '(' + ')' + '{' + FunctionBody + '}') + attr.action.%1,%2,%3,%4,%5,%6,%7,%8,%9 : BuildFunction(%3) + attr.action.%1,%2,%3,%4,%5,%6,%7,%8 : AddModifier(%2) + attr.action.%1,%2,%3,%4,%5,%6,%7,%8 : AddModifier(%1) + attr.action.%1,%2,%5,%6,%7,%8 : AddTypeGenerics(%4) + attr.action.%1,%2,%5,%6,%7,%8 : AddParams(%6) + attr.action.%1,%2,%7,%8 : AddType(%8) + attr.action.%1,%7 : AddFunctionBody(%10) attr.action.%3,%4 : AddTypeGenerics(%5) attr.action.%3,%4 : AddParams(%7) attr.action.%3,%4 : AddType(%9) @@ -2276,6 +2279,8 @@ rule MemberFunctionDeclaration: ONEOF( attr.action.%3,%4 : SetIsOptional(%3) attr.action.%5,%6 : AddType(%9) attr.action.%5 : AddFunctionBody(%11) + attr.action.%9 : SetIsIterator() + attr.action.%9 : AddFunctionBody(%8) ## MemberAccessorDeclaration: AccessibilityModifieropt staticopt GetAccessor AccessibilityModifieropt staticopt SetAccessor rule MemberAccessorDeclaration: ONEOF(