Handling proper context for functions 54/170254/2
authorLukasz Wlazly <l.wlazly@partner.samsung.com>
Thu, 15 Feb 2018 13:25:18 +0000 (14:25 +0100)
committerRadoslaw Cybulski <r.cybulski@partner.samsung.com>
Wed, 22 May 2019 13:13:49 +0000 (15:13 +0200)
Previously calling function assigned to variable was done with invalid context.
This patch changes context to correct.

Change-Id: Ifbc074c5eca747411c6613d8b3057fa969d763a4

src/batch/EvaluationContext.cpp
src/batch/EvaluationContext.hpp
src/batch/Evaluator.cpp
tests/no-ui-scenarios/BatchExecTests.cpp

index 735c0c1..d9b4b9d 100644 (file)
@@ -39,6 +39,14 @@ EvaluationContext::EvaluationContext() : parent(current)
        ASSERT(parent);
        current = this;
        globalContext = this->parent->globalContext;
+       this->data->parent = parent->data;
+}
+
+EvaluationContext::EvaluationContext(std::shared_ptr<Data> data) : parent(current)
+{
+       current = this;
+       globalContext = this->parent->globalContext;
+       this->data->parent = data;
 }
 
 EvaluationContext::~EvaluationContext()
@@ -46,6 +54,11 @@ EvaluationContext::~EvaluationContext()
        current = parent;
 }
 
+std::shared_ptr<EvaluationContext::Data> EvaluationContext::getData() const
+{
+       return data;
+}
+
 void EvaluationContext::initializeGlobalContext(ExecutorInterface &ei)
 {
        globalContext = std::make_shared<GlobalContext>(GlobalContext{ ei });
@@ -58,12 +71,12 @@ ExecutorInterface &EvaluationContext::executionInterface() const
 
 void EvaluationContext::setVariable(const std::string &ident, EvaluationValue val)
 {
-       variables[ident] = std::move(val);
+       data->variables[ident] = std::move(val);
 }
 
 EvaluationValue EvaluationContext::getVariable(const Optional<TokenLocation> &loc, const std::string &ident)
 {
-       EvaluationContext *self = this;
+       auto self = data;
        while (self) {
                auto it = self->variables.find(ident);
                if (it != self->variables.end()) return it->second;
@@ -135,4 +148,3 @@ EvaluationValue ExecutorInterface::getVariableByName(const std::string &name)
 {
        throw EvaluationFailure{} << "getVariableByName not implemeneted";
 }
-
index 714abcb..be0e828 100644 (file)
@@ -124,8 +124,15 @@ struct ExecutorInterface {
 class EvaluationContext
 {
        struct GlobalContext;
+
 public:
+       struct Data {
+               std::unordered_map<std::string, EvaluationValue> variables;
+               std::shared_ptr<Data> parent;
+       };
+
        explicit EvaluationContext(ExecutorInterface &ei);
+       explicit EvaluationContext(std::shared_ptr<Data> data);
        explicit EvaluationContext();
        ~EvaluationContext();
 
@@ -135,6 +142,8 @@ public:
        EvaluationContext &operator = (const EvaluationContext &) = delete;
        EvaluationContext &operator = (EvaluationContext &&) = delete;
 
+       std::shared_ptr<Data> getData() const;
+
        /**
         * @brief Sets variable
         *
@@ -193,7 +202,7 @@ public:
 private:
        void initializeGlobalContext(ExecutorInterface &ei);
 
-       std::unordered_map<std::string, EvaluationValue> variables;
+       std::shared_ptr<Data> data = std::make_shared<Data>();
        EvaluationContext *parent = nullptr;
        std::shared_ptr<GlobalContext> globalContext;
        std::vector<const std::string *> batchPathStack;
index 05e2229..2d5836d 100644 (file)
@@ -622,11 +622,12 @@ FunctionEvaluator::FunctionEvaluator(TokenLocation location_, std::string functi
 
 void FunctionEvaluator::evaluateImpl() const
 {
+       auto data = EvaluationContext::getCurrentEvaluationContext().getData();
        EvaluationContext::getCurrentEvaluationContext().setVariable(functionName,
        EvaluationValueFunction {[ = ](EvaluationValueFunction::Args args) -> EvaluationValue {
                        if (this->argNames.size() != args.size())
                                throw EvaluationFailure{} << "invalid number of arguments";
-                       EvaluationContext ctx;
+                       EvaluationContext ctx(data);
                        for (auto i = 0u; i < args.size(); ++i)
                        {
                                ctx.setVariable(argNames[i], args[i]);
index c4d064d..b49928d 100644 (file)
@@ -976,6 +976,15 @@ TEST_F(ScriptTest, functionReturn)
                        { "a2" },
                } };
 
+       int expected = 0;
+       exec.variables["sth"] = EvaluationValueFunction {
+               [&](int a1) -> EvaluationValue {
+                       expected = a1;
+                       return a1;
+               }, {
+                       { "a1" },
+               } };
+
        ASSERT_NO_THROW(
                executeWithInfo(
                        "def myFunc() {\n"
@@ -1019,6 +1028,22 @@ TEST_F(ScriptTest, functionReturn)
                                         "{\n"
                                         "  return 12\n"
                                         "}\n", ec, false), ReturnValue);
+
+       ASSERT_NO_THROW(
+               executeWithInfo(
+                       "def myFunc() {\n"
+                       "  def myFunc3(a) {\n"
+                       "    sth(a)\n"
+                       "  }\n"
+                       "  def myFunc2(a) {\n"
+                       "    myFunc3(a)\n"
+                       "  }\n"
+                       "  return myFunc2\n"
+                       "}\n"
+                       "tmp = myFunc()\n"
+                       "tmp(13)\n", ec)
+       );
+       ASSERT_EQ(expected, 13);
 }
 
 int main(int argc, char *argv[])
@@ -1030,4 +1055,3 @@ int main(int argc, char *argv[])
                return 1;
        }
 }
-