diff options
author | Shinichiro Hamaji <shinichiro.hamaji@gmail.com> | 2015-06-23 16:51:07 +0900 |
---|---|---|
committer | Shinichiro Hamaji <shinichiro.hamaji@gmail.com> | 2015-06-23 20:27:40 +0900 |
commit | ffc52c3c5bed9d696d0296c1674d2e75460bef40 (patch) | |
tree | 7364bea9749e3de9fcf308b9c4b825e7425b881a | |
parent | 9042b995db7f0b9499e0c3087269505e5e817a58 (diff) | |
download | kati-ffc52c3c5bed9d696d0296c1674d2e75460bef40.tar.gz |
[C++] Let target specific variable have its own scope
-rw-r--r-- | dep.cc | 69 | ||||
-rw-r--r-- | dep.h | 7 | ||||
-rw-r--r-- | eval.cc | 33 | ||||
-rw-r--r-- | eval.h | 10 | ||||
-rw-r--r-- | exec.cc | 17 | ||||
-rw-r--r-- | exec.h | 4 | ||||
-rw-r--r-- | main.cc | 11 | ||||
-rw-r--r-- | rule.cc | 2 | ||||
-rw-r--r-- | rule.h | 7 | ||||
-rw-r--r-- | var.h | 39 |
10 files changed, 138 insertions, 61 deletions
@@ -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); } @@ -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); @@ -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()); } @@ -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_; @@ -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); } @@ -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_ @@ -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; @@ -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)); @@ -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_ @@ -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(); |