diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/yue.cpp | 132 | ||||
| -rw-r--r-- | src/yuescript/ast.cpp | 70 | ||||
| -rw-r--r-- | src/yuescript/ast.hpp | 95 | ||||
| -rw-r--r-- | src/yuescript/parser.cpp | 80 | ||||
| -rw-r--r-- | src/yuescript/parser.hpp | 15 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 372 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 98 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 1 |
8 files changed, 711 insertions, 152 deletions
diff --git a/src/yue.cpp b/src/yue.cpp index 4bb4e70..8fe2aba 100644 --- a/src/yue.cpp +++ b/src/yue.cpp | |||
| @@ -9,18 +9,25 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
| 9 | #include "yuescript/yue_compiler.h" | 9 | #include "yuescript/yue_compiler.h" |
| 10 | #include "yuescript/yue_parser.h" | 10 | #include "yuescript/yue_parser.h" |
| 11 | 11 | ||
| 12 | #include <algorithm> | ||
| 12 | #include <chrono> | 13 | #include <chrono> |
| 14 | #include <condition_variable> | ||
| 13 | #include <cstdlib> | 15 | #include <cstdlib> |
| 16 | #include <deque> | ||
| 14 | #include <fstream> | 17 | #include <fstream> |
| 18 | #include <functional> | ||
| 15 | #include <future> | 19 | #include <future> |
| 16 | #include <iomanip> | 20 | #include <iomanip> |
| 17 | #include <iostream> | 21 | #include <iostream> |
| 18 | #include <limits> | 22 | #include <limits> |
| 19 | #include <memory> | 23 | #include <memory> |
| 24 | #include <mutex> | ||
| 20 | #include <sstream> | 25 | #include <sstream> |
| 26 | #include <stdexcept> | ||
| 21 | #include <string_view> | 27 | #include <string_view> |
| 22 | #include <thread> | 28 | #include <thread> |
| 23 | #include <tuple> | 29 | #include <tuple> |
| 30 | #include <vector> | ||
| 24 | using namespace std::string_view_literals; | 31 | using namespace std::string_view_literals; |
| 25 | using namespace std::string_literals; | 32 | using namespace std::string_literals; |
| 26 | using namespace std::chrono_literals; | 33 | using namespace std::chrono_literals; |
| @@ -32,35 +39,102 @@ using namespace std::chrono_literals; | |||
| 32 | 39 | ||
| 33 | #if __has_include(<pthread.h>) | 40 | #if __has_include(<pthread.h>) |
| 34 | #include <pthread.h> | 41 | #include <pthread.h> |
| 35 | template<class R> | 42 | #endif |
| 36 | std::future<R> async(const std::function<R()>& f) { | ||
| 37 | using Fn = std::packaged_task<R()>; | ||
| 38 | auto task = new Fn(f); | ||
| 39 | std::future<R> fut = task->get_future(); | ||
| 40 | 43 | ||
| 41 | pthread_attr_t attr; | 44 | class AsyncPool { |
| 42 | pthread_attr_init(&attr); | 45 | public: |
| 43 | pthread_attr_setstacksize(&attr, 8 * 1024 * 1024); | 46 | explicit AsyncPool(size_t workerCount) { |
| 47 | workerCount = std::max<size_t>(workerCount, 1); | ||
| 48 | #if __has_include(<pthread.h>) | ||
| 49 | pthread_attr_t attr; | ||
| 50 | pthread_attr_init(&attr); | ||
| 51 | pthread_attr_setstacksize(&attr, 8 * 1024 * 1024); | ||
| 52 | _workers.reserve(workerCount); | ||
| 53 | for (size_t i = 0; i < workerCount; i++) { | ||
| 54 | pthread_t worker; | ||
| 55 | const int result = pthread_create(&worker, &attr, [](void* data) -> void* { | ||
| 56 | static_cast<AsyncPool*>(data)->run(); | ||
| 57 | return nullptr; | ||
| 58 | }, this); | ||
| 59 | if (result != 0) { | ||
| 60 | { | ||
| 61 | std::lock_guard<std::mutex> lock(_mutex); | ||
| 62 | _stopping = true; | ||
| 63 | } | ||
| 64 | _condition.notify_all(); | ||
| 65 | for (auto createdWorker : _workers) { | ||
| 66 | pthread_join(createdWorker, nullptr); | ||
| 67 | } | ||
| 68 | pthread_attr_destroy(&attr); | ||
| 69 | throw std::runtime_error("failed to create compiler worker thread"); | ||
| 70 | } | ||
| 71 | _workers.push_back(worker); | ||
| 72 | } | ||
| 73 | pthread_attr_destroy(&attr); | ||
| 74 | #else | ||
| 75 | _workers.reserve(workerCount); | ||
| 76 | for (size_t i = 0; i < workerCount; i++) { | ||
| 77 | _workers.emplace_back([this]() { run(); }); | ||
| 78 | } | ||
| 79 | #endif | ||
| 80 | } | ||
| 44 | 81 | ||
| 45 | pthread_t th; | 82 | ~AsyncPool() { |
| 46 | pthread_create(&th, &attr, | 83 | { |
| 47 | [](void* p)->void* { | 84 | std::lock_guard<std::mutex> lock(_mutex); |
| 48 | std::unique_ptr<Fn> fn(static_cast<Fn*>(p)); | 85 | _stopping = true; |
| 49 | (*fn)(); | 86 | } |
| 50 | return nullptr; | 87 | _condition.notify_all(); |
| 51 | }, | 88 | #if __has_include(<pthread.h>) |
| 52 | task); | 89 | for (auto worker : _workers) { |
| 53 | pthread_attr_destroy(&attr); | 90 | pthread_join(worker, nullptr); |
| 54 | pthread_detach(th); | 91 | } |
| 55 | return fut; | ||
| 56 | } | ||
| 57 | #else | 92 | #else |
| 58 | template<class R> | 93 | for (auto& worker : _workers) { |
| 59 | std::future<R> async(const std::function<R()>& f) { | 94 | worker.join(); |
| 60 | // fallback: ignore stack size | 95 | } |
| 61 | return std::async(std::launch::async, f); | ||
| 62 | } | ||
| 63 | #endif | 96 | #endif |
| 97 | } | ||
| 98 | |||
| 99 | template<class R> | ||
| 100 | std::future<R> async(const std::function<R()>& f) { | ||
| 101 | auto task = std::make_shared<std::packaged_task<R()>>(f); | ||
| 102 | auto result = task->get_future(); | ||
| 103 | { | ||
| 104 | std::lock_guard<std::mutex> lock(_mutex); | ||
| 105 | _tasks.emplace_back([task]() { (*task)(); }); | ||
| 106 | } | ||
| 107 | _condition.notify_one(); | ||
| 108 | return result; | ||
| 109 | } | ||
| 110 | |||
| 111 | private: | ||
| 112 | void run() { | ||
| 113 | while (true) { | ||
| 114 | std::function<void()> task; | ||
| 115 | { | ||
| 116 | std::unique_lock<std::mutex> lock(_mutex); | ||
| 117 | _condition.wait(lock, [this]() { | ||
| 118 | return _stopping || !_tasks.empty(); | ||
| 119 | }); | ||
| 120 | if (_stopping && _tasks.empty()) return; | ||
| 121 | task = std::move(_tasks.front()); | ||
| 122 | _tasks.pop_front(); | ||
| 123 | } | ||
| 124 | task(); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | std::mutex _mutex; | ||
| 129 | std::condition_variable _condition; | ||
| 130 | std::deque<std::function<void()>> _tasks; | ||
| 131 | bool _stopping = false; | ||
| 132 | #if __has_include(<pthread.h>) | ||
| 133 | std::vector<pthread_t> _workers; | ||
| 134 | #else | ||
| 135 | std::vector<std::thread> _workers; | ||
| 136 | #endif | ||
| 137 | }; | ||
| 64 | 138 | ||
| 65 | #if not(defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY) | 139 | #if not(defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY) |
| 66 | #define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { \ | 140 | #define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { \ |
| @@ -823,6 +897,10 @@ int main(int narg, const char** args) { | |||
| 823 | } | 897 | } |
| 824 | } | 898 | } |
| 825 | #endif // YUE_COMPILER_ONLY | 899 | #endif // YUE_COMPILER_ONLY |
| 900 | const size_t workerCount = std::min( | ||
| 901 | files.size(), | ||
| 902 | static_cast<size_t>(std::max(1u, std::thread::hardware_concurrency()))); | ||
| 903 | AsyncPool pool(workerCount); | ||
| 826 | #ifndef YUE_NO_WATCHER | 904 | #ifndef YUE_NO_WATCHER |
| 827 | if (watchFiles) { | 905 | if (watchFiles) { |
| 828 | auto fullWorkPath = fs::absolute(fs::path(workPath)).string(); | 906 | auto fullWorkPath = fs::absolute(fs::path(workPath)).string(); |
| @@ -832,7 +910,7 @@ int main(int narg, const char** args) { | |||
| 832 | } | 910 | } |
| 833 | std::list<std::future<std::string>> results; | 911 | std::list<std::future<std::string>> results; |
| 834 | for (const auto& file : files) { | 912 | for (const auto& file : files) { |
| 835 | auto task = async<std::string>([=]() { | 913 | auto task = pool.async<std::string>([=]() { |
| 836 | #ifndef YUE_COMPILER_ONLY | 914 | #ifndef YUE_COMPILER_ONLY |
| 837 | return compileFile(fs::absolute(file.first), config, fullWorkPath, fullTargetPath, minify, rewrite); | 915 | return compileFile(fs::absolute(file.first), config, fullWorkPath, fullTargetPath, minify, rewrite); |
| 838 | #else | 916 | #else |
| @@ -870,7 +948,7 @@ int main(int narg, const char** args) { | |||
| 870 | #endif // YUE_NO_WATCHER | 948 | #endif // YUE_NO_WATCHER |
| 871 | std::list<std::future<std::tuple<int, std::string, std::string>>> results; | 949 | std::list<std::future<std::tuple<int, std::string, std::string>>> results; |
| 872 | for (const auto& file : files) { | 950 | for (const auto& file : files) { |
| 873 | auto task = async<std::tuple<int, std::string, std::string>>([=]() { | 951 | auto task = pool.async<std::tuple<int, std::string, std::string>>([=]() { |
| 874 | std::ifstream input(file.first, std::ios::in); | 952 | std::ifstream input(file.first, std::ios::in); |
| 875 | if (input) { | 953 | if (input) { |
| 876 | std::string s( | 954 | std::string s( |
diff --git a/src/yuescript/ast.cpp b/src/yuescript/ast.cpp index 99ab8f5..1de2071 100644 --- a/src/yuescript/ast.cpp +++ b/src/yuescript/ast.cpp | |||
| @@ -9,12 +9,74 @@ Redistributions in binary form must reproduce the above copyright notice, this l | |||
| 9 | 9 | ||
| 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/ |
| 11 | 11 | ||
| 12 | #include <algorithm> | ||
| 12 | #include <cassert> | 13 | #include <cassert> |
| 14 | #include <cstdint> | ||
| 13 | 15 | ||
| 14 | #include "yuescript/ast.hpp" | 16 | #include "yuescript/ast.hpp" |
| 15 | 17 | ||
| 16 | namespace parserlib { | 18 | namespace parserlib { |
| 17 | 19 | ||
| 20 | namespace { | ||
| 21 | |||
| 22 | thread_local ast_arena* currentAstArena = nullptr; | ||
| 23 | |||
| 24 | struct alignas(std::max_align_t) ast_allocation_header { | ||
| 25 | ast_arena* arena = nullptr; | ||
| 26 | }; | ||
| 27 | |||
| 28 | } // namespace | ||
| 29 | |||
| 30 | void* ast_arena::allocate(size_t size, size_t alignment) { | ||
| 31 | constexpr size_t BlockSize = 1024 * 1024; | ||
| 32 | auto tryAllocate = [size, alignment](block& item) -> void* { | ||
| 33 | auto address = reinterpret_cast<uintptr_t>(item.data.get() + item.used); | ||
| 34 | auto aligned = (address + alignment - 1) & ~(alignment - 1); | ||
| 35 | auto offset = static_cast<size_t>(aligned - reinterpret_cast<uintptr_t>(item.data.get())); | ||
| 36 | if (offset + size > item.size) return nullptr; | ||
| 37 | item.used = offset + size; | ||
| 38 | return item.data.get() + offset; | ||
| 39 | }; | ||
| 40 | if (!_blocks.empty()) { | ||
| 41 | if (auto ptr = tryAllocate(_blocks.back())) return ptr; | ||
| 42 | } | ||
| 43 | block item; | ||
| 44 | item.size = std::max(BlockSize, size + alignment - 1); | ||
| 45 | item.data = std::unique_ptr<std::byte[]>(new std::byte[item.size]); | ||
| 46 | _blocks.push_back(std::move(item)); | ||
| 47 | return tryAllocate(_blocks.back()); | ||
| 48 | } | ||
| 49 | |||
| 50 | ast_arena_scope::ast_arena_scope(ast_arena& arena) | ||
| 51 | : _previous(currentAstArena) { | ||
| 52 | currentAstArena = &arena; | ||
| 53 | } | ||
| 54 | |||
| 55 | ast_arena_scope::~ast_arena_scope() { | ||
| 56 | currentAstArena = _previous; | ||
| 57 | } | ||
| 58 | |||
| 59 | void* ast_node::operator new(size_t size) { | ||
| 60 | const auto allocationSize = sizeof(ast_allocation_header) + size; | ||
| 61 | ast_allocation_header* header = nullptr; | ||
| 62 | if (currentAstArena) { | ||
| 63 | header = static_cast<ast_allocation_header*>( | ||
| 64 | currentAstArena->allocate(allocationSize, alignof(ast_allocation_header))); | ||
| 65 | header->arena = currentAstArena; | ||
| 66 | } else { | ||
| 67 | header = static_cast<ast_allocation_header*>(::operator new(allocationSize)); | ||
| 68 | } | ||
| 69 | return header + 1; | ||
| 70 | } | ||
| 71 | |||
| 72 | void ast_node::operator delete(void* ptr) noexcept { | ||
| 73 | if (!ptr) return; | ||
| 74 | auto header = static_cast<ast_allocation_header*>(ptr) - 1; | ||
| 75 | if (!header->arena) { | ||
| 76 | ::operator delete(header); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 18 | traversal ast_node::traverse(const std::function<traversal(ast_node*)>& func) { | 80 | traversal ast_node::traverse(const std::function<traversal(ast_node*)>& func) { |
| 19 | return func(this); | 81 | return func(this); |
| 20 | } | 82 | } |
| @@ -125,9 +187,9 @@ bool ast_container::visit_child(const std::function<bool(ast_node*)>& func) { | |||
| 125 | @return pointer to ast node created, or null if there was an error. | 187 | @return pointer to ast node created, or null if there was an error. |
| 126 | The return object must be deleted by the caller. | 188 | The return object must be deleted by the caller. |
| 127 | */ | 189 | */ |
| 128 | ast_node* parse(input& i, rule& g, error_list& el, void* ud) { | 190 | ast_node* parse(input& i, rule& g, error_list& el, void* ud, bool resolveLeftRecursion) { |
| 129 | ast_stack st; | 191 | ast_stack st; |
| 130 | if (!parse(i, g, el, &st, ud)) { | 192 | if (!parse(i, g, el, &st, ud, resolveLeftRecursion)) { |
| 131 | for (auto node : st) { | 193 | for (auto node : st) { |
| 132 | delete node; | 194 | delete node; |
| 133 | } | 195 | } |
| @@ -146,9 +208,9 @@ ast_node* parse(input& i, rule& g, error_list& el, void* ud) { | |||
| 146 | @param ud user data, passed to the parse procedures. | 208 | @param ud user data, passed to the parse procedures. |
| 147 | @return true on parsing success, false on failure. | 209 | @return true on parsing success, false on failure. |
| 148 | */ | 210 | */ |
| 149 | ast_node* start_with(input& i, rule& g, error_list& el, void* ud) { | 211 | ast_node* start_with(input& i, rule& g, error_list& el, void* ud, bool resolveLeftRecursion) { |
| 150 | ast_stack st; | 212 | ast_stack st; |
| 151 | if (!start_with(i, g, el, &st, ud)) { | 213 | if (!start_with(i, g, el, &st, ud, resolveLeftRecursion)) { |
| 152 | for (auto node : st) { | 214 | for (auto node : st) { |
| 153 | delete node; | 215 | delete node; |
| 154 | } | 216 | } |
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index b3b0d23..1985b84 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp | |||
| @@ -11,12 +11,17 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
| 11 | 11 | ||
| 12 | #pragma once | 12 | #pragma once |
| 13 | 13 | ||
| 14 | #include <array> | ||
| 14 | #include <cassert> | 15 | #include <cassert> |
| 15 | #include <list> | 16 | #include <cstddef> |
| 16 | #include <deque> | 17 | #include <deque> |
| 18 | #include <iterator> | ||
| 19 | #include <list> | ||
| 20 | #include <memory> | ||
| 17 | #include <stdexcept> | 21 | #include <stdexcept> |
| 18 | #include <string_view> | 22 | #include <string_view> |
| 19 | #include <type_traits> | 23 | #include <type_traits> |
| 24 | #include <vector> | ||
| 20 | 25 | ||
| 21 | #include "yuescript/parser.hpp" | 26 | #include "yuescript/parser.hpp" |
| 22 | 27 | ||
| @@ -25,6 +30,7 @@ namespace parserlib { | |||
| 25 | using namespace std::string_view_literals; | 30 | using namespace std::string_view_literals; |
| 26 | 31 | ||
| 27 | class ast_node; | 32 | class ast_node; |
| 33 | class ast_arena; | ||
| 28 | template <bool Required, class T> | 34 | template <bool Required, class T> |
| 29 | class ast_ptr; | 35 | class ast_ptr; |
| 30 | template <bool Required, class T> | 36 | template <bool Required, class T> |
| @@ -63,10 +69,41 @@ enum class traversal { | |||
| 63 | Stop | 69 | Stop |
| 64 | }; | 70 | }; |
| 65 | 71 | ||
| 72 | class ast_arena { | ||
| 73 | public: | ||
| 74 | ast_arena() = default; | ||
| 75 | ast_arena(const ast_arena&) = delete; | ||
| 76 | ast_arena& operator=(const ast_arena&) = delete; | ||
| 77 | |||
| 78 | void* allocate(size_t size, size_t alignment); | ||
| 79 | |||
| 80 | private: | ||
| 81 | struct block { | ||
| 82 | std::unique_ptr<std::byte[]> data; | ||
| 83 | size_t size = 0; | ||
| 84 | size_t used = 0; | ||
| 85 | }; | ||
| 86 | std::vector<block> _blocks; | ||
| 87 | }; | ||
| 88 | |||
| 89 | class ast_arena_scope { | ||
| 90 | public: | ||
| 91 | explicit ast_arena_scope(ast_arena& arena); | ||
| 92 | ~ast_arena_scope(); | ||
| 93 | ast_arena_scope(const ast_arena_scope&) = delete; | ||
| 94 | ast_arena_scope& operator=(const ast_arena_scope&) = delete; | ||
| 95 | |||
| 96 | private: | ||
| 97 | ast_arena* _previous = nullptr; | ||
| 98 | }; | ||
| 99 | |||
| 66 | /** Base class for AST nodes. | 100 | /** Base class for AST nodes. |
| 67 | */ | 101 | */ |
| 68 | class ast_node : public input_range { | 102 | class ast_node : public input_range { |
| 69 | public: | 103 | public: |
| 104 | static void* operator new(size_t size); | ||
| 105 | static void operator delete(void* ptr) noexcept; | ||
| 106 | |||
| 70 | ast_node() | 107 | ast_node() |
| 71 | : _ref(0) { } | 108 | : _ref(0) { } |
| 72 | 109 | ||
| @@ -154,15 +191,59 @@ bool ast_is(ast_node* node) { | |||
| 154 | 191 | ||
| 155 | class ast_member; | 192 | class ast_member; |
| 156 | 193 | ||
| 157 | /** type of ast member vector. | 194 | class ast_member_vector { |
| 158 | */ | 195 | public: |
| 159 | typedef std::vector<ast_member*> ast_member_vector; | 196 | using iterator = ast_member**; |
| 197 | using const_iterator = ast_member* const*; | ||
| 198 | using reverse_iterator = std::reverse_iterator<iterator>; | ||
| 199 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; | ||
| 200 | |||
| 201 | void reserve(size_t size) { | ||
| 202 | if (size <= InlineCapacity) return; | ||
| 203 | if (_heap) { | ||
| 204 | _overflow.reserve(size); | ||
| 205 | } else { | ||
| 206 | _overflow.reserve(size); | ||
| 207 | for (size_t i = 0; i < _size; i++) _overflow.push_back(_inline[i]); | ||
| 208 | _heap = true; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | void push_back(ast_member* member) { | ||
| 213 | if (_heap) { | ||
| 214 | _overflow.push_back(member); | ||
| 215 | } else if (_size < InlineCapacity) { | ||
| 216 | _inline[_size] = member; | ||
| 217 | } else { | ||
| 218 | reserve(_size + 1); | ||
| 219 | _overflow.push_back(member); | ||
| 220 | } | ||
| 221 | _size++; | ||
| 222 | } | ||
| 223 | |||
| 224 | iterator begin() { return _heap ? _overflow.data() : _inline.data(); } | ||
| 225 | iterator end() { return begin() + _size; } | ||
| 226 | const_iterator begin() const { return _heap ? _overflow.data() : _inline.data(); } | ||
| 227 | const_iterator end() const { return begin() + _size; } | ||
| 228 | reverse_iterator rbegin() { return reverse_iterator(end()); } | ||
| 229 | reverse_iterator rend() { return reverse_iterator(begin()); } | ||
| 230 | const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } | ||
| 231 | const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } | ||
| 232 | |||
| 233 | private: | ||
| 234 | static constexpr size_t InlineCapacity = 3; | ||
| 235 | std::array<ast_member*, InlineCapacity> _inline{}; | ||
| 236 | std::vector<ast_member*> _overflow; | ||
| 237 | size_t _size = 0; | ||
| 238 | bool _heap = false; | ||
| 239 | }; | ||
| 160 | 240 | ||
| 161 | /** base class for AST nodes with children. | 241 | /** base class for AST nodes with children. |
| 162 | */ | 242 | */ |
| 163 | class ast_container : public ast_node { | 243 | class ast_container : public ast_node { |
| 164 | public: | 244 | public: |
| 165 | void add_members(std::initializer_list<ast_member*> members) { | 245 | void add_members(std::initializer_list<ast_member*> members) { |
| 246 | m_members.reserve(members.size()); | ||
| 166 | for (auto member : members) { | 247 | for (auto member : members) { |
| 167 | m_members.push_back(member); | 248 | m_members.push_back(member); |
| 168 | } | 249 | } |
| @@ -595,10 +676,11 @@ private: | |||
| 595 | @param g root rule of grammar. | 676 | @param g root rule of grammar. |
| 596 | @param el list of errors. | 677 | @param el list of errors. |
| 597 | @param ud user data, passed to the parse procedures. | 678 | @param ud user data, passed to the parse procedures. |
| 679 | @param resolveLeftRecursion enables the general left-recursion resolver. | ||
| 598 | @return pointer to ast node created, or null if there was an error. | 680 | @return pointer to ast node created, or null if there was an error. |
| 599 | The return object must be deleted by the caller. | 681 | The return object must be deleted by the caller. |
| 600 | */ | 682 | */ |
| 601 | ast_node* parse(input& i, rule& g, error_list& el, void* ud); | 683 | ast_node* parse(input& i, rule& g, error_list& el, void* ud, bool resolveLeftRecursion = true); |
| 602 | 684 | ||
| 603 | /** check if the start part of given input matches grammar. | 685 | /** check if the start part of given input matches grammar. |
| 604 | The parse procedures of each rule parsed are executed | 686 | The parse procedures of each rule parsed are executed |
| @@ -606,8 +688,9 @@ ast_node* parse(input& i, rule& g, error_list& el, void* ud); | |||
| 606 | @param i input. | 688 | @param i input. |
| 607 | @param g root rule of grammar. | 689 | @param g root rule of grammar. |
| 608 | @param ud user data, passed to the parse procedures. | 690 | @param ud user data, passed to the parse procedures. |
| 691 | @param resolveLeftRecursion enables the general left-recursion resolver. | ||
| 609 | @return true on parsing success, false on failure. | 692 | @return true on parsing success, false on failure. |
| 610 | */ | 693 | */ |
| 611 | ast_node* start_with(input& i, rule& g, error_list& el, void* ud); | 694 | ast_node* start_with(input& i, rule& g, error_list& el, void* ud, bool resolveLeftRecursion = true); |
| 612 | 695 | ||
| 613 | } // namespace parserlib | 696 | } // namespace parserlib |
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp index 5910348..ae7b9a2 100644 --- a/src/yuescript/parser.cpp +++ b/src/yuescript/parser.cpp | |||
| @@ -38,6 +38,20 @@ namespace CodeCvt { | |||
| 38 | namespace parserlib { | 38 | namespace parserlib { |
| 39 | 39 | ||
| 40 | input utf8_decode(const std::string& str) { | 40 | input utf8_decode(const std::string& str) { |
| 41 | bool ascii = true; | ||
| 42 | for (unsigned char ch : str) { | ||
| 43 | if (ch >= 0x80) { | ||
| 44 | ascii = false; | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | if (ascii) { | ||
| 49 | input result(str.size(), char32_t{}); | ||
| 50 | for (size_t i = 0; i < str.size(); i++) { | ||
| 51 | result[i] = static_cast<unsigned char>(str[i]); | ||
| 52 | } | ||
| 53 | return result; | ||
| 54 | } | ||
| 41 | return CodeCvt::utf8to32(str); | 55 | return CodeCvt::utf8to32(str); |
| 42 | } | 56 | } |
| 43 | 57 | ||
| @@ -131,13 +145,17 @@ public: | |||
| 131 | // matches | 145 | // matches |
| 132 | _match_vector m_matches; | 146 | _match_vector m_matches; |
| 133 | 147 | ||
| 148 | // whether to resolve left-recursive rules | ||
| 149 | bool m_resolve_left_recursion; | ||
| 150 | |||
| 134 | // constructor | 151 | // constructor |
| 135 | _context(input& i, void* ud) | 152 | _context(input& i, void* ud, bool resolveLeftRecursion) |
| 136 | : m_user_data(ud) | 153 | : m_user_data(ud) |
| 137 | , m_pos(i) | 154 | , m_pos(i) |
| 138 | , m_error_pos(i) | 155 | , m_error_pos(i) |
| 139 | , m_begin(i.begin()) | 156 | , m_begin(i.begin()) |
| 140 | , m_end(i.end()) { | 157 | , m_end(i.end()) |
| 158 | , m_resolve_left_recursion(resolveLeftRecursion) { | ||
| 141 | } | 159 | } |
| 142 | 160 | ||
| 143 | // check if the end is reached | 161 | // check if the end is reached |
| @@ -451,7 +469,7 @@ public: | |||
| 451 | virtual bool parse_non_term(_context& con) const override { | 469 | virtual bool parse_non_term(_context& con) const override { |
| 452 | pos pos = con.m_pos; | 470 | pos pos = con.m_pos; |
| 453 | if (m_expr->parse_non_term(con)) { | 471 | if (m_expr->parse_non_term(con)) { |
| 454 | item_t item = {&pos, &con.m_pos, con.m_user_data}; | 472 | item_t item = {&pos, &con.m_pos, con.m_user_data, con.m_begin, con.m_end}; |
| 455 | return m_handler(item); | 473 | return m_handler(item); |
| 456 | } | 474 | } |
| 457 | return false; | 475 | return false; |
| @@ -461,7 +479,7 @@ public: | |||
| 461 | virtual bool parse_term(_context& con) const override { | 479 | virtual bool parse_term(_context& con) const override { |
| 462 | pos pos = con.m_pos; | 480 | pos pos = con.m_pos; |
| 463 | if (m_expr->parse_term(con)) { | 481 | if (m_expr->parse_term(con)) { |
| 464 | item_t item = {&pos, &con.m_pos, con.m_user_data}; | 482 | item_t item = {&pos, &con.m_pos, con.m_user_data, con.m_begin, con.m_end}; |
| 465 | return m_handler(item); | 483 | return m_handler(item); |
| 466 | } | 484 | } |
| 467 | return false; | 485 | return false; |
| @@ -854,6 +872,40 @@ private: | |||
| 854 | rule& m_rule; | 872 | rule& m_rule; |
| 855 | }; | 873 | }; |
| 856 | 874 | ||
| 875 | // predictive rule dispatch | ||
| 876 | class _dispatch : public _expr { | ||
| 877 | public: | ||
| 878 | _dispatch(const dispatch_handler& handler, std::initializer_list<rule*> rules) | ||
| 879 | : m_handler(handler) { | ||
| 880 | m_rules.reserve(rules.size()); | ||
| 881 | for (rule* target : rules) { | ||
| 882 | m_rules.push_back(new _ref(*target)); | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | virtual ~_dispatch() { | ||
| 887 | for (_expr* target : m_rules) { | ||
| 888 | delete target; | ||
| 889 | } | ||
| 890 | } | ||
| 891 | |||
| 892 | virtual bool parse_non_term(_context& con) const override { | ||
| 893 | const size_t index = m_handler(con.m_pos.m_it, con.m_end); | ||
| 894 | if (index >= m_rules.size()) return false; | ||
| 895 | return m_rules[index]->parse_non_term(con); | ||
| 896 | } | ||
| 897 | |||
| 898 | virtual bool parse_term(_context& con) const override { | ||
| 899 | const size_t index = m_handler(con.m_pos.m_it, con.m_end); | ||
| 900 | if (index >= m_rules.size()) return false; | ||
| 901 | return m_rules[index]->parse_term(con); | ||
| 902 | } | ||
| 903 | |||
| 904 | private: | ||
| 905 | dispatch_handler m_handler; | ||
| 906 | std::vector<_expr*> m_rules; | ||
| 907 | }; | ||
| 908 | |||
| 857 | // eof | 909 | // eof |
| 858 | class _eof : public _expr { | 910 | class _eof : public _expr { |
| 859 | public: | 911 | public: |
| @@ -930,6 +982,10 @@ _state::_state(_context& con) | |||
| 930 | 982 | ||
| 931 | // parse non-term rule. | 983 | // parse non-term rule. |
| 932 | bool _context::parse_non_term(rule& r) { | 984 | bool _context::parse_non_term(rule& r) { |
| 985 | if (!m_resolve_left_recursion) { | ||
| 986 | return _parse_non_term(r); | ||
| 987 | } | ||
| 988 | |||
| 933 | // save the state of the rule | 989 | // save the state of the rule |
| 934 | rule::_state old_state = r.m_state; | 990 | rule::_state old_state = r.m_state; |
| 935 | // restore the rule's state | 991 | // restore the rule's state |
| @@ -1024,6 +1080,10 @@ bool _context::parse_non_term(rule& r) { | |||
| 1024 | 1080 | ||
| 1025 | // parse term rule. | 1081 | // parse term rule. |
| 1026 | bool _context::parse_term(rule& r) { | 1082 | bool _context::parse_term(rule& r) { |
| 1083 | if (!m_resolve_left_recursion) { | ||
| 1084 | return _parse_term(r); | ||
| 1085 | } | ||
| 1086 | |||
| 1027 | // save the state of the rule | 1087 | // save the state of the rule |
| 1028 | rule::_state old_state = r.m_state; | 1088 | rule::_state old_state = r.m_state; |
| 1029 | // restore the rule's state | 1089 | // restore the rule's state |
| @@ -1619,6 +1679,10 @@ expr user(const expr& e, const user_handler& handler) { | |||
| 1619 | return _private::construct_expr(new _user(_private::get_expr(e), handler)); | 1679 | return _private::construct_expr(new _user(_private::get_expr(e), handler)); |
| 1620 | } | 1680 | } |
| 1621 | 1681 | ||
| 1682 | expr dispatch(const dispatch_handler& handler, std::initializer_list<rule*> rules) { | ||
| 1683 | return _private::construct_expr(new _dispatch(handler, rules)); | ||
| 1684 | } | ||
| 1685 | |||
| 1622 | /** parses the given input. | 1686 | /** parses the given input. |
| 1623 | The parse procedures of each rule parsed are executed | 1687 | The parse procedures of each rule parsed are executed |
| 1624 | before this function returns, if parsing succeeds. | 1688 | before this function returns, if parsing succeeds. |
| @@ -1629,9 +1693,9 @@ expr user(const expr& e, const user_handler& handler) { | |||
| 1629 | @param ud user data, passed to the parse procedures. | 1693 | @param ud user data, passed to the parse procedures. |
| 1630 | @return true on parsing success, false on failure. | 1694 | @return true on parsing success, false on failure. |
| 1631 | */ | 1695 | */ |
| 1632 | bool parse(input& i, rule& g, error_list& el, void* st, void* ud) { | 1696 | bool parse(input& i, rule& g, error_list& el, void* st, void* ud, bool resolveLeftRecursion) { |
| 1633 | // prepare context | 1697 | // prepare context |
| 1634 | _context con(i, ud); | 1698 | _context con(i, ud, resolveLeftRecursion); |
| 1635 | 1699 | ||
| 1636 | // parse grammar | 1700 | // parse grammar |
| 1637 | if (!con.parse_non_term(g)) { | 1701 | if (!con.parse_non_term(g)) { |
| @@ -1664,9 +1728,9 @@ bool parse(input& i, rule& g, error_list& el, void* st, void* ud) { | |||
| 1664 | @param ud user data, passed to the parse procedures. | 1728 | @param ud user data, passed to the parse procedures. |
| 1665 | @return true on parsing success, false on failure. | 1729 | @return true on parsing success, false on failure. |
| 1666 | */ | 1730 | */ |
| 1667 | bool start_with(input& i, rule& g, error_list& el, void* st, void* ud) { | 1731 | bool start_with(input& i, rule& g, error_list& el, void* st, void* ud, bool resolveLeftRecursion) { |
| 1668 | // prepare context | 1732 | // prepare context |
| 1669 | _context con(i, ud); | 1733 | _context con(i, ud, resolveLeftRecursion); |
| 1670 | 1734 | ||
| 1671 | // parse grammar | 1735 | // parse grammar |
| 1672 | if (!con.parse_non_term(g)) { | 1736 | if (!con.parse_non_term(g)) { |
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp index 4742539..9ce962d 100644 --- a/src/yuescript/parser.hpp +++ b/src/yuescript/parser.hpp | |||
| @@ -18,6 +18,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
| 18 | #endif | 18 | #endif |
| 19 | 19 | ||
| 20 | #include <functional> | 20 | #include <functional> |
| 21 | #include <initializer_list> | ||
| 21 | #include <list> | 22 | #include <list> |
| 22 | #include <locale> | 23 | #include <locale> |
| 23 | #include <string> | 24 | #include <string> |
| @@ -64,8 +65,11 @@ struct item_t { | |||
| 64 | pos* begin; | 65 | pos* begin; |
| 65 | pos* end; | 66 | pos* end; |
| 66 | void* user_data; | 67 | void* user_data; |
| 68 | input_it input_begin; | ||
| 69 | input_it input_end; | ||
| 67 | }; | 70 | }; |
| 68 | typedef std::function<bool(const item_t&)> user_handler; | 71 | typedef std::function<bool(const item_t&)> user_handler; |
| 72 | typedef std::function<size_t(input_it, input_it)> dispatch_handler; | ||
| 69 | 73 | ||
| 70 | /** a grammar expression. | 74 | /** a grammar expression. |
| 71 | */ | 75 | */ |
| @@ -402,6 +406,11 @@ expr false_(); | |||
| 402 | */ | 406 | */ |
| 403 | expr user(const expr& e, const user_handler& handler); | 407 | expr user(const expr& e, const user_handler& handler); |
| 404 | 408 | ||
| 409 | /** selects one rule without probing the other alternatives. | ||
| 410 | @return an expression that parses the selected rule. | ||
| 411 | */ | ||
| 412 | expr dispatch(const dispatch_handler& handler, std::initializer_list<rule*> rules); | ||
| 413 | |||
| 405 | /** parses the given input. | 414 | /** parses the given input. |
| 406 | The parse procedures of each rule parsed are executed | 415 | The parse procedures of each rule parsed are executed |
| 407 | before this function returns, if parsing succeeds. | 416 | before this function returns, if parsing succeeds. |
| @@ -410,9 +419,10 @@ expr user(const expr& e, const user_handler& handler); | |||
| 410 | @param el list of errors. | 419 | @param el list of errors. |
| 411 | @param st ast object stack. | 420 | @param st ast object stack. |
| 412 | @param ud user data, passed to the parse procedures. | 421 | @param ud user data, passed to the parse procedures. |
| 422 | @param resolveLeftRecursion enables the general left-recursion resolver. | ||
| 413 | @return true on parsing success, false on failure. | 423 | @return true on parsing success, false on failure. |
| 414 | */ | 424 | */ |
| 415 | bool parse(input& i, rule& g, error_list& el, void* st, void* ud); | 425 | bool parse(input& i, rule& g, error_list& el, void* st, void* ud, bool resolveLeftRecursion = true); |
| 416 | 426 | ||
| 417 | /** check if the start part of given input matches grammar. | 427 | /** check if the start part of given input matches grammar. |
| 418 | The parse procedures of each rule parsed are executed | 428 | The parse procedures of each rule parsed are executed |
| @@ -422,9 +432,10 @@ bool parse(input& i, rule& g, error_list& el, void* st, void* ud); | |||
| 422 | @param el list of errors. | 432 | @param el list of errors. |
| 423 | @param st ast object stack. | 433 | @param st ast object stack. |
| 424 | @param ud user data, passed to the parse procedures. | 434 | @param ud user data, passed to the parse procedures. |
| 435 | @param resolveLeftRecursion enables the general left-recursion resolver. | ||
| 425 | @return true on parsing success, false on failure. | 436 | @return true on parsing success, false on failure. |
| 426 | */ | 437 | */ |
| 427 | bool start_with(input& i, rule& g, error_list& el, void* st, void* ud); | 438 | bool start_with(input& i, rule& g, error_list& el, void* st, void* ud, bool resolveLeftRecursion = true); |
| 428 | 439 | ||
| 429 | /** output the specific input range to the specific stream. | 440 | /** output the specific input range to the specific stream. |
| 430 | @param stream stream. | 441 | @param stream stream. |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index df260ab..72ae001 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -145,6 +145,8 @@ public: | |||
| 145 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb | 145 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb |
| 146 | BREAK_IF(idx == 0); | 146 | BREAK_IF(idx == 0); |
| 147 | _useModule = true; | 147 | _useModule = true; |
| 148 | lua_rawgeti(L, -1, idx); // tb current | ||
| 149 | _moduleScopeBaseline = static_cast<int>(lua_objlen(L, -1)); | ||
| 148 | BLOCK_END | 150 | BLOCK_END |
| 149 | } | 151 | } |
| 150 | 152 | ||
| @@ -157,6 +159,8 @@ public: | |||
| 157 | #endif // YUE_NO_MACRO | 159 | #endif // YUE_NO_MACRO |
| 158 | 160 | ||
| 159 | CompileInfo compile(std::string_view codes, const YueConfig& config) { | 161 | CompileInfo compile(std::string_view codes, const YueConfig& config) { |
| 162 | ast_arena arena; | ||
| 163 | ast_arena_scope arenaScope(arena); | ||
| 160 | _config = config; | 164 | _config = config; |
| 161 | #ifndef YUE_NO_MACRO | 165 | #ifndef YUE_NO_MACRO |
| 162 | if (L) passOptions(); | 166 | if (L) passOptions(); |
| @@ -337,27 +341,46 @@ public: | |||
| 337 | 341 | ||
| 338 | void clear() { | 342 | void clear() { |
| 339 | _indentOffset = 0; | 343 | _indentOffset = 0; |
| 344 | _funcLevel = 0; | ||
| 345 | _gotoScope = 0; | ||
| 340 | _scopes.clear(); | 346 | _scopes.clear(); |
| 347 | _importedGlobal = nullptr; | ||
| 341 | _codeCache.clear(); | 348 | _codeCache.clear(); |
| 342 | _buf.str(""); | 349 | _buf.str(""); |
| 343 | _buf.clear(); | 350 | _buf.clear(); |
| 344 | _joinBuf.str(""); | 351 | _joinBuf.str(""); |
| 345 | _joinBuf.clear(); | 352 | _joinBuf.clear(); |
| 346 | _globals.clear(); | 353 | _globals.clear(); |
| 354 | _rootDefs.clear(); | ||
| 355 | _labels.clear(); | ||
| 356 | gotos.clear(); | ||
| 357 | _exportedKeys.clear(); | ||
| 358 | _exportedMetaKeys.clear(); | ||
| 347 | _info = {}; | 359 | _info = {}; |
| 348 | _varArgs = {}; | 360 | _varArgs = {}; |
| 349 | _withVars = {}; | 361 | _withVars = {}; |
| 350 | _continueVars = {}; | 362 | _continueVars = {}; |
| 351 | _funcStates = {}; | 363 | _funcStates = {}; |
| 364 | _enableBreakLoop = {}; | ||
| 365 | _gotoScopes = {}; | ||
| 352 | #ifndef YUE_NO_MACRO | 366 | #ifndef YUE_NO_MACRO |
| 353 | if (_useModule) { | 367 | if (_useModule) { |
| 354 | _useModule = false; | 368 | _useModule = false; |
| 355 | if (!_sameModule) { | 369 | int top = lua_gettop(L); |
| 356 | int top = lua_gettop(L); | 370 | DEFER(lua_settop(L, top)); |
| 357 | DEFER(lua_settop(L, top)); | 371 | lua_pushliteral(L, YUE_MODULES); // YUE_MODULES |
| 358 | lua_pushliteral(L, YUE_MODULES); // YUE_MODULES | 372 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], tb |
| 359 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], tb | 373 | int idx = static_cast<int>(lua_objlen(L, -1)); |
| 360 | int idx = static_cast<int>(lua_objlen(L, -1)); | 374 | if (_sameModule) { |
| 375 | if (idx > 0) { | ||
| 376 | lua_rawgeti(L, -1, idx); // tb current | ||
| 377 | while (static_cast<int>(lua_objlen(L, -1)) > _moduleScopeBaseline) { | ||
| 378 | int scopeIndex = static_cast<int>(lua_objlen(L, -1)); | ||
| 379 | lua_pushnil(L); | ||
| 380 | lua_rawseti(L, -2, scopeIndex); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | } else { | ||
| 361 | lua_pushnil(L); // tb nil | 384 | lua_pushnil(L); // tb nil |
| 362 | lua_rawseti(L, -2, idx); // tb[idx] = nil, tb | 385 | lua_rawseti(L, -2, idx); // tb[idx] = nil, tb |
| 363 | } | 386 | } |
| @@ -370,6 +393,7 @@ private: | |||
| 370 | bool _stateOwner = false; | 393 | bool _stateOwner = false; |
| 371 | bool _useModule = false; | 394 | bool _useModule = false; |
| 372 | bool _sameModule = false; | 395 | bool _sameModule = false; |
| 396 | int _moduleScopeBaseline = 0; | ||
| 373 | lua_State* L = nullptr; | 397 | lua_State* L = nullptr; |
| 374 | std::function<void(void*)> _luaOpen; | 398 | std::function<void(void*)> _luaOpen; |
| 375 | #endif // YUE_NO_MACRO | 399 | #endif // YUE_NO_MACRO |
| @@ -1366,6 +1390,130 @@ private: | |||
| 1366 | return ast_ptr<false, T>(res.node.template to<T>()); | 1390 | return ast_ptr<false, T>(res.node.template to<T>()); |
| 1367 | } | 1391 | } |
| 1368 | 1392 | ||
| 1393 | template <class T> | ||
| 1394 | ast_ptr<false, T> makeLeaf(std::string_view codes, ast_node* parent) { | ||
| 1395 | auto converted = std::make_unique<input>(utf8_decode(std::string(codes))); | ||
| 1396 | auto node = parent->new_ptr<T>(); | ||
| 1397 | node->m_begin.m_it = converted->begin(); | ||
| 1398 | node->m_end.m_it = converted->end(); | ||
| 1399 | _codeCache.push_back(std::move(converted)); | ||
| 1400 | return node; | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | ast_ptr<false, Variable_t> makeVariable(std::string_view name, ast_node* parent) { | ||
| 1404 | auto variable = parent->new_ptr<Variable_t>(); | ||
| 1405 | if (std::any_of(name.begin(), name.end(), [](unsigned char ch) { return ch >= 0x80; })) { | ||
| 1406 | variable->name.set(makeLeaf<UnicodeName_t>(name, parent)); | ||
| 1407 | } else { | ||
| 1408 | variable->name.set(makeLeaf<Name_t>(name, parent)); | ||
| 1409 | } | ||
| 1410 | return variable; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | ast_ptr<false, Callable_t> makeVariableCallable(std::string_view name, ast_node* parent) { | ||
| 1414 | auto callable = parent->new_ptr<Callable_t>(); | ||
| 1415 | callable->item.set(makeVariable(name, parent)); | ||
| 1416 | return callable; | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | ast_ptr<false, Value_t> makeConstValue(std::string_view code, ast_node* parent) { | ||
| 1420 | auto simple = parent->new_ptr<SimpleValue_t>(); | ||
| 1421 | simple->value.set(makeLeaf<ConstValue_t>(code, parent)); | ||
| 1422 | auto value = parent->new_ptr<Value_t>(); | ||
| 1423 | value->item.set(simple); | ||
| 1424 | return value; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | ast_ptr<false, Exp_t> makeConstExp(std::string_view code, ast_node* parent) { | ||
| 1428 | auto exp = newExp(makeConstValue(code, parent), parent); | ||
| 1429 | exp->sep.set(parent->new_ptr<Seperator_t>()); | ||
| 1430 | return exp; | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | ast_ptr<false, Exp_t> makeNumberExp(int value, ast_node* parent) { | ||
| 1434 | auto simple = parent->new_ptr<SimpleValue_t>(); | ||
| 1435 | simple->value.set(makeLeaf<Num_t>(std::to_string(value), parent)); | ||
| 1436 | auto exp = newExp(simple, parent); | ||
| 1437 | exp->sep.set(parent->new_ptr<Seperator_t>()); | ||
| 1438 | return exp; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | ast_ptr<false, Exp_t> makeVariableExp(std::string_view name, ast_node* parent) { | ||
| 1442 | auto chain = parent->new_ptr<ChainValue_t>(); | ||
| 1443 | chain->sep.set(parent->new_ptr<Seperator_t>()); | ||
| 1444 | chain->items.push_back(makeVariableCallable(name, parent)); | ||
| 1445 | auto value = parent->new_ptr<Value_t>(); | ||
| 1446 | value->item.set(chain); | ||
| 1447 | auto unary = parent->new_ptr<UnaryExp_t>(); | ||
| 1448 | unary->expos.push_back(value); | ||
| 1449 | auto exp = parent->new_ptr<Exp_t>(); | ||
| 1450 | exp->sep.set(parent->new_ptr<Seperator_t>()); | ||
| 1451 | exp->pipeExprs.push_back(unary); | ||
| 1452 | return exp; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | ast_ptr<false, ExpList_t> makeVariableExpList(std::string_view name, ast_node* parent) { | ||
| 1456 | auto list = parent->new_ptr<ExpList_t>(); | ||
| 1457 | list->sep.set(parent->new_ptr<Seperator_t>()); | ||
| 1458 | list->exprs.push_back(makeVariableExp(name, parent)); | ||
| 1459 | return list; | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | ast_ptr<false, ExpList_t> makeVariableExpList(const str_list& names, ast_node* parent) { | ||
| 1463 | auto list = parent->new_ptr<ExpList_t>(); | ||
| 1464 | list->sep.set(parent->new_ptr<Seperator_t>()); | ||
| 1465 | for (const auto& name : names) { | ||
| 1466 | list->exprs.push_back(makeVariableExp(name, parent)); | ||
| 1467 | } | ||
| 1468 | return list; | ||
| 1469 | } | ||
| 1470 | |||
| 1471 | ast_ptr<false, Goto_t> makeGoto(std::string_view label, ast_node* parent) { | ||
| 1472 | auto node = parent->new_ptr<Goto_t>(); | ||
| 1473 | node->label.set(makeLeaf<UnicodeName_t>(label, parent)); | ||
| 1474 | return node; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | bool startsWithStatementSep(std::string_view codes) const { | ||
| 1478 | size_t index = 0; | ||
| 1479 | while (index < codes.size()) { | ||
| 1480 | while (index < codes.size()) { | ||
| 1481 | switch (codes[index]) { | ||
| 1482 | case ' ': | ||
| 1483 | case '\t': | ||
| 1484 | case '\r': | ||
| 1485 | case '\n': | ||
| 1486 | index++; | ||
| 1487 | continue; | ||
| 1488 | default: | ||
| 1489 | break; | ||
| 1490 | } | ||
| 1491 | break; | ||
| 1492 | } | ||
| 1493 | if (index + 1 >= codes.size() || codes.substr(index, 2) != "--"sv) break; | ||
| 1494 | if (codes.substr(index, 4) == "--[["sv) { | ||
| 1495 | auto close = codes.find("]]"sv, index + 4); | ||
| 1496 | if (close == std::string_view::npos) return false; | ||
| 1497 | index = close + 2; | ||
| 1498 | } else { | ||
| 1499 | auto lineEnd = codes.find_first_of("\r\n"sv, index + 2); | ||
| 1500 | if (lineEnd == std::string_view::npos) return false; | ||
| 1501 | index = lineEnd; | ||
| 1502 | } | ||
| 1503 | } | ||
| 1504 | if (index == codes.size()) return false; | ||
| 1505 | switch (codes[index]) { | ||
| 1506 | case '(': | ||
| 1507 | case '\'': | ||
| 1508 | case '"': | ||
| 1509 | return true; | ||
| 1510 | case '[': | ||
| 1511 | return index + 1 < codes.size() && (codes[index + 1] == '[' || codes[index + 1] == '='); | ||
| 1512 | default: | ||
| 1513 | return false; | ||
| 1514 | } | ||
| 1515 | } | ||
| 1516 | |||
| 1369 | bool isChainValueCall(ChainValue_t* chainValue) const { | 1517 | bool isChainValueCall(ChainValue_t* chainValue) const { |
| 1370 | return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); | 1518 | return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); |
| 1371 | } | 1519 | } |
| @@ -2297,7 +2445,7 @@ private: | |||
| 2297 | for (; i != exprs.end(); ++i) { | 2445 | for (; i != exprs.end(); ++i) { |
| 2298 | auto var = getUnusedName("_obj_"sv); | 2446 | auto var = getUnusedName("_obj_"sv); |
| 2299 | addToScope(var); | 2447 | addToScope(var); |
| 2300 | extraExprs.push_back(toAst<Exp_t>(var, *i)); | 2448 | extraExprs.push_back(makeVariableExp(var, *i)); |
| 2301 | } | 2449 | } |
| 2302 | popScope(); | 2450 | popScope(); |
| 2303 | ast_ptr<true, ast_node> funcCall = values.back(); | 2451 | ast_ptr<true, ast_node> funcCall = values.back(); |
| @@ -2413,7 +2561,7 @@ private: | |||
| 2413 | if (_withVars.empty()) { | 2561 | if (_withVars.empty()) { |
| 2414 | throw CompileError("short table appending must be called within a with block"sv, x); | 2562 | throw CompileError("short table appending must be called within a with block"sv, x); |
| 2415 | } else { | 2563 | } else { |
| 2416 | tmpChain->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue)); | 2564 | tmpChain->items.push_back(makeVariableCallable(_withVars.top(), chainValue)); |
| 2417 | } | 2565 | } |
| 2418 | } | 2566 | } |
| 2419 | auto varName = singleVariableFrom(tmpChain, AccessType::Write); | 2567 | auto varName = singleVariableFrom(tmpChain, AccessType::Write); |
| @@ -2427,7 +2575,7 @@ private: | |||
| 2427 | } | 2575 | } |
| 2428 | auto objVar = getUnusedName("_obj_"sv); | 2576 | auto objVar = getUnusedName("_obj_"sv); |
| 2429 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2577 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| 2430 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | 2578 | newAssignment->expList.set(makeVariableExpList(objVar, x)); |
| 2431 | auto assign = x->new_ptr<Assign_t>(); | 2579 | auto assign = x->new_ptr<Assign_t>(); |
| 2432 | assign->values.push_back(newExp(tmpChain, tmpChain)); | 2580 | assign->values.push_back(newExp(tmpChain, tmpChain)); |
| 2433 | newAssignment->action.set(assign); | 2581 | newAssignment->action.set(assign); |
| @@ -2481,7 +2629,7 @@ private: | |||
| 2481 | break; | 2629 | break; |
| 2482 | } | 2630 | } |
| 2483 | leftVar = getUnusedName("_obj_"sv); | 2631 | leftVar = getUnusedName("_obj_"sv); |
| 2484 | auto tmpAsmt = assignmentFrom(toAst<Exp_t>(leftVar, tmpLeft), tmpLeft, tmpLeft); | 2632 | auto tmpAsmt = assignmentFrom(makeVariableExp(leftVar, tmpLeft), tmpLeft, tmpLeft); |
| 2485 | str_list temp; | 2633 | str_list temp; |
| 2486 | transformAssignment(tmpAsmt, temp); | 2634 | transformAssignment(tmpAsmt, temp); |
| 2487 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | 2635 | auto [beforeAssignment, afterAssignment] = splitAssignment(); |
| @@ -2492,7 +2640,7 @@ private: | |||
| 2492 | throw CompileError("right value missing"sv, values.front()); | 2640 | throw CompileError("right value missing"sv, values.front()); |
| 2493 | } | 2641 | } |
| 2494 | auto newChain = chainValue->new_ptr<ChainValue_t>(); | 2642 | auto newChain = chainValue->new_ptr<ChainValue_t>(); |
| 2495 | newChain->items.push_back(toAst<Callable_t>(leftVar, newChain)); | 2643 | newChain->items.push_back(makeVariableCallable(leftVar, newChain)); |
| 2496 | newChain->items.push_back(chainValue->items.back()); | 2644 | newChain->items.push_back(chainValue->items.back()); |
| 2497 | auto newLeft = newExp(newChain, newChain); | 2645 | auto newLeft = newExp(newChain, newChain); |
| 2498 | auto newAsmt = assignmentFrom(newLeft, *vit, newLeft); | 2646 | auto newAsmt = assignmentFrom(newLeft, *vit, newLeft); |
| @@ -2750,7 +2898,7 @@ private: | |||
| 2750 | if (pair.targetVar.empty() && pair.defVal) { | 2898 | if (pair.targetVar.empty() && pair.defVal) { |
| 2751 | if (needScope) extraScope = true; | 2899 | if (needScope) extraScope = true; |
| 2752 | auto objVar = getUnusedName("_tmp_"sv); | 2900 | auto objVar = getUnusedName("_tmp_"sv); |
| 2753 | auto objExp = toAst<Exp_t>(objVar, pair.target); | 2901 | auto objExp = makeVariableExp(objVar, pair.target); |
| 2754 | leftPairs.push_back({pair.target, objExp.get()}); | 2902 | leftPairs.push_back({pair.target, objExp.get()}); |
| 2755 | pair.target.set(objExp); | 2903 | pair.target.set(objExp); |
| 2756 | pair.targetVar = objVar; | 2904 | pair.targetVar = objVar; |
| @@ -2804,11 +2952,11 @@ private: | |||
| 2804 | pushScope(); | 2952 | pushScope(); |
| 2805 | } | 2953 | } |
| 2806 | objVar = getUnusedName("_obj_"sv); | 2954 | objVar = getUnusedName("_obj_"sv); |
| 2807 | auto newAssignment = assignmentFrom(toAst<Exp_t>(objVar, x), destruct.value, x); | 2955 | auto newAssignment = assignmentFrom(makeVariableExp(objVar, x), destruct.value, x); |
| 2808 | transformAssignment(newAssignment, temp); | 2956 | transformAssignment(newAssignment, temp); |
| 2809 | } | 2957 | } |
| 2810 | auto chain = pair.target->new_ptr<ChainValue_t>(); | 2958 | auto chain = pair.target->new_ptr<ChainValue_t>(); |
| 2811 | chain->items.push_back(toAst<Callable_t>(objVar, chain)); | 2959 | chain->items.push_back(makeVariableCallable(objVar, chain)); |
| 2812 | chain->items.dup(pair.structure->items); | 2960 | chain->items.dup(pair.structure->items); |
| 2813 | auto valueExp = newExp(chain, pair.target); | 2961 | auto valueExp = newExp(chain, pair.target); |
| 2814 | auto newAssignment = assignmentFrom(pair.target, valueExp, x); | 2962 | auto newAssignment = assignmentFrom(pair.target, valueExp, x); |
| @@ -2834,7 +2982,7 @@ private: | |||
| 2834 | if (needScope) extraScope = true; | 2982 | if (needScope) extraScope = true; |
| 2835 | auto objVar = getUnusedName("_tmp_"sv); | 2983 | auto objVar = getUnusedName("_tmp_"sv); |
| 2836 | addToScope(objVar); | 2984 | addToScope(objVar); |
| 2837 | auto objExp = toAst<Exp_t>(objVar, item.target); | 2985 | auto objExp = makeVariableExp(objVar, item.target); |
| 2838 | leftPairs.push_back({item.target, objExp.get()}); | 2986 | leftPairs.push_back({item.target, objExp.get()}); |
| 2839 | item.target.set(objExp); | 2987 | item.target.set(objExp); |
| 2840 | item.targetVar = objVar; | 2988 | item.targetVar = objVar; |
| @@ -2844,7 +2992,7 @@ private: | |||
| 2844 | } | 2992 | } |
| 2845 | popScope(); | 2993 | popScope(); |
| 2846 | if (_parser.match<Name_t>(destruct.valueVar) && isLocal(destruct.valueVar)) { | 2994 | if (_parser.match<Name_t>(destruct.valueVar) && isLocal(destruct.valueVar)) { |
| 2847 | auto callable = toAst<Callable_t>(destruct.valueVar, destruct.value); | 2995 | auto callable = makeVariableCallable(destruct.valueVar, destruct.value); |
| 2848 | for (auto& v : values) { | 2996 | for (auto& v : values) { |
| 2849 | v->items.push_front(callable); | 2997 | v->items.push_front(callable); |
| 2850 | } | 2998 | } |
| @@ -2873,7 +3021,7 @@ private: | |||
| 2873 | pushScope(); | 3021 | pushScope(); |
| 2874 | } | 3022 | } |
| 2875 | auto valVar = getUnusedName("_obj_"sv); | 3023 | auto valVar = getUnusedName("_obj_"sv); |
| 2876 | auto targetVar = toAst<Exp_t>(valVar, destruct.value); | 3024 | auto targetVar = makeVariableExp(valVar, destruct.value); |
| 2877 | auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value); | 3025 | auto newAssignment = assignmentFrom(targetVar, destruct.value, destruct.value); |
| 2878 | transformAssignment(newAssignment, temp); | 3026 | transformAssignment(newAssignment, temp); |
| 2879 | auto callable = singleValueFrom(targetVar)->item.to<ChainValue_t>()->items.front(); | 3027 | auto callable = singleValueFrom(targetVar)->item.to<ChainValue_t>()->items.front(); |
| @@ -3061,7 +3209,7 @@ private: | |||
| 3061 | int rIndex = count - index; | 3209 | int rIndex = count - index; |
| 3062 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); | 3210 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); |
| 3063 | } else { | 3211 | } else { |
| 3064 | indexItem.set(toAst<Exp_t>(std::to_string(index), pair)); | 3212 | indexItem.set(makeNumberExp(index, pair)); |
| 3065 | } | 3213 | } |
| 3066 | if (optional && varDefOnly && !assignable) { | 3214 | if (optional && varDefOnly && !assignable) { |
| 3067 | if (defVal) { | 3215 | if (defVal) { |
| @@ -3112,7 +3260,7 @@ private: | |||
| 3112 | auto name = _parser.toString(vp->name); | 3260 | auto name = _parser.toString(vp->name); |
| 3113 | auto uname = vp->name->name.as<UnicodeName_t>(); | 3261 | auto uname = vp->name->name.as<UnicodeName_t>(); |
| 3114 | auto chain = toAst<ChainValue_t>('.' + name, vp->name); | 3262 | auto chain = toAst<ChainValue_t>('.' + name, vp->name); |
| 3115 | pairs.push_back({toAst<Exp_t>(name, vp).get(), | 3263 | pairs.push_back({makeVariableExp(name, vp).get(), |
| 3116 | uname ? variableToString(vp->name) : name, | 3264 | uname ? variableToString(vp->name) : name, |
| 3117 | chain, | 3265 | chain, |
| 3118 | defVal}); | 3266 | defVal}); |
| @@ -3222,7 +3370,7 @@ private: | |||
| 3222 | int rIndex = count - index; | 3370 | int rIndex = count - index; |
| 3223 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); | 3371 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); |
| 3224 | } else { | 3372 | } else { |
| 3225 | indexItem.set(toAst<Exp_t>(std::to_string(index), tb)); | 3373 | indexItem.set(makeNumberExp(index, tb)); |
| 3226 | } | 3374 | } |
| 3227 | for (auto& p : subPairs) { | 3375 | for (auto& p : subPairs) { |
| 3228 | if (sep) p.structure->items.push_front(sep); | 3376 | if (sep) p.structure->items.push_front(sep); |
| @@ -3309,7 +3457,7 @@ private: | |||
| 3309 | auto slice = toAst<Slice_t>( | 3457 | auto slice = toAst<Slice_t>( |
| 3310 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); | 3458 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); |
| 3311 | chain->items.push_back(slice); | 3459 | chain->items.push_back(slice); |
| 3312 | auto nil = toAst<Exp_t>("nil"sv, slice); | 3460 | auto nil = makeConstExp("nil"sv, slice); |
| 3313 | pairs.push_back({exp, | 3461 | pairs.push_back({exp, |
| 3314 | varName, | 3462 | varName, |
| 3315 | chain, | 3463 | chain, |
| @@ -3357,7 +3505,7 @@ private: | |||
| 3357 | size_t size = std::max(exprs.size(), values.size()); | 3505 | size_t size = std::max(exprs.size(), values.size()); |
| 3358 | ast_ptr<false, Exp_t> nil; | 3506 | ast_ptr<false, Exp_t> nil; |
| 3359 | if (values.size() < size) { | 3507 | if (values.size() < size) { |
| 3360 | nil = toAst<Exp_t>("nil"sv, x); | 3508 | nil = makeConstExp("nil"sv, x); |
| 3361 | while (values.size() < size) values.emplace_back(nil); | 3509 | while (values.size() < size) values.emplace_back(nil); |
| 3362 | } | 3510 | } |
| 3363 | using iter = node_container::iterator; | 3511 | using iter = node_container::iterator; |
| @@ -3548,7 +3696,7 @@ private: | |||
| 3548 | auto objVar = getUnusedName("_obj_"sv); | 3696 | auto objVar = getUnusedName("_obj_"sv); |
| 3549 | addToScope(objVar); | 3697 | addToScope(objVar); |
| 3550 | valueItems.pop_back(); | 3698 | valueItems.pop_back(); |
| 3551 | valueItems.push_back(toAst<Exp_t>(objVar, *j)); | 3699 | valueItems.push_back(makeVariableExp(objVar, *j)); |
| 3552 | auto expList = x->new_ptr<ExpList_t>(); | 3700 | auto expList = x->new_ptr<ExpList_t>(); |
| 3553 | auto newAssign = x->new_ptr<ExpListAssign_t>(); | 3701 | auto newAssign = x->new_ptr<ExpListAssign_t>(); |
| 3554 | newAssign->expList.set(expList); | 3702 | newAssign->expList.set(expList); |
| @@ -3676,7 +3824,7 @@ private: | |||
| 3676 | auto assign = des.inlineAssignment->action.to<Assign_t>(); | 3824 | auto assign = des.inlineAssignment->action.to<Assign_t>(); |
| 3677 | auto tmpVar = getUnusedName("_tmp_"sv); | 3825 | auto tmpVar = getUnusedName("_tmp_"sv); |
| 3678 | forceAddToScope(tmpVar); | 3826 | forceAddToScope(tmpVar); |
| 3679 | auto tmpExp = toAst<Exp_t>(tmpVar, exp); | 3827 | auto tmpExp = makeVariableExp(tmpVar, exp); |
| 3680 | assignList->exprs.push_back(tmpExp); | 3828 | assignList->exprs.push_back(tmpExp); |
| 3681 | auto vExp = exp->new_ptr<Exp_t>(); | 3829 | auto vExp = exp->new_ptr<Exp_t>(); |
| 3682 | vExp->pipeExprs.dup(exp->pipeExprs); | 3830 | vExp->pipeExprs.dup(exp->pipeExprs); |
| @@ -3740,13 +3888,13 @@ private: | |||
| 3740 | auto exp = newExp(tmpChain, x); | 3888 | auto exp = newExp(tmpChain, x); |
| 3741 | auto objVar = getUnusedName("_obj_"sv); | 3889 | auto objVar = getUnusedName("_obj_"sv); |
| 3742 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 3890 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| 3743 | newAssignment->expList.set(toAst<ExpList_t>(objVar, x)); | 3891 | newAssignment->expList.set(makeVariableExpList(objVar, x)); |
| 3744 | auto assign = x->new_ptr<Assign_t>(); | 3892 | auto assign = x->new_ptr<Assign_t>(); |
| 3745 | assign->values.push_back(exp); | 3893 | assign->values.push_back(exp); |
| 3746 | newAssignment->action.set(assign); | 3894 | newAssignment->action.set(assign); |
| 3747 | transformAssignment(newAssignment, temp); | 3895 | transformAssignment(newAssignment, temp); |
| 3748 | chain->items.clear(); | 3896 | chain->items.clear(); |
| 3749 | chain->items.push_back(toAst<Callable_t>(objVar, x)); | 3897 | chain->items.push_back(makeVariableCallable(objVar, x)); |
| 3750 | chain->items.push_back(ptr); | 3898 | chain->items.push_back(ptr); |
| 3751 | } | 3899 | } |
| 3752 | BLOCK_END | 3900 | BLOCK_END |
| @@ -3760,12 +3908,12 @@ private: | |||
| 3760 | BREAK_IF(!var.empty()); | 3908 | BREAK_IF(!var.empty()); |
| 3761 | auto upVar = getUnusedName("_update_"sv); | 3909 | auto upVar = getUnusedName("_update_"sv); |
| 3762 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 3910 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| 3763 | newAssignment->expList.set(toAst<ExpList_t>(upVar, x)); | 3911 | newAssignment->expList.set(makeVariableExpList(upVar, x)); |
| 3764 | auto assign = x->new_ptr<Assign_t>(); | 3912 | auto assign = x->new_ptr<Assign_t>(); |
| 3765 | assign->values.push_back(exp); | 3913 | assign->values.push_back(exp); |
| 3766 | newAssignment->action.set(assign); | 3914 | newAssignment->action.set(assign); |
| 3767 | transformAssignment(newAssignment, temp); | 3915 | transformAssignment(newAssignment, temp); |
| 3768 | tmpChain->items.push_back(toAst<Exp_t>(upVar, x)); | 3916 | tmpChain->items.push_back(makeVariableExp(upVar, x)); |
| 3769 | itemAdded = true; | 3917 | itemAdded = true; |
| 3770 | BLOCK_END | 3918 | BLOCK_END |
| 3771 | if (!itemAdded) tmpChain->items.push_back(item); | 3919 | if (!itemAdded) tmpChain->items.push_back(item); |
| @@ -3882,7 +4030,7 @@ private: | |||
| 3882 | if (*it != nodes.front() && cond->assignment) { | 4030 | if (*it != nodes.front() && cond->assignment) { |
| 3883 | auto x = *it; | 4031 | auto x = *it; |
| 3884 | auto newIf = x->new_ptr<If_t>(); | 4032 | auto newIf = x->new_ptr<If_t>(); |
| 3885 | newIf->type.set(toAst<IfType_t>("if"sv, x)); | 4033 | newIf->type.set(makeLeaf<IfType_t>("if"sv, x)); |
| 3886 | for (auto j = ns.rbegin(); j != ns.rend(); ++j) { | 4034 | for (auto j = ns.rbegin(); j != ns.rend(); ++j) { |
| 3887 | newIf->nodes.push_back(*j); | 4035 | newIf->nodes.push_back(*j); |
| 3888 | } | 4036 | } |
| @@ -3903,7 +4051,7 @@ private: | |||
| 3903 | if (nodes.size() != ns.size()) { | 4051 | if (nodes.size() != ns.size()) { |
| 3904 | auto x = ns.back(); | 4052 | auto x = ns.back(); |
| 3905 | auto newIf = x->new_ptr<If_t>(); | 4053 | auto newIf = x->new_ptr<If_t>(); |
| 3906 | newIf->type.set(toAst<IfType_t>("if"sv, x)); | 4054 | newIf->type.set(makeLeaf<IfType_t>("if"sv, x)); |
| 3907 | for (auto j = ns.rbegin(); j != ns.rend(); ++j) { | 4055 | for (auto j = ns.rbegin(); j != ns.rend(); ++j) { |
| 3908 | newIf->nodes.push_back(*j); | 4056 | newIf->nodes.push_back(*j); |
| 3909 | } | 4057 | } |
| @@ -3915,7 +4063,7 @@ private: | |||
| 3915 | if (usage == ExpUsage::Closure) { | 4063 | if (usage == ExpUsage::Closure) { |
| 3916 | auto x = nodes.front(); | 4064 | auto x = nodes.front(); |
| 3917 | auto newIf = x->new_ptr<If_t>(); | 4065 | auto newIf = x->new_ptr<If_t>(); |
| 3918 | newIf->type.set(toAst<IfType_t>(unless ? "unless"sv : "if"sv, x)); | 4066 | newIf->type.set(makeLeaf<IfType_t>(unless ? "unless"sv : "if"sv, x)); |
| 3919 | for (ast_node* node : nodes) { | 4067 | for (ast_node* node : nodes) { |
| 3920 | newIf->nodes.push_back(node); | 4068 | newIf->nodes.push_back(node); |
| 3921 | } | 4069 | } |
| @@ -3971,7 +4119,7 @@ private: | |||
| 3971 | pushScope(); | 4119 | pushScope(); |
| 3972 | } | 4120 | } |
| 3973 | } | 4121 | } |
| 3974 | auto expList = toAst<ExpList_t>(desVar, x); | 4122 | auto expList = makeVariableExpList(desVar, x); |
| 3975 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4123 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 3976 | if (asmt->expList) { | 4124 | if (asmt->expList) { |
| 3977 | for (auto expr : asmt->expList->exprs.objects()) { | 4125 | for (auto expr : asmt->expList->exprs.objects()) { |
| @@ -3986,7 +4134,7 @@ private: | |||
| 3986 | auto expList = x->new_ptr<ExpList_t>(); | 4134 | auto expList = x->new_ptr<ExpList_t>(); |
| 3987 | expList->exprs.push_back(exp); | 4135 | expList->exprs.push_back(exp); |
| 3988 | auto assignOne = x->new_ptr<Assign_t>(); | 4136 | auto assignOne = x->new_ptr<Assign_t>(); |
| 3989 | auto valExp = toAst<Exp_t>(desVar, x); | 4137 | auto valExp = makeVariableExp(desVar, x); |
| 3990 | assignOne->values.push_back(valExp); | 4138 | assignOne->values.push_back(valExp); |
| 3991 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4139 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 3992 | assignment->expList.set(expList); | 4140 | assignment->expList.set(expList); |
| @@ -4211,7 +4359,7 @@ private: | |||
| 4211 | addToScope(varName); | 4359 | addToScope(varName); |
| 4212 | auto condExp = node->new_ptr<Exp_t>(); | 4360 | auto condExp = node->new_ptr<Exp_t>(); |
| 4213 | condExp->pipeExprs.dup(*item.second); | 4361 | condExp->pipeExprs.dup(*item.second); |
| 4214 | auto varExp = toAst<Exp_t>(varName, node); | 4362 | auto varExp = makeVariableExp(varName, node); |
| 4215 | auto assignment = assignmentFrom(varExp, condExp, node); | 4363 | auto assignment = assignmentFrom(varExp, condExp, node); |
| 4216 | preDefine = assignment; | 4364 | preDefine = assignment; |
| 4217 | stack.push_back(varExp->pipeExprs); | 4365 | stack.push_back(varExp->pipeExprs); |
| @@ -4229,7 +4377,7 @@ private: | |||
| 4229 | stack.pop_front(); | 4377 | stack.pop_front(); |
| 4230 | auto opValue = exp->new_ptr<ExpOpValue_t>(); | 4378 | auto opValue = exp->new_ptr<ExpOpValue_t>(); |
| 4231 | const auto& two = std::get<std::string>(stack.front()); | 4379 | const auto& two = std::get<std::string>(stack.front()); |
| 4232 | auto op = toAst<BinaryOperator_t>(two, exp); | 4380 | auto op = makeLeaf<BinaryOperator_t>(two, exp); |
| 4233 | opValue->op.set(op); | 4381 | opValue->op.set(op); |
| 4234 | stack.pop_front(); | 4382 | stack.pop_front(); |
| 4235 | const auto& three = std::get<ast_list<true, UnaryExp_t>>(stack.front()); | 4383 | const auto& three = std::get<ast_list<true, UnaryExp_t>>(stack.front()); |
| @@ -4237,7 +4385,7 @@ private: | |||
| 4237 | condExp->opValues.push_back(opValue); | 4385 | condExp->opValues.push_back(opValue); |
| 4238 | if (preDefine) { | 4386 | if (preDefine) { |
| 4239 | auto ifNode = exp->new_ptr<If_t>(); | 4387 | auto ifNode = exp->new_ptr<If_t>(); |
| 4240 | ifNode->type.set(toAst<IfType_t>("unless"sv, exp)); | 4388 | ifNode->type.set(makeLeaf<IfType_t>("unless"sv, exp)); |
| 4241 | auto ifCond = exp->new_ptr<IfCond_t>(); | 4389 | auto ifCond = exp->new_ptr<IfCond_t>(); |
| 4242 | ifCond->condition.set(condExp); | 4390 | ifCond->condition.set(condExp); |
| 4243 | ifNode->nodes.push_back(ifCond); | 4391 | ifNode->nodes.push_back(ifCond); |
| @@ -4247,7 +4395,7 @@ private: | |||
| 4247 | if (newCondExp) { | 4395 | if (newCondExp) { |
| 4248 | if (!nodes) { | 4396 | if (!nodes) { |
| 4249 | auto ifNodePrev = exp->new_ptr<If_t>(); | 4397 | auto ifNodePrev = exp->new_ptr<If_t>(); |
| 4250 | ifNodePrev->type.set(toAst<IfType_t>("unless"sv, exp)); | 4398 | ifNodePrev->type.set(makeLeaf<IfType_t>("unless"sv, exp)); |
| 4251 | auto ifCondPrev = exp->new_ptr<IfCond_t>(); | 4399 | auto ifCondPrev = exp->new_ptr<IfCond_t>(); |
| 4252 | ifCondPrev->condition.set(newCondExp); | 4400 | ifCondPrev->condition.set(newCondExp); |
| 4253 | ifNodePrev->nodes.push_back(ifCondPrev); | 4401 | ifNodePrev->nodes.push_back(ifCondPrev); |
| @@ -4309,7 +4457,7 @@ private: | |||
| 4309 | nodes->push_back(stmt); | 4457 | nodes->push_back(stmt); |
| 4310 | } else { | 4458 | } else { |
| 4311 | auto opValue = exp->new_ptr<ExpOpValue_t>(); | 4459 | auto opValue = exp->new_ptr<ExpOpValue_t>(); |
| 4312 | opValue->op.set(toAst<BinaryOperator_t>("and"sv, exp)); | 4460 | opValue->op.set(makeLeaf<BinaryOperator_t>("and"sv, exp)); |
| 4313 | opValue->pipeExprs.dup(condExp->pipeExprs); | 4461 | opValue->pipeExprs.dup(condExp->pipeExprs); |
| 4314 | newCondExp->opValues.push_back(opValue); | 4462 | newCondExp->opValues.push_back(opValue); |
| 4315 | newCondExp->opValues.dup(condExp->opValues); | 4463 | newCondExp->opValues.dup(condExp->opValues); |
| @@ -4432,7 +4580,7 @@ private: | |||
| 4432 | codes = YueFormat{}.toString(block); | 4580 | codes = YueFormat{}.toString(block); |
| 4433 | } else { | 4581 | } else { |
| 4434 | auto withNode = block->new_ptr<With_t>(); | 4582 | auto withNode = block->new_ptr<With_t>(); |
| 4435 | withNode->valueList.set(toAst<ExpList_t>(_withVars.top(), x)); | 4583 | withNode->valueList.set(makeVariableExpList(_withVars.top(), x)); |
| 4436 | withNode->body.set(block); | 4584 | withNode->body.set(block); |
| 4437 | codes = YueFormat{}.toString(withNode); | 4585 | codes = YueFormat{}.toString(withNode); |
| 4438 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 4586 | auto simpleValue = x->new_ptr<SimpleValue_t>(); |
| @@ -4519,7 +4667,7 @@ private: | |||
| 4519 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 4667 | auto simpleValue = x->new_ptr<SimpleValue_t>(); |
| 4520 | simpleValue->value.set(funLit); | 4668 | simpleValue->value.set(funLit); |
| 4521 | auto funcName = getUnusedName("_anon_func_"sv); | 4669 | auto funcName = getUnusedName("_anon_func_"sv); |
| 4522 | auto assignment = assignmentFrom(toAst<Exp_t>(funcName, x), newExp(simpleValue, x), x); | 4670 | auto assignment = assignmentFrom(makeVariableExp(funcName, x), newExp(simpleValue, x), x); |
| 4523 | auto scopes = std::move(_scopes); | 4671 | auto scopes = std::move(_scopes); |
| 4524 | _scopes.push_back(std::move(scopes.front())); | 4672 | _scopes.push_back(std::move(scopes.front())); |
| 4525 | scopes.pop_front(); | 4673 | scopes.pop_front(); |
| @@ -4620,7 +4768,7 @@ private: | |||
| 4620 | } | 4768 | } |
| 4621 | } | 4769 | } |
| 4622 | objVar = getUnusedName("_exp_"sv); | 4770 | objVar = getUnusedName("_exp_"sv); |
| 4623 | auto expList = toAst<ExpList_t>(objVar, x); | 4771 | auto expList = makeVariableExpList(objVar, x); |
| 4624 | auto assign = x->new_ptr<Assign_t>(); | 4772 | auto assign = x->new_ptr<Assign_t>(); |
| 4625 | assign->values.push_back(left); | 4773 | assign->values.push_back(left); |
| 4626 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4774 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -4670,7 +4818,7 @@ private: | |||
| 4670 | temp.push_back(clearBuf()); | 4818 | temp.push_back(clearBuf()); |
| 4671 | pushScope(); | 4819 | pushScope(); |
| 4672 | assign->values.clear(); | 4820 | assign->values.clear(); |
| 4673 | assign->values.push_back(toAst<Exp_t>(objVar, x)); | 4821 | assign->values.push_back(makeVariableExp(objVar, x)); |
| 4674 | transformAssignment(assignment, temp); | 4822 | transformAssignment(assignment, temp); |
| 4675 | popScope(); | 4823 | popScope(); |
| 4676 | temp.push_back(indent() + "else"s + nl(x)); | 4824 | temp.push_back(indent() + "else"s + nl(x)); |
| @@ -5081,7 +5229,7 @@ private: | |||
| 5081 | } | 5229 | } |
| 5082 | auto newAssign = x->new_ptr<Assign_t>(); | 5230 | auto newAssign = x->new_ptr<Assign_t>(); |
| 5083 | for (const auto& argName : argNames) { | 5231 | for (const auto& argName : argNames) { |
| 5084 | newAssign->values.push_back(toAst<Exp_t>(argName, x)); | 5232 | newAssign->values.push_back(makeVariableExp(argName, x)); |
| 5085 | } | 5233 | } |
| 5086 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 5234 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| 5087 | newAssignment->expList.set(newExpList); | 5235 | newAssignment->expList.set(newExpList); |
| @@ -5480,7 +5628,7 @@ private: | |||
| 5480 | _rootDefs.clear(); | 5628 | _rootDefs.clear(); |
| 5481 | temp.push_back(std::move(last)); | 5629 | temp.push_back(std::move(last)); |
| 5482 | } | 5630 | } |
| 5483 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { | 5631 | if (!temp.empty() && startsWithStatementSep(temp.back())) { |
| 5484 | auto rit = ++temp.rbegin(); | 5632 | auto rit = ++temp.rbegin(); |
| 5485 | if (rit != temp.rend() && !rit->empty()) { | 5633 | if (rit != temp.rend() && !rit->empty()) { |
| 5486 | auto index = std::string::npos; | 5634 | auto index = std::string::npos; |
| @@ -5600,12 +5748,34 @@ private: | |||
| 5600 | if (_useModule) { | 5748 | if (_useModule) { |
| 5601 | lua_pushliteral(L, YUE_MODULES); // YUE_MODULES | 5749 | lua_pushliteral(L, YUE_MODULES); // YUE_MODULES |
| 5602 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], mods | 5750 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], mods |
| 5603 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #mods, mods | 5751 | if (lua_istable(L, -1) != 0) { |
| 5604 | lua_rawgeti(L, -1, idx); // mods[idx], mods cur | 5752 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #mods, mods |
| 5605 | lua_remove(L, -2); // cur | 5753 | if (idx > 0) { |
| 5606 | return; | 5754 | lua_rawgeti(L, -1, idx); // mods[idx], mods cur |
| 5755 | lua_remove(L, -2); // cur | ||
| 5756 | return; | ||
| 5757 | } | ||
| 5758 | } | ||
| 5759 | lua_pop(L, 1); | ||
| 5760 | _useModule = false; | ||
| 5761 | } | ||
| 5762 | if (_sameModule) { | ||
| 5763 | lua_pushliteral(L, YUE_MODULES); // YUE_MODULES | ||
| 5764 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[YUE_MODULES], mods | ||
| 5765 | if (lua_istable(L, -1) != 0) { | ||
| 5766 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #mods, mods | ||
| 5767 | if (idx > 0) { | ||
| 5768 | lua_rawgeti(L, -1, idx); // mods[idx], mods cur | ||
| 5769 | lua_remove(L, -2); // cur | ||
| 5770 | _useModule = true; | ||
| 5771 | _moduleScopeBaseline = static_cast<int>(lua_objlen(L, -1)); | ||
| 5772 | return; | ||
| 5773 | } | ||
| 5774 | } | ||
| 5775 | lua_pop(L, 1); | ||
| 5607 | } | 5776 | } |
| 5608 | _useModule = true; | 5777 | _useModule = true; |
| 5778 | _moduleScopeBaseline = 0; | ||
| 5609 | if (!L) { | 5779 | if (!L) { |
| 5610 | L = luaL_newstate(); | 5780 | L = luaL_newstate(); |
| 5611 | int top = lua_gettop(L); | 5781 | int top = lua_gettop(L); |
| @@ -6026,7 +6196,7 @@ private: | |||
| 6026 | arg.name = getUnusedName("_arg_"sv); | 6196 | arg.name = getUnusedName("_arg_"sv); |
| 6027 | auto simpleValue = def->new_ptr<SimpleValue_t>(); | 6197 | auto simpleValue = def->new_ptr<SimpleValue_t>(); |
| 6028 | simpleValue->value.set(def->name); | 6198 | simpleValue->value.set(def->name); |
| 6029 | auto asmt = assignmentFrom(newExp(simpleValue, def), toAst<Exp_t>(arg.name, def), def); | 6199 | auto asmt = assignmentFrom(newExp(simpleValue, def), makeVariableExp(arg.name, def), def); |
| 6030 | arg.assignment = asmt; | 6200 | arg.assignment = asmt; |
| 6031 | break; | 6201 | break; |
| 6032 | } | 6202 | } |
| @@ -6034,7 +6204,7 @@ private: | |||
| 6034 | arg.name = getUnusedName("_arg_"sv); | 6204 | arg.name = getUnusedName("_arg_"sv); |
| 6035 | auto value = def->new_ptr<Value_t>(); | 6205 | auto value = def->new_ptr<Value_t>(); |
| 6036 | value->item.set(def->name); | 6206 | value->item.set(def->name); |
| 6037 | auto asmt = assignmentFrom(newExp(value, def), toAst<Exp_t>(arg.name, def), def); | 6207 | auto asmt = assignmentFrom(newExp(value, def), makeVariableExp(arg.name, def), def); |
| 6038 | arg.assignment = asmt; | 6208 | arg.assignment = asmt; |
| 6039 | break; | 6209 | break; |
| 6040 | } | 6210 | } |
| @@ -6042,7 +6212,7 @@ private: | |||
| 6042 | arg.name = getUnusedName("_arg_"sv); | 6212 | arg.name = getUnusedName("_arg_"sv); |
| 6043 | auto simpleValue = def->new_ptr<SimpleValue_t>(); | 6213 | auto simpleValue = def->new_ptr<SimpleValue_t>(); |
| 6044 | simpleValue->value.set(def->name); | 6214 | simpleValue->value.set(def->name); |
| 6045 | auto asmt = assignmentFrom(newExp(simpleValue, def), toAst<Exp_t>(arg.name, def), def); | 6215 | auto asmt = assignmentFrom(newExp(simpleValue, def), makeVariableExp(arg.name, def), def); |
| 6046 | arg.assignment = asmt; | 6216 | arg.assignment = asmt; |
| 6047 | break; | 6217 | break; |
| 6048 | } | 6218 | } |
| @@ -6051,7 +6221,7 @@ private: | |||
| 6051 | forceAddToScope(arg.name); | 6221 | forceAddToScope(arg.name); |
| 6052 | if (def->defaultValue) { | 6222 | if (def->defaultValue) { |
| 6053 | pushScope(); | 6223 | pushScope(); |
| 6054 | auto expList = toAst<ExpList_t>(arg.name, x); | 6224 | auto expList = makeVariableExpList(arg.name, x); |
| 6055 | auto assign = x->new_ptr<Assign_t>(); | 6225 | auto assign = x->new_ptr<Assign_t>(); |
| 6056 | assign->values.push_back(def->defaultValue.get()); | 6226 | assign->values.push_back(def->defaultValue.get()); |
| 6057 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6227 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -6219,7 +6389,7 @@ private: | |||
| 6219 | chainValue->items.pop_back(); | 6389 | chainValue->items.pop_back(); |
| 6220 | auto value = x->new_ptr<Value_t>(); | 6390 | auto value = x->new_ptr<Value_t>(); |
| 6221 | value->item.set(chainValue); | 6391 | value->item.set(chainValue); |
| 6222 | auto exp = newExp(value, toAst<BinaryOperator_t>("!="sv, x), toAst<Value_t>("nil"sv, x), x); | 6392 | auto exp = newExp(value, makeLeaf<BinaryOperator_t>("!="sv, x), makeConstValue("nil"sv, x), x); |
| 6223 | parens->expr.set(exp); | 6393 | parens->expr.set(exp); |
| 6224 | } | 6394 | } |
| 6225 | switch (usage) { | 6395 | switch (usage) { |
| @@ -6323,7 +6493,7 @@ private: | |||
| 6323 | if (_withVars.empty()) { | 6493 | if (_withVars.empty()) { |
| 6324 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); | 6494 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); |
| 6325 | } | 6495 | } |
| 6326 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 6496 | chainValue->items.push_back(makeVariableCallable(_withVars.top(), x)); |
| 6327 | } | 6497 | } |
| 6328 | auto newObj = singleVariableFrom(chainValue, AccessType::Read); | 6498 | auto newObj = singleVariableFrom(chainValue, AccessType::Read); |
| 6329 | if (!newObj.empty()) { | 6499 | if (!newObj.empty()) { |
| @@ -6333,7 +6503,7 @@ private: | |||
| 6333 | auto assign = x->new_ptr<Assign_t>(); | 6503 | auto assign = x->new_ptr<Assign_t>(); |
| 6334 | assign->values.push_back(exp); | 6504 | assign->values.push_back(exp); |
| 6335 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 6505 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); |
| 6336 | expListAssign->expList.set(toAst<ExpList_t>(objVar, x)); | 6506 | expListAssign->expList.set(makeVariableExpList(objVar, x)); |
| 6337 | expListAssign->action.set(assign); | 6507 | expListAssign->action.set(assign); |
| 6338 | transformAssignment(expListAssign, temp); | 6508 | transformAssignment(expListAssign, temp); |
| 6339 | } | 6509 | } |
| @@ -6344,16 +6514,16 @@ private: | |||
| 6344 | } | 6514 | } |
| 6345 | dotItem->name.set(name); | 6515 | dotItem->name.set(name); |
| 6346 | partOne->items.clear(); | 6516 | partOne->items.clear(); |
| 6347 | partOne->items.push_back(toAst<Callable_t>(objVar, x)); | 6517 | partOne->items.push_back(makeVariableCallable(objVar, x)); |
| 6348 | partOne->items.push_back(dotItem); | 6518 | partOne->items.push_back(dotItem); |
| 6349 | auto it = opIt; | 6519 | auto it = opIt; |
| 6350 | ++it; | 6520 | ++it; |
| 6351 | if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { | 6521 | if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { |
| 6352 | if (auto invoke = ast_cast<Invoke_t>(*it)) { | 6522 | if (auto invoke = ast_cast<Invoke_t>(*it)) { |
| 6353 | invoke->args.push_front(toAst<Exp_t>(objVar, x)); | 6523 | invoke->args.push_front(makeVariableExp(objVar, x)); |
| 6354 | } else { | 6524 | } else { |
| 6355 | auto invokeArgs = static_cast<InvokeArgs_t*>(*it); | 6525 | auto invokeArgs = static_cast<InvokeArgs_t*>(*it); |
| 6356 | invokeArgs->args.push_front(toAst<Exp_t>(objVar, x)); | 6526 | invokeArgs->args.push_front(makeVariableExp(objVar, x)); |
| 6357 | } | 6527 | } |
| 6358 | } | 6528 | } |
| 6359 | objVar = getUnusedName("_obj_"sv); | 6529 | objVar = getUnusedName("_obj_"sv); |
| @@ -6362,7 +6532,7 @@ private: | |||
| 6362 | auto assign = x->new_ptr<Assign_t>(); | 6532 | auto assign = x->new_ptr<Assign_t>(); |
| 6363 | assign->values.push_back(exp); | 6533 | assign->values.push_back(exp); |
| 6364 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 6534 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); |
| 6365 | expListAssign->expList.set(toAst<ExpList_t>(objVar, x)); | 6535 | expListAssign->expList.set(makeVariableExpList(objVar, x)); |
| 6366 | expListAssign->action.set(assign); | 6536 | expListAssign->action.set(assign); |
| 6367 | transformAssignment(expListAssign, temp); | 6537 | transformAssignment(expListAssign, temp); |
| 6368 | } | 6538 | } |
| @@ -6378,7 +6548,7 @@ private: | |||
| 6378 | temp.push_back(clearBuf()); | 6548 | temp.push_back(clearBuf()); |
| 6379 | pushScope(); | 6549 | pushScope(); |
| 6380 | auto partTwo = x->new_ptr<ChainValue_t>(); | 6550 | auto partTwo = x->new_ptr<ChainValue_t>(); |
| 6381 | partTwo->items.push_back(toAst<Callable_t>(objVar, x)); | 6551 | partTwo->items.push_back(makeVariableCallable(objVar, x)); |
| 6382 | for (auto it = ++opIt; it != chainList.end(); ++it) { | 6552 | for (auto it = ++opIt; it != chainList.end(); ++it) { |
| 6383 | partTwo->items.push_back(*it); | 6553 | partTwo->items.push_back(*it); |
| 6384 | } | 6554 | } |
| @@ -6461,7 +6631,7 @@ private: | |||
| 6461 | if (_withVars.empty()) { | 6631 | if (_withVars.empty()) { |
| 6462 | throw CompileError("short dot/colon syntax must be called within a with block"sv, chainList.front()); | 6632 | throw CompileError("short dot/colon syntax must be called within a with block"sv, chainList.front()); |
| 6463 | } else { | 6633 | } else { |
| 6464 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 6634 | baseChain->items.push_back(makeVariableCallable(_withVars.top(), x)); |
| 6465 | } | 6635 | } |
| 6466 | break; | 6636 | break; |
| 6467 | } | 6637 | } |
| @@ -6478,7 +6648,7 @@ private: | |||
| 6478 | auto assign = x->new_ptr<Assign_t>(); | 6648 | auto assign = x->new_ptr<Assign_t>(); |
| 6479 | assign->values.push_back(exp); | 6649 | assign->values.push_back(exp); |
| 6480 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6650 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 6481 | assignment->expList.set(toAst<ExpList_t>(baseVar, x)); | 6651 | assignment->expList.set(makeVariableExpList(baseVar, x)); |
| 6482 | assignment->action.set(assign); | 6652 | assignment->action.set(assign); |
| 6483 | transformAssignment(assignment, temp); | 6653 | transformAssignment(assignment, temp); |
| 6484 | } | 6654 | } |
| @@ -6486,7 +6656,7 @@ private: | |||
| 6486 | auto assign = x->new_ptr<Assign_t>(); | 6656 | auto assign = x->new_ptr<Assign_t>(); |
| 6487 | assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, x)); | 6657 | assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, x)); |
| 6488 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6658 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 6489 | assignment->expList.set(toAst<ExpList_t>(fnVar, x)); | 6659 | assignment->expList.set(makeVariableExpList(fnVar, x)); |
| 6490 | assignment->action.set(assign); | 6660 | assignment->action.set(assign); |
| 6491 | transformAssignment(assignment, temp); | 6661 | transformAssignment(assignment, temp); |
| 6492 | } | 6662 | } |
| @@ -6553,7 +6723,7 @@ private: | |||
| 6553 | if (_withVars.empty()) { | 6723 | if (_withVars.empty()) { |
| 6554 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); | 6724 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); |
| 6555 | } else { | 6725 | } else { |
| 6556 | chain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 6726 | chain->items.push_back(makeVariableCallable(_withVars.top(), x)); |
| 6557 | } | 6727 | } |
| 6558 | } | 6728 | } |
| 6559 | for (auto it = chainList.begin(); it != opIt; ++it) { | 6729 | for (auto it = chainList.begin(); it != opIt; ++it) { |
| @@ -6600,7 +6770,7 @@ private: | |||
| 6600 | } | 6770 | } |
| 6601 | } | 6771 | } |
| 6602 | auto var = getUnusedName("_obj_"sv); | 6772 | auto var = getUnusedName("_obj_"sv); |
| 6603 | auto target = toAst<Exp_t>(var, x); | 6773 | auto target = makeVariableExp(var, x); |
| 6604 | { | 6774 | { |
| 6605 | auto assignment = assignmentFrom(target, newExp(chain, x), x); | 6775 | auto assignment = assignmentFrom(target, newExp(chain, x), x); |
| 6606 | transformAssignment(assignment, temp); | 6776 | transformAssignment(assignment, temp); |
| @@ -6744,7 +6914,7 @@ private: | |||
| 6744 | switch (chainList.front()->get_id()) { | 6914 | switch (chainList.front()->get_id()) { |
| 6745 | case id<DotChainItem_t>(): | 6915 | case id<DotChainItem_t>(): |
| 6746 | case id<ColonChainItem_t>(): | 6916 | case id<ColonChainItem_t>(): |
| 6747 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 6917 | chainValue->items.push_back(makeVariableCallable(_withVars.top(), x)); |
| 6748 | break; | 6918 | break; |
| 6749 | } | 6919 | } |
| 6750 | for (auto i = chainList.begin(); i != current; ++i) { | 6920 | for (auto i = chainList.begin(); i != current; ++i) { |
| @@ -6755,7 +6925,7 @@ private: | |||
| 6755 | if (callVar.empty() || !isLocal(callVar)) { | 6925 | if (callVar.empty() || !isLocal(callVar)) { |
| 6756 | callVar = getUnusedName("_call_"s); | 6926 | callVar = getUnusedName("_call_"s); |
| 6757 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 6927 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 6758 | assignment->expList.set(toAst<ExpList_t>(callVar, x)); | 6928 | assignment->expList.set(makeVariableExpList(callVar, x)); |
| 6759 | auto assign = x->new_ptr<Assign_t>(); | 6929 | auto assign = x->new_ptr<Assign_t>(); |
| 6760 | assign->values.push_back(exp); | 6930 | assign->values.push_back(exp); |
| 6761 | assignment->action.set(assign); | 6931 | assignment->action.set(assign); |
| @@ -6768,21 +6938,21 @@ private: | |||
| 6768 | { | 6938 | { |
| 6769 | auto name = _parser.toString(colonItem->name); | 6939 | auto name = _parser.toString(colonItem->name); |
| 6770 | auto chainValue = x->new_ptr<ChainValue_t>(); | 6940 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| 6771 | chainValue->items.push_back(toAst<Callable_t>(callVar, x)); | 6941 | chainValue->items.push_back(makeVariableCallable(callVar, x)); |
| 6772 | if (ast_is<ExistentialOp_t>(*current)) { | 6942 | if (ast_is<ExistentialOp_t>(*current)) { |
| 6773 | chainValue->items.push_back(x->new_ptr<ExistentialOp_t>()); | 6943 | chainValue->items.push_back(x->new_ptr<ExistentialOp_t>()); |
| 6774 | } | 6944 | } |
| 6775 | chainValue->items.push_back(toAst<Exp_t>('\"' + name + '\"', x)); | 6945 | chainValue->items.push_back(toAst<Exp_t>('\"' + name + '\"', x)); |
| 6776 | if (auto invoke = ast_cast<Invoke_t>(followItem)) { | 6946 | if (auto invoke = ast_cast<Invoke_t>(followItem)) { |
| 6777 | auto newInvoke = x->new_ptr<Invoke_t>(); | 6947 | auto newInvoke = x->new_ptr<Invoke_t>(); |
| 6778 | newInvoke->args.push_back(toAst<Exp_t>(callVar, x)); | 6948 | newInvoke->args.push_back(makeVariableExp(callVar, x)); |
| 6779 | newInvoke->args.dup(invoke->args); | 6949 | newInvoke->args.dup(invoke->args); |
| 6780 | chainValue->items.push_back(newInvoke); | 6950 | chainValue->items.push_back(newInvoke); |
| 6781 | ++next; | 6951 | ++next; |
| 6782 | } else { | 6952 | } else { |
| 6783 | auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); | 6953 | auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); |
| 6784 | auto newInvokeArgs = x->new_ptr<InvokeArgs_t>(); | 6954 | auto newInvokeArgs = x->new_ptr<InvokeArgs_t>(); |
| 6785 | newInvokeArgs->args.push_back(toAst<Exp_t>(callVar, x)); | 6955 | newInvokeArgs->args.push_back(makeVariableExp(callVar, x)); |
| 6786 | newInvokeArgs->args.dup(invokeArgs->args); | 6956 | newInvokeArgs->args.dup(invokeArgs->args); |
| 6787 | chainValue->items.push_back(newInvokeArgs); | 6957 | chainValue->items.push_back(newInvokeArgs); |
| 6788 | ++next; | 6958 | ++next; |
| @@ -6867,7 +7037,7 @@ private: | |||
| 6867 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); | 7037 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); |
| 6868 | if (rIndex->modifier) { | 7038 | if (rIndex->modifier) { |
| 6869 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | 7039 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); |
| 6870 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | 7040 | opValue->op.set(makeLeaf<BinaryOperator_t>("-"sv, rIndex)); |
| 6871 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | 7041 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); |
| 6872 | indexNode->opValues.push_back(opValue); | 7042 | indexNode->opValues.push_back(opValue); |
| 6873 | indexNode->opValues.dup(rIndex->modifier->opValues); | 7043 | indexNode->opValues.dup(rIndex->modifier->opValues); |
| @@ -6892,15 +7062,15 @@ private: | |||
| 6892 | return; | 7062 | return; |
| 6893 | } else { | 7063 | } else { |
| 6894 | auto itemVar = getUnusedName("_item_"sv); | 7064 | auto itemVar = getUnusedName("_item_"sv); |
| 6895 | auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x); | 7065 | auto asmt = assignmentFrom(makeVariableExp(itemVar, x), newExp(prevChain, x), x); |
| 6896 | auto stmt1 = x->new_ptr<Statement_t>(); | 7066 | auto stmt1 = x->new_ptr<Statement_t>(); |
| 6897 | stmt1->content.set(asmt); | 7067 | stmt1->content.set(asmt); |
| 6898 | auto newChain = x->new_ptr<ChainValue_t>(); | 7068 | auto newChain = x->new_ptr<ChainValue_t>(); |
| 6899 | newChain->items.push_back(toAst<Callable_t>(itemVar, x)); | 7069 | newChain->items.push_back(makeVariableCallable(itemVar, x)); |
| 6900 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); | 7070 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); |
| 6901 | if (rIndex->modifier) { | 7071 | if (rIndex->modifier) { |
| 6902 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | 7072 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); |
| 6903 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | 7073 | opValue->op.set(makeLeaf<BinaryOperator_t>("-"sv, rIndex)); |
| 6904 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | 7074 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); |
| 6905 | indexNode->opValues.push_back(opValue); | 7075 | indexNode->opValues.push_back(opValue); |
| 6906 | indexNode->opValues.dup(rIndex->modifier->opValues); | 7076 | indexNode->opValues.dup(rIndex->modifier->opValues); |
| @@ -7663,7 +7833,7 @@ private: | |||
| 7663 | auto block = x->new_ptr<Block_t>(); | 7833 | auto block = x->new_ptr<Block_t>(); |
| 7664 | if (checkVar.empty() || !isLocal(checkVar)) { | 7834 | if (checkVar.empty() || !isLocal(checkVar)) { |
| 7665 | checkVar = getUnusedName("_check_"sv); | 7835 | checkVar = getUnusedName("_check_"sv); |
| 7666 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp); | 7836 | auto assignment = assignmentFrom(makeVariableExp(checkVar, inExp), newExp(inExp, inExp), inExp); |
| 7667 | auto stmt = x->new_ptr<Statement_t>(); | 7837 | auto stmt = x->new_ptr<Statement_t>(); |
| 7668 | stmt->content.set(assignment); | 7838 | stmt->content.set(assignment); |
| 7669 | block->statementOrComments.push_back(stmt); | 7839 | block->statementOrComments.push_back(stmt); |
| @@ -7674,7 +7844,7 @@ private: | |||
| 7674 | newUnaryExp->expos.dup(unary_exp->expos); | 7844 | newUnaryExp->expos.dup(unary_exp->expos); |
| 7675 | auto exp = newExp(newUnaryExp, x); | 7845 | auto exp = newExp(newUnaryExp, x); |
| 7676 | varName = getUnusedName("_val_"sv); | 7846 | varName = getUnusedName("_val_"sv); |
| 7677 | auto assignExp = toAst<Exp_t>(varName, x); | 7847 | auto assignExp = makeVariableExp(varName, x); |
| 7678 | auto assignment = assignmentFrom(assignExp, exp, x); | 7848 | auto assignment = assignmentFrom(assignExp, exp, x); |
| 7679 | auto stmt = x->new_ptr<Statement_t>(); | 7849 | auto stmt = x->new_ptr<Statement_t>(); |
| 7680 | stmt->content.set(assignment); | 7850 | stmt->content.set(assignment); |
| @@ -7759,7 +7929,7 @@ private: | |||
| 7759 | } | 7929 | } |
| 7760 | if (checkVar.empty() || !isLocal(checkVar)) { | 7930 | if (checkVar.empty() || !isLocal(checkVar)) { |
| 7761 | checkVar = getUnusedName("_check_"sv); | 7931 | checkVar = getUnusedName("_check_"sv); |
| 7762 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp); | 7932 | auto assignment = assignmentFrom(makeVariableExp(checkVar, inExp), newExp(inExp, inExp), inExp); |
| 7763 | transformAssignment(assignment, temp); | 7933 | transformAssignment(assignment, temp); |
| 7764 | } | 7934 | } |
| 7765 | if (varName.empty()) { | 7935 | if (varName.empty()) { |
| @@ -7768,7 +7938,7 @@ private: | |||
| 7768 | newUnaryExp->expos.dup(unary_exp->expos); | 7938 | newUnaryExp->expos.dup(unary_exp->expos); |
| 7769 | auto exp = newExp(newUnaryExp, x); | 7939 | auto exp = newExp(newUnaryExp, x); |
| 7770 | varName = getUnusedName("_val_"sv); | 7940 | varName = getUnusedName("_val_"sv); |
| 7771 | auto assignExp = toAst<Exp_t>(varName, x); | 7941 | auto assignExp = makeVariableExp(varName, x); |
| 7772 | auto assignment = assignmentFrom(assignExp, exp, x); | 7942 | auto assignment = assignmentFrom(assignExp, exp, x); |
| 7773 | transformAssignment(assignment, temp); | 7943 | transformAssignment(assignment, temp); |
| 7774 | } | 7944 | } |
| @@ -7825,7 +7995,7 @@ private: | |||
| 7825 | newUnaryExp->expos.dup(unary_exp->expos); | 7995 | newUnaryExp->expos.dup(unary_exp->expos); |
| 7826 | auto exp = newExp(newUnaryExp, x); | 7996 | auto exp = newExp(newUnaryExp, x); |
| 7827 | auto newVar = getUnusedName("_val_"sv); | 7997 | auto newVar = getUnusedName("_val_"sv); |
| 7828 | auto assignExp = toAst<Exp_t>(newVar, x); | 7998 | auto assignExp = makeVariableExp(newVar, x); |
| 7829 | auto assignment = assignmentFrom(assignExp, exp, x); | 7999 | auto assignment = assignmentFrom(assignExp, exp, x); |
| 7830 | transformAssignment(assignment, temp); | 8000 | transformAssignment(assignment, temp); |
| 7831 | 8001 | ||
| @@ -8280,7 +8450,7 @@ private: | |||
| 8280 | } | 8450 | } |
| 8281 | case ExpUsage::Assignment: { | 8451 | case ExpUsage::Assignment: { |
| 8282 | auto assign = x->new_ptr<Assign_t>(); | 8452 | auto assign = x->new_ptr<Assign_t>(); |
| 8283 | assign->values.push_back(toAst<Exp_t>(tableVar, x)); | 8453 | assign->values.push_back(makeVariableExp(tableVar, x)); |
| 8284 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8454 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 8285 | assignment->expList.set(assignList); | 8455 | assignment->expList.set(assignList); |
| 8286 | assignment->action.set(assign); | 8456 | assignment->action.set(assign); |
| @@ -8722,7 +8892,7 @@ private: | |||
| 8722 | case ExpUsage::Assignment: { | 8892 | case ExpUsage::Assignment: { |
| 8723 | out.push_back(clearBuf()); | 8893 | out.push_back(clearBuf()); |
| 8724 | auto assign = x->new_ptr<Assign_t>(); | 8894 | auto assign = x->new_ptr<Assign_t>(); |
| 8725 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | 8895 | assign->values.push_back(makeVariableExp(accumVar, x)); |
| 8726 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8896 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 8727 | assignment->expList.set(assignList); | 8897 | assignment->expList.set(assignList); |
| 8728 | assignment->action.set(assign); | 8898 | assignment->action.set(assign); |
| @@ -8771,7 +8941,7 @@ private: | |||
| 8771 | case id<TableLit_t>(): | 8941 | case id<TableLit_t>(): |
| 8772 | case id<Comprehension_t>(): { | 8942 | case id<Comprehension_t>(): { |
| 8773 | auto desVar = getUnusedName("_des_"sv); | 8943 | auto desVar = getUnusedName("_des_"sv); |
| 8774 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); | 8944 | destructPairs.emplace_back(item, makeVariableExp(desVar, x)); |
| 8775 | vars.push_back(desVar); | 8945 | vars.push_back(desVar); |
| 8776 | varAfter.push_back(desVar); | 8946 | varAfter.push_back(desVar); |
| 8777 | break; | 8947 | break; |
| @@ -10227,7 +10397,7 @@ private: | |||
| 10227 | str_list tmp; | 10397 | str_list tmp; |
| 10228 | if (usage == ExpUsage::Assignment) { | 10398 | if (usage == ExpUsage::Assignment) { |
| 10229 | auto assign = x->new_ptr<Assign_t>(); | 10399 | auto assign = x->new_ptr<Assign_t>(); |
| 10230 | assign->values.push_back(toAst<Exp_t>(classVar, x)); | 10400 | assign->values.push_back(makeVariableExp(classVar, x)); |
| 10231 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10401 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10232 | assignment->expList.set(expList); | 10402 | assignment->expList.set(expList); |
| 10233 | assignment->action.set(assign); | 10403 | assignment->action.set(assign); |
| @@ -10509,7 +10679,7 @@ private: | |||
| 10509 | if (withVar.empty()) { | 10679 | if (withVar.empty()) { |
| 10510 | withVar = getUnusedName("_with_"sv); | 10680 | withVar = getUnusedName("_with_"sv); |
| 10511 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10681 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10512 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 10682 | assignment->expList.set(makeVariableExpList(withVar, x)); |
| 10513 | auto assign = x->new_ptr<Assign_t>(); | 10683 | auto assign = x->new_ptr<Assign_t>(); |
| 10514 | assign->values.push_back(with->assign->values.objects().front()); | 10684 | assign->values.push_back(with->assign->values.objects().front()); |
| 10515 | assignment->action.set(assign); | 10685 | assignment->action.set(assign); |
| @@ -10523,7 +10693,7 @@ private: | |||
| 10523 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10693 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10524 | assignment->expList.set(with->valueList); | 10694 | assignment->expList.set(with->valueList); |
| 10525 | auto assign = x->new_ptr<Assign_t>(); | 10695 | auto assign = x->new_ptr<Assign_t>(); |
| 10526 | assign->values.push_back(toAst<Exp_t>(withVar, x)); | 10696 | assign->values.push_back(makeVariableExp(withVar, x)); |
| 10527 | bool skipFirst = true; | 10697 | bool skipFirst = true; |
| 10528 | for (auto value : with->assign->values.objects()) { | 10698 | for (auto value : with->assign->values.objects()) { |
| 10529 | if (skipFirst) { | 10699 | if (skipFirst) { |
| @@ -10551,7 +10721,7 @@ private: | |||
| 10551 | if (withVar.empty() || !isLocal(withVar)) { | 10721 | if (withVar.empty() || !isLocal(withVar)) { |
| 10552 | withVar = getUnusedName("_with_"sv); | 10722 | withVar = getUnusedName("_with_"sv); |
| 10553 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10723 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10554 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 10724 | assignment->expList.set(makeVariableExpList(withVar, x)); |
| 10555 | auto assign = x->new_ptr<Assign_t>(); | 10725 | auto assign = x->new_ptr<Assign_t>(); |
| 10556 | assign->values.dup(with->valueList->exprs); | 10726 | assign->values.dup(with->valueList->exprs); |
| 10557 | assignment->action.set(assign); | 10727 | assignment->action.set(assign); |
| @@ -10635,7 +10805,7 @@ private: | |||
| 10635 | } | 10805 | } |
| 10636 | if (with->eop) { | 10806 | if (with->eop) { |
| 10637 | auto ifNode = x->new_ptr<If_t>(); | 10807 | auto ifNode = x->new_ptr<If_t>(); |
| 10638 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); | 10808 | ifNode->type.set(makeLeaf<IfType_t>("if"sv, x)); |
| 10639 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); | 10809 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); |
| 10640 | ifNode->nodes.push_back(with->body); | 10810 | ifNode->nodes.push_back(with->body); |
| 10641 | if (breakWithVar.empty()) { | 10811 | if (breakWithVar.empty()) { |
| @@ -10717,7 +10887,7 @@ private: | |||
| 10717 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10887 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10718 | assignment->expList.set(assignList); | 10888 | assignment->expList.set(assignList); |
| 10719 | auto assign = x->new_ptr<Assign_t>(); | 10889 | auto assign = x->new_ptr<Assign_t>(); |
| 10720 | assign->values.push_back(toAst<Exp_t>(breakWithVar.empty() ? withVar : breakWithVar, x)); | 10890 | assign->values.push_back(makeVariableExp(breakWithVar.empty() ? withVar : breakWithVar, x)); |
| 10721 | assignment->action.set(assign); | 10891 | assignment->action.set(assign); |
| 10722 | transformAssignment(assignment, temp); | 10892 | transformAssignment(assignment, temp); |
| 10723 | } | 10893 | } |
| @@ -10899,7 +11069,7 @@ private: | |||
| 10899 | } | 11069 | } |
| 10900 | } | 11070 | } |
| 10901 | auto newChain = x->new_ptr<ChainValue_t>(); | 11071 | auto newChain = x->new_ptr<ChainValue_t>(); |
| 10902 | auto callable = toAst<Callable_t>(_info.moduleName, x); | 11072 | auto callable = makeVariableCallable(_info.moduleName, x); |
| 10903 | newChain->items.push_front(callable); | 11073 | newChain->items.push_front(callable); |
| 10904 | newChain->items.push_back(exportNode->target); | 11074 | newChain->items.push_back(exportNode->target); |
| 10905 | auto exp = newExp(newChain, x); | 11075 | auto exp = newExp(newChain, x); |
| @@ -10964,7 +11134,7 @@ private: | |||
| 10964 | } else if (_info.exportDefault) { | 11134 | } else if (_info.exportDefault) { |
| 10965 | auto exp = exportNode->target.to<Exp_t>(); | 11135 | auto exp = exportNode->target.to<Exp_t>(); |
| 10966 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 11136 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10967 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName, x)); | 11137 | assignment->expList.set(makeVariableExpList(_info.moduleName, x)); |
| 10968 | auto assign = x->new_ptr<Assign_t>(); | 11138 | auto assign = x->new_ptr<Assign_t>(); |
| 10969 | assign->values.push_back(exp); | 11139 | assign->values.push_back(exp); |
| 10970 | assignment->action.set(assign); | 11140 | assignment->action.set(assign); |
| @@ -10983,7 +11153,7 @@ private: | |||
| 10983 | auto name = variableToString(var); | 11153 | auto name = variableToString(var); |
| 10984 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName + "[\""s + name + "\"]"s, x)); | 11154 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName + "[\""s + name + "\"]"s, x)); |
| 10985 | auto assign = x->new_ptr<Assign_t>(); | 11155 | auto assign = x->new_ptr<Assign_t>(); |
| 10986 | assign->values.push_back(toAst<Exp_t>(name, x)); | 11156 | assign->values.push_back(makeVariableExp(name, x)); |
| 10987 | assignment->action.set(assign); | 11157 | assignment->action.set(assign); |
| 10988 | transformAssignment(assignment, temp); | 11158 | transformAssignment(assignment, temp); |
| 10989 | assignment->expList.set(assignList); | 11159 | assignment->expList.set(assignList); |
| @@ -11469,7 +11639,7 @@ private: | |||
| 11469 | ast_ptr<false, ExpListAssign_t> objAssign; | 11639 | ast_ptr<false, ExpListAssign_t> objAssign; |
| 11470 | if (objVar.empty()) { | 11640 | if (objVar.empty()) { |
| 11471 | objVar = getUnusedName("_obj_"sv); | 11641 | objVar = getUnusedName("_obj_"sv); |
| 11472 | auto expList = toAst<ExpList_t>(objVar, x); | 11642 | auto expList = makeVariableExpList(objVar, x); |
| 11473 | auto assign = x->new_ptr<Assign_t>(); | 11643 | auto assign = x->new_ptr<Assign_t>(); |
| 11474 | if (importNode->item.is<Exp_t>()) { | 11644 | if (importNode->item.is<Exp_t>()) { |
| 11475 | assign->values.push_back(importNode->item); | 11645 | assign->values.push_back(importNode->item); |
| @@ -11489,7 +11659,7 @@ private: | |||
| 11489 | case id<Variable_t>(): { | 11659 | case id<Variable_t>(): { |
| 11490 | auto var = static_cast<Variable_t*>(name); | 11660 | auto var = static_cast<Variable_t*>(name); |
| 11491 | { | 11661 | { |
| 11492 | auto callable = toAst<Callable_t>(objVar, x); | 11662 | auto callable = makeVariableCallable(objVar, x); |
| 11493 | auto dotChainItem = x->new_ptr<DotChainItem_t>(); | 11663 | auto dotChainItem = x->new_ptr<DotChainItem_t>(); |
| 11494 | dotChainItem->name.set(var->name); | 11664 | dotChainItem->name.set(var->name); |
| 11495 | auto chainValue = x->new_ptr<ChainValue_t>(); | 11665 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| @@ -11510,7 +11680,7 @@ private: | |||
| 11510 | auto var = static_cast<ColonImportName_t*>(name)->name.get(); | 11680 | auto var = static_cast<ColonImportName_t*>(name)->name.get(); |
| 11511 | { | 11681 | { |
| 11512 | auto nameNode = var->name.get(); | 11682 | auto nameNode = var->name.get(); |
| 11513 | auto callable = toAst<Callable_t>(objVar, x); | 11683 | auto callable = makeVariableCallable(objVar, x); |
| 11514 | auto colonChain = x->new_ptr<ColonChainItem_t>(); | 11684 | auto colonChain = x->new_ptr<ColonChainItem_t>(); |
| 11515 | colonChain->name.set(nameNode); | 11685 | colonChain->name.set(nameNode); |
| 11516 | auto chainValue = x->new_ptr<ChainValue_t>(); | 11686 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| @@ -11952,11 +12122,11 @@ private: | |||
| 11952 | if (whileNode->assignment) { | 12122 | if (whileNode->assignment) { |
| 11953 | auto x = whileNode; | 12123 | auto x = whileNode; |
| 11954 | auto repeat = x->new_ptr<Repeat_t>(); | 12124 | auto repeat = x->new_ptr<Repeat_t>(); |
| 11955 | repeat->condition.set(toAst<Exp_t>("false"sv, x)); | 12125 | repeat->condition.set(makeConstExp("false"sv, x)); |
| 11956 | auto ifNode = x->new_ptr<If_t>(); | 12126 | auto ifNode = x->new_ptr<If_t>(); |
| 11957 | auto ifCond = x->new_ptr<IfCond_t>(); | 12127 | auto ifCond = x->new_ptr<IfCond_t>(); |
| 11958 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 12128 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
| 11959 | ifNode->type.set(toAst<IfType_t>(isUntil ? "unless"sv : "if"sv, x)); | 12129 | ifNode->type.set(makeLeaf<IfType_t>(isUntil ? "unless"sv : "if"sv, x)); |
| 11960 | ifCond->condition.set(whileNode->condition); | 12130 | ifCond->condition.set(whileNode->condition); |
| 11961 | ifCond->assignment.set(whileNode->assignment); | 12131 | ifCond->assignment.set(whileNode->assignment); |
| 11962 | ifNode->nodes.push_back(ifCond); | 12132 | ifNode->nodes.push_back(ifCond); |
| @@ -12160,7 +12330,7 @@ private: | |||
| 12160 | } | 12330 | } |
| 12161 | } | 12331 | } |
| 12162 | objVar = getUnusedName("_exp_"sv); | 12332 | objVar = getUnusedName("_exp_"sv); |
| 12163 | auto expList = toAst<ExpList_t>(objVar, x); | 12333 | auto expList = makeVariableExpList(objVar, x); |
| 12164 | auto assign = x->new_ptr<Assign_t>(); | 12334 | auto assign = x->new_ptr<Assign_t>(); |
| 12165 | assign->values.push_back(switchNode->target); | 12335 | assign->values.push_back(switchNode->target); |
| 12166 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 12336 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -12246,7 +12416,7 @@ private: | |||
| 12246 | conds.back().append(vStr); | 12416 | conds.back().append(vStr); |
| 12247 | } else { | 12417 | } else { |
| 12248 | auto varName = getUnusedName("_val_"sv); | 12418 | auto varName = getUnusedName("_val_"sv); |
| 12249 | auto vExp = toAst<Exp_t>(varName, chain); | 12419 | auto vExp = makeVariableExp(varName, chain); |
| 12250 | auto asmt = assignmentFrom(vExp, newExp(chain, chain), chain); | 12420 | auto asmt = assignmentFrom(vExp, newExp(chain, chain), chain); |
| 12251 | transformAssignment(asmt, temp); | 12421 | transformAssignment(asmt, temp); |
| 12252 | transformExp(item.target, conds, ExpUsage::Closure); | 12422 | transformExp(item.target, conds, ExpUsage::Closure); |
| @@ -12665,7 +12835,7 @@ private: | |||
| 12665 | } | 12835 | } |
| 12666 | if (isBreak) { | 12836 | if (isBreak) { |
| 12667 | if (breakLoop->valueList) { | 12837 | if (breakLoop->valueList) { |
| 12668 | auto expList = toAst<ExpList_t>(join(breakLoop->vars, ","sv), breakLoop); | 12838 | auto expList = makeVariableExpList(breakLoop->vars, breakLoop); |
| 12669 | auto assignment = breakLoop->new_ptr<ExpListAssign_t>(); | 12839 | auto assignment = breakLoop->new_ptr<ExpListAssign_t>(); |
| 12670 | assignment->expList.set(expList); | 12840 | assignment->expList.set(expList); |
| 12671 | auto assign = breakLoop->new_ptr<Assign_t>(); | 12841 | auto assign = breakLoop->new_ptr<Assign_t>(); |
| @@ -12690,7 +12860,7 @@ private: | |||
| 12690 | _buf << indent() << "break"sv << nl(breakLoop); | 12860 | _buf << indent() << "break"sv << nl(breakLoop); |
| 12691 | out.push_back(clearBuf()); | 12861 | out.push_back(clearBuf()); |
| 12692 | } else { | 12862 | } else { |
| 12693 | transformGoto(toAst<Goto_t>("goto "s + item.var, breakLoop), temp); | 12863 | transformGoto(makeGoto(item.var, breakLoop), temp); |
| 12694 | out.push_back(join(temp)); | 12864 | out.push_back(join(temp)); |
| 12695 | } | 12865 | } |
| 12696 | } | 12866 | } |
| @@ -12778,7 +12948,7 @@ private: | |||
| 12778 | return; | 12948 | return; |
| 12779 | } | 12949 | } |
| 12780 | auto valName = getUnusedName("_tmp_"); | 12950 | auto valName = getUnusedName("_tmp_"); |
| 12781 | auto newValue = toAst<Exp_t>(valName, value); | 12951 | auto newValue = makeVariableExp(valName, value); |
| 12782 | ast_list<false, ExpListAssign_t> assignments; | 12952 | ast_list<false, ExpListAssign_t> assignments; |
| 12783 | for (auto exp : chainAssign->exprs.objects()) { | 12953 | for (auto exp : chainAssign->exprs.objects()) { |
| 12784 | auto assignment = assignmentFrom(static_cast<Exp_t*>(exp), newValue, exp); | 12954 | auto assignment = assignmentFrom(static_cast<Exp_t*>(exp), newValue, exp); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 8ab667d..62ce386 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -769,7 +769,46 @@ YueParser::YueParser() { | |||
| 769 | }); | 769 | }); |
| 770 | 770 | ||
| 771 | SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value); | 771 | SimpleTable = Seperator >> key_value >> *(space >> ',' >> space >> key_value); |
| 772 | Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue, dec_exp_level); | 772 | auto chain_value_start = pl::user(true_(), [](const item_t& item) { |
| 773 | auto current = item.begin->m_it; | ||
| 774 | if (current == item.input_end) return false; | ||
| 775 | auto ch = *current; | ||
| 776 | if (ch == '@') return true; | ||
| 777 | if (ch == '$') { | ||
| 778 | current++; | ||
| 779 | return current != item.input_end | ||
| 780 | && (*current == '_' || *current > 255 | ||
| 781 | || (*current >= 'a' && *current <= 'z') | ||
| 782 | || (*current >= 'A' && *current <= 'Z')); | ||
| 783 | } | ||
| 784 | if (!(ch == '_' || ch > 255 | ||
| 785 | || (ch >= 'a' && ch <= 'z') | ||
| 786 | || (ch >= 'A' && ch <= 'Z'))) { | ||
| 787 | return false; | ||
| 788 | } | ||
| 789 | bool ascii = true; | ||
| 790 | std::string name; | ||
| 791 | do { | ||
| 792 | if (*current > 255) { | ||
| 793 | ascii = false; | ||
| 794 | } else { | ||
| 795 | name += static_cast<char>(*current); | ||
| 796 | } | ||
| 797 | current++; | ||
| 798 | if (current == item.input_end) break; | ||
| 799 | ch = *current; | ||
| 800 | } while (ch == '_' || ch > 255 | ||
| 801 | || (ch >= 'a' && ch <= 'z') | ||
| 802 | || (ch >= 'A' && ch <= 'Z') | ||
| 803 | || (ch >= '0' && ch <= '9')); | ||
| 804 | if (ascii && Keywords.find(name) != Keywords.end()) return false; | ||
| 805 | while (current != item.input_end && (*current == ' ' || *current == '\t')) current++; | ||
| 806 | return current == item.input_end || *current != ':'; | ||
| 807 | }); | ||
| 808 | Value = inc_exp_level >> ensure( | ||
| 809 | chain_value_start >> ChainValue | | ||
| 810 | SimpleValue | SimpleTable | ChainValue, | ||
| 811 | dec_exp_level); | ||
| 773 | 812 | ||
| 774 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; | 813 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; |
| 775 | SingleString = '\'' >> *single_string_inner >> ('\'' | unclosed_single_string_error); | 814 | SingleString = '\'' >> *single_string_inner >> ('\'' | unclosed_single_string_error); |
| @@ -1114,11 +1153,62 @@ YueParser::YueParser() { | |||
| 1114 | 1153 | ||
| 1115 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; | 1154 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; |
| 1116 | 1155 | ||
| 1117 | SimpleValue = | 1156 | simple_value_fallback = |
| 1118 | TableLit | ConstValue | If | Switch | Try | With | | 1157 | TableLit | ConstValue | If | Switch | Try | With | |
| 1119 | ClassDecl | For | While | Repeat | Do | | 1158 | ClassDecl | For | While | Repeat | Do | |
| 1120 | UnaryValue | TblComprehension | Comprehension | | 1159 | UnaryValue | TblComprehension | Comprehension | |
| 1121 | FunLit | Num | VarArg; | 1160 | FunLit | Num | VarArg; |
| 1161 | SimpleValue = pl::dispatch([](input_it current, input_it end) -> size_t { | ||
| 1162 | if (current == end) return 14; | ||
| 1163 | auto startsKeyword = [current, end](std::string_view keyword) { | ||
| 1164 | auto it = current; | ||
| 1165 | for (char expected : keyword) { | ||
| 1166 | if (it == end || *it != static_cast<unsigned char>(expected)) return false; | ||
| 1167 | ++it; | ||
| 1168 | } | ||
| 1169 | if (it == end) return true; | ||
| 1170 | const auto ch = *it; | ||
| 1171 | return !(ch == '_' || (ch >= 'a' && ch <= 'z') | ||
| 1172 | || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')); | ||
| 1173 | }; | ||
| 1174 | switch (*current) { | ||
| 1175 | case '{': return 14; | ||
| 1176 | case '-': { | ||
| 1177 | auto next = current + 1; | ||
| 1178 | return next != end && *next == '>' ? 14 : 11; | ||
| 1179 | } | ||
| 1180 | case '#': case '~': return 11; | ||
| 1181 | case '.': { | ||
| 1182 | auto next = current + 1; | ||
| 1183 | if (next != end && *next >= '0' && *next <= '9') return 12; | ||
| 1184 | if (next != end && *next == '.') { | ||
| 1185 | ++next; | ||
| 1186 | if (next != end && *next == '.') return 13; | ||
| 1187 | } | ||
| 1188 | return 14; | ||
| 1189 | } | ||
| 1190 | default: | ||
| 1191 | if (*current >= '0' && *current <= '9') return 12; | ||
| 1192 | break; | ||
| 1193 | } | ||
| 1194 | if (startsKeyword("nil"sv) || startsKeyword("true"sv) || startsKeyword("false"sv)) return 1; | ||
| 1195 | if (startsKeyword("if"sv) || startsKeyword("unless"sv)) return 2; | ||
| 1196 | if (startsKeyword("switch"sv)) return 3; | ||
| 1197 | if (startsKeyword("try"sv)) return 4; | ||
| 1198 | if (startsKeyword("with"sv)) return 5; | ||
| 1199 | if (startsKeyword("class"sv)) return 6; | ||
| 1200 | if (startsKeyword("for"sv)) return 7; | ||
| 1201 | if (startsKeyword("while"sv) || startsKeyword("until"sv)) return 8; | ||
| 1202 | if (startsKeyword("repeat"sv)) return 9; | ||
| 1203 | if (startsKeyword("do"sv)) return 10; | ||
| 1204 | if (startsKeyword("not"sv)) return 11; | ||
| 1205 | return 14; | ||
| 1206 | }, { | ||
| 1207 | TableLit.this_ptr(), ConstValue.this_ptr(), If.this_ptr(), Switch.this_ptr(), | ||
| 1208 | Try.this_ptr(), With.this_ptr(), ClassDecl.this_ptr(), For.this_ptr(), | ||
| 1209 | While.this_ptr(), Repeat.this_ptr(), Do.this_ptr(), UnaryValue.this_ptr(), | ||
| 1210 | Num.this_ptr(), VarArg.this_ptr(), simple_value_fallback.this_ptr() | ||
| 1211 | }); | ||
| 1122 | 1212 | ||
| 1123 | ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '='); | 1213 | ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '='); |
| 1124 | 1214 | ||
| @@ -1204,7 +1294,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
| 1204 | error_list errors; | 1294 | error_list errors; |
| 1205 | try { | 1295 | try { |
| 1206 | State state; | 1296 | State state; |
| 1207 | return ::yue::start_with(*converted, r, errors, &state); | 1297 | return ::yue::start_with(*converted, r, errors, &state, false); |
| 1208 | } catch (const ParserError&) { | 1298 | } catch (const ParserError&) { |
| 1209 | return false; | 1299 | return false; |
| 1210 | } catch (const std::logic_error&) { | 1300 | } catch (const std::logic_error&) { |
| @@ -1232,7 +1322,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) { | |||
| 1232 | try { | 1322 | try { |
| 1233 | State state; | 1323 | State state; |
| 1234 | state.lax = lax; | 1324 | state.lax = lax; |
| 1235 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); | 1325 | res.node.set(::yue::parse(*(res.codes), r, errors, &state, false)); |
| 1236 | if (state.exportCount > 0) { | 1326 | if (state.exportCount > 0) { |
| 1237 | int index = 0; | 1327 | int index = 0; |
| 1238 | std::string moduleName; | 1328 | std::string moduleName; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index cfcbb48..f122b59 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -405,6 +405,7 @@ private: | |||
| 405 | AST_RULE(ChainValue); | 405 | AST_RULE(ChainValue); |
| 406 | AST_RULE(SimpleTable); | 406 | AST_RULE(SimpleTable); |
| 407 | AST_RULE(SimpleValue); | 407 | AST_RULE(SimpleValue); |
| 408 | NONE_AST_RULE(simple_value_fallback); | ||
| 408 | AST_RULE(Value); | 409 | AST_RULE(Value); |
| 409 | AST_RULE(LuaStringOpen); | 410 | AST_RULE(LuaStringOpen); |
| 410 | AST_RULE(LuaStringContent); | 411 | AST_RULE(LuaStringContent); |
