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/parse_tree.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "tools/gn/functions.h"
12 #include "tools/gn/operators.h"
13 #include "tools/gn/scope.h"
14 #include "tools/gn/string_utils.h"
18 std::string
IndentFor(int value
) {
20 for (int i
= 0; i
< value
; i
++)
27 ParseNode::ParseNode() {
30 ParseNode::~ParseNode() {
33 const AccessorNode
* ParseNode::AsAccessor() const { return NULL
; }
34 const BinaryOpNode
* ParseNode::AsBinaryOp() const { return NULL
; }
35 const BlockNode
* ParseNode::AsBlock() const { return NULL
; }
36 const ConditionNode
* ParseNode::AsConditionNode() const { return NULL
; }
37 const FunctionCallNode
* ParseNode::AsFunctionCall() const { return NULL
; }
38 const IdentifierNode
* ParseNode::AsIdentifier() const { return NULL
; }
39 const ListNode
* ParseNode::AsList() const { return NULL
; }
40 const LiteralNode
* ParseNode::AsLiteral() const { return NULL
; }
41 const UnaryOpNode
* ParseNode::AsUnaryOp() const { return NULL
; }
43 // AccessorNode ---------------------------------------------------------------
45 AccessorNode::AccessorNode() {
48 AccessorNode::~AccessorNode() {
51 const AccessorNode
* AccessorNode::AsAccessor() const {
55 Value
AccessorNode::Execute(Scope
* scope
, Err
* err
) const {
56 Value index_value
= index_
->Execute(scope
, err
);
59 if (!index_value
.VerifyTypeIs(Value::INTEGER
, err
))
62 const Value
* base_value
= scope
->GetValue(base_
.value(), true);
64 *err
= MakeErrorDescribing("Undefined identifier.");
67 if (!base_value
->VerifyTypeIs(Value::LIST
, err
))
70 int64 index_int
= index_value
.int_value();
72 *err
= Err(index_
->GetRange(), "Negative array subscript.",
73 "You gave me " + base::Int64ToString(index_int
) + ".");
76 size_t index_sizet
= static_cast<size_t>(index_int
);
77 if (index_sizet
>= base_value
->list_value().size()) {
78 *err
= Err(index_
->GetRange(), "Array subscript out of range.",
79 "You gave me " + base::Int64ToString(index_int
) +
80 " but I was expecting something from 0 to " +
82 static_cast<int64
>(base_value
->list_value().size()) - 1) +
87 // 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
89 // is used. If there is, this will crash! Currently, this is just used for
90 // array accesses where this "shouldn't" happen.
91 return base_value
->list_value()[index_sizet
];
94 LocationRange
AccessorNode::GetRange() const {
95 return LocationRange(base_
.location(), index_
->GetRange().end());
98 Err
AccessorNode::MakeErrorDescribing(const std::string
& msg
,
99 const std::string
& help
) const {
100 return Err(GetRange(), msg
, help
);
103 void AccessorNode::Print(std::ostream
& out
, int indent
) const {
104 out
<< IndentFor(indent
) << "ACCESSOR\n";
105 out
<< IndentFor(indent
+ 1) << base_
.value() << "\n";
106 index_
->Print(out
, indent
+ 1);
109 // BinaryOpNode ---------------------------------------------------------------
111 BinaryOpNode::BinaryOpNode() {
114 BinaryOpNode::~BinaryOpNode() {
117 const BinaryOpNode
* BinaryOpNode::AsBinaryOp() const {
121 Value
BinaryOpNode::Execute(Scope
* scope
, Err
* err
) const {
122 return ExecuteBinaryOperator(scope
, this, left_
.get(), right_
.get(), err
);
125 LocationRange
BinaryOpNode::GetRange() const {
126 return left_
->GetRange().Union(right_
->GetRange());
129 Err
BinaryOpNode::MakeErrorDescribing(const std::string
& msg
,
130 const std::string
& help
) const {
131 return Err(op_
, msg
, help
);
134 void BinaryOpNode::Print(std::ostream
& out
, int indent
) const {
135 out
<< IndentFor(indent
) << "BINARY(" << op_
.value() << ")\n";
136 left_
->Print(out
, indent
+ 1);
137 right_
->Print(out
, indent
+ 1);
140 // BlockNode ------------------------------------------------------------------
142 BlockNode::BlockNode(bool has_scope
) : has_scope_(has_scope
) {
145 BlockNode::~BlockNode() {
146 STLDeleteContainerPointers(statements_
.begin(), statements_
.end());
149 const BlockNode
* BlockNode::AsBlock() const {
153 Value
BlockNode::Execute(Scope
* containing_scope
, Err
* err
) const {
155 Scope
our_scope(containing_scope
);
156 Value ret
= ExecuteBlockInScope(&our_scope
, err
);
157 if (err
->has_error())
160 // Check for unused vars in the scope.
161 //our_scope.CheckForUnusedVars(err);
164 return ExecuteBlockInScope(containing_scope
, err
);
167 LocationRange
BlockNode::GetRange() const {
168 if (begin_token_
.type() != Token::INVALID
&&
169 end_token_
.type() != Token::INVALID
) {
170 return begin_token_
.range().Union(end_token_
.range());
171 } else if (!statements_
.empty()) {
172 return statements_
[0]->GetRange().Union(
173 statements_
[statements_
.size() - 1]->GetRange());
175 return LocationRange();
178 Err
BlockNode::MakeErrorDescribing(const std::string
& msg
,
179 const std::string
& help
) const {
180 return Err(GetRange(), msg
, help
);
183 void BlockNode::Print(std::ostream
& out
, int indent
) const {
184 out
<< IndentFor(indent
) << "BLOCK\n";
185 for (size_t i
= 0; i
< statements_
.size(); i
++)
186 statements_
[i
]->Print(out
, indent
+ 1);
189 Value
BlockNode::ExecuteBlockInScope(Scope
* our_scope
, Err
* err
) const {
190 for (size_t i
= 0; i
< statements_
.size() && !err
->has_error(); i
++) {
191 // Check for trying to execute things with no side effects in a block.
192 const ParseNode
* cur
= statements_
[i
];
193 if (cur
->AsList() || cur
->AsLiteral() || cur
->AsUnaryOp() ||
194 cur
->AsIdentifier()) {
195 *err
= cur
->MakeErrorDescribing(
196 "This statement has no effect.",
197 "Either delete it or do something with the result.");
200 cur
->Execute(our_scope
, err
);
205 // ConditionNode --------------------------------------------------------------
207 ConditionNode::ConditionNode() {
210 ConditionNode::~ConditionNode() {
213 const ConditionNode
* ConditionNode::AsConditionNode() const {
217 Value
ConditionNode::Execute(Scope
* scope
, Err
* err
) const {
218 Value condition_result
= condition_
->Execute(scope
, err
);
219 if (err
->has_error())
221 if (condition_result
.type() != Value::BOOLEAN
) {
222 *err
= condition_
->MakeErrorDescribing(
223 "Condition does not evaluate to a boolean value.",
224 std::string("This is a value of type \"") +
225 Value::DescribeType(condition_result
.type()) +
227 err
->AppendRange(if_token_
.range());
231 if (condition_result
.boolean_value()) {
232 if_true_
->ExecuteBlockInScope(scope
, err
);
233 } else if (if_false_
) {
234 // The else block is optional. It's either another condition (for an
235 // "else if" and we can just Execute it and the condition will handle
236 // the scoping) or it's a block indicating an "else" in which ase we
237 // need to be sure it inherits our scope.
238 const BlockNode
* if_false_block
= if_false_
->AsBlock();
240 if_false_block
->ExecuteBlockInScope(scope
, err
);
242 if_false_
->Execute(scope
, err
);
248 LocationRange
ConditionNode::GetRange() const {
250 return if_token_
.range().Union(if_false_
->GetRange());
251 return if_token_
.range().Union(if_true_
->GetRange());
254 Err
ConditionNode::MakeErrorDescribing(const std::string
& msg
,
255 const std::string
& help
) const {
256 return Err(if_token_
, msg
, help
);
259 void ConditionNode::Print(std::ostream
& out
, int indent
) const {
260 out
<< IndentFor(indent
) << "CONDITION\n";
261 condition_
->Print(out
, indent
+ 1);
262 if_true_
->Print(out
, indent
+ 1);
264 if_false_
->Print(out
, indent
+ 1);
267 // FunctionCallNode -----------------------------------------------------------
269 FunctionCallNode::FunctionCallNode() {
272 FunctionCallNode::~FunctionCallNode() {
275 const FunctionCallNode
* FunctionCallNode::AsFunctionCall() const {
279 Value
FunctionCallNode::Execute(Scope
* scope
, Err
* err
) const {
280 return functions::RunFunction(scope
, this, args_
.get(), block_
.get(), err
);
283 LocationRange
FunctionCallNode::GetRange() const {
285 return function_
.range().Union(block_
->GetRange());
286 return function_
.range().Union(args_
->GetRange());
289 Err
FunctionCallNode::MakeErrorDescribing(const std::string
& msg
,
290 const std::string
& help
) const {
291 return Err(function_
, msg
, help
);
294 void FunctionCallNode::Print(std::ostream
& out
, int indent
) const {
295 out
<< IndentFor(indent
) << "FUNCTION(" << function_
.value() << ")\n";
296 args_
->Print(out
, indent
+ 1);
298 block_
->Print(out
, indent
+ 1);
301 // IdentifierNode --------------------------------------------------------------
303 IdentifierNode::IdentifierNode() {
306 IdentifierNode::IdentifierNode(const Token
& token
) : value_(token
) {
309 IdentifierNode::~IdentifierNode() {
312 const IdentifierNode
* IdentifierNode::AsIdentifier() const {
316 Value
IdentifierNode::Execute(Scope
* scope
, Err
* err
) const {
317 const Value
* result
= scope
->GetValue(value_
.value(), true);
319 *err
= MakeErrorDescribing("Undefined identifier");
325 LocationRange
IdentifierNode::GetRange() const {
326 return value_
.range();
329 Err
IdentifierNode::MakeErrorDescribing(const std::string
& msg
,
330 const std::string
& help
) const {
331 return Err(value_
, msg
, help
);
334 void IdentifierNode::Print(std::ostream
& out
, int indent
) const {
335 out
<< IndentFor(indent
) << "IDENTIFIER(" << value_
.value() << ")\n";
338 // ListNode -------------------------------------------------------------------
340 ListNode::ListNode() {
343 ListNode::~ListNode() {
344 STLDeleteContainerPointers(contents_
.begin(), contents_
.end());
347 const ListNode
* ListNode::AsList() const {
351 Value
ListNode::Execute(Scope
* scope
, Err
* err
) const {
352 Value
result_value(this, Value::LIST
);
353 std::vector
<Value
>& results
= result_value
.list_value();
354 results
.resize(contents_
.size());
356 for (size_t i
= 0; i
< contents_
.size(); i
++) {
357 const ParseNode
* cur
= contents_
[i
];
358 results
[i
] = cur
->Execute(scope
, err
);
359 if (err
->has_error())
361 if (results
[i
].type() == Value::NONE
) {
362 *err
= cur
->MakeErrorDescribing(
363 "This does not evaluate to a value.",
364 "I can't do something with nothing.");
371 LocationRange
ListNode::GetRange() const {
372 return LocationRange(begin_token_
.location(), end_token_
.location());
375 Err
ListNode::MakeErrorDescribing(const std::string
& msg
,
376 const std::string
& help
) const {
377 return Err(begin_token_
, msg
, help
);
380 void ListNode::Print(std::ostream
& out
, int indent
) const {
381 out
<< IndentFor(indent
) << "LIST\n";
382 for (size_t i
= 0; i
< contents_
.size(); i
++)
383 contents_
[i
]->Print(out
, indent
+ 1);
386 // LiteralNode -----------------------------------------------------------------
388 LiteralNode::LiteralNode() {
391 LiteralNode::LiteralNode(const Token
& token
) : value_(token
) {
394 LiteralNode::~LiteralNode() {
397 const LiteralNode
* LiteralNode::AsLiteral() const {
401 Value
LiteralNode::Execute(Scope
* scope
, Err
* err
) const {
402 switch (value_
.type()) {
403 case Token::TRUE_TOKEN
:
404 return Value(this, true);
405 case Token::FALSE_TOKEN
:
406 return Value(this, false);
407 case Token::INTEGER
: {
409 if (!base::StringToInt64(value_
.value(), &result_int
)) {
410 *err
= MakeErrorDescribing("This does not look like an integer");
413 return Value(this, result_int
);
415 case Token::STRING
: {
416 Value
v(this, Value::STRING
);
417 ExpandStringLiteral(scope
, value_
, &v
, err
);
426 LocationRange
LiteralNode::GetRange() const {
427 return value_
.range();
430 Err
LiteralNode::MakeErrorDescribing(const std::string
& msg
,
431 const std::string
& help
) const {
432 return Err(value_
, msg
, help
);
435 void LiteralNode::Print(std::ostream
& out
, int indent
) const {
436 out
<< IndentFor(indent
) << "LITERAL(" << value_
.value() << ")\n";
439 // UnaryOpNode ----------------------------------------------------------------
441 UnaryOpNode::UnaryOpNode() {
444 UnaryOpNode::~UnaryOpNode() {
447 const UnaryOpNode
* UnaryOpNode::AsUnaryOp() const {
451 Value
UnaryOpNode::Execute(Scope
* scope
, Err
* err
) const {
452 Value operand_value
= operand_
->Execute(scope
, err
);
453 if (err
->has_error())
455 return ExecuteUnaryOperator(scope
, this, operand_value
, err
);
458 LocationRange
UnaryOpNode::GetRange() const {
459 return op_
.range().Union(operand_
->GetRange());
462 Err
UnaryOpNode::MakeErrorDescribing(const std::string
& msg
,
463 const std::string
& help
) const {
464 return Err(op_
, msg
, help
);
467 void UnaryOpNode::Print(std::ostream
& out
, int indent
) const {
468 out
<< IndentFor(indent
) << "UNARY(" << op_
.value() << ")\n";
469 operand_
->Print(out
, indent
+ 1);