functions.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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. 4 5#include "tools/gn/functions.h" 6 7#include <iostream> 8 9#include "base/environment.h" 10#include "base/strings/string_util.h" 11#include "tools/gn/config.h" 12#include "tools/gn/config_values_generator.h" 13#include "tools/gn/err.h" 14#include "tools/gn/input_file.h" 15#include "tools/gn/parse_tree.h" 16#include "tools/gn/scheduler.h" 17#include "tools/gn/scope.h" 18#include "tools/gn/settings.h" 19#include "tools/gn/template.h" 20#include "tools/gn/token.h" 21#include "tools/gn/value.h" 22 23bool EnsureNotProcessingImport(const ParseNode* node, 24 const Scope* scope, 25 Err* err) { 26 if (scope->IsProcessingImport()) { 27 *err = Err(node, "Not valid from an import.", 28 "Imports are for defining defaults, variables, and rules. The\n" 29 "appropriate place for this kind of thing is really in a normal\n" 30 "BUILD file."); 31 return false; 32 } 33 return true; 34} 35 36bool EnsureNotProcessingBuildConfig(const ParseNode* node, 37 const Scope* scope, 38 Err* err) { 39 if (scope->IsProcessingBuildConfig()) { 40 *err = Err(node, "Not valid from the build config.", 41 "You can't do this kind of thing from the build config script, " 42 "silly!\nPut it in a regular BUILD file."); 43 return false; 44 } 45 return true; 46} 47 48bool FillTargetBlockScope(const Scope* scope, 49 const FunctionCallNode* function, 50 const std::string& target_type, 51 const BlockNode* block, 52 const std::vector<Value>& args, 53 Scope* block_scope, 54 Err* err) { 55 if (!block) { 56 FillNeedsBlockError(function, err); 57 return false; 58 } 59 60 // Copy the target defaults, if any, into the scope we're going to execute 61 // the block in. 62 const Scope* default_scope = scope->GetTargetDefaults(target_type); 63 if (default_scope) { 64 if (!default_scope->NonRecursiveMergeTo(block_scope, false, function, 65 "target defaults", err)) 66 return false; 67 } 68 69 // The name is the single argument to the target function. 70 if (!EnsureSingleStringArg(function, args, err)) 71 return false; 72 73 // Set the target name variable to the current target, and mark it used 74 // because we don't want to issue an error if the script ignores it. 75 const base::StringPiece target_name("target_name"); 76 block_scope->SetValue(target_name, Value(function, args[0].string_value()), 77 function); 78 block_scope->MarkUsed(target_name); 79 return true; 80} 81 82void FillNeedsBlockError(const FunctionCallNode* function, Err* err) { 83 *err = Err(function->function(), "This function call requires a block.", 84 "The block's \"{\" must be on the same line as the function " 85 "call's \")\"."); 86} 87 88bool EnsureSingleStringArg(const FunctionCallNode* function, 89 const std::vector<Value>& args, 90 Err* err) { 91 if (args.size() != 1) { 92 *err = Err(function->function(), "Incorrect arguments.", 93 "This function requires a single string argument."); 94 return false; 95 } 96 return args[0].VerifyTypeIs(Value::STRING, err); 97} 98 99const Label& ToolchainLabelForScope(const Scope* scope) { 100 return scope->settings()->toolchain_label(); 101} 102 103Label MakeLabelForScope(const Scope* scope, 104 const FunctionCallNode* function, 105 const std::string& name) { 106 const Label& toolchain_label = ToolchainLabelForScope(scope); 107 return Label(scope->GetSourceDir(), name, toolchain_label.dir(), 108 toolchain_label.name()); 109} 110 111namespace functions { 112 113// assert ---------------------------------------------------------------------- 114 115const char kAssert[] = "assert"; 116const char kAssert_HelpShort[] = 117 "assert: Assert an expression is true at generation time."; 118const char kAssert_Help[] = 119 "assert: Assert an expression is true at generation time.\n" 120 "\n" 121 " assert(<condition> [, <error string>])\n" 122 "\n" 123 " If the condition is false, the build will fail with an error. If the\n" 124 " optional second argument is provided, that string will be printed\n" 125 " with the error message.\n" 126 "\n" 127 "Examples:\n" 128 " assert(is_win)\n" 129 " assert(defined(sources), \"Sources must be defined\")\n"; 130 131Value RunAssert(Scope* scope, 132 const FunctionCallNode* function, 133 const std::vector<Value>& args, 134 Err* err) { 135 if (args.size() != 1 && args.size() != 2) { 136 *err = Err(function->function(), "Wrong number of arguments.", 137 "assert() takes one or two argument, " 138 "were you expecting somethig else?"); 139 } else if (args[0].type() != Value::BOOLEAN) { 140 *err = Err(function->function(), "Assertion value not a bool."); 141 } else if (!args[0].boolean_value()) { 142 if (args.size() == 2) { 143 // Optional string message. 144 if (args[1].type() != Value::STRING) { 145 *err = Err(function->function(), "Assertion failed.", 146 "<<<ERROR MESSAGE IS NOT A STRING>>>"); 147 } else { 148 *err = Err(function->function(), "Assertion failed.", 149 args[1].string_value()); 150 } 151 } else { 152 *err = Err(function->function(), "Assertion failed."); 153 } 154 155 if (args[0].origin()) { 156 // If you do "assert(foo)" we'd ideally like to show you where foo was 157 // set, and in this case the origin of the args will tell us that. 158 // However, if you do "assert(foo && bar)" the source of the value will 159 // be the assert like, which isn't so helpful. 160 // 161 // So we try to see if the args are from the same line or not. This will 162 // break if you do "assert(\nfoo && bar)" and we may show the second line 163 // as the source, oh well. The way around this is to check to see if the 164 // origin node is inside our function call block. 165 Location origin_location = args[0].origin()->GetRange().begin(); 166 if (origin_location.file() != function->function().location().file() || 167 origin_location.line_number() != 168 function->function().location().line_number()) { 169 err->AppendSubErr(Err(args[0].origin()->GetRange(), "", 170 "This is where it was set.")); 171 } 172 } 173 } 174 return Value(); 175} 176 177// config ---------------------------------------------------------------------- 178 179const char kConfig[] = "config"; 180const char kConfig_HelpShort[] = 181 "config: Defines a configuration object."; 182const char kConfig_Help[] = 183 "config: Defines a configuration object.\n" 184 "\n" 185 " Configuration objects can be applied to targets and specify sets of\n" 186 " compiler flags, includes, defines, etc. They provide a way to\n" 187 " conveniently group sets of this configuration information.\n" 188 "\n" 189 " A config is referenced by its label just like a target.\n" 190 "\n" 191 " The values in a config are additive only. If you want to remove a flag\n" 192 " you need to remove the corresponding config that sets it. The final\n" 193 " set of flags, defines, etc. for a target is generated in this order:\n" 194 "\n" 195 " 1. The values specified directly on the target (rather than using a\n" 196 " config.\n" 197 " 2. The configs specified in the target's \"configs\" list, in order.\n" 198 " 3. Direct dependent configs from a breadth-first traversal of the\n" 199 " dependency tree in the order that the targets appear in \"deps\".\n" 200 " 4. All dependent configs from a breadth-first traversal of the\n" 201 " dependency tree in the order that the targets appear in \"deps\".\n" 202 "\n" 203 "Variables valid in a config definition:\n" 204 CONFIG_VALUES_VARS_HELP 205 "\n" 206 "Variables on a target used to apply configs:\n" 207 " all_dependent_configs, configs, direct_dependent_configs,\n" 208 " forward_dependent_configs_from\n" 209 "\n" 210 "Example:\n" 211 " config(\"myconfig\") {\n" 212 " includes = [ \"include/common\" ]\n" 213 " defines = [ \"ENABLE_DOOM_MELON\" ]\n" 214 " }\n" 215 "\n" 216 " executable(\"mything\") {\n" 217 " configs = [ \":myconfig\" ]\n" 218 " }\n"; 219 220Value RunConfig(const FunctionCallNode* function, 221 const std::vector<Value>& args, 222 Scope* scope, 223 Err* err) { 224 if (!EnsureSingleStringArg(function, args, err) || 225 !EnsureNotProcessingImport(function, scope, err)) 226 return Value(); 227 228 Label label(MakeLabelForScope(scope, function, args[0].string_value())); 229 230 if (g_scheduler->verbose_logging()) 231 g_scheduler->Log("Defining config", label.GetUserVisibleName(true)); 232 233 // Create the new config. 234 scoped_ptr<Config> config(new Config(scope->settings(), label)); 235 config->set_defined_from(function); 236 if (!Visibility::FillItemVisibility(config.get(), scope, err)) 237 return Value(); 238 239 // Fill it. 240 const SourceDir& input_dir = scope->GetSourceDir(); 241 ConfigValuesGenerator gen(&config->config_values(), scope, input_dir, err); 242 gen.Run(); 243 if (err->has_error()) 244 return Value(); 245 246 // Mark as complete. 247 scope->settings()->build_settings()->ItemDefined(config.PassAs<Item>()); 248 return Value(); 249} 250 251// declare_args ---------------------------------------------------------------- 252 253const char kDeclareArgs[] = "declare_args"; 254const char kDeclareArgs_HelpShort[] = 255 "declare_args: Declare build arguments."; 256const char kDeclareArgs_Help[] = 257 "declare_args: Declare build arguments.\n" 258 "\n" 259 " Introduces the given arguments into the current scope. If they are\n" 260 " not specified on the command line or in a toolchain's arguments,\n" 261 " the default values given in the declare_args block will be used.\n" 262 " However, these defaults will not override command-line values.\n" 263 "\n" 264 " See also \"gn help buildargs\" for an overview.\n" 265 "\n" 266 "Example:\n" 267 " declare_args() {\n" 268 " enable_teleporter = true\n" 269 " enable_doom_melon = false\n" 270 " }\n" 271 "\n" 272 " If you want to override the (default disabled) Doom Melon:\n" 273 " gn --args=\"enable_doom_melon=true enable_teleporter=false\"\n" 274 " This also sets the teleporter, but it's already defaulted to on so\n" 275 " it will have no effect.\n"; 276 277Value RunDeclareArgs(Scope* scope, 278 const FunctionCallNode* function, 279 const std::vector<Value>& args, 280 BlockNode* block, 281 Err* err) { 282 Scope block_scope(scope); 283 block->ExecuteBlockInScope(&block_scope, err); 284 if (err->has_error()) 285 return Value(); 286 287 // Pass the values from our scope into the Args object for adding to the 288 // scope with the proper values (taking into account the defaults given in 289 // the block_scope, and arguments passed into the build). 290 Scope::KeyValueMap values; 291 block_scope.GetCurrentScopeValues(&values); 292 scope->settings()->build_settings()->build_args().DeclareArgs( 293 values, scope, err); 294 return Value(); 295} 296 297// defined --------------------------------------------------------------------- 298 299const char kDefined[] = "defined"; 300const char kDefined_HelpShort[] = 301 "defined: Returns whether an identifier is defined."; 302const char kDefined_Help[] = 303 "defined: Returns whether an identifier is defined.\n" 304 "\n" 305 " Returns true if the given argument is defined. This is most useful in\n" 306 " templates to assert that the caller set things up properly.\n" 307 "\n" 308 " You can pass an identifier:\n" 309 " defined(foo)\n" 310 " which will return true or false depending on whether foo is defined in\n" 311 " the current scope.\n" 312 "\n" 313 " You can also check a named scope:\n" 314 " defined(foo.bar)\n" 315 " which returns true if both foo is defined and bar is defined on the\n" 316 " named scope foo. It will throw an error if foo is defined but is not\n" 317 " a scope.\n" 318 "\n" 319 "Example:\n" 320 "\n" 321 " template(\"mytemplate\") {\n" 322 " # To help users call this template properly...\n" 323 " assert(defined(invoker.sources), \"Sources must be defined\")\n" 324 "\n" 325 " # If we want to accept an optional \"values\" argument, we don't\n" 326 " # want to dereference something that may not be defined.\n" 327 " if (defined(invoker.values)) {\n" 328 " values = invoker.values\n" 329 " } else {\n" 330 " values = \"some default value\"\n" 331 " }\n" 332 " }\n"; 333 334Value RunDefined(Scope* scope, 335 const FunctionCallNode* function, 336 const ListNode* args_list, 337 Err* err) { 338 const std::vector<const ParseNode*>& args_vector = args_list->contents(); 339 if (args_vector.size() != 1) { 340 *err = Err(function, "Wrong number of arguments to defined().", 341 "Expecting exactly one."); 342 return Value(); 343 } 344 345 const IdentifierNode* identifier = args_vector[0]->AsIdentifier(); 346 if (identifier) { 347 // Passed an identifier "defined(foo)". 348 if (scope->GetValue(identifier->value().value())) 349 return Value(function, true); 350 return Value(function, false); 351 } 352 353 const AccessorNode* accessor = args_vector[0]->AsAccessor(); 354 if (accessor) { 355 // Passed an accessor "defined(foo.bar)". 356 if (accessor->member()) { 357 // The base of the accessor must be a scope if it's defined. 358 const Value* base = scope->GetValue(accessor->base().value()); 359 if (!base) 360 return Value(function, false); 361 if (!base->VerifyTypeIs(Value::SCOPE, err)) 362 return Value(); 363 364 // Check the member inside the scope to see if its defined. 365 if (base->scope_value()->GetValue(accessor->member()->value().value())) 366 return Value(function, true); 367 return Value(function, false); 368 } 369 } 370 371 // Argument is invalid. 372 *err = Err(function, "Bad thing passed to defined().", 373 "It should be of the form defined(foo) or defined(foo.bar)."); 374 return Value(); 375} 376 377// getenv ---------------------------------------------------------------------- 378 379const char kGetEnv[] = "getenv"; 380const char kGetEnv_HelpShort[] = 381 "getenv: Get an environment variable."; 382const char kGetEnv_Help[] = 383 "getenv: Get an environment variable.\n" 384 "\n" 385 " value = getenv(env_var_name)\n" 386 "\n" 387 " Returns the value of the given enironment variable. If the value is\n" 388 " not found, it will try to look up the variable with the \"opposite\"\n" 389 " case (based on the case of the first letter of the variable), but\n" 390 " is otherwise case-sensitive.\n" 391 "\n" 392 " If the environment variable is not found, the empty string will be\n" 393 " returned. Note: it might be nice to extend this if we had the concept\n" 394 " of \"none\" in the language to indicate lookup failure.\n" 395 "\n" 396 "Example:\n" 397 "\n" 398 " home_dir = getenv(\"HOME\")\n"; 399 400Value RunGetEnv(Scope* scope, 401 const FunctionCallNode* function, 402 const std::vector<Value>& args, 403 Err* err) { 404 if (!EnsureSingleStringArg(function, args, err)) 405 return Value(); 406 407 scoped_ptr<base::Environment> env(base::Environment::Create()); 408 409 std::string result; 410 if (!env->GetVar(args[0].string_value().c_str(), &result)) 411 return Value(function, ""); // Not found, return empty string. 412 return Value(function, result); 413} 414 415// import ---------------------------------------------------------------------- 416 417const char kImport[] = "import"; 418const char kImport_HelpShort[] = 419 "import: Import a file into the current scope."; 420const char kImport_Help[] = 421 "import: Import a file into the current scope.\n" 422 "\n" 423 " The import command loads the rules and variables resulting from\n" 424 " executing the given file into the current scope.\n" 425 "\n" 426 " By convention, imported files are named with a .gni extension.\n" 427 "\n" 428 " An import is different than a C++ \"include\". The imported file is\n" 429 " executed in a standalone environment from the caller of the import\n" 430 " command. The results of this execution are cached for other files that\n" 431 " import the same .gni file.\n" 432 "\n" 433 " Note that you can not import a BUILD.gn file that's otherwise used\n" 434 " in the build. Files must either be imported or implicitly loaded as\n" 435 " a result of deps rules, but not both.\n" 436 "\n" 437 " The imported file's scope will be merged with the scope at the point\n" 438 " import was called. If there is a conflict (both the current scope and\n" 439 " the imported file define some variable or rule with the same name but\n" 440 " different value), a runtime error will be thrown. Therefore, it's good\n" 441 " practice to minimize the stuff that an imported file defines.\n" 442 "\n" 443 "Examples:\n" 444 "\n" 445 " import(\"//build/rules/idl_compilation_rule.gni\")\n" 446 "\n" 447 " # Looks in the current directory.\n" 448 " import(\"my_vars.gni\")\n"; 449 450Value RunImport(Scope* scope, 451 const FunctionCallNode* function, 452 const std::vector<Value>& args, 453 Err* err) { 454 if (!EnsureSingleStringArg(function, args, err)) 455 return Value(); 456 457 const SourceDir& input_dir = scope->GetSourceDir(); 458 SourceFile import_file = 459 input_dir.ResolveRelativeFile(args[0].string_value()); 460 scope->settings()->import_manager().DoImport(import_file, function, 461 scope, err); 462 return Value(); 463} 464 465// set_sources_assignment_filter ----------------------------------------------- 466 467const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter"; 468const char kSetSourcesAssignmentFilter_HelpShort[] = 469 "set_sources_assignment_filter: Set a pattern to filter source files."; 470const char kSetSourcesAssignmentFilter_Help[] = 471 "set_sources_assignment_filter: Set a pattern to filter source files.\n" 472 "\n" 473 " The sources assignment filter is a list of patterns that remove files\n" 474 " from the list implicitly whenever the \"sources\" variable is\n" 475 " assigned to. This is intended to be used to globally filter out files\n" 476 " with platform-specific naming schemes when they don't apply, for\n" 477 " example, you may want to filter out all \"*_win.cc\" files on non-\n" 478 " Windows platforms.\n" 479 "\n" 480 " See \"gn help patterns\" for specifics on patterns.\n" 481 "\n" 482 " Typically this will be called once in the master build config script\n" 483 " to set up the filter for the current platform. Subsequent calls will\n" 484 " overwrite the previous values.\n" 485 "\n" 486 " If you want to bypass the filter and add a file even if it might\n" 487 " be filtered out, call set_sources_assignment_filter([]) to clear the\n" 488 " list of filters. This will apply until the current scope exits\n" 489 "\n" 490 "Example:\n" 491 " # Filter out all _win files.\n" 492 " set_sources_assignment_filter([ \"*_win.cc\", \"*_win.h\" ])\n"; 493 494Value RunSetSourcesAssignmentFilter(Scope* scope, 495 const FunctionCallNode* function, 496 const std::vector<Value>& args, 497 Err* err) { 498 if (args.size() != 1) { 499 *err = Err(function, "set_sources_assignment_filter takes one argument."); 500 } else { 501 scoped_ptr<PatternList> f(new PatternList); 502 f->SetFromValue(args[0], err); 503 if (!err->has_error()) 504 scope->set_sources_assignment_filter(f.Pass()); 505 } 506 return Value(); 507} 508 509// print ----------------------------------------------------------------------- 510 511const char kPrint[] = "print"; 512const char kPrint_HelpShort[] = 513 "print: Prints to the console."; 514const char kPrint_Help[] = 515 "print: Prints to the console.\n" 516 "\n" 517 " Prints all arguments to the console separated by spaces. A newline is\n" 518 " automatically appended to the end.\n" 519 "\n" 520 " This function is intended for debugging. Note that build files are run\n" 521 " in parallel so you may get interleaved prints. A buildfile may also\n" 522 " be executed more than once in parallel in the context of different\n" 523 " toolchains so the prints from one file may be duplicated or\n" 524 " interleaved with itself.\n" 525 "\n" 526 "Examples:\n" 527 " print(\"Hello world\")\n" 528 "\n" 529 " print(sources, deps)\n"; 530 531Value RunPrint(Scope* scope, 532 const FunctionCallNode* function, 533 const std::vector<Value>& args, 534 Err* err) { 535 std::string output; 536 for (size_t i = 0; i < args.size(); i++) { 537 if (i != 0) 538 output.push_back(' '); 539 output.append(args[i].ToString(false)); 540 } 541 output.push_back('\n'); 542 543 const BuildSettings::PrintCallback& cb = 544 scope->settings()->build_settings()->print_callback(); 545 if (cb.is_null()) 546 printf("%s", output.c_str()); 547 else 548 cb.Run(output); 549 550 return Value(); 551} 552 553// ----------------------------------------------------------------------------- 554 555FunctionInfo::FunctionInfo() 556 : self_evaluating_args_runner(NULL), 557 generic_block_runner(NULL), 558 executed_block_runner(NULL), 559 no_block_runner(NULL), 560 help_short(NULL), 561 help(NULL), 562 is_target(false) { 563} 564 565FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf, 566 const char* in_help_short, 567 const char* in_help, 568 bool in_is_target) 569 : self_evaluating_args_runner(seaf), 570 generic_block_runner(NULL), 571 executed_block_runner(NULL), 572 no_block_runner(NULL), 573 help_short(in_help_short), 574 help(in_help), 575 is_target(in_is_target) { 576} 577 578FunctionInfo::FunctionInfo(GenericBlockFunction gbf, 579 const char* in_help_short, 580 const char* in_help, 581 bool in_is_target) 582 : self_evaluating_args_runner(NULL), 583 generic_block_runner(gbf), 584 executed_block_runner(NULL), 585 no_block_runner(NULL), 586 help_short(in_help_short), 587 help(in_help), 588 is_target(in_is_target) { 589} 590 591FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, 592 const char* in_help_short, 593 const char* in_help, 594 bool in_is_target) 595 : self_evaluating_args_runner(NULL), 596 generic_block_runner(NULL), 597 executed_block_runner(ebf), 598 no_block_runner(NULL), 599 help_short(in_help_short), 600 help(in_help), 601 is_target(in_is_target) { 602} 603 604FunctionInfo::FunctionInfo(NoBlockFunction nbf, 605 const char* in_help_short, 606 const char* in_help, 607 bool in_is_target) 608 : self_evaluating_args_runner(NULL), 609 generic_block_runner(NULL), 610 executed_block_runner(NULL), 611 no_block_runner(nbf), 612 help_short(in_help_short), 613 help(in_help), 614 is_target(in_is_target) { 615} 616 617// Setup the function map via a static initializer. We use this because it 618// avoids race conditions without having to do some global setup function or 619// locking-heavy singleton checks at runtime. In practice, we always need this 620// before we can do anything interesting, so it's OK to wait for the 621// initializer. 622struct FunctionInfoInitializer { 623 FunctionInfoMap map; 624 625 FunctionInfoInitializer() { 626 #define INSERT_FUNCTION(command, is_target) \ 627 map[k##command] = FunctionInfo(&Run##command, \ 628 k##command##_HelpShort, \ 629 k##command##_Help, \ 630 is_target); 631 632 INSERT_FUNCTION(Action, true) 633 INSERT_FUNCTION(ActionForEach, true) 634 INSERT_FUNCTION(Component, true) 635 INSERT_FUNCTION(Executable, true) 636 INSERT_FUNCTION(Group, true) 637 INSERT_FUNCTION(SharedLibrary, true) 638 INSERT_FUNCTION(SourceSet, true) 639 INSERT_FUNCTION(StaticLibrary, true) 640 INSERT_FUNCTION(Test, true) 641 642 INSERT_FUNCTION(Assert, false) 643 INSERT_FUNCTION(Config, false) 644 INSERT_FUNCTION(Copy, false) 645 INSERT_FUNCTION(DeclareArgs, false) 646 INSERT_FUNCTION(Defined, false) 647 INSERT_FUNCTION(ExecScript, false) 648 INSERT_FUNCTION(GetEnv, false) 649 INSERT_FUNCTION(Import, false) 650 INSERT_FUNCTION(Print, false) 651 INSERT_FUNCTION(ProcessFileTemplate, false) 652 INSERT_FUNCTION(ReadFile, false) 653 INSERT_FUNCTION(RebasePath, false) 654 INSERT_FUNCTION(SetDefaults, false) 655 INSERT_FUNCTION(SetDefaultToolchain, false) 656 INSERT_FUNCTION(SetSourcesAssignmentFilter, false) 657 INSERT_FUNCTION(Template, false) 658 INSERT_FUNCTION(Tool, false) 659 INSERT_FUNCTION(Toolchain, false) 660 INSERT_FUNCTION(ToolchainArgs, false) 661 INSERT_FUNCTION(WriteFile, false) 662 663 #undef INSERT_FUNCTION 664 } 665}; 666const FunctionInfoInitializer function_info; 667 668const FunctionInfoMap& GetFunctions() { 669 return function_info.map; 670} 671 672Value RunFunction(Scope* scope, 673 const FunctionCallNode* function, 674 const ListNode* args_list, 675 BlockNode* block, 676 Err* err) { 677 const Token& name = function->function(); 678 679 const FunctionInfoMap& function_map = GetFunctions(); 680 FunctionInfoMap::const_iterator found_function = 681 function_map.find(name.value()); 682 if (found_function == function_map.end()) { 683 // No built-in function matching this, check for a template. 684 const Template* templ = 685 scope->GetTemplate(function->function().value().as_string()); 686 if (templ) { 687 Value args = args_list->Execute(scope, err); 688 if (err->has_error()) 689 return Value(); 690 return templ->Invoke(scope, function, args.list_value(), block, err); 691 } 692 693 *err = Err(name, "Unknown function."); 694 return Value(); 695 } 696 697 if (found_function->second.self_evaluating_args_runner) { 698 return found_function->second.self_evaluating_args_runner( 699 scope, function, args_list, err); 700 } 701 702 // All other function types take a pre-executed set of args. 703 Value args = args_list->Execute(scope, err); 704 if (err->has_error()) 705 return Value(); 706 707 if (found_function->second.generic_block_runner) { 708 if (!block) { 709 FillNeedsBlockError(function, err); 710 return Value(); 711 } 712 return found_function->second.generic_block_runner( 713 scope, function, args.list_value(), block, err); 714 } 715 716 if (found_function->second.executed_block_runner) { 717 if (!block) { 718 FillNeedsBlockError(function, err); 719 return Value(); 720 } 721 722 Scope block_scope(scope); 723 block->ExecuteBlockInScope(&block_scope, err); 724 if (err->has_error()) 725 return Value(); 726 return found_function->second.executed_block_runner( 727 function, args.list_value(), &block_scope, err); 728 } 729 730 // Otherwise it's a no-block function. 731 return found_function->second.no_block_runner(scope, function, 732 args.list_value(), err); 733} 734 735} // namespace functions 736