Replace command buffer FlushSync with WaitForTokenInRange and WaitForGetOffsetInRange
[chromium-blink-merge.git] / tools / gn / scope.cc
blob3f714ec36d4664fd9865b348afdc67fa4b567c33
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "tools/gn/scope.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "tools/gn/parse_tree.h"
11 namespace {
13 // FLags set in the mode_flags_ of a scope. If a bit is set, it applies
14 // recursively to all dependent scopes.
15 const unsigned kProcessingBuildConfigFlag = 1;
16 const unsigned kProcessingImportFlag = 2;
18 } // namespace
20 Scope::Scope(const Settings* settings)
21 : const_containing_(NULL),
22 mutable_containing_(NULL),
23 settings_(settings),
24 mode_flags_(0) {
27 Scope::Scope(Scope* parent)
28 : const_containing_(NULL),
29 mutable_containing_(parent),
30 settings_(parent->settings()),
31 mode_flags_(0) {
34 Scope::Scope(const Scope* parent)
35 : const_containing_(parent),
36 mutable_containing_(NULL),
37 settings_(parent->settings()),
38 mode_flags_(0) {
41 Scope::~Scope() {
42 STLDeleteContainerPairSecondPointers(target_defaults_.begin(),
43 target_defaults_.end());
46 const Value* Scope::GetValue(const base::StringPiece& ident,
47 bool counts_as_used) {
48 // First check for programatically-provided values.
49 for (ProviderSet::const_iterator i = programmatic_providers_.begin();
50 i != programmatic_providers_.end(); ++i) {
51 const Value* v = (*i)->GetProgrammaticValue(ident);
52 if (v)
53 return v;
56 RecordMap::iterator found = values_.find(ident);
57 if (found != values_.end()) {
58 if (counts_as_used)
59 found->second.used = true;
60 return &found->second.value;
63 // Search in the parent scope.
64 if (const_containing_)
65 return const_containing_->GetValue(ident);
66 if (mutable_containing_)
67 return mutable_containing_->GetValue(ident, counts_as_used);
68 return NULL;
71 Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident,
72 const ParseNode* set_node) {
73 RecordMap::iterator found = values_.find(ident);
74 if (found != values_.end())
75 return &found->second.value; // Already have in the current scope.
77 // Search in the parent scope.
78 if (containing()) {
79 const Value* in_containing = containing()->GetValue(ident);
80 if (in_containing) {
81 // Promote to current scope.
82 return SetValue(ident, *in_containing, set_node);
85 return NULL;
88 const Value* Scope::GetValue(const base::StringPiece& ident) const {
89 RecordMap::const_iterator found = values_.find(ident);
90 if (found != values_.end())
91 return &found->second.value;
92 if (containing())
93 return containing()->GetValue(ident);
94 return NULL;
97 Value* Scope::SetValue(const base::StringPiece& ident,
98 const Value& v,
99 const ParseNode* set_node) {
100 Record& r = values_[ident]; // Clears any existing value.
101 r.value = v;
102 r.value.set_origin(set_node);
103 return &r.value;
106 bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) {
107 if (GetTemplate(name))
108 return false;
109 templates_[name] = decl;
110 return true;
113 const FunctionCallNode* Scope::GetTemplate(const std::string& name) const {
114 TemplateMap::const_iterator found = templates_.find(name);
115 if (found != templates_.end())
116 return found->second;
117 if (containing())
118 return containing()->GetTemplate(name);
119 return NULL;
122 void Scope::MarkUsed(const base::StringPiece& ident) {
123 RecordMap::iterator found = values_.find(ident);
124 if (found == values_.end()) {
125 NOTREACHED();
126 return;
128 found->second.used = true;
131 void Scope::MarkUnused(const base::StringPiece& ident) {
132 RecordMap::iterator found = values_.find(ident);
133 if (found == values_.end()) {
134 NOTREACHED();
135 return;
137 found->second.used = false;
140 bool Scope::IsSetButUnused(const base::StringPiece& ident) const {
141 RecordMap::const_iterator found = values_.find(ident);
142 if (found != values_.end()) {
143 if (!found->second.used) {
144 return true;
147 return false;
150 bool Scope::CheckForUnusedVars(Err* err) const {
151 for (RecordMap::const_iterator i = values_.begin();
152 i != values_.end(); ++i) {
153 if (!i->second.used) {
154 std::string help = "You set the variable \"" + i->first.as_string() +
155 "\" here and it was unused before it went\nout of scope.";
157 const BinaryOpNode* binary = i->second.value.origin()->AsBinaryOp();
158 if (binary && binary->op().type() == Token::EQUAL) {
159 // Make a nicer error message for normal var sets.
160 *err = Err(binary->left()->GetRange(), "Assignment had no effect.",
161 help);
162 } else {
163 // This will happen for internally-generated variables.
164 *err = Err(i->second.value.origin(), "Assignment had no effect.", help);
166 return false;
169 return true;
172 void Scope::GetCurrentScopeValues(KeyValueMap* output) const {
173 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i)
174 (*output)[i->first] = i->second.value;
177 bool Scope::NonRecursiveMergeTo(Scope* dest,
178 const ParseNode* node_for_err,
179 const char* desc_for_err,
180 Err* err) const {
181 // Values.
182 for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) {
183 const Value& new_value = i->second.value;
184 const Value* existing_value = dest->GetValue(i->first);
185 if (existing_value && new_value != *existing_value) {
186 // Value present in both the source and the dest.
187 std::string desc_string(desc_for_err);
188 *err = Err(node_for_err, "Value collision.",
189 "This " + desc_string + " contains \"" + i->first.as_string() + "\"");
190 err->AppendSubErr(Err(i->second.value, "defined here.",
191 "Which would clobber the one in your current scope"));
192 err->AppendSubErr(Err(*existing_value, "defined here.",
193 "Executing " + desc_string + " should not conflict with anything "
194 "in the current\nscope unless the values are identical."));
195 return false;
197 dest->values_[i->first] = i->second;
200 // Target defaults are owning pointers.
201 for (NamedScopeMap::const_iterator i = target_defaults_.begin();
202 i != target_defaults_.end(); ++i) {
203 if (dest->GetTargetDefaults(i->first)) {
204 // TODO(brettw) it would be nice to know the origin of a
205 // set_target_defaults so we can give locations for the colliding target
206 // defaults.
207 std::string desc_string(desc_for_err);
208 *err = Err(node_for_err, "Target defaults collision.",
209 "This " + desc_string + " contains target defaults for\n"
210 "\"" + i->first + "\" which would clobber one for the\n"
211 "same target type in your current scope. It's unfortunate that I'm "
212 "too stupid\nto tell you the location of where the target defaults "
213 "were set. Usually\nthis happens in the BUILDCONFIG.gn file.");
214 return false;
217 Scope* s = new Scope(settings_);
218 i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err);
219 dest->target_defaults_[i->first] = s;
222 // Sources assignment filter.
223 if (sources_assignment_filter_) {
224 if (dest->GetSourcesAssignmentFilter()) {
225 // Sources assignment filter present in both the source and the dest.
226 std::string desc_string(desc_for_err);
227 *err = Err(node_for_err, "Assignment filter collision.",
228 "The " + desc_string + " contains a sources_assignment_filter which\n"
229 "would clobber the one in your current scope.");
230 return false;
232 dest->sources_assignment_filter_.reset(
233 new PatternList(*sources_assignment_filter_));
236 // Templates.
237 for (TemplateMap::const_iterator i = templates_.begin();
238 i != templates_.end(); ++i) {
239 const FunctionCallNode* existing_template = dest->GetTemplate(i->first);
240 if (existing_template) {
241 // Rule present in both the source and the dest.
242 std::string desc_string(desc_for_err);
243 *err = Err(node_for_err, "Template collision.",
244 "This " + desc_string + " contains a template \"" + i->first + "\"");
245 err->AppendSubErr(Err(i->second->function(), "defined here.",
246 "Which would clobber the one in your current scope"));
247 err->AppendSubErr(Err(existing_template->function(), "defined here.",
248 "Executing " + desc_string + " should not conflict with anything "
249 "in the current\nscope."));
250 return false;
252 dest->templates_.insert(*i);
255 return true;
258 Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
259 if (GetTargetDefaults(target_type))
260 return NULL;
262 Scope** dest = &target_defaults_[target_type];
263 if (*dest) {
264 NOTREACHED(); // Already set.
265 return *dest;
267 *dest = new Scope(settings_);
268 return *dest;
271 const Scope* Scope::GetTargetDefaults(const std::string& target_type) const {
272 NamedScopeMap::const_iterator found = target_defaults_.find(target_type);
273 if (found != target_defaults_.end())
274 return found->second;
275 if (containing())
276 return containing()->GetTargetDefaults(target_type);
277 return NULL;
280 const PatternList* Scope::GetSourcesAssignmentFilter() const {
281 if (sources_assignment_filter_)
282 return sources_assignment_filter_.get();
283 if (containing())
284 return containing()->GetSourcesAssignmentFilter();
285 return NULL;
288 void Scope::SetProcessingBuildConfig() {
289 DCHECK((mode_flags_ & kProcessingBuildConfigFlag) == 0);
290 mode_flags_ |= kProcessingBuildConfigFlag;
293 void Scope::ClearProcessingBuildConfig() {
294 DCHECK(mode_flags_ & kProcessingBuildConfigFlag);
295 mode_flags_ &= ~(kProcessingBuildConfigFlag);
298 bool Scope::IsProcessingBuildConfig() const {
299 if (mode_flags_ & kProcessingBuildConfigFlag)
300 return true;
301 if (containing())
302 return containing()->IsProcessingBuildConfig();
303 return false;
306 void Scope::SetProcessingImport() {
307 DCHECK((mode_flags_ & kProcessingImportFlag) == 0);
308 mode_flags_ |= kProcessingImportFlag;
311 void Scope::ClearProcessingImport() {
312 DCHECK(mode_flags_ & kProcessingImportFlag);
313 mode_flags_ &= ~(kProcessingImportFlag);
316 bool Scope::IsProcessingImport() const {
317 if (mode_flags_ & kProcessingImportFlag)
318 return true;
319 if (containing())
320 return containing()->IsProcessingImport();
321 return false;
324 const SourceDir& Scope::GetSourceDir() const {
325 if (!source_dir_.is_null())
326 return source_dir_;
327 if (containing())
328 return containing()->GetSourceDir();
329 return source_dir_;
332 void Scope::SetProperty(const void* key, void* value) {
333 if (!value) {
334 DCHECK(properties_.find(key) != properties_.end());
335 properties_.erase(key);
336 } else {
337 properties_[key] = value;
341 void* Scope::GetProperty(const void* key, const Scope** found_on_scope) const {
342 PropertyMap::const_iterator found = properties_.find(key);
343 if (found != properties_.end()) {
344 if (found_on_scope)
345 *found_on_scope = this;
346 return found->second;
348 if (containing())
349 return containing()->GetProperty(key, found_on_scope);
350 return NULL;
353 void Scope::AddProvider(ProgrammaticProvider* p) {
354 programmatic_providers_.insert(p);
357 void Scope::RemoveProvider(ProgrammaticProvider* p) {
358 DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end());
359 programmatic_providers_.erase(p);