From 125f709b065acb35bcd216001720c0bb4635dd25 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Mon, 22 Nov 2021 01:48:26 +0800 Subject: clean up. --- src/yuescript/yue_ast.h | 14 ++- src/yuescript/yue_compiler.cpp | 196 ++++++++++++++++++++--------------------- src/yuescript/yue_parser.cpp | 75 ++++++++-------- src/yuescript/yue_parser.h | 1 + 4 files changed, 145 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 719b1cd..fe9c7b9 100755 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -176,7 +176,7 @@ AST_END(ImportTabLit) AST_NODE(ImportAs) ast_ptr literal; - ast_sel target; + ast_sel target; AST_MEMBER(ImportAs, &literal, &target) AST_END(ImportAs) @@ -691,7 +691,7 @@ AST_NODE(FunLit) AST_END(FunLit) AST_NODE(MacroName) - ast_ptr name; + ast_ptr name; AST_MEMBER(MacroName, &name) AST_END(MacroName) @@ -701,6 +701,11 @@ AST_NODE(MacroLit) AST_MEMBER(MacroLit, &argsDef, &body) AST_END(MacroLit) +AST_NODE(MacroInPlace) + ast_ptr body; + AST_MEMBER(MacroInPlace, &body) +AST_END(MacroInPlace) + AST_NODE(Macro) ast_ptr name; ast_ptr macroLit; @@ -775,8 +780,9 @@ AST_END(statement_sep) AST_NODE(Statement) ast_sel content; + Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, + BreakLoop_t, Label_t, Goto_t, Backcall_t, LocalAttrib_t, + PipeBody_t, ExpListAssign_t> content; ast_ptr appendix; ast_ptr needSep; AST_MEMBER(Statement, &content, &appendix, &needSep) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 14e33a5..b3f6bdd 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -60,7 +60,7 @@ using namespace parserlib; typedef std::list str_list; -const std::string_view version = "0.9.0"sv; +const std::string_view version = "0.9.1"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -1007,6 +1007,7 @@ private: case id(): transformGlobal(static_cast(content), out); break; case id(): transformExport(static_cast(content), out); break; case id(): transformMacro(static_cast(content), out, false); break; + case id(): transformMacroInPlace(static_cast(content)); break; case id(): transformBreakLoop(static_cast(content), out); break; case id(): transformLabel(static_cast(content), out); break; case id(): transformGoto(static_cast(content), out); break; @@ -3919,6 +3920,55 @@ private: } } + void transformMacroInPlace(MacroInPlace_t* macroInPlace) { +#ifdef YUE_NO_MACRO + throw std::logic_error(_info.errorMessage("macro feature not supported"sv, macroInPlace)); +#else // YUE_NO_MACRO + auto x = macroInPlace; + pushCurrentModule(); // cur + int top = lua_gettop(L) - 1; + DEFER(lua_settop(L, top)); + lua_pop(L, 1); // empty + auto fcodes = _parser.toString(macroInPlace).substr(1); + Utils::trim(fcodes); + pushYue("loadstring"sv); // loadstring + lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes + lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk + pushOptions(macroInPlace->m_begin.m_line - 1); // loadstring codes chunk options + if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err + std::string err = lua_tostring(L, -1); + throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); + } // f err + if (lua_isnil(L, -2) != 0) { // f == nil, f err + std::string err = lua_tostring(L, -1); + throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); + } + lua_pop(L, 1); // f + pushYue("pcall"sv); // f pcall + lua_insert(L, -2); // pcall f + if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc + std::string err = lua_tostring(L, -1); + throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); + } // success res + if (lua_toboolean(L, -2) == 0) { + std::string err = lua_tostring(L, -1); + throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); + } // true macroFunc + lua_remove(L, -2); // macroFunc + pushYue("pcall"sv); // macroFunc pcall + lua_insert(L, -2); // pcall macroFunc + bool success = lua_pcall(L, 1, 2, 0) == 0; + if (!success) { // err + std::string err = lua_tostring(L, -1); + throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); + } // success err + if (lua_toboolean(L, -2) == 0) { + std::string err = lua_tostring(L, -1); + throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); + } +#endif // YUE_NO_MACRO + } + #ifndef YUE_NO_MACRO std::string expandBuiltinMacro(const std::string& name, ast_node* x) { if (name == "LINE"sv) { @@ -3933,8 +3983,8 @@ private: std::tuple expandMacroStr(ChainValue_t* chainValue) { const auto& chainList = chainValue->items.objects(); auto x = ast_to(chainList.front())->item.to(); - auto macroName = x->name ? _parser.toString(x->name) : Empty; - if (!macroName.empty() && !_useModule) { + auto macroName = _parser.toString(x->name); + if (!_useModule) { auto code = expandBuiltinMacro(macroName, x); if (!code.empty()) return {Empty, code, {}}; throw std::logic_error(_info.errorMessage("can not resolve macro"sv, x)); @@ -3942,57 +3992,6 @@ private: pushCurrentModule(); // cur int top = lua_gettop(L) - 1; DEFER(lua_settop(L, top)); - if (macroName.empty()) { - lua_pop(L, 1); // empty - const node_container* args = nullptr; - auto item = *(++chainList.begin()); - if (auto invoke = ast_cast(item)) { - args = &invoke->args.objects(); - } else { - args = &ast_to(item)->args.objects(); - } - if (args->size() != 1) { - throw std::logic_error(_info.errorMessage("in-place macro must be followed by a compile time function"sv, x)); - } - auto fcodes = _parser.toString(args->back()); - Utils::trim(fcodes); - pushYue("loadstring"sv); // loadstring - lua_pushlstring(L, fcodes.c_str(), fcodes.size()); // loadstring codes - lua_pushliteral(L, "=(macro in-place)"); // loadstring codes chunk - pushOptions(args->back()->m_begin.m_line - 1); // loadstring codes chunk options - if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), f err - std::string err = lua_tostring(L, -1); - throw std::logic_error(_info.errorMessage("failed to load macro codes\n"s + err, x)); - } // f err - if (lua_isnil(L, -2) != 0) { // f == nil, f err - std::string err = lua_tostring(L, -1); - throw std::logic_error(_info.errorMessage("failed to load macro codes, at (macro in-place): "s + err, x)); - } - lua_pop(L, 1); // f - pushYue("pcall"sv); // f pcall - lua_insert(L, -2); // pcall f - if (lua_pcall(L, 1, 2, 0) != 0) { // f(), success macroFunc - std::string err = lua_tostring(L, -1); - throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); - } // success res - if (lua_toboolean(L, -2) == 0) { - std::string err = lua_tostring(L, -1); - throw std::logic_error(_info.errorMessage("failed to generate macro function\n"s + err, x)); - } // true macroFunc - lua_remove(L, -2); // macroFunc - pushYue("pcall"sv); // macroFunc pcall - lua_insert(L, -2); // pcall macroFunc - bool success = lua_pcall(L, 1, 2, 0) == 0; - if (!success) { // err - std::string err = lua_tostring(L, -1); - throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); - } // success err - if (lua_toboolean(L, -2) == 0) { - std::string err = lua_tostring(L, -1); - throw std::logic_error(_info.errorMessage("failed to expand macro: "s + err, x)); - } - return {Empty, Empty, {}}; - } lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName lua_rawget(L, -2); // cur[macroName], cur macroFunc if (lua_isfunction(L, -1) == 0) { @@ -6097,38 +6096,49 @@ private: auto name = moduleNameFrom(import->literal); import->target.set(toAst(name, x)); } - if (auto tabLit = import->target.as()) { - auto newTab = x->new_ptr(); -#ifndef YUE_NO_MACRO - bool importAllMacro = false; + if (ast_is(import->target)) { + bool importAllMacro = import->target.is(); std::list> macroPairs; - for (auto item : tabLit->items.objects()) { - switch (item->getId()) { - case id(): { - auto macroName = static_cast(item); - auto name = _parser.toString(macroName->name); - macroPairs.emplace_back(name, name); - break; - } - case id(): { - auto pair = static_cast(item); - macroPairs.emplace_back(_parser.toString(pair->key->name), _parser.toString(pair->value->name)); - break; + auto newTab = x->new_ptr(); + if (auto tabLit = import->target.as()) { + for (auto item : tabLit->items.objects()) { + switch (item->getId()) { +#ifdef YUE_NO_MACRO + case id(): + case id(): + case id(): { + throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); + break; + } +#else // YUE_NO_MACRO + case id(): { + auto macroName = static_cast(item); + auto name = _parser.toString(macroName->name); + macroPairs.emplace_back(name, name); + break; + } + case id(): { + auto pair = static_cast(item); + macroPairs.emplace_back(_parser.toString(pair->key->name), _parser.toString(pair->value->name)); + break; + } + case id(): + if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); + importAllMacro = true; + break; +#endif // YUE_NO_MACRO + case id(): + case id(): + case id(): + case id(): + case id(): + newTab->items.push_back(item); + break; + default: YUEE("AST node mismatch", item); break; } - case id(): - if (importAllMacro) throw std::logic_error(_info.errorMessage("import all macro symbol duplicated"sv, item)); - importAllMacro = true; - break; - case id(): - case id(): - case id(): - case id(): - case id(): - newTab->items.push_back(item); - break; - default: YUEE("AST node mismatch", item); break; } } +#ifndef YUE_NO_MACRO if (importAllMacro || !macroPairs.empty()) { auto moduleName = _parser.toString(import->literal); Utils::replace(moduleName, "'"sv, ""sv); @@ -6188,21 +6198,8 @@ private: } } #else // YUE_NO_MACRO - for (auto item : tabLit->items.objects()) { - switch (item->getId()) { - case id(): - case id(): - case id(): { - throw std::logic_error(_info.errorMessage("macro feature not supported"sv, item)); - break; - } - case id(): - case id(): - case id(): - newTab->items.push_back(item); - break; - default: YUEE("AST node mismatch", item); break; - } + if (importAllMacro) { + throw std::logic_error(_info.errorMessage("macro feature not supported"sv, import->target)); } #endif // YUE_NO_MACRO if (newTab->items.empty()) { @@ -6220,13 +6217,14 @@ private: auto chainValue = x->new_ptr(); chainValue->items.push_back(callable); value->item.set(chainValue); - } else { - auto tabLit = ast_to(target); + } else if (auto tabLit = ast_cast(target)) { auto simpleValue = x->new_ptr(); auto tableLit = x->new_ptr(); tableLit->values.dup(tabLit->items); simpleValue->value.set(tableLit); value->item.set(simpleValue); + } else { + return; } auto exp = newExp(value, x); auto assignList = x->new_ptr(); diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 5628062..9257fab 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -71,12 +71,12 @@ YueParser::YueParser() { #define sym(str) (Space >> str) #define symx(str) expr(str) #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> Cut) - #define key(str) (Space >> str >> not_(AlphaNum)) + #define key(str) (str >> not_(AlphaNum)) #define disable_do(patt) (DisableDo >> ((patt) >> EnableDo | EnableDo >> Cut)) #define disable_chain(patt) (DisableChain >> ((patt) >> EnableChain | EnableChain >> Cut)) #define disable_do_chain(patt) (DisableDoChain >> ((patt) >> EnableDoChain | EnableDoChain >> Cut)) #define disable_arg_table_block(patt) (DisableArgTableBlock >> ((patt) >> EnableArgTableBlock | EnableArgTableBlock >> Cut)) - #define plain_body_with(str) (-key(str) >> InBlock | key(str) >> Statement) + #define plain_body_with(str) (-(Space >> key(str)) >> InBlock | Space >> key(str) >> Statement) #define plain_body (InBlock | Statement) Variable = pl::user(Name, [](const item_t& item) { @@ -182,12 +182,12 @@ YueParser::YueParser() { Attrib = (expr("const") | expr("close")) >> not_(AlphaNum); Local = key("local") >> (Space >> local_flag | local_values); - LocalAttrib = Space >> Attrib >> NameList >> Assign; + LocalAttrib = Attrib >> NameList >> Assign; colon_import_name = sym('\\') >> Space >> Variable; ImportName = colon_import_name | Space >> Variable; ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); - ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; + ImportFrom = ImportNameList >> *SpaceBreak >> Space >> key("from") >> Exp; import_literal_inner = (range('a', 'z') | range('A', 'Z') | set("_-")) >> *(AlphaNum | '-'); import_literal_chain = Seperator >> import_literal_inner >> *(expr('.') >> import_literal_inner); @@ -208,11 +208,11 @@ YueParser::YueParser() { -import_tab_lines >> White >> sym('}') | KeyValue >> *(sym(',') >> KeyValue)); - ImportAs = ImportLiteral >> -(key("as") >> (ImportTabLit | Space >> Variable)); + ImportAs = ImportLiteral >> -(Space >> key("as") >> Space >> (ImportTabLit | Variable | import_all_macro)); Import = key("import") >> (ImportAs | ImportFrom); - Label = Space >> expr("::") >> LabelName >> expr("::"); + Label = expr("::") >> LabelName >> expr("::"); Goto = key("goto") >> Space >> LabelName; @@ -222,9 +222,9 @@ YueParser::YueParser() { WithExp = ExpList >> -Assign; - With = key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); - SwitchCase = key("when") >> disable_chain(ExpList) >> plain_body_with("then"); - SwitchElse = key("else") >> plain_body; + With = Space >> key("with") >> -existential_op >> disable_do_chain(WithExp) >> plain_body_with("do"); + SwitchCase = Space >> key("when") >> disable_chain(ExpList) >> plain_body_with("then"); + SwitchElse = Space >> key("else") >> plain_body; SwitchBlock = *EmptyLine >> Advance >> Seperator >> @@ -233,18 +233,18 @@ YueParser::YueParser() { -(+SpaceBreak >> SwitchElse) >> PopIndent; - Switch = key("switch") >> disable_do(Exp) >> -key("do") + Switch = Space >> key("switch") >> disable_do(Exp) >> -(Space >> key("do")) >> -Space >> Break >> SwitchBlock; IfCond = disable_chain(Exp >> -Assign); - IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> key("elseif") >> IfCond >> plain_body_with("then"); - IfElse = -(Break >> *EmptyLine >> CheckIndent) >> key("else") >> plain_body; + IfElseIf = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("elseif") >> IfCond >> plain_body_with("then"); + IfElse = -(Break >> *EmptyLine >> CheckIndent) >> Space >> key("else") >> plain_body; IfType = (expr("if") | expr("unless")) >> not_(AlphaNum); If = Space >> IfType >> IfCond >> plain_body_with("then") >> *IfElseIf >> -IfElse; WhileType = (expr("while") | expr("until")) >> not_(AlphaNum); - While = Space >> WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); - Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> key("until") >> Exp; + While = WhileType >> disable_do_chain(Exp) >> plain_body_with("do"); + Repeat = key("repeat") >> Body >> Break >> *EmptyLine >> CheckIndent >> Space >> key("until") >> Exp; for_step_value = sym(',') >> Exp; for_args = Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; @@ -253,10 +253,10 @@ YueParser::YueParser() { for_in = star_exp | ExpList; - ForEach = key("for") >> AssignableNameList >> key("in") >> + ForEach = key("for") >> AssignableNameList >> Space >> key("in") >> disable_do_chain(for_in) >> plain_body_with("do"); - Do = pl::user(key("do"), [](const item_t& item) { + Do = pl::user(Space >> key("do"), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); return st->doStack.empty() || st->doStack.top(); }) >> Body; @@ -299,15 +299,15 @@ YueParser::YueParser() { return true; }); - Comprehension = sym('[') >> Exp >> CompInner >> sym(']'); + Comprehension = sym('[') >> Exp >> Space >> CompInner >> sym(']'); comp_value = sym(',') >> Exp; - TblComprehension = sym('{') >> Exp >> -comp_value >> CompInner >> sym('}'); + TblComprehension = sym('{') >> Exp >> -comp_value >> Space >> CompInner >> sym('}'); CompInner = Seperator >> (CompForEach | CompFor) >> *CompClause; star_exp = sym('*') >> Exp; - CompForEach = key("for") >> AssignableNameList >> key("in") >> (star_exp | Exp); + CompForEach = key("for") >> AssignableNameList >> Space >> key("in") >> (star_exp | Exp); CompFor = key("for") >> Space >> Variable >> sym('=') >> Exp >> sym(',') >> Exp >> -for_step_value; - CompClause = CompFor | CompForEach | key("when") >> Exp; + CompClause = Space >> (CompFor | CompForEach | key("when") >> Exp); Assign = sym('=') >> Seperator >> (With | If | Switch | TableBlock | Exp >> *(Space >> set(",;") >> Exp)); @@ -491,10 +491,10 @@ YueParser::YueParser() { ClassBlock = +SpaceBreak >> Advance >> Seperator >> ClassLine >> *(+SpaceBreak >> ClassLine) >> PopIndent; ClassDecl = - key("class") >> not_(expr(':')) >> + Space >> key("class") >> not_(expr(':')) >> -Assignable >> - -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> - -(key("using") >> PreventIndent >> ensure(ExpList, PopIndent)) >> + -(Space >> key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> + -(Space >> key("using") >> PreventIndent >> ensure(ExpList, PopIndent)) >> -ClassBlock; global_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); @@ -507,13 +507,13 @@ YueParser::YueParser() { State* st = reinterpret_cast(item.user_data); st->exportCount++; return true; - }) >> (pl::user(export_default >> Exp, [](const item_t& item) { + }) >> (pl::user(Space >> export_default >> Exp, [](const item_t& item) { State* st = reinterpret_cast(item.user_data); bool isValid = !st->exportDefault && st->exportCount == 1; st->exportDefault = true; return isValid; }) - | (not_(export_default) >> pl::user(true_(), [](const item_t& item) { + | (not_(Space >> export_default) >> pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); if (st->exportDefault && st->exportCount > 1) { return false; @@ -521,7 +521,7 @@ YueParser::YueParser() { return true; } }) >> ExpList >> -Assign) - | Macro) >> not_(Space >> statement_appendix); + | Space >> Macro) >> not_(Space >> statement_appendix); variable_pair = sym(':') >> Variable >> not_('#'); @@ -560,16 +560,17 @@ YueParser::YueParser() { ) ); - outer_var_shadow = key("using") >> (NameList | Space >> expr("nil")); + outer_var_shadow = Space >> key("using") >> (NameList | Space >> expr("nil")); FnArgsDef = sym('(') >> White >> -FnArgDefList >> -outer_var_shadow >> White >> sym(')'); fn_arrow = expr("->") | expr("=>"); FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; - MacroName = expr('$') >> -Name; + MacroName = expr('$') >> Name; macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); MacroLit = -macro_args_def >> Space >> expr("->") >> Body; Macro = key("macro") >> Space >> Name >> sym('=') >> MacroLit; + MacroInPlace = expr('$') >> Space >> expr("->") >> Body; NameList = Seperator >> Space >> Variable >> *(sym(',') >> Space >> Variable); NameOrDestructure = Space >> Variable | TableLit; @@ -578,7 +579,7 @@ YueParser::YueParser() { fn_arrow_back = expr('<') >> set("-="); Backcall = -FnArgsDef >> Space >> fn_arrow_back >> Space >> ChainValue; - PipeBody = Seperator >> Space >> PipeOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> PipeOperator >> unary_exp); + PipeBody = Seperator >> PipeOperator >> unary_exp >> *(+SpaceBreak >> CheckIndent >> Space >> PipeOperator >> unary_exp); ExpList = Seperator >> Exp >> *(sym(',') >> Exp); ExpListLow = Seperator >> Exp >> *(Space >> set(",;") >> Exp); @@ -606,24 +607,22 @@ YueParser::YueParser() { const_value = (expr("nil") | expr("true") | expr("false")) >> not_(AlphaNum); - SimpleValue = - (Space >> const_value) | + SimpleValue = Space >> (const_value | If | Switch | With | ClassDecl | ForEach | For | While | Do | - (Space >> unary_value) | - TblComprehension | TableLit | Comprehension | FunLit | - (Space >> Num); + unary_value | TblComprehension | TableLit | Comprehension | + FunLit | Num); ExpListAssign = ExpList >> -(Update | Assign); - if_line = key("if") >> Exp >> -Assign; - unless_line = key("unless") >> Exp; + if_line = Space >> key("if") >> Exp >> -Assign; + unless_line = Space >> key("unless") >> Exp; statement_appendix = (if_line | unless_line | CompInner) >> Space; statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[="))); - Statement = ( + Statement = Space >> ( Import | While | Repeat | For | ForEach | Return | Local | Global | Export | Macro | - Space >> BreakLoop | Label | Goto | LocalAttrib | + MacroInPlace | BreakLoop | Label | Goto | LocalAttrib | Backcall | PipeBody | ExpListAssign ) >> Space >> -statement_appendix >> -statement_sep; diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 22527d9..c752461 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -303,6 +303,7 @@ private: AST_RULE(MacroName) AST_RULE(MacroLit) AST_RULE(Macro) + AST_RULE(MacroInPlace) AST_RULE(NameOrDestructure) AST_RULE(AssignableNameList) AST_RULE(InvokeArgs) -- cgit v1.2.3-55-g6feb