From 8acb48264d3ae87e5cdae2fea4207be22cf08a97 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Mon, 8 Mar 2021 21:02:05 +0800 Subject: add new syntax for issue #41. fix a issue for destructure syntax with TableBlock. try fix luarocks installing problem again for issue #42. --- CMakeLists.txt | 72 ++++++++-------- spec/inputs/destructure.yue | 23 ++++- spec/inputs/metatable.yue | 11 +++ src/yuescript/ast.hpp | 2 +- src/yuescript/yue_ast.h | 2 +- src/yuescript/yue_compiler.cpp | 188 ++++++++++++++++++++++++++--------------- src/yuescript/yue_parser.cpp | 4 +- 7 files changed, 195 insertions(+), 107 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce5a7f7..55bcd7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,42 +1,46 @@ -project ( yue CXX ) -cmake_minimum_required ( VERSION 3.1 ) - -MESSAGE(STATUS "Lua: using information from luarocks") - -MESSAGE(STATUS "LUA_LIBDIR: " ${LUA_INCDIR}/../lib " " ${LUA_INCDIR}/../../lib ) -MESSAGE(STATUS "LUA_INCDIR: " ${LUA_INCDIR}) -MESSAGE(STATUS "LUA: " ${LUA}) - -SET(LUA_EXECUTABLE "${LUA}") -SET(LUA_INCLUDE_DIR "${LUA_INCDIR}") - -GET_FILENAME_COMPONENT(LUA_EXEC_NAME ${LUA} NAME_WE) -IF(LUA_EXEC_NAME STREQUAL "luajit") - FIND_LIBRARY(LUA_LIBRARIES - NAMES luajit libluajit - PATHS ${LUA_INCDIR}/../lib ${LUA_INCDIR}/../../lib - NO_DEFAULT_PATH) -ELSEIF(LUA_EXEC_NAME MATCHES "lua.*") - FIND_LIBRARY(LUA_LIBRARIES - NAMES lua lua54 lua53 lua52 lua51 liblua liblua54 liblua53 liblua52 liblua51 liblua5.4 liblua5.3 liblua5.2 liblua5.1 - PATHS ${LUA_INCDIR}/../lib ${LUA_INCDIR}/../../lib - NO_DEFAULT_PATH) -ENDIF() +project(yue CXX) +cmake_minimum_required(VERSION 3.1) + +SET(LUA_LIBDIR ${LUA_INCDIR}/../lib " " ${LUA_INCDIR}/../../lib) + +find_package(Lua) +IF(LUA_FOUND) + SET(LUA_LIBRARIES "${LUA_LIBRARY}") +ELSE(LUA_FOUND) + MESSAGE(STATUS "Lua: using information from luarocks") + SET(LUA_INCLUDE_DIR "${LUA_INCDIR}") + GET_FILENAME_COMPONENT(LUA_EXEC_NAME ${LUA} NAME_WE) + IF(LUA_EXEC_NAME STREQUAL "luajit") + FIND_LIBRARY(LUA_LIBRARIES + NAMES luajit libluajit + PATHS ${LUA_LIBDIR} + NO_DEFAULT_PATH) + ELSEIF(LUA_EXEC_NAME MATCHES "lua.*") + FIND_LIBRARY(LUA_LIBRARIES + NAMES lua lua54 lua53 lua52 lua51 liblua liblua54 liblua53 liblua52 liblua51 liblua5.4 liblua5.3 liblua5.2 liblua5.1 + PATHS ${LUA_LIBDIR} + NO_DEFAULT_PATH) + ENDIF(LUA_EXEC_NAME) +ENDIF(LUA_FOUND) + +MESSAGE(STATUS "Lua: " ${LUA}) +MESSAGE(STATUS "Lua include: " ${LUA_INCLUDE_DIR}) MESSAGE(STATUS "Lua library: ${LUA_LIBRARIES}") -enable_language( CXX ) -include_directories( src ${LUA_INCLUDE_DIR} ) -add_definitions( -std=c++17 -O3 -fPIC ) +enable_language(CXX) +include_directories(src ${LUA_INCLUDE_DIR}) +add_definitions(-std=c++17 -O3 -fPIC) -add_library( libyue MODULE src/yuescript/ast.cpp src/yuescript/parser.cpp src/yuescript/yue_parser.cpp src/yuescript/yue_compiler.cpp src/yuescript/yuescript.cpp) -set_target_properties( libyue PROPERTIES PREFIX "" ) -set_target_properties( libyue PROPERTIES OUTPUT_NAME "yue" ) -target_link_libraries( libyue ${LUA_LIBRARIES} ) +add_library(libyue MODULE src/yuescript/ast.cpp src/yuescript/parser.cpp src/yuescript/yue_parser.cpp src/yuescript/yue_compiler.cpp src/yuescript/yuescript.cpp) +set_target_properties(libyue PROPERTIES PREFIX "") +set_target_properties(libyue PROPERTIES OUTPUT_NAME "yue") +target_link_libraries(libyue ${LUA_LIBRARIES}) -add_executable( yue src/yuescript/ast.cpp src/yuescript/yue_compiler.cpp src/yuescript/yue_parser.cpp src/yuescript/yuescript.cpp src/yuescript/parser.cpp src/yue.cpp ) -target_link_libraries( yue ${LUA_LIBRARIES} ) +add_executable(yue src/yuescript/ast.cpp src/yuescript/yue_compiler.cpp src/yuescript/yue_parser.cpp src/yuescript/yuescript.cpp src/yuescript/parser.cpp src/yue.cpp) +target_link_libraries(yue ${LUA_LIBRARIES}) +target_link_options(yue PRIVATE -ldl -lpthread) if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - target_link_options( yue PRIVATE -ldl -lpthread -lstdc++fs ) + target_link_options(yue PRIVATE -lstdc++fs) endif() install(CODE "") diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 6b52441..c68045d 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue @@ -41,7 +41,28 @@ do "Bellagio, Italy 22021" } - {poet: {:name, address: {street, city}}} = futurists + do {poet: {:name, address: {street, city}}} = futurists + + do { + :sculptor + :painter + poet: + :name + address: + * street + * city + } = futurists + +do + a: + b: c + d: e = tb + +do + a: + * b: c + * d: e + * f = tb -- diff --git a/spec/inputs/metatable.yue b/spec/inputs/metatable.yue index 13ea917..100844c 100644 --- a/spec/inputs/metatable.yue +++ b/spec/inputs/metatable.yue @@ -48,4 +48,15 @@ with tb b = t#.close#.test c = t #.close# .test +#:mt = a +a = #:mt +a = #:__index:mt + +local index +#:__index:index = a +:index# = a + +do #:{new:ctor, :update} = a +do {new:ctor, :update} = a.# + nil diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index eb5cd69..162a82e 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp @@ -420,7 +420,7 @@ public: return false; } - const node_container& objects() const { + const node_container& objects() const { return m_objects; } diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index b673eb3..96968c9 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -431,7 +431,7 @@ AST_NODE(meta_variable_pair) AST_END(meta_variable_pair) AST_NODE(meta_normal_pair) - ast_sel key; + ast_sel key; ast_sel value; AST_MEMBER(meta_normal_pair, &key, &value) AST_END(meta_normal_pair) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index a958462..e8d028d 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -59,7 +59,7 @@ inline std::string s(std::string_view sv) { return std::string(sv); } -const std::string_view version = "0.7.1"sv; +const std::string_view version = "0.7.2"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -1366,19 +1366,32 @@ private: std::list destructFromExp(ast_node* node) { const node_container* tableItems = nullptr; - if (ast_is(node)) { - auto item = singleValueFrom(node)->item.get(); - if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); - auto tbA = item->getByPath(); - if (tbA) { - tableItems = &tbA->values.objects(); - } else { - auto tbB = ast_cast(item); - if (tbB) tableItems = &tbB->pairs.objects(); + switch (node->getId()) { + case id(): { + auto item = singleValueFrom(node)->item.get(); + if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); + auto tbA = item->getByPath(); + if (tbA) { + tableItems = &tbA->values.objects(); + } else { + auto tbB = ast_cast(item); + if (tbB) tableItems = &tbB->pairs.objects(); + } + break; + } + case id(): { + auto table = ast_cast(node); + tableItems = &table->values.objects(); + break; } - } else if (auto table = ast_cast(node)) { - tableItems = &table->values.objects(); + case id(): { + auto table = ast_cast(node); + tableItems = &table->values.objects(); + break; + } + default: YUEE("AST node mismatch", node); break; } + if (!tableItems) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); std::list pairs; int index = 0; for (auto pair : *tableItems) { @@ -1412,7 +1425,7 @@ private: pairs.push_back({ isVariable, varName, - s("["sv) + std::to_string(index) + s("]"sv) + '[' + std::to_string(index) + ']' }); } break; @@ -1429,23 +1442,29 @@ private: } case id(): { auto np = static_cast(pair); - auto key = np->key->getByPath(); - if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); + std::string keyName; + if (np->key) { + auto key = np->key->getByPath(); + if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); + keyName = _parser.toString(key); + if (Keywords.find(keyName) != Keywords.end()) { + keyName = s("[\""sv) + keyName + s("\"]"sv); + } else { + keyName = s("."sv) + keyName; + } + } if (auto exp = np->value.as()) { if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); auto item = singleValueFrom(exp)->item.get(); if (ast_is(item) || item->getByPath()) { auto subPairs = destructFromExp(exp); - auto name = _parser.toString(key); for (auto& p : subPairs) { - if (Keywords.find(name) != Keywords.end()) { - pairs.push_back({p.isVariable, p.name, - s("[\""sv) + name + s("\"]"sv) + p.structure}); - } else { - pairs.push_back({p.isVariable, p.name, - s("."sv) + name + p.structure}); - } + pairs.push_back({ + p.isVariable, + p.name, + keyName + p.structure + }); } } else { bool lintGlobal = _config.lintGlobalVariable; @@ -1458,32 +1477,39 @@ private: varName = std::move(temp.back()); } _config.lintGlobalVariable = lintGlobal; - auto name = _parser.toString(key); - if (Keywords.find(name) != Keywords.end()) { - pairs.push_back({ - isVariable, - varName, - s("[\""sv) + name + s("\"]"sv) - }); - } else { - pairs.push_back({ - isVariable, - varName, - s("."sv) + name - }); - } + pairs.push_back({ + isVariable, + varName, + keyName + }); } break; } if (np->value.is()) { - auto subPairs = destructFromExp(pair); + auto subPairs = destructFromExp(np->value); for (auto& p : subPairs) { - pairs.push_back({p.isVariable, p.name, - s("."sv) + _parser.toString(key) + p.structure}); + pairs.push_back({ + p.isVariable, + p.name, + keyName + p.structure + }); } } break; } + case id(): { + auto tb = static_cast(pair); + ++index; + auto subPairs = destructFromExp(tb); + for (auto& p : subPairs) { + pairs.push_back({ + p.isVariable, + p.name, + '[' + std::to_string(index) + ']' + p.structure + }); + } + break; + } default: YUEE("AST node mismatch", pair); break; } } @@ -1498,9 +1524,10 @@ private: auto exprs = assignment->expList->exprs.objects(); auto values = assignment->action.to()->values.objects(); size_t size = std::max(exprs.size(), values.size()); - ast_ptr var; + ast_list cache; if (exprs.size() < size) { - var = toAst("_"sv, x); + auto var = toAst("_"sv, x); + cache.push_back(var); while (exprs.size() < size) exprs.emplace_back(var); } ast_ptr nullNode; @@ -1551,18 +1578,20 @@ private: case id(): { auto mp = static_cast(item); auto newPair = item->new_ptr(); - switch (mp->key->getId()) { - case id(): { - auto key = _parser.toString(mp->key); - _buf << "__"sv << key; - auto newKey = toAst(clearBuf(), mp->key); - newPair->key.set(newKey); - break; + if (mp->key) { + switch (mp->key->getId()) { + case id(): { + auto key = _parser.toString(mp->key); + _buf << "__"sv << key; + auto newKey = toAst(clearBuf(), mp->key); + newPair->key.set(newKey); + break; + } + case id(): + newPair->key.set(mp->key); + break; + default: YUEE("AST node mismatch", mp->key); break; } - case id(): - newPair->key.set(mp->key); - break; - default: YUEE("AST node mismatch", mp->key); break; } newPair->value.set(mp->value); subMetaDestruct->values.push_back(newPair); @@ -5150,6 +5179,7 @@ private: str_list temp; incIndentOffset(); auto metatable = table->new_ptr(); + ast_sel metatableItem; for (auto pair : pairs) { bool isMetamethod = false; switch (pair->getId()) { @@ -5161,6 +5191,9 @@ private: case id(): { isMetamethod = true; auto mp = static_cast(pair); + if (metatableItem) { + throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); + } auto name = _parser.toString(mp->name); _buf << "__"sv << name << ':' << name; auto newPair = toAst(clearBuf(), pair); @@ -5171,21 +5204,31 @@ private: isMetamethod = true; auto mp = static_cast(pair); auto newPair = pair->new_ptr(); - switch (mp->key->getId()) { - case id(): { - auto key = _parser.toString(mp->key); - _buf << "__"sv << key; - auto newKey = toAst(clearBuf(), mp->key); - newPair->key.set(newKey); - break; + if (mp->key) { + if (metatableItem) { + throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->key)); } - case id(): - newPair->key.set(mp->key); - break; - default: YUEE("AST node mismatch", mp->key); break; + switch (mp->key->getId()) { + case id(): { + auto key = _parser.toString(mp->key); + _buf << "__"sv << key; + auto newKey = toAst(clearBuf(), mp->key); + newPair->key.set(newKey); + break; + } + case id(): + newPair->key.set(mp->key); + break; + default: YUEE("AST node mismatch", mp->key); break; + } + newPair->value.set(mp->value); + metatable->pairs.push_back(newPair); + } else { + if (!metatable->pairs.empty()) { + throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->value)); + } + metatableItem.set(mp->value); } - newPair->value.set(mp->value); - metatable->pairs.push_back(newPair); break; } default: YUEE("AST node mismatch", pair); break; @@ -5194,7 +5237,7 @@ private: temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair); } } - if (metatable->pairs.empty()) { + if (metatable->pairs.empty() && !metatableItem) { out.push_back(s("{"sv) + nll(table) + join(temp)); decIndentOffset(); out.back() += (indent() + s("}"sv)); @@ -5211,7 +5254,16 @@ private: } tabStr += ", "sv; str_list tmp; - transform_simple_table(metatable, tmp); + if (!metatable->pairs.empty()) { + transform_simple_table(metatable, tmp); + } else switch (metatableItem->getId()) { + case id(): + transformExp(static_cast(metatableItem.get()), tmp, ExpUsage::Closure); + break; + case id(): + transformTableBlock(static_cast(metatableItem.get()), tmp); + break; + } tabStr += tmp.back(); tabStr += s(")"sv); out.push_back(tabStr); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index ec6c997..2234a59 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -328,7 +328,7 @@ YueParser::YueParser() { unary_operator = expr('-') >> not_(set(">=") | space_one) | - expr('#') | + expr('#') >> not_(':') | expr('~') >> not_(expr('=') | space_one) | expr("not") >> not_(AlphaNum); unary_exp = *(Space >> unary_operator) >> expo_exp; @@ -525,7 +525,7 @@ YueParser::YueParser() { meta_variable_pair = sym(':') >> Variable >> expr('#'); - meta_normal_pair = (Space >> Name | sym('[') >> Exp >> sym(']')) >> expr("#:") >> + meta_normal_pair = Space >> -(Name | symx('[') >> Exp >> sym(']')) >> expr("#:") >> (Exp | TableBlock | +(SpaceBreak) >> Exp); KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; -- cgit v1.2.3-55-g6feb