{
return value->oper_contains(val.value);
}
+bool EvaluationValue::is(const EvaluationValue &val) const
+{
+ return value->oper_is(val.value);
+}
EvaluationValue::operator bool() const
{
size_t hash() const;
bool contains(const EvaluationValue &) const;
+ bool is(const EvaluationValue &) const;
explicit operator bool() const;
EvaluationValue operator()(const std::vector<EvaluationValue> &values, const std::unordered_map<std::string, EvaluationValue> &keyArgs);
{
return other->isEmpty();
}
+ bool oper_is(const EvaluationValuePtr &other) override
+ {
+ return other->isEmpty();
+ }
bool oper_is_true() override
{
return false;
virtual int oper_order(const EvaluationValuePtr &);
virtual size_t oper_hash();
virtual bool oper_contains(const EvaluationValuePtr &value);
+ virtual bool oper_is(const EvaluationValuePtr &value) = 0;
virtual bool oper_is_true() = 0;
virtual EvaluationValuePtr oper_call(const std::vector<EvaluationValue> &args, const std::unordered_map<std::string, EvaluationValue> &keyArgs);
virtual EvaluationValuePtr oper_attr_get(const std::string &name);
{
return other->isBoolean() && value == other->asBoolean();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return oper_equal(v);
+ }
bool oper_is_true() override
{
return value;
{
return value.find(v) != value.end();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return this == v.get();
+ }
EvaluationValuePtr oper_bit_and(const EvaluationValuePtr &o) const override
{
auto &r = o->asDict();
if (other->isInteger()) return value == static_cast<double>(other->asInteger());
return false;
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return v->isDouble() && oper_equal(v);
+ }
int oper_order(const EvaluationValuePtr &other) override
{
if (other->isDouble()) return orderValues(value, other->asDouble());
{
throw EvaluationFailure{} << "unsupported operation, can't compare values " << typeName() << " and " << other->typeName();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return this == v.get();
+ }
bool oper_is_true() override
{
return true;
if (other->isDouble()) return static_cast<double>(value) == other->asDouble();
return false;
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return v->isInteger() && oper_equal(v);
+ }
int oper_order(const EvaluationValuePtr &other) override
{
if (other->isInteger()) return orderValues(value, other->asInteger());
{
return other->isIterator() && value == other->asIterator();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return this == v.get();
+ }
bool oper_is_true() override
{
return bool(value->get());
{
return other->isPoint() && value == other->asPoint();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return oper_equal(v);
+ }
bool oper_is_true() override
{
return true;
{
return other->isSet() && value == other->asSet();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return this == v.get();
+ }
bool oper_is_true() override
{
return !value.empty();
{
return other->isString() && value == other->asString();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return oper_equal(v);
+ }
bool oper_is_true() override
{
return !value.empty();
auto otherId = EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementUniqueId(other->asUIElement());
return selfId == otherId;
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return oper_equal(v);
+ }
bool oper_is_true() override
{
return true;
{
return other->isVector() && value == other->asVector();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return this == v.get();
+ }
int oper_order(const EvaluationValuePtr &other) override
{
if (!other->isVector())
{
return other->isBoolean() && value == other->asWait();
}
+ bool oper_is(const EvaluationValuePtr &v) override
+ {
+ return this == v.get();
+ }
EvaluationValuePtr oper_call(const std::vector<EvaluationValue> &args, const std::unordered_map<std::string, EvaluationValue> &keyArgs) override
{
EvaluationValueFunction::validateArgumentCount(args.size(), 0, 0);
switch (kind) {
case Kind::IN:
return vals[1].contains(vals[0]);
+ case Kind::IS:
+ return vals[1].is(vals[0]);
case Kind::NOT:
return !vals[0];
case Kind::MINUS:
case Kind::IN:
desc = "in";
break;
+ case Kind::IS:
+ desc = "is";
+ break;
case Kind::NOT:
desc = "not";
break;
+EmptyEvaluator::EmptyEvaluator(TokenLocation tokenLocation) :
+ ExpressionEvaluator(std::move(tokenLocation)) { }
+
+EvaluationValue EmptyEvaluator::evaluateImpl() const
+{
+ return EvaluationValue{};
+}
+
+void EmptyEvaluator::printSelfInfo(unsigned int depth) const
+{
+ printLocationAndIndent(location(), depth) << "none";
+}
+
+
+
CallEvaluator::CallEvaluator(TokenLocation tokenLocation, ExprPtr function, ExprPtrs args, ExprMapPtrs keywordArgs) :
ExpressionEvaluator(tokenLocation), function(std::move(function)), args(std::move(args)), keywordArgs(std::move(keywordArgs)) { }
void printSelfInfo(unsigned int depth) const override;
};
+/**
+ * @brief Type representing constructor of a empty value
+ */
+class EmptyEvaluator : public ExpressionEvaluator
+{
+protected:
+ EvaluationValue evaluateImpl() const override;
+public:
+ EmptyEvaluator(TokenLocation location_);
+
+ void printSelfInfo(unsigned int depth) const override;
+};
+
/**
* @brief Type representing constructor of a string
*/
EvaluationValue evaluateImpl() const override;
public:
enum class Kind {
- IN, GET, SET, MINUS, NOT, LOG_OR, LOG_AND, ADD, SUB, MUL, DIV, MOD, LSHIFT, RSHIFT, BIT_OR, BIT_NOT, BIT_AND, BIT_XOR
+ IN, GET, SET, MINUS, NOT, LOG_OR, LOG_AND, ADD, SUB, MUL, DIV, MOD, LSHIFT, RSHIFT, BIT_OR, BIT_NOT, BIT_AND, BIT_XOR, IS
};
OperatorEvaluator(TokenLocation location_, ExprPtrs args, Kind kind);
* If found, resulting token will be KEYWORD rather than IDENTIFIER.
*/
static std::unordered_set<std::string> keywords {
- "true", "false", "def", "return", "if", "else", "elif", "for", "in", "break", "continue", "while"
+ "true", "false", "def", "return", "if", "else", "elif", "for", "in", "break", "continue", "while", "none"
};
/**
case TokenType::KEYWORD:
if (t.text() == "true") return std::make_shared<BooleanEvaluator>(t.location(), true);
if (t.text() == "false") return std::make_shared<BooleanEvaluator>(t.location(), false);
+ if (t.text() == "none") return std::make_shared<EmptyEvaluator>(t.location());
if (t.text() == "def" && index < tokens.size() && tokens[index].text() == "(") return parseLambda();
break;
case TokenType::IDENTIFIER:
auto v = parseExprAboveComparisions();
if (!v) return {};
e = std::make_shared<OperatorEvaluator>(location, ExprPtrs{ std::move(e), std::move(v) }, OperatorEvaluator::Kind::IN);
+ } else if (t == "is") {
+ ++index;
+ auto v = parseExprAboveComparisions();
+ if (!v) return {};
+ e = std::make_shared<OperatorEvaluator>(location, ExprPtrs{ std::move(e), std::move(v) }, OperatorEvaluator::Kind::IS);
} else if (t == "not") {
++index;
if (!consume("in")) return {};
, ec);
}
+TEST_F(ScriptTest, operatorIs)
+{
+ TestBatchExecutor exec;
+ EvaluationContext ec{ exec };
+
+ executeCountAsserts(
+ R"_(
+ assert(true is true)
+ assert(not (true is false))
+ assert(false is false)
+ assert(not (false is true))
+ assert(0 is 0)
+ assert(not (0 is 0.0))
+ assert(not (0.0 is 0))
+ assert(1.0 is 1.0)
+ assert(not (false is 0))
+ assert(not (false is 0.0))
+ assert(not (false is ""))
+ assert("" is "")
+ assert("qwerty" is "qwerty")
+ assert(not ([] is []))
+ assert(not ({} is {}))
+ assert(not ({'':''} is {'':''}))
+ )_"
+ , 16);
+}
+
int main(int argc, char *argv[])
{
try {