From 14ac9a31f84c7bd25b37c4ae6ad133572a5df3a7 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Sat, 26 Jun 2021 14:56:24 +0800 Subject: fix issue #55. --- src/yuescript/yue_ast.h | 3 ++- src/yuescript/yue_compiler.cpp | 46 +++++++++++++++++++++++------------------- src/yuescript/yue_parser.cpp | 2 +- 3 files changed, 28 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 695fbe1..7d79341 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h @@ -627,8 +627,9 @@ AST_END(Export) AST_NODE(FnArgDef) ast_sel name; + ast_ptr op; ast_ptr defaultValue; - AST_MEMBER(FnArgDef, &name, &defaultValue) + AST_MEMBER(FnArgDef, &name, &op, &defaultValue) AST_END(FnArgDef) AST_NODE(FnArgDefList) diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 4b3064e..90fc60f 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -56,7 +56,7 @@ using namespace parserlib; typedef std::list str_list; -const std::string_view version = "0.7.14"sv; +const std::string_view version = "0.7.15"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -2801,6 +2801,7 @@ private: void transformFnArgDefList(FnArgDefList_t* argDefList, str_list& out) { auto x = argDefList; struct ArgItem { + bool checkExistence = false; std::string name; std::string assignSelf; }; @@ -2815,27 +2816,33 @@ private: case id(): arg.name = _parser.toString(def->name); break; case id(): { assignSelf = true; + if (def->op) { + if (def->defaultValue) { + throw std::logic_error(_info.errorMessage("argument with default value should not check for existence"sv, def->op)); + } + arg.checkExistence = true; + } auto selfName = static_cast(def->name.get()); switch (selfName->name->getId()) { case id(): { auto clsName = static_cast(selfName->name.get()); arg.name = _parser.toString(clsName->name); - arg.assignSelf = "self.__class."s + arg.name; + arg.assignSelf = _parser.toString(clsName); break; } - case id(): - arg.name = "self.__class"sv; - break; case id(): { auto sfName = static_cast(selfName->name.get()); arg.name = _parser.toString(sfName->name); - arg.assignSelf = "self."s + arg.name; + arg.assignSelf = _parser.toString(sfName); break; } case id(): arg.name = "self"sv; + if (def->op) throw std::logic_error(_info.errorMessage("can only check existence for assigning self field"sv, selfName->name)); + break; + default: + throw std::logic_error(_info.errorMessage("invald self expression here"sv, selfName->name)); break; - default: YUEE("AST node mismatch", selfName->name.get()); break; } break; } @@ -2867,23 +2874,20 @@ private: else varNames.append(", "s + arg.name); _varArgs.top() = true; } - std::string initCodes = join(temp); if (assignSelf) { - auto sjoin = [](const decltype(argItems)& items, int index) { - std::string result; - for (auto it = items.begin(); it != items.end(); ++it) { - if (it->assignSelf.empty()) continue; - if (result.empty()) result = (&it->name)[index]; - else result.append(", "s + (&it->name)[index]); - } - return result; - }; - std::string sleft = sjoin(argItems, 1); - std::string sright = sjoin(argItems, 0); - initCodes.append(indent() + sleft + " = "s + sright + nll(argDefList)); + for (const auto& item : argItems) { + if (item.assignSelf.empty()) continue; + if (item.checkExistence) { + auto stmt = toAst(item.assignSelf + " = "s + item.name + " if "s + item.name + '?', x); + transformStatement(stmt, temp); + } else { + auto assignment = toAst(item.assignSelf + " = "s + item.name, x); + transformAssignment(assignment, temp); + } + } } out.push_back(varNames); - out.push_back(initCodes); + out.push_back(join(temp)); } void transformSelfName(SelfName_t* selfName, str_list& out, const ast_sel& invoke = {}) { diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 255469d..c79d58e 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -548,7 +548,7 @@ YueParser::YueParser() { KeyValueList = KeyValue >> *(sym(',') >> KeyValue); KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (Exp | TableBlock)); - FnArgDef = (Variable | SelfName) >> -(sym('=') >> Space >> Exp); + FnArgDef = (Variable | SelfName >> -existential_op) >> -(sym('=') >> Space >> Exp); FnArgDefList = Space >> Seperator >> ( ( -- cgit v1.2.3-55-g6feb