Refactors how current EvaluationContext is passed over 67/167267/34
authorRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Tue, 16 Jan 2018 12:23:54 +0000 (13:23 +0100)
committerRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Wed, 24 Jan 2018 14:42:54 +0000 (15:42 +0100)
Current EvaluationContext object is no longer passed around as function
argument. Now there's global thread_local pointer to current
EvaluationContext value. Creating new EvaluationContext updates this
pointer, but only for the current thread.

Change-Id: I9ce52ddb2860a53e405da85fe0cd53a833f73d8c

src/UniversalSwitch.cpp
src/batch/BatchRunner.cpp
src/batch/EvaluationContext.cpp
src/batch/EvaluationContext.hpp
src/batch/EvaluationValue.cpp
src/batch/EvaluationValue.hpp
src/batch/Evaluator.cpp
src/batch/Evaluator.hpp
tests/no-ui-scenarios/BatchExecTests.cpp
tests/ui-scenarios/main.cpp

index 2c5b8a9..2e1577f 100644 (file)
@@ -269,4 +269,5 @@ void UniversalSwitch::terminate()
        }
        purgeBatchTimerIfNeeded();
        batchModeTimers.clear();
+       DEBUG("terminating completed");
 }
index 0f8a5c5..6a36e42 100644 (file)
@@ -221,17 +221,16 @@ struct TestExecutor : ExecutorInterface {
        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)) };
@@ -241,24 +240,24 @@ struct TestExecutor : ExecutorInterface {
                        }
                };
                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
                                {
@@ -287,7 +286,7 @@ struct TestExecutor : ExecutorInterface {
                        }
                };
                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, [&]()
@@ -301,7 +300,7 @@ struct TestExecutor : ExecutorInterface {
                        }
                };
                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());
@@ -322,7 +321,7 @@ struct TestExecutor : ExecutorInterface {
                        }
                };
                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([&]() {
@@ -336,17 +335,17 @@ struct TestExecutor : ExecutorInterface {
                        }
                };
                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([&]()
@@ -364,7 +363,7 @@ struct TestExecutor : ExecutorInterface {
                };
                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);
@@ -385,7 +384,7 @@ struct TestExecutor : ExecutorInterface {
                                        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";
@@ -441,7 +440,7 @@ struct TestExecutor : ExecutorInterface {
        {
                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));
        }
@@ -450,7 +449,7 @@ struct TestExecutor : ExecutorInterface {
        {
                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);
        }
@@ -858,7 +857,7 @@ Optional<std::thread> runBatch(const std::string &sourceName, std::string output
        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;
@@ -892,7 +891,7 @@ Optional<std::thread> runBatch(const std::string &sourceName, std::string output
                                });
                                exec->outputStream() << "evaluation started\n";
                                try {
-                                       result->evaluate(ec);
+                                       result->evaluate();
                                        exec->outputStream() << "evaluation successed\n";
                                } catch (EvaluationFailure &e) {
                                        if (e.hasLocation())
index d656b08..26801fc 100644 (file)
@@ -34,17 +34,32 @@ struct EvaluationContext::GlobalContext {
        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 });
@@ -83,7 +98,7 @@ EvaluationValue EvaluationContext::callFunction(const Optional<TokenLocation> &l
        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;
@@ -159,17 +174,17 @@ EvaluationValue EvaluationContext::convert(const Optional<TokenLocation> &loc, c
                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:
@@ -188,7 +203,7 @@ EvaluationValue EvaluationContext::convert(const Optional<TokenLocation> &loc, c
 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;
@@ -198,8 +213,8 @@ int EvaluationContext::getSingleIndex(const std::vector<EvaluationValue> &args,
 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;
 
@@ -357,7 +372,7 @@ bool EvaluationContext::evaluateIn(const Optional<TokenLocation> &loc, const Eva
        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: {
index 4e48104..b5502c1 100644 (file)
@@ -40,15 +40,50 @@ struct ExecutorInterface {
        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);
@@ -58,7 +93,24 @@ public:
        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);
index ab8ce65..65bd87c 100644 (file)
@@ -44,9 +44,9 @@ TokenLocation EvaluationFailure::location()
        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)
@@ -348,7 +348,7 @@ bool EvaluationValue::operator >= (const EvaluationValue &other) const
 
 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) {
@@ -365,7 +365,7 @@ namespace detail
                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>();
@@ -379,7 +379,7 @@ namespace detail
                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";
@@ -389,23 +389,25 @@ namespace detail
                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()) <<
index 2a9da0a..07eb2fb 100644 (file)
@@ -112,79 +112,77 @@ namespace detail
        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)) { }
@@ -194,13 +192,13 @@ namespace detail
                        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;
 
@@ -216,10 +214,10 @@ namespace detail
        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>;
@@ -379,61 +377,61 @@ private:
 
 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()) <<
@@ -441,17 +439,17 @@ namespace detail
                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);
                };
        }
 }
index 0a7f988..f5a976d 100644 (file)
@@ -37,9 +37,9 @@ TokenLocation Evaluator::location() const
 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)
@@ -57,9 +57,9 @@ void IdentifierEvaluator::printSelfInfo(std::ostringstream &os, unsigned int dep
 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
@@ -73,9 +73,9 @@ void AttributeEvaluator::printSelfInfo(std::ostringstream &os, unsigned int dept
 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
@@ -91,10 +91,10 @@ void AttributeSetterEvaluator::printSelfInfo(std::ostringstream &os, unsigned in
 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;
 }
 
@@ -109,10 +109,10 @@ void SetterEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth)
 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 };
 }
 
@@ -129,7 +129,7 @@ void PointEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) c
 IntegerEvaluator::IntegerEvaluator(TokenLocation tokenLocation, int value) :
        ExpressionEvaluator(std::move(tokenLocation)), value(value) { }
 
-EvaluationValue IntegerEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue IntegerEvaluator::evaluate() const
 {
        return value;
 }
@@ -143,7 +143,7 @@ void IntegerEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth)
 DoubleEvaluator::DoubleEvaluator(TokenLocation tokenLocation, double value) :
        ExpressionEvaluator(std::move(tokenLocation)), value(value) { }
 
-EvaluationValue DoubleEvaluator::evaluate(EvaluationContext &ec) const
+EvaluationValue DoubleEvaluator::evaluate() const
 {
        return value;
 }
@@ -157,7 +157,7 @@ void DoubleEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth)
 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 };
 }
@@ -171,11 +171,11 @@ void StringEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth)
 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) };
@@ -229,23 +229,23 @@ void ArraySetDictEvaluator::printSelfInfo(std::ostringstream &os, unsigned int d
 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";
@@ -285,7 +285,7 @@ void OperatorEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth
 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) {
@@ -304,9 +304,9 @@ EvaluationValue CompOperatorEvaluator::evaluate(EvaluationContext &ec) const
                }
                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);
        }
@@ -357,7 +357,7 @@ void CompOperatorEvaluator::printSelfInfo(std::ostringstream &os, unsigned int d
 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;
 }
@@ -371,14 +371,14 @@ void BooleanEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth)
 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
@@ -396,9 +396,9 @@ void CallEvaluator::printSelfInfo(std::ostringstream &os, unsigned int depth) co
 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
@@ -411,11 +411,10 @@ void ExpressionAsStatementEvaluator::printSelfInfo(std::ostringstream &os, unsig
 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
index ad3c9c9..a29b9f8 100644 (file)
@@ -66,7 +66,7 @@ public:
         * 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;
 };
 
 /**
@@ -83,7 +83,7 @@ public:
         * 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>;
@@ -107,7 +107,7 @@ class IdentifierEvaluator : public 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;
 };
 
@@ -125,7 +125,7 @@ class AttributeEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -143,7 +143,7 @@ class AttributeSetterEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -160,7 +160,7 @@ class SetterEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -176,7 +176,7 @@ class PointEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -189,7 +189,7 @@ class IntegerEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -202,7 +202,7 @@ class DoubleEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -215,7 +215,7 @@ class BooleanEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -228,7 +228,7 @@ class StringEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -247,7 +247,7 @@ public:
        };
        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;
@@ -268,7 +268,7 @@ class CallEvaluator : public ExpressionEvaluator
 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;
 };
 
@@ -287,7 +287,7 @@ public:
        };
        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;
@@ -311,7 +311,7 @@ public:
        };
        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;
@@ -328,7 +328,7 @@ class ExpressionAsStatementEvaluator : public StatementEvaluator
 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;
 };
 
@@ -341,7 +341,7 @@ class BlockEvaluator : public StatementEvaluator
 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;
 };
 
index 08c57e9..c5d1283 100644 (file)
@@ -123,14 +123,14 @@ TEST(TestExec, simpleParser)
        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;
                                }
@@ -140,7 +140,7 @@ TEST(TestExec, simpleParser)
        TestExecutor exec(std::move(vars));
        EvaluationContext ec { exec };
        try {
-               result->evaluate(ec);
+               result->evaluate();
        } catch (EvaluationFailure e) {
                std::ostringstream os;
                if (e.hasLocation())
@@ -195,14 +195,14 @@ protected:
                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 {};
                        }
@@ -211,7 +211,7 @@ protected:
                EvaluationContext ec{ exec };
 
                try {
-                       result->evaluate(ec);
+                       result->evaluate();
                } catch (EvaluationFailure &e) {
                        size_t i = 0, c = 1;
                        while (i < txt.size()) {
index 2873aab..35a89ff 100644 (file)
@@ -66,5 +66,7 @@ int main(int argc, char *argv[])
        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;
 }