aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2026-07-24 17:12:21 +0800
committerLi Jin <dragon-fly@qq.com>2026-07-24 17:12:21 +0800
commit676da10a45af912d9226dce4cb447bf7bd923da0 (patch)
tree1d973ebb1dd157c6db9f99c50259d5248a2d8240 /src
parentc9f3a486cfdad6e134ec88b1e43717508e066796 (diff)
downloadyuescript-676da10a45af912d9226dce4cb447bf7bd923da0.tar.gz
yuescript-676da10a45af912d9226dce4cb447bf7bd923da0.tar.bz2
yuescript-676da10a45af912d9226dce4cb447bf7bd923da0.zip
Optimize compiler parsing and module state
Diffstat (limited to 'src')
-rw-r--r--src/yue.cpp132
-rw-r--r--src/yuescript/ast.cpp70
-rw-r--r--src/yuescript/ast.hpp95
-rw-r--r--src/yuescript/parser.cpp80
-rw-r--r--src/yuescript/parser.hpp15
-rw-r--r--src/yuescript/yue_compiler.cpp372
-rw-r--r--src/yuescript/yue_parser.cpp98
-rw-r--r--src/yuescript/yue_parser.h1
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>
24using namespace std::string_view_literals; 31using namespace std::string_view_literals;
25using namespace std::string_literals; 32using namespace std::string_literals;
26using namespace std::chrono_literals; 33using 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>
35template<class R> 42#endif
36std::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; 44class AsyncPool {
42 pthread_attr_init(&attr); 45public:
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
58template<class R> 93 for (auto& worker : _workers) {
59std::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
111private:
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
10THIS 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.*/ 10THIS 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
16namespace parserlib { 18namespace parserlib {
17 19
20namespace {
21
22thread_local ast_arena* currentAstArena = nullptr;
23
24struct alignas(std::max_align_t) ast_allocation_header {
25 ast_arena* arena = nullptr;
26};
27
28} // namespace
29
30void* 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
50ast_arena_scope::ast_arena_scope(ast_arena& arena)
51 : _previous(currentAstArena) {
52 currentAstArena = &arena;
53}
54
55ast_arena_scope::~ast_arena_scope() {
56 currentAstArena = _previous;
57}
58
59void* 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
72void 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
18traversal ast_node::traverse(const std::function<traversal(ast_node*)>& func) { 80traversal 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*/
128ast_node* parse(input& i, rule& g, error_list& el, void* ud) { 190ast_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*/
149ast_node* start_with(input& i, rule& g, error_list& el, void* ud) { 211ast_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 {
25using namespace std::string_view_literals; 30using namespace std::string_view_literals;
26 31
27class ast_node; 32class ast_node;
33class ast_arena;
28template <bool Required, class T> 34template <bool Required, class T>
29class ast_ptr; 35class ast_ptr;
30template <bool Required, class T> 36template <bool Required, class T>
@@ -63,10 +69,41 @@ enum class traversal {
63 Stop 69 Stop
64}; 70};
65 71
72class ast_arena {
73public:
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
80private:
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
89class ast_arena_scope {
90public:
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
96private:
97 ast_arena* _previous = nullptr;
98};
99
66/** Base class for AST nodes. 100/** Base class for AST nodes.
67 */ 101 */
68class ast_node : public input_range { 102class ast_node : public input_range {
69public: 103public:
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
155class ast_member; 192class ast_member;
156 193
157/** type of ast member vector. 194class ast_member_vector {
158 */ 195public:
159typedef 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
233private:
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 */
163class ast_container : public ast_node { 243class ast_container : public ast_node {
164public: 244public:
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*/
601ast_node* parse(input& i, rule& g, error_list& el, void* ud); 683ast_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*/
611ast_node* start_with(input& i, rule& g, error_list& el, void* ud); 694ast_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 {
38namespace parserlib { 38namespace parserlib {
39 39
40input utf8_decode(const std::string& str) { 40input 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
876class _dispatch : public _expr {
877public:
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
904private:
905 dispatch_handler m_handler;
906 std::vector<_expr*> m_rules;
907};
908
857// eof 909// eof
858class _eof : public _expr { 910class _eof : public _expr {
859public: 911public:
@@ -930,6 +982,10 @@ _state::_state(_context& con)
930 982
931// parse non-term rule. 983// parse non-term rule.
932bool _context::parse_non_term(rule& r) { 984bool _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.
1026bool _context::parse_term(rule& r) { 1082bool _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
1682expr 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*/
1632bool parse(input& i, rule& g, error_list& el, void* st, void* ud) { 1696bool 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*/
1667bool start_with(input& i, rule& g, error_list& el, void* st, void* ud) { 1731bool 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};
68typedef std::function<bool(const item_t&)> user_handler; 71typedef std::function<bool(const item_t&)> user_handler;
72typedef 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 */
403expr user(const expr& e, const user_handler& handler); 407expr 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*/
412expr 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*/
415bool parse(input& i, rule& g, error_list& el, void* st, void* ud); 425bool 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*/
427bool start_with(input& i, rule& g, error_list& el, void* st, void* ud); 438bool 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);