Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(796)

Unified Diff: tools/gn/parse_tree.cc

Issue 207233003: Add "." accessors to GN. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review comments Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/parse_tree.h ('k') | tools/gn/parse_tree_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/parse_tree.cc
diff --git a/tools/gn/parse_tree.cc b/tools/gn/parse_tree.cc
index bc50f201c2c617b0aca54df87ab6a6c1a0297c84..4015fd1f353149acfd0d610b5f7eddc3cf52c608 100644
--- a/tools/gn/parse_tree.cc
+++ b/tools/gn/parse_tree.cc
@@ -53,6 +53,38 @@ const AccessorNode* AccessorNode::AsAccessor() const {
}
Value AccessorNode::Execute(Scope* scope, Err* err) const {
+ if (index_)
+ return ExecuteArrayAccess(scope, err);
+ else if (member_)
+ return ExecuteScopeAccess(scope, err);
+ NOTREACHED();
+ return Value();
+}
+
+LocationRange AccessorNode::GetRange() const {
+ if (index_)
+ return LocationRange(base_.location(), index_->GetRange().end());
+ else if (member_)
+ return LocationRange(base_.location(), member_->GetRange().end());
+ NOTREACHED();
+ return LocationRange();
+}
+
+Err AccessorNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(GetRange(), msg, help);
+}
+
+void AccessorNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "ACCESSOR\n";
+ out << IndentFor(indent + 1) << base_.value() << "\n";
+ if (index_)
+ index_->Print(out, indent + 1);
+ else if (member_)
+ member_->Print(out, indent + 1);
+}
+
+Value AccessorNode::ExecuteArrayAccess(Scope* scope, Err* err) const {
Value index_value = index_->Execute(scope, err);
if (err->has_error())
return Value();
@@ -91,19 +123,46 @@ Value AccessorNode::Execute(Scope* scope, Err* err) const {
return base_value->list_value()[index_sizet];
}
-LocationRange AccessorNode::GetRange() const {
- return LocationRange(base_.location(), index_->GetRange().end());
-}
-
-Err AccessorNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(GetRange(), msg, help);
-}
+Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const {
+ // We jump through some hoops here since ideally a.b will count "b" as
+ // accessed in the given scope. The value "a" might be in some normal nested
+ // scope and we can modify it, but it might also be inherited from the
+ // readonly root scope and we can't do used variable tracking on it. (It's
+ // not legal to const cast it away since the root scope will be in readonly
+ // mode and being accessed from multiple threads without locking.) So this
+ // code handles both cases.
+ const Value* result = NULL;
+
+ // Look up the value in the scope named by "base_".
+ Value* mutable_base_value = scope->GetMutableValue(base_.value(), true);
+ if (mutable_base_value) {
+ // Common case: base value is mutable so we can track variable accesses
+ // for unused value warnings.
+ if (!mutable_base_value->VerifyTypeIs(Value::SCOPE, err))
+ return Value();
+ result = mutable_base_value->scope_value()->GetValue(
+ member_->value().value(), true);
+ } else {
+ // Fall back to see if the value is on a read-only scope.
+ const Value* const_base_value = scope->GetValue(base_.value(), true);
+ if (const_base_value) {
+ // Read only value, don't try to mark the value access as a "used" one.
+ if (!const_base_value->VerifyTypeIs(Value::SCOPE, err))
+ return Value();
+ result =
+ const_base_value->scope_value()->GetValue(member_->value().value());
+ } else {
+ *err = Err(base_, "Undefined identifier.");
+ return Value();
+ }
+ }
-void AccessorNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "ACCESSOR\n";
- out << IndentFor(indent + 1) << base_.value() << "\n";
- index_->Print(out, indent + 1);
+ if (!result) {
+ *err = Err(member_.get(), "No value named \"" +
+ member_->value().value() + "\" in scope \"" + base_.value() + "\"");
+ return Value();
+ }
+ return *result;
}
// BinaryOpNode ---------------------------------------------------------------
« no previous file with comments | « tools/gn/parse_tree.h ('k') | tools/gn/parse_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698