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 #ifndef VAR_H_ 16 #define VAR_H_ 17 18 #include <memory> 19 #include <string> 20 #include <unordered_map> 21 #include <unordered_set> 22 23 #include "eval.h" 24 #include "expr.h" 25 #include "log.h" 26 #include "stmt.h" 27 #include "string_piece.h" 28 #include "symtab.h" 29 30 using namespace std; 31 32 class Evaluator; 33 class Value; 34 35 enum struct VarOrigin { 36 UNDEFINED, 37 DEFAULT, 38 ENVIRONMENT, 39 ENVIRONMENT_OVERRIDE, 40 FILE, 41 COMMAND_LINE, 42 OVERRIDE, 43 AUTOMATIC, 44 }; 45 46 const char* GetOriginStr(VarOrigin origin); 47 48 class Var : public Evaluable { 49 public: 50 virtual ~Var(); 51 52 virtual const char* Flavor() const = 0; 53 virtual VarOrigin Origin() const = 0; IsDefined()54 virtual bool IsDefined() const { return true; } 55 56 virtual void AppendVar(Evaluator* ev, Value* v); 57 58 virtual StringPiece String() const = 0; 59 60 virtual string DebugString() const = 0; 61 ReadOnly()62 bool ReadOnly() const { return readonly_; } SetReadOnly()63 void SetReadOnly() { readonly_ = true; } 64 Deprecated()65 bool Deprecated() const { return message_ && !error_; } SetDeprecated(StringPiece msg)66 void SetDeprecated(StringPiece msg) { 67 message_.reset(new string(msg.as_string())); 68 } 69 Obsolete()70 bool Obsolete() const { return error_; } SetObsolete(StringPiece msg)71 void SetObsolete(StringPiece msg) { 72 message_.reset(new string(msg.as_string())); 73 error_ = true; 74 } 75 DeprecatedMessage()76 const string& DeprecatedMessage() const { return *message_; } 77 78 // This variable was used (either written or read from) Used(Evaluator * ev,const Symbol & sym)79 void Used(Evaluator* ev, const Symbol& sym) const { 80 if (!message_) { 81 return; 82 } 83 84 if (error_) { 85 ev->Error(StringPrintf("*** %s is obsolete%s.", sym.c_str(), 86 message_->c_str())); 87 } else { 88 WARN_LOC(ev->loc(), "%s has been deprecated%s.", sym.c_str(), 89 message_->c_str()); 90 } 91 } 92 93 protected: 94 Var(); 95 96 private: 97 bool readonly_; 98 unique_ptr<string> message_; 99 bool error_; 100 }; 101 102 class SimpleVar : public Var { 103 public: 104 explicit SimpleVar(VarOrigin origin); 105 SimpleVar(const string& v, VarOrigin origin); 106 Flavor()107 virtual const char* Flavor() const override { return "simple"; } Origin()108 virtual VarOrigin Origin() const override { return origin_; } 109 110 virtual void Eval(Evaluator* ev, string* s) const override; 111 112 virtual void AppendVar(Evaluator* ev, Value* v) override; 113 114 virtual StringPiece String() const override; 115 116 virtual string DebugString() const override; 117 mutable_value()118 string* mutable_value() { return &v_; } 119 120 private: 121 string v_; 122 VarOrigin origin_; 123 }; 124 125 class RecursiveVar : public Var { 126 public: 127 RecursiveVar(Value* v, VarOrigin origin, StringPiece orig); 128 Flavor()129 virtual const char* Flavor() const override { return "recursive"; } Origin()130 virtual VarOrigin Origin() const override { return origin_; } 131 132 virtual void Eval(Evaluator* ev, string* s) const override; 133 134 virtual void AppendVar(Evaluator* ev, Value* v) override; 135 136 virtual StringPiece String() const override; 137 138 virtual string DebugString() const override; 139 140 private: 141 Value* v_; 142 VarOrigin origin_; 143 StringPiece orig_; 144 }; 145 146 class UndefinedVar : public Var { 147 public: 148 UndefinedVar(); 149 Flavor()150 virtual const char* Flavor() const override { return "undefined"; } Origin()151 virtual VarOrigin Origin() const override { return VarOrigin::UNDEFINED; } IsDefined()152 virtual bool IsDefined() const override { return false; } 153 154 virtual void Eval(Evaluator* ev, string* s) const override; 155 156 virtual StringPiece String() const override; 157 158 virtual string DebugString() const override; 159 }; 160 161 extern UndefinedVar* kUndefined; 162 163 class RuleVar : public Var { 164 public: RuleVar(Var * v,AssignOp op)165 RuleVar(Var* v, AssignOp op) : v_(v), op_(op) {} ~RuleVar()166 virtual ~RuleVar() { delete v_; } 167 Flavor()168 virtual const char* Flavor() const override { return v_->Flavor(); } Origin()169 virtual VarOrigin Origin() const override { return v_->Origin(); } IsDefined()170 virtual bool IsDefined() const override { return v_->IsDefined(); } Eval(Evaluator * ev,string * s)171 virtual void Eval(Evaluator* ev, string* s) const override { 172 v_->Eval(ev, s); 173 } AppendVar(Evaluator * ev,Value * v)174 virtual void AppendVar(Evaluator* ev, Value* v) override { 175 v_->AppendVar(ev, v); 176 } String()177 virtual StringPiece String() const override { return v_->String(); } DebugString()178 virtual string DebugString() const override { return v_->DebugString(); } 179 v()180 Var* v() const { return v_; } op()181 AssignOp op() const { return op_; } 182 183 private: 184 Var* v_; 185 AssignOp op_; 186 }; 187 188 class Vars : public unordered_map<Symbol, Var*> { 189 public: 190 ~Vars(); 191 192 Var* Lookup(Symbol name) const; 193 Var* Peek(Symbol name) const; 194 195 void Assign(Symbol name, Var* v, bool* readonly); 196 197 static void add_used_env_vars(Symbol v); 198 used_env_vars()199 static const unordered_set<Symbol>& used_env_vars() { return used_env_vars_; } 200 201 private: 202 static unordered_set<Symbol> used_env_vars_; 203 }; 204 205 class ScopedVar { 206 public: 207 // Does not take ownerships of arguments. 208 ScopedVar(Vars* vars, Symbol name, Var* var); 209 ~ScopedVar(); 210 211 private: 212 Vars* vars_; 213 Var* orig_; 214 Vars::iterator iter_; 215 }; 216 217 #endif // VAR_H_ 218