• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 Google Inc. All rights reserved
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // +build ignore
16 
17 #include "var.h"
18 
19 #include "eval.h"
20 #include "expr.h"
21 #include "log.h"
22 
23 unordered_map<const Var*, string> Var::diagnostic_messages_;
24 
GetOriginStr(VarOrigin origin)25 const char* GetOriginStr(VarOrigin origin) {
26   switch (origin) {
27     case VarOrigin::UNDEFINED:
28       return "undefined";
29     case VarOrigin::DEFAULT:
30       return "default";
31     case VarOrigin::ENVIRONMENT:
32       return "environment";
33     case VarOrigin::ENVIRONMENT_OVERRIDE:
34       return "environment override";
35     case VarOrigin::FILE:
36       return "file";
37     case VarOrigin::COMMAND_LINE:
38       return "command line";
39     case VarOrigin::OVERRIDE:
40       return "override";
41     case VarOrigin::AUTOMATIC:
42       return "automatic";
43   }
44   CHECK(false);
45   return "*** broken origin ***";
46 }
47 
Var()48 Var::Var() : Var(VarOrigin::UNDEFINED) {}
49 
Var(VarOrigin origin)50 Var::Var(VarOrigin origin)
51     : origin_(origin), readonly_(false), deprecated_(false), obsolete_(false) {}
52 
~Var()53 Var::~Var() {
54   diagnostic_messages_.erase(this);
55 }
56 
AppendVar(Evaluator *,Value *)57 void Var::AppendVar(Evaluator*, Value*) {
58   CHECK(false);
59 }
60 
SetDeprecated(const StringPiece & msg)61 void Var::SetDeprecated(const StringPiece& msg) {
62   deprecated_ = true;
63   diagnostic_messages_[this] = msg.as_string();
64 }
65 
SetObsolete(const StringPiece & msg)66 void Var::SetObsolete(const StringPiece& msg) {
67   obsolete_ = true;
68   diagnostic_messages_[this] = msg.as_string();
69 }
70 
Used(Evaluator * ev,const Symbol & sym) const71 void Var::Used(Evaluator* ev, const Symbol& sym) const {
72   if (obsolete_) {
73     ev->Error(StringPrintf("*** %s is obsolete%s.", sym.c_str(),
74                            diagnostic_message_text()));
75   } else if (deprecated_) {
76     WARN_LOC(ev->loc(), "%s has been deprecated%s.", sym.c_str(),
77              diagnostic_message_text());
78   }
79 }
80 
diagnostic_message_text() const81 const char* Var::diagnostic_message_text() const {
82   auto it = diagnostic_messages_.find(this);
83   return it == diagnostic_messages_.end() ? "" : it->second.c_str();
84 }
85 
DeprecatedMessage() const86 const string& Var::DeprecatedMessage() const {
87   static const string empty_string;
88   auto it = diagnostic_messages_.find(this);
89   return it == diagnostic_messages_.end() ? empty_string : it->second;
90 }
91 
Undefined()92 Var* Var::Undefined() {
93   static Var* undefined_var;
94   if (!undefined_var) {
95     undefined_var = new UndefinedVar();
96   }
97   return undefined_var;
98 }
99 
SimpleVar(VarOrigin origin)100 SimpleVar::SimpleVar(VarOrigin origin) : Var(origin) {}
101 
SimpleVar(const string & v,VarOrigin origin)102 SimpleVar::SimpleVar(const string& v, VarOrigin origin) : Var(origin), v_(v) {}
103 
SimpleVar(VarOrigin origin,Evaluator * ev,Value * v)104 SimpleVar::SimpleVar(VarOrigin origin, Evaluator* ev, Value* v) : Var(origin) {
105   v->Eval(ev, &v_);
106 }
107 
Eval(Evaluator * ev,string * s) const108 void SimpleVar::Eval(Evaluator* ev, string* s) const {
109   ev->CheckStack();
110   *s += v_;
111 }
112 
AppendVar(Evaluator * ev,Value * v)113 void SimpleVar::AppendVar(Evaluator* ev, Value* v) {
114   string buf;
115   v->Eval(ev, &buf);
116   v_.push_back(' ');
117   v_ += buf;
118 }
119 
String() const120 StringPiece SimpleVar::String() const {
121   return v_;
122 }
123 
DebugString() const124 string SimpleVar::DebugString() const {
125   return v_;
126 }
127 
RecursiveVar(Value * v,VarOrigin origin,StringPiece orig)128 RecursiveVar::RecursiveVar(Value* v, VarOrigin origin, StringPiece orig)
129     : Var(origin), v_(v), orig_(orig) {}
130 
Eval(Evaluator * ev,string * s) const131 void RecursiveVar::Eval(Evaluator* ev, string* s) const {
132   ev->CheckStack();
133   v_->Eval(ev, s);
134 }
135 
AppendVar(Evaluator * ev,Value * v)136 void RecursiveVar::AppendVar(Evaluator* ev, Value* v) {
137   ev->CheckStack();
138   v_ = Value::NewExpr(v_, Value::NewLiteral(" "), v);
139 }
140 
String() const141 StringPiece RecursiveVar::String() const {
142   return orig_;
143 }
144 
DebugString() const145 string RecursiveVar::DebugString() const {
146   return Value::DebugString(v_);
147 }
148 
UndefinedVar()149 UndefinedVar::UndefinedVar() {}
150 
Eval(Evaluator *,string *) const151 void UndefinedVar::Eval(Evaluator*, string*) const {
152   // Nothing to do.
153 }
154 
String() const155 StringPiece UndefinedVar::String() const {
156   return StringPiece("");
157 }
158 
DebugString() const159 string UndefinedVar::DebugString() const {
160   return "*undefined*";
161 }
162 
~Vars()163 Vars::~Vars() {
164   for (auto p : *this) {
165     delete p.second;
166   }
167 }
168 
add_used_env_vars(Symbol v)169 void Vars::add_used_env_vars(Symbol v) {
170   used_env_vars_.insert(v);
171 }
172 
Lookup(Symbol name) const173 Var* Vars::Lookup(Symbol name) const {
174   auto found = find(name);
175   if (found == end())
176     return Var::Undefined();
177   Var* v = found->second;
178   if (v->Origin() == VarOrigin::ENVIRONMENT ||
179       v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
180     used_env_vars_.insert(name);
181   }
182   return v;
183 }
184 
Peek(Symbol name) const185 Var* Vars::Peek(Symbol name) const {
186   auto found = find(name);
187   return found == end() ? Var::Undefined() : found->second;
188 }
189 
Assign(Symbol name,Var * v,bool * readonly)190 void Vars::Assign(Symbol name, Var* v, bool* readonly) {
191   *readonly = false;
192   auto p = emplace(name, v);
193   if (!p.second) {
194     Var* orig = p.first->second;
195     if (orig->ReadOnly()) {
196       *readonly = true;
197       return;
198     }
199     if (orig->Origin() == VarOrigin::OVERRIDE ||
200         orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
201       return;
202     }
203     if (orig->Origin() == VarOrigin::AUTOMATIC) {
204       ERROR("overriding automatic variable is not implemented yet");
205     }
206     if (orig->IsDefined())
207       delete p.first->second;
208     p.first->second = v;
209   }
210 }
211 
212 SymbolSet Vars::used_env_vars_;
213 
ScopedVar(Vars * vars,Symbol name,Var * var)214 ScopedVar::ScopedVar(Vars* vars, Symbol name, Var* var)
215     : vars_(vars), orig_(NULL) {
216   auto p = vars->emplace(name, var);
217   iter_ = p.first;
218   if (!p.second) {
219     orig_ = iter_->second;
220     iter_->second = var;
221   }
222 }
223 
~ScopedVar()224 ScopedVar::~ScopedVar() {
225   if (orig_) {
226     iter_->second = orig_;
227   } else {
228     vars_->erase(iter_);
229   }
230 }
231