}
purgeBatchTimerIfNeeded();
batchModeTimers.clear();
+ DEBUG("terminating completed");
}
std::unordered_map<std::pair<detail::Kind, std::string>, EvaluationValue> setters;
std::unordered_map<std::pair<detail::Kind, std::string>, EvaluationValue> getters;
std::ostream &output;
- EvaluationContext ec;
// NOTE: constructor of TestExecutor must be called on main thread
// constructor calls NavigationInterface object, which might be
// in progress of updating itself (context change) on main thread
- TestExecutor(std::ostream &output) : output(output), ec(*this)
+ TestExecutor(std::ostream &output) : output(output)
{
insertRoleConstants();
insertStateConstants();
variables["sleep"] = detail::UserFunctionType<double> {
- [&](EvaluationContext & ec, double tm) -> EvaluationValue {
+ [&](double tm) -> EvaluationValue {
if (tm > 0)
{
auto sleepTime = std::chrono::milliseconds{ static_cast<int>(std::floor(1000.0 * tm + 0.5)) };
}
};
variables["print"] = detail::UserFunctionType<std::string> {
- [&](EvaluationContext & ec, std::string txt) -> EvaluationValue {
+ [&](std::string txt) -> EvaluationValue {
output << txt << "\n";
return {};
}
};
variables["get_at_point"] = detail::UserFunctionType<Point> {
- [&](EvaluationContext & ec, Point pt) -> EvaluationValue {
+ [&](Point pt) -> EvaluationValue {
return convert(pt);
}
};
variables["assert"] = detail::UserFunctionType<bool> {
- [&](EvaluationContext & ec, bool condition) -> EvaluationValue {
+ [&](bool condition) -> EvaluationValue {
if (!condition) throw EvaluationFailure{} << "assertion failed";
return {};
}
};
variables["wait_for_tts"] = detail::UserFunctionType<std::string> {
- [&](EvaluationContext & ec, std::string pattern) -> EvaluationValue {
+ [&](std::string pattern) -> EvaluationValue {
std::regex regex;
try
{
}
};
variables["wait_for_application"] = detail::UserFunctionType<std::string> {
- [&](EvaluationContext & ec, std::string name) -> EvaluationValue {
+ [&](std::string name) -> EvaluationValue {
auto h = contextInfo.lock();
auto untilMoment = std::chrono::high_resolution_clock::now() + 3000ms;
auto success = h.waitForCondition(untilMoment, [&]()
}
};
variables["find_by_name"] = detail::UserFunctionType<std::string, std::vector<int>, std::vector<int>> {
- [&](EvaluationContext & ec, std::string name, std::vector<int> roles, std::vector<int> states) -> EvaluationValue {
+ [&](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());
}
};
getters[ { detail::Kind::UIELEMENT, "name" }] = detail::UserFunctionType<std::shared_ptr<UIElement>> {
- [&](EvaluationContext & ec, std::shared_ptr<UIElement> uiElem)
+ [&](std::shared_ptr<UIElement> uiElem)
{
ASSERT(uiElem->getObject());
return executeOnMainThread([&]() {
}
};
getters[ { detail::Kind::POINT, "x" }] = detail::UserFunctionType<Point> {
- [&](EvaluationContext & ec, Point p) -> EvaluationValue {
+ [&](Point p) -> EvaluationValue {
return p.x;
}
};
getters[ { detail::Kind::POINT, "y" }] = detail::UserFunctionType<Point> {
- [&](EvaluationContext & ec, Point p) -> EvaluationValue {
+ [&](Point p) -> EvaluationValue {
return p.y;
}
};
getters[ { detail::Kind::UIELEMENT, "middle_point" }] = detail::UserFunctionType<std::shared_ptr<UIElement>> {
- [&](EvaluationContext & ec, std::shared_ptr<UIElement> uiElem) -> EvaluationValue {
+ [&](std::shared_ptr<UIElement> uiElem) -> EvaluationValue {
ASSERT(uiElem->getObject());
Optional<Rectangle> result;
return executeOnMainThread([&]()
};
for (auto activityName : ActivityFactory::getInstance()->getAllActivityTypes()) {
variables[activityName] = detail::FunctionType::Type{
- [ = ](EvaluationContext & ec, std::vector<EvaluationValue> args) -> EvaluationValue {
+ [ = ](std::vector<EvaluationValue> args) -> EvaluationValue {
auto activity = executeOnMainThread([&]()
{
return ActivityFactory::getInstance()->createActivity(activityName);
for (size_t i = 0; i < args.size(); ++i)
{
ASSERT(uiActivity);
- uiArgs[i] = detail::ConvertTo<std::shared_ptr<UIElement>>::convert(ec, std::move(args[i]));
+ 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";
{
auto it = setters.find({ self.kind(), name });
if (it != setters.end()) {
- return it->second.as<detail::FunctionType>()(ec, self, std::move(value));
+ return it->second.as<detail::FunctionType>()(self, std::move(value));
}
return ExecutorInterface::setAttribute(self, name, std::move(value));
}
{
auto it = getters.find({ self.kind(), name });
if (it != getters.end()) {
- return it->second.as<detail::FunctionType>()(ec, self);
+ return it->second.as<detail::FunctionType>()(self);
}
return ExecutorInterface::getAttribute(self, name);
}
auto exec = std::make_unique<TestExecutor>(*outputPtr);
return std::thread { [result = std::move(result), exec = std::move(exec), outputPtr = std::move(outputPtr), dlog = std::move(dlog) ]() mutable
{
- EvaluationContext &ec = exec->ec;
+ EvaluationContext ec(*exec);
exec->outputStream() << "waiting for context change...\n";
auto until = std::chrono::high_resolution_clock::now() + std::chrono::seconds{ 2 };
bool hasContext = false;
});
exec->outputStream() << "evaluation started\n";
try {
- result->evaluate(ec);
+ result->evaluate();
exec->outputStream() << "evaluation successed\n";
} catch (EvaluationFailure &e) {
if (e.hasLocation())
ExecutorInterface &executionInterface;
};
-EvaluationContext::EvaluationContext(ExecutorInterface &ei)
+static thread_local EvaluationContext *current = nullptr;
+
+EvaluationContext &EvaluationContext::getCurrentEvaluationContext()
+{
+ ASSERT(current);
+ return *current;
+}
+
+EvaluationContext::EvaluationContext(ExecutorInterface &ei) : parent(current)
{
+ current = this;
initializeGlobalContext(ei);
}
-EvaluationContext::EvaluationContext(EvaluationContext &parent) :
- parent(&parent)
+EvaluationContext::EvaluationContext() : parent(current)
{
+ ASSERT(parent);
+ current = this;
globalContext = this->parent->globalContext;
}
+EvaluationContext::~EvaluationContext()
+{
+ current = parent;
+}
+
void EvaluationContext::initializeGlobalContext(ExecutorInterface &ei)
{
globalContext = std::make_shared<GlobalContext>(GlobalContext{ ei });
switch (function.kind()) {
case detail::Kind::FUNCTION:
try {
- return function.as<detail::FunctionType>()(*this, std::move(values));
+ return function.as<detail::FunctionType>()(std::move(values));
} catch (EvaluationFailure &e) {
if (loc) e.setLocationIfMissing(*loc);
throw;
switch (value.kind()) {
case detail::Kind::FUNCTION:
case detail::Kind::STRING:
- return detail::ConvertTo<std::string>::convert(*this, value);
+ return detail::ConvertTo<std::string>::convert(value);
case detail::Kind::INTEGER:
- return detail::ConvertTo<int>::convert(*this, value);
+ return detail::ConvertTo<int>::convert(value);
case detail::Kind::DOUBLE:
- return detail::ConvertTo<double>::convert(*this, value);
+ return detail::ConvertTo<double>::convert(value);
case detail::Kind::UIELEMENT:
- return detail::ConvertTo<std::shared_ptr<UIElement>>::convert(*this, value);
+ return detail::ConvertTo<std::shared_ptr<UIElement>>::convert(value);
case detail::Kind::BOOLEAN:
- return detail::ConvertTo<bool>::convert(*this, value);
+ return detail::ConvertTo<bool>::convert(value);
case detail::Kind::POINT:
- return detail::ConvertTo<Point>::convert(*this, value);
+ return detail::ConvertTo<Point>::convert(value);
case detail::Kind::EMPTY:
return {};
case detail::Kind::VECTOR:
int EvaluationContext::getSingleIndex(const std::vector<EvaluationValue> &args, int size, std::string typeName)
{
ASSERT(args.size() >= 2);
- auto index = detail::ConvertTo<int>::convert(*this, args[1]);
+ 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;
std::pair<int, int> EvaluationContext::getDoubleIndexes(const std::vector<EvaluationValue> &args, int size)
{
ASSERT(args.size() >= 3);
- auto index1 = detail::ConvertTo<int>::convert(*this, args[1]);
- auto index2 = detail::ConvertTo<int>::convert(*this, args[2]);
+ 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;
try {
switch (self.kind()) {
case detail::Kind::STRING: {
- auto val = detail::ConvertTo<std::string>::convert(*this, value);
+ auto val = detail::ConvertTo<std::string>::convert(value);
return self.as<std::string>().find(val) != std::string::npos;
}
case detail::Kind::SET: {
virtual std::ostream &outputStream() = 0;
};
+/**
+ * @brief Class holding context of evaluation
+ *
+ * EvaluationContext objects represent scope. Allows access to variables in current scope,
+ * pointer to parent EvaluationContext (scope) if any and handle to ExecutionInterface.
+ * All EvaluationContext objects in the same evaluation have the same ExecutionInterface handle.
+ * Constructing EvaluationContext also updates "current" EvaluationContext object, which is getable
+ * by calling getCurrentEvaluationContext function.
+ * You should create EvaluationContext on stack and only, when new scope "begins", you
+ * should also destroy it, when the scope "ends". There should be one (root) EvaluationContext
+ * object, which represents root scope and lives as long as given batch executes.
+ */
class EvaluationContext
{
struct GlobalContext;
public:
explicit EvaluationContext(ExecutorInterface &ei);
- explicit EvaluationContext(EvaluationContext &parent);
+ explicit EvaluationContext();
+ ~EvaluationContext();
+
+ EvaluationContext(const EvaluationContext &) = delete;
+ EvaluationContext(EvaluationContext &&) = delete;
+
+ EvaluationContext &operator = (const EvaluationContext &) = delete;
+ EvaluationContext &operator = (EvaluationContext &&) = delete;
+ /**
+ * @brief Sets variable
+ *
+ * Sets or updates variable by name ident with value val.
+ * 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);
+
+ /**
+ * @brief Returns variable with name
+ *
+ * All EvaluationContext (this, it's parent, it's parent's parent and so on) will be checked in
+ * 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);
bool evaluateIn(const Optional<TokenLocation> &loc, const EvaluationValue &self, const EvaluationValue &value);
EvaluationValue evaluateMinus(const Optional<TokenLocation> &loc, const EvaluationValue &self);
+ /**
+ * @brief Returns reference to ExecutionInterface object
+ *
+ * ExecutionInterface object provides functionality, which requires "touching" external
+ * world (requesting some at-spi properties and so on). User should override ExecutionInterface
+ * methods to support, what should be supported. All EvaluationContext objects from given batch
+ * run share the same ExecutionInterface object.
+ */
ExecutorInterface &executionInterface() const;
+
+ /**
+ * @brief Returns reference to current (last created) EvaluationContext object.
+ *
+ * Will assert, if there's no EvaluationContext.
+ * EvaluationContext objects are kept in thread_local variable and are accessible (by calling
+ * getCurrentEvaluationContext function) only from the same thread, on which they were created.
+ */
+ static EvaluationContext &getCurrentEvaluationContext();
private:
void initializeGlobalContext(ExecutorInterface &ei);
int getSingleIndex(const std::vector<EvaluationValue> &args, int size, std::string typeName);
return *location_;
}
-EvaluationValue detail::FunctionType::operator()(EvaluationContext &ec, std::vector<EvaluationValue> args) const
+EvaluationValue detail::FunctionType::operator()(std::vector<EvaluationValue> args) const
{
- return function(ec, std::move(args));
+ return function(std::move(args));
}
std::string EvaluationValue::toString(detail::Kind k)
namespace detail
{
- int ConvertTo<int>::convert(EvaluationContext &ec, EvaluationValue e)
+ int ConvertTo<int>::convert(EvaluationValue e)
{
if (e.kind() == detail::Kind::INTEGER) return e.as<int>();
if (e.kind() == detail::Kind::DOUBLE) {
throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
" to " << EvaluationValue::toString(detail::Kind::INTEGER);
}
- double ConvertTo<double>::convert(EvaluationContext &ec, EvaluationValue e)
+ 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>();
throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
" to " << EvaluationValue::toString(detail::Kind::DOUBLE);
}
- std::string ConvertTo<std::string>::convert(EvaluationContext &ec, EvaluationValue e)
+ 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";
throw EvaluationFailure{} << "can't convert from " << EvaluationValue::toString(e.kind()) <<
" to " << EvaluationValue::toString(detail::Kind::STRING);
}
- bool ConvertTo<bool>::convert(EvaluationContext &ec, EvaluationValue e)
+ bool ConvertTo<bool>::convert(EvaluationValue e)
{
return bool(e);
}
- std::shared_ptr<UIElement> ConvertTo<std::shared_ptr<UIElement>>::convert(EvaluationContext &ec, EvaluationValue 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 ec.executionInterface().convert(e.as<Point>());
- if (e.kind() == detail::Kind::STRING) return ec.executionInterface().convert(e.as<std::string>());
+ 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(EvaluationContext &ec, EvaluationValue e)
+ EvaluationValue ConvertTo<EvaluationValue>::convert(EvaluationValue e)
{
return std::move(e);
}
- Point ConvertTo<Point>::convert(EvaluationContext &ec, EvaluationValue 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()) <<
template<int ...S> struct sequence_gen<0, S...> {
typedef sequence<S...> type;
};
- template <typename C, typename A, typename ... ARGS> struct apply_helper {
- const std::function<C> &c;
- A &a;
+ template <typename C, typename ... ARGS> struct apply_helper {
+ const C &c;
const std::tuple<ARGS...> &args;
template<int ... S> auto apply_2(sequence<S...>)
{
- return c(a, std::get<S>(args)...);
+ return c(std::get<S>(args)...);
}
auto apply_1()
{
return apply_2(typename sequence_gen<sizeof...(ARGS)>::type());
}
};
- template <typename C, typename A, typename ... ARGS> auto apply(const std::function<C> &c, A &&a, const std::tuple<ARGS...> &args)
+ template <typename C, typename ... ARGS> auto apply(const C &c, const std::tuple<ARGS...> &args)
{
- apply_helper<C, A, ARGS...> ah { c, std::forward<A>(a), args };
+ apply_helper<C, ARGS...> ah { c, args };
return ah.apply_1();
}
template <typename T> struct ConvertTo;
template <> struct ConvertTo<int> {
- static int convert(EvaluationContext &ec, EvaluationValue e);
+ static int convert(EvaluationValue e);
};
template <> struct ConvertTo<double> {
- static double convert(EvaluationContext &ec, EvaluationValue e);
+ static double convert(EvaluationValue e);
};
template <> struct ConvertTo<std::string> {
- static std::string convert(EvaluationContext &ec, EvaluationValue e);
+ static std::string convert(EvaluationValue e);
};
template <> struct ConvertTo<bool> {
- static bool convert(EvaluationContext &ec, EvaluationValue e);
+ static bool convert(EvaluationValue e);
};
template <> struct ConvertTo<std::shared_ptr<UIElement>> {
- static std::shared_ptr<UIElement> convert(EvaluationContext &ec, EvaluationValue e);
+ static std::shared_ptr<UIElement> convert(EvaluationValue e);
};
template <> struct ConvertTo<EvaluationValue> {
- static EvaluationValue convert(EvaluationContext &ec, EvaluationValue e);
+ static EvaluationValue convert(EvaluationValue e);
};
template <> struct ConvertTo<Point> {
- static Point convert(EvaluationContext &ec, EvaluationValue e);
+ static Point convert(EvaluationValue e);
};
template <typename T> struct ConvertTo<std::vector<T>> {
- static std::vector<T> convert(EvaluationContext &ec, EvaluationValue e);
+ static std::vector<T> convert(EvaluationValue e);
};
template <typename T> struct ConvertTo<std::unordered_set<T>> {
- static std::unordered_set<T> convert(EvaluationContext &ec, EvaluationValue e);
+ 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(EvaluationContext &ec, EvaluationValue e);
+ static std::unordered_map<K, V> convert(EvaluationValue e);
};
template <size_t I, size_t S> struct Converter {
- template <typename ... ARGS> static void convert(EvaluationContext &ce,
- std::tuple<ARGS...> &dst, std::vector<EvaluationValue> &sourceArgs)
+ template <typename ... ARGS> static void convert(std::tuple<ARGS...> &dst, 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(ce, std::move(sourceArgs[I]));
+ std::get<I>(dst) = ConvertTo<typename std::decay<T>::type>::convert(std::move(sourceArgs[I]));
} catch (EvaluationFailure &e) {
e << ", when converting " << (I + 1) << " argument";
throw;
}
- Converter < I + 1, S >::convert(ce, dst, sourceArgs);
+ Converter < I + 1, S >::convert(dst, sourceArgs);
}
};
template <size_t S> struct Converter<S, S> {
- template <typename ... ARGS> static void convert(EvaluationContext &, std::tuple<ARGS...> &, std::vector<EvaluationValue> &)
+ template <typename ... ARGS> static void convert(std::tuple<ARGS...> &, std::vector<EvaluationValue> &)
{
}
};
class FunctionType
{
public:
- using Type = std::function<EvaluationValue(EvaluationContext &ec, std::vector<EvaluationValue>)>;
+ using Type = std::function<EvaluationValue(std::vector<EvaluationValue>)>;
FunctionType() = default;
FunctionType(Type t) : function(std::move(t)) { }
return bool(function);
}
- template <typename ... ARGS> auto operator()(EvaluationContext &ec, ARGS &&... args) const
+ template <typename ... ARGS> auto operator()(ARGS &&... args) const
{
std::vector<EvaluationValue> tmp;
pack(tmp, std::forward<ARGS>(args)...);
- return function(ec, std::move(tmp));
+ return function(std::move(tmp));
}
- EvaluationValue operator()(EvaluationContext &ec, std::vector<EvaluationValue> args) const;
+ EvaluationValue operator()(std::vector<EvaluationValue> args) const;
private:
Type function;
template <typename ... ARGS> class UserFunctionType : public FunctionType
{
public:
- UserFunctionType(std::function<EvaluationValue(EvaluationContext &, ARGS...)> f) :
+ UserFunctionType(std::function<EvaluationValue(ARGS...)> f) :
FunctionType(constructConvertingArgsFunction(std::move(f))) { }
private:
- static Type constructConvertingArgsFunction(std::function<EvaluationValue(EvaluationContext &, ARGS...)> f);
+ static Type constructConvertingArgsFunction(std::function<EvaluationValue(ARGS...)> f);
};
using VectorType = std::vector<EvaluationValue>;
namespace detail
{
- template <typename T> std::vector<T> ConvertTo<std::vector<T>>::convert(EvaluationContext &ec, EvaluationValue e)
+ template <typename T> std::vector<T> ConvertTo<std::vector<T>>::convert(EvaluationValue e)
{
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(ec, e));
+ 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(ec, e));
+ 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(ec, e.first));
+ 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);
}
- template <typename T> std::unordered_set<T> ConvertTo<std::unordered_set<T>>::convert(EvaluationContext &ec, EvaluationValue e)
+ template <typename T> std::unordered_set<T> ConvertTo<std::unordered_set<T>>::convert(EvaluationValue e)
{
std::unordered_set<T> result;
if (e.kind() == detail::Kind::VECTOR) {
result.reserve(e.as<VectorType>().size());
for (auto &e : e.as<VectorType>()) {
- result.insert(ConvertTo<T>::convert(ec, e));
+ 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(ec, e));
+ 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(ec, e.first));
+ 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(EvaluationContext &ec, EvaluationValue e)
+ template <typename K, typename V> std::unordered_map<K, V> ConvertTo<std::unordered_map<K, V>>::convert(EvaluationValue e)
{
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(ec, e.first);
- auto v = ConvertTo<V>::convert(ec, e.second);
+ 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()) <<
return std::move(result);
}
template <typename ... ARGS>
- auto UserFunctionType<ARGS...>::constructConvertingArgsFunction(std::function<EvaluationValue(EvaluationContext &, ARGS...)> f) -> Type
+ auto UserFunctionType<ARGS...>::constructConvertingArgsFunction(std::function<EvaluationValue(ARGS...)> f) -> Type
{
- return [f = std::move(f)](EvaluationContext & ec, std::vector<EvaluationValue> sourceArgs) -> EvaluationValue {
+ 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(ec, args, sourceArgs);
- return detail::apply(f, ec, args);
+ detail::Converter<0, sizeof...(ARGS)>::convert(args, sourceArgs);
+ return detail::apply(f, args);
};
}
}
IdentifierEvaluator::IdentifierEvaluator(TokenLocation tokenLocation, std::string identifier) :
ExpressionEvaluator(std::move(tokenLocation)), identifier(std::move(identifier)) { }
-EvaluationValue IdentifierEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue IdentifierEvaluator::evaluate() const
{
- return ec.getVariable(location(), identifier);
+ return EvaluationContext::getCurrentEvaluationContext().getVariable(location(), identifier);
}
static std::ostringstream &printLocationAndIndent(std::ostringstream &os, const TokenLocation &loc, unsigned int depth)
AttributeEvaluator::AttributeEvaluator(TokenLocation tokenLocation, ExprPtr self, std::string identifier) :
ExpressionEvaluator(std::move(tokenLocation)), self(std::move(self)), identifier(std::move(identifier)) { }
-EvaluationValue AttributeEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue AttributeEvaluator::evaluate() const
{
- return ec.getAttribute(location(), self->evaluate(ec), identifier);
+ return EvaluationContext::getCurrentEvaluationContext().getAttribute(location(), self->evaluate(), 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::evaluate(EvaluationContext &ec) const
+EvaluationValue AttributeSetterEvaluator::evaluate() const
{
- return ec.setAttribute(location(), self->evaluate(ec), identifier, value->evaluate(ec));
+ return EvaluationContext::getCurrentEvaluationContext().setAttribute(location(), self->evaluate(), identifier, value->evaluate());
}
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::evaluate(EvaluationContext &ec) const
+EvaluationValue SetterEvaluator::evaluate() const
{
- auto v = value->evaluate(ec);
- ec.setVariable(identifier, v);
+ auto v = value->evaluate();
+ EvaluationContext::getCurrentEvaluationContext().setVariable(identifier, v);
return v;
}
PointEvaluator::PointEvaluator(TokenLocation tokenLocation, ExprPtr x, ExprPtr y) :
ExpressionEvaluator(std::move(tokenLocation)), x(std::move(x)), y(std::move(y)) { }
-EvaluationValue PointEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue PointEvaluator::evaluate() const
{
- auto xInt = detail::ConvertTo<int>::convert(ec, x->evaluate(ec));
- auto yInt = detail::ConvertTo<int>::convert(ec, y->evaluate(ec));
+ auto xInt = detail::ConvertTo<int>::convert(x->evaluate());
+ auto yInt = detail::ConvertTo<int>::convert(y->evaluate());
return Point{ xInt, yInt };
}
IntegerEvaluator::IntegerEvaluator(TokenLocation tokenLocation, int value) :
ExpressionEvaluator(std::move(tokenLocation)), value(value) { }
-EvaluationValue IntegerEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue IntegerEvaluator::evaluate() const
{
return value;
}
DoubleEvaluator::DoubleEvaluator(TokenLocation tokenLocation, double value) :
ExpressionEvaluator(std::move(tokenLocation)), value(value) { }
-EvaluationValue DoubleEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue DoubleEvaluator::evaluate() const
{
return value;
}
StringEvaluator::StringEvaluator(TokenLocation tokenLocation, std::string value) :
ExpressionEvaluator(std::move(tokenLocation)), value(std::move(value)) { }
-EvaluationValue StringEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue StringEvaluator::evaluate() const
{
return EvaluationValue{ value };
}
ArraySetDictEvaluator::ArraySetDictEvaluator(TokenLocation tokenLocation, ExprPtrs values, Kind kind) :
ExpressionEvaluator(std::move(tokenLocation)), values(std::move(values)), kind(kind) { }
-EvaluationValue ArraySetDictEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue ArraySetDictEvaluator::evaluate() const
{
std::vector<EvaluationValue> vals;
for (auto &v : values)
- vals.push_back(v->evaluate(ec));
+ vals.push_back(v->evaluate());
if (kind == Kind::VECTOR)
return { std::move(vals) };
OperatorEvaluator::OperatorEvaluator(TokenLocation tokenLocation, ExprPtrs args, Kind kind) :
ExpressionEvaluator(std::move(tokenLocation)), args(std::move(args)), kind(kind) { }
-EvaluationValue OperatorEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue OperatorEvaluator::evaluate() const
{
std::vector<EvaluationValue> vals;
for (auto &a : args)
- vals.push_back(a->evaluate(ec));
+ vals.push_back(a->evaluate());
switch (kind) {
case Kind::IN:
- return ec.evaluateIn(location(), vals[1], vals[0]);
+ return EvaluationContext::getCurrentEvaluationContext().evaluateIn(location(), vals[1], vals[0]);
case Kind::NOT:
return !bool(vals[0]);
case Kind::MINUS:
- return ec.evaluateMinus(location(), vals[0]);
+ return EvaluationContext::getCurrentEvaluationContext().evaluateMinus(location(), vals[0]);
case Kind::GET:
- return ec.evaluateAccessGet(location(), vals);
+ return EvaluationContext::getCurrentEvaluationContext().evaluateAccessGet(location(), vals);
case Kind::SET:
- return ec.evaluateAccessSet(location(), std::move(vals));
+ return EvaluationContext::getCurrentEvaluationContext().evaluateAccessSet(location(), std::move(vals));
}
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::evaluate(EvaluationContext &ec) const
+EvaluationValue CompOperatorEvaluator::evaluate() const
{
auto cmp = [](const EvaluationValue & l, const EvaluationValue & r, Kind kind) {
switch (kind) {
}
return false;
};
- auto l = args[0]->evaluate(ec);
+ auto l = args[0]->evaluate();
for (auto i = 0u; i < kinds.size(); ++i) {
- auto r = args[i + 1]->evaluate(ec);
+ auto r = args[i + 1]->evaluate();
if (!cmp(l, r, kinds[i])) return false;
l = std::move(r);
}
BooleanEvaluator::BooleanEvaluator(TokenLocation tokenLocation, bool value) :
ExpressionEvaluator(std::move(tokenLocation)), value(std::move(value)) { }
-EvaluationValue BooleanEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue BooleanEvaluator::evaluate() const
{
return value;
}
CallEvaluator::CallEvaluator(TokenLocation tokenLocation, ExprPtr function, ExprPtrs args) :
ExpressionEvaluator(tokenLocation), function(std::move(function)), args(std::move(args)) { }
-EvaluationValue CallEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue CallEvaluator::evaluate() const
{
std::vector<EvaluationValue> values;
values.reserve(args.size());
for (auto &arg : args) {
- values.push_back(arg->evaluate(ec));
+ values.push_back(arg->evaluate());
}
- return ec.callFunction(location(), function->evaluate(ec), std::move(values));
+ return EvaluationContext::getCurrentEvaluationContext().callFunction(location(), function->evaluate(), std::move(values));
}
void CallEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
ExpressionAsStatementEvaluator::ExpressionAsStatementEvaluator(TokenLocation tokenLocation, ExprPtr expr) :
StatementEvaluator(tokenLocation), expr(std::move(expr)) { }
-void ExpressionAsStatementEvaluator::evaluate(EvaluationContext &ec) const
+void ExpressionAsStatementEvaluator::evaluate() const
{
- expr->evaluate(ec);
+ expr->evaluate();
}
void ExpressionAsStatementEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
BlockEvaluator::BlockEvaluator(TokenLocation tokenLocation, StatPtrs evals) :
StatementEvaluator(tokenLocation), evals(std::move(evals)) { }
-void BlockEvaluator::evaluate(EvaluationContext &parentEc) const
+void BlockEvaluator::evaluate() const
{
- EvaluationContext ec { parentEc };
for (auto &b : evals)
- b->evaluate(ec);
+ b->evaluate();
}
void BlockEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) const
* Calling this function will evaluate given expression, including it's all children,
* and return produced value. Might possibly raise an EvaluationFailure exception.
*/
- virtual EvaluationValue evaluate(EvaluationContext &ec) const = 0;
+ virtual EvaluationValue evaluate() const = 0;
};
/**
* Calling this function will evaluate given statement, including it's all children.
* Might possibly raise an EvaluationFailure exception.
*/
- virtual void evaluate(EvaluationContext &ec) const = 0;
+ virtual void evaluate() const = 0;
};
using ExprPtr = std::shared_ptr<ExpressionEvaluator>;
public:
IdentifierEvaluator(TokenLocation location_, std::string identifier);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
AttributeEvaluator(TokenLocation location_, ExprPtr self, std::string identifier);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
AttributeSetterEvaluator(TokenLocation location_, ExprPtr self, std::string identifier, ExprPtr value);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
SetterEvaluator(TokenLocation location_, std::string identifier, ExprPtr value);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
PointEvaluator(TokenLocation location_, ExprPtr x, ExprPtr y);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
IntegerEvaluator(TokenLocation location_, int value);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
DoubleEvaluator(TokenLocation location_, double value);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
BooleanEvaluator(TokenLocation location_, bool value);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
StringEvaluator(TokenLocation location_, std::string value);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
};
ArraySetDictEvaluator(TokenLocation location_, ExprPtrs values, Kind kind);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
private:
ExprPtrs values;
public:
CallEvaluator(TokenLocation location_, ExprPtr function, ExprPtrs args);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
};
OperatorEvaluator(TokenLocation location_, ExprPtrs args, Kind kind);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
private:
ExprPtrs args;
};
CompOperatorEvaluator(TokenLocation location_, ExprPtrs args, std::vector<Kind> kinds, std::vector<TokenLocation> locations);
- EvaluationValue evaluate(EvaluationContext &ec) const override;
+ EvaluationValue evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
private:
ExprPtrs args;
public:
ExpressionAsStatementEvaluator(TokenLocation location_, ExprPtr expr);
- void evaluate(EvaluationContext &ec) const override;
+ void evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
public:
BlockEvaluator(TokenLocation location_, StatPtrs evals);
- void evaluate(EvaluationContext &ec) const override;
+ void evaluate() const override;
void printSelfInfo(std::ostringstream &os, unsigned int depth) const override;
};
auto vars = VarsType {
{
"foo", detail::UserFunctionType<int, std::string, std::string, bool>{
- [&](EvaluationContext &, int v1, std::string v2, std::string v3, bool v4) -> EvaluationValue {
+ [&](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>{
- [&](EvaluationContext &, std::string value) -> EvaluationValue {
+ [&](std::string value) -> EvaluationValue {
result2 = value;
return nullptr;
}
TestExecutor exec(std::move(vars));
EvaluationContext ec { exec };
try {
- result->evaluate(ec);
+ result->evaluate();
} catch (EvaluationFailure e) {
std::ostringstream os;
if (e.hasLocation())
auto vars = VarsType { };
std::ostringstream output;
vars["assert"] = detail::UserFunctionType<bool> {
- [&](EvaluationContext &, bool val) -> EvaluationValue {
+ [&](bool val) -> EvaluationValue {
if (!val) throw EvaluationFailure{} << "assertion failed2";
++callCount;
return {};
}
};
vars["print"] = detail::UserFunctionType<EvaluationValue> {
- [&](EvaluationContext &, EvaluationValue val) -> EvaluationValue {
+ [&](EvaluationValue val) -> EvaluationValue {
output << ">>> " << val << "\n";
return {};
}
EvaluationContext ec{ exec };
try {
- result->evaluate(ec);
+ result->evaluate();
} catch (EvaluationFailure &e) {
size_t i = 0, c = 1;
while (i < txt.size()) {
app_event_handler_h handler;
ui_app_add_event_handler(&handler, APP_EVENT_LANGUAGE_CHANGED, _setting_time_lang_changed, nullptr);
- return ui_app_main(argc, argv, &event_callback, nullptr);
+ auto returnCode = ui_app_main(argc, argv, &event_callback, nullptr);
+ DEBUG("main function done");
+ return returnCode;
}