#define NUMBER_OF_STEPS 10
-UIElement::UIElement(std::shared_ptr<AtspiAccessible> ptr, Optional<Point> scanningCoordinates,
+UIElement::UIElement(std::shared_ptr<AtspiAccessible> ptr, Point scanningCoordinates,
ApplicationCategory appCategory) : atspi(Singleton<UniversalSwitch>::instance().getAtspi()), obj(std::move(ptr)),
appCategory(appCategory), scanningCoordinates(std::move(scanningCoordinates))
{
Point UIElement::getScanningCoordinates() const
{
- if (scanningCoordinates)
- return *scanningCoordinates;
-
- ASSERT(obj, "No object and scanningCoordinates");
-
- auto comp = atspi_accessible_get_component(obj.get());
- ASSERT(comp, "No component in AT-SPI object");
-
- auto rect = atspi_component_get_extents(comp, ATSPI_COORD_TYPE_WINDOW, nullptr);
- ASSERT(rect, "No extents");
-
- // central point of rectangle
- return {rect->x + (rect->width / 2), rect->y + (rect->height / 2)};
+ return scanningCoordinates;
}
namespace
OTHER,
};
- UIElement(std::shared_ptr<AtspiAccessible> ptr, Optional<Point> scanningCoordinates, ApplicationCategory appCategory);
+ UIElement(std::shared_ptr<AtspiAccessible> ptr, Point scanningCoordinates, ApplicationCategory appCategory);
std::shared_ptr<AtspiAccessible> getObject() const;
ApplicationCategory appCategory;
Optional<std::unordered_map<std::string, std::string>> attributes;
- Optional<Point> scanningCoordinates;
+ Point scanningCoordinates;
};
#endif
#include "Lexer.hpp"
#include "Parser.hpp"
#include "EvaluationContext.hpp"
+#include "EvaluationValue.hpp"
#include "Evaluator.hpp"
#include "../ActivityFactory.hpp"
#include "../Observer.hpp"
return h->takeValue();
}
-namespace std
-{
- template <> struct hash<std::pair<detail::Kind, std::string>> {
- size_t operator()(const std::pair<detail::Kind, std::string> &p) const
- {
- return std::hash<std::string>()(p.second) ^ (unsigned char)p.first;
- }
- };
-}
-
struct TestExecutor : ExecutorInterface {
NavigationInterface::CallbackHandle contextChangedHandle;
struct ContextInfo {
bool found = false;
};
Monitor<TTSInfo> ttsInfo;
- std::unordered_map<std::string, EvaluationValue> variables;
- std::unordered_map<std::pair<detail::Kind, std::string>, EvaluationValue> setters;
- std::unordered_map<std::pair<detail::Kind, std::string>, EvaluationValue> getters;
+ std::unordered_map<std::string, EvaluationValue_> variables;
std::ostream &output;
// NOTE: constructor of TestExecutor must be called on main thread
{
insertRoleConstants();
insertStateConstants();
- variables["sleep"] = detail::UserFunctionType<double> {
- [&](double tm) -> EvaluationValue {
- if (tm > 0)
- {
- auto sleepTime = std::chrono::milliseconds{ static_cast<int>(std::floor(1000.0 * tm + 0.5)) };
- std::this_thread::sleep_for(sleepTime);
- }
- return {};
+ variables["sleep"] = [&](double tm) -> EvaluationValue_ {
+ if (tm > 0)
+ {
+ auto sleepTime = std::chrono::milliseconds{ static_cast<int>(std::floor(1000.0 * tm + 0.5)) };
+ std::this_thread::sleep_for(sleepTime);
}
+ return {};
};
- variables["print"] = detail::UserFunctionType<std::string> {
- [&](std::string txt) -> EvaluationValue {
- output << txt << "\n";
- return {};
- }
+ variables["print"] = [&](std::string txt) -> EvaluationValue_ {
+ output << txt << "\n";
+ return {};
};
- variables["get_at_point"] = detail::UserFunctionType<Point> {
- [&](Point pt) -> EvaluationValue {
- return convert(pt);
- }
+ variables["get_at_point"] = [&](Point pt) -> EvaluationValue_ {
+ return convertToUIElement(pt);
};
- variables["assert"] = detail::UserFunctionType<bool> {
- [&](bool condition) -> EvaluationValue {
- if (!condition) throw EvaluationFailure{} << "assertion failed";
- return {};
- }
+ variables["assert"] = [&](bool condition) -> EvaluationValue_ {
+ if (!condition) throw EvaluationFailure{} << "assertion failed";
+ return {};
};
- variables["wait_for_tts"] = detail::UserFunctionType<std::string> {
- [&](std::string pattern) -> EvaluationValue {
- std::regex regex;
- try
- {
- regex = std::regex {
- pattern,
- std::regex_constants::nosubs |
- std::regex_constants::optimize |
- std::regex_constants::ECMAScript
- };
- } catch (...)
- {
- throw EvaluationFailure{} << "invalid regex pattern '" << pattern << "'";
- }
-
+ variables["wait_for_tts"] = [&](std::string pattern) -> EvaluationValue_ {
+ std::regex regex;
+ try
+ {
+ regex = std::regex {
+ pattern,
+ std::regex_constants::nosubs |
+ std::regex_constants::optimize |
+ std::regex_constants::ECMAScript
+ };
+ } catch (...)
+ {
+ throw EvaluationFailure{} << "invalid regex pattern '" << pattern << "'";
+ }
+ {
auto h = ttsInfo.lock();
h->searchLine = std::move(regex);
h->found = false;
return {};
}
};
- variables["wait_for_application"] = detail::UserFunctionType<std::string> {
- [&](std::string name) -> EvaluationValue {
- auto h = contextInfo.lock();
- auto untilMoment = std::chrono::high_resolution_clock::now() + 3000ms;
- auto success = h.waitForCondition(untilMoment, [&]()
- {
- return h->rootName == name;
- });
- if (!success)
- throw EvaluationFailure{} << "wait_for_application('" << name << "'): operation timeouted, " <<
- "current root name is '" << h->rootName << "'";
- return {};
- }
- };
- variables["find_by_name"] = detail::UserFunctionType<std::string, std::vector<int>, std::vector<int>> {
- [&](std::string name, std::vector<int> roles, std::vector<int> states) -> EvaluationValue {
- auto root = getVisibleRoot();
- if (!root) throw EvaluationFailure{} << "no visible root (context changed didn't happen)";
- ASSERT(root->getObject());
- Monitor<BatchValueOrError<std::vector<std::shared_ptr<UIElement>>>> monitor;
-
- return executeOnMainThread([&]()
- {
- getAllObjects(root->getObject(), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> allElements) {
- findByName(std::get<0>(allElements), name, wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements) {
- auto &elems = std::get<0>(elements);
- makeUIElements(std::move(elems), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>> uiElems) {
- auto h = monitor.lock();
- h->setValue(std::move(std::get<0>(uiElems)));
- }));
- }));
- }), std::move(roles), std::move(states));
- }, monitor);
- }
+ variables["wait_for_application"] = [&](std::string name) -> EvaluationValue_ {
+ auto h = contextInfo.lock();
+ auto untilMoment = std::chrono::high_resolution_clock::now() + 3000ms;
+ auto success = h.waitForCondition(untilMoment, [&]() {
+ return h->rootName == name;
+ });
+ if (!success)
+ throw EvaluationFailure{} << "wait_for_application('" << name << "'): operation timeouted, " <<
+ "current root name is '" << h->rootName << "'";
+ return {};
};
- getters[ { detail::Kind::UIELEMENT, "name" }] = detail::UserFunctionType<std::shared_ptr<UIElement>> {
- [&](std::shared_ptr<UIElement> uiElem)
+ variables["find_by_name"] = [&](std::string name, std::vector<int> roles, std::vector<int> states) -> EvaluationValue_ {
+ auto root = getVisibleRoot();
+ if (!root) throw EvaluationFailure{} << "no visible root (context changed didn't happen)";
+ ASSERT(root->getObject());
+ Monitor<BatchValueOrError<std::vector<std::shared_ptr<UIElement>>>> monitor;
+
+ return executeOnMainThread([&]()
{
- ASSERT(uiElem->getObject());
- return executeOnMainThread([&]() {
- auto root = getVisibleRoot();
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- auto found = atspi->getName(uiElem->getObject());
- if (found)
- return std::move(*found);
- throw EvaluationFailure{} << "failed to get at-spi object's name (use dlogutil to get at-spi error message)";
- });
- }
- };
- getters[ { detail::Kind::POINT, "x" }] = detail::UserFunctionType<Point> {
- [&](Point p) -> EvaluationValue {
- return p.x;
- }
- };
- getters[ { detail::Kind::POINT, "y" }] = detail::UserFunctionType<Point> {
- [&](Point p) -> EvaluationValue {
- return p.y;
- }
+ getAllObjects(root->getObject(), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> allElements) {
+ findByName(std::get<0>(allElements), name, wrap(monitor, [ = ](DBus::ValueOrError<std::vector<AtspiAccessiblePtr>> elements) {
+ auto &elems = std::get<0>(elements);
+ makeUIElements(std::move(elems), wrap(monitor, [ = ](DBus::ValueOrError<std::vector<std::shared_ptr<UIElement>>> uiElems) {
+ auto h = monitor.lock();
+ h->setValue(std::move(std::get<0>(uiElems)));
+ }));
+ }));
+ }), std::move(roles), std::move(states));
+ }, monitor);
};
- getters[ { detail::Kind::UIELEMENT, "middle_point" }] = detail::UserFunctionType<std::shared_ptr<UIElement>> {
- [&](std::shared_ptr<UIElement> uiElem) -> EvaluationValue {
- ASSERT(uiElem->getObject());
- Optional<Rectangle> result;
- return executeOnMainThread([&]()
+ for (auto activityName : ActivityFactory::getInstance()->getAllActivityTypes()) {
+ variables[activityName] = [ = ](std::vector<EvaluationValue_> args) -> EvaluationValue_ {
+ auto activity = executeOnMainThread([&]()
{
- auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
- auto comp = atspi->getComponentInterface(uiElem->getObject());
- if (comp) {
- auto found = atspi->getScreenPosition(comp);
- if (found)
- return (*found).getCenterPoint();
- }
- throw EvaluationFailure{} << "failed to get at-spi object's screen position (use dlogutil to get at-spi error message)";
+ return ActivityFactory::getInstance()->createActivity(activityName);
});
- }
- };
- for (auto activityName : ActivityFactory::getInstance()->getAllActivityTypes()) {
- variables[activityName] = detail::FunctionType::Type{
- [ = ](std::vector<EvaluationValue> args) -> EvaluationValue {
- auto activity = executeOnMainThread([&]()
- {
- return ActivityFactory::getInstance()->createActivity(activityName);
- });
- if (!activity)
- throw EvaluationFailure{} << "failed to construct '" << activityName << "' activity";
- auto numOfArgs = activity->getRequiredNumberOfArgumentsIfAllowedInBatchProcessing();
- if (!numOfArgs)
- throw EvaluationFailure{} << "activity '" << activityName << "' is not supported";
- if (*numOfArgs != args.size())
- throw EvaluationFailure{} << "invalid number of arguments for activity '" << activityName <<
- "', got " << args.size() << ", expected " << *numOfArgs;
- auto uiActivity = std::dynamic_pointer_cast<UIActivity>(activity);
- if (!args.empty() && !uiActivity)
- throw EvaluationFailure{} << "activity '" << activityName << "' doesn't inherit from Observer<UIElement>, "
- "which it must, becuase it expects arguments";
- std::vector<std::shared_ptr<UIElement>> uiArgs(args.size());
- for (size_t i = 0; i < args.size(); ++i)
- {
- ASSERT(uiActivity);
- uiArgs[i] = detail::ConvertTo<std::shared_ptr<UIElement>>::convert(std::move(args[i]));
- if (!uiArgs[i])
- throw EvaluationFailure{} << "can't convert argument " << (i + 1) <<
- " of kind " << EvaluationValue::toString(args[i].kind()) << " to UIElement";
- }
- Monitor<BatchValueOrError<bool>> monitor;
+ if (!activity)
+ throw EvaluationFailure{} << "failed to construct '" << activityName << "' activity";
+ auto numOfArgs = activity->getRequiredNumberOfArgumentsIfAllowedInBatchProcessing();
+ if (!numOfArgs)
+ throw EvaluationFailure{} << "activity '" << activityName << "' is not supported";
+ if (*numOfArgs != args.size())
+ throw EvaluationFailure{} << "invalid number of arguments for activity '" << activityName <<
+ "', got " << args.size() << ", expected " << *numOfArgs;
+ auto uiActivity = std::dynamic_pointer_cast<Observer<UIElement>>(activity);
+ if (!args.empty() && !uiActivity)
+ throw EvaluationFailure{} << "activity '" << activityName << "' doesn't inherit from Observer<UIElement>, "
+ "which it must, becuase it expects arguments";
+ std::vector<std::shared_ptr<UIElement>> uiArgs(args.size());
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ ASSERT(uiActivity);
+ uiArgs[i] = args[i].convertToUIElement();
+ if (!uiArgs[i])
+ throw EvaluationFailure{} << "can't convert argument " << (i + 1) <<
+ " of kind " << args[i].typeName() << " to UIElement";
+ }
+ Monitor<BatchValueOrError<bool>> monitor;
+ {
+ executeOnMainThread([&]()
{
- executeOnMainThread([&]()
- {
- DEBUG("calling activity %s", activityName.c_str());
- for (auto &arg : uiArgs) {
- ASSERT(uiActivity);
- uiActivity->update(std::move(arg));
- }
- activity->process(DoneCallback{ [ = ] {
- auto h = monitor.lock();
- h->setValue(true);
- } });
- DEBUG("calling activity %s done", activityName.c_str());
- }, monitor);
- }
- return {};
- } };
+ DEBUG("calling activity %s", activityName.c_str());
+ for (auto &arg : uiArgs) {
+ ASSERT(uiActivity);
+ uiActivity->update(std::move(arg));
+ }
+ activity->process(DoneCallback{ [ = ] {
+ auto h = monitor.lock();
+ h->setValue(true);
+ } });
+ if (!activity->isCompleted())
+ throw EvaluationFailure{} << "not enough arguments for activity '" << activityName << "'";
+ DEBUG("calling activity %s done", activityName.c_str());
+ }, monitor);
+ auto h = monitor.lock();
+ ASSERT(*h); // sanity check, must be set, otherwise an exception was throw
+ }
+ return {};
+ };
}
auto updateContextInfo = [this](std::shared_ptr<UIElement> root, std::shared_ptr<NavigationElement> navigationContext) {
registerCb<NavigationCallbackType::ContextChanged>(std::move(updateContextInfo));
}
~TestExecutor() = default;
- EvaluationValue getVariableByName(const std::string &name) override
+ EvaluationValue_ getVariableByName(const std::string &name) override
{
auto it = variables.find(name);
if (it != variables.end())
throw EvaluationFailure{} << "unknown variable '" << name << "'";
}
- EvaluationValue setAttribute(const EvaluationValue &self, const std::string &name, EvaluationValue value) override
- {
- auto it = setters.find({ self.kind(), name });
- if (it != setters.end()) {
- return it->second.as<detail::FunctionType>()(self, std::move(value));
- }
- return ExecutorInterface::setAttribute(self, name, std::move(value));
- }
-
- EvaluationValue getAttribute(const EvaluationValue &self, const std::string &name) override
- {
- auto it = getters.find({ self.kind(), name });
- if (it != getters.end()) {
- return it->second.as<detail::FunctionType>()(self);
- }
- return ExecutorInterface::getAttribute(self, name);
- }
-
std::shared_ptr<UIElement> getVisibleRoot() override
{
auto h = contextInfo.lock();
{
return output;
}
- std::shared_ptr<UIElement> convert(Point pt) override
+ std::shared_ptr<UIElement> convertToUIElement(Point pt) override
{
return executeOnMainThread([&]() {
auto root = getVisibleRoot();
auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
auto found = atspi->getAtPoint(pt, Atspi::CoordType::Screen, root->getObject());
+ if (!found) throw EvaluationFailure{} << "no at-spi object found at position <" <<
+ pt.x << ", " << pt.y << ">";
return std::make_shared<UIElement>(std::move(found), pt, root->getApplicationCategory());
});
}
+
+ std::string getUIElementName(const std::shared_ptr<UIElement> &uiElem) override
+ {
+ return executeOnMainThread([&]() {
+ auto atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ auto found = atspi->getName(uiElem->getObject());
+ if (found)
+ return std::move(*found);
+ throw EvaluationFailure{} << "failed to get at-spi object's name (use dlogutil to get at-spi error message)";
+ });
+ }
+ std::string getUIElementUniqueId(const std::shared_ptr<UIElement> &uiElem) override
+ {
+ return executeOnMainThread([&]() {
+ return Atspi::getUniqueId(uiElem->getObject());
+ });
+ }
void findByName(const std::vector<AtspiAccessiblePtr> &elems, std::string requestedName, std::function<void(DBus::ValueOrError<std::vector<AtspiAccessiblePtr>>)> callback)
{
struct Exec {
}
}
- std::shared_ptr<UIElement> convert(const std::string &requestedName) override
+ std::shared_ptr<UIElement> convertToUIElement(const std::string &requestedName) override
{
Monitor<BatchValueOrError<std::shared_ptr<UIElement>>> monitor;
#include "EvaluationContext.hpp"
-using detail::VectorType;
-using detail::SetType;
-using detail::FunctionType;
-using detail::DictType;
-
-namespace std
-{
- template <> struct hash<std::pair<detail::Kind, detail::Kind>> {
- size_t operator()(std::pair<detail::Kind, detail::Kind> p) const
- {
- return ((unsigned char)p.first << 8) | (unsigned char)p.second;
- }
- };
-}
struct EvaluationContext::GlobalContext {
ExecutorInterface &executionInterface;
};
return globalContext->executionInterface;
}
-void EvaluationContext::setVariable(const std::string &ident, EvaluationValue val)
+void EvaluationContext::setVariable(const std::string &ident, EvaluationValue_ val)
{
variables[ident] = std::move(val);
}
-EvaluationValue EvaluationContext::getVariable(const Optional<TokenLocation> &loc, const std::string &ident)
+EvaluationValue_ EvaluationContext::getVariable(const Optional<TokenLocation> &loc, const std::string &ident)
{
EvaluationContext *self = this;
while (self) {
}
}
-EvaluationValue EvaluationContext::callFunction(const Optional<TokenLocation> &loc, EvaluationValue function, std::vector<EvaluationValue> values)
-{
- Optional<EvaluationValue> v;
-
- switch (function.kind()) {
- case detail::Kind::FUNCTION:
- try {
- return function.as<detail::FunctionType>()(std::move(values));
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
- case detail::Kind::STRING:
- case detail::Kind::INTEGER:
- case detail::Kind::DOUBLE:
- case detail::Kind::UIELEMENT:
- case detail::Kind::BOOLEAN:
- case detail::Kind::POINT:
- case detail::Kind::EMPTY:
- case detail::Kind::VECTOR:
- case detail::Kind::SET:
- case detail::Kind::DICT:
- break;
- }
- throw EvaluationFailure{loc} << "value of kind " << EvaluationValue::toString(function.kind()) <<
- " is not callable";
-}
-
-EvaluationValue ExecutorInterface::getVariableByName(const std::string &name)
-{
- throw EvaluationFailure{} << "unknown variable '" << name << "'";
-}
-
-EvaluationValue ExecutorInterface::setAttribute(const EvaluationValue &self, const std::string &name, EvaluationValue value)
-{
- throw EvaluationFailure{} << "value of kind " << EvaluationValue::toString(self.kind()) <<
- " doesn't accept attribute '" << name << "'";
-}
-
-EvaluationValue ExecutorInterface::getAttribute(const EvaluationValue &self, const std::string &name)
-{
- throw EvaluationFailure{} << "value of kind " << EvaluationValue::toString(self.kind()) <<
- " doesn't have attribute '" << name << "'";
-}
-
-std::shared_ptr<UIElement> ExecutorInterface::convert(Point pt)
-{
- throw EvaluationFailure{} << "no at-spi object found at position " << pt.toString();
-}
-
-std::shared_ptr<UIElement> ExecutorInterface::convert(const std::string &txt)
-{
- throw EvaluationFailure{} << "no at-spi object found with name '" << txt << "'";
-}
-
-EvaluationValue EvaluationContext::getAttribute(const Optional<TokenLocation> &loc, EvaluationValue self, const std::string &identifier)
-{
- try {
- return globalContext->executionInterface.getAttribute(self, identifier);
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
-}
-
-EvaluationValue EvaluationContext::setAttribute(const Optional<TokenLocation> &loc, EvaluationValue self, const std::string &identifier, EvaluationValue value)
-{
- try {
- return globalContext->executionInterface.setAttribute(self, identifier, std::move(value));
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
-}
-
-EvaluationValue EvaluationContext::convert(const Optional<TokenLocation> &loc, const EvaluationValue &value, detail::Kind targetType)
+std::string ExecutorInterface::getUIElementName(const std::shared_ptr<UIElement> &elem)
{
- if (value.kind() == targetType) return value;
-
- try {
- switch (value.kind()) {
- case detail::Kind::FUNCTION:
- case detail::Kind::STRING:
- return detail::ConvertTo<std::string>::convert(value);
- case detail::Kind::INTEGER:
- return detail::ConvertTo<int>::convert(value);
- case detail::Kind::DOUBLE:
- return detail::ConvertTo<double>::convert(value);
- case detail::Kind::UIELEMENT:
- return detail::ConvertTo<std::shared_ptr<UIElement>>::convert(value);
- case detail::Kind::BOOLEAN:
- return detail::ConvertTo<bool>::convert(value);
- case detail::Kind::POINT:
- return detail::ConvertTo<Point>::convert(value);
- case detail::Kind::EMPTY:
- return {};
- case detail::Kind::VECTOR:
- case detail::Kind::SET:
- case detail::Kind::DICT:
- break;
- }
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
- throw EvaluationFailure{loc} << "can't convert from " << EvaluationValue::toString(value.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::FUNCTION);
+ throw EvaluationFailure{} << "getUIElementName not implemeneted";
}
-int EvaluationContext::getSingleIndex(const std::vector<EvaluationValue> &args, int size, std::string typeName)
+std::string ExecutorInterface::getUIElementUniqueId(const std::shared_ptr<UIElement> &elem)
{
- ASSERT(args.size() >= 2);
- auto index = detail::ConvertTo<int>::convert(args[1]);
- auto origIndex = index;
- if (index < 0) index += size;
- if (index < 0 || index >= size) throw EvaluationFailure{} << origIndex << " is out of range for " << typeName << " of size " << size;
- return index;
+ throw EvaluationFailure{} << "getUIElementUniqueId not implemeneted";
}
-std::pair<int, int> EvaluationContext::getDoubleIndexes(const std::vector<EvaluationValue> &args, int size)
+std::shared_ptr<UIElement> ExecutorInterface::convertToUIElement(Point pt)
{
- ASSERT(args.size() >= 3);
- auto index1 = detail::ConvertTo<int>::convert(args[1]);
- auto index2 = detail::ConvertTo<int>::convert(args[2]);
- if (index1 < 0) index1 += size;
- if (index2 < 0) index2 += size;
-
- if (index1 < 0) index1 = 0;
- else if (index1 > size) index1 = size;
- if (index2 < index1) index2 = index1;
- else if (index2 > size) index2 = size;
- return std::pair<int, int> { index1, index2 };
+ throw EvaluationFailure{} << "convertToUIElement from Point not implemeneted";
}
-EvaluationValue EvaluationContext::evaluateAccessGet(const Optional<TokenLocation> &loc, const std::vector<EvaluationValue> &args)
+std::shared_ptr<UIElement> ExecutorInterface::convertToUIElement(const std::string &txt)
{
- try {
- ASSERT(!args.empty());
- auto &self = args[0];
- switch (self.kind()) {
- case detail::Kind::STRING:
- if (args.size() == 2) {
- auto index = getSingleIndex(args, static_cast<int>(self.as<std::string>().size()), "string");
- return self.as<std::string>().substr(index, 1);
- } else if (args.size() == 3) {
- auto indexes = getDoubleIndexes(args, static_cast<int>(self.as<std::string>().size()));
- return self.as<std::string>().substr(indexes.first, indexes.second - indexes.first);
- }
- break;
- case detail::Kind::FUNCTION:
- case detail::Kind::INTEGER:
- case detail::Kind::DOUBLE:
- case detail::Kind::UIELEMENT:
- case detail::Kind::BOOLEAN:
- case detail::Kind::POINT:
- case detail::Kind::EMPTY:
- case detail::Kind::SET:
- break;
- case detail::Kind::VECTOR:
- if (args.size() == 2) {
- auto index = getSingleIndex(args, static_cast<int>(self.as<VectorType>().size()), "vector");
- return self.as<VectorType>()[index];
- } else if (args.size() == 3) {
- auto indexes = getDoubleIndexes(args, static_cast<int>(self.as<VectorType>().size()));
- std::vector<EvaluationValue> tmp;
- tmp.reserve(indexes.second - indexes.first);
- for (auto i = indexes.first; i < indexes.second; ++i)
- tmp.push_back(self.as<VectorType>()[i]);
- return std::move(tmp);
- }
- break;
- case detail::Kind::DICT:
- if (args.size() == 2) {
- auto key = EvaluationValueKey{ args[1] };
- auto it = self.as<detail::DictType>().find(key);
- if (it == self.as<detail::DictType>().end()) throw EvaluationFailure{loc} << "key not found";
- return it->second;
- }
- break;
- }
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
-
- std::ostringstream tmp;
- tmp << EvaluationValue::toString(args[0].kind()) << "[";
- for (auto i = 1u; i < args.size(); ++i) {
- if (i != 1) tmp << ", ";
- tmp << EvaluationValue::toString(args[i].kind());
- }
- tmp << "]";
- throw EvaluationFailure{loc} << "unable to evaluate " << tmp.str();
-}
-
-EvaluationValue EvaluationContext::evaluateAccessSet(const Optional<TokenLocation> &loc, std::vector<EvaluationValue> args)
-{
- try {
- ASSERT(!args.empty());
- auto &self = args[0];
- switch (self.kind()) {
- case detail::Kind::STRING:
- case detail::Kind::FUNCTION:
- case detail::Kind::INTEGER:
- case detail::Kind::DOUBLE:
- case detail::Kind::UIELEMENT:
- case detail::Kind::BOOLEAN:
- case detail::Kind::POINT:
- case detail::Kind::EMPTY:
- case detail::Kind::SET:
- break;
- case detail::Kind::VECTOR:
- if (args.size() == 3) {
- auto index = getSingleIndex(args, static_cast<int>(self.as<VectorType>().size()), "vector");
- self.as<VectorType>()[index] = args[2];
- return std::move(args[2]);
- } else if (args.size() == 4 && args[3].kind() == detail::Kind::VECTOR) {
- auto indexes = getDoubleIndexes(args, static_cast<int>(self.as<VectorType>().size()));
- std::vector<EvaluationValue> tmp;
- tmp.reserve(self.as<VectorType>().size() - (indexes.second - indexes.first) + args[3].as<VectorType>().size());
- for (auto i = 0; i < indexes.first; ++i) tmp.push_back(std::move(self.as<VectorType>()[i]));
- for (auto &v : args[3].as<VectorType>()) tmp.push_back(v);
- for (auto i = indexes.second; i < static_cast<int>(self.as<VectorType>().size()); ++i) tmp.push_back(std::move(self.as<VectorType>()[i]));
- self.as<VectorType>() = std::move(tmp);
- return {};
- }
- break;
- case detail::Kind::DICT:
- if (args.size() == 3) {
- self.as<DictType>()[std::move(args[1])] = args[2];
- return std::move(args[2]);
- }
- break;
- }
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
-
- std::ostringstream tmp;
- tmp << EvaluationValue::toString(args[0].kind()) << "[";
- for (auto i = 1; i < (int)args.size() - 1; ++i) {
- if (i != 1) tmp << ", ";
- tmp << EvaluationValue::toString(args[i].kind());
- }
- tmp << "] = " << EvaluationValue::toString(args.back().kind());
- throw EvaluationFailure{loc} << "unable to evaluate " << tmp.str();
+ throw EvaluationFailure{} << "convertToUIElement from String not implemeneted";
}
-
-EvaluationValue EvaluationContext::evaluateMinus(const Optional<TokenLocation> &loc, const EvaluationValue &self)
+EvaluationValue_ ExecutorInterface::getVariableByName(const std::string &name)
{
- try {
- switch (self.kind()) {
- case detail::Kind::INTEGER:
- return -self.as<int>();
- case detail::Kind::DOUBLE:
- return -self.as<double>();
- case detail::Kind::STRING:
- case detail::Kind::SET:
- case detail::Kind::DICT:
- case detail::Kind::VECTOR:
- case detail::Kind::FUNCTION:
- case detail::Kind::UIELEMENT:
- case detail::Kind::BOOLEAN:
- case detail::Kind::POINT:
- case detail::Kind::EMPTY:
- break;
- }
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
- throw EvaluationFailure{loc} << "unable to negate value of type " << EvaluationValue::toString(self.kind());
+ throw EvaluationFailure{} << "getVariableByName not implemeneted";
}
-bool EvaluationContext::evaluateIn(const Optional<TokenLocation> &loc, const EvaluationValue &self, const EvaluationValue &value)
-{
- try {
- switch (self.kind()) {
- case detail::Kind::STRING: {
- auto val = detail::ConvertTo<std::string>::convert(value);
- return self.as<std::string>().find(val) != std::string::npos;
- }
- case detail::Kind::SET: {
- return self.as<SetType>().find(value) != self.as<SetType>().end();
- }
- case detail::Kind::DICT: {
- return self.as<DictType>().find(value) != self.as<DictType>().end();
- }
- case detail::Kind::VECTOR:
- for (auto &v : self.as<VectorType>())
- if (v == value) return true;
- return false;
- case detail::Kind::FUNCTION:
- case detail::Kind::INTEGER:
- case detail::Kind::DOUBLE:
- case detail::Kind::UIELEMENT:
- case detail::Kind::BOOLEAN:
- case detail::Kind::POINT:
- case detail::Kind::EMPTY:
- break;
- }
- } catch (EvaluationFailure &e) {
- if (loc) e.setLocationIfMissing(*loc);
- throw;
- }
- throw EvaluationFailure{loc} << "value of type " << EvaluationValue::toString(self.kind()) << " is not a collection";
-}
class UIElement;
+/**
+ * @brief Interface class for providing external world functionality (at-spi queries and so on)
+ *
+ * User should reimplement all methods. Default implementations will throw "not implemented" exceptions.
+ */
struct ExecutorInterface {
virtual ~ExecutorInterface() = default;
- virtual EvaluationValue getVariableByName(const std::string &name);
- virtual EvaluationValue setAttribute(const EvaluationValue &self, const std::string &name, EvaluationValue value);
- virtual EvaluationValue getAttribute(const EvaluationValue &self, const std::string &name);
- virtual std::shared_ptr<UIElement> convert(Point pt);
- virtual std::shared_ptr<UIElement> convert(const std::string &);
+ /**
+ * @brief Finds variable by name
+ *
+ * Fallback method, when variable is not found in any script's scopes.
+ * This is sort of global variables implementation.
+ * Note, while variable found by this found can't be overwritten (can be updated)
+ * it can be shadowed in batch. For example:
+ * {
+ * foo = 1
+ * print(foo)
+ * }
+ * will print 1 even if getVariableByName would return different value for foo.
+ */
+ virtual EvaluationValue_ getVariableByName(const std::string &name);
+
+ /**
+ * @brief Finds object on screen by position
+ *
+ * Implementation is expected to return object "closest" to user at position
+ * given as argument. Batch implementation queries visible at-spi objects
+ * for their position and "walk" all objects in tree-like fashion, until
+ * single object is found. If the object is not found, then exception
+ * should be raised.
+ */
+ virtual std::shared_ptr<UIElement> convertToUIElement(Point pt);
+
+ /**
+ * @brief Finds object on screen by name
+ *
+ * Implementation is expected to return object with at-spi name
+ * exactly matching one given, but only if there's only one. Otherwise an
+ * exception should be raised.
+ */
+ virtual std::shared_ptr<UIElement> convertToUIElement(const std::string &);
+
+ /**
+ * @brief Returns at-spi name of given object
+ */
+ virtual std::string getUIElementName(const std::shared_ptr<UIElement> &);
+
+ /**
+ * @brief Returns string uniquely identifying given at-spi object
+ */
+ virtual std::string getUIElementUniqueId(const std::shared_ptr<UIElement> &);
+
+ /**
+ * @brief Returns at-spi object, which is root of visible at-spi elements
+ *
+ * Visible root is expected to be some descendant of application's root element.
+ */
virtual std::shared_ptr<UIElement> getVisibleRoot() = 0;
+
+ /**
+ * @brief Returns stream, which should be used for writing any kind of output
+ *
+ * Note, that this stream should be only used from batch's thread.
+ * Stream might as well point to /dev/null.
+ * There's only single stream for all kinds of output, debug or not.
+ */
virtual std::ostream &outputStream() = 0;
};
* This variables hides variable with the same name from some parent EvaluationContext,
* but it doesn't overwrite it.
*/
- void setVariable(const std::string &ident, EvaluationValue val);
+ void setVariable(const std::string &ident, EvaluationValue_ val);
/**
* @brief Returns variable with name
* order until value is found. At last ExecutionInterface object will be requested to provide the value
* by calling getVariableByName.
*/
- EvaluationValue getVariable(const Optional<TokenLocation> &loc, const std::string &ident);
-
- EvaluationValue callFunction(const Optional<TokenLocation> &loc, EvaluationValue function, std::vector<EvaluationValue> values);
- EvaluationValue getAttribute(const Optional<TokenLocation> &loc, EvaluationValue self, const std::string &identifier);
- EvaluationValue setAttribute(const Optional<TokenLocation> &loc, EvaluationValue self, const std::string &identifier, EvaluationValue value);
- EvaluationValue convert(const Optional<TokenLocation> &loc, const EvaluationValue &value, detail::Kind targetType);
- EvaluationValue evaluateAccessGet(const Optional<TokenLocation> &loc, const std::vector<EvaluationValue> &args);
- EvaluationValue evaluateAccessSet(const Optional<TokenLocation> &loc, std::vector<EvaluationValue> args);
- bool evaluateIn(const Optional<TokenLocation> &loc, const EvaluationValue &self, const EvaluationValue &value);
- EvaluationValue evaluateMinus(const Optional<TokenLocation> &loc, const EvaluationValue &self);
+ EvaluationValue_ getVariable(const Optional<TokenLocation> &loc, const std::string &ident);
/**
* @brief Returns reference to ExecutionInterface object
static EvaluationContext &getCurrentEvaluationContext();
private:
void initializeGlobalContext(ExecutorInterface &ei);
- int getSingleIndex(const std::vector<EvaluationValue> &args, int size, std::string typeName);
- std::pair<int, int> getDoubleIndexes(const std::vector<EvaluationValue> &args, int size);
- std::unordered_map<std::string, EvaluationValue> variables;
+ std::unordered_map<std::string, EvaluationValue_> variables;
EvaluationContext *parent = nullptr;
std::shared_ptr<GlobalContext> globalContext;
};
*/
#include "EvaluationValue.hpp"
+#include "EvaluationValueBase.hpp"
#include "EvaluationContext.hpp"
#include "../UniversalSwitch.hpp"
#include <cmath>
-EvaluationFailure::EvaluationFailure(Optional<TokenLocation> loc) : location_(std::move(loc))
+EvaluationValue_::EvaluationValue_() : value(EvaluationValueBase::create())
{
}
-void EvaluationFailure::setLocationIfMissing(TokenLocation loc)
+EvaluationValue_::EvaluationValue_(std::nullptr_t) : value(EvaluationValueBase::create())
{
- if (!location_) location_ = std::move(loc);
}
-std::string EvaluationFailure::message() const
+EvaluationValue_::EvaluationValue_(EvaluationValuePtr v) : value(std::move(v))
{
- return text->str();
}
-bool EvaluationFailure::hasLocation() const
+void EvaluationValue_::convertTo(int &v) const
{
- return bool(location_);
+ EvaluationValueInteger tmp = {};
+ convertTo(tmp);
+ v = static_cast<std::remove_reference<decltype(v)>::type>(tmp);
}
-
-TokenLocation EvaluationFailure::location()
+void EvaluationValue_::convertTo(unsigned int &v) const
{
- ASSERT(hasLocation());
- return *location_;
+ EvaluationValueInteger tmp = {};
+ convertTo(tmp);
+ v = static_cast<std::remove_reference<decltype(v)>::type>(tmp);
}
-
-EvaluationValue detail::FunctionType::operator()(std::vector<EvaluationValue> args) const
+void EvaluationValue_::convertTo(short &v) const
{
- return function(std::move(args));
+ EvaluationValueInteger tmp = {};
+ convertTo(tmp);
+ v = static_cast<std::remove_reference<decltype(v)>::type>(tmp);
}
-
-std::string EvaluationValue::toString(detail::Kind k)
-{
- switch (k) {
- case detail::Kind::EMPTY:
- return "EMPTY";
- case detail::Kind::STRING:
- return "STRING";
- case detail::Kind::INTEGER:
- return "INTEGER";
- case detail::Kind::DOUBLE:
- return "DOUBLE";
- case detail::Kind::UIELEMENT:
- return "UIELEMENT";
- case detail::Kind::BOOLEAN:
- return "BOOLEAN";
- case detail::Kind::POINT:
- return "POINT";
- case detail::Kind::FUNCTION:
- return "FUNCTION";
- case detail::Kind::VECTOR:
- return "VECTOR";
- case detail::Kind::SET:
- return "SET";
- case detail::Kind::DICT:
- return "DICT";
- }
- return "";
+void EvaluationValue_::convertTo(unsigned short &v) const
+{
+ EvaluationValueInteger tmp = {};
+ convertTo(tmp);
+ v = static_cast<std::remove_reference<decltype(v)>::type>(tmp);
+}
+void EvaluationValue_::convertTo(signed char &v) const
+{
+ EvaluationValueInteger tmp = {};
+ convertTo(tmp);
+ v = static_cast<std::remove_reference<decltype(v)>::type>(tmp);
+}
+void EvaluationValue_::convertTo(unsigned char &v) const
+{
+ EvaluationValueInteger tmp = {};
+ convertTo(tmp);
+ v = static_cast<std::remove_reference<decltype(v)>::type>(tmp);
}
-detail::Data::Data(int t) : integer(t) { }
-detail::Data::Data(double t) : double_(t) { }
-detail::Data::Data(bool t) : boolean(t) { }
-detail::Data::Data(std::string t) : string(std::move(t)) { }
-detail::Data::Data(std::shared_ptr<UIElement> t) : uiElement(std::move(t)) { }
-detail::Data::Data(Point t) : point(t) { }
-detail::Data::Data(FunctionType t) : function(std::move(t)) { }
-detail::Data::Data(VectorType t) : vector(std::make_shared<VectorType>(std::move(t))) { }
-detail::Data::Data(SetType t) : set(std::make_shared<SetType>(std::move(t))) { }
-detail::Data::Data(DictType t) : dict(std::make_shared<DictType>(std::move(t))) { }
+#define Q(type) \
+ EvaluationValue_::EvaluationValue_(EvaluationValue ## type v) : value(EvaluationValueBase::create(std::move(v))) { } \
+ EvaluationValue ## type EvaluationValue_::convertTo ## type() const { \
+ EvaluationValue ## type tmp; \
+ convertTo(tmp); \
+ return std::move(tmp); \
+ } \
+ const EvaluationValue ## type &EvaluationValue_::as ## type() { return value->as ## type(); } \
+ bool EvaluationValue_::is ## type() const { return value->is ## type(); } \
+ void EvaluationValue_::convertTo(EvaluationValue ## type &r) const { \
+ auto t = value->convertTo ## type(); \
+ if (t.get() == value.get()) r = value->as ## type(); \
+ else r = std::move(t->as ## type()); \
+ }
+Q(String)
+Q(Integer)
+Q(Double)
+Q(UIElement)
+Q(Boolean)
+Q(Point)
+Q(Function)
+Q(Vector)
+Q(Set)
+Q(Dict)
+#undef Q
-size_t EvaluationValueKey::calculateHash(const EvaluationValue &self)
-{
- switch (self.kind()) {
- case detail::Kind::STRING:
- return std::hash<std::string>()(self.as<std::string>());
- case detail::Kind::INTEGER:
- return std::hash<int>()(self.as<int>());
- case detail::Kind::DOUBLE:
- return std::hash<double>()(self.as<double>());
- case detail::Kind::UIELEMENT:
- return std::hash<std::string>()(Atspi::getUniqueId(self.as<std::shared_ptr<UIElement>>()->getObject()));
- case detail::Kind::BOOLEAN:
- return std::hash<bool>()(self.as<bool>());
- case detail::Kind::POINT:
- return (std::hash<size_t>()(self.as<Point>().x) << 16) ^ std::hash<size_t>()(self.as<Point>().y);
- case detail::Kind::EMPTY:
- return 0;
- case detail::Kind::FUNCTION:
- case detail::Kind::SET:
- case detail::Kind::VECTOR:
- case detail::Kind::DICT:
- break;
- }
- throw EvaluationFailure{} << "can't calculate hash for value of type " << EvaluationValue::toString(self.kind());
+std::string EvaluationValue_::typeName() const
+{
+ return value->typeName();
}
-EvaluationValueKey::EvaluationValueKey(EvaluationValue val) :
- value(std::make_shared<EvaluationValue>(std::move(val)))
+bool EvaluationValue_::operator == (const EvaluationValue_ &other) const
{
- hash = calculateHash(getValue());
+ return value->oper_cmp(EvaluationValueBase::Cmp::Equal, other.value);
}
-
-EvaluationValueKey::EvaluationValueKey(EvaluationValue val, size_t hash) :
- value(std::make_shared<EvaluationValue>(std::move(val))), hash(hash)
-{}
-
-bool EvaluationValueKey::operator == (const EvaluationValueKey &k) const
+bool EvaluationValue_::operator != (const EvaluationValue_ &other) const
{
- return getValue() == k.getValue();
+ return value->oper_cmp(EvaluationValueBase::Cmp::NotEqual, other.value);
}
-
-std::ostream &operator << (std::ostream &s, const EvaluationValue &v)
-{
- switch (v.kind()) {
- case detail::Kind::EMPTY:
- s << "{}";
- break;
- case detail::Kind::STRING:
- s << "'" << v.data.string << "'";
- break;
- case detail::Kind::INTEGER:
- s << v.data.integer;
- break;
- case detail::Kind::DOUBLE:
- s << v.data.double_;
- break;
- case detail::Kind::UIELEMENT:
- s << Atspi::getUniqueId(v.data.uiElement->getObject());
- break;
- case detail::Kind::BOOLEAN:
- s << (v.data.boolean ? "true" : "false");
- break;
- case detail::Kind::POINT:
- s << "<" << v.data.point.x << ", " << v.data.point.y << ">";
- break;
- case detail::Kind::FUNCTION:
- s << "functor";
- break;
- case detail::Kind::VECTOR: {
- s << "[";
- bool first = true;
- for (auto &a : *v.data.vector) {
- if (first) {
- s << " ";
- first = false;
- } else {
- s << ", ";
- }
- s << a;
- }
- s << " ]";
- break;
- }
- case detail::Kind::SET: {
- s << "{";
- bool first = true;
- for (auto &a : *v.data.set) {
- if (first) {
- s << " ";
- first = false;
- } else {
- s << ", ";
- }
- s << a;
- }
- s << " }";
- break;
- }
- case detail::Kind::DICT: {
- s << "{";
- bool first = true;
- for (auto &a : *v.data.dict) {
- if (first) {
- s << " ";
- first = false;
- } else {
- s << ", ";
- }
- s << "{ " << a.first << ": " << a.second << " }";
- }
- s << " }";
- break;
- }
- }
- return s;
+bool EvaluationValue_::operator < (const EvaluationValue_ &other) const
+{
+ return value->oper_order(EvaluationValueBase::Order::Less, other.value);
+}
+bool EvaluationValue_::operator > (const EvaluationValue_ &other) const
+{
+ return value->oper_order(EvaluationValueBase::Order::More, other.value);
+}
+bool EvaluationValue_::operator <= (const EvaluationValue_ &other) const
+{
+ return value->oper_order(EvaluationValueBase::Order::LessThan, other.value);
+}
+bool EvaluationValue_::operator >= (const EvaluationValue_ &other) const
+{
+ return value->oper_order(EvaluationValueBase::Order::MoreThan, other.value);
}
-std::ostream &operator << (std::ostream &s, const EvaluationValueKey &v)
+size_t EvaluationValue_::hash() const
{
- return s << v.getValue();
+ return value->oper_hash();
+}
+bool EvaluationValue_::contains(const EvaluationValue_ &val) const
+{
+ return value->oper_contains(val.value);
}
-detail::Kind EvaluationValue::kind() const
+EvaluationValue_::operator bool() const
{
- return kind_;
+ return value->oper_is_true();
}
-bool EvaluationValue::operator == (const EvaluationValue &other) const
-{
- if (kind() != other.kind()) {
- if (kind() == detail::Kind::INTEGER && other.kind() == detail::Kind::DOUBLE)
- return static_cast<double>(as<int>()) == other.as<double>();
- if (kind() == detail::Kind::DOUBLE && other.kind() == detail::Kind::INTEGER)
- return static_cast<double>(other.as<int>()) == as<double>();
- return false;
- }
- switch (kind()) {
- case detail::Kind::EMPTY:
- return true;
- case detail::Kind::STRING:
- return as<std::string>() == other.as<std::string>();
- case detail::Kind::INTEGER:
- return as<int>() == other.as<int>();
- case detail::Kind::DOUBLE:
- return as<int>() == other.as<int>();
- case detail::Kind::UIELEMENT:
- return Atspi::getUniqueId(as<std::shared_ptr<UIElement>>()->getObject()) ==
- Atspi::getUniqueId(other.as<std::shared_ptr<UIElement>>()->getObject());
- case detail::Kind::BOOLEAN:
- return as<bool>() == other.as<bool>();
- case detail::Kind::POINT:
- return as<Point>() == other.as<Point>();
- case detail::Kind::VECTOR:
- return as<detail::VectorType>() == other.as<detail::VectorType>();
- case detail::Kind::SET:
- return as<detail::SetType>() == other.as<detail::SetType>();
- case detail::Kind::DICT:
- return as<detail::DictType>() == other.as<detail::DictType>();
- case detail::Kind::FUNCTION:
- throw EvaluationFailure{} << "can't compare " << EvaluationValue::toString(kind()) <<
- " with " << EvaluationValue::toString(other.kind());
- };
- return false;
+EvaluationValue_ EvaluationValue_::operator()(const std::vector<EvaluationValue_> &values)
+{
+ return value->oper_call(values);
+}
+EvaluationValue_ EvaluationValue_::index_get(const EvaluationValue_ &i1) const
+{
+ return value->oper_index_get(i1.value);
+}
+EvaluationValue_ EvaluationValue_::index_get(const EvaluationValue_ &i1, const EvaluationValue_ &i2) const
+{
+ return value->oper_index_get(i1.value, i2.value);
+}
+EvaluationValue_ EvaluationValue_::index_set(const EvaluationValue_ &i1, const EvaluationValue_ &val)
+{
+ return value->oper_index_set(i1.value, val.value);
+}
+EvaluationValue_ EvaluationValue_::index_set(const EvaluationValue_ &i1, const EvaluationValue_ &i2, const EvaluationValue_ &val)
+{
+ return value->oper_index_set(i1.value, i2.value, val.value);
}
-bool EvaluationValue::operator < (const EvaluationValue &other) const
-{
- if (kind() != other.kind()) {
- if (kind() == detail::Kind::INTEGER && other.kind() == detail::Kind::DOUBLE)
- return static_cast<double>(as<int>()) < other.as<double>();
- if (kind() == detail::Kind::DOUBLE && other.kind() == detail::Kind::INTEGER)
- return as<double>() < static_cast<double>(other.as<int>());
- } else {
- switch (kind()) {
- case detail::Kind::EMPTY:
- break;
- case detail::Kind::STRING:
- return as<std::string>() < other.as<std::string>();
- case detail::Kind::INTEGER:
- return as<int>() < other.as<int>();
- case detail::Kind::DOUBLE:
- return as<double>() < other.as<double>();
- case detail::Kind::UIELEMENT:
- break;
- case detail::Kind::BOOLEAN:
- break;
- case detail::Kind::POINT:
- break;
- case detail::Kind::FUNCTION:
- break;
- case detail::Kind::VECTOR:
- for (auto i = 0u; i < std::min(as<detail::VectorType>().size(), other.as<detail::VectorType>().size()); ++i) {
- if (as<detail::VectorType>()[i] < other.as<detail::VectorType>()[i]) return true;
- if (!(as<detail::VectorType>()[i] == other.as<detail::VectorType>()[i])) return false;
- }
- return as<detail::VectorType>().size() < other.as<detail::VectorType>().size();
- case detail::Kind::SET:
- break;
- case detail::Kind::DICT:
- break;
- };
- }
- throw EvaluationFailure{} << "can't order values of type " << EvaluationValue::toString(kind()) <<
- " and " << EvaluationValue::toString(other.kind());
+EvaluationValue_ EvaluationValue_::operator - () const
+{
+ return value->oper_negate();
}
-EvaluationValue::operator bool () const
-{
- switch (kind()) {
- case detail::Kind::INTEGER:
- return as<int>() != 0;
- case detail::Kind::DOUBLE:
- return as<double>() != 0;
- case detail::Kind::BOOLEAN:
- return as<bool>();
- case detail::Kind::STRING:
- return !as<std::string>().empty();
- case detail::Kind::UIELEMENT:
- return true;
- case detail::Kind::FUNCTION:
- return true;
- case detail::Kind::POINT:
- return true;
- case detail::Kind::VECTOR:
- return !as<detail::VectorType>().empty();
- case detail::Kind::SET:
- return !as<detail::SetType>().empty();
- case detail::Kind::DICT:
- return !as<detail::DictType>().empty();
- case detail::Kind::EMPTY:
- return false;
- }
- ASSERT(0); // every type has a true / false value in boolean context
- return false;
+EvaluationValue_ EvaluationValue_::attr_get(const std::string &name) const
+{
+ return value->oper_attr_get(name);
+}
+EvaluationValue_ EvaluationValue_::attr_set(const std::string &name, const EvaluationValue_ &val)
+{
+ return value->oper_attr_set(name, val.value);
}
-bool EvaluationValue::operator != (const EvaluationValue &other) const
+std::ostream &operator << (std::ostream &s, const EvaluationValue_ &v)
{
- return !(*this == other);
+ return s << v.value;
}
-bool EvaluationValue::operator > (const EvaluationValue &other) const
+EvaluationFailure::EvaluationFailure(Optional<TokenLocation> loc) : location_(std::move(loc))
{
- return (other < *this);
}
-bool EvaluationValue::operator <= (const EvaluationValue &other) const
+void EvaluationFailure::setLocationIfMissing(TokenLocation loc)
{
- return !(other < *this);
+ if (!location_) location_ = std::move(loc);
}
-bool EvaluationValue::operator >= (const EvaluationValue &other) const
+std::string EvaluationFailure::message() const
{
- return !(*this < other);
+ return text->str();
}
-namespace detail
-{
- int ConvertTo<int>::convert(EvaluationValue e)
- {
- if (e.kind() == detail::Kind::INTEGER) return e.as<int>();
- if (e.kind() == detail::Kind::DOUBLE) {
- if (static_cast<double>(static_cast<int>(e.as<double>())) == e.as<double>()) {
- return static_cast<int>(e.as<double>());
- }
- } else if (e.kind() == detail::Kind::STRING) {
- auto text = e.as<std::string>();
- size_t pos = 0;
- auto value = std::stoi(text, &pos);
- if (pos == text.size())
- return value;
- }
- throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::INTEGER);
- }
- double ConvertTo<double>::convert(EvaluationValue e)
- {
- if (e.kind() == detail::Kind::INTEGER) return e.as<int>();
- if (e.kind() == detail::Kind::DOUBLE) return e.as<double>();
- if (e.kind() == detail::Kind::STRING) {
- auto text = e.as<std::string>();
- size_t pos = 0;
- auto value = std::stod(text, &pos);
- if (pos == text.size())
- return value;
- }
- throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::DOUBLE);
- }
- std::string ConvertTo<std::string>::convert(EvaluationValue e)
- {
- if (e.kind() == detail::Kind::INTEGER) return std::to_string(e.as<int>());
- if (e.kind() == detail::Kind::BOOLEAN) return e.as<bool>() ? "true" : "false";
- if (e.kind() == detail::Kind::STRING) return e.as<std::string>();
- if (e.kind() == detail::Kind::POINT)
- return "<" + std::to_string(e.as<Point>().x) + ", " + std::to_string(e.as<Point>().y) + ">";
- throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::STRING);
- }
- bool ConvertTo<bool>::convert(EvaluationValue e)
- {
- return bool(e);
- }
- std::shared_ptr<UIElement> ConvertTo<std::shared_ptr<UIElement>>::convert(EvaluationValue e)
- {
- if (e.kind() == detail::Kind::UIELEMENT) return std::move(e.as<std::shared_ptr<UIElement>>());
- if (e.kind() == detail::Kind::POINT)
- return EvaluationContext::getCurrentEvaluationContext().executionInterface().convert(e.as<Point>());
- if (e.kind() == detail::Kind::STRING)
- return EvaluationContext::getCurrentEvaluationContext().executionInterface().convert(e.as<std::string>());
- throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::UIELEMENT);
- }
- EvaluationValue ConvertTo<EvaluationValue>::convert(EvaluationValue e)
- {
- return std::move(e);
- }
- Point ConvertTo<Point>::convert(EvaluationValue e)
- {
- if (e.kind() == detail::Kind::POINT) return e.as<Point>();
- throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::POINT);
- }
+bool EvaluationFailure::hasLocation() const
+{
+ return bool(location_);
+}
- template <> std::string &get<std::string>(detail::Data &d)
- {
- return d.string;
- }
- template <> int &get<int>(detail::Data &d)
- {
- return d.integer;
- }
- template <> std::shared_ptr<UIElement> &get<std::shared_ptr<UIElement>>(detail::Data &d)
- {
- return d.uiElement;
- }
- template <> bool &get<bool>(detail::Data &d)
- {
- return d.boolean;
- }
- template <> double &get<double>(detail::Data &d)
- {
- return d.double_;
- }
- template <> Point &get<Point>(detail::Data &d)
- {
- return d.point;
- }
- template <> FunctionType &get<detail::FunctionType>(detail::Data &d)
- {
- return d.function;
- }
- template <> VectorType &get<detail::VectorType>(detail::Data &d)
- {
- return *d.vector;
- }
- template <> SetType &get<detail::SetType>(detail::Data &d)
- {
- return *d.set;
- }
- template <> DictType &get<detail::DictType>(detail::Data &d)
- {
- return *d.dict;
- }
+TokenLocation EvaluationFailure::location()
+{
+ ASSERT(hasLocation());
+ return *location_;
+}
- template <> std::string get<std::string>(const detail::Data &d)
- {
- return d.string;
- }
- template <> int get<int>(const detail::Data &d)
- {
- return d.integer;
- }
- template <> std::shared_ptr<UIElement> get<std::shared_ptr<UIElement>>(const detail::Data &d)
- {
- return d.uiElement;
- }
- template <> bool get<bool>(const detail::Data &d)
- {
- return d.boolean;
- }
- template <> double get<double>(const detail::Data &d)
- {
- return d.double_;
- }
- template <> Point get<Point>(const detail::Data &d)
- {
- return d.point;
- }
- template <> FunctionType get<detail::FunctionType>(const detail::Data &d)
- {
- return d.function;
- }
- template <> VectorType get<detail::VectorType>(const detail::Data &d)
- {
- return *d.vector;
- }
- template <> SetType get<detail::SetType>(const detail::Data &d)
- {
- return *d.set;
- }
- template <> DictType get<detail::DictType>(const detail::Data &d)
- {
- return *d.dict;
- }
-};
#include <unordered_map>
#include <tuple>
#include <ostream>
-
-class EvaluationContext;
-
-class EvaluationFailure;
-class EvaluationValue;
-class EvaluationValueKey
-{
-public:
- EvaluationValueKey() = default;
- EvaluationValueKey(EvaluationValue val);
- EvaluationValueKey(EvaluationValue val, size_t hash);
-
- const EvaluationValue &getValue() const
- {
- return *value;
- }
- operator const EvaluationValue &() const
- {
- return *value;
- }
-
- size_t getHash() const
- {
- return hash;
- }
-
- bool operator == (const EvaluationValueKey &k) const;
-
- friend std::ostream &operator << (std::ostream &s, const EvaluationValue &v);
-
- static size_t calculateHash(const EvaluationValue &v);
-private:
- std::shared_ptr<EvaluationValue> value;
- size_t hash = 0;
-};
-
-namespace std
-{
- template <> struct hash<EvaluationValueKey> {
- size_t operator()(const EvaluationValueKey &v) const
- {
- return v.getHash();
- }
- };
-}
+#include <type_traits>
class EvaluationFailure : public std::exception
{
mutable std::string cachedText;
};
+class EvaluationValue_;
+
+namespace std
+{
+ template <> struct hash<EvaluationValue_> {
+ size_t operator()(const EvaluationValue_ &) const;
+ };
+}
+
+class EvaluationContext;
+class EvaluationValueBase;
+using EvaluationValuePtr = std::shared_ptr<EvaluationValueBase>;
+using EvaluationValueEmpty = std::nullptr_t;
+using EvaluationValueString = std::string;
+using EvaluationValueInteger = int64_t;
+using EvaluationValueDouble = double;
+using EvaluationValueUIElement = std::shared_ptr<UIElement>;
+using EvaluationValueBoolean = bool;
+using EvaluationValuePoint = Point;
+class EvaluationValueFunction;
+using EvaluationValueVector = std::vector<EvaluationValue_>;
+using EvaluationValueSet = std::unordered_set<EvaluationValue_>;
+using EvaluationValueDict = std::unordered_map<EvaluationValue_, EvaluationValue_>;
+
+/**
+ * @brief Wrapper class containing batch script value
+ *
+ * This is a wrapper, contaiing a value from batch script. It can hold any type of supported value.
+ * Any functionality requested from object of this class will be redirected to correct implementation
+ * method in the EvaluationValueBase interface. Classes inheriting from EvaluationValueBase are classes
+ * implementing values of all supported types (see EvaluationValue***.cpp files). Those classes
+ * override virtual methods of the EvaluationValueBase interface to add required functionality.
+ *
+ * EvaluationValue_ supports implicit cast from C++ types, which can be used in batch script (for example
+ * chars shorts and ints can be converted to EvaluationValueInteger, std::string can be converted to
+ * EvaluationValueString and so on).
+ */
+class EvaluationValue_
+{
+public:
+ EvaluationValue_();
+ EvaluationValue_(const EvaluationValue_ &) = default;
+ EvaluationValue_(EvaluationValue_ &&) = default;
+ EvaluationValue_(std::nullptr_t);
+ EvaluationValue_(EvaluationValuePtr v);
+ EvaluationValue_(unsigned char v) : EvaluationValue_(static_cast<EvaluationValueInteger>(v)) { }
+ EvaluationValue_(signed char v) : EvaluationValue_(static_cast<EvaluationValueInteger>(v)) { }
+ EvaluationValue_(unsigned short v) : EvaluationValue_(static_cast<EvaluationValueInteger>(v)) { }
+ EvaluationValue_(short v) : EvaluationValue_(static_cast<EvaluationValueInteger>(v)) { }
+ EvaluationValue_(unsigned int v) : EvaluationValue_(static_cast<EvaluationValueInteger>(v)) { }
+ EvaluationValue_(int v) : EvaluationValue_(static_cast<EvaluationValueInteger>(v)) { }
+ template <typename T> EvaluationValue_(std::vector<T> tmp) : EvaluationValue_(fromVector(std::move(tmp))) { }
+ template <typename T> EvaluationValue_(std::unordered_set<T> tmp) : EvaluationValue_(fromSet(std::move(tmp))) { }
+ template <typename K, typename EvaluationValuePtr> EvaluationValue_(std::unordered_map<K, EvaluationValuePtr> tmp) : EvaluationValue_(fromMap(std::move(tmp))) { }
+
+ EvaluationValue_ &operator = (const EvaluationValue_ &) = default;
+ EvaluationValue_ &operator = (EvaluationValue_ &&) = default;
+ template <typename T> EvaluationValue_ &operator = (T &&t)
+ {
+ *this = EvaluationValue_{ std::forward<T>(t) };
+ return *this;
+ }
+
+ void convertTo(EvaluationValue_ &o) const
+ {
+ o = *this;
+ }
+ void convertTo(int &v) const;
+ void convertTo(unsigned int &v) const;
+ void convertTo(short &v) const;
+ void convertTo(unsigned short &v) const;
+ void convertTo(signed char &v) const;
+ void convertTo(unsigned char &v) const;
+ template <typename T> void convertTo(std::vector<T> &v) const {
+
+ }
+#define Q(type) \
+ EvaluationValue_(EvaluationValue ## type); \
+ EvaluationValue ## type convertTo ## type() const; \
+ void convertTo(EvaluationValue ## type &) const; \
+ const EvaluationValue ## type &as ## type(); \
+ bool is ## type() const;
+
+ Q(String)
+ Q(Integer)
+ Q(Double)
+ Q(UIElement)
+ Q(Boolean)
+ Q(Point)
+ Q(Function)
+ Q(Vector)
+ Q(Set)
+ Q(Dict)
+#undef Q
+
+ std::string typeName() const;
+ bool operator == (const EvaluationValue_ &) const;
+ bool operator != (const EvaluationValue_ &) const;
+ bool operator < (const EvaluationValue_ &) const;
+ bool operator > (const EvaluationValue_ &) const;
+ bool operator <= (const EvaluationValue_ &) const;
+ bool operator >= (const EvaluationValue_ &) const;
+
+ size_t hash() const;
+ bool contains(const EvaluationValue_ &) const;
+ explicit operator bool() const;
+
+ EvaluationValue_ operator()(const std::vector<EvaluationValue_> &values);
+ EvaluationValue_ index_get(const EvaluationValue_ &) const;
+ EvaluationValue_ index_get(const EvaluationValue_ &, const EvaluationValue_ &) const;
+ EvaluationValue_ index_set(const EvaluationValue_ &, const EvaluationValue_ &value);
+ EvaluationValue_ index_set(const EvaluationValue_ &, const EvaluationValue_ &, const EvaluationValue_ &value);
+
+ EvaluationValue_ operator - () const;
+
+ EvaluationValue_ attr_get(const std::string &name) const;
+ EvaluationValue_ attr_set(const std::string &name, const EvaluationValue_ &value);
+
+ auto getInternalValue() const
+ {
+ return value;
+ }
+
+ friend std::ostream &operator << (std::ostream &s, const EvaluationValue_ &v);
+private:
+ EvaluationValuePtr value;
+
+ template <typename T> static EvaluationValueVector fromVector(std::vector<T> tmp) {
+ EvaluationValueVector res;
+ res.reserve(tmp.size());
+ for(auto &t : tmp)
+ res.push_back(std::move(t));
+ return res;
+ }
+ template <typename T> static EvaluationValueSet fromSet(std::unordered_set<T> tmp) {
+ EvaluationValueSet res;
+ res.reserve(tmp.size());
+ for(auto &t : tmp)
+ res.insert(std::move(t));
+ return res;
+ }
+ template <typename K, typename EvaluationValuePtr> static EvaluationValueDict fromMap(std::unordered_map<K, EvaluationValuePtr> tmp) {
+ EvaluationValueDict res;
+ res.reserve(tmp.size());
+ for(auto &t : tmp)
+ res.insert({ t.first, std::move(t.second) });
+ return res;
+ }
+};
+
namespace detail
{
- // TODO: check licence
template<int ...> struct sequence {};
template<int N, int ...S> struct sequence_gen : sequence_gen < N - 1, N - 1, S... > {};
template<int ...S> struct sequence_gen<0, S...> {
apply_helper<C, ARGS...> ah { c, args };
return ah.apply_1();
}
- template <typename T> struct ConvertTo;
- template <> struct ConvertTo<int> {
- static int convert(EvaluationValue e);
- };
- template <> struct ConvertTo<double> {
- static double convert(EvaluationValue e);
- };
- template <> struct ConvertTo<std::string> {
- static std::string convert(EvaluationValue e);
- };
- template <> struct ConvertTo<bool> {
- static bool convert(EvaluationValue e);
- };
- template <> struct ConvertTo<std::shared_ptr<UIElement>> {
- static std::shared_ptr<UIElement> convert(EvaluationValue e);
- };
- template <> struct ConvertTo<EvaluationValue> {
- static EvaluationValue convert(EvaluationValue e);
- };
- template <> struct ConvertTo<Point> {
- static Point convert(EvaluationValue e);
- };
- template <typename T> struct ConvertTo<std::vector<T>> {
- static std::vector<T> convert(EvaluationValue e);
- };
- template <typename T> struct ConvertTo<std::unordered_set<T>> {
- static std::unordered_set<T> convert(EvaluationValue e);
- };
- template <typename K, typename V> struct ConvertTo<std::unordered_map<K, V>> {
- static std::unordered_map<K, V> convert(EvaluationValue e);
- };
template <size_t I, size_t S> struct Converter {
- template <typename ... ARGS> static void convert(std::tuple<ARGS...> &dst, std::vector<EvaluationValue> &sourceArgs)
+ template <typename ... ARGS> static void convert(std::tuple<ARGS...> &dst, const std::vector<EvaluationValue_> &sourceArgs)
{
- using T = typename std::tuple_element<I, std::tuple<ARGS...>>::type;
try {
- std::get<I>(dst) = ConvertTo<typename std::decay<T>::type>::convert(std::move(sourceArgs[I]));
+ sourceArgs[I].convertTo(std::get<I>(dst));
} catch (EvaluationFailure &e) {
e << ", when converting " << (I + 1) << " argument";
throw;
}
};
template <size_t S> struct Converter<S, S> {
- template <typename ... ARGS> static void convert(std::tuple<ARGS...> &, std::vector<EvaluationValue> &)
+ template <typename ... ARGS> static void convert(std::tuple<ARGS...> &, const std::vector<EvaluationValue_> &)
{
}
};
- class FunctionType
- {
- public:
- using Type = std::function<EvaluationValue(std::vector<EvaluationValue>)>;
- FunctionType() = default;
- FunctionType(Type t) : function(std::move(t)) { }
-
- explicit operator bool () const
- {
- return bool(function);
- }
-
- template <typename ... ARGS> auto operator()(ARGS &&... args) const
- {
- std::vector<EvaluationValue> tmp;
- pack(tmp, std::forward<ARGS>(args)...);
- return function(std::move(tmp));
- }
- EvaluationValue operator()(std::vector<EvaluationValue> args) const;
- private:
- Type function;
-
- template <typename T, typename ... ARGS> static void pack(std::vector<EvaluationValue> &tmp, T &&t, ARGS &&... args)
- {
- tmp.push_back(std::forward<T>(t));
- pack(tmp, std::forward<ARGS>(args)...);
- }
- static void pack(std::vector<EvaluationValue> &tmp)
- {
- }
- };
- template <typename ... ARGS> class UserFunctionType : public FunctionType
+ template <typename T, typename A = void, typename ... ARGS> struct is_one_of_types {
+ enum { value = std::is_same<T, A>::value || is_one_of_types<T, ARGS...>::value };
+ };
+ template <typename T> struct is_one_of_types<T> {
+ enum { value = 0 };
+ };
+
+ template <typename T> struct is_allowed_evaluatation_value_type { enum { value = 0 }; };
+ template <typename T> struct is_allowed_evaluatation_value_type<T&> { enum { value = is_allowed_evaluatation_value_type<T>::value }; };
+ template <typename T> struct is_allowed_evaluatation_value_type<const T&> { enum { value = is_allowed_evaluatation_value_type<T>::value }; };
+ template <typename T> struct is_allowed_evaluatation_value_type<const T> { enum { value = is_allowed_evaluatation_value_type<T>::value }; };
+ template <> struct is_allowed_evaluatation_value_type<int> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<unsigned int> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<short> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<unsigned short> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<signed char> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<unsigned char> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValue_> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueEmpty> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueString> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueInteger> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueDouble> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueUIElement> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueBoolean> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValuePoint> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueFunction> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueVector> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueSet> { enum { value = 1 }; };
+ template <> struct is_allowed_evaluatation_value_type<EvaluationValueDict> { enum { value = 1 }; };
+ template <typename T> struct is_allowed_evaluatation_value_type<std::vector<T>> {
+ enum { value = is_allowed_evaluatation_value_type<T>::value };
+ };
+ template <typename T> struct is_allowed_evaluatation_value_type<std::unordered_set<T>> {
+ enum { value = is_allowed_evaluatation_value_type<T>::value };
+ };
+ template <typename K, typename EvaluationValuePtr> struct is_allowed_evaluatation_value_type<std::unordered_map<K, EvaluationValuePtr>> {
+ enum { value = is_allowed_evaluatation_value_type<K>::value && is_allowed_evaluatation_value_type<EvaluationValuePtr>::value };
+ };
+ template <typename T = void, typename ... ARGS> struct are_args_allowed_evaluation_value {
+ enum { value = is_allowed_evaluatation_value_type<T>::value && are_args_allowed_evaluation_value<ARGS...>::value };
+ };
+ template <> struct are_args_allowed_evaluation_value<> {
+ enum { value = 1 };
+ };
+ template <typename T> struct are_args_allowed_evaluation_value_from_tuple;
+ template <typename ... ARGS> struct are_args_allowed_evaluation_value_from_tuple<std::tuple<ARGS...>> {
+ enum { value = are_args_allowed_evaluation_value<ARGS...>::value };
+ };
+ namespace get_type_from_lambda_impl
{
- public:
- UserFunctionType(std::function<EvaluationValue(ARGS...)> f) :
- FunctionType(constructConvertingArgsFunction(std::move(f))) { }
- private:
- static Type constructConvertingArgsFunction(std::function<EvaluationValue(ARGS...)> f);
- };
-
- using VectorType = std::vector<EvaluationValue>;
- using SetType = std::unordered_set<EvaluationValueKey>;
- using DictType = std::unordered_map<EvaluationValueKey, EvaluationValue>;
-
- enum class Kind : unsigned char {
- EMPTY = 0,
- STRING, INTEGER, DOUBLE, UIELEMENT, BOOLEAN, POINT, FUNCTION, VECTOR, SET, DICT
- };
-
- template <typename T> struct TypeToKind;
- template <> struct TypeToKind<std::string> {
- static constexpr auto kind = Kind::STRING;
- };
- template <> struct TypeToKind<int> {
- static constexpr auto kind = Kind::INTEGER;
- };
- template <> struct TypeToKind<double> {
- static constexpr auto kind = Kind::DOUBLE;
- };
- template <> struct TypeToKind<std::shared_ptr<UIElement>> {
- static constexpr auto kind = Kind::UIELEMENT;
- };
- template <> struct TypeToKind<bool> {
- static constexpr auto kind = Kind::BOOLEAN;
- };
- template <> struct TypeToKind<Point> {
- static constexpr auto kind = Kind::STRING;
- };
- template <> struct TypeToKind<FunctionType> {
- static constexpr auto kind = Kind::FUNCTION;
- };
- template <> struct TypeToKind<VectorType> {
- static constexpr auto kind = Kind::VECTOR;
- };
- template <> struct TypeToKind<SetType> {
- static constexpr auto kind = Kind::SET;
- };
- template <> struct TypeToKind<DictType> {
- static constexpr auto kind = Kind::DICT;
- };
- template <typename ... ARGS> struct TypeToKind<UserFunctionType<ARGS...>> {
- static constexpr auto kind = Kind::FUNCTION;
- };
- template <typename R, typename ... ARGS> struct TypeToKind<std::function<R(ARGS...)>> {
- static constexpr auto kind = Kind::FUNCTION;
- };
- template <typename T> struct TypeToKind<std::vector<T>> {
- static constexpr auto kind = Kind::VECTOR;
- };
- template <typename T> struct TypeToKind<std::unordered_set<T>> {
- static constexpr auto kind = Kind::SET;
- };
- template <typename K, typename V> struct TypeToKind<std::unordered_map<K, V>> {
- static constexpr auto kind = Kind::DICT;
- };
- // TODO: turn it into c++17 std::variant, when we upgrade to c++17
- // although current version ain't optimal, it's not big of a deal
- // as it's only used for testing and any DBUS call will be
- // order of magnitude slower
- struct Data {
- std::string string;
- int integer = 0;
- std::shared_ptr<UIElement> uiElement;
- bool boolean = false;
- double double_ = 0;
- Point point;
- FunctionType function;
- std::shared_ptr<VectorType> vector;
- std::shared_ptr<SetType> set;
- std::shared_ptr<DictType> dict;
-
- Data() = default;
- Data(int integer);
- Data(bool boolean);
- Data(std::string);
- Data(double);
- Data(std::shared_ptr<UIElement>);
- Data(Point);
- Data(FunctionType);
- Data(SetType);
- Data(DictType);
- Data(VectorType);
- template <typename T> Data(std::vector<T> t) : Data(VectorType{ t.begin(), t.end() }) { }
- template <typename T> Data(std::unordered_set<T> t) : Data(SetType{ t.begin(), t.end() }) { }
- template <typename K, typename V> Data(std::unordered_map<K, V> t) : Data(DictType{ t.begin(), t.end() }) { }
+ template<typename T> struct make_tuple_from_args { };
+ template<typename C, typename ... ARGS>
+ struct make_tuple_from_args<EvaluationValue_(C::*)(ARGS...)> {
+ using type = std::tuple<ARGS...>;
+ };
+ template<typename C, typename ... ARGS>
+ struct make_tuple_from_args<EvaluationValue_(C::*)(ARGS...) const> {
+ using type = std::tuple<ARGS...>;
+ };
+ }
+ template <typename T, typename OPER = decltype(&std::remove_reference<T>::type::operator())> struct get_args_as_tuple_from_lambda {
+ using type = typename get_type_from_lambda_impl::make_tuple_from_args<OPER>::type;
};
-
- template <typename T> T &get(detail::Data &d) = delete;
- template <> std::string &get<std::string>(detail::Data &d);
- template <> int &get<int>(detail::Data &d);
- template <> std::shared_ptr<UIElement> &get<std::shared_ptr<UIElement>>(detail::Data &d);
- template <> bool &get<bool>(detail::Data &d);
- template <> double &get<double>(detail::Data &d);
- template <> Point &get<Point>(detail::Data &d);
- template <> FunctionType &get<detail::FunctionType>(detail::Data &d);
- template <> VectorType &get<detail::VectorType>(detail::Data &d);
- template <> SetType &get<detail::SetType>(detail::Data &d);
- template <> DictType &get<detail::DictType>(detail::Data &d);
-
- template <typename T> T get(const detail::Data &d) = delete;
- template <> std::string get<std::string>(const detail::Data &d);
- template <> int get<int>(const detail::Data &d);
- template <> std::shared_ptr<UIElement> get<std::shared_ptr<UIElement>>(const detail::Data &d);
- template <> bool get<bool>(const detail::Data &d);
- template <> double get<double>(const detail::Data &d);
- template <> Point get<Point>(const detail::Data &d);
- template <> FunctionType get<detail::FunctionType>(const detail::Data &d);
- template <> VectorType get<detail::VectorType>(const detail::Data &d);
- template <> SetType get<detail::SetType>(const detail::Data &d);
- template <> DictType get<detail::DictType>(const detail::Data &d);
}
-class EvaluationValue
+class EvaluationValueFunction
{
public:
- static std::string toString(detail::Kind k);
-
- EvaluationValue() = default;
- EvaluationValue(std::nullptr_t) {}
- template <typename T, typename = typename std::enable_if<std::is_constructible<detail::Data, T>::value, void *>::type>
- EvaluationValue(T && t) : data(std::move(t)), kind_(detail::TypeToKind<typename std::decay<T>::type>::kind) { }
- EvaluationValue(const EvaluationValue &) = default;
- EvaluationValue(EvaluationValue &&) = default;
- ~EvaluationValue() = default;
+ using Type = std::function<EvaluationValue_(const std::vector<EvaluationValue_>&)>;
- EvaluationValue &operator = (const EvaluationValue &) = default;
- EvaluationValue &operator = (EvaluationValue &&) = default;
+ EvaluationValueFunction() = default;
+ template <typename T, typename ARGS_TUPLE = typename detail::get_args_as_tuple_from_lambda<T>::type,
+ typename = typename std::enable_if<detail::are_args_allowed_evaluation_value_from_tuple<ARGS_TUPLE>::value>::type>
+ EvaluationValueFunction(T && f) : function(constructConvertingArgsFunction<ARGS_TUPLE>(std::move(f))) { }
+ EvaluationValueFunction(std::function<EvaluationValue_(const std::vector<EvaluationValue_> &)> f) : function(std::move(f)) {}
- detail::Kind kind() const;
- template <typename T> auto &as()
+ explicit operator bool () const
{
- ASSERT(kind() == detail::TypeToKind<typename std::decay<T>::type>::kind);
- return detail::get<T>(data);
+ return bool(function);
}
- template <typename T> auto as() const
- {
- ASSERT(kind() == detail::TypeToKind<typename std::decay<T>::type>::kind);
- return detail::get<T>(data);
- }
-
- bool operator == (const EvaluationValue &other) const;
- bool operator < (const EvaluationValue &other) const;
- bool operator != (const EvaluationValue &other) const;
- bool operator > (const EvaluationValue &other) const;
- bool operator <= (const EvaluationValue &other) const;
- bool operator >= (const EvaluationValue &other) const;
-
- explicit operator bool () const;
- friend std::ostream &operator << (std::ostream &s, const EvaluationValue &v);
-private:
- detail::Data data;
- detail::Kind kind_ = detail::Kind::EMPTY;
-};
-
-namespace detail
-{
- template <typename T> std::vector<T> ConvertTo<std::vector<T>>::convert(EvaluationValue e)
+ EvaluationValue_ operator () (const std::vector<EvaluationValue_> &args) const
{
- std::vector<T> result;
-
- if (e.kind() == detail::Kind::VECTOR) {
- result.reserve(e.as<VectorType>().size());
- for (auto &e : e.as<VectorType>()) {
- result.push_back(ConvertTo<T>::convert(e));
- }
- } else if (e.kind() == detail::Kind::SET) {
- result.reserve(e.as<SetType>().size());
- for (auto &e : e.as<SetType>()) {
- result.push_back(ConvertTo<T>::convert(e));
- }
- } else if (e.kind() == detail::Kind::DICT) {
- result.reserve(e.as<DictType>().size());
- for (auto &e : e.as<DictType>()) {
- result.push_back(ConvertTo<T>::convert(e.first));
- }
- } else throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::VECTOR);
- return std::move(result);
+ return function(args);
}
- template <typename T> std::unordered_set<T> ConvertTo<std::unordered_set<T>>::convert(EvaluationValue e)
- {
- std::unordered_set<T> result;
+protected:
+ Type function;
- if (e.kind() == detail::Kind::VECTOR) {
- result.reserve(e.as<VectorType>().size());
- for (auto &e : e.as<VectorType>()) {
- result.insert(ConvertTo<T>::convert(e));
- }
- } else if (e.kind() == detail::Kind::SET) {
- result.reserve(e.as<SetType>().size());
- for (auto &e : e.as<SetType>()) {
- result.insert(ConvertTo<T>::convert(e));
- }
- } else if (e.kind() == detail::Kind::DICT) {
- result.reserve(e.as<DictType>().size());
- for (auto &e : e.as<DictType>()) {
- result.insert(ConvertTo<T>::convert(e.first));
- }
- } else throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::VECTOR);
- return std::move(result);
- }
- template <typename K, typename V> std::unordered_map<K, V> ConvertTo<std::unordered_map<K, V>>::convert(EvaluationValue e)
+ static void validateArgumentCount(size_t expected, size_t got)
{
- std::unordered_map<K, V> result;
-
- if (e.kind() == detail::Kind::DICT) {
- result.reserve(e.as<DictType>().size());
- for (auto &e : e.as<DictType>()) {
- auto k = ConvertTo<K>::convert(e.first);
- auto v = ConvertTo<V>::convert(e.second);
- result.insert({ k, v });
- }
- } else throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
- " to " << EvaluationValue::toString(detail::Kind::VECTOR);
- return std::move(result);
+ if (got < expected)
+ throw EvaluationFailure{} << "not enough arguments, expected " << expected << ", got " << got;
+ if (got > expected)
+ throw EvaluationFailure{} << "too many arguments, expected " << expected << ", got " << got;
}
- template <typename ... ARGS>
- auto UserFunctionType<ARGS...>::constructConvertingArgsFunction(std::function<EvaluationValue(ARGS...)> f) -> Type
+private:
+ template <typename ARGS_TUPLE, typename T>
+ static EvaluationValueFunction::Type constructConvertingArgsFunction(T &&f)
{
- return [f = std::move(f)](std::vector<EvaluationValue> sourceArgs) -> EvaluationValue {
- constexpr auto expectedArgs = sizeof...(ARGS);
- if (sourceArgs.size() < expectedArgs)
- throw EvaluationFailure{} << "not enough arguments, expected " << expectedArgs << ", got " << sourceArgs.size();
- if (sourceArgs.size() > expectedArgs)
- throw EvaluationFailure{} << "too many arguments, expected " << expectedArgs << ", got " << sourceArgs.size();
- std::tuple<ARGS...> args;
- detail::Converter<0, sizeof...(ARGS)>::convert(args, sourceArgs);
+ return [f = std::move(f)](const std::vector<EvaluationValue_> &sourceArgs) -> EvaluationValue_ {
+ constexpr auto expectedArgs = std::tuple_size<ARGS_TUPLE>::value;
+ validateArgumentCount(expectedArgs, sourceArgs.size());
+ //std::tuple<ARGS...>
+ ARGS_TUPLE args;
+ detail::Converter<0, expectedArgs>::convert(args, sourceArgs);
return detail::apply(f, args);
};
}
-}
+};
#endif
--- /dev/null
+#include "EvaluationValueBase.hpp"
+#include "EvaluationValue.hpp"
+#include "../UniversalSwitchLog.hpp"
+
+namespace std
+{
+ size_t hash<EvaluationValue_>::operator()(const EvaluationValue_ &v) const
+ {
+ return v.hash();
+ }
+}
+
+#define Q(type) \
+ void EvaluationValueBase::as(EvaluationValue ## type &v, const EvaluationValuePtr &q) { v = q->as ## type(); } \
+ void EvaluationValueBase::convertTo(EvaluationValue ## type &v, const EvaluationValuePtr &q) { v = q->convertTo ## type()->as ## type(); } \
+ const EvaluationValue ## type &EvaluationValueBase::as ## type() { throw EvaluationFailure{} << \
+ "unsupported operation, type " << typeName() << " can't be represented as " #type; } \
+ EvaluationValuePtr EvaluationValueBase::convertTo ## type() { throw EvaluationFailure{} << \
+ "unsupported operation, can't convert " << typeName() << " to " #type; }
+
+Q(String)
+Q(Integer)
+Q(Double)
+Q(UIElement)
+Q(Boolean)
+Q(Point)
+Q(Function)
+Q(Vector)
+Q(Set)
+Q(Dict)
+#undef Q
+
+std::ostream &operator << (std::ostream &s, const EvaluationValuePtr &v)
+{
+ v->writeToStream(s);
+ return s;
+}
+
+size_t EvaluationValueBase::oper_hash()
+{
+ throw EvaluationFailure{} << "unsupported operation, can't calculate hash for " << typeName();
+}
+
+bool EvaluationValueBase::oper_cmp(Cmp cmp, const EvaluationValuePtr &o)
+{
+ auto v = oper_equal(o);
+ return cmp == Cmp::Equal ? v : !v;
+}
+
+bool EvaluationValueBase::oper_order(Order order, const EvaluationValuePtr &o)
+{
+ auto cmp = [](const EvaluationValuePtr & l, const EvaluationValuePtr & r) -> int {
+ try
+ {
+ return l->oper_order(r);
+ } catch (EvaluationFailure &ev)
+ {
+ try {
+ return -r->oper_order(l);
+ } catch (EvaluationFailure) { }
+ throw;
+ }
+ };
+ auto v = cmp(shared_from_this(), o);
+ switch (order) {
+ case Order::Less:
+ return v < 0;
+ case Order::LessThan:
+ return v <= 0;
+ case Order::More:
+ return v > 0;
+ case Order::MoreThan:
+ return v >= 0;
+ }
+ ASSERT(0);
+ return false;
+}
+
+int EvaluationValueBase::oper_order(const EvaluationValuePtr &o)
+{
+ throw EvaluationFailure{} << "unsupported operation, can't order values " << o->typeName() << " and " << typeName();
+}
+
+size_t EvaluationValueBase::getSingleIndex(const EvaluationValuePtr &index, size_t size) const
+{
+ auto i = index->convertToInteger()->asInteger();
+ auto origIndex = i;
+ if (i < 0) i += static_cast<EvaluationValueInteger>(size);
+ if (i < 0 || i >= static_cast<EvaluationValueInteger>(size))
+ throw EvaluationFailure{} << origIndex << " is out of range for " << typeName() << " of size " << size;
+ return static_cast<size_t>(i);
+}
+
+std::pair<size_t, size_t> EvaluationValueBase::getDoubleIndexes(const EvaluationValuePtr &from, const EvaluationValuePtr &to, size_t size_) const
+{
+ auto index1 = from->convertToInteger()->asInteger();
+ auto index2 = to->convertToInteger()->asInteger();
+ auto size = static_cast<EvaluationValueInteger>(size_);
+
+ if (index1 < 0) index1 += size;
+ if (index2 < 0) index2 += size;
+
+ if (index1 < 0) index1 = 0;
+ else if (index1 > size) index1 = size;
+
+ if (index2 < index1) index2 = index1;
+ else if (index2 > size) index2 = size;
+
+ return { static_cast<size_t>(index1), static_cast<size_t>(index2) };
+}
+
+bool EvaluationValueBase::oper_contains(const EvaluationValuePtr &value)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a container";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_call(const std::vector<EvaluationValue_> &args)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a callable";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_attr_get(const std::string &name)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " doesn't have a " << name << " attribute";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_attr_set(const std::string &name, const EvaluationValuePtr &)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " doesn't have a " << name << " attribute";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_negate()
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a number";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_index_get(const EvaluationValuePtr &index)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a container";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_index_get(const EvaluationValuePtr &from, const EvaluationValuePtr &to)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a container";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_index_set(const EvaluationValuePtr &index, const EvaluationValuePtr &value)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a wrte-able container";
+}
+
+EvaluationValuePtr EvaluationValueBase::oper_index_set(const EvaluationValuePtr &from, const EvaluationValuePtr &to, const EvaluationValuePtr &value)
+{
+ throw EvaluationFailure{} << "unsupported operation, " << typeName() << " is not a wrte-able container";
+}
+
+class EvaluationValueEmptyImpl : public EvaluationValueBase
+{
+public:
+ std::string typeName() const override
+ {
+ return "Empty";
+ }
+ bool isEmpty() const override
+ {
+ return true;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << "null";
+ }
+ size_t oper_hash() override
+ {
+ return 1;
+ }
+
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isEmpty();
+ }
+ bool oper_is_true() override
+ {
+ return false;
+ }
+};
+
+EvaluationValuePtr EvaluationValueBase::create()
+{
+ return std::make_shared<EvaluationValueEmptyImpl>();
+}
--- /dev/null
+/*
+ * Copyright 2017 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_EVALUATION_VALUE_BASE
+#define TEST_EVALUATION_VALUE_BASE
+
+#include "EvaluationValue.hpp"
+
+// sanity check and for safety - comparing those pointers is an error anyway
+bool operator == (EvaluationValuePtr, EvaluationValuePtr) = delete;
+bool operator != (EvaluationValuePtr, EvaluationValuePtr) = delete;
+bool operator <= (EvaluationValuePtr, EvaluationValuePtr) = delete;
+bool operator >= (EvaluationValuePtr, EvaluationValuePtr) = delete;
+bool operator < (EvaluationValuePtr, EvaluationValuePtr) = delete;
+bool operator > (EvaluationValuePtr, EvaluationValuePtr) = delete;
+
+class EvaluationValueBase : public std::enable_shared_from_this<EvaluationValueBase>
+{
+protected:
+ EvaluationValueBase() = default;
+ virtual ~EvaluationValueBase() = default;
+
+ EvaluationValueBase(const EvaluationValueBase &) = delete;
+ EvaluationValueBase(EvaluationValueBase &&) = delete;
+
+ EvaluationValueBase &operator = (const EvaluationValueBase &) = delete;
+ EvaluationValueBase &operator = (EvaluationValueBase &&) = delete;
+
+ template <typename T> static int orderValues(T a, T b)
+ {
+ if (a == b) return 0;
+ return a < b ? -1 : 1;
+ }
+public:
+ enum class Cmp {
+ Equal, NotEqual
+ };
+ enum class Order {
+ Less, LessThan, More, MoreThan
+ };
+
+ bool oper_cmp(Cmp, const EvaluationValuePtr &);
+ bool oper_order(Order, const EvaluationValuePtr &);
+ virtual bool isEmpty() const
+ {
+ return false;
+ }
+
+ virtual std::string typeName() const = 0;
+ virtual bool oper_equal(const EvaluationValuePtr &) = 0;
+ virtual int oper_order(const EvaluationValuePtr &);
+ virtual size_t oper_hash();
+ virtual bool oper_contains(const EvaluationValuePtr &value);
+ virtual bool oper_is_true() = 0;
+ virtual EvaluationValuePtr oper_call(const std::vector<EvaluationValue_> &args);
+ virtual EvaluationValuePtr oper_attr_get(const std::string &name);
+ virtual EvaluationValuePtr oper_attr_set(const std::string &name, const EvaluationValuePtr &);
+ virtual EvaluationValuePtr oper_negate();
+ virtual EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index);
+ virtual EvaluationValuePtr oper_index_get(const EvaluationValuePtr &from, const EvaluationValuePtr &to);
+ virtual EvaluationValuePtr oper_index_set(const EvaluationValuePtr &index, const EvaluationValuePtr &value);
+ virtual EvaluationValuePtr oper_index_set(const EvaluationValuePtr &from, const EvaluationValuePtr &to, const EvaluationValuePtr &value);
+
+ virtual void writeToStream(std::ostream &) const = 0;
+
+ static EvaluationValuePtr create();
+#define Q(type) \
+ static void as(EvaluationValue ## type &v, const EvaluationValuePtr &q); \
+ static void convertTo(EvaluationValue ## type &v, const EvaluationValuePtr &q); \
+ static EvaluationValuePtr create(EvaluationValue ## type); \
+ virtual EvaluationValuePtr convertTo ## type(); \
+ virtual const EvaluationValue ## type &as ## type(); \
+ virtual bool is ## type() const { return false; }
+
+ Q(String)
+ Q(Integer)
+ Q(Double)
+ Q(UIElement)
+ Q(Boolean)
+ Q(Point)
+ Q(Function)
+ Q(Vector)
+ Q(Set)
+ Q(Dict)
+#undef Q
+
+ size_t getSingleIndex(const EvaluationValuePtr &index, size_t size) const;
+ std::pair<size_t, size_t> getDoubleIndexes(const EvaluationValuePtr &from, const EvaluationValuePtr &to, size_t size) const;
+
+ static EvaluationContext ¤tContext();
+public:
+ class ContextManager
+ {
+ EvaluationContext *prev = nullptr;
+ public:
+ ContextManager(EvaluationContext &);
+ ~ContextManager();
+
+ ContextManager(const ContextManager &) = delete;
+ ContextManager(ContextManager &&) = delete;
+
+ ContextManager &operator = (const ContextManager &) = delete;
+ ContextManager &operator = (ContextManager &&) = delete;
+ };
+};
+std::ostream &operator << (std::ostream &s, const EvaluationValuePtr &v);
+
+#endif
--- /dev/null
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueBooleanImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueBooleanImpl(EvaluationValueBoolean v) : value(v) { }
+
+ std::string typeName() const override
+ {
+ return "Boolean";
+ }
+ bool isBoolean() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return shared_from_this();
+ }
+ const EvaluationValueBoolean &asBoolean() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << (value ? "true" : "false");
+ }
+ size_t oper_hash() override
+ {
+ return std::hash<EvaluationValueBoolean>()(value);
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isBoolean() && value == other->asBoolean();
+ }
+ bool oper_is_true() override
+ {
+ return value;
+ }
+private:
+ EvaluationValueBoolean value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueBoolean v)
+{
+ return std::make_shared<EvaluationValueBooleanImpl>(v);
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueDictImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueDictImpl(EvaluationValueDict v) : value(std::move(v)) { }
+
+ std::string typeName() const override
+ {
+ return "Dict";
+ }
+ bool isDict() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(!value.empty());
+ }
+ EvaluationValuePtr convertToDict() override
+ {
+ return shared_from_this();
+ }
+ const EvaluationValueDict &asDict() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ if (value.empty()) {
+ os << "{:}";
+ return;
+ }
+ os << "{ ";
+ bool first = true;
+ for (auto &v : value) {
+ if (first) first = false;
+ else os << ", ";
+ os << v.first << ": " << v.second;
+ }
+ os << " }";
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isDict() && value == other->asDict();
+ }
+ bool oper_is_true() override
+ {
+ return !value.empty();
+ }
+ bool oper_contains(const EvaluationValuePtr &v) override
+ {
+ return value.find(v) != value.end();
+ }
+ EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index) override
+ {
+ auto it = value.find(index);
+ if (it == value.end()) throw EvaluationFailure{} << "missing key '" << index << "'";
+ return it->second.getInternalValue();
+ }
+ EvaluationValuePtr oper_index_set(const EvaluationValuePtr &index, const EvaluationValuePtr &val) override
+ {
+ auto it = value.insert({ index, val });
+ it.first->second = val;
+ return val;
+ }
+private:
+ EvaluationValueDict value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueDict v)
+{
+ return std::make_shared<EvaluationValueDictImpl>(std::move(v));
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueDoubleImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueDoubleImpl(EvaluationValueDouble v) : value(v) { }
+
+ std::string typeName() const override
+ {
+ return "Double";
+ }
+ bool isDouble() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(bool(value));
+ }
+ EvaluationValuePtr convertToDouble() override
+ {
+ return shared_from_this();
+ }
+ EvaluationValuePtr convertToString() override
+ {
+ return create(std::to_string(value));
+ }
+ EvaluationValuePtr convertToInteger() override
+ {
+ if (static_cast<EvaluationValueInteger>(value) != value)
+ throw EvaluationFailure{} << "'" << value << "' doesn't fit into integer";
+ return create(static_cast<EvaluationValueInteger>(value));
+ }
+ const EvaluationValueDouble &asDouble() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << value;
+ }
+ size_t oper_hash() override
+ {
+ return std::hash<double>()(value);
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ if (other->isDouble()) return value == other->asDouble();
+ if (other->isInteger()) return value == static_cast<double>(other->asInteger());
+ return false;
+ }
+ int oper_order(const EvaluationValuePtr &other) override
+ {
+ if (other->isDouble()) return orderValues(value, other->asDouble());
+ if (other->isInteger()) return orderValues(value, static_cast<double>(other->asInteger()));
+ return EvaluationValueBase::oper_order(other);
+ }
+ bool oper_is_true() override
+ {
+ return value != 0;
+ }
+ EvaluationValuePtr oper_negate() override
+ {
+ return create(-value);
+ }
+private:
+ EvaluationValueDouble value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueDouble v)
+{
+ return std::make_shared<EvaluationValueDoubleImpl>(v);
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+#include "EvaluationContext.hpp"
+
+class EvaluationValueFunctionImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueFunctionImpl(EvaluationValueFunction v) : value(std::move(v))
+ {
+ ASSERT(value);
+ }
+
+ std::string typeName() const override
+ {
+ return "Function";
+ }
+ bool isFunction() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ assert(value);
+ return create(bool(value));
+ }
+ EvaluationValuePtr convertToFunction() override
+ {
+ return shared_from_this();
+ }
+ const EvaluationValueFunction &asFunction() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << "<functor>";
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ throw EvaluationFailure{} << "unsupported operation, can't compare values " << typeName() << " and " << other->typeName();
+ }
+ bool oper_is_true() override
+ {
+ return true;
+ }
+ EvaluationValuePtr oper_call(const std::vector<EvaluationValue_> &args) override
+ {
+ return value(args).getInternalValue();
+ }
+private:
+ EvaluationValueFunction value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueFunction v)
+{
+ return std::make_shared<EvaluationValueFunctionImpl>(std::move(v));
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueIntegerImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueIntegerImpl(EvaluationValueInteger v) : value(v) { }
+
+ std::string typeName() const override
+ {
+ return "Integer";
+ }
+ bool isInteger() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(bool(value));
+ }
+ EvaluationValuePtr convertToInteger() override
+ {
+ return shared_from_this();
+ }
+ EvaluationValuePtr convertToString() override
+ {
+ return create(std::to_string(value));
+ }
+ EvaluationValuePtr convertToDouble() override
+ {
+ return create(static_cast<double>(value));
+ }
+ const EvaluationValueInteger &asInteger() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << value;
+ }
+ size_t oper_hash() override
+ {
+ return std::hash<EvaluationValueInteger>()(value);
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ if (other->isInteger()) return value == other->asInteger();
+ if (other->isDouble()) return static_cast<double>(value) == other->asDouble();
+ return false;
+ }
+ int oper_order(const EvaluationValuePtr &other) override
+ {
+ if (other->isInteger()) return orderValues(value, other->asInteger());
+ if (other->isDouble()) return orderValues(static_cast<double>(value), other->asDouble());
+ return EvaluationValueBase::oper_order(other);
+ }
+ bool oper_is_true() override
+ {
+ return value != 0;
+ }
+ EvaluationValuePtr oper_negate() override
+ {
+ return create(-value);
+ }
+private:
+ EvaluationValueInteger value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueInteger v)
+{
+ return std::make_shared<EvaluationValueIntegerImpl>(v);
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+#include "EvaluationContext.hpp"
+#include "../Geometry.hpp"
+
+class EvaluationValuePointImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValuePointImpl(EvaluationValuePoint v) : value(v) { }
+
+ std::string typeName() const override
+ {
+ return "Point";
+ }
+ bool isPoint() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(true);
+ }
+ EvaluationValuePtr convertToPoint() override
+ {
+ return shared_from_this();
+ }
+ EvaluationValuePtr convertToUIElement() override
+ {
+ return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().convertToUIElement(value));
+ }
+ const EvaluationValuePoint &asPoint() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << "<" << value.x << ", " << value.y << ">";
+ }
+ size_t oper_hash() override
+ {
+ return (std::hash<size_t>()(value.x) << 16) ^ std::hash<size_t>()(value.y);
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isPoint() && value == other->asPoint();
+ }
+ bool oper_is_true() override
+ {
+ return true;
+ }
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "x") return create(static_cast<EvaluationValueInteger>(value.x));
+ if (name == "y") return create(static_cast<EvaluationValueInteger>(value.y));
+ return EvaluationValueBase::oper_attr_get(name);
+ }
+private:
+ EvaluationValuePoint value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValuePoint v)
+{
+ return std::make_shared<EvaluationValuePointImpl>(v);
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueSetImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueSetImpl(EvaluationValueSet v) : value(std::move(v)) { }
+
+ std::string typeName() const override
+ {
+ return "Set";
+ }
+ bool isSet() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(!value.empty());
+ }
+ EvaluationValuePtr convertToSet() override
+ {
+ return shared_from_this();
+ }
+ EvaluationValuePtr convertToVector() override
+ {
+ return create(EvaluationValueVector{ value.begin(), value.end() });
+ }
+ const EvaluationValueSet &asSet() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ if (value.empty()) {
+ os << "{}";
+ return;
+ }
+
+ os << "{ ";
+ bool first = true;
+ for (auto &v : value) {
+ if (first) first = false;
+ else os << ", ";
+ os << v;
+ }
+ os << " }";
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isSet() && value == other->asSet();
+ }
+ bool oper_is_true() override
+ {
+ return !value.empty();
+ }
+ bool oper_contains(const EvaluationValuePtr &v) override
+ {
+ return value.find(v) != value.end();
+ }
+private:
+ EvaluationValueSet value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueSet v)
+{
+ return std::make_shared<EvaluationValueSetImpl>(std::move(v));
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+#include "EvaluationContext.hpp"
+#include "../Geometry.hpp"
+
+class EvaluationValueStringImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueStringImpl(EvaluationValueString v) : value(std::move(v)) { }
+
+ std::string typeName() const override
+ {
+ return "String";
+ }
+ bool isString() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(!value.empty());
+ }
+ EvaluationValuePtr convertToString() override
+ {
+ return shared_from_this();
+ }
+ EvaluationValuePtr convertToUIElement() override
+ {
+ return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().convertToUIElement(value));
+ }
+ const EvaluationValueString &asString() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << "'" << value << "'";
+ }
+ size_t oper_hash() override
+ {
+ return std::hash<EvaluationValueString>()(value);
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isString() && value == other->asString();
+ }
+ bool oper_is_true() override
+ {
+ return !value.empty();
+ }
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "len") return create(static_cast<EvaluationValueInteger>(value.size()));
+ return EvaluationValueBase::oper_attr_get(name);
+ }
+ EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index) override
+ {
+ auto i = getSingleIndex(index, value.size());
+ return create(value.substr(i, 1));
+ }
+ EvaluationValuePtr oper_index_get(const EvaluationValuePtr &from, const EvaluationValuePtr &to) override
+ {
+ auto indexes = getDoubleIndexes(from, to, value.size());
+ return create(value.substr(indexes.first, indexes.second - indexes.first));
+ }
+private:
+ EvaluationValueString value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueString v)
+{
+ return std::make_shared<EvaluationValueStringImpl>(std::move(v));
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+#include "EvaluationContext.hpp"
+#include "../UIElement.hpp"
+#include "../Atspi.hpp"
+
+class EvaluationValueUIElementImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueUIElementImpl(EvaluationValueUIElement v) : value(std::move(v)) { }
+
+ std::string typeName() const override
+ {
+ return "UIElement";
+ }
+ bool isUIElement() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(bool(value->getObject()));
+ }
+ EvaluationValuePtr convertToUIElement() override
+ {
+ return shared_from_this();
+ }
+ const EvaluationValueUIElement &asUIElement() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ os << "<" <<
+ EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementUniqueId(value) <<
+ ">";
+ }
+ size_t oper_hash() override
+ {
+ auto id = EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementUniqueId(value);
+ return std::hash<std::string>()(id);
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ if (!other->isUIElement()) return false;
+
+ auto selfId = EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementUniqueId(value);
+ auto otherId = EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementUniqueId(other->asUIElement());
+ return selfId == otherId;
+ }
+ bool oper_is_true() override
+ {
+ return true;
+ }
+ EvaluationValuePtr oper_attr_get(const std::string &name) override
+ {
+ if (name == "name")
+ return create(EvaluationContext::getCurrentEvaluationContext().executionInterface().getUIElementName(value));
+ if (name == "middle_point")
+ return create(value->getScanningCoordinates());
+ return EvaluationValueBase::oper_attr_get(name);
+ }
+private:
+ EvaluationValueUIElement value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueUIElement v)
+{
+ ASSERT(v->getObject());
+ return std::make_shared<EvaluationValueUIElementImpl>(std::move(v));
+}
--- /dev/null
+#include "EvaluationValueBase.hpp"
+
+class EvaluationValueVectorImpl : public EvaluationValueBase
+{
+public:
+ EvaluationValueVectorImpl(EvaluationValueVector v) : value(std::move(v)) { }
+
+ std::string typeName() const override
+ {
+ return "Vector";
+ }
+ bool isVector() const override
+ {
+ return true;
+ }
+ EvaluationValuePtr convertToBoolean() override
+ {
+ return create(!value.empty());
+ }
+ EvaluationValuePtr convertToVector() override
+ {
+ return shared_from_this();
+ }
+ const EvaluationValueVector &asVector() override
+ {
+ return value;
+ }
+
+ void writeToStream(std::ostream &os) const override
+ {
+ if (value.empty()) {
+ os << "[]";
+ return;
+ }
+ os << "[ ";
+ bool first = true;
+ for (auto &v : value) {
+ if (first) first = false;
+ else os << ", ";
+ os << v;
+ }
+ os << " ]";
+ }
+ bool oper_equal(const EvaluationValuePtr &other) override
+ {
+ return other->isVector() && value == other->asVector();
+ }
+ int oper_order(const EvaluationValuePtr &other) override
+ {
+ if (!other->isVector())
+ return EvaluationValueBase::oper_order(other);
+
+ auto &o = other->asVector();
+ for (auto i = 0u; i < std::min(value.size(), o.size()); ++i) {
+ if (value[i] == o[i]) continue;
+ return value[i] < o[i] ? -1 : 1;
+ }
+ if (value.size() < o.size()) return -1;
+ if (value.size() > o.size()) return 1;
+ return 0;
+ }
+ bool oper_is_true() override
+ {
+ return !value.empty();
+ }
+ bool oper_contains(const EvaluationValuePtr &v) override
+ {
+ for (auto &a : value)
+ if (a == v)
+ return true;
+ return false;
+ }
+ EvaluationValuePtr oper_index_get(const EvaluationValuePtr &index) override
+ {
+ auto i = getSingleIndex(index, value.size());
+ return value[i].getInternalValue();
+ }
+ EvaluationValuePtr oper_index_get(const EvaluationValuePtr &from, const EvaluationValuePtr &to) override
+ {
+ auto indexes = getDoubleIndexes(from, to, value.size());
+ std::vector<EvaluationValue_> tmp;
+ tmp.reserve(indexes.second - indexes.first);
+ for (auto i = indexes.first; i < indexes.second; ++i)
+ tmp.push_back(value[i]);
+ return create(std::move(tmp));
+ }
+ EvaluationValuePtr oper_index_set(const EvaluationValuePtr &index, const EvaluationValuePtr &val) override
+ {
+ auto i = getSingleIndex(index, value.size());
+ value[i] = val;
+ return val;
+ }
+ EvaluationValuePtr oper_index_set(const EvaluationValuePtr &from, const EvaluationValuePtr &to, const EvaluationValuePtr &val) override
+ {
+ if (!val->isVector())
+ return EvaluationValueBase::oper_index_set(from, to, val);
+
+ auto indexes = getDoubleIndexes(from, to, value.size());
+ std::vector<EvaluationValue_> tmp;
+ tmp.reserve(value.size() - (indexes.second - indexes.first) + val->asVector().size());
+ for (size_t i = 0; i < indexes.first; ++i)
+ tmp.push_back(value[i]);
+ for (auto &q : val->asVector())
+ tmp.push_back(q);
+ for (size_t i = indexes.second; i < value.size(); ++i)
+ tmp.push_back(value[i]);
+ value = std::move(tmp);
+ return shared_from_this();
+ }
+private:
+ EvaluationValueVector value;
+};
+
+EvaluationValuePtr EvaluationValueBase::create(EvaluationValueVector v)
+{
+ return std::make_shared<EvaluationValueVectorImpl>(std::move(v));
+}
#include <string>
#include <iomanip>
-using detail::VectorType;
-using detail::SetType;
-using detail::FunctionType;
-using detail::DictType;
-
std::ostringstream &Evaluator::printLocationAndIndent(std::ostringstream &os, const TokenLocation &loc, unsigned int depth) const
{
std::string indent(static_cast<size_t>(depth), ' ');
debugInterface = std::move(inf);
}
-template <typename F> static auto evaluateHelper(std::string debugId, F && f)
+template <typename F> static auto evaluateHelper(std::string debugId, TokenLocation loc, F &&f)
{
struct CallOnExit {
std::function<void()> func;
~CallOnExit() { func(); }
};
EvaluationDepthCountManager countManager;
- if (!debugInterface) return f();
+ if (!debugInterface) {
+ try {
+ return f();
+ } catch(EvaluationFailure &ev) {
+ ev.setLocationIfMissing(loc);
+ throw;
+ }
+ }
std::string indent(static_cast<size_t>(evaluationDepth * 2), ' ');
try {
CallOnExit call{ [&]() { debugInterface->write(indent + "leaving " + debugId); } };
debugInterface->write(indent + "entering " + debugId);
return f();
+ } catch(EvaluationFailure &ev) {
+ ev.setLocationIfMissing(loc);
+ debugInterface->write(indent + "exception " + debugId + " (" + ev.what() + "), leaving");
+ throw;
} catch (std::exception &ex) {
debugInterface->write(indent + "exception " + debugId + " (" + ex.what() + "), leaving");
throw;
}
}
-EvaluationValue ExpressionEvaluator::evaluate() const
+EvaluationValue_ ExpressionEvaluator::evaluate() const
{
- return evaluateHelper(std::to_string(getDebugId()), [&]() { return evaluateImpl(); } );
+ return evaluateHelper(std::to_string(getDebugId()), location(), [&]() { return evaluateImpl(); });
}
void StatementEvaluator::evaluate() const
{
- return evaluateHelper(std::to_string(getDebugId()), [&]() { return evaluateImpl(); } );
+ return evaluateHelper(std::to_string(getDebugId()), location(), [&]() { return evaluateImpl(); });
}
IdentifierEvaluator::IdentifierEvaluator(TokenLocation tokenLocation, std::string identifier) :
ExpressionEvaluator(std::move(tokenLocation)), identifier(std::move(identifier)) { }
-EvaluationValue IdentifierEvaluator::evaluateImpl() const
+EvaluationValue_ IdentifierEvaluator::evaluateImpl() const
{
return EvaluationContext::getCurrentEvaluationContext().getVariable(location(), identifier);
}
AttributeEvaluator::AttributeEvaluator(TokenLocation tokenLocation, ExprPtr self, std::string identifier) :
ExpressionEvaluator(std::move(tokenLocation)), self(std::move(self)), identifier(std::move(identifier)) { }
-EvaluationValue AttributeEvaluator::evaluateImpl() const
+EvaluationValue_ AttributeEvaluator::evaluateImpl() const
{
- return EvaluationContext::getCurrentEvaluationContext().getAttribute(location(), self->evaluate(), identifier);
+ return self->evaluate().attr_get(identifier);
}
void AttributeEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
AttributeSetterEvaluator::AttributeSetterEvaluator(TokenLocation tokenLocation, ExprPtr self, std::string identifier, ExprPtr value) :
ExpressionEvaluator(std::move(tokenLocation)), self(std::move(self)), value(std::move(value)), identifier(std::move(identifier)) { }
-EvaluationValue AttributeSetterEvaluator::evaluateImpl() const
+EvaluationValue_ AttributeSetterEvaluator::evaluateImpl() const
{
- return EvaluationContext::getCurrentEvaluationContext().setAttribute(location(), self->evaluate(), identifier, value->evaluate());
+ auto val = value->evaluate();
+ return self->evaluate().attr_set(identifier, std::move(val));
}
void AttributeSetterEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
SetterEvaluator::SetterEvaluator(TokenLocation tokenLocation, std::string identifier, ExprPtr value) :
ExpressionEvaluator(std::move(tokenLocation)), value(std::move(value)), identifier(std::move(identifier)) { }
-EvaluationValue SetterEvaluator::evaluateImpl() const
+EvaluationValue_ SetterEvaluator::evaluateImpl() const
{
auto v = value->evaluate();
EvaluationContext::getCurrentEvaluationContext().setVariable(identifier, v);
PointEvaluator::PointEvaluator(TokenLocation tokenLocation, ExprPtr x, ExprPtr y) :
ExpressionEvaluator(std::move(tokenLocation)), x(std::move(x)), y(std::move(y)) { }
-EvaluationValue PointEvaluator::evaluateImpl() const
+EvaluationValue_ PointEvaluator::evaluateImpl() const
{
- auto xInt = detail::ConvertTo<int>::convert(x->evaluate());
- auto yInt = detail::ConvertTo<int>::convert(y->evaluate());
- return Point{ xInt, yInt };
+ auto xInt = x->evaluate().convertToInteger();
+ auto yInt = y->evaluate().convertToInteger();
+ return EvaluationValuePoint{ static_cast<int>(xInt), static_cast<int>(yInt) };
}
void PointEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
}
-IntegerEvaluator::IntegerEvaluator(TokenLocation tokenLocation, int value) :
+IntegerEvaluator::IntegerEvaluator(TokenLocation tokenLocation, int64_t value) :
ExpressionEvaluator(std::move(tokenLocation)), value(value) { }
-EvaluationValue IntegerEvaluator::evaluateImpl() const
+EvaluationValue_ IntegerEvaluator::evaluateImpl() const
{
return value;
}
DoubleEvaluator::DoubleEvaluator(TokenLocation tokenLocation, double value) :
ExpressionEvaluator(std::move(tokenLocation)), value(value) { }
-EvaluationValue DoubleEvaluator::evaluateImpl() const
+EvaluationValue_ DoubleEvaluator::evaluateImpl() const
{
return value;
}
StringEvaluator::StringEvaluator(TokenLocation tokenLocation, std::string value) :
ExpressionEvaluator(std::move(tokenLocation)), value(std::move(value)) { }
-EvaluationValue StringEvaluator::evaluateImpl() const
+EvaluationValue_ StringEvaluator::evaluateImpl() const
{
- return EvaluationValue{ value };
+ return value;
}
void StringEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
ArraySetDictEvaluator::ArraySetDictEvaluator(TokenLocation tokenLocation, ExprPtrs values, Kind kind) :
ExpressionEvaluator(std::move(tokenLocation)), values(std::move(values)), kind(kind) { }
-EvaluationValue ArraySetDictEvaluator::evaluateImpl() const
+EvaluationValue_ ArraySetDictEvaluator::evaluateImpl() const
{
- std::vector<EvaluationValue> vals;
+ std::vector<EvaluationValue_> vals;
for (auto &v : values)
vals.push_back(v->evaluate());
if (kind == Kind::VECTOR)
- return { std::move(vals) };
+ return std::move(vals);
if (kind == Kind::SET) {
- SetType tmp;
+ EvaluationValueSet tmp;
for (auto &v : vals) {
tmp.insert(std::move(v));
}
}
ASSERT(kind == Kind::DICT);
- DictType tmp;
+ EvaluationValueDict tmp;
for (auto i = 0u; i < vals.size(); i += 2) {
tmp.insert({ std::move(vals[i]), std::move(vals[i + 1]) });
}
OperatorEvaluator::OperatorEvaluator(TokenLocation tokenLocation, ExprPtrs args, Kind kind) :
ExpressionEvaluator(std::move(tokenLocation)), args(std::move(args)), kind(kind) { }
-EvaluationValue OperatorEvaluator::evaluateImpl() const
+EvaluationValue_ OperatorEvaluator::evaluateImpl() const
{
- std::vector<EvaluationValue> vals;
+ std::vector<EvaluationValue_> vals;
for (auto &a : args)
vals.push_back(a->evaluate());
switch (kind) {
case Kind::IN:
- return EvaluationContext::getCurrentEvaluationContext().evaluateIn(location(), vals[1], vals[0]);
+ return vals[1].contains(vals[0]);
case Kind::NOT:
- return !bool(vals[0]);
+ return !vals[0];
case Kind::MINUS:
- return EvaluationContext::getCurrentEvaluationContext().evaluateMinus(location(), vals[0]);
+ return -vals[0];
case Kind::GET:
- return EvaluationContext::getCurrentEvaluationContext().evaluateAccessGet(location(), vals);
+ if (vals.size() == 2) return vals[0].index_get(vals[1]);
+ ASSERT(vals.size() == 3);
+ return vals[0].index_get(vals[1], vals[2]);
case Kind::SET:
- return EvaluationContext::getCurrentEvaluationContext().evaluateAccessSet(location(), std::move(vals));
+ if (vals.size() == 3) return vals[0].index_set(vals[1], vals[1]);
+ ASSERT(vals.size() == 4);
+ return vals[0].index_set(vals[1], vals[2], vals[3]);
}
ASSERT(0);
throw EvaluationFailure{} << "unknown operator";
CompOperatorEvaluator::CompOperatorEvaluator(TokenLocation tokenLocation, ExprPtrs args, std::vector<Kind> kinds, std::vector<TokenLocation> locations) :
ExpressionEvaluator(std::move(tokenLocation)), args(std::move(args)), kinds(kinds), locations(std::move(locations)) { }
-EvaluationValue CompOperatorEvaluator::evaluateImpl() const
+EvaluationValue_ CompOperatorEvaluator::evaluateImpl() const
{
- auto cmp = [](const EvaluationValue & l, const EvaluationValue & r, Kind kind) {
+ auto cmp = [](const EvaluationValue_ & l, const EvaluationValue_ & r, const TokenLocation & loc, Kind kind) {
switch (kind) {
case Kind::EQ:
return l == r;
auto l = args[0]->evaluate();
for (auto i = 0u; i < kinds.size(); ++i) {
auto r = args[i + 1]->evaluate();
- if (!cmp(l, r, kinds[i])) return false;
+ if (!cmp(l, r, locations[i], kinds[i]))
+ return false;
l = std::move(r);
}
return true;
BooleanEvaluator::BooleanEvaluator(TokenLocation tokenLocation, bool value) :
ExpressionEvaluator(std::move(tokenLocation)), value(std::move(value)) { }
-EvaluationValue BooleanEvaluator::evaluateImpl() const
+EvaluationValue_ BooleanEvaluator::evaluateImpl() const
{
return value;
}
CallEvaluator::CallEvaluator(TokenLocation tokenLocation, ExprPtr function, ExprPtrs args) :
ExpressionEvaluator(tokenLocation), function(std::move(function)), args(std::move(args)) { }
-EvaluationValue CallEvaluator::evaluateImpl() const
+EvaluationValue_ CallEvaluator::evaluateImpl() const
{
- std::vector<EvaluationValue> values;
+ std::vector<EvaluationValue_> values;
values.reserve(args.size());
for (auto &arg : args) {
values.push_back(arg->evaluate());
}
- return EvaluationContext::getCurrentEvaluationContext().callFunction(location(), function->evaluate(), std::move(values));
+ return function->evaluate()(values);
}
void CallEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
{
- printLocationAndIndent(os, location(), depth) << "call\n";
- printLocationAndIndent(os, location(), depth) << "function set is\n";
+ printLocationAndIndent(os, location(), depth) << "function call\n";
function->printSelfInfo(os, depth + 1);
for (auto i = 0u; i < args.size(); ++i) {
printLocationAndIndent(os, location(), depth) << "arg " << i << " is\n";
#include <unordered_map>
#include <sstream>
-class EvaluationContext;
-class EvaluationValue;
-class TokenLocation;
-class Evaluator;
+class EvaluationValue_;
/**
* @brief Class for printing debug information, when evaluation batch
* Calling this function will evaluate given expression (by calling evaluateImpl).
* It will also deal with debug printing (if any).
*/
- EvaluationValue evaluate() const;
+ EvaluationValue_ evaluate() const;
protected:
/**
* @brief Virtual evaluation function.
* Calling this function will evaluate given expression, including it's all children,
* and return produced value. Might raise an EvaluationFailure exception.
*/
- virtual EvaluationValue evaluateImpl() const = 0;
+ virtual EvaluationValue_ evaluateImpl() const = 0;
};
/**
class IdentifierEvaluator : public ExpressionEvaluator
{
std::string identifier;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
IdentifierEvaluator(TokenLocation location_, std::string identifier);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
{
ExprPtr self;
std::string identifier;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
AttributeEvaluator(TokenLocation location_, ExprPtr self, std::string identifier);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
{
ExprPtr self, value;
std::string identifier;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
AttributeSetterEvaluator(TokenLocation location_, ExprPtr self, std::string identifier, ExprPtr value);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
{
ExprPtr value;
std::string identifier;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
SetterEvaluator(TokenLocation location_, std::string identifier, ExprPtr value);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
class PointEvaluator : public ExpressionEvaluator
{
ExprPtr x, y;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
PointEvaluator(TokenLocation location_, ExprPtr x, ExprPtr y);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
*/
class IntegerEvaluator : public ExpressionEvaluator
{
- int value;
+ int64_t value;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
- IntegerEvaluator(TokenLocation location_, int value);
+ IntegerEvaluator(TokenLocation location_, int64_t value);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
class DoubleEvaluator : public ExpressionEvaluator
{
double value;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
DoubleEvaluator(TokenLocation location_, double value);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
class BooleanEvaluator : public ExpressionEvaluator
{
bool value;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
BooleanEvaluator(TokenLocation location_, bool value);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
class StringEvaluator : public ExpressionEvaluator
{
std::string value;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
StringEvaluator(TokenLocation location_, std::string value);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
*/
class ArraySetDictEvaluator : public ExpressionEvaluator
{
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
enum class Kind {
SET, VECTOR, DICT
};
ArraySetDictEvaluator(TokenLocation location_, ExprPtrs values, Kind kind);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
private:
ExprPtrs values;
{
ExprPtr function;
ExprPtrs args;
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
CallEvaluator(TokenLocation location_, ExprPtr function, ExprPtrs args);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
*/
class OperatorEvaluator : public ExpressionEvaluator
{
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
enum class Kind {
IN, GET, SET, MINUS, NOT
};
OperatorEvaluator(TokenLocation location_, ExprPtrs args, Kind kind);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
private:
ExprPtrs args;
*/
class CompOperatorEvaluator : public ExpressionEvaluator
{
+protected:
+ EvaluationValue_ evaluateImpl() const override;
public:
enum class Kind {
EQ, NE, LE, LT, GE, GT
};
CompOperatorEvaluator(TokenLocation location_, ExprPtrs args, std::vector<Kind> kinds, std::vector<TokenLocation> locations);
- EvaluationValue evaluateImpl() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
private:
ExprPtrs args;
#include "batch/Evaluator.hpp"
#include <sstream>
-using VarsType = std::unordered_map<std::string, EvaluationValue>;
-using ActsType = std::unordered_map<std::string, detail::FunctionType>;
+using VarsType = std::unordered_map<std::string, EvaluationValue_>;
+using ActsType = std::unordered_map<std::string, EvaluationValueFunction>;
struct TestExecutor : ExecutorInterface {
TestExecutor(VarsType variables = {}, ActsType activities = {},
variables(std::move(variables)), activities(std::move(activities)),
pointToUI(std::move(pointToUI)), stringToUI(std::move(stringToUI)) { }
- EvaluationValue getVariableByName(const std::string &name) override
+ EvaluationValue_ getVariableByName(const std::string &name) override
{
auto it = variables.find(name);
if (it == variables.end()) throw EvaluationFailure{} << "no variable " << name;
ASSERT_TRUE(result);
std::string result2;
- auto vars = VarsType {
- {
- "foo", detail::UserFunctionType<int, std::string, std::string, bool>{
- [&](int v1, std::string v2, std::string v3, bool v4) -> EvaluationValue {
- return std::to_string(v1) + "," + v2 + "," + v3 + "," + (v4 ? "true" : "false");
- }
- }
- },
- {
- "bar", detail::UserFunctionType<std::string>{
- [&](std::string value) -> EvaluationValue {
- result2 = value;
- return nullptr;
- }
- }
- },
+ VarsType vars;
+ vars["foo"] = [&](int v1, std::string v2, std::string v3, bool v4) -> EvaluationValue_ {
+ return std::to_string(v1) + "," + v2 + "," + v3 + "," + (v4 ? "true" : "false");
+ };
+ vars["bar"] = [&](std::string value) -> EvaluationValue_ {
+ result2 = value;
+ return {};
};
TestExecutor exec(std::move(vars));
EvaluationContext ec { exec };
size_t callCount = 0;
auto vars = VarsType { };
std::ostringstream output;
- vars["assert"] = detail::UserFunctionType<bool> {
- [&](bool val) -> EvaluationValue {
- if (!val) throw EvaluationFailure{} << "assertion failed2";
- ++callCount;
- return {};
- }
+ vars["assert"] = [&](bool val) -> EvaluationValue_ {
+ if (!val) throw EvaluationFailure{} << "assertion failed";
+ ++callCount;
+ return {};
};
- vars["print"] = detail::UserFunctionType<EvaluationValue> {
- [&](EvaluationValue val) -> EvaluationValue {
- output << ">>> " << val << "\n";
- return {};
- }
+ vars["print"] = [&](EvaluationValue_ val) -> EvaluationValue_ {
+ output << ">>> " << val << "\n";
+ return {};
};
TestExecutor exec{ std::move(vars) };
EvaluationContext ec{ exec };
"assert(1 < 2 > 1)\n"
"assert(1 < 2 < 3)\n"
"assert(not (1 > 2))\n"
- , 12);
+
+ "assert(1.0 == 1)\n"
+ "assert(1.0 != 2)\n"
+ "assert(1.0 < 2)\n"
+ "assert(1.0 > -1)\n"
+ "assert(1.0 <= 2)\n"
+ "assert(1.0 <= 1)\n"
+ "assert(1.0 >= -1)\n"
+ "assert(1.0 >= 1)\n"
+
+ "assert(1 == 1.0)\n"
+ "assert(1 != 2.0)\n"
+ "assert(1 < 2.0)\n"
+ "assert(1 > -1.0)\n"
+ "assert(1 <= 2.0)\n"
+ "assert(1 <= 1.0)\n"
+ "assert(1 >= -1.0)\n"
+ "assert(1 >= 1.0)\n"
+
+ "assert(1.0 == 1.0)\n"
+ "assert(1.0 != 2.0)\n"
+ "assert(1.0 < 2.0)\n"
+ "assert(1.0 > -1.0)\n"
+ "assert(1.0 <= 2.0)\n"
+ "assert(1.0 <= 1.0)\n"
+ "assert(1.0 >= -1.0)\n"
+ "assert(1.0 >= 1.0)\n"
+
+ "assert(true == true)\n"
+ "assert(false == false)\n"
+ "assert(true != false)\n"
+ "assert(false != true)\n"
+ , 12 + 8 + 8 + 8 + 4);
}
TEST_F(ScriptTest, vector)