| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |