From 50353c1456324e7bd3c130fceaf400aed7880a41 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 12 Sep 2019 16:12:20 +0800 Subject: spec/assign.moon and spec/bubbling.moon compiled --- MoonParser/ast.cpp | 72 +- MoonParser/ast.hpp | 471 ++++++-------- MoonParser/moon_ast.cpp | 1556 +++++++++++++++++++++++++++++++------------- MoonParser/moon_parser.cpp | 12 +- MoonParser/moon_parser.h | 8 +- MoonParser/parser.cpp | 12 +- MoonParser/parser.hpp | 15 +- 7 files changed, 1367 insertions(+), 779 deletions(-) diff --git a/MoonParser/ast.cpp b/MoonParser/ast.cpp index 6217f3e..dbf5d17 100644 --- a/MoonParser/ast.cpp +++ b/MoonParser/ast.cpp @@ -6,7 +6,7 @@ namespace parserlib { //current AST container. -static ast_container *_current = 0; +static ast_container* _current = 0; int ast_type_id = 0; @@ -30,14 +30,6 @@ ast_container::ast_container() { _current = this; } - -/** sets the container under construction to be this. - @param src source object. - */ -ast_container::ast_container(const ast_container &src) { - _current = this; -} - /** Asks all members to construct themselves from the stack. The members are asked to construct themselves in reverse order. @@ -49,7 +41,7 @@ void ast_container::construct(ast_stack &st) { it != m_members.rend(); ++it) { - ast_member *member = *it; + ast_member* member = *it; member->construct(st); } } @@ -141,42 +133,64 @@ ast_node* ast_container::getChild(int index) const { const auto& members = this->members(); for (auto member : members) { if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { - if (ptr->get()) { - if (i == index) return ptr->get(); - i++; - } + if (i == index) return ptr->get(); } else if (_ast_list* list = ast_cast<_ast_list>(member)) { for (auto obj : list->objects()) { - if (obj) { - if (i == index) return obj; - i++; - } + if (i == index) return obj; } } + i++; } return nullptr; } -int ast_container::getChildCount() const { - int count = 0; +ast_node* ast_container::getFirstChild() const { const auto& members = this->members(); - for (auto member : members) { + if (!members.empty()) { + auto member = members.front(); if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { - if (ptr->get()) count++; + return ptr->get(); } else if (_ast_list* list = ast_cast<_ast_list>(member)) { - for (auto obj : list->objects()) { - if (obj) count++; + if (!list->objects().empty()) { + return list->objects().front(); + } + } + } + return nullptr; +} + +ast_node* ast_container::getLastChild() const { + const auto& members = this->members(); + if (!members.empty()) { + auto member = members.back(); + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + return ptr->get(); + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + if (!list->objects().empty()) { + return list->objects().front(); } } } + return nullptr; +} + +size_t ast_container::getChildCount() const { + size_t count = 0; + const auto& members = this->members(); + for (auto member : members) { + if (_ast_ptr* ptr = ast_cast<_ast_ptr>(member)) { + count += 1; + } else if (_ast_list* list = ast_cast<_ast_list>(member)) { + count += list->objects().size(); + } + } return count; } //register the AST member to the current container. -void ast_member::_init() { - assert(_current); - m_container = _current; - _current->m_members.push_back(this); +void ast_member::add_to_owner() { + assert(_current); + _current->m_members.push_back(this); } @@ -188,7 +202,7 @@ void ast_member::_init() { @return pointer to ast node created, or null if there was an error. The return object must be deleted by the caller. */ -ast_node *parse(input &i, rule &g, error_list &el, void* ud) { +ast_node* _parse(input &i, rule &g, error_list &el, void* ud) { ast_stack st; if (!parse(i, g, el, &st, ud)) return 0; assert(st.size() == 1); diff --git a/MoonParser/ast.hpp b/MoonParser/ast.hpp index 4d52dfc..982eea8 100644 --- a/MoonParser/ast.hpp +++ b/MoonParser/ast.hpp @@ -13,14 +13,14 @@ namespace parserlib { class ast_node; -template class ast_ptr; +template class ast_ptr; template class ast_list; template class ast; /** type of AST node stack. */ -typedef std::vector ast_stack; +typedef std::vector ast_stack; extern int ast_type_id; @@ -41,33 +41,24 @@ enum class traversal { */ class ast_node : public input_range { public: - ///constructor. - ast_node() : m_parent(nullptr) {} - - /** copy constructor. - @param n source object. - */ - ast_node(const ast_node &n) : m_parent(nullptr) {} - - ///destructor. - virtual ~ast_node() {} - - /** assignment operator. - @param n source object. - @return reference to this. - */ - ast_node &operator = (const ast_node &n) { return *this; } - - /** get the parent node. - @return the parent node, if there is one. - */ - ast_node *parent() const { return m_parent; } - + ast_node() : _ref(0) {} + + void retain() { + ++_ref; + } + + void release() { + --_ref; + if (_ref == 0) { + delete this; + } + } + /** interface for filling the contents of the node from a node stack. @param st stack. */ - virtual void construct(ast_stack &st) {} + virtual void construct(ast_stack& st) {} /** interface for visiting AST tree use. */ @@ -81,7 +72,11 @@ public: virtual ast_node* getChild(int) const { return nullptr; } - virtual int getChildCount() const { return 0; } + virtual size_t getChildCount() const { return 0; } + + virtual ast_node* getFirstChild() const { return nullptr; } + + virtual ast_node* getLastChild() const { return nullptr; } virtual size_t getId() const { return "ast_node"_id; } @@ -89,10 +84,8 @@ public: virtual int get_type() { return ast_type(); } private: - //parent - ast_node *m_parent; - - template friend class ast_ptr; + int _ref; + template friend class ast_ptr; template friend class ast_choice; template friend class ast_list; template friend class ast; @@ -117,7 +110,7 @@ class ast_member; /** type of ast member vector. */ -typedef std::vector ast_member_vector; +typedef std::vector ast_member_vector; /** base class for AST nodes with children. @@ -128,25 +121,10 @@ public: */ ast_container(); - /** sets the container under construction to be this. - Members are not copied. - @param src source object. - */ - ast_container(const ast_container &src); - - /** the assignment operator. - The members are not copied. - @param src source object. - @return reference to this. - */ - ast_container &operator = (const ast_container &src) { - return *this; - } - /** returns the vector of AST members. @return the vector of AST members. */ - const ast_member_vector &members() const { + const ast_member_vector& members() const { return m_members; } @@ -155,7 +133,7 @@ public: from a node stack. @param st stack. */ - virtual void construct(ast_stack &st) override; + virtual void construct(ast_stack& st) override; virtual ast_node* getByPath(std::initializer_list paths) override; @@ -167,7 +145,11 @@ public: virtual ast_node* getChild(int index) const override; - virtual int getChildCount() const override; + virtual size_t getChildCount() const override; + + virtual ast_node* getFirstChild() const override; + + virtual ast_node* getLastChild() const override; virtual size_t getId() const override { return "ast_container"_id; } @@ -185,58 +167,76 @@ class ast_member { public: /** automatically registers itself to the container under construction. */ - ast_member() { _init(); } + ast_member(bool is_member) { + if (is_member) add_to_owner(); + } - /** automatically registers itself to the container under construction. - @param src source object. - */ - ast_member(const ast_member &src) { _init(); } - - /** the assignment operator. - @param src source object. - @return reference to this. - */ - ast_member &operator = (const ast_member &src) { - return *this; - } - - /** returns the container this belongs to. - @return the container this belongs to. - */ - ast_container *container() const { return m_container; } + virtual ~ast_member() {} /** interface for filling the the member from a node stack. @param st stack. */ - virtual void construct(ast_stack &st) = 0; + virtual void construct(ast_stack& st) = 0; + + virtual bool accept(ast_node* node) = 0; virtual int get_type() { return ast_type(); } private: - //the container this belongs to. - ast_container *m_container; - //register the AST member to the current container. - void _init(); + void add_to_owner(); }; template -T* ast_cast(ast_member *member) { +T* ast_cast(ast_member* member) { return member && ast_type() == member->get_type() ? static_cast(member) : nullptr; } class _ast_ptr : public ast_member { public: - _ast_ptr(ast_node *node): m_ptr(node) {} + _ast_ptr(ast_node* node, bool is_member) : ast_member(is_member), m_ptr(node) { + if (node) node->retain(); + } + + virtual ~_ast_ptr() { + if (m_ptr) { + m_ptr->release(); + m_ptr = nullptr; + } + } ast_node* get() const { return m_ptr; } + template + T* as() const { + return ast_cast(m_ptr); + } + + template + T* to() const { + assert(m_ptr->getId() == ast_type()); + return static_cast(m_ptr); + } + + void set(ast_node* node) { + if (node == m_ptr) return; + else if (!node) { + if (m_ptr) m_ptr->release(); + m_ptr = nullptr; + } + else if (accept(node)) { + if (m_ptr) m_ptr->release(); + m_ptr = node; + node->retain(); + } + } + virtual int get_type() override { return ast_type<_ast_ptr>(); } protected: - ast_node *m_ptr; + ast_node* m_ptr; }; /** pointer to an AST object. @@ -245,75 +245,37 @@ protected: @tparam T type of object to control. @tparam OPT if true, the object becomes optional. */ -template class ast_ptr : public _ast_ptr { +template class ast_ptr : public _ast_ptr { public: - /** the default constructor. - @param obj object. - */ - ast_ptr(T *obj = nullptr) : _ast_ptr(obj) { - _set_parent(); - } - - /** the copy constructor. - It duplicates the underlying object. - @param src source object. - */ - ast_ptr(const ast_ptr &src) : - _ast_ptr(src.m_ptr ? new T(*src.m_ptr) : nullptr) - { - _set_parent(); - } + ast_ptr(T* node = nullptr) : _ast_ptr(node, MEM) {} - /** deletes the underlying object. - */ - ~ast_ptr() { - delete m_ptr; - } + ast_ptr(const ast_ptr& other) : _ast_ptr(other.get(), MEM) {} - /** copies the given object. - The old object is deleted. - @param obj new object. - @return reference to this. - */ - ast_ptr &operator = (const T *obj) { - delete m_ptr; - m_ptr = obj ? new T(*obj) : nullptr; - _set_parent(); - return *this; - } - - /** copies the underlying object. - The old object is deleted. - @param src source object. - @return reference to this. - */ - ast_ptr &operator = (const ast_ptr &src) { - delete m_ptr; - m_ptr = src.m_ptr ? new T(*src.m_ptr) : nullptr; - _set_parent(); - return *this; - } + ast_ptr& operator=(const ast_ptr& other) { + set(other.get()); + return *this; + } /** gets the underlying ptr value. @return the underlying ptr value. */ - T *get() const { + T* get() const { return static_cast(m_ptr); } /** auto conversion to the underlying object ptr. @return the underlying ptr value. */ - operator T *() const { + operator T*() const { return static_cast(m_ptr); } /** member access. @return the underlying ptr value. */ - T *operator ->() const { + T* operator->() const { assert(m_ptr); - return m_ptr; + return static_cast(m_ptr); } /** Pops a node from the stack. @@ -321,118 +283,120 @@ public: @exception std::logic_error thrown if the node is not of the appropriate type; thrown only if OPT == false or if the stack is empty. */ - virtual void construct(ast_stack &st) { + virtual void construct(ast_stack& st) override { //check the stack node if (st.empty()) { if (OPT) return; else throw std::logic_error("invalid AST stack"); } - - //get the node - ast_node *node = st.back(); - - //get the object - T *obj = std::is_same() ? static_cast(node) : ast_cast(node); - - //if the object is optional, simply return - if (OPT) { - if (!obj) return; - } - - //else if the object is mandatory, throw an exception - else { - if (!obj) throw std::logic_error("invalid AST node"); - } - - //pop the node from the stack + + ast_node* node = st.back(); + + if (!ast_ptr::accept(node)) { + //if the object is optional, simply return + if (OPT) { + return; + } else { //else if the object is mandatory, throw an exception + throw std::logic_error("invalid AST node"); + } + } + st.pop_back(); - - //set the new object - delete m_ptr; - m_ptr = obj; - _set_parent(); + + m_ptr = node; + node->retain(); } private: - //set parent of object - void _set_parent() { - if (m_ptr) m_ptr->m_parent = container(); - } + virtual bool accept(ast_node* node) override { + return node && (std::is_same() || ast_type() == node->get_type()); + } }; +template +inline ast_ptr new_ptr() { + return ast_ptr(new T); +} + template class ast_choice : public _ast_ptr { public: - ast_choice(ast_node *obj = nullptr) : _ast_ptr(obj) { - _set_parent(); - } - - ast_choice(const ast_choice &src) : - _ast_ptr(src.m_ptr ? new ast_node(*src.m_ptr) : nullptr) - { - _set_parent(); - } + ast_choice() : _ast_ptr(nullptr, true) {} - ~ast_choice() { - delete m_ptr; - } - - ast_choice &operator = (const ast_node *obj) { - delete m_ptr; - m_ptr = obj ? new ast_node(*obj) : nullptr; - _set_parent(); - return *this; - } + ast_choice(const ast_choice& other) : _ast_ptr(other.get(), true) {} - ast_choice &operator = (const ast_choice &src) { - delete m_ptr; - m_ptr = src.m_ptr ? new ast_node(*src.m_ptr) : nullptr; - _set_parent(); - return *this; - } + ast_choice& operator=(const ast_choice& other) { + set(other.get()); + return *this; + } - operator ast_node *() const { + operator ast_node*() const { return m_ptr; } - ast_node *operator ->() const { + ast_node* operator->() const { assert(m_ptr); return m_ptr; } - virtual void construct(ast_stack &st) { + virtual void construct(ast_stack& st) override { if (st.empty()) { throw std::logic_error("invalid AST stack"); } - ast_node *node = st.back(); - ast_node *obj = nullptr; - - using swallow = bool[]; - (void)swallow{obj || (obj = std::is_same() ? node : ast_cast(node))...}; + ast_node* node = st.back(); - if (!obj) throw std::logic_error("invalid AST node"); + if (!ast_choice::accept(node)) throw std::logic_error("invalid AST node"); st.pop_back(); - delete m_ptr; - m_ptr = obj; - _set_parent(); + m_ptr = node; + node->retain(); } private: - void _set_parent() { - if (m_ptr) m_ptr->m_parent = container(); - } + virtual bool accept(ast_node* node) override { + if (!node) return false; + using swallow = bool[]; + bool* result = nullptr; + (void)swallow{result || (result = ast_type() == node->get_type())...}; + return result; + } }; class _ast_list : public ast_member { public: - ///list type. - typedef std::list container; + typedef std::list container; - virtual int get_type() override { return ast_type<_ast_list>(); } + _ast_list() : ast_member(true) {} + + ~_ast_list() { + clear(); + } + + void add(ast_node* node) { + if (accept(node)) { + m_objects.push_back(node); + node->retain(); + } + } - const container &objects() const { + const container& objects() const { return m_objects; } + + void clear() { + for(ast_node* obj : m_objects) { + if (obj) obj->release(); + } + m_objects.clear(); + } + + void dup(const _ast_list& src) { + for(ast_node* obj : src.m_objects) { + m_objects.push_back(obj); + obj->retain(); + } + } + + virtual int get_type() override { return ast_type<_ast_list>(); } protected: container m_objects; }; @@ -447,86 +411,39 @@ public: ///the default constructor. ast_list() {} - /** duplicates the objects of the given list. - @param src source object. - */ - ast_list(const ast_list &src) { - _dup(src); - } - - /** deletes the objects. - */ - ~ast_list() { - _clear(); - } - - /** deletes the objects of this list and duplicates the given one. - @param src source object. - @return reference to this. - */ - ast_list &operator = (const ast_list &src) { - if (&src != this) { - _clear(); - _dup(src); - } - return *this; - } + ast_list(const ast_list& other) { + clear(); + dup(other); + } - /** returns the container of objects. - @return the container of objects. - */ - const container &objects() const { - return m_objects; - } + ast_list& operator=(const ast_list& other) { + clear(); + dup(other); + return *this; + } /** Pops objects of type T from the stack until no more objects can be popped. @param st stack. */ virtual void construct(ast_stack &st) override { - for(;;) { - //if the stack is empty - if (st.empty()) break; - - //get the node - ast_node *node = st.back(); - - //get the object - T *obj = std::is_same() ? static_cast(node) : ast_cast(node); - + while (!st.empty()) { + ast_node* node = st.back(); + //if the object was not not of the appropriate type, //end the list parsing - if (!obj) return; - - //remove the node from the stack + if (!ast_list::accept(node)) return; + st.pop_back(); //insert the object in the list, in reverse order - m_objects.push_front(obj); - - //set the object's parent - obj->m_parent = ast_member::container(); + m_objects.push_front(node); + node->retain(); } } private: - //deletes the objects of this list. - void _clear() { - while (!m_objects.empty()) { - delete m_objects.back(); - m_objects.pop_back(); - } - } - - //duplicate the given list. - void _dup(const ast_list &src) { - for(typename container::const_iterator it = src.m_objects.begin(); - it != src.m_objects.end(); - ++it) - { - T *obj = new T(*it); - m_objects.push_back(obj); - obj->m_parent = ast_member::container(); - } - } + virtual bool accept(ast_node* node) override { + return node && (std::is_same() || ast_type() == node->get_type()); + } }; @@ -538,15 +455,15 @@ public: /** constructor. @param r rule to attach the AST function to. */ - ast(rule &r) { + ast(rule& r) { r.set_parse_proc(&_parse_proc); } private: //parse proc - static void _parse_proc(const pos &b, const pos &e, void *d) { - ast_stack *st = reinterpret_cast(d); - T *obj = new T; + static void _parse_proc(const pos& b, const pos& e, void* d) { + ast_stack* st = reinterpret_cast(d); + T* obj = new T; obj->m_begin = b; obj->m_end = e; obj->construct(*st); @@ -563,23 +480,27 @@ private: @return pointer to ast node created, or null if there was an error. The return object must be deleted by the caller. */ -ast_node *parse(input &i, rule &g, error_list &el, void* ud); +ast_node* _parse(input &i, rule &g, error_list &el, void* ud); /** parses the given input. @param i input. @param g root rule of grammar. @param el list of errors. - @param ast result pointer to created ast. @param ud user data, passed to the parse procedures. - @return true on success, false on error. + @return ast nodes. */ -template bool parse(input &i, rule &g, error_list &el, T *&ast, void* ud = nullptr) { - ast_node *node = parse(i, g, el, ud); - ast = ast_cast(node); - if (ast) return true; - delete node; - return false; +template ast_ptr parse(input &i, rule &g, error_list &el, void* ud = nullptr) { + ast_node* node = _parse(i, g, el, ud); + T* ast = ast_cast(node); + ast_ptr ptr; + if (ast) { + ast_stack st{node}; + ptr.construct(st); + } else if (node) { + delete node; + } + return ptr; } diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp index a98e75e..3c433ae 100644 --- a/MoonParser/moon_ast.cpp +++ b/MoonParser/moon_ast.cpp @@ -151,16 +151,16 @@ public: void complile(const std::string& codes) { input input = _converter.from_bytes(codes); error_list el; - BlockEnd_t* root = nullptr; State st; - if (parse(input, BlockEnd, el, root, &st)) { - std::cout << "matched!\n"; + auto root = parse(input, BlockEnd, el, &st); + if (root) { + std::cout << "compiled!\n\n"; std::vector out; root->eachChild([&](ast_node* node) { switch (node->getId()) { case "Block"_id: pushScope(); - transformBody(node, out); + transformBody(static_cast(node), out, true); popScope(); break; default: break; @@ -170,20 +170,21 @@ public: if (out.size() == 1) { result = std::move(out.front()); } else if (out.size() > 1) { - result = join(out, "\n"); + result = join(out, "\n"sv); } std::cout << result << '\n'; } else { - std::cout << "not matched!\n"; + std::cout << "compile failed!\n"; for (error_list::iterator it = el.begin(); it != el.end(); ++it) { const error& err = *it; std::cout << "line " << err.m_begin.m_line << ", col " << err.m_begin.m_col << ": syntax error\n"; } } + _codeCache.clear(); } - private: Converter _converter; + std::vector _codeCache; std::ostringstream _buf; std::string _newLine = "\n"; std::vector _lineTable; @@ -199,7 +200,11 @@ private: _scopes.back().vars = MakeUnique>(); } - bool isDefined(const std::string& name, bool checkShadowScope = false) { + void popScope() { + _scopes.pop_back(); + } + + bool isDefined(const std::string& name, bool checkShadowScopeOnly = false) { bool isDefined = false; for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { auto vars = it->vars.get(); @@ -207,7 +212,7 @@ private: isDefined = true; break; } - if (checkShadowScope && it->allows) break; + if (checkShadowScopeOnly && it->allows) break; } return isDefined; } @@ -244,8 +249,15 @@ private: return !defined; } - void popScope() { - _scopes.pop_back(); + std::string getValidName(std::string_view name) { + int index = 0; + std::string newName; + do { + _buf << name << index; + newName = clearBuf(); + index++; + } while (isDefined(newName)); + return newName; } const std::string nll(ast_node* node) { @@ -259,7 +271,11 @@ private: } std::string indent() { - return std::string(_scopes.size() - 1, '\t'); + return std::string((_scopes.size() - 1) * 2, ' '); + } + + std::string indent(int offset) { + return std::string((_scopes.size() - 1 + offset) * 2, ' '); } std::string clearBuf() { @@ -285,335 +301,530 @@ private: } std::string toString(ast_node* node) { - auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); + auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); + return trim(str); + } + + std::string toString(input::iterator begin, input::iterator end) { + auto str = _converter.to_bytes(std::wstring(begin, end)); return trim(str); } void noop(ast_node* node, std::vector& out) { - auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); + auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str)); // out.push_back(trim(str)); } void noopnl(ast_node* node, std::vector& out) { - auto str = _converter.to_bytes(std::u32string(node->m_begin.m_it, node->m_end.m_it)); + auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str) + nll(node)); // out.push_back(trim(str) + nll(node)); } - void transformStatement(ast_node* statement, std::vector& out) { - std::vector temp; - auto transformContent = [&](ast_node* node, std::vector& out) { - switch (node->getId()) { - case "Import"_id: transformImport(node, temp); break; - case "While"_id: transformWhile(node, temp); break; - case "With"_id: transformWith(node, temp); break; - case "For"_id: transformFor(node, temp); break; - case "ForEach"_id: transformForEach(node, temp); break; - case "Switch"_id: transformSwitch(node, temp); break; - case "Return"_id: transformReturn(node, temp); break; - case "Local"_id: transformLocal(node, temp); break; - case "Export"_id: transformExport(node, temp); break; - case "BreakLoop"_id: transformBreakLoop(node, temp); break; - case "Assignment"_id: transformAssignment(node, temp); break; - case "ExpList"_id: - transformExpList(node, temp); - temp.back() = indent() + temp.back() + nll(node); + Value_t* singleValueFrom(ast_node* expList) { + ast_node* singleValue = nullptr; + expList->traverse([&](ast_node* n) { + if (n->getId() == "Value"_id) { + if (!singleValue) { + singleValue = n; + return traversal::Return; + } else { + singleValue = nullptr; + return traversal::Stop; + } + } + return traversal::Continue; + }); + return static_cast(singleValue); + } + + Statement_t* lastStatementFrom(ast_node* body) { + ast_node* last = nullptr; + body->traverse([&](ast_node* n) { + switch (n->getId()) { + case "Statement"_id: + last = n; + return traversal::Return; + default: return traversal::Continue; + } + }); + return static_cast(last); + } + + template + ast_ptr toAst(std::string_view codes, rule& r) { + _codeCache.push_back(_converter.from_bytes(s(codes))); + error_list el; + State st; + return parse(_codeCache.back(), r, el, &st); + } + + void transformStatement(Statement_t* statement, std::vector& out) { + if (statement->appendix) { + auto appendix = statement->appendix; + switch (appendix->item->getId()) { + case "if_else_line"_id: { + auto if_else_line = static_cast(appendix->item.get()); + auto ifCond = new_ptr(); + ifCond->condition = if_else_line->condition; + + auto exprList = new_ptr(); + exprList->exprs.add(if_else_line->elseExpr); + auto stmt = new_ptr(); + stmt->content.set(exprList); + auto body = new_ptr(); + body->content.set(stmt); + auto ifElseIf = new_ptr(); + ifElseIf->body.set(body); + + stmt = new_ptr(); + stmt->content.set(statement->content); + body = new_ptr(); + body->content.set(stmt); + auto ifNode = new_ptr(); + ifNode->firstCondition.set(ifCond); + ifNode->firstBody.set(body); + ifNode->branches.add(ifElseIf); + + statement->appendix.set(nullptr); + auto simpleValue = new_ptr(); + simpleValue->value.set(ifNode); + auto value = new_ptr(); + value->item.set(simpleValue); + auto exp = new_ptr(); + exp->value.set(value); + exprList = new_ptr(); + exprList->exprs.add(exp); + statement->content.set(exprList); break; + } + case "unless_line"_id: { + break; + } + case "CompInner"_id: { + break; + } default: break; } - }; - if (statement->getChildCount() > 1) { - pushScope(); - transformContent(statement->getChild(0), out); - popScope(); - transform_statement_appendix(statement->getChild(1), temp); - } else { - transformContent(statement->getChild(0), out); } - switch (temp.size()) { - case 1: // body - out.push_back(std::move(temp.front())); - break; - case 2: // body, if - out.push_back(join({std::move(temp[1]), std::move(temp[0]), s("end"sv) + nlr(statement)})); - break; - case 3: // body, if, else - out.push_back(join({std::move(temp[1]), std::move(temp[0]), std::move(temp[2]), s("end"sv) + nlr(statement)})); + auto node = statement->content.get(); + if (!node) { + out.push_back(Empty); + return; + } + switch (node->getId()) { + case "Import"_id: transformImport(node, out); break; + case "While"_id: transformWhile(node, out); break; + case "With"_id: transformWith(node, out); break; + case "For"_id: transformFor(static_cast(node), out); break; + case "ForEach"_id: transformForEach(static_cast(node), out); break; + case "Switch"_id: transformSwitch(node, out); break; + case "Return"_id: transformReturn(static_cast(node), out); break; + case "Local"_id: transformLocal(node, out); break; + case "Export"_id: transformExport(node, out); break; + case "BreakLoop"_id: transformBreakLoop(node, out); break; + case "Assignment"_id: transformStatementAssign(statement, out); break; + case "ExpList"_id: { + auto expList = static_cast(node); + if (expList->exprs.objects().empty()) { + out.push_back(Empty); + break; + } + if (auto singleValue = singleValueFrom(expList)) { + if (auto ifNode = static_cast(singleValue->getByPath({"SimpleValue"_id, "If"_id}))) { + transformIf(ifNode, out); + break; + } + if (singleValue->getByPath({"ChainValue"_id, "InvokeArgs"_id})) { + transformValue(singleValue, out); + out.back() = indent() + out.back() + nlr(singleValue); + break; + } + } + std::string preDefine; + if (addToScope(s("_"sv))) { + preDefine = indent() + s("local _"sv) + nll(expList); + } + preDefine.append(indent() + s("_ = "sv)); + std::vector temp; + transformExpList(expList, temp); + out.push_back(preDefine + temp.back() + nlr(expList)); break; + } + default: break; } } - void transform_statement_appendix(ast_node* appendix, std::vector& out) { - appendix->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "if_else_line"_id: transform_if_else_line(node, out); break; - case "unless_line"_id: transform_unless_line(node, out); break; - case "CompInner"_id: transformCompInner(node, out); break; - default: break; + std::string transformAssignDefs(ExpList_t* expList) { + std::vector preDefs; + std::vector values; + expList->traverse([&](ast_node* child) { + if (child->getId() == "Value"_id) { + auto target = child->getByPath({"ChainValue"_id, "Callable"_id, "Name"_id}); + if (target) { + auto name = toString(target); + if (addToScope(name)) { + preDefs.push_back(name); + } + } + return traversal::Return; } + return traversal::Continue; }); + if (!preDefs.empty()) { + return indent() + s("local "sv) + join(preDefs, ", "sv); + } + return std::string(); } - void transform_if_else_line(ast_node* if_else_line, std::vector& out) { - std::vector temp; - if_else_line->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Exp"_id: + void transformStatementAssign(Statement_t* statement, std::vector& out) { + auto assignment = static_cast(statement->content.get()); + if (auto ifNode = assignment->getByPath({"Assign"_id, "If"_id})) { + auto expList = assignment->assignable.get(); + std::vector temp; + std::list> ifCondPairs; + ifCondPairs.emplace_back(); + std::string preDefine = transformAssignDefs(expList); + if (!preDefine.empty()) temp.push_back(preDefine + nll(expList)); + ifNode->traverse([&](ast_node* node) { + switch (node->getId()) { + case "IfCond"_id: + ifCondPairs.back().first = static_cast(node); + return traversal::Return; + case "Body"_id: + ifCondPairs.back().second = static_cast(node); + ifCondPairs.emplace_back(); + return traversal::Return; + default: return traversal::Continue; + } + }); + for (const auto& pair : ifCondPairs) { + if (pair.first) { + std::vector tmp; + auto condition = pair.first->condition.get(); + transformExp(condition, tmp); + _buf << indent() << (pair == ifCondPairs.front() ? ""sv : "else"sv) << + "if "sv << tmp.front() << " then"sv << nll(condition); + temp.push_back(clearBuf()); + } + if (pair.second) { + if (!pair.first) { + temp.push_back(indent() + s("else"sv) + nll(pair.second)); + } + auto last = lastStatementFrom(pair.second); + auto valueList = last ? last->content.as() : nullptr; + if (last && valueList) { + auto newAssignment = new_ptr(); + newAssignment->assignable.set(expList); + auto assign = new_ptr(); + if (valueList->getChildCount() == 2) { + if (auto subIfNode = valueList->getByPath({ + "Exp"_id, "Value"_id, "SimpleValue"_id, "If"_id})) { + assign->value.set(subIfNode); + } + } + if (!assign->value) { + auto expListLow = new_ptr(); + expListLow->exprs = valueList->exprs; + assign->value.set(expListLow); + } + newAssignment->target.set(assign); + last->content.set(newAssignment); + } pushScope(); - transformExp(node, temp); + transformBody(pair.second, temp); popScope(); - break; - default: break; + if (!pair.first) { + temp.push_back(indent() + s("end"sv) + nll(pair.second)); + } + } } - }); - out.push_back(indent() + s("if "sv) + temp[0] + s(" then"sv) + nll(if_else_line)); - out.push_back(indent() + s("else "sv) + nll(if_else_line) + indent() + '\t' + temp[1] + nll(if_else_line)); + out.push_back(join(temp)); + return; + } + if (auto expList = assignment->getByPath({"Assign"_id, "ExpListLow"_id})) { + auto singleValue = singleValueFrom(expList); + if (singleValue && singleValue->item->getId() == "SimpleValue"_id) { + auto valueItem = singleValue->item->getFirstChild(); + switch (valueItem->getId()) { + case "Comprehension"_id: { + std::vector temp; + auto expList = assignment->assignable.get(); + transformExpList(expList, temp); + transformCompInPlace(static_cast(valueItem), temp.front(), temp); + std::string preDefine = transformAssignDefs(expList); + out.push_back(preDefine + nll(statement) + temp.back()); + return; + } + case "For"_id: { + std::vector temp; + auto expList = assignment->assignable.get(); + std::string preDefine = transformAssignDefs(expList); + transformForInPlace(static_cast(valueItem), temp, expList); + out.push_back(preDefine + nll(statement) + temp.front()); + return; + } + case "ForEach"_id: { + std::vector temp; + auto expList = assignment->assignable.get(); + std::string preDefine = transformAssignDefs(expList); + transformForEachInPlace(static_cast(valueItem), temp, expList); + out.push_back(preDefine + nll(statement) + temp.front()); + return; + } + } + } + } + transformAssignment(assignment, out); } - void transformAssignment(ast_node* assignment, std::vector& out) { + void transformAssignment(Assignment_t* assignment, std::vector& out) { std::vector temp; - std::string preDefined; - assignment->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "ExpList"_id: { - std::vector preDefs; - std::vector values; - node->traverse([&](ast_node* child) { - if (child->getId() == "Value"_id) { - auto target = child->getByPath({"ChainValue"_id, "Callable"_id, "Name"_id}); - if (target) { - auto name = toString(target); - if (addToScope(name)) { - preDefs.push_back(name); + auto expList = assignment->assignable.get(); + auto action = assignment->target.get(); + std::string preDefine = transformAssignDefs(expList); + transformExpList(expList, temp); + bool oneLined = expList->getChildCount() == 2 && + traversal::Stop != action->traverse([&](ast_node* node) { + if (node->getId() == "FunLit"_id) { + if (auto body = node->getByPath({"Body"_id})) { + if (traversal::Stop == body->traverse([&](ast_node* n) { + if (n->getId() == "Callable"_id) { + if (auto name = n->getByPath({"Name"_id})) { + if (temp.front() ==toString(name)) { + return traversal::Stop; + } } } - return traversal::Return; + return traversal::Continue; + })) { + return traversal::Stop; } - return traversal::Continue; - }); - if (!preDefs.empty()) { - preDefined = indent() + s("local "sv) + join(preDefs, ", "sv) + nll(node); } - transformExpList(node, temp); - break; } - case "Update"_id: transformUpdate(node, temp); break; - case "Assign"_id: { - auto child = node->getChild(0); - switch (child->getId()) { - case "With"_id: transformWith(child, temp); break; - case "If"_id: - transformIfClosure(child, temp); - break; - case "Switch"_id: transformSwitch(child, temp); break; - case "TableBlock"_id: transformTableBlock(child, temp); break; - case "ExpListLow"_id: - transformExpListLow(child, temp); - break; - default: break; - } - break; + return traversal::Continue; + }); + switch (action->getId()) { + case "Update"_id: transformUpdate(action, temp); break; + case "Assign"_id: { + auto child = action->getFirstChild(); + switch (child->getId()) { + case "With"_id: transformWith(child, temp); break; + case "If"_id: transformIfClosure(static_cast(child), temp); break; + case "Switch"_id: transformSwitch(child, temp); break; + case "TableBlock"_id: transformTableBlock(child, temp); break; + case "ExpListLow"_id: transformExpListLow(static_cast(child), temp); break; + default: break; } - default: break; + break; } - }); - out.push_back(preDefined + indent() + temp[0] + s(" = "sv) + temp[1] + nll(assignment)); + default: break; + } + if (oneLined) { + out.push_back((preDefine.empty() ? indent() + temp[0] : preDefine) + s(" = "sv) + temp[1] + nll(assignment)); + } else { + out.push_back((preDefine.empty() ? Empty : preDefine + nll(assignment)) + indent() + temp[0] + s(" = "sv) + temp[1] + nll(assignment)); + } } - void transformIfClosure(ast_node* ifNode, std::vector& out) { + + void transformIf(If_t* ifNode, std::vector& out, bool withClosure = false) { std::vector temp; - temp.push_back(s("(function()"sv) + nll(ifNode)); - pushScope(); + if (withClosure) { + temp.push_back(s("(function()"sv) + nll(ifNode)); + pushScope(); + } + std::list> ifCondPairs; + ifCondPairs.emplace_back(); ifNode->traverse([&](ast_node* node) { switch (node->getId()) { - case "IfCond"_id: { - std::vector tmp; - auto exp = node->getChild(0); - transformExp(exp, tmp); - _buf << indent() << "if "sv << tmp.front() << " then"sv << nll(exp); - temp.push_back(clearBuf()); + case "IfCond"_id: + ifCondPairs.back().first = static_cast(node); return traversal::Return; - } case "Body"_id: - transformBody(node, temp); + ifCondPairs.back().second = static_cast(node); + ifCondPairs.emplace_back(); return traversal::Return; default: return traversal::Continue; } }); - popScope(); - temp.push_back(indent() + s("end)()"sv)); + for (const auto& pair : ifCondPairs) { + if (pair.first) { + std::vector tmp; + auto condition = pair.first->condition.get(); + transformExp(condition, tmp); + _buf << indent() << (pair == ifCondPairs.front() ? ""sv : "else"sv) << + "if "sv << tmp.front() << " then"sv << nll(condition); + temp.push_back(clearBuf()); + } + if (pair.second) { + if (!pair.first) { + temp.push_back(indent() + s("else"sv) + nll(pair.second)); + } + pushScope(); + transformBody(pair.second, temp, withClosure); + popScope(); + if (!pair.first) { + temp.push_back(indent() + s("end"sv) + nll(pair.second)); + } + } + } + if (withClosure) { + popScope(); + temp.push_back(indent() + s("end)()"sv)); + } out.push_back(join(temp)); } - void transformExpList(ast_node* expList, std::vector& out) { + void transformIfClosure(If_t* ifNode, std::vector& out) { + transformIf(ifNode, out, true); + } + + void transformExpList(ExpList_t* expList, std::vector& out) { std::vector temp; - expList->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Exp"_id: transformExp(node, temp); break; - default: break; - } - }); + for (auto exp : expList->exprs.objects()) { + transformExp(static_cast(exp), temp); + } out.push_back(join(temp, ", "sv)); } - void transformExpListLow(ast_node* expListLow, std::vector& out) { + void transformExpListLow(ExpListLow_t* expListLow, std::vector& out) { std::vector temp; - expListLow->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Exp"_id: transformExp(node, temp); break; - default: break; - } - }); + for (auto exp : expListLow->exprs.objects()) { + transformExp(static_cast(exp), temp); + } out.push_back(join(temp, ", "sv)); } - void transformExp(ast_node* exp, std::vector& out) { + void transformExp(Exp_t* exp, std::vector& out) { std::vector temp; - exp->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Value"_id: transformValue(node, temp); break; - case "exp_op_value"_id: transform_exp_op_value(node, temp); break; - default: break; - } - }); + transformValue(exp->value, temp); + for (auto _opValue : exp->opValues.objects()) { + auto opValue = static_cast(_opValue); + transformBinaryOperator(opValue->op, temp); + transformValue(opValue->value, temp); + } out.push_back(join(temp, " "sv)); } - void transform_exp_op_value(ast_node* exp_op_value, std::vector& out) { - exp_op_value->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "BinaryOperator"_id: transformBinaryOperator(node, out); break; - case "Value"_id: transformValue(node, out); break; - default: break; - } - }); - } - - void transformValue(ast_node* value, std::vector& out) { - value->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "SimpleValue"_id: transformSimpleValue(node, out); break; - case "simple_table"_id: transform_simple_table(node, out); break; - case "ChainValue"_id: transformChainValue(node, out); break; - case "String"_id: transformString(node, out); break; - default: break; - } - }); + void transformValue(Value_t* value, std::vector& out) { + auto item = value->item.get(); + switch (item->getId()) { + case "SimpleValue"_id: transformSimpleValue(static_cast(item), out); break; + case "simple_table"_id: transform_simple_table(item, out); break; + case "ChainValue"_id: transformChainValue(static_cast(item), out); break; + case "String"_id: transformString(static_cast(item), out); break; + default: break; + } } - void transformChainValue(ast_node* chainValue, std::vector& out) { + void transformChainValue(ChainValue_t* chainValue, std::vector& out) { std::vector temp; - bool hasInvokeArgs = false; - chainValue->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Chain"_id: transformChain(node, temp); break; - case "Callable"_id: transformCallable(node, temp); break; - case "InvokeArgs"_id: - hasInvokeArgs = true; - transformInvokeArgs(node, temp); - break; - default: break; - } - }); - out.push_back(hasInvokeArgs ? (temp[0] + s("("sv) + temp[1] + s(")"sv)) : temp[0]); + auto caller = chainValue->caller.get(); + switch (caller->getId()) { + case "Chain"_id: transformChain(static_cast(caller), temp); break; + case "Callable"_id: transformCallable(static_cast(caller), temp, chainValue->arguments); break; + default: break; + } + if (chainValue->arguments) { + transformInvokeArgs(chainValue->arguments, temp); + out.push_back(temp[0] + s("("sv) + temp[1] + s(")"sv)); + } else { + out.push_back(temp[0]); + } } - void transformCallable(ast_node* callable, std::vector& out) { - callable->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Name"_id: transformName(node, out); break; - case "SelfName"_id: transformSelfName(node, out); break; - case "VarArg"_id: transformVarArg(node, out); break; - case "Parens"_id: transformParens(node, out); break; - default: break; - } - }); + void transformCallable(Callable_t* callable, std::vector& out, bool invoke) { + auto item = callable->item.get(); + switch (item->getId()) { + case "Name"_id: transformName(static_cast(item), out); break; + case "SelfName"_id: transformSelfName(static_cast(item), out, invoke); break; + case "VarArg"_id: out.push_back(s("..."sv)); break; + case "Parens"_id: transformParens(static_cast(item), out); break; + default: break; + } } - void transformParens(ast_node* parans, std::vector& out) { + void transformParens(Parens_t* parans, std::vector& out) { std::vector temp; - parans->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Exp"_id: transformExp(node, temp); break; - default: break; - } - }); + transformExp(parans->expr, temp); out.push_back(s("("sv) + temp.front() + s(")"sv)); } - void transformSimpleValue(ast_node* simpleValue, std::vector& out) { - simpleValue->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "const_value"_id: transform_const_value(node, out); break; - case "If"_id: transformIf(node, out); break; - case "Switch"_id: transformSwitch(node, out); break; - case "With"_id: transformWith(node, out); break; - case "ClassDecl"_id: transformClassDecl(node, out); break; - case "ForEach"_id: transformForEach(node, out); break; - case "For"_id: transformFor(node, out); break; - case "While"_id: transformWhile(node, out); break; - case "Do"_id: transformDo(node, out); break; - case "unary_exp"_id: transform_unary_exp(node, out); break; - case "TblComprehension"_id: transformTblComprehension(node, out); break; - case "TableLit"_id: transformTableLit(node, out); break; - case "Comprehension"_id: transformComprehension(node, out); break; - case "FunLit"_id: transformFunLit(node, out); break; - case "Num"_id: transformNum(node, out); break; - default: break; - } - }); + void transformSimpleValue(SimpleValue_t* simpleValue, std::vector& out) { + auto node = simpleValue->value.get(); + switch (node->getId()) { + case "const_value"_id: transform_const_value(node, out); break; + case "If"_id: transformIfClosure(static_cast(node), out); break; + case "Switch"_id: transformSwitch(node, out); break; + case "With"_id: transformWith(node, out); break; + case "ClassDecl"_id: transformClassDecl(node, out); break; + case "ForEach"_id: transformForEachClosure(static_cast(node), out); break; + case "For"_id: transformForClosure(static_cast(node), out); break; + case "While"_id: transformWhile(node, out); break; + case "Do"_id: transformDo(node, out); break; + case "unary_exp"_id: transform_unary_exp(static_cast(node), out); break; + case "TblComprehension"_id: transformTblComprehension(node, out); break; + case "TableLit"_id: transformTableLit(static_cast(node), out); break; + case "Comprehension"_id: transformComprehension(static_cast(node), out); break; + case "FunLit"_id: transformFunLit(static_cast(node), out); break; + case "Num"_id: transformNum(static_cast(node), out); break; + default: break; + } } - void transformFunLit(ast_node* funLit, std::vector& out) { + void transformFunLit(FunLit_t* funLit, std::vector& out) { std::vector temp; - bool isFatArrow = false; - bool hasArgsDef = false; - ast_node* body = nullptr; + bool isFatArrow = toString(funLit->arrow) == "=>"sv; pushScope(); - funLit->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "FnArgsDef"_id: - hasArgsDef = true; - transformFnArgsDef(node, temp); - break; - case "fn_arrow"_id: - isFatArrow = toString(node) == "=>"sv; - break; - case "Body"_id: - transformBody(node, temp); - body = node; - break; - default: break; + if (auto argsDef = funLit->argsDef.get()) { + transformFnArgsDef(argsDef, temp); + if (funLit->body) { + transformBody(funLit->body, temp, true); + } else { + temp.push_back(Empty); } - }); - popScope(); - if (hasArgsDef) { auto& args = temp[0]; auto& initArgs = temp[1]; auto& bodyCodes = temp[2]; _buf << "function("sv << - (isFatArrow ? s("self"sv) + s(args.empty() ? ""sv : ", "sv) : Empty) << - args << ')' << nll(funLit) << - (initArgs.empty() ? Empty : initArgs) << - (body ? bodyCodes : Empty) << - indent() << "end"sv; - out.push_back(clearBuf()); + (isFatArrow ? s("self, "sv) : Empty) << + args << ')' << nlr(argsDef) << + initArgs << bodyCodes; } else { - auto& bodyCodes = temp[0]; - out.push_back( - s("function()"sv) + nll(funLit) + - (body ? bodyCodes : Empty) + - indent() + s("end"sv) - ); + if (funLit->body) { + transformBody(funLit->body, temp, true); + } else { + temp.push_back(Empty); + } + auto& bodyCodes = temp.back(); + _buf << "function("sv << + (isFatArrow ? s("self"sv) : Empty) << + ')' << nll(funLit) << bodyCodes; } + popScope(); + _buf << indent() << "end"sv; + out.push_back(clearBuf()); } - void transformBody(ast_node* body, std::vector& out) { + void transformBody(Body_t* body, std::vector& out, bool implicitReturn = false) { + if (implicitReturn) { + auto last = lastStatementFrom(body); + if (ast_is(last->content)) { + auto expList = static_cast(last->content.get()); + auto expListLow = new_ptr(); + expListLow->exprs = expList->exprs; + auto returnNode = new_ptr(); + returnNode->valueList.set(expListLow); + auto statement = ast_cast(last); + statement->content.set(returnNode); + } + } std::vector temp; body->traverse([&](ast_node* node) { switch (node->getId()) { case "Statement"_id: - transformStatement(node, temp); + transformStatement(static_cast(node), temp); return traversal::Return; default: return traversal::Continue; } @@ -621,290 +832,739 @@ private: out.push_back(join(temp)); } - void transformFnArgsDef(ast_node* argsDef, std::vector& out) { - argsDef->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "FnArgDefList"_id: transformFnArgDefList(node, out); break; - case "outer_var_shadow"_id: transform_outer_var_shadow(node, out); break; - default: break; + void transformReturn(Return_t* returnNode, std::vector& out) { + if (auto valueList = returnNode->valueList.get()) { + if (auto singleValue = singleValueFrom(valueList)) { + if (auto comp = singleValue->getByPath({"SimpleValue"_id, "Comprehension"_id})) { + transformCompReturn(static_cast(comp), out); + } else { + transformValue(singleValue, out); + out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); + } + } else { + std::vector temp; + transformExpListLow(valueList, temp); + out.push_back(indent() + s("return "sv) + temp.front() + nlr(returnNode)); } - }); + } else { + out.push_back(s("return"sv) + nll(returnNode)); + } } - void transform_outer_var_shadow(ast_node* shadow, std::vector& out) { + void transformFnArgsDef(FnArgsDef_t* argsDef, std::vector& out) { + if (!argsDef->defList) { + out.push_back(Empty); + return; + } + transformFnArgDefList(argsDef->defList, out); + if (argsDef->shadowOption) { + transform_outer_var_shadow(argsDef->shadowOption, out); + } + } + + void transform_outer_var_shadow(outer_var_shadow_t* shadow, std::vector& out) { markVarShadowed(); - shadow->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "NameList"_id: - node->eachChild([&](ast_node* child) { - if (child->getId() == "Name"_id) { - this->addToAllowList(toString(child)); - } - }); - break; - default: break; + if (shadow->varList) { + for (auto name : shadow->varList->names.objects()) { + addToAllowList(toString(name)); } - }); + } } - void transformFnArgDefList(ast_node* argDefList, std::vector& out) { - std::vector> argItems; - const int Name = 0; - const int AssignSelf = 1; - const int DefaultVal = 2; - argDefList->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "FnArgDef"_id: { - argItems.emplace_back(2); - auto& arg = argItems.back(); - node->eachChild([&](ast_node* child) { - switch (child->getId()) { - case "Name"_id: arg[Name] = toString(child); break; - case "SelfName"_id: - child->eachChild([&](ast_node* inner) { - switch (inner->getId()) { - case "self_class_name"_id: - arg[Name] = toString(inner->getChild(0)); - arg[AssignSelf] = s("self.__class."sv) + arg.front(); - break; - case "self_class"_id: - arg[Name] = "self.__class"sv; - break; - case "self_name"_id: - arg[Name] = toString(inner->getChild(0)); - arg[AssignSelf] = s("self."sv) + arg.front(); - break; - case "self"_id: - arg[Name] = "self"sv; - break; - } - }); - break; - case "Exp"_id: transformExp(child, arg); break; - default: break; - } - }); + void transformFnArgDefList(FnArgDefList_t* argDefList, std::vector& out) { + struct ArgItem { + std::string name; + std::string assignSelf; + std::string defaultVal; + }; + std::list argItems; + std::vector temp; + std::string varNames; + bool assignSelf = false; + for (auto _def : argDefList->definitions.objects()) { + auto def = static_cast(_def); + auto& arg = argItems.emplace_back(); + switch (def->name->getId()) { + case "Name"_id: arg.name = toString(def->name); break; + case "SelfName"_id: { + assignSelf = true; + auto selfName = static_cast(def->name.get()); + switch (selfName->name->getId()) { + case "self_class_name"_id: + arg.name = toString(selfName->name->getFirstChild()); + arg.assignSelf = s("self.__class."sv) + arg.name; + break; + case "self_class"_id: + arg.name = "self.__class"sv; + break; + case "self_name"_id: + arg.name = toString(selfName->name->getFirstChild()); + arg.assignSelf = s("self."sv) + arg.name; + break; + case "self"_id: + arg.name = "self"sv; + break; + default: break; + } break; } - case "VarArg"_id: - argItems.emplace_back(2); - argItems.back()[Name] = "..."sv; - break; - default: break; } - }); - std::string varNames; - for (const auto& item : argItems) { - if (varNames.empty()) { - varNames = item[Name]; - } else { - varNames.append(s(", "sv) + item[Name]); + if (def->defaultValue) { + transformExp(static_cast(def->defaultValue.get()), temp); + arg.defaultVal = temp.front(); + temp.clear(); + _buf << indent() << "if "sv << arg.name << " == nil then"sv << nll(def) << + indent(1) << arg.name << " = "sv << arg.defaultVal << nll(def) << + indent() << "end"sv << nll(def); } - forceAddToScope(item[Name]); + if (varNames.empty()) varNames = arg.name; + else varNames.append(s(", "sv) + arg.name); + forceAddToScope(arg.name); } - for (const auto& item : argItems) { - if (item.size() == 3 && !item[DefaultVal].empty()) { - _buf << indent() << "if "sv << item[Name] << " == nil then"sv << nll(argDefList) << - indent() << '\t' << item[Name] << " = "sv << item[DefaultVal] << nll(argDefList) << - indent() << "end"sv << nll(argDefList); - } + if (argDefList->varArg) { + auto& arg = argItems.emplace_back(); + arg.name = "..."sv; + if (varNames.empty()) varNames = arg.name; + else varNames.append(s(", "sv) + arg.name); } std::string initCodes = clearBuf(); - std::vector> assignSelfVars; - for (const auto& item : argItems) { - if (!item[AssignSelf].empty()) { - assignSelfVars.push_back({&item[AssignSelf], &item[Name]}); - } - } - auto sjoin = [](const decltype(assignSelfVars)& items, int index) { - std::string result; - for (auto it = items.begin(); it != items.end(); ++it) { - if (result.empty()) result = *((*it)[index]); - else result.append(s(", "sv) + *((*it)[index])); - } - return result; - }; - std::string sleft = sjoin(assignSelfVars, 0); - std::string sright = sjoin(assignSelfVars, 1); - if (!assignSelfVars.empty()) { - initCodes.append(sleft + s(" = "sv) + sright + nll(argDefList)); + if (assignSelf) { + auto sjoin = [](const decltype(argItems)& items, int index) { + std::string result; + for (auto it = items.begin(); it != items.end(); ++it) { + if (it->assignSelf.empty()) continue; + if (result.empty()) result = (&it->name)[index]; + else result.append(s(", "sv) + (&it->name)[index]); + } + return result; + }; + std::string sleft = sjoin(argItems, 1); + std::string sright = sjoin(argItems, 0); + initCodes.append(indent() + sleft + s(" = "sv) + sright + nll(argDefList)); } out.push_back(varNames); out.push_back(initCodes); } - void transformChain(ast_node* chain, std::vector& out) { - chain->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "chain_call"_id: transform_chain_call(node, out); break; - case "chain_item"_id: transform_chain_item(node, out); break; - case "chain_dot_chain"_id: transform_chain_dot_chain(node, out); break; - case "ColonChain"_id: transformColonChain(node, out); break; - default: break; - } - }); + void transformSelfName(SelfName_t* selfName, std::vector& out, bool invoke) { + auto name = selfName->name.get(); + switch (name->getId()) { + case "self_class_name"_id: + out.push_back(s("self.__class."sv) + toString(name->getFirstChild())); + break; + case "self_class"_id: + out.push_back(s("self.__class"sv)); + break; + case "self_name"_id: + out.push_back(s("self"sv) + s(invoke ? ":"sv : "."sv) + toString(name->getFirstChild())); + break; + case "self"_id: + out.push_back(s("self"sv)); + break; + } + } + + void transformChain(Chain_t* chain, std::vector& out) { + auto item = chain->item.get(); + switch (item->getId()) { + case "chain_call"_id: transform_chain_call(static_cast(item), out); break; + case "chain_item"_id: transformChainItems(static_cast(item)->chain, out); break; + case "chain_dot_chain"_id: transform_chain_dot_chain(item, out); break; + case "ColonChain"_id: transformColonChain(static_cast(item), out); break; + default: break; + } } - void transform_chain_call(ast_node* chain_call, std::vector& out) { + void transform_chain_call(chain_call_t* chain_call, std::vector& out) { std::vector temp; - chain_call->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Callable"_id: transformCallable(node, temp); break; - case "String"_id: transformString(node, temp); break; - case "ChainItems"_id: transformChainItems(node, temp); break; - default: break; - } - }); + auto caller = chain_call->caller.get(); + switch (caller->getId()) { + case "Callable"_id: transformCallable(static_cast(caller), temp, true); break; + case "String"_id: transformString(static_cast(caller), temp); break; + default: break; + } + transformChainItems(chain_call->chain, temp); out.push_back(join(temp)); } - void transformChainItems(ast_node* chainItems, std::vector& out) { + void transformChainItems(ChainItems_t* chainItems, std::vector& out) { std::vector temp; - chainItems->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "ChainItem"_id: transformChainItem(node, temp); break; - case "ColonChain"_id: transformColonChain(node, temp); break; - default: break; - } - }); + for (auto _chainItem : chainItems->simpleChain.objects()) { + auto chainItem = static_cast(_chainItem); + transformChainItem(chainItem, temp); + } + if (chainItems->colonChain) { + transformColonChain(chainItems->colonChain, temp); + } out.push_back(join(temp)); } - void transformChainItem(ast_node* chainItem, std::vector& out) { - chainItem->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Invoke"_id: transformInvoke(node, out); break; - case "DotChainItem"_id: - out.push_back(s("."sv) + toString(node->getChild(0))); - break; - case "Slice"_id: transformSlice(node, out); break; + void transformChainItem(ChainItem_t* chainItem, std::vector& out) { + auto item = chainItem->item.get(); + switch (item->getId()) { + case "Invoke"_id: transformInvoke(static_cast(item), out); break; + case "DotChainItem"_id: + out.push_back(s("."sv) + toString(item->getFirstChild())); + break; + case "Slice"_id: transformSlice(item, out); break; + case "Exp"_id: + transformExp(static_cast(item), out); + out.back() = s("["sv) + out.back() + s("]"sv); + break; + default: break; + } + } + + void transformInvoke(Invoke_t* invoke, std::vector& out) { + auto argument = invoke->argument.get(); + switch (argument->getId()) { + case "FnArgs"_id: transformFnArgs(static_cast(argument), out); break; + case "SingleString"_id: transformSingleString(static_cast(argument), out); break; + case "DoubleString"_id: transformDoubleString(static_cast(argument), out); break; + case "LuaString"_id: transformLuaString(static_cast(argument), out); break; + default: break; + } + } + + void transformFnArgs(FnArgs_t* fnArgs, std::vector& out) { + std::vector temp; + for (auto node : fnArgs->args.objects()) { + transformExp(static_cast(node), temp); + } + std::string args = join(temp, ", "sv); + out.push_back(args.empty() ? s("()"sv) : s("("sv) + args + s(")"sv)); + } + + void transformColonChain(ColonChain_t* colonChain, std::vector& out) { + std::vector temp; + temp.push_back(s(":"sv) + toString(colonChain->colonChain->name)); + if (colonChain->invokeChain) { + transform_invoke_chain(colonChain->invokeChain, temp); + } + out.push_back(join(temp)); + } + + void transform_invoke_chain(invoke_chain_t* invoke_chain, std::vector& out) { + std::vector temp; + transformInvoke(invoke_chain->invoke, temp); + if (invoke_chain->chain) { + transformChainItems(invoke_chain->chain, temp); + } + out.push_back(join(temp)); + } + + void transform_unary_exp(unary_exp_t* unary_exp, std::vector& out) { + std::string op = toString(unary_exp->m_begin.m_it, unary_exp->item->m_begin.m_it); + std::vector temp{op + (op == "not"sv ? op + " " : Empty)}; + transformExp(unary_exp->item, temp); + out.push_back(join(temp)); + } + + void transformName(Name_t* name, std::vector& out) { + out.push_back(toString(name)); + } + + void transformNum(Num_t* num, std::vector& out) { + out.push_back(toString(num)); + } + + void transformTableLit(TableLit_t* tableLit, std::vector& out) { + std::vector temp; + ast_node* lastNode = nullptr; + for (auto _tableValue : tableLit->values.objects()) { + auto tableValue = static_cast(_tableValue); + auto value = tableValue->value.get(); + switch (value->getId()) { + case "KeyValue"_id: case "Exp"_id: - transformExp(node, out); - out.back() = s("["sv) + out.back() + s("]"sv); + if (value->getId() == "Exp"_id) { + transformExp(static_cast(value), temp); + } else { + transformKeyValue(static_cast(value), temp); + } + temp.back() = (lastNode ? s(","sv) + nll(lastNode) : Empty) + indent(1) + temp.back(); + lastNode = value; break; default: break; } - }); + } + out.push_back(s("{"sv) + nll(tableLit) + join(temp) + nlr(tableLit) + indent() + s("}"sv)); } - void transformInvoke(ast_node* invoke, std::vector& out) { - invoke->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "FnArgs"_id: transformFnArgs(node, out); break; - case "SingleString"_id: transformSingleString(node, out); break; - case "DoubleString"_id: transformDoubleString(node, out); break; - case "LuaString"_id: transformLuaString(node, out); break; + void transformComprehension(Comprehension_t* comp, std::vector& out) { + std::vector temp; + std::string accum = getValidName("_accum_"); + std::string len = getValidName("_len_"); + addToScope(accum); + addToScope(len); + transformExp(comp->value, temp); + auto compInner = comp->forLoop.get(); + switch (compInner->compFor->getId()) { + case "CompForEach"_id: + transformCompForEach( + static_cast(compInner->compFor.get()), temp); + break; + case "CompFor"_id: transformCompFor(compInner->compFor, temp); break; + default: break; + } + std::vector clauseCodes; + for (auto clause : compInner->clauses.objects()) { + pushScope(); + auto child = clause->getFirstChild(); + switch (child->getId()) { + case "CompForEach"_id: + transformCompForEach(static_cast(child), clauseCodes); + break; + case "CompFor"_id: transformCompFor(child, clauseCodes); break; + case "Exp"_id: + transformExp(static_cast(child), clauseCodes); + clauseCodes.back() = indent() + s("if "sv) + clauseCodes.back() + s(" then"sv) + nll(clause); + break; default: break; } - }); + } + for (size_t i = 0; i < compInner->clauses.objects().size(); ++i) { + popScope(); + } + _buf << indent() << "local "sv << accum << " = { }"sv << nll(comp); + _buf << indent() << "local "sv << len << " = 1"sv << nll(comp); + _buf << temp.back(); + pushScope(); + if (clauseCodes.empty()) { + _buf << indent() << accum << "["sv << len << "] = "sv << temp.front() << nll(comp); + _buf << indent() << len << " = "sv << len << " + 1"sv << nll(comp); + } else { + _buf << join(clauseCodes); + _buf << indent(int(clauseCodes.size())) << accum << "["sv << len << "] = "sv << temp.front() << nll(comp); + _buf << indent(int(clauseCodes.size())) << len << " = "sv << len << " + 1"sv << nll(comp); + for (int ind = int(clauseCodes.size()) - 1; ind > -1 ; --ind) { + _buf << indent(ind) << "end"sv << nll(comp); + } + } + popScope(); + _buf << indent() << "end"sv << nll(comp); + out.push_back(accum); + out.push_back(clearBuf()); } - void transformFnArgs(ast_node* fnArgs, std::vector& out) { + void transformCompInPlace(Comprehension_t* comp, const std::string& expStr, std::vector& out) { std::vector temp; - fnArgs->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Exp"_id: transformExp(node, temp); break; - default: break; + pushScope(); + transformComprehension(comp, temp); + out.push_back( + s("do"sv) + nll(comp) + + temp.back() + + indent() + expStr + s(" = "sv) + temp.front() + nll(comp)); + popScope(); + out.back() = out.back() + indent() + s("end"sv) + nlr(comp); + } + + void transformCompReturn(Comprehension_t* comp, std::vector& out) { + std::vector temp; + transformComprehension(comp, temp); + out.push_back(temp.back() + indent() + s("return "sv) + temp.front() + nlr(comp)); + } + + void transformCompClosure(Comprehension_t* comp, std::vector& out) { + std::vector temp; + std::string before = s("(function()"sv) + nll(comp); + pushScope(); + transformComprehension(comp, temp); + out.push_back( + before + + temp.back() + + indent() + s("return "sv) + temp.front() + nlr(comp)); + popScope(); + out.back() = out.back() + indent() + s("end)()"sv); + } + + void transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, std::vector& out) { + std::vector temp; + transformAssignableNameList(nameList, temp); + switch (loopTarget->getId()) { + case "star_exp"_id: { + auto star_exp = static_cast(loopTarget); + auto listName = getValidName("_list_"); + auto indexName = getValidName("_index_"); + addToScope(listName); + addToScope(indexName); + transformExp(star_exp->value, temp); + _buf << indent() << "local "sv << listName << " = "sv << temp.back() << nll(nameList); + _buf << indent() << "for "sv << indexName << " = 1, #"sv << listName << " do"sv << nlr(loopTarget); + _buf << indent(1) << "local "sv << temp.front() << " = "sv << listName << "["sv << indexName << "]"sv << nll(nameList); + out.push_back(clearBuf()); + break; } - }); - std::string args = join(temp, ", "sv); - out.push_back(args.empty() ? s("()"sv) : s("("sv) + args + s(")"sv)); + case "Exp"_id: + transformExp(static_cast(loopTarget), temp); + _buf << indent() << "for "sv << temp.front() << " in "sv << temp.back() << " do"sv << nlr(loopTarget); + out.push_back(clearBuf()); + break; + case "ExpList"_id: + transformExpList(static_cast(loopTarget), temp); + _buf << indent() << "for "sv << temp.front() << " in "sv << temp.back() << " do"sv << nlr(loopTarget); + out.push_back(clearBuf()); + break; + default: break; + } } - void transformColonChain(ast_node* colonChain, std::vector& out) { + void transformCompForEach(CompForEach_t* comp, std::vector& out) { + transformForEachHead(comp->nameList, comp->loopValue, out); + } + + void transformAssignableNameList(AssignableNameList_t* nameList, std::vector& out) { std::vector temp; - colonChain->eachChild([&](ast_node* node) { + for (auto node : nameList->items.objects()) { switch (node->getId()) { - case "ColonChainItem"_id: - temp.push_back(s(":"sv) + toString(node->getChild(0))); + case "Name"_id: + transformName(static_cast(node), temp); + break; + case "TableLit"_id: + transformTableLit(static_cast(node), temp); break; - case "invoke_chain"_id: transform_invoke_chain(node, temp); break; default: break; } - }); + } + out.push_back(join(temp, ", "sv)); + } + + void transformInvokeArgs(InvokeArgs_t* invokeArgs, std::vector& out) { + std::vector temp; + if (invokeArgs->argsList) { + transformExpList(invokeArgs->argsList, temp); + } + if (invokeArgs->argsTableBlock) { + transform_invoke_args_with_table(invokeArgs->argsTableBlock, temp); + } + if (invokeArgs->tableBlock) { + transformTableBlock(invokeArgs->tableBlock, temp); + } + out.push_back(join(temp, ", "sv)); + } + + void transformForHead(For_t* forNode, std::vector& out) { + std::vector temp; + std::string varName = toString(forNode->varName); + transformExp(forNode->startValue, temp); + transformExp(forNode->stopValue, temp); + if (forNode->stepValue) { + transformExp(forNode->stepValue->value, temp); + } else { + temp.emplace_back(); + } + _buf << indent() << "for "sv << varName << " = "sv << temp[0] << ", "sv << temp[1] << (temp[2].empty() ? Empty : s(", "sv) + temp[2]) << " do"sv << nll(forNode); + out.push_back(clearBuf()); + } + + void transformFor(For_t* forNode, std::vector& out) { + std::vector temp; + transformForHead(forNode, temp); + pushScope(); + transformBody(forNode->body, temp); + popScope(); + out.push_back(temp[0] + temp[1] + indent() + s("end"sv) + nlr(forNode)); + } + + void transformForClosure(For_t* forNode, std::vector& out) { + std::vector temp; + std::string accum = getValidName("_accum_"); + std::string len = getValidName("_len_"); + addToScope(accum); + addToScope(len); + _buf << "(function()"sv << nll(forNode); + pushScope(); + _buf << indent() << "local "sv << accum << " = { }"sv << nll(forNode); + _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); + temp.push_back(clearBuf()); + transformForHead(forNode, temp); + auto last = lastStatementFrom(forNode->body); + bool hasTableItem = ast_is(last->content); + if (hasTableItem) { + _buf << accum << "["sv << len << "]"sv; + std::string assignLeft = clearBuf(); + auto expList = toAst(assignLeft, ExpList); + auto assignment = new_ptr(); + assignment->assignable.set(expList); + auto expListLow = new_ptr(); + expListLow->exprs = ast_cast(last->content)->exprs; + auto assign = new_ptr(); + assign->value.set(expListLow); + assignment->target.set(assign); + last->content.set(assignment); + } + pushScope(); + transformBody(forNode->body, temp); + temp.push_back(indent() + len + s(" = "sv) + len + s(" + 1"sv) + nlr(forNode->body)); + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(forNode) + indent() + s("return "sv) + accum + nlr(forNode)); + popScope(); + temp.push_back(indent() + s("end)()"sv) + nlr(forNode)); out.push_back(join(temp)); } - void transform_invoke_chain(ast_node* invoke_chain, std::vector& out) { + void transformForInPlace(For_t* forNode, std::vector& out, ExpList_t* assignExpList) { std::vector temp; - invoke_chain->eachChild([&](ast_node* node) { - switch (node->getId()) { - case "Invoke"_id: transformInvoke(node, temp); break; - case "ChainItems"_id: transformChainItems(node, temp); break; + std::string accum = getValidName("_accum_"); + std::string len = getValidName("_len_"); + _buf << indent() << "do"sv << nll(forNode); + pushScope(); + addToScope(accum); + addToScope(len); + _buf << indent() << "local "sv << accum << " = { }"sv << nll(forNode); + _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); + temp.push_back(clearBuf()); + transformForHead(forNode, temp); + auto last = lastStatementFrom(forNode->body); + bool hasTableItem = ast_is(last->content); + if (hasTableItem) { + _buf << accum << "["sv << len << "]"sv; + std::string assignLeft = clearBuf(); + auto expList = toAst(assignLeft, ExpList); + auto assignment = new_ptr(); + assignment->assignable.set(expList); + auto expListLow = new_ptr(); + expListLow->exprs = ast_cast(last->content)->exprs; + auto assign = new_ptr(); + assign->value.set(expListLow); + assignment->target.set(assign); + last->content.set(assignment); + } + pushScope(); + transformBody(forNode->body, temp); + temp.push_back(indent() + len + s(" = "sv) + len + s(" + 1"sv) + nlr(forNode->body)); + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(forNode)); + transformExpList(assignExpList, temp); + temp.back() = indent() + temp.back() + s(" = "sv) + accum + nlr(forNode); + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(forNode)); + out.push_back(join(temp)); + } + + void transformBinaryOperator(BinaryOperator_t* node, std::vector& out) { + out.push_back(toString(node)); + } + + void transformForEach(ForEach_t* forEach, std::vector& out) { + std::vector temp; + transformForEachHead(forEach->nameList, forEach->loopValue, temp); + pushScope(); + transformBody(forEach->body, temp); + popScope(); + out.push_back(temp[0] + temp[1] + indent() + s("end"sv) + nlr(forEach)); + } + + void transformForEachClosure(ForEach_t* forEach, std::vector& out) { + std::vector temp; + std::string accum = getValidName("_accum_"); + std::string len = getValidName("_len_"); + addToScope(accum); + addToScope(len); + _buf << "(function()"sv << nll(forEach); + pushScope(); + _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); + _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); + temp.push_back(clearBuf()); + transformForEachHead(forEach->nameList, forEach->loopValue, temp); + auto last = lastStatementFrom(forEach->body); + bool hasTableItem = ast_is(last->content); + if (hasTableItem) { + _buf << accum << "["sv << len << "]"sv; + std::string assignLeft = clearBuf(); + auto expList = toAst(assignLeft, ExpList); + auto assignment = new_ptr(); + assignment->assignable.set(expList); + auto expListLow = new_ptr(); + expListLow->exprs = ast_cast(last->content)->exprs; + auto assign = new_ptr(); + assign->value.set(expListLow); + assignment->target.set(assign); + last->content.set(assignment); + } + pushScope(); + transformBody(forEach->body, temp); + temp.push_back(indent() + len + s(" = "sv) + len + s(" + 1"sv) + nlr(forEach->body)); + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(forEach) + indent() + s("return "sv) + accum + nlr(forEach)); + popScope(); + temp.push_back(indent() + s("end)()"sv) + nlr(forEach)); + out.push_back(join(temp)); + } + + void transformForEachInPlace(ForEach_t* forEach, std::vector& out, ExpList_t* assignExpList) { + std::vector temp; + std::string accum = getValidName("_accum_"); + std::string len = getValidName("_len_"); + _buf << indent() << "do"sv << nll(forEach); + pushScope(); + addToScope(accum); + addToScope(len); + _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); + _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); + temp.push_back(clearBuf()); + transformForEachHead(forEach->nameList, forEach->loopValue, temp); + auto last = lastStatementFrom(forEach->body); + bool hasTableItem = ast_is(last->content); + if (hasTableItem) { + _buf << accum << "["sv << len << "]"sv; + std::string assignLeft = clearBuf(); + auto expList = toAst(assignLeft, ExpList); + auto assignment = new_ptr(); + assignment->assignable.set(expList); + auto expListLow = new_ptr(); + expListLow->exprs = ast_cast(last->content)->exprs; + auto assign = new_ptr(); + assign->value.set(expListLow); + assignment->target.set(assign); + last->content.set(assignment); + } + pushScope(); + transformBody(forEach->body, temp); + temp.push_back(indent() + len + s(" = "sv) + len + s(" + 1"sv) + nlr(forEach->body)); + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(forEach)); + transformExpList(assignExpList, temp); + temp.back() = indent() + temp.back() + s(" = "sv) + accum + nlr(forEach); + popScope(); + temp.push_back(indent() + s("end"sv) + nlr(forEach)); + out.push_back(join(temp)); + } + + void transformKeyValue(KeyValue_t* keyValue, std::vector& out) { + auto item = keyValue->item.get(); + switch (item->getId()) { + case "variable_pair"_id: + out.push_back(toString(static_cast(item)->name)); + break; + case "normal_pair"_id: { + auto pair = static_cast(item); + auto key = pair->key.get(); + std::vector temp; + switch (key->getId()) { + case "KeyName"_id: transformKeyName(static_cast(key), temp); break; + case "Exp"_id: + transformExp(static_cast(key), temp); + temp.back() = s("["sv) + temp.back() + s("]"sv); + break; + case "DoubleString"_id: transformDoubleString(static_cast(key), temp); break; + case "SingleString"_id: transformSingleString(static_cast(key), temp); break; + default: break; + } + auto value = pair->value.get(); + switch (value->getId()) { + case "Exp"_id: transformExp(static_cast(value), temp); break; + case "TableBlock"_id: transformTableBlock(static_cast(value), temp); break; + default: break; + } + out.push_back(temp[0] + s(" = "sv) + temp[1]); + break; + } + default: break; + } + } + + void transformKeyName(KeyName_t* keyName, std::vector& out) { + auto name = keyName->name.get(); + switch (name->getId()) { + case "SelfName"_id: transformSelfName(static_cast(name), out, false); break; + case "_Name"_id: out.push_back(toString(name)); break; + default: break; + } + } + + void transformLuaString(LuaString_t* luaString, std::vector& out) { + out.push_back(toString(luaString)); + } + + void transformSingleString(SingleString_t* singleString, std::vector& out) { + out.push_back(toString(singleString)); + } + + void transformDoubleString(DoubleString_t* doubleString, std::vector& out) { + std::vector temp; + for (auto _seg : doubleString->segments.objects()) { + auto seg = static_cast(_seg); + auto content = seg->content.get(); + switch (content->getId()) { + case "double_string_inner"_id: + temp.push_back(s("\""sv) + toString(content) + s("\""sv)); + break; + case "Exp"_id: + transformExp(static_cast(content), temp); + temp.back() = s("tostring("sv) + temp.back() + s(")"sv); + break; default: break; } - }); - out.push_back(join(temp)); + } + out.push_back(join(temp, " .. "sv)); } - void transformUpdate(ast_node* node, std::vector& out) {noop(node, out);} + void transformString(String_t* string, std::vector& out) { + auto str = string->str.get(); + switch (str->getId()) { + case "SingleString"_id: transformSingleString(static_cast(str), out); break; + case "DoubleString"_id: transformDoubleString(static_cast(str), out); break; + case "LuaString"_id: transformLuaString(static_cast(str), out); break; + default: break; + } + } + void transformUpdate(ast_node* node, std::vector& out) {noop(node, out);} void transformImport(ast_node* node, std::vector& out) {noopnl(node, out);} void transformWhile(ast_node* node, std::vector& out) {noopnl(node, out);} void transformWith(ast_node* node, std::vector& out) {noopnl(node, out);} - void transformFor(ast_node* node, std::vector& out) {noopnl(node, out);} - void transformIf(ast_node* node, std::vector& out) { noopnl(node, out); } - void transformForEach(ast_node* node, std::vector& out) {noopnl(node, out);} void transformSwitch(ast_node* node, std::vector& out) {noopnl(node, out);} - void transformReturn(ast_node* node, std::vector& out) {noopnl(node, out);} void transformTableBlock(ast_node* node, std::vector& out) {noopnl(node, out);} void transformLocal(ast_node* node, std::vector& out) {noopnl(node, out);} void transformExport(ast_node* node, std::vector& out) {noopnl(node, out);} void transformBreakLoop(ast_node* node, std::vector& out) {noopnl(node, out);} void transform_unless_line(ast_node* node, std::vector& out) {noop(node, out);} - void transformCompInner(ast_node* node, std::vector& out) {noop(node, out);} void transform_simple_table(ast_node* node, std::vector& out) {noop(node, out);} - void transformString(ast_node* node, std::vector& out) {noop(node, out);} - void transformInvokeArgs(ast_node* node, std::vector& out) {noop(node, out);} - void transformName(ast_node* node, std::vector& out) {noop(node, out);} - void transformSelfName(ast_node* node, std::vector& out) {noop(node, out);} void transform_const_value(ast_node* node, std::vector& out) {noop(node, out);} void transformClassDecl(ast_node* node, std::vector& out) {noop(node, out);} void transformDo(ast_node* node, std::vector& out) {noop(node, out);} - void transform_unary_exp(ast_node* node, std::vector& out) {noop(node, out);} void transformTblComprehension(ast_node* node, std::vector& out) {noop(node, out);} - void transformTableLit(ast_node* node, std::vector& out) {noop(node, out);} - void transformComprehension(ast_node* node, std::vector& out) {noop(node, out);} - void transformNum(ast_node* node, std::vector& out) {noop(node, out);} - void transformVarArg(ast_node* node, std::vector& out) {noop(node, out);} - void transformBinaryOperator(ast_node* node, std::vector& out) {noop(node, out);} - void transform_chain_item(ast_node* node, std::vector& out) {noop(node, out);} void transform_chain_dot_chain(ast_node* node, std::vector& out) {noop(node, out);} void transformSlice(ast_node* node, std::vector& out) {noop(node, out);} - void transformSingleString(ast_node* node, std::vector& out) {noop(node, out);} - void transformDoubleString(ast_node* node, std::vector& out) {noop(node, out);} - void transformLuaString(ast_node* node, std::vector& out) {noop(node, out);} + void transformCompFor(ast_node* node, std::vector& out) {noop(node, out);} + void transformCompClause(ast_node* node, std::vector& out) {noop(node, out);} + void transform_invoke_args_with_table(ast_node* node, std::vector& out) {noop(node, out);} }; const std::string MoonCompliler::Empty; int main() { - std::string s = R"TestCodesHere(a = 998 -f, d = (-> - joop = 2302 + 567 + std::string s = R"TestCodesHere( +-- vararg bubbling +f = (...) -> #{...} + +dont_bubble = -> + [x for x in ((...)-> print ...)("hello")] + +k = [x for x in ((...)-> print ...)("hello")] + +j = for i=1,10 + (...) -> print ... + +-- bubble me - (hi, a, b = Vec2(100,200), c, d, ... using nil) -> - d = "中文" - hi = 1021 +m = (...) -> + [x for x in *{...} when f(...) > 4] - a,b,c,d = 1,2,3,4 +x = for i in *{...} do i +y = [x for x in *{...}] +z = [x for x in hallo when f(...) > 4] - hello[232], (5+5)[121], hello, x[99] = 100, 200, 300 - joop = 12), 123 if true else print("a",1,2)\abc(998).x +a = for i=1,10 do ... -a, b = if hello - "hello" -else - "nothing", "yeah" +b = for i=1,10 + -> print ... -a, b = if hello - if yeah then "one", "two" else "mmhh" -else - print "the other" - "nothing", "yeah")TestCodesHere"; +)TestCodesHere"; MoonCompliler{}.complile(s); diff --git a/MoonParser/moon_parser.cpp b/MoonParser/moon_parser.cpp index 7731513..ae8c53d 100644 --- a/MoonParser/moon_parser.cpp +++ b/MoonParser/moon_parser.cpp @@ -1,5 +1,13 @@ #include "moon_parser.h" +std::unordered_set State::keywords = { + "and", "while", "else", "using", "continue", + "local", "not", "then", "return", "from", + "extends", "for", "do", "or", "export", + "class", "in", "unless", "when", "elseif", + "switch", "break", "if", "with", "import", "true", "false", "nil" +}; + rule plain_space = *set(" \t"); rule Break = nl(-expr('\r') >> '\n'); rule Any = Break | any(); @@ -185,7 +193,9 @@ rule For = key("for") >> DisableDo >> extern rule AssignableNameList; -rule for_in = sym('*') >> Exp | ExpList; +extern rule star_exp; + +rule for_in = star_exp | ExpList; rule ForEach = key("for") >> AssignableNameList >> key("in") >> DisableDo >> ensure(for_in, PopDo) >> diff --git a/MoonParser/moon_parser.h b/MoonParser/moon_parser.h index bf618aa..6f9ef8f 100644 --- a/MoonParser/moon_parser.h +++ b/MoonParser/moon_parser.h @@ -21,11 +21,5 @@ struct State size_t stringOpen; std::stack indents; std::stack doStack; - std::unordered_set keywords = { - "and", "while", "else", "using", "continue", - "local", "not", "then", "return", "from", - "extends", "for", "do", "or", "export", - "class", "in", "unless", "when", "elseif", - "switch", "break", "if", "with", "import", "true", "false", "nil" - }; + static std::unordered_set keywords; }; diff --git a/MoonParser/parser.cpp b/MoonParser/parser.cpp index 2378abe..03857c6 100644 --- a/MoonParser/parser.cpp +++ b/MoonParser/parser.cpp @@ -1143,10 +1143,8 @@ expr expr::operator !() const { @param e end position. */ input_range::input_range(const pos &b, const pos &e) : - m_begin(b), - m_end(e) -{ -} +m_begin(b), +m_end(e) {} /** constructor. @@ -1155,10 +1153,8 @@ input_range::input_range(const pos &b, const pos &e) : @param t error type. */ error::error(const pos &b, const pos &e, int t) : - input_range(b, e), - m_type(t) -{ -} +input_range(b, e), +m_type(t) {} /** compare on begin position. diff --git a/MoonParser/parser.hpp b/MoonParser/parser.hpp index cbabf06..ae83215 100644 --- a/MoonParser/parser.hpp +++ b/MoonParser/parser.hpp @@ -31,17 +31,9 @@ inline std::size_t constexpr operator"" _id(const char* s, size_t) } ///type of the parser's input. -typedef std::basic_string input; +typedef std::basic_string input; typedef input::iterator input_it; - -template -struct deletable_facet : Facet -{ - template - deletable_facet(Args&& ...args): Facet(std::forward(args)...) {} - ~deletable_facet() {} -}; -typedef std::wstring_convert>, input::value_type> Converter; +typedef std::wstring_convert> Converter; namespace parserlib { @@ -152,6 +144,8 @@ typedef void (*parse_proc)(const pos &b, const pos &e, void *d); ///input range. class input_range { public: + virtual ~input_range() {} + ///begin position. pos m_begin; @@ -160,7 +154,6 @@ public: ///empty constructor. input_range() {} - virtual ~input_range() {} /** constructor. @param b begin position. -- cgit v1.2.3-55-g6feb