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