aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.h8
-rw-r--r--func.cc15
-rw-r--r--var.cc18
-rw-r--r--var.h18
4 files changed, 47 insertions, 12 deletions
diff --git a/eval.h b/eval.h
index 6a27c62..d99c778 100644
--- a/eval.h
+++ b/eval.h
@@ -50,13 +50,7 @@ class Evaluator {
const Loc& loc() const { return loc_; }
-#if 0
- const vector<Rule*>& rules() const { return rules_; }
- const Vars* vars() const { return vars_; }
- const unordered_map<StringPiece, Vars*>& rule_vars() const {
- return rule_vars_;
- }
-#endif
+ Vars* mutable_vars() { return vars_; }
void Error(const string& msg);
diff --git a/func.cc b/func.cc
index 9d694b9..3118430 100644
--- a/func.cc
+++ b/func.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <iterator>
+#include <memory>
#include <unordered_map>
#include "ast.h"
@@ -14,6 +15,7 @@
#include "log.h"
#include "parser.h"
#include "strutil.h"
+#include "var.h"
namespace {
@@ -389,8 +391,17 @@ void CallFunc(const vector<Value*>&, Evaluator*, string*) {
printf("TODO(call)");
}
-void ForeachFunc(const vector<Value*>&, Evaluator*, string*) {
- printf("TODO(foreach)");
+void ForeachFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
+ shared_ptr<string> varname = args[0]->Eval(ev);
+ shared_ptr<string> list = args[1]->Eval(ev);
+ WordWriter ww(s);
+ for (StringPiece tok : WordScanner(*list)) {
+ unique_ptr<SimpleVar> v(new SimpleVar(
+ make_shared<string>(tok.data(), tok.size()), "automatic"));
+ ScopedVar sv(ev->mutable_vars(), *varname, v.get());
+ ww.MaybeAddWhitespace();
+ args[2]->Eval(ev, s);
+ }
}
void OriginFunc(const vector<Value*>&, Evaluator*, string*) {
diff --git a/var.cc b/var.cc
index ee708f4..be1db17 100644
--- a/var.cc
+++ b/var.cc
@@ -82,3 +82,21 @@ void Vars::Assign(StringPiece name, Var* v) {
p.first->second = v;
}
}
+
+ScopedVar::ScopedVar(Vars* vars, StringPiece name, Var* var)
+ : vars_(vars), orig_(NULL) {
+ auto p = vars->insert(make_pair(name, var));
+ iter_ = p.first;
+ if (!p.second) {
+ orig_ = iter_->second;
+ iter_->second = var;
+ }
+}
+
+ScopedVar::~ScopedVar() {
+ if (orig_) {
+ iter_->second = orig_;
+ } else {
+ vars_->erase(iter_);
+ }
+}
diff --git a/var.h b/var.h
index e1b9d11..1d35c8f 100644
--- a/var.h
+++ b/var.h
@@ -47,7 +47,7 @@ class SimpleVar : public Var {
virtual void AppendVar(Evaluator* ev, Value* v);
- string DebugString() const override;
+ virtual string DebugString() const override;
private:
shared_ptr<string> v_;
@@ -69,7 +69,7 @@ class RecursiveVar : public Var {
virtual void AppendVar(Evaluator* ev, Value* v);
- string DebugString() const override;
+ virtual string DebugString() const override;
private:
Value* v_;
@@ -90,7 +90,7 @@ class UndefinedVar : public Var {
virtual void Eval(Evaluator* ev, string* s) const override;
- string DebugString() const override;
+ virtual string DebugString() const override;
};
extern UndefinedVar* kUndefined;
@@ -104,4 +104,16 @@ class Vars : public unordered_map<StringPiece, Var*> {
void Assign(StringPiece name, Var* v);
};
+class ScopedVar {
+ public:
+ // Does not take ownerships of arguments.
+ ScopedVar(Vars* vars, StringPiece name, Var* var);
+ ~ScopedVar();
+
+ private:
+ Vars* vars_;
+ Var* orig_;
+ Vars::iterator iter_;
+};
+
#endif // VAR_H_