// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef TOOLS_GN_SCOPE_H_ #define TOOLS_GN_SCOPE_H_ #include #include #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "tools/gn/err.h" #include "tools/gn/pattern.h" #include "tools/gn/source_dir.h" #include "tools/gn/value.h" class FunctionCallNode; class ImportManager; class Item; class ParseNode; class Settings; class TargetManager; class Template; // Scope for the script execution. // // Scopes are nested. Writing goes into the toplevel scope, reading checks // values resursively down the stack until a match is found or there are no // more containing scopes. // // A containing scope can be const or non-const. The const containing scope is // used primarily to refer to the master build config which is shared across // many invocations. A const containing scope, however, prevents us from // marking variables "used" which prevents us from issuing errors on unused // variables. So you should use a non-const containing scope whenever possible. class Scope { public: typedef base::hash_map KeyValueMap; // Holds an owning list of scoped_ptrs of Items (since we can't make a vector // of scoped_ptrs). typedef ScopedVector< scoped_ptr > ItemVector; // Allows code to provide values for built-in variables. This class will // automatically register itself on construction and deregister itself on // destruction. class ProgrammaticProvider { public: ProgrammaticProvider(Scope* scope) : scope_(scope) { scope_->AddProvider(this); } ~ProgrammaticProvider() { scope_->RemoveProvider(this); } // Returns a non-null value if the given value can be programmatically // generated, or NULL if there is none. virtual const Value* GetProgrammaticValue( const base::StringPiece& ident) = 0; protected: Scope* scope_; }; // Creates an empty toplevel scope. Scope(const Settings* settings); // Creates a dependent scope. Scope(Scope* parent); Scope(const Scope* parent); ~Scope(); const Settings* settings() const { return settings_; } // See the const_/mutable_containing_ var declaraions below. Yes, it's a // bit weird that we can have a const pointer to the "mutable" one. Scope* mutable_containing() { return mutable_containing_; } const Scope* mutable_containing() const { return mutable_containing_; } const Scope* const_containing() const { return const_containing_; } const Scope* containing() const { return mutable_containing_ ? mutable_containing_ : const_containing_; } // Returns NULL if there's no such value. // // counts_as_used should be set if the variable is being read in a way that // should count for unused variable checking. const Value* GetValue(const base::StringPiece& ident, bool counts_as_used); const Value* GetValue(const base::StringPiece& ident) const; // Returns the requested value as a mutable one if possible. If the value // is not found in a mutable scope, then returns null. Note that the value // could still exist in a const scope, so GetValue() could still return // non-null in this case. // // Say you have a local scope that then refers to the const root scope from // the master build config. You can't change the values from the master // build config (it's read-only so it can be read from multiple threads // without locking). Read-only operations would work on values from the root // scope, but write operations would only work on values in the derived // scope(s). // // Be careful when calling this. It's not normally correct to modify values, // but you should instead do a new Set each time. // // Consider this code: // a = 5 // { // a = 6 // } // The 6 should get set on the nested scope rather than modify the value // in the outer one. Value* GetMutableValue(const base::StringPiece& ident, bool counts_as_used); // Same as GetValue, but if the value exists in a parent scope, we'll copy // it to the current scope. If the return value is non-null, the value is // guaranteed to be set in the current scope. Generatlly this will be used // if the calling code is planning on modifying the value in-place. // // Since this is used when doing read-modifies, we never count this access // as reading the variable, since we assume it will be written to. Value* GetValueForcedToCurrentScope(const base::StringPiece& ident, const ParseNode* set_node); // The set_node indicates the statement that caused the set, for displaying // errors later. Returns a pointer to the value in the current scope (a copy // is made for storage). Value* SetValue(const base::StringPiece& ident, const Value& v, const ParseNode* set_node); // Templates associated with this scope. A template can only be set once, so // AddTemplate will fail and return false if a rule with that name already // exists. GetTemplate returns NULL if the rule doesn't exist, and it will // check all containing scoped rescursively. bool AddTemplate(const std::string& name, scoped_ptr