Gentoo Archives: gentoo-commits

From: "Petteri Räty" <betelgeuse@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/libbash:master commit in: scripts/, src/core/, bashast/
Date: Sat, 07 May 2011 12:25:11
Message-Id: 45746a47c5205d0b4f3729ef9fa9373894733c8c.betelgeuse@gentoo
1 commit: 45746a47c5205d0b4f3729ef9fa9373894733c8c
2 Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
3 AuthorDate: Thu May 5 13:26:54 2011 +0000
4 Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
5 CommitDate: Sat May 7 12:13:40 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=45746a47
7
8 Walker: support defining local variables
9
10 ---
11 bashast/libbashWalker.g | 20 ++++++++++++++----
12 scripts/function_def.bash | 10 +++++++++
13 scripts/function_def.bash.result | 1 +
14 src/core/interpreter.cpp | 40 +++++++++++++++++++++++++++++++++----
15 src/core/interpreter.h | 39 +++++++++++++++++++++---------------
16 5 files changed, 84 insertions(+), 26 deletions(-)
17
18 diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
19 index 064556a..1a305ef 100644
20 --- a/bashast/libbashWalker.g
21 +++ b/bashast/libbashWalker.g
22 @@ -91,7 +91,11 @@ start: list|EOF;
23
24 list: ^(LIST (function_def|logic_command_list)+);
25
26 -variable_definitions: ^(VARIABLE_DEFINITIONS var_def+);
27 +variable_definitions
28 +@declarations {
29 + bool local = false;
30 +}
31 + :^(VARIABLE_DEFINITIONS (LOCAL { local = true; })? var_def[local]+);
32
33 name_base returns[std::string libbash_value]
34 :NAME { $libbash_value = walker->get_string($NAME); }
35 @@ -115,13 +119,16 @@ options{ k=1; }
36 :DIGIT { $libbash_value = walker->get_string($DIGIT); }
37 |NUMBER { $libbash_value = walker->get_string($NUMBER); };
38
39 -var_def
40 +var_def[bool local]
41 @declarations {
42 std::map<int, std::string> values;
43 unsigned index = 0;
44 }
45 :^(EQUALS name string_expr?) {
46 - walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index);
47 + if(local)
48 + walker->define_local($name.libbash_value, $string_expr.libbash_value, false, $name.index);
49 + else
50 + walker->set_value($name.libbash_value, $string_expr.libbash_value, $name.index);
51 }
52 |^(EQUALS libbash_name=name_base ^(ARRAY (
53 (expr=string_expr
54 @@ -130,7 +137,10 @@ var_def
55 } expr=string_expr))
56 { values[index++] = expr.libbash_value; })*
57 )){
58 - walker->define(libbash_name, values);
59 + if(local)
60 + walker->define_local(libbash_name, values);
61 + else
62 + walker->define(libbash_name, values);
63 };
64
65 string_expr returns[std::string libbash_value, bool quoted]
66 @@ -282,7 +292,7 @@ simple_command
67 @declarations {
68 std::vector<std::string> libbash_args;
69 }
70 - :^(COMMAND string_expr (argument[libbash_args])* var_def*) {
71 + :^(COMMAND string_expr (argument[libbash_args])* var_def[true]*) {
72 if(walker->has_function($string_expr.libbash_value))
73 {
74 walker->set_status(walker->call($string_expr.libbash_value,
75
76 diff --git a/scripts/function_def.bash b/scripts/function_def.bash
77 index 194d030..cbce4cd 100644
78 --- a/scripts/function_def.bash
79 +++ b/scripts/function_def.bash
80 @@ -26,3 +26,13 @@ FOO001="4 5"
81 ARRAY=(1 2 3)
82 func_with_args ${ARRAY[@]} $FOO001
83 func_with_args 100 $ARG2 $ARG3 $ARG4
84 +
85 +func_nested1() {
86 + echo $foo_nested ${bar_nested[0]}
87 +}
88 +func_nested2() {
89 + local foo_nested=hi bar_nested=(1 2
90 + 3)
91 + func_nested1
92 +}
93 +func_nested2
94
95 diff --git a/scripts/function_def.bash.result b/scripts/function_def.bash.result
96 index de9f3f8..bfc30b5 100644
97 --- a/scripts/function_def.bash.result
98 +++ b/scripts/function_def.bash.result
99 @@ -1,3 +1,4 @@
100 +hi 1
101 ARG1=100
102 ARG2=2
103 ARG3=3
104
105 diff --git a/src/core/interpreter.cpp b/src/core/interpreter.cpp
106 index 5363636..aa6c4de 100644
107 --- a/src/core/interpreter.cpp
108 +++ b/src/core/interpreter.cpp
109 @@ -24,6 +24,8 @@
110
111 #include "core/interpreter.h"
112
113 +#include <cctype>
114 +
115 #include <functional>
116
117 #include <boost/algorithm/string/classification.hpp>
118 @@ -31,6 +33,7 @@
119 #include <boost/algorithm/string/replace.hpp>
120 #include <boost/algorithm/string/split.hpp>
121 #include <boost/algorithm/string/trim.hpp>
122 +#include <boost/foreach.hpp>
123 #include <boost/range/adaptor/map.hpp>
124 #include <boost/range/algorithm/copy.hpp>
125
126 @@ -49,6 +52,33 @@ std::string interpreter::get_string(pANTLR3_BASE_TREE node)
127 token->stop - token->start + 1);
128 }
129
130 +std::shared_ptr<variable> interpreter::resolve_variable(const std::string& name) const
131 +{
132 + if(name.empty())
133 + throw interpreter_exception("Variable name shouldn't be empty");
134 + // positional parameter
135 + if(isdigit(name[0]) && !local_members.empty())
136 + {
137 + auto iter_local = local_members.back().find(name);
138 + if(iter_local != local_members.back().end())
139 + return iter_local->second;
140 + }
141 + else
142 + {
143 + BOOST_REVERSE_FOREACH(auto& frame, local_members)
144 + {
145 + auto iter_local = frame.find(name);
146 + if(iter_local != frame.end())
147 + return iter_local->second;
148 + }
149 + }
150 +
151 + auto iter_global = members.find(name);
152 + if(iter_global == members.end())
153 + return std::shared_ptr<variable>();
154 + return iter_global->second;
155 +}
156 +
157 bool interpreter::is_unset_or_null(const std::string& name,
158 const unsigned index) const
159 {
160 @@ -155,13 +185,13 @@ void interpreter::split_word(const std::string& word, std::vector<std::string>&
161 output.insert(output.end(), splitted_values.begin(), splitted_values.end());
162 }
163
164 -inline void define_function_arguments(std::unique_ptr<scope>& current_stack,
165 +inline void define_function_arguments(scope& current_stack,
166 const std::vector<std::string>& arguments)
167 {
168 for(auto i = 0u; i != arguments.size(); ++i)
169 {
170 const std::string& name = boost::lexical_cast<std::string>(i + 1);
171 - (*current_stack)[name] = std::shared_ptr<variable>(new variable(name, arguments[i]));
172 + current_stack[name].reset(new variable(name, arguments[i]));
173 }
174 }
175
176 @@ -177,8 +207,8 @@ int interpreter::call(const std::string& name,
177 func_index = iter->second;
178
179 // Prepare function stack and arguments
180 - local_members.push(std::unique_ptr<scope>(new scope));
181 - define_function_arguments(local_members.top(), arguments);
182 + local_members.push_back(scope());
183 + define_function_arguments(local_members.back(), arguments);
184
185 auto INPUT = ctx->pTreeParser->ctnstream;
186 auto ISTREAM = INPUT->tnstream->istream;
187 @@ -192,7 +222,7 @@ int interpreter::call(const std::string& name,
188 ISTREAM->seek(ISTREAM, curr);
189
190 // Clear function stack
191 - local_members.pop();
192 + local_members.pop_back();
193
194 return 0;
195 }
196
197 diff --git a/src/core/interpreter.h b/src/core/interpreter.h
198 index 35ae8ac..7673479 100644
199 --- a/src/core/interpreter.h
200 +++ b/src/core/interpreter.h
201 @@ -29,7 +29,6 @@
202
203 #include <functional>
204 #include <memory>
205 -#include <stack>
206 #include <string>
207
208 #include <antlr3basetree.h>
209 @@ -60,7 +59,7 @@ class interpreter
210 /// \var private::local_members
211 /// \brief local scope for function arguments, execution environment and
212 /// local variables
213 - std::stack<std::unique_ptr<scope>> local_members;
214 + std::vector<scope> local_members;
215
216 std::ostream* out;
217
218 @@ -83,6 +82,8 @@ class interpreter
219 const std::string& delim,
220 std::string& result) const;
221
222 + std::shared_ptr<variable> resolve_variable(const std::string&) const;
223 +
224 public:
225
226 interpreter(): out(&std::cout), err(&std::cerr), in(&std::cin)
227 @@ -401,17 +402,11 @@ public:
228 template <typename T>
229 T resolve(const std::string& name, const unsigned index=0) const
230 {
231 - if(!local_members.empty())
232 - {
233 - auto iter_local = local_members.top()->find(name);
234 - if(iter_local != local_members.top()->end())
235 - return iter_local->second->get_value<T>(index);
236 - }
237 -
238 - auto iter_global = members.find(name);
239 - if(iter_global == members.end())
240 - return T();
241 - return iter_global->second->get_value<T>(index);
242 + auto var = resolve_variable(name);
243 + if(var)
244 + return var->get_value<T>(index);
245 + else
246 + return T{};
247 }
248
249 /// \brief resolve array variable
250 @@ -495,9 +490,21 @@ public:
251 bool readonly=false,
252 const unsigned index=0)
253 {
254 - std::shared_ptr<variable> target(
255 - new variable(name, value, readonly, index));
256 - members[name] = target;
257 + members[name].reset(new variable(name, value, readonly, index));
258 + }
259 +
260 + /// \brief define a new local variable
261 + /// \param the name of the variable
262 + /// \param the value of the variable
263 + /// \param whether it's readonly, default is false
264 + /// \param whether it's null, default is false
265 + template <typename T>
266 + void define_local(const std::string& name,
267 + const T& value,
268 + bool readonly=false,
269 + const unsigned index=0)
270 + {
271 + local_members.back()[name].reset(new variable(name, value, readonly, index));
272 }
273
274 /// \brief define a new function