diff options
author | Mu Qiao <qiaomuf@gentoo.org> | 2011-04-21 19:58:16 +0800 |
---|---|---|
committer | Mu Qiao <qiaomuf@gentoo.org> | 2011-04-28 10:57:53 +0800 |
commit | be5289bca55b033742300ed0f5f69121b2bb76c4 (patch) | |
tree | 708461b2083f82124c3be9169c87466083c7de53 | |
parent | Core: use reference/pointer for the interpreter object (diff) | |
download | libbash-be5289bca55b033742300ed0f5f69121b2bb76c4.tar.gz libbash-be5289bca55b033742300ed0f5f69121b2bb76c4.tar.bz2 libbash-be5289bca55b033742300ed0f5f69121b2bb76c4.zip |
Core: support unsetting variables, fix is_null
Empty variable values are all treated as null value. This simplifies
the previous code and fixes some logic errors.
-rw-r--r-- | bashast/libbashWalker.g | 5 | ||||
-rw-r--r-- | scripts/var_def.bash.result | 4 | ||||
-rw-r--r-- | src/core/interpreter.cpp | 21 | ||||
-rw-r--r-- | src/core/interpreter.h | 19 | ||||
-rw-r--r-- | src/core/symbols.hpp | 40 | ||||
-rw-r--r-- | src/core/tests/interpreter_test.cpp | 29 | ||||
-rw-r--r-- | src/core/tests/symbols_test.cpp | 12 |
7 files changed, 105 insertions, 25 deletions
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g index e278d1b..203cd28 100644 --- a/bashast/libbashWalker.g +++ b/bashast/libbashWalker.g @@ -119,10 +119,9 @@ var_def @declarations { std::map<int, std::string> values; unsigned index = 0; - bool is_null = true; } - :^(EQUALS name (string_expr { is_null = false; })?) { - walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index, is_null); + :^(EQUALS name string_expr?) { + walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index); } |^(EQUALS libbash_name=name_base ^(ARRAY ( (expr=string_expr diff --git a/scripts/var_def.bash.result b/scripts/var_def.bash.result index e840ebe..1b9e287 100644 --- a/scripts/var_def.bash.result +++ b/scripts/var_def.bash.result @@ -5,8 +5,8 @@ $- has not been implemented yet $! has not been implemented yet ARRAY01=1 2 3 4 5 ARRAY02=1 2 4 5 -ARRAY03=2 3 -ARRAY04=2 3 +ARRAY03= 2 3 +ARRAY04= 2 3 ARRAY05=1 2 3 4 5 ARRAY06=1 2 3 4 5 ARRAY07=1 2 3 4 5 diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp index 9548e8a..f0bf61e 100644 --- a/src/core/interpreter.cpp +++ b/src/core/interpreter.cpp @@ -178,3 +178,24 @@ void interpreter::get_all_function_names(std::vector<std::string>& function_name { boost::copy(functions | boost::adaptors::map_keys, back_inserter(function_names)); } + +void interpreter::unset(const std::string& name) +{ + auto iter = members.find(name); + if(iter == members.end()) + return; + else if(iter->second->is_readonly()) + throw interpreter_exception("Can't unset readonly variable " + name); + else + members.erase(name); +} + +void interpreter::unset(const std::string& name, + const unsigned index) +{ + auto iter = members.find(name); + if(iter == members.end()) + return; + else + iter->second->unset_value(index); +} diff --git a/src/core/interpreter.h b/src/core/interpreter.h index e471b94..dc446fc 100644 --- a/src/core/interpreter.h +++ b/src/core/interpreter.h @@ -468,14 +468,13 @@ public: template <typename T> const T& set_value(const std::string& name, const T& new_value, - const unsigned index=0, - bool is_null=false) + const unsigned index=0) { auto i = members.find(name); if(i == members.end()) - define(name, new_value, false, is_null, index); + define(name, new_value, false, index); else - i->second->set_value(new_value, index, is_null); + i->second->set_value(new_value, index); return new_value; } @@ -494,6 +493,15 @@ public: return resolve<T>("?"); } + /// \brief unset a variable + /// \param the name of the variable + void unset(const std::string& name); + + /// \brief unset a array member + /// \param the name of the array + /// \param the index of the member + void unset(const std::string& name, const unsigned index); + /// \brief define a new global variable /// \param the name of the variable /// \param the value of the variable @@ -503,11 +511,10 @@ public: void define(const std::string& name, const T& value, bool readonly=false, - bool is_null=false, const unsigned index=0) { std::shared_ptr<variable> target( - new variable(name, value, readonly, is_null, index)); + new variable(name, value, readonly, index)); members[name] = target; } diff --git a/src/core/symbols.hpp b/src/core/symbols.hpp index b11d338..89fd657 100644 --- a/src/core/symbols.hpp +++ b/src/core/symbols.hpp @@ -137,12 +137,10 @@ public: variable(const std::string& name, const T& v, bool ro=false, - bool is_null=false, const unsigned index=0) : name(name), readonly(ro) { - if(!is_null) - value[index] = v; + value[index] = v; } /// \brief retrieve actual value of the variable, if index is out of bound, @@ -182,16 +180,22 @@ public: /// \param whether to set the variable to null value, default is false template <typename T> void set_value(const T& new_value, - const unsigned index=0, - bool is_null=false) + const unsigned index=0) { if(readonly) throw interpreter_exception(get_name() + " is readonly variable"); - if(is_null) - value.erase(index); - else - value[index] = new_value; + value[index] = new_value; + } + + /// \brief unset the variable, only used for array variable + /// \param the index to be unset + void unset_value(const unsigned index) + { + if(readonly) + throw interpreter_exception(get_name() + " is readonly variable"); + + value.erase(index); } /// \brief get the length of a variable @@ -211,10 +215,24 @@ public: /// \brief check whether the value of the variable is null /// \return whether the value of the variable is null - bool is_null(const unsigned index=0) const + bool is_unset(const unsigned index=0) const { return value.find(index) == value.end(); } + + /// \brief check whether the value of the variable is unset + /// \return whether the value of the variable is unset + bool is_null(const unsigned index=0) const + { + return get_value<std::string>(index) == ""; + } + + /// \brief check whether the value of the variable is readonly + /// \return whether the value of the variable is readonly + bool is_readonly() const + { + return readonly; + } }; // specialization for arrays @@ -222,7 +240,7 @@ template <> inline variable::variable<>(const std::string& name, const std::map<int, std::string>& v, bool ro, - bool, unsigned) + unsigned) : name(name), value(v.begin(), v.end()), readonly(ro) { } diff --git a/src/core/tests/interpreter_test.cpp b/src/core/tests/interpreter_test.cpp index 2e92a22..54f25b0 100644 --- a/src/core/tests/interpreter_test.cpp +++ b/src/core/tests/interpreter_test.cpp @@ -54,7 +54,7 @@ TEST(interpreter, define_resolve_array) EXPECT_STREQ("3", walker.resolve<string>("array", 2).c_str()); EXPECT_STREQ("", walker.resolve<string>("undefined",100).c_str()); - walker.define("partial", 10, false, false, 8); + walker.define("partial", 10, false, 8); EXPECT_EQ(1, walker.get_array_length("partial")); EXPECT_EQ(10, walker.resolve<int>("partial", 8)); } @@ -142,6 +142,33 @@ TEST(interpreter, get_array_values) EXPECT_EQ(3, array_values[2]); } +TEST(interpreter, unset_values) +{ + interpreter walker; + std::map<int, std::string> values = {{0, "1"}, {1, "2"}, {2, "3"}}; + walker.define("array", values); + walker.define("ro_array", values, true); + walker.define("var", "123"); + walker.define("ro_var", "123", true); + + EXPECT_STREQ("2", walker.resolve<string>("array", 1).c_str()); + walker.unset("array", 1); + EXPECT_STREQ("", walker.resolve<string>("array", 1).c_str()); + walker.unset("array"); + EXPECT_STREQ("", walker.resolve<string>("array", 0).c_str()); + EXPECT_STREQ("", walker.resolve<string>("array", 1).c_str()); + EXPECT_STREQ("", walker.resolve<string>("array", 2).c_str()); + + EXPECT_THROW(walker.unset("ro_array", 1), interpreter_exception); + EXPECT_THROW(walker.unset("ro_array"), interpreter_exception); + + EXPECT_STREQ("123", walker.resolve<string>("var").c_str()); + walker.unset("var"); + EXPECT_STREQ("", walker.resolve<string>("var").c_str()); + + EXPECT_THROW(walker.unset("ro_var"), interpreter_exception); +} + TEST(interperter, substring_expansion_exception) { interpreter walker; diff --git a/src/core/tests/symbols_test.cpp b/src/core/tests/symbols_test.cpp index d614947..f151318 100644 --- a/src/core/tests/symbols_test.cpp +++ b/src/core/tests/symbols_test.cpp @@ -122,9 +122,17 @@ TEST(symbol_test, is_null) { variable var("foo", 10); EXPECT_FALSE(var.is_null()); - var.set_value("bar", 0, true); + var.set_value(""); EXPECT_TRUE(var.is_null()); - EXPECT_TRUE(variable("foo", "", false, true).is_null()); + EXPECT_TRUE(variable("foo", "").is_null()); +} + +TEST(symbol_test, is_unset) +{ + map<int, string> values = {{0, "1"}, {1, "2"}, {2, "3"}}; + variable array("foo", values); + array.unset_value(1); + EXPECT_TRUE(array.is_unset(1)); } TEST(symbol_test, get_length) |