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

Side by Side 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, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/gn/parse_tree.h ('k') | tools/gn/parse_tree_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/gn/parse_tree.h" 5 #include "tools/gn/parse_tree.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 } 46 }
47 47
48 AccessorNode::~AccessorNode() { 48 AccessorNode::~AccessorNode() {
49 } 49 }
50 50
51 const AccessorNode* AccessorNode::AsAccessor() const { 51 const AccessorNode* AccessorNode::AsAccessor() const {
52 return this; 52 return this;
53 } 53 }
54 54
55 Value AccessorNode::Execute(Scope* scope, Err* err) const { 55 Value AccessorNode::Execute(Scope* scope, Err* err) const {
56 if (index_)
57 return ExecuteArrayAccess(scope, err);
58 else if (member_)
59 return ExecuteScopeAccess(scope, err);
60 NOTREACHED();
61 return Value();
62 }
63
64 LocationRange AccessorNode::GetRange() const {
65 if (index_)
66 return LocationRange(base_.location(), index_->GetRange().end());
67 else if (member_)
68 return LocationRange(base_.location(), member_->GetRange().end());
69 NOTREACHED();
70 return LocationRange();
71 }
72
73 Err AccessorNode::MakeErrorDescribing(const std::string& msg,
74 const std::string& help) const {
75 return Err(GetRange(), msg, help);
76 }
77
78 void AccessorNode::Print(std::ostream& out, int indent) const {
79 out << IndentFor(indent) << "ACCESSOR\n";
80 out << IndentFor(indent + 1) << base_.value() << "\n";
81 if (index_)
82 index_->Print(out, indent + 1);
83 else if (member_)
84 member_->Print(out, indent + 1);
85 }
86
87 Value AccessorNode::ExecuteArrayAccess(Scope* scope, Err* err) const {
56 Value index_value = index_->Execute(scope, err); 88 Value index_value = index_->Execute(scope, err);
57 if (err->has_error()) 89 if (err->has_error())
58 return Value(); 90 return Value();
59 if (!index_value.VerifyTypeIs(Value::INTEGER, err)) 91 if (!index_value.VerifyTypeIs(Value::INTEGER, err))
60 return Value(); 92 return Value();
61 93
62 const Value* base_value = scope->GetValue(base_.value(), true); 94 const Value* base_value = scope->GetValue(base_.value(), true);
63 if (!base_value) { 95 if (!base_value) {
64 *err = MakeErrorDescribing("Undefined identifier."); 96 *err = MakeErrorDescribing("Undefined identifier.");
65 return Value(); 97 return Value();
(...skipping 18 matching lines...) Expand all
84 return Value(); 116 return Value();
85 } 117 }
86 118
87 // Doing this assumes that there's no way in the language to do anything 119 // Doing this assumes that there's no way in the language to do anything
88 // between the time the reference is created and the time that the reference 120 // between the time the reference is created and the time that the reference
89 // is used. If there is, this will crash! Currently, this is just used for 121 // is used. If there is, this will crash! Currently, this is just used for
90 // array accesses where this "shouldn't" happen. 122 // array accesses where this "shouldn't" happen.
91 return base_value->list_value()[index_sizet]; 123 return base_value->list_value()[index_sizet];
92 } 124 }
93 125
94 LocationRange AccessorNode::GetRange() const { 126 Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const {
95 return LocationRange(base_.location(), index_->GetRange().end()); 127 // We jump through some hoops here since ideally a.b will count "b" as
96 } 128 // accessed in the given scope. The value "a" might be in some normal nested
129 // scope and we can modify it, but it might also be inherited from the
130 // readonly root scope and we can't do used variable tracking on it. (It's
131 // not legal to const cast it away since the root scope will be in readonly
132 // mode and being accessed from multiple threads without locking.) So this
133 // code handles both cases.
134 const Value* result = NULL;
97 135
98 Err AccessorNode::MakeErrorDescribing(const std::string& msg, 136 // Look up the value in the scope named by "base_".
99 const std::string& help) const { 137 Value* mutable_base_value = scope->GetMutableValue(base_.value(), true);
100 return Err(GetRange(), msg, help); 138 if (mutable_base_value) {
101 } 139 // Common case: base value is mutable so we can track variable accesses
140 // for unused value warnings.
141 if (!mutable_base_value->VerifyTypeIs(Value::SCOPE, err))
142 return Value();
143 result = mutable_base_value->scope_value()->GetValue(
144 member_->value().value(), true);
145 } else {
146 // Fall back to see if the value is on a read-only scope.
147 const Value* const_base_value = scope->GetValue(base_.value(), true);
148 if (const_base_value) {
149 // Read only value, don't try to mark the value access as a "used" one.
150 if (!const_base_value->VerifyTypeIs(Value::SCOPE, err))
151 return Value();
152 result =
153 const_base_value->scope_value()->GetValue(member_->value().value());
154 } else {
155 *err = Err(base_, "Undefined identifier.");
156 return Value();
157 }
158 }
102 159
103 void AccessorNode::Print(std::ostream& out, int indent) const { 160 if (!result) {
104 out << IndentFor(indent) << "ACCESSOR\n"; 161 *err = Err(member_.get(), "No value named \"" +
105 out << IndentFor(indent + 1) << base_.value() << "\n"; 162 member_->value().value() + "\" in scope \"" + base_.value() + "\"");
106 index_->Print(out, indent + 1); 163 return Value();
164 }
165 return *result;
107 } 166 }
108 167
109 // BinaryOpNode --------------------------------------------------------------- 168 // BinaryOpNode ---------------------------------------------------------------
110 169
111 BinaryOpNode::BinaryOpNode() { 170 BinaryOpNode::BinaryOpNode() {
112 } 171 }
113 172
114 BinaryOpNode::~BinaryOpNode() { 173 BinaryOpNode::~BinaryOpNode() {
115 } 174 }
116 175
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 520
462 Err UnaryOpNode::MakeErrorDescribing(const std::string& msg, 521 Err UnaryOpNode::MakeErrorDescribing(const std::string& msg,
463 const std::string& help) const { 522 const std::string& help) const {
464 return Err(op_, msg, help); 523 return Err(op_, msg, help);
465 } 524 }
466 525
467 void UnaryOpNode::Print(std::ostream& out, int indent) const { 526 void UnaryOpNode::Print(std::ostream& out, int indent) const {
468 out << IndentFor(indent) << "UNARY(" << op_.value() << ")\n"; 527 out << IndentFor(indent) << "UNARY(" << op_.value() << ")\n";
469 operand_->Print(out, indent + 1); 528 operand_->Print(out, indent + 1);
470 } 529 }
OLDNEW
« 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