From 3beb1bff21d15f93c1164c130f9ba00add74a256 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Mon, 1 Jun 2020 11:45:51 +0800 Subject: [PATCH] App: improve FunctionExpression forward compatibility Remove runtime check when constructing FunctionExpression, in order to support future built-in function. Exception will be thrown when evaluating the expression to inform user about the error. --- src/App/Expression.cpp | 64 +++------------------------------- src/App/ExpressionParser.h | 8 +++-- src/App/ExpressionParser.l | 6 ++-- src/App/ExpressionParser.tab.c | 2 +- src/App/ExpressionParser.y | 2 +- src/App/lex.ExpressionParser.c | 4 +-- 6 files changed, 17 insertions(+), 69 deletions(-) diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index fc4503b977..b8c58d6d2c 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -1766,66 +1766,12 @@ bool OperatorExpression::isRightAssociative() const TYPESYSTEM_SOURCE(App::FunctionExpression, App::UnitExpression) -FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f, std::vector _args) +FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f, std::string &&name, std::vector _args) : UnitExpression(_owner) , f(_f) + , fname(std::move(name)) , args(_args) { - switch (f) { - case ACOS: - case ASIN: - case ATAN: - case ABS: - case EXP: - case LOG: - case LOG10: - case SIN: - case SINH: - case TAN: - case TANH: - case SQRT: - case COS: - case COSH: - case ROUND: - case TRUNC: - case CEIL: - case FLOOR: - case MINVERT: - if (args.size() != 1) - EXPR_THROW("Invalid number of arguments: exactly one required."); - break; - case MOD: - case ATAN2: - case POW: - if (args.size() != 2) - EXPR_THROW("Invalid number of arguments: exactly two required."); - break; - case HYPOT: - case CATH: - if (args.size() < 2 || args.size() > 3) - EXPR_THROW("Invalid number of arguments: exactly two, or three required."); - break; - case STDDEV: - case SUM: - case AVERAGE: - case COUNT: - case MIN: - case MAX: - case CREATE: - case MSCALE: - if (args.size() == 0) - EXPR_THROW("Invalid number of arguments: at least one required."); - break; - case LIST: - case TUPLE: - break; - case NONE: - case AGGREGATES: - case LAST: - default: - EXPR_THROW("Unknown function"); - break; - } } FunctionExpression::~FunctionExpression() @@ -2392,7 +2338,7 @@ Expression *FunctionExpression::simplify() const return eval(); } else - return new FunctionExpression(owner, f, a); + return new FunctionExpression(owner, f, std::string(fname), a); } /** @@ -2473,7 +2419,7 @@ void FunctionExpression::_toString(std::ostream &ss, bool persistent,int) const case CREATE: ss << "create("; break;; default: - assert(0); + ss << fname << "("; break;; } for (size_t i = 0; i < args.size(); ++i) { ss << args[i]->toString(persistent); @@ -2498,7 +2444,7 @@ Expression *FunctionExpression::_copy() const a.push_back((*i)->copy()); ++i; } - return new FunctionExpression(owner, f, a); + return new FunctionExpression(owner, f, std::string(fname), a); } void FunctionExpression::_visit(ExpressionVisitor &v) diff --git a/src/App/ExpressionParser.h b/src/App/ExpressionParser.h index 90d426ba49..f7c802357e 100644 --- a/src/App/ExpressionParser.h +++ b/src/App/ExpressionParser.h @@ -287,7 +287,8 @@ public: LAST, }; - FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, std::vector _args = std::vector()); + FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, + std::string &&name = std::string(), std::vector _args = std::vector()); virtual ~FunctionExpression(); @@ -305,6 +306,7 @@ protected: virtual void _toString(std::ostream &ss, bool persistent, int indent) const override; Function f; /**< Function to execute */ + std::string fname; std::vector args; /** Arguments to function*/ }; @@ -484,9 +486,9 @@ public: std::vector arguments; std::vector list; std::string string; - FunctionExpression::Function func; + std::pair func; ObjectIdentifier::String string_or_identifier; - semantic_type() : expr(0), ivalue(0), fvalue(0), func(FunctionExpression::NONE) {} + semantic_type() : expr(0), ivalue(0), fvalue(0), func({FunctionExpression::NONE, std::string()}) {} }; #define YYSTYPE semantic_type diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index 9febd74701..709723527f 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -342,9 +342,9 @@ $[A-Za-z]{1,2}{DIGIT}+ COUNTCHARS; yylval.string = yytext; return CELLADDR s.erase(i + 1); std::map::const_iterator j = registered_functions.find(s); if (j != registered_functions.end()) - yylval.func = j->second; - else - yylval.func = FunctionExpression::NONE; + yylval.func.first = j->second; + else + { yylval.func.first = FunctionExpression::NONE; yylval.func.second = std::move(s); } return FUNC; } diff --git a/src/App/ExpressionParser.tab.c b/src/App/ExpressionParser.tab.c index bfb4f7845e..6ba3711ea9 100644 --- a/src/App/ExpressionParser.tab.c +++ b/src/App/ExpressionParser.tab.c @@ -1517,7 +1517,7 @@ yyreduce: case 18: #line 85 "ExpressionParser.y" /* yacc.c:1646 */ - { (yyval.expr) = new FunctionExpression(DocumentObject, (yyvsp[-2].func), (yyvsp[-1].arguments)); } + { (yyval.expr) = new FunctionExpression(DocumentObject, (yyvsp[-2].func.first), std::move((yyvsp[-2].func.second)), (yyvsp[-1].arguments)); } #line 1522 "ExpressionParser.tab.c" /* yacc.c:1646 */ break; diff --git a/src/App/ExpressionParser.y b/src/App/ExpressionParser.y index 7cbb8afc6d..9914833893 100644 --- a/src/App/ExpressionParser.y +++ b/src/App/ExpressionParser.y @@ -82,7 +82,7 @@ exp: num { $$ = $1; | exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); } | exp '^' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); } | indexable { $$ = $1; } - | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); } + | FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1.first, std::move($1.second), $2); } | cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); } ; diff --git a/src/App/lex.ExpressionParser.c b/src/App/lex.ExpressionParser.c index f3c631788a..aaba24e346 100644 --- a/src/App/lex.ExpressionParser.c +++ b/src/App/lex.ExpressionParser.c @@ -9286,9 +9286,9 @@ YY_RULE_SETUP s.erase(i + 1); std::map::const_iterator j = registered_functions.find(s); if (j != registered_functions.end()) - yylval.func = j->second; + yylval.func.first = j->second; else - yylval.func = FunctionExpression::NONE; + { yylval.func.first = FunctionExpression::NONE; yylval.func.second = std::move(s); } return FUNC; } YY_BREAK