X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fstructure%2FSGExpression.hxx;h=2cfa3dc8909d629959816210282535f3be13f37c;hb=b2c3a90adfb6c0285d02355fd8ab061b7f2f1e6c;hp=c3e3bac5844e0fdd001897f8e8b839c0a826ca05;hpb=0b1f074bcff315546304a5c7d9886f37a1b71a18;p=simgear.git diff --git a/simgear/structure/SGExpression.hxx b/simgear/structure/SGExpression.hxx index c3e3bac5..2cfa3dc8 100644 --- a/simgear/structure/SGExpression.hxx +++ b/simgear/structure/SGExpression.hxx @@ -22,25 +22,124 @@ #ifndef _SG_EXPRESSION_HXX #define _SG_EXPRESSION_HXX 1 +#include +#include +#include +#include +#include + #include #include #include #include #include +#include +#include /// Expression tree implementation. +namespace simgear +{ + namespace expression + { + enum Type { + BOOL = 0, + INT, + FLOAT, + DOUBLE + }; + template struct TypeTraits; + template<> struct TypeTraits { + static const Type typeTag = BOOL; + }; + template<> struct TypeTraits { + static const Type typeTag = INT; + }; + template<> struct TypeTraits { + static const Type typeTag = FLOAT; + }; + template<> struct TypeTraits { + static const Type typeTag = DOUBLE; + }; + + struct Value + { + Type typeTag; + union { + bool boolVal; + int intVal; + float floatVal; + double doubleVal; + } val; + + Value() : typeTag(DOUBLE) + { + val.doubleVal = 0.0; + } + + Value(bool val_) : typeTag(BOOL) + { + val.boolVal = val_; + } + + Value(int val_) : typeTag(INT) + { + val.intVal = val_; + } + + Value(float val_) : typeTag(FLOAT) + { + val.floatVal = val_; + } + + Value(double val_) : typeTag(DOUBLE) + { + val.doubleVal = val_; + } + + }; + + class Binding; + } + + class Expression : public SGReferenced + { + public: + virtual ~Expression() {} + virtual expression::Type getType() const = 0; + }; + + const expression::Value eval(const Expression* exp, + const expression::Binding* binding = 0); + +} + template -class SGExpression : public SGReferenced { +class SGExpression : public simgear::Expression { public: virtual ~SGExpression() {} - virtual void eval(T&) const = 0; + typedef T result_type; + typedef T operand_type; + virtual void eval(T&, const simgear::expression::Binding*) const = 0; - T getValue() const - { T value; eval(value); return value; } + T getValue(const simgear::expression::Binding* binding = 0) const + { T value; eval(value, binding); return value; } + + double getDoubleValue(const simgear::expression::Binding* binding = 0) const + { T value; eval(value, binding); return value; } virtual bool isConst() const { return false; } virtual SGExpression* simplify(); + virtual simgear::expression::Type getType() const + { + return simgear::expression::TypeTraits::typeTag; + } + virtual simgear::expression::Type getOperandType() const + { + return simgear::expression::TypeTraits::typeTag; + } + virtual void collectDependentProperties(std::set& props) const + { } }; /// Constant value expression @@ -51,9 +150,9 @@ public: { } void setValue(const T& value) { _value = value; } - const T& getValue() const + const T& getValue(const simgear::expression::Binding* binding = 0) const { return _value; } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding*) const { value = _value; } virtual bool isConst() const { return true; } private: @@ -89,7 +188,9 @@ public: _expression = _expression->simplify(); return SGExpression::simplify(); } - + + virtual void collectDependentProperties(std::set& props) const + { _expression->collectDependentProperties(props); } protected: SGUnaryExpression(SGExpression* expression = 0) { setOperand(expression); } @@ -101,11 +202,11 @@ private: template class SGBinaryExpression : public SGExpression { public: - const SGExpression* getOperand(unsigned i) const + const SGExpression* getOperand(size_t i) const { return _expressions[i]; } - SGExpression* getOperand(unsigned i) + SGExpression* getOperand(size_t i) { return _expressions[i]; } - void setOperand(unsigned i, SGExpression* expression) + void setOperand(size_t i, SGExpression* expression) { if (!expression) expression = new SGConstExpression(T()); @@ -123,6 +224,12 @@ public: return SGExpression::simplify(); } + virtual void collectDependentProperties(std::set& props) const + { + _expressions[0]->collectDependentProperties(props); + _expressions[1]->collectDependentProperties(props); + } + protected: SGBinaryExpression(SGExpression* expr0, SGExpression* expr1) { setOperand(0, expr0); setOperand(1, expr1); } @@ -134,34 +241,48 @@ private: template class SGNaryExpression : public SGExpression { public: - unsigned getNumOperands() const + size_t getNumOperands() const { return _expressions.size(); } - const SGExpression* getOperand(unsigned i) const + const SGExpression* getOperand(size_t i) const { return _expressions[i]; } - SGExpression* getOperand(unsigned i) + SGExpression* getOperand(size_t i) { return _expressions[i]; } - unsigned addOperand(SGExpression* expression) + size_t addOperand(SGExpression* expression) { if (!expression) - return ~unsigned(0); + return ~size_t(0); _expressions.push_back(expression); return _expressions.size() - 1; } + template + void addOperands(Iter begin, Iter end) + { + for (Iter iter = begin; iter != end; ++iter) + { + addOperand(static_cast< ::SGExpression*>(*iter)); + } + } + virtual bool isConst() const { - for (unsigned i = 0; i < _expressions.size(); ++i) + for (size_t i = 0; i < _expressions.size(); ++i) if (!_expressions[i]->isConst()) return false; return true; } virtual SGExpression* simplify() { - for (unsigned i = 0; i < _expressions.size(); ++i) + for (size_t i = 0; i < _expressions.size(); ++i) _expressions[i] = _expressions[i]->simplify(); return SGExpression::simplify(); } + virtual void collectDependentProperties(std::set& props) const + { + for (size_t i = 0; i < _expressions.size(); ++i) + _expressions[i]->collectDependentProperties(props); + } protected: SGNaryExpression() { } @@ -182,8 +303,11 @@ public: { } void setPropertyNode(const SGPropertyNode* prop) { _prop = prop; } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding*) const { doEval(value); } + + virtual void collectDependentProperties(std::set& props) const + { props.insert(_prop.get()); } private: void doEval(float& value) const { if (_prop) value = _prop->getFloatValue(); } @@ -205,8 +329,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = getOperand()->getValue(); if (value <= 0) value = -value; } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = getOperand()->getValue(b); if (value <= 0) value = -value; } using SGUnaryExpression::getOperand; }; @@ -218,8 +342,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = acos(SGMisc::clip(getOperand()->getValue(), -1, 1)); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = acos((double)SGMisc::clip(getOperand()->getValue(b), -1, 1)); } using SGUnaryExpression::getOperand; }; @@ -231,8 +355,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = asin(SGMisc::clip(getOperand()->getValue(), -1, 1)); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = asin((double)SGMisc::clip(getOperand()->getValue(b), -1, 1)); } using SGUnaryExpression::getOperand; }; @@ -244,8 +368,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = atan(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = atan(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -257,8 +381,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = ceil(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = ceil(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -270,8 +394,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = cos(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = cos(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -283,8 +407,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = cosh(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = cosh(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -296,8 +420,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = exp(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = exp(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -309,8 +433,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = floor(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = floor(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -322,8 +446,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = log(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = log(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -335,8 +459,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = log10(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = log10(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -348,8 +472,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = sin(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = sin(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -361,8 +485,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = sinh(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = sinh(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -374,8 +498,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = getOperand()->getValue(); value = value*value; } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = getOperand()->getValue(b); value = value*value; } using SGUnaryExpression::getOperand; }; @@ -387,8 +511,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = sqrt(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = sqrt(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -400,8 +524,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = tan(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = tan(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -413,8 +537,8 @@ public: : SGUnaryExpression(expr) { } - virtual void eval(T& value) const - { value = tanh(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = tanh(getOperand()->getDoubleValue(b)); } using SGUnaryExpression::getOperand; }; @@ -430,8 +554,8 @@ public: const T& getScale() const { return _scale; } - virtual void eval(T& value) const - { value = _scale * getOperand()->getValue(); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = _scale * getOperand()->getValue(b); } virtual SGExpression* simplify() { @@ -457,8 +581,8 @@ public: const T& getBias() const { return _bias; } - virtual void eval(T& value) const - { value = _bias + getOperand()->getValue(); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = _bias + getOperand()->getValue(b); } virtual SGExpression* simplify() { @@ -481,10 +605,10 @@ public: _interpTable(interpTable) { } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { if (_interpTable) - value = _interpTable->interpolate(getOperand()->getValue()); + value = _interpTable->interpolate(getOperand()->getValue(b)); } using SGUnaryExpression::getOperand; @@ -517,9 +641,9 @@ public: const T& getClipMax() const { return _clipMax; } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { - value = SGMisc::clip(getOperand()->getValue(), _clipMin, _clipMax); + value = SGMisc::clip(getOperand()->getValue(b), _clipMin, _clipMax); } virtual SGExpression* simplify() @@ -554,32 +678,24 @@ public: const T& getScroll() const { return _scroll; } - virtual void eval(T& value) const - { value = apply_mods(getOperand()->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = apply_mods(getOperand()->getValue(b)); } using SGUnaryExpression::getOperand; private: T apply_mods(T property) const { - T modprop; - if (_step > 0) { - T scrollval = 0; - if(_scroll > 0) { - // calculate scroll amount (for odometer like movement) - T remainder = _step - fmod(fabs(property), _step); - if (remainder < _scroll) { - scrollval = (_scroll - remainder) / _scroll * _step; - } - } - // apply stepping of input value - if(property > 0) - modprop = ((floor(property/_step) * _step) + scrollval); - else - modprop = ((ceil(property/_step) * _step) + scrollval); - } else { - modprop = property; - } + if( _step <= SGLimits::min() ) return property; + + // apply stepping of input value + T modprop = floor(property/_step)*_step; + + // calculate scroll amount (for odometer like movement) + T remainder = property <= SGLimits::min() ? -fmod(property,_step) : (_step - fmod(property,_step)); + if( remainder > SGLimits::min() && remainder < _scroll ) + modprop += (_scroll - remainder) / _scroll * _step; + return modprop; } @@ -603,10 +719,10 @@ public: void setDisabledValue(const T& disabledValue) { _disabledValue = disabledValue; } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { if (_enable->test()) - value = getOperand()->getValue(); + value = getOperand()->getValue(b); else value = _disabledValue; } @@ -617,6 +733,12 @@ public: return getOperand()->simplify(); return SGUnaryExpression::simplify(); } + + virtual void collectDependentProperties(std::set& props) const + { + SGUnaryExpression::collectDependentProperties(props); + _enable->collectDependentProperties(props); + } using SGUnaryExpression::getOperand; private: @@ -630,8 +752,8 @@ public: SGAtan2Expression(SGExpression* expr0, SGExpression* expr1) : SGBinaryExpression(expr0, expr1) { } - virtual void eval(T& value) const - { value = atan2(getOperand(0)->getValue(), getOperand(1)->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = atan2(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); } using SGBinaryExpression::getOperand; }; @@ -641,8 +763,8 @@ public: SGDivExpression(SGExpression* expr0, SGExpression* expr1) : SGBinaryExpression(expr0, expr1) { } - virtual void eval(T& value) const - { value = getOperand(0)->getValue() / getOperand(1)->getValue(); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = getOperand(0)->getValue(b) / getOperand(1)->getValue(b); } using SGBinaryExpression::getOperand; }; @@ -652,8 +774,8 @@ public: SGModExpression(SGExpression* expr0, SGExpression* expr1) : SGBinaryExpression(expr0, expr1) { } - virtual void eval(T& value) const - { value = mod(getOperand(0)->getValue(), getOperand(1)->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = mod(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); } using SGBinaryExpression::getOperand; private: int mod(const int& v0, const int& v1) const @@ -670,8 +792,8 @@ public: SGPowExpression(SGExpression* expr0, SGExpression* expr1) : SGBinaryExpression(expr0, expr1) { } - virtual void eval(T& value) const - { value = pow(getOperand(0)->getValue(), getOperand(1)->getValue()); } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { value = pow(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); } using SGBinaryExpression::getOperand; }; @@ -683,12 +805,31 @@ public: SGSumExpression(SGExpression* expr0, SGExpression* expr1) : SGNaryExpression(expr0, expr1) { } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { value = T(0); - unsigned sz = SGNaryExpression::getNumOperands(); - for (unsigned i = 0; i < sz; ++i) - value += getOperand(i)->getValue(); + size_t sz = SGNaryExpression::getNumOperands(); + for (size_t i = 0; i < sz; ++i) + value += getOperand(i)->getValue(b); + } + using SGNaryExpression::getValue; + using SGNaryExpression::getOperand; +}; + +template +class SGDifferenceExpression : public SGNaryExpression { +public: + SGDifferenceExpression() + { } + SGDifferenceExpression(SGExpression* expr0, SGExpression* expr1) + : SGNaryExpression(expr0, expr1) + { } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { + value = getOperand(0)->getValue(b); + size_t sz = SGNaryExpression::getNumOperands(); + for (size_t i = 1; i < sz; ++i) + value -= getOperand(i)->getValue(b); } using SGNaryExpression::getValue; using SGNaryExpression::getOperand; @@ -702,12 +843,12 @@ public: SGProductExpression(SGExpression* expr0, SGExpression* expr1) : SGNaryExpression(expr0, expr1) { } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { value = T(1); - unsigned sz = SGNaryExpression::getNumOperands(); - for (unsigned i = 0; i < sz; ++i) - value *= getOperand(i)->getValue(); + size_t sz = SGNaryExpression::getNumOperands(); + for (size_t i = 0; i < sz; ++i) + value *= getOperand(i)->getValue(b); } using SGNaryExpression::getValue; using SGNaryExpression::getOperand; @@ -721,15 +862,15 @@ public: SGMinExpression(SGExpression* expr0, SGExpression* expr1) : SGNaryExpression(expr0, expr1) { } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { - unsigned sz = SGNaryExpression::getNumOperands(); + size_t sz = SGNaryExpression::getNumOperands(); if (sz < 1) return; - value = getOperand(0)->getValue(); - for (unsigned i = 1; i < sz; ++i) - value = SGMisc::min(value, getOperand(i)->getValue()); + value = getOperand(0)->getValue(b); + for (size_t i = 1; i < sz; ++i) + value = SGMisc::min(value, getOperand(i)->getValue(b)); } using SGNaryExpression::getOperand; }; @@ -742,15 +883,15 @@ public: SGMaxExpression(SGExpression* expr0, SGExpression* expr1) : SGNaryExpression(expr0, expr1) { } - virtual void eval(T& value) const + virtual void eval(T& value, const simgear::expression::Binding* b) const { - unsigned sz = SGNaryExpression::getNumOperands(); + size_t sz = SGNaryExpression::getNumOperands(); if (sz < 1) return; - value = getOperand(0)->getValue(); - for (unsigned i = 1; i < sz; ++i) - value = SGMisc::max(value, getOperand(i)->getValue()); + value = getOperand(0)->getValue(b); + for (size_t i = 1; i < sz; ++i) + value = SGMisc::max(value, getOperand(i)->getValue(b)); } using SGNaryExpression::getOperand; }; @@ -760,6 +901,11 @@ typedef SGExpression SGExpressionf; typedef SGExpression SGExpressiond; typedef SGExpression SGExpressionb; +typedef SGSharedPtr SGExpressioni_ref; +typedef SGSharedPtr SGExpressionf_ref; +typedef SGSharedPtr SGExpressiond_ref; +typedef SGSharedPtr SGExpressionb_ref; + /** * Global function to make an expression out of properties. @@ -798,4 +944,350 @@ SGExpression* SGReadBoolExpression(SGPropertyNode *inputRoot, const SGPropertyNode *configNode); +namespace simgear +{ + namespace expression + { + struct ParseError : public sg_exception + { + ParseError(const std::string& message = std::string()) + : sg_exception(message) {} + }; + + // Support for binding variables around an expression. + class Binding + { + public: + virtual ~Binding() {} + const virtual Value* getBindings() const = 0; + virtual Value* getBindings() = 0; + }; + + class VariableLengthBinding : public Binding + { + public: + const Value* getBindings() const + { + if (_bindings.empty()) + return 0; + else + return &_bindings[0]; + } + Value* getBindings() + { + if (_bindings.empty()) + return 0; + else + return &_bindings[0]; + } + std::vector _bindings; + }; + + template class FixedLengthBinding : public Binding + { + public: + Value* getBindings() + { + return &_bindings[0]; + } + const Value* getBindings() const + { + return &_bindings[0]; + } + Value _bindings[Size]; + }; + + struct VariableBinding + { + VariableBinding() : type(expression::DOUBLE), location(-1) {} + + VariableBinding(const std::string& name_, expression::Type type_, + int location_) + : name(name_), type(type_), location(location_) + { + } + std::string name; + expression::Type type; + int location; + }; + + class BindingLayout + { + public: + size_t addBinding(const std::string& name, expression::Type type); + bool findBinding(const std::string& name, VariableBinding& result) const; + std::vector bindings; + }; + + class Parser { + public: + typedef Expression* (*exp_parser)(const SGPropertyNode* exp, + Parser* parser); + void addParser(const std::string& name, exp_parser parser) + { + getParserMap().insert(std::make_pair(name, parser)); + } + Expression* read(const SGPropertyNode* exp) + { + ParserMap& map = getParserMap(); + ParserMap::iterator itr = map.find(exp->getName()); + if (itr == map.end()) + throw ParseError(std::string("unknown expression ") + exp->getName()); + exp_parser parser = itr->second; + return (*parser)(exp, this); + } + // XXX vector of SGSharedPtr? + bool readChildren(const SGPropertyNode* exp, + std::vector& result); + /** + * Function that parses a property tree, producing an expression. + */ + typedef std::map ParserMap; + virtual ParserMap& getParserMap() = 0; + /** + * After an expression is parsed, the binding layout may contain + * references that need to be bound during evaluation. + */ + BindingLayout& getBindingLayout() { return _bindingLayout; } + protected: + BindingLayout _bindingLayout; + }; + + class ExpressionParser : public Parser + { + public: + ParserMap& getParserMap() + { + return ParserMapSingleton::instance()->_parserTable; + } + static void addExpParser(const std::string&, exp_parser); + protected: + struct ParserMapSingleton : public simgear::Singleton + { + ParserMap _parserTable; + }; + }; + + /** + * Constructor for registering parser functions. + */ + struct ExpParserRegistrar + { + ExpParserRegistrar(const std::string& token, Parser::exp_parser parser) + { + ExpressionParser::addExpParser(token, parser); + } + }; + + } + + /** + * Access a variable definition. Use a location from a BindingLayout. + */ + template + class VariableExpression : public ::SGExpression { + public: + VariableExpression(int location) : _location(location) {} + virtual ~VariableExpression() {} + virtual void eval(T& value, const simgear::expression::Binding* b) const + { + const expression::Value* values = b->getBindings(); + value = *reinterpret_cast(&values[_location].val); + } + protected: + int _location; + + }; + + /** + * An n-ary expression where the types of the argument aren't the + * same as the return type. + */ + template + class GeneralNaryExpression : public ::SGExpression { + public: + typedef OpType operand_type; + size_t getNumOperands() const + { return _expressions.size(); } + const ::SGExpression* getOperand(size_t i) const + { return _expressions[i]; } + ::SGExpression* getOperand(size_t i) + { return _expressions[i]; } + size_t addOperand(::SGExpression* expression) + { + if (!expression) + return ~size_t(0); + _expressions.push_back(expression); + return _expressions.size() - 1; + } + + template + void addOperands(Iter begin, Iter end) + { + for (Iter iter = begin; iter != end; ++iter) + { + addOperand(static_cast< ::SGExpression*>(*iter)); + } + } + + virtual bool isConst() const + { + for (size_t i = 0; i < _expressions.size(); ++i) + if (!_expressions[i]->isConst()) + return false; + return true; + } + virtual ::SGExpression* simplify() + { + for (size_t i = 0; i < _expressions.size(); ++i) + _expressions[i] = _expressions[i]->simplify(); + return SGExpression::simplify(); + } + + simgear::expression::Type getOperandType() const + { + return simgear::expression::TypeTraits::typeTag; + } + + protected: + GeneralNaryExpression() + { } + GeneralNaryExpression(::SGExpression* expr0, + ::SGExpression* expr1) + { addOperand(expr0); addOperand(expr1); } + + std::vector > > _expressions; + }; + + /** + * A predicate that wraps, for example the STL template predicate + * expressions like std::equal_to. + */ + template class Pred> + class PredicateExpression : public GeneralNaryExpression { + public: + PredicateExpression() + { + } + PredicateExpression(::SGExpression* expr0, + ::SGExpression* expr1) + : GeneralNaryExpression(expr0, expr1) + { + } + virtual void eval(bool& value, const simgear::expression::Binding* b) const + { + size_t sz = this->getNumOperands(); + if (sz != 2) + return; + value = _pred(this->getOperand(0)->getValue(b), + this->getOperand(1)->getValue(b)); + } + protected: + Pred _pred; + }; + + template class Pred, typename OpType> + PredicateExpression* + makePredicate(SGExpression* op1, SGExpression* op2) + { + return new PredicateExpression(op1, op2); + } + + template + class EqualToExpression : public PredicateExpression + { + public: + EqualToExpression() {} + EqualToExpression(::SGExpression* expr0, + ::SGExpression* expr1) + : PredicateExpression(expr0, expr1) + { + } + }; + + template + class LessExpression : public PredicateExpression + { + public: + LessExpression() {} + LessExpression(::SGExpression* expr0, ::SGExpression* expr1) + : PredicateExpression(expr0, expr1) + { + } + }; + + template + class LessEqualExpression + : public PredicateExpression + { + public: + LessEqualExpression() {} + LessEqualExpression(::SGExpression* expr0, + ::SGExpression* expr1) + : PredicateExpression(expr0, expr1) + { + } + }; + + class NotExpression : public ::SGUnaryExpression + { + public: + NotExpression(::SGExpression* expr = 0) + : ::SGUnaryExpression(expr) + { + } + void eval(bool& value, const expression::Binding* b) const + { + value = !getOperand()->getValue(b); + } + }; + + class OrExpression : public ::SGNaryExpression + { + public: + void eval(bool& value, const expression::Binding* b) const + { + value = false; + for (int i = 0; i < (int)getNumOperands(); ++i) { + value = value || getOperand(i)->getValue(b); + if (value) + return; + } + } + }; + + class AndExpression : public ::SGNaryExpression + { + public: + void eval(bool& value, const expression::Binding* b) const + { + value = true; + for (int i = 0; i < (int)getNumOperands(); ++i) { + value = value && getOperand(i)->getValue(b); + if (!value) + return; + } + } + }; + + /** + * Convert an operand from OpType to T. + */ + template + class ConvertExpression : public GeneralNaryExpression + { + public: + ConvertExpression() {} + ConvertExpression(::SGExpression* expr0) + { + this->addOperand(expr0); + } + virtual void eval(T& value, const simgear::expression::Binding* b) const + { + typename ConvertExpression::operand_type result; + this->_expressions.at(0)->eval(result, b); + value = result; + } + }; +} #endif // _SG_EXPRESSION_HXX