App: add list/tuple() function to Expression

For easy creation of Python list/tuple using expression. Range
expression can now be expanded into list or tuple.
This commit is contained in:
Zheng, Lei
2019-08-26 15:55:39 +08:00
committed by wmayer
parent 38c47d6e95
commit c3db1e02ec
2 changed files with 63 additions and 12 deletions

View File

@@ -85,8 +85,7 @@ FC_LOG_LEVEL_INIT("Expression",true,true)
#define __EXPR_THROW(_e,_msg,_expr) do {\
std::ostringstream ss;\
ss << _msg;\
if(_expr) ss << std::endl << (_expr)->toString();\
ss << _msg << (_expr);\
throw _e(ss.str().c_str());\
}while(0)
@@ -94,8 +93,7 @@ FC_LOG_LEVEL_INIT("Expression",true,true)
#define __EXPR_SET_MSG(_e,_msg,_expr) do {\
std::ostringstream ss;\
ss << _msg << _e.what();\
if(_expr) ss << std::endl << (_expr)->toString();\
ss << _msg << _e.what() << (_expr);\
_e.setMessage(ss.str());\
}while(0)
@@ -122,6 +120,12 @@ FC_LOG_LEVEL_INIT("Expression",true,true)
#define PY_THROW(_msg) __EXPR_THROW(Py::RuntimeError,_msg, (Expression*)0)
static inline std::ostream &operator<<(std::ostream &os, const App::Expression *expr) {
if(expr)
os << std::endl << expr->toString();
return os;
}
////////////////////////////////////////////////////////////////////////////////
// WARNING! The following define enables slightly faster any type comparison which
@@ -1518,18 +1522,18 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
case CEIL:
case FLOOR:
if (args.size() != 1)
throw ExpressionError("Invalid number of arguments: exactly one required.");
EXPR_THROW("Invalid number of arguments: exactly one required.");
break;
case MOD:
case ATAN2:
case POW:
if (args.size() != 2)
throw ExpressionError("Invalid number of arguments: exactly two required.");
EXPR_THROW("Invalid number of arguments: exactly two required.");
break;
case HYPOT:
case CATH:
if (args.size() < 2 || args.size() > 3)
throw ExpressionError("Invalid number of arguments: exactly two, or three required.");
EXPR_THROW("Invalid number of arguments: exactly two, or three required.");
break;
case STDDEV:
case SUM:
@@ -1538,13 +1542,17 @@ FunctionExpression::FunctionExpression(const DocumentObject *_owner, Function _f
case MIN:
case MAX:
if (args.size() == 0)
throw ExpressionError("Invalid number of arguments: at least one required.");
EXPR_THROW("Invalid number of arguments: at least one required.");
break;
case LIST:
case TUPLE:
break;
case NONE:
case AGGREGATES:
case LAST:
default:
throw ExpressionError("Unknown function");
EXPR_THROW("Unknown function");
break;
}
}
@@ -1771,6 +1779,11 @@ Expression * FunctionExpression::eval() const
if (f > AGGREGATES)
return evalAggregate();
if(f == LIST || f == TUPLE) {
Base::PyGILStateLocker lock;
return new PyObjectExpression(owner,getPyValue().ptr());
}
std::unique_ptr<Expression> e1(args[0]->eval());
std::unique_ptr<Expression> e2(args.size() > 1 ? args[1]->eval() : 0);
std::unique_ptr<Expression> e3(args.size() > 2 ? args[2]->eval() : 0);
@@ -1988,6 +2001,23 @@ boost::any FunctionExpression::getValueAsAny() const {
}
Py::Object FunctionExpression::getPyValue() const {
if(f == LIST) {
if(args.size() == 1 && args[0]->isDerivedFrom(RangeExpression::getClassTypeId()))
return args[0]->getPyValue();
Py::List list(args.size());
int i=0;
for(auto &arg : args)
list.setItem(i++,arg->getPyValue());
return list;
} else if (f == TUPLE) {
if(args.size() == 1 && args[0]->isDerivedFrom(RangeExpression::getClassTypeId()))
return Py::Tuple(args[0]->getPyValue());
Py::Tuple tuple(args.size());
int i=0;
for(auto &arg : args)
tuple.setItem(i++,arg->getPyValue());
return tuple;
}
ExpressionPtr e(eval());
return e->getPyValue();
}
@@ -2100,6 +2130,10 @@ std::string FunctionExpression::toString(bool persistent) const
return "min(" + ss.str() + ")";
case MAX:
return "max(" + ss.str() + ")";
case LIST:
return "list(" + ss.str() + ")";
case TUPLE:
return "tuple(" + ss.str() + ")";
default:
assert(0);
return std::string();
@@ -2637,11 +2671,24 @@ bool RangeExpression::isTouched() const
Expression *RangeExpression::eval() const
{
throw Exception("Range expression cannot be evaluated");
Base::PyGILStateLocker lock;
return expressionFromPy(owner,getPyValue());
}
boost::any RangeExpression::getValueAsAny() const {
Base::PyGILStateLocker lock;
return __pyObjectFromAny(getPyValue());
}
Py::Object RangeExpression::getPyValue() const {
return Py::Object();
Py::List list;
Range range(getRange());
do {
Property * p = owner->getPropertyByName(range.address().c_str());
if(p)
list.append(Py::asObject(p->getPyObject()));
} while (range.next());
return list;
}
std::string RangeExpression::toString(bool) const
@@ -2924,6 +2971,8 @@ static void initParser(const App::DocumentObject *owner)
registered_functions["floor"] = FunctionExpression::FLOOR;
registered_functions["hypot"] = FunctionExpression::HYPOT;
registered_functions["cath"] = FunctionExpression::CATH;
registered_functions["list"] = FunctionExpression::LIST;
registered_functions["tuple"] = FunctionExpression::TUPLE;
// Aggregates
registered_functions["sum"] = FunctionExpression::SUM;

View File

@@ -267,6 +267,8 @@ public:
FLOOR,
HYPOT,
CATH,
LIST,
TUPLE,
// Aggregates
AGGREGATES,
@@ -453,7 +455,7 @@ public:
Range getRange() const;
virtual boost::any getValueAsAny() const override { return boost::any(); }
virtual boost::any getValueAsAny() const override;
virtual Py::Object getPyValue() const override;