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

Side by Side Diff: tools/gn/functions.cc

Issue 212933008: Don't dynamically scope GN templates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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/function_template.cc ('k') | tools/gn/functions_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/functions.h" 5 #include "tools/gn/functions.h"
6 6
7 #include <iostream> 7 #include <iostream>
8 8
9 #include "base/environment.h" 9 #include "base/environment.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
11 #include "tools/gn/config.h" 11 #include "tools/gn/config.h"
12 #include "tools/gn/config_values_generator.h" 12 #include "tools/gn/config_values_generator.h"
13 #include "tools/gn/err.h" 13 #include "tools/gn/err.h"
14 #include "tools/gn/input_file.h" 14 #include "tools/gn/input_file.h"
15 #include "tools/gn/parse_tree.h" 15 #include "tools/gn/parse_tree.h"
16 #include "tools/gn/scheduler.h" 16 #include "tools/gn/scheduler.h"
17 #include "tools/gn/scope.h" 17 #include "tools/gn/scope.h"
18 #include "tools/gn/settings.h" 18 #include "tools/gn/settings.h"
19 #include "tools/gn/template.h"
19 #include "tools/gn/token.h" 20 #include "tools/gn/token.h"
20 #include "tools/gn/value.h" 21 #include "tools/gn/value.h"
21 22
22 namespace {
23
24 // This is called when a template is invoked. When we see a template
25 // declaration, that funciton is RunTemplate.
26 Value RunTemplateInvocation(Scope* scope,
27 const FunctionCallNode* invocation,
28 const std::vector<Value>& args,
29 BlockNode* block,
30 const FunctionCallNode* rule,
31 Err* err) {
32 if (!EnsureNotProcessingImport(invocation, scope, err))
33 return Value();
34
35 Scope block_scope(scope);
36 if (!FillTargetBlockScope(scope, invocation,
37 invocation->function().value().as_string(),
38 block, args, &block_scope, err))
39 return Value();
40
41 // Run the block for the rule invocation.
42 block->ExecuteBlockInScope(&block_scope, err);
43 if (err->has_error())
44 return Value();
45
46 // Now run the rule itself with that block as the current scope.
47 rule->block()->ExecuteBlockInScope(&block_scope, err);
48 if (err->has_error())
49 return Value();
50
51 block_scope.CheckForUnusedVars(err);
52 return Value();
53 }
54
55 } // namespace
56
57 // ----------------------------------------------------------------------------
58
59 bool EnsureNotProcessingImport(const ParseNode* node, 23 bool EnsureNotProcessingImport(const ParseNode* node,
60 const Scope* scope, 24 const Scope* scope,
61 Err* err) { 25 Err* err) {
62 if (scope->IsProcessingImport()) { 26 if (scope->IsProcessingImport()) {
63 *err = Err(node, "Not valid from an import.", 27 *err = Err(node, "Not valid from an import.",
64 "Imports are for defining defaults, variables, and rules. The\n" 28 "Imports are for defining defaults, variables, and rules. The\n"
65 "appropriate place for this kind of thing is really in a normal\n" 29 "appropriate place for this kind of thing is really in a normal\n"
66 "BUILD file."); 30 "BUILD file.");
67 return false; 31 return false;
68 } 32 }
(...skipping 21 matching lines...) Expand all
90 Err* err) { 54 Err* err) {
91 if (!block) { 55 if (!block) {
92 FillNeedsBlockError(function, err); 56 FillNeedsBlockError(function, err);
93 return false; 57 return false;
94 } 58 }
95 59
96 // Copy the target defaults, if any, into the scope we're going to execute 60 // Copy the target defaults, if any, into the scope we're going to execute
97 // the block in. 61 // the block in.
98 const Scope* default_scope = scope->GetTargetDefaults(target_type); 62 const Scope* default_scope = scope->GetTargetDefaults(target_type);
99 if (default_scope) { 63 if (default_scope) {
100 if (!default_scope->NonRecursiveMergeTo(block_scope, function, 64 if (!default_scope->NonRecursiveMergeTo(block_scope, false, function,
101 "target defaults", err)) 65 "target defaults", err))
102 return false; 66 return false;
103 } 67 }
104 68
105 // The name is the single argument to the target function. 69 // The name is the single argument to the target function.
106 if (!EnsureSingleStringArg(function, args, err)) 70 if (!EnsureSingleStringArg(function, args, err))
107 return false; 71 return false;
108 72
109 // Set the target name variable to the current target, and mark it used 73 // Set the target name variable to the current target, and mark it used
110 // because we don't want to issue an error if the script ignores it. 74 // because we don't want to issue an error if the script ignores it.
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 288
325 // defined --------------------------------------------------------------------- 289 // defined ---------------------------------------------------------------------
326 290
327 const char kDefined[] = "defined"; 291 const char kDefined[] = "defined";
328 const char kDefined_Help[] = 292 const char kDefined_Help[] =
329 "defined: Returns whether an identifier is defined.\n" 293 "defined: Returns whether an identifier is defined.\n"
330 "\n" 294 "\n"
331 " Returns true if the given argument is defined. This is most useful in\n" 295 " Returns true if the given argument is defined. This is most useful in\n"
332 " templates to assert that the caller set things up properly.\n" 296 " templates to assert that the caller set things up properly.\n"
333 "\n" 297 "\n"
298 " You can pass an identifier:\n"
299 " defined(foo)\n"
300 " which will return true or false depending on whether foo is defined in\n"
301 " the current scope.\n"
302 "\n"
303 " You can also check a named scope:\n"
304 " defined(foo.bar)\n"
305 " which returns true if both foo is defined and bar is defined on the\n"
306 " named scope foo. It will throw an error if foo is defined but is not\n"
307 " a scope.\n"
308 "\n"
334 "Example:\n" 309 "Example:\n"
335 "\n" 310 "\n"
336 " template(\"mytemplate\") {\n" 311 " template(\"mytemplate\") {\n"
337 " # To help users call this template properly...\n" 312 " # To help users call this template properly...\n"
338 " assert(defined(sources), \"Sources must be defined\")\n" 313 " assert(defined(invoker.sources), \"Sources must be defined\")\n"
339 "\n" 314 "\n"
340 " # If we want to accept an optional \"values\" argument, we don't\n" 315 " # If we want to accept an optional \"values\" argument, we don't\n"
341 " # want to dereference something that may not be defined.\n" 316 " # want to dereference something that may not be defined.\n"
342 " if (!defined(outputs)) {\n" 317 " if (defined(invoker.values)) {\n"
343 " outputs = []\n" 318 " values = invoker.values\n"
319 " } else {\n"
320 " values = \"some default value\"\n"
344 " }\n" 321 " }\n"
345 " }\n"; 322 " }\n";
346 323
347 Value RunDefined(Scope* scope, 324 Value RunDefined(Scope* scope,
348 const FunctionCallNode* function, 325 const FunctionCallNode* function,
349 const ListNode* args_list, 326 const ListNode* args_list,
350 Err* err) { 327 Err* err) {
351 const std::vector<const ParseNode*>& args_vector = args_list->contents(); 328 const std::vector<const ParseNode*>& args_vector = args_list->contents();
352 const IdentifierNode* identifier = NULL; 329 if (args_vector.size() != 1) {
353 if (args_vector.size() != 1 || 330 *err = Err(function, "Wrong number of arguments to defined().",
354 !(identifier = args_vector[0]->AsIdentifier())) { 331 "Expecting exactly one.");
355 *err = Err(function, "Bad argument to defined().",
356 "defined() takes one argument which should be an identifier.");
357 return Value(); 332 return Value();
358 } 333 }
359 334
360 if (scope->GetValue(identifier->value().value())) 335 const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
361 return Value(function, true); 336 if (identifier) {
362 return Value(function, false); 337 // Passed an identifier "defined(foo)".
338 if (scope->GetValue(identifier->value().value()))
339 return Value(function, true);
340 return Value(function, false);
341 }
342
343 const AccessorNode* accessor = args_vector[0]->AsAccessor();
344 if (accessor) {
345 // Passed an accessor "defined(foo.bar)".
346 if (accessor->member()) {
347 // The base of the accessor must be a scope if it's defined.
348 const Value* base = scope->GetValue(accessor->base().value());
349 if (!base)
350 return Value(function, false);
351 if (!base->VerifyTypeIs(Value::SCOPE, err))
352 return Value();
353
354 // Check the member inside the scope to see if its defined.
355 if (base->scope_value()->GetValue(accessor->member()->value().value()))
356 return Value(function, true);
357 return Value(function, false);
358 }
359 }
360
361 // Argument is invalid.
362 *err = Err(function, "Bad thing passed to defined().",
363 "It should be of the form defined(foo) or defined(foo.bar).");
364 return Value();
363 } 365 }
364 366
365 // getenv ---------------------------------------------------------------------- 367 // getenv ----------------------------------------------------------------------
366 368
367 const char kGetEnv[] = "getenv"; 369 const char kGetEnv[] = "getenv";
368 const char kGetEnv_Help[] = 370 const char kGetEnv_Help[] =
369 "getenv: Get an environment variable.\n" 371 "getenv: Get an environment variable.\n"
370 "\n" 372 "\n"
371 " value = getenv(env_var_name)\n" 373 " value = getenv(env_var_name)\n"
372 "\n" 374 "\n"
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 const ListNode* args_list, 620 const ListNode* args_list,
619 BlockNode* block, 621 BlockNode* block,
620 Err* err) { 622 Err* err) {
621 const Token& name = function->function(); 623 const Token& name = function->function();
622 624
623 const FunctionInfoMap& function_map = GetFunctions(); 625 const FunctionInfoMap& function_map = GetFunctions();
624 FunctionInfoMap::const_iterator found_function = 626 FunctionInfoMap::const_iterator found_function =
625 function_map.find(name.value()); 627 function_map.find(name.value());
626 if (found_function == function_map.end()) { 628 if (found_function == function_map.end()) {
627 // No built-in function matching this, check for a template. 629 // No built-in function matching this, check for a template.
628 const FunctionCallNode* rule = 630 const Template* templ =
629 scope->GetTemplate(function->function().value().as_string()); 631 scope->GetTemplate(function->function().value().as_string());
630 if (rule) { 632 if (templ) {
631 Value args = args_list->Execute(scope, err); 633 Value args = args_list->Execute(scope, err);
632 if (err->has_error()) 634 if (err->has_error())
633 return Value(); 635 return Value();
634 return RunTemplateInvocation(scope, function, args.list_value(), block, 636 return templ->Invoke(scope, function, args.list_value(), block, err);
635 rule, err);
636 } 637 }
637 638
638 *err = Err(name, "Unknown function."); 639 *err = Err(name, "Unknown function.");
639 return Value(); 640 return Value();
640 } 641 }
641 642
642 if (found_function->second.self_evaluating_args_runner) { 643 if (found_function->second.self_evaluating_args_runner) {
643 return found_function->second.self_evaluating_args_runner( 644 return found_function->second.self_evaluating_args_runner(
644 scope, function, args_list, err); 645 scope, function, args_list, err);
645 } 646 }
(...skipping 25 matching lines...) Expand all
671 return found_function->second.executed_block_runner( 672 return found_function->second.executed_block_runner(
672 function, args.list_value(), &block_scope, err); 673 function, args.list_value(), &block_scope, err);
673 } 674 }
674 675
675 // Otherwise it's a no-block function. 676 // Otherwise it's a no-block function.
676 return found_function->second.no_block_runner(scope, function, 677 return found_function->second.no_block_runner(scope, function,
677 args.list_value(), err); 678 args.list_value(), err);
678 } 679 }
679 680
680 } // namespace functions 681 } // namespace functions
OLDNEW
« no previous file with comments | « tools/gn/function_template.cc ('k') | tools/gn/functions_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698