aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji@gmail.com>2016-02-18 18:18:54 +0900
committerShinichiro Hamaji <shinichiro.hamaji@gmail.com>2016-02-22 16:19:42 +0900
commitc9b9e5eea8b477a103cdec951ef2a299f9cd49ba (patch)
treee28f4e11d2e0e15a01082c10f05038f67d298946
parenta67fba3bf217ece75b66cb9adb6539e9d098ce9c (diff)
downloadkati-c9b9e5eea8b477a103cdec951ef2a299f9cd49ba.tar.gz
[C++] Associate global variables with Symbols directly
-rw-r--r--command.cc7
-rw-r--r--dep.cc3
-rw-r--r--eval.cc9
-rw-r--r--eval.h4
-rw-r--r--func.cc10
-rw-r--r--main.cc21
-rw-r--r--symtab.cc49
-rw-r--r--symtab.h14
-rw-r--r--var.cc4
-rw-r--r--var.h2
10 files changed, 91 insertions, 32 deletions
diff --git a/command.cc b/command.cc
index ac7fadd..f75a8a0 100644
--- a/command.cc
+++ b/command.cc
@@ -171,12 +171,11 @@ void ParseCommandPrefixes(StringPiece* s, bool* echo, bool* ignore_error) {
CommandEvaluator::CommandEvaluator(Evaluator* ev)
: ev_(ev) {
- Vars* vars = ev_->mutable_vars();
#define INSERT_AUTO_VAR(name, sym) do { \
Var* v = new name(this, sym); \
- (*vars)[Intern(sym)] = v; \
- (*vars)[Intern(sym"D")] = new AutoSuffixDVar(this, sym"D", v); \
- (*vars)[Intern(sym"F")] = new AutoSuffixFVar(this, sym"F", v); \
+ Intern(sym).SetGlobalVar(v); \
+ Intern(sym"D").SetGlobalVar(new AutoSuffixDVar(this, sym"D", v)); \
+ Intern(sym"F").SetGlobalVar(new AutoSuffixFVar(this, sym"F", v)); \
} while (0)
INSERT_AUTO_VAR(AutoAtVar, "@");
INSERT_AUTO_VAR(AutoLessVar, "<");
diff --git a/dep.cc b/dep.cc
index 57b322c..da209c7 100644
--- a/dep.cc
+++ b/dep.cc
@@ -244,7 +244,8 @@ class DepBuilder {
depfile_var_name_(Intern(".KATI_DEPFILE")) {
ScopedTimeReporter tr("make dep (populate)");
PopulateRules(rules);
- LOG_STAT("%zu variables", ev->mutable_vars()->size());
+ // TODO?
+ //LOG_STAT("%zu variables", ev->mutable_vars()->size());
LOG_STAT("%zu explicit rules", rules_.size());
LOG_STAT("%zu implicit rules", implicit_rules_->size());
LOG_STAT("%zu suffix rules", suffix_rules_.size());
diff --git a/eval.cc b/eval.cc
index be4bb34..6322fc1 100644
--- a/eval.cc
+++ b/eval.cc
@@ -30,9 +30,8 @@
#include "symtab.h"
#include "var.h"
-Evaluator::Evaluator(const Vars* vars)
- : vars_(new Vars(*vars)),
- last_rule_(NULL),
+Evaluator::Evaluator()
+ : last_rule_(NULL),
current_scope_(NULL),
avoid_io_(false),
eval_depth_(0) {
@@ -102,7 +101,7 @@ void Evaluator::EvalAssign(const AssignStmt* stmt) {
Var* rhs = EvalRHS(lhs, stmt->rhs, stmt->orig_rhs, stmt->op,
stmt->directive == AssignDirective::OVERRIDE);
if (rhs)
- vars_->Assign(lhs, rhs);
+ lhs.SetGlobalVar(rhs);
}
void Evaluator::EvalRule(const RuleStmt* stmt) {
@@ -284,7 +283,7 @@ void Evaluator::EvalExport(const ExportStmt* stmt) {
}
Var* Evaluator::LookupVarGlobal(Symbol name) {
- Var* v = vars_->Lookup(name);
+ Var* v = name.GetGlobalVar();
if (v->IsDefined())
return v;
used_undefined_vars_.insert(name);
diff --git a/eval.h b/eval.h
index cb03d5d..3eede2b 100644
--- a/eval.h
+++ b/eval.h
@@ -33,7 +33,7 @@ class Vars;
class Evaluator {
public:
- Evaluator(const Vars* vars);
+ Evaluator();
~Evaluator();
void EvalAssign(const AssignStmt* stmt);
@@ -56,7 +56,6 @@ class Evaluator {
const unordered_map<Symbol, Vars*>& rule_vars() const {
return rule_vars_;
}
- Vars* mutable_vars() { return vars_; }
const unordered_map<Symbol, bool>& exports() const { return exports_; }
void Error(const string& msg);
@@ -97,7 +96,6 @@ class Evaluator {
Var* LookupVarGlobal(Symbol name);
- Vars* vars_;
unordered_map<Symbol, Vars*> rule_vars_;
vector<const Rule*> rules_;
unordered_map<Symbol, bool> exports_;
diff --git a/func.cc b/func.cc
index 2ea8afa..876b274 100644
--- a/func.cc
+++ b/func.cc
@@ -595,7 +595,7 @@ void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
new SimpleVar(args[i]->Eval(ev), VarOrigin::AUTOMATIC));
av.push_back(move(s));
}
- vector<unique_ptr<ScopedVar>> sv;
+ vector<unique_ptr<ScopedGlobalVar>> sv;
for (size_t i = 1; ; i++) {
string s;
Symbol tmpvar_name_sym(Symbol::IsUninitialized{});
@@ -606,8 +606,7 @@ void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
tmpvar_name_sym = Intern(s);
}
if (i < args.size()) {
- sv.emplace_back(new ScopedVar(ev->mutable_vars(),
- tmpvar_name_sym, av[i-1].get()));
+ sv.emplace_back(new ScopedGlobalVar(tmpvar_name_sym, av[i-1].get()));
} else {
// We need to blank further automatic vars
Var *v = ev->LookupVar(tmpvar_name_sym);
@@ -615,8 +614,7 @@ void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
if (v->Origin() != VarOrigin::AUTOMATIC) break;
av.emplace_back(new SimpleVar("", VarOrigin::AUTOMATIC));
- sv.emplace_back(new ScopedVar(ev->mutable_vars(),
- tmpvar_name_sym, av[i-1].get()));
+ sv.emplace_back(new ScopedGlobalVar(tmpvar_name_sym, av[i-1].get()));
}
}
@@ -633,7 +631,7 @@ void ForeachFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
for (StringPiece tok : WordScanner(list)) {
unique_ptr<SimpleVar> v(new SimpleVar(
tok.as_string(), VarOrigin::AUTOMATIC));
- ScopedVar sv(ev->mutable_vars(), Intern(varname), v.get());
+ ScopedGlobalVar sv(Intern(varname), v.get());
ww.MaybeAddWhitespace();
args[2]->Eval(ev, s);
}
diff --git a/main.cc b/main.cc
index c732dda..2627bfd 100644
--- a/main.cc
+++ b/main.cc
@@ -105,13 +105,13 @@ static void ReadBootstrapMakefile(const vector<Symbol>& targets,
Parse(Intern(bootstrap).str(), Loc("*bootstrap*", 0), stmts);
}
-static void SetVar(StringPiece l, VarOrigin origin, Vars* vars) {
+static void SetVar(StringPiece l, VarOrigin origin) {
size_t found = l.find('=');
CHECK(found != string::npos);
Symbol lhs = Intern(l.substr(0, found));
StringPiece rhs = l.substr(found + 1);
- vars->Assign(lhs,
- new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
+ lhs.SetGlobalVar(
+ new RecursiveVar(NewLiteral(rhs.data()), origin, rhs.data()));
}
extern "C" char** environ;
@@ -138,14 +138,12 @@ static int Run(const vector<Symbol>& targets,
MakefileCacheManager* cache_mgr = NewMakefileCacheManager();
- Vars* vars = new Vars();
- vars->Assign(Intern("MAKEFILE_LIST"),
- new SimpleVar(StringPrintf(" %s", g_flags.makefile),
- VarOrigin::FILE));
+ Intern("MAKEFILE_LIST").SetGlobalVar(
+ new SimpleVar(StringPrintf(" %s", g_flags.makefile), VarOrigin::FILE));
for (char** p = environ; *p; p++) {
- SetVar(*p, VarOrigin::ENVIRONMENT, vars);
+ SetVar(*p, VarOrigin::ENVIRONMENT);
}
- Evaluator* ev = new Evaluator(vars);
+ Evaluator* ev = new Evaluator();
vector<Stmt*> bootstrap_asts;
ReadBootstrapMakefile(targets, &bootstrap_asts);
@@ -157,7 +155,7 @@ static int Run(const vector<Symbol>& targets,
ev->set_is_bootstrap(false);
for (StringPiece l : cl_vars) {
- SetVar(l, VarOrigin::COMMAND_LINE, ev->mutable_vars());
+ SetVar(l, VarOrigin::COMMAND_LINE);
}
{
@@ -210,9 +208,6 @@ static int Run(const vector<Symbol>& targets,
for (Stmt* stmt : bootstrap_asts)
delete stmt;
delete ev;
- // Each Var will be deleted by |ev|.
- vars->clear();
- delete vars;
delete cache_mgr;
return 0;
diff --git a/symtab.cc b/symtab.cc
index af0b620..fb81bfe 100644
--- a/symtab.cc
+++ b/symtab.cc
@@ -27,8 +27,18 @@
#include "log.h"
#include "strutil.h"
+#include "var.h"
+
+struct SymbolData {
+ SymbolData()
+ : gv(kUndefined) {
+ }
+
+ Var* gv;
+};
vector<string*>* g_symbols;
+static vector<SymbolData> g_symbol_data;
Symbol kEmptySym = Symbol(Symbol::IsUninitialized());
Symbol kShellSym = Symbol(Symbol::IsUninitialized());
@@ -37,6 +47,45 @@ Symbol::Symbol(int v)
: v_(v) {
}
+Var* Symbol::GetGlobalVar() const {
+ if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
+ g_symbol_data.resize(v_ + 1);
+ }
+ Var* v = g_symbol_data[v_].gv;
+ if (v->Origin() == VarOrigin::ENVIRONMENT ||
+ v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
+ Vars::add_used_env_vars(*this);
+ }
+ return v;
+}
+
+void Symbol::SetGlobalVar(Var* v) const {
+ if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
+ g_symbol_data.resize(v_ + 1);
+ }
+ Var* orig = g_symbol_data[v_].gv;
+ if (orig->Origin() == VarOrigin::OVERRIDE ||
+ orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
+ return;
+ }
+ if (orig->Origin() == VarOrigin::AUTOMATIC) {
+ ERROR("overriding automatic variable is not implemented yet");
+ }
+ if (orig->IsDefined())
+ delete orig;
+ g_symbol_data[v_].gv = v;
+}
+
+ScopedGlobalVar::ScopedGlobalVar(Symbol name, Var* var)
+ : name_(name), orig_(NULL) {
+ orig_ = name.GetGlobalVar();
+ g_symbol_data[name_.val()].gv = var;
+}
+
+ScopedGlobalVar::~ScopedGlobalVar() {
+ g_symbol_data[name_.val()].gv = orig_;
+}
+
class Symtab {
public:
Symtab() {
diff --git a/symtab.h b/symtab.h
index 9d8a120..d1de4e1 100644
--- a/symtab.h
+++ b/symtab.h
@@ -25,6 +25,7 @@ using namespace std;
extern vector<string*>* g_symbols;
class Symtab;
+class Var;
class Symbol {
public:
@@ -54,6 +55,9 @@ class Symbol {
bool IsValid() const { return v_ >= 0; }
+ Var* GetGlobalVar() const;
+ void SetGlobalVar(Var* v) const;
+
private:
explicit Symbol(int v);
@@ -62,6 +66,16 @@ class Symbol {
friend class Symtab;
};
+class ScopedGlobalVar {
+ public:
+ ScopedGlobalVar(Symbol name, Var* var);
+ ~ScopedGlobalVar();
+
+ private:
+ Symbol name_;
+ Var* orig_;
+};
+
inline bool operator==(const Symbol& x, const Symbol& y) {
return x.val() == y.val();
}
diff --git a/var.cc b/var.cc
index a5cde3e..73f542c 100644
--- a/var.cc
+++ b/var.cc
@@ -112,6 +112,10 @@ Vars::~Vars() {
}
}
+void Vars::add_used_env_vars(Symbol v) {
+ used_env_vars_.insert(v);
+}
+
Var* Vars::Lookup(Symbol name) const {
auto found = find(name);
if (found == end())
diff --git a/var.h b/var.h
index 5ba5fcb..5fc09fa 100644
--- a/var.h
+++ b/var.h
@@ -179,6 +179,8 @@ class Vars : public unordered_map<Symbol, Var*> {
void Assign(Symbol name, Var* v);
+ static void add_used_env_vars(Symbol v);
+
static const unordered_set<Symbol>& used_env_vars() {
return used_env_vars_;
}