aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji@gmail.com>2015-06-23 16:51:07 +0900
committerShinichiro Hamaji <shinichiro.hamaji@gmail.com>2015-06-23 20:27:40 +0900
commitffc52c3c5bed9d696d0296c1674d2e75460bef40 (patch)
tree7364bea9749e3de9fcf308b9c4b825e7425b881a
parent9042b995db7f0b9499e0c3087269505e5e817a58 (diff)
downloadkati-ffc52c3c5bed9d696d0296c1674d2e75460bef40.tar.gz
[C++] Let target specific variable have its own scope
-rw-r--r--dep.cc69
-rw-r--r--dep.h7
-rw-r--r--eval.cc33
-rw-r--r--eval.h10
-rw-r--r--exec.cc17
-rw-r--r--exec.h4
-rw-r--r--main.cc11
-rw-r--r--rule.cc2
-rw-r--r--rule.h7
-rw-r--r--var.h39
10 files changed, 138 insertions, 61 deletions
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 @@ DepNode::DepNode(StringPiece o, bool p)
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 @@ class DepBuilder {
// 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 @@ class DepBuilder {
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 @@ class DepBuilder {
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 @@ class DepBuilder {
}
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 @@ class DepBuilder {
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 @@ struct DepNode {
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(const Vars* vars)
}
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 @@ void Evaluator::DoAssign(StringPiece lhs, Value* rhs_v, StringPiece orig_rhs,
}
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 @@ void Evaluator::EvalRule(const RuleAST* ast) {
return;
Rule* rule;
- RuleVar rule_var;
+ RuleVarAssignment rule_var;
ParseRule(loc_, *expr, ast->term == '=', &rule, &rule_var);
if (rule) {
@@ -131,8 +135,10 @@ void Evaluator::EvalRule(const RuleAST* ast) {
}
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 @@ Var* Evaluator::LookupVarInCurrentScope(StringPiece name) {
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 @@ class Evaluator {
// 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 @@ class AutoVar : public Var {
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 @@ struct Runner {
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 @@ class Executor {
}
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 @@ class Executor {
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 @@ void AutoSuffixFVar::Eval(Evaluator* ev, string* s) const {
} // 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 @@ static int Run(const vector<StringPiece>& targets,
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 @@ Rule::Rule()
}
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 @@ class Rule {
}
};
-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 @@ class UndefinedVar : public Var {
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();