[C++] Let target specific variable have its own scope
diff --git a/dep.cc b/dep.cc
index 7b326f8..c35df36 100644
--- a/dep.cc
+++ b/dep.cc
@@ -19,6 +19,7 @@
 #include <unordered_map>
 #include <unordered_set>
 
+#include "eval.h"
 #include "fileutil.h"
 #include "log.h"
 #include "rule.h"
@@ -40,16 +41,16 @@
       has_rule(false),
       is_order_only(false),
       is_phony(p),
-      target_specific_vars(NULL) {
+      rule_vars(NULL) {
   g_dep_node_pool->push_back(this);
 }
 
 class DepBuilder {
  public:
-  DepBuilder(const vector<shared_ptr<Rule>>& rules,
-             const Vars& vars,
+  DepBuilder(Evaluator* ev,
+             const vector<shared_ptr<Rule>>& rules,
              const unordered_map<StringPiece, Vars*>& rule_vars)
-      : vars_(vars),
+      : ev_(ev),
         rule_vars_(rule_vars),
         first_rule_(NULL) {
     PopulateRules(rules);
@@ -71,9 +72,12 @@
     // TODO: LogStats?
 
     for (StringPiece target : targets) {
-      unique_ptr<Vars> tsvs(new Vars);
-      DepNode* n = BuildPlan(target, "", tsvs.get());
+      cur_rule_vars_.reset(new Vars);
+      ev_->set_current_scope(cur_rule_vars_.get());
+      DepNode* n = BuildPlan(target, "");
       nodes->push_back(n);
+      ev_->set_current_scope(NULL);
+      cur_rule_vars_.reset(NULL);
     }
   }
 
@@ -275,7 +279,7 @@
     return rule.get();
   }
 
-  DepNode* BuildPlan(StringPiece output, StringPiece needed_by, Vars* tsvs) {
+  DepNode* BuildPlan(StringPiece output, StringPiece needed_by) {
     LOG("BuildPlan: %s for %s",
         output.as_string().c_str(),
         needed_by.as_string().c_str());
@@ -294,7 +298,33 @@
       return n;
     }
 
-    // TODO: Handle TSVs
+    vector<unique_ptr<ScopedVar>> sv;
+    if (vars) {
+      for (const auto& p : *vars) {
+        StringPiece name = p.first;
+        RuleVar* var = reinterpret_cast<RuleVar*>(p.second);
+        CHECK(var);
+        Var* new_var = var->v();
+        if (var->op() == AssignOp::PLUS_EQ) {
+          Var* old_var = ev_->LookupVar(name);
+          if (old_var->IsDefined()) {
+            // TODO: This would be incorrect and has a leak.
+            shared_ptr<string> s = make_shared<string>();
+            old_var->Eval(ev_, s.get());
+            *s += ' ';
+            new_var->Eval(ev_, s.get());
+            new_var = new SimpleVar(s, old_var->Origin());
+          }
+        } else if (var->op() == AssignOp::QUESTION_EQ) {
+          Var* old_var = ev_->LookupVar(name);
+          if (old_var->IsDefined()) {
+            continue;
+          }
+        }
+        sv.push_back(move(unique_ptr<ScopedVar>(
+            new ScopedVar(cur_rule_vars_.get(), name, new_var))));
+      }
+    }
 
     for (StringPiece input : rule->inputs) {
       if (rule->output_patterns.size() > 0) {
@@ -309,20 +339,33 @@
       }
 
       n->actual_inputs.push_back(input);
-      DepNode* c = BuildPlan(input, output, tsvs);
+      DepNode* c = BuildPlan(input, output);
       n->deps.push_back(c);
     }
 
     // TODO: order only
+
     n->has_rule = true;
     n->cmds = rule->cmds;
+    if (cur_rule_vars_->empty()) {
+      n->rule_vars = NULL;
+    } else {
+      n->rule_vars = new Vars;
+      for (auto p : *cur_rule_vars_) {
+        n->rule_vars->insert(p);
+      }
+    }
+    n->loc = rule->loc;
+    if (!rule->cmds.empty() && rule->cmd_lineno)
+      n->loc.lineno = rule->cmd_lineno;
 
     return n;
   }
 
+  Evaluator* ev_;
   unordered_map<StringPiece, shared_ptr<Rule>> rules_;
-  const Vars& vars_;
   const unordered_map<StringPiece, Vars*>& rule_vars_;
+  unique_ptr<Vars> cur_rule_vars_;
 
   vector<shared_ptr<Rule>> implicit_rules_;   // pattern=%. no prefix,suffix.
   //vector<Rule*> iprefix_rules_;   // pattern=prefix%..  may have suffix
@@ -335,12 +378,12 @@
   unordered_set<StringPiece> phony_;
 };
 
-void MakeDep(const vector<shared_ptr<Rule>>& rules,
-             const Vars& vars,
+void MakeDep(Evaluator* ev,
+             const vector<shared_ptr<Rule>>& rules,
              const unordered_map<StringPiece, Vars*>& rule_vars,
              const vector<StringPiece>& targets,
              vector<DepNode*>* nodes) {
-  DepBuilder db(rules, vars, rule_vars);
+  DepBuilder db(ev, rules, rule_vars);
   db.Build(targets, nodes);
 }
 
diff --git a/dep.h b/dep.h
index 8dbda6a..934d4fe 100644
--- a/dep.h
+++ b/dep.h
@@ -23,6 +23,7 @@
 #include "loc.h"
 #include "string_piece.h"
 
+class Evaluator;
 class Rule;
 class Value;
 class Vars;
@@ -38,15 +39,15 @@
   bool is_order_only;
   bool is_phony;
   vector<StringPiece> actual_inputs;
-  Vars* target_specific_vars;
+  Vars* rule_vars;
   Loc loc;
 };
 
 void InitDepNodePool();
 void QuitDepNodePool();
 
-void MakeDep(const vector<shared_ptr<Rule>>& rules,
-             const Vars& vars,
+void MakeDep(Evaluator* ev,
+             const vector<shared_ptr<Rule>>& rules,
              const unordered_map<StringPiece, Vars*>& rule_vars,
              const vector<StringPiece>& targets,
              vector<DepNode*>* nodes);
diff --git a/eval.cc b/eval.cc
index 5c01634..98912f6 100644
--- a/eval.cc
+++ b/eval.cc
@@ -40,14 +40,14 @@
 }
 
 Evaluator::~Evaluator() {
-  delete vars_;
+  // delete vars_;
   // for (auto p : rule_vars) {
   //   delete p.second;
   // }
 }
 
-void Evaluator::DoAssign(StringPiece lhs, Value* rhs_v, StringPiece orig_rhs,
-                         AssignOp op) {
+Var* Evaluator::EvalRHS(StringPiece lhs, Value* rhs_v, StringPiece orig_rhs,
+                        AssignOp op) {
   const char* origin = is_bootstrap_ ? "default" : "file";
 
   Var* rhs = NULL;
@@ -83,15 +83,19 @@
   }
 
   LOG("Assign: %.*s=%s", SPF(lhs), rhs->DebugString().c_str());
-  if (needs_assign)
-    vars_->Assign(lhs, rhs);
+  if (needs_assign) {
+    return rhs;
+  }
+  return NULL;
 }
 
 void Evaluator::EvalAssign(const AssignAST* ast) {
   loc_ = ast->loc();
   last_rule_ = NULL;
   StringPiece lhs = Intern(*ast->lhs->Eval(this));
-  DoAssign(lhs, ast->rhs, ast->orig_rhs, ast->op);
+  Var* rhs = EvalRHS(lhs, ast->rhs, ast->orig_rhs, ast->op);
+  if (rhs)
+    vars_->Assign(lhs, rhs);
 }
 
 void Evaluator::EvalRule(const RuleAST* ast) {
@@ -104,7 +108,7 @@
     return;
 
   Rule* rule;
-  RuleVar rule_var;
+  RuleVarAssignment rule_var;
   ParseRule(loc_, *expr, ast->term == '=', &rule, &rule_var);
 
   if (rule) {
@@ -131,8 +135,10 @@
     }
 
     current_scope_ = p.first->second;
-    DoAssign(Intern(rule_var.lhs), rhs, STRING_PIECE("*TODO*"),
-             rule_var.op);
+    StringPiece lhs = Intern(rule_var.lhs);
+    Var* rhs_var = EvalRHS(lhs, rhs, STRING_PIECE("*TODO*"), rule_var.op);
+    if (rhs_var)
+      current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
     current_scope_ = NULL;
   }
 }
@@ -255,15 +261,6 @@
   return in_vars_->Lookup(name);
 }
 
-EvalResult* Evaluator::GetEvalResult() {
-  EvalResult* er = new EvalResult;
-  er->rules.swap(rules_);
-  er->vars = vars_;
-  vars_ = NULL;
-  er->rule_vars.swap(rule_vars_);
-  return er;
-}
-
 void Evaluator::Error(const string& msg) {
   ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
 }
diff --git a/eval.h b/eval.h
index a9be28f..70d5466 100644
--- a/eval.h
+++ b/eval.h
@@ -55,18 +55,22 @@
   // For target specific variables.
   Var* LookupVarInCurrentScope(StringPiece name);
 
-  EvalResult* GetEvalResult();
-
   const Loc& loc() const { return loc_; }
 
+  const vector<shared_ptr<Rule>>& rules() const { return rules_; }
+  const unordered_map<StringPiece, Vars*>& rule_vars() const {
+    return rule_vars_;
+  }
   Vars* mutable_vars() { return vars_; }
 
   void Error(const string& msg);
 
   void set_is_bootstrap(bool b) { is_bootstrap_ = b; }
 
+  void set_current_scope(Vars* v) { current_scope_ = v; }
+
  private:
-  void DoAssign(StringPiece lhs, Value* rhs, StringPiece orig_rhs, AssignOp op);
+  Var* EvalRHS(StringPiece lhs, Value* rhs, StringPiece orig_rhs, AssignOp op);
   void DoInclude(const char* fname, bool should_exist);
 
   const Vars* in_vars_;
diff --git a/exec.cc b/exec.cc
index 9cab1f8..bdfa2fd 100644
--- a/exec.cc
+++ b/exec.cc
@@ -45,7 +45,6 @@
     return "automatic";
   }
 
-  virtual bool IsDefined() const override { CHECK(false); }
   virtual void AppendVar(Evaluator*, Value*) override { CHECK(false); }
 
   virtual StringPiece String() const override {
@@ -116,9 +115,9 @@
 
 class Executor {
  public:
-  explicit Executor(Vars* vars)
-      : vars_(vars),
-        ev_(new Evaluator(vars_)) {
+  explicit Executor(Evaluator* ev)
+      : ev_(ev) {
+    Vars* vars = ev_->mutable_vars();
 #define INSERT_AUTO_VAR(name, sym) do {                                 \
       Var* v = new name(this, sym);                                     \
       (*vars)[STRING_PIECE(sym)] = v;                                   \
@@ -165,9 +164,10 @@
   }
 
   void CreateRunners(DepNode* n, vector<Runner*>* runners) {
+    ev_->set_current_scope(n->rule_vars);
     current_dep_node_ = n;
     for (Value* v : n->cmds) {
-      shared_ptr<string> cmd = v->Eval(ev_.get());
+      shared_ptr<string> cmd = v->Eval(ev_);
       while (true) {
         size_t index = cmd->find('\n');
         if (index == string::npos)
@@ -185,13 +185,14 @@
       runners->push_back(runner);
       continue;
     }
+    ev_->set_current_scope(NULL);
   }
 
   const DepNode* current_dep_node() const { return current_dep_node_; }
 
  private:
   Vars* vars_;
-  unique_ptr<Evaluator> ev_;
+  Evaluator* ev_;
   unordered_map<StringPiece, bool> done_;
   DepNode* current_dep_node_;
 };
@@ -246,8 +247,8 @@
 
 }  // namespace
 
-void Exec(const vector<DepNode*>& roots, Vars* vars) {
-  unique_ptr<Executor> executor(new Executor(vars));
+void Exec(const vector<DepNode*>& roots, Evaluator* ev) {
+  unique_ptr<Executor> executor(new Executor(ev));
   for (DepNode* root : roots) {
     executor->ExecNode(root, NULL);
   }
diff --git a/exec.h b/exec.h
index fbbd75e..94ff691 100644
--- a/exec.h
+++ b/exec.h
@@ -20,8 +20,8 @@
 using namespace std;
 
 class DepNode;
-class Vars;
+class Evaluator;
 
-void Exec(const vector<DepNode*>& roots, Vars* vars);
+void Exec(const vector<DepNode*>& roots, Evaluator* ev);
 
 #endif  // EXEC_H_
diff --git a/main.cc b/main.cc
index 1820ae0..f8c05c7 100644
--- a/main.cc
+++ b/main.cc
@@ -158,20 +158,13 @@
     ast->Eval(ev);
   }
 
-  EvalResult* er = ev->GetEvalResult();
-  for (auto p : *er->vars) {
-    vars->Assign(p.first, p.second);
-  }
-  er->vars->clear();
-
   vector<DepNode*> nodes;
-  MakeDep(er->rules, *vars, er->rule_vars, targets, &nodes);
+  MakeDep(ev, ev->rules(), ev->rule_vars(), targets, &nodes);
 
-  Exec(nodes, vars);
+  Exec(nodes, ev);
 
   for (AST* ast : bootstrap_asts)
     delete ast;
-  delete er;
   delete ev;
   delete vars;
   delete cache_mgr;
diff --git a/rule.cc b/rule.cc
index fe0c2a8..d98a409 100644
--- a/rule.cc
+++ b/rule.cc
@@ -60,7 +60,7 @@
 }
 
 void ParseRule(Loc& loc, StringPiece line, bool is_assign,
-               Rule** out_rule, RuleVar* rule_var) {
+               Rule** out_rule, RuleVarAssignment* rule_var) {
   size_t index = line.find(':');
   if (index == string::npos) {
     ERROR("%s:%d: *** missing separator.", LOCF(loc));
diff --git a/rule.h b/rule.h
index 323d96c..42dba37 100644
--- a/rule.h
+++ b/rule.h
@@ -24,7 +24,6 @@
 
 using namespace std;
 
-class Evaluator;
 class Value;
 
 class Rule {
@@ -51,15 +50,15 @@
   }
 };
 
-struct RuleVar {
+struct RuleVarAssignment {
   vector<StringPiece> outputs;
   StringPiece lhs;
   StringPiece rhs;
   AssignOp op;
 };
 
-// If |rule| is not NULL, rule_var is filled.
+// If |rule| is not NULL, |rule_var| is filled.
 void ParseRule(Loc& loc, StringPiece line, bool is_assign,
-               Rule** rule, RuleVar* rule_var);
+               Rule** rule, RuleVarAssignment* rule_var);
 
 #endif  // RULE_H_
diff --git a/var.h b/var.h
index fadd155..ee6b32c 100644
--- a/var.h
+++ b/var.h
@@ -19,6 +19,7 @@
 #include <string>
 #include <unordered_map>
 
+#include "ast.h"
 #include "string_piece.h"
 #include "value.h"
 
@@ -118,6 +119,44 @@
 
 extern UndefinedVar* kUndefined;
 
+class RuleVar : public Var {
+ public:
+  RuleVar(Var* v, AssignOp op)
+      : v_(v), op_(op) {}
+  virtual ~RuleVar() {
+    delete v_;
+  }
+
+  virtual const char* Flavor() const {
+    return v_->Flavor();
+  }
+  virtual const char* Origin() const {
+    return v_->Origin();
+  }
+  virtual bool IsDefined() const {
+    return v_->IsDefined();
+  }
+  virtual void Eval(Evaluator* ev, string* s) const {
+    v_->Eval(ev, s);
+  }
+  virtual void AppendVar(Evaluator* ev, Value* v) {
+    v_->AppendVar(ev, v);
+  }
+  virtual StringPiece String() const override {
+    return v_->String();
+  }
+  virtual string DebugString() const override {
+    return v_->DebugString();
+  }
+
+  Var* v() const { return v_; }
+  AssignOp op() const { return op_; }
+
+ private:
+  Var* v_;
+  AssignOp op_;
+};
+
 class Vars : public unordered_map<StringPiece, Var*> {
  public:
   ~Vars();