functions.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// found in the LICENSE file.
4d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
5d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/functions.h"
6d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include <iostream>
8d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
9d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_util.h"
10d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config.h"
11d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/config_values_generator.h"
12d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/err.h"
13d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/input_file.h"
14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/item_tree.h"
15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/parse_tree.h"
16d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scheduler.h"
17d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/scope.h"
18d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/settings.h"
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/target_manager.h"
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/token.h"
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "tools/gn/value.h"
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochnamespace {
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This is called when a template is invoked. When we see a template
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declaration, that funciton is RunTemplate.
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunTemplateInvocation(Scope* scope,
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const FunctionCallNode* invocation,
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const std::vector<Value>& args,
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            BlockNode* block,
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const FunctionCallNode* rule,
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            Err* err) {
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!EnsureNotProcessingImport(invocation, scope, err))
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Scope block_scope(scope);
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!FillTargetBlockScope(scope, invocation,
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            invocation->function().value().as_string(),
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            block, args, &block_scope, err))
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Run the block for the rule invocation.
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block->ExecuteBlockInScope(&block_scope, err);
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (err->has_error())
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Now run the rule itself with that block as the current scope.
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  rule->block()->ExecuteBlockInScope(&block_scope, err);
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (err->has_error())
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return Value();
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// ----------------------------------------------------------------------------
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingImport(const ParseNode* node,
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               const Scope* scope,
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               Err* err) {
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (scope->IsProcessingImport()) {
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(node, "Not valid from an import.",
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        "Imports are for defining defaults, variables, and rules. The\n"
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        "appropriate place for this kind of thing is really in a normal\n"
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "BUILD file.");
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureNotProcessingBuildConfig(const ParseNode* node,
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const Scope* scope,
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    Err* err) {
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (scope->IsProcessingBuildConfig()) {
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(node, "Not valid from the build config.",
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "You can't do this kind of thing from the build config script, "
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        "silly!\nPut it in a regular BUILD file.");
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool FillTargetBlockScope(const Scope* scope,
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const FunctionCallNode* function,
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          const std::string& target_type,
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const BlockNode* block,
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          const std::vector<Value>& args,
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          Scope* block_scope,
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                          Err* err) {
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!block) {
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    FillNeedsBlockError(function, err);
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Copy the target defaults, if any, into the scope we're going to execute
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the block in.
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Scope* default_scope = scope->GetTargetDefaults(target_type);
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (default_scope) {
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!default_scope->NonRecursiveMergeTo(block_scope, function,
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            "target defaults", err))
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return false;
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The name is the single argument to the target function.
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!EnsureSingleStringArg(function, args, err))
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Set the target name variable to the current target, and mark it used
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // because we don't want to issue an error if the script ignores it.
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const base::StringPiece target_name("target_name");
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block_scope->SetValue(target_name, Value(function, args[0].string_value()),
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        function);
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  block_scope->MarkUsed(target_name);
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *err = Err(function->function(), "This function call requires a block.",
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "The block's \"{\" must be on the same line as the function "
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "call's \")\".");
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool EnsureSingleStringArg(const FunctionCallNode* function,
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           const std::vector<Value>& args,
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           Err* err) {
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (args.size() != 1) {
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(function->function(), "Incorrect arguments.",
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               "This function requires a single string argument.");
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return args[0].VerifyTypeIs(Value::STRING, err);
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const Label& ToolchainLabelForScope(const Scope* scope) {
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return scope->settings()->toolchain()->label();
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Label MakeLabelForScope(const Scope* scope,
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const FunctionCallNode* function,
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                        const std::string& name) {
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Label& toolchain_label = ToolchainLabelForScope(scope);
1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Label(scope->GetSourceDir(), name, toolchain_label.dir(),
1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               toolchain_label.name());
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace functions {
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// assert ----------------------------------------------------------------------
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert[] = "assert";
152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kAssert_Help[] =
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "assert: Assert an expression is true at generation time.\n"
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  assert(<condition> [, <error string>])\n"
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  If the condition is false, the build will fail with an error. If the\n"
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  optional second argument is provided, that string will be printed\n"
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  with the error message.\n"
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Examples:\n"
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  assert(is_win)\n"
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  assert(defined(sources), \"Sources must be defined\")\n";
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunAssert(Scope* scope,
166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const FunctionCallNode* function,
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (args.size() != 1 && args.size() != 2) {
170d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function->function(), "Wrong number of arguments.",
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               "assert() takes one or two argument, "
172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               "were you expecting somethig else?");
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (args[0].type() != Value::BOOLEAN) {
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *err = Err(function->function(), "Assertion value not a bool.");
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (!args[0].boolean_value()) {
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (args.size() == 2) {
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      // Optional string message.
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (args[1].type() != Value::STRING) {
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *err = Err(function->function(), "Assertion failed.",
1803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            "<<<ERROR MESSAGE IS NOT A STRING>>>");
1813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      } else {
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        *err = Err(function->function(), "Assertion failed.",
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            args[1].string_value());
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    } else {
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      *err = Err(function->function(), "Assertion failed.");
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
189d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (args[0].origin()) {
190d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // If you do "assert(foo)" we'd ideally like to show you where foo was
191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // set, and in this case the origin of the args will tell us that.
192d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // However, if you do "assert(foo && bar)" the source of the value will
193d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // be the assert like, which isn't so helpful.
194d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      //
195d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // So we try to see if the args are from the same line or not. This will
196d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // break if you do "assert(\nfoo && bar)" and we may show the second line
197d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // as the source, oh well. The way around this is to check to see if the
198d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // origin node is inside our function call block.
199d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      Location origin_location = args[0].origin()->GetRange().begin();
200d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (origin_location.file() != function->function().location().file() ||
201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          origin_location.line_number() !=
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch              function->function().location().line_number()) {
203d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                              "This is where it was set."));
205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
206d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    }
207d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
208d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
209d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
210d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// config ----------------------------------------------------------------------
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig[] = "config";
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kConfig_Help[] =
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunConfig(const FunctionCallNode* function,
218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Scope* scope,
220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
221d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
222d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
223d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
224d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
225d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Label label(MakeLabelForScope(scope, function, args[0].string_value()));
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
227d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (g_scheduler->verbose_logging())
228d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    g_scheduler->Log("Generating config", label.GetUserVisibleName(true));
229d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
230d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Create the empty config object.
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ItemTree* tree = &scope->settings()->build_settings()->item_tree();
232d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  Config* config = Config::GetConfig(scope->settings(), function->GetRange(),
233d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                     label, NULL, err);
234d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
236d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
237d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Fill it.
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const SourceDir& input_dir = scope->GetSourceDir();
239d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ConfigValuesGenerator gen(&config->config_values(), scope,
240d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                            function->function(), input_dir, err);
241d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  gen.Run();
242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (err->has_error())
243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Mark as complete.
246d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  {
247d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    base::AutoLock lock(tree->lock());
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    tree->MarkItemDefinedLocked(scope->settings()->build_settings(), label,
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                err);
250d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
251d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
253d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// declare_args ----------------------------------------------------------------
255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs[] = "declare_args";
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kDeclareArgs_Help[] =
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "declare_args: Declare build arguments used by this file.\n"
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  Introduces the given arguments into the current scope. If they are\n"
2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  not specified on the command line or in a toolchain's arguments,\n"
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  the default values given in the declare_args block will be used.\n"
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  However, these defaults will not override command-line values.\n"
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  See also \"gn help buildargs\" for an overview.\n"
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Example:\n"
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  declare_args() {\n"
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    enable_teleporter = true\n"
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    enable_doom_melon = false\n"
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  }\n"
2723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  If you want to override the (default disabled) Doom Melon:\n"
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    gn --args=\"enable_doom_melon=true enable_teleporter=false\"\n"
2753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  This also sets the teleporter, but it's already defaulted to on so\n"
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  it will have no effect.\n";
277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunDeclareArgs(Scope* scope,
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     const FunctionCallNode* function,
280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     const std::vector<Value>& args,
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                     BlockNode* block,
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                     Err* err) {
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Scope block_scope(scope);
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  block->ExecuteBlockInScope(&block_scope, err);
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err->has_error())
286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Pass the values from our scope into the Args object for adding to the
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // scope with the proper values (taking into account the defaults given in
2903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // the block_scope, and arguments passed into the build).
2913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Scope::KeyValueMap values;
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  block_scope.GetCurrentScopeValues(&values);
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scope->settings()->build_settings()->build_args().DeclareArgs(
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      values, scope, err);
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Value();
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// defined ---------------------------------------------------------------------
299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDefined[] = "defined";
3013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const char kDefined_Help[] =
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "defined: Returns whether an identifier is defined.\n"
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  Returns true if the given argument is defined. This is most useful in\n"
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  templates to assert that the caller set things up properly.\n"
3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "Example:\n"
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  template(\"mytemplate\") {\n"
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    # To help users call this template properly...\n"
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    assert(defined(sources), \"Sources must be defined\")\n"
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "\n"
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    # If we want to accept an optional \"values\" argument, we don't\n"
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    # want to dereference something that may not be defined.\n"
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    if (!defined(outputs)) {\n"
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "      outputs = []\n"
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "    }\n"
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    "  }\n";
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Value RunDefined(Scope* scope,
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 const FunctionCallNode* function,
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 const ListNode* args_list,
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 Err* err) {
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const std::vector<const ParseNode*>& args_vector = args_list->contents();
3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const IdentifierNode* identifier = NULL;
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (args_vector.size() != 1 ||
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      !(identifier = args_vector[0]->AsIdentifier())) {
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *err = Err(function, "Bad argument to defined().",
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        "defined() takes one argument which should be an identifier.");
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
331d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
332d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (scope->GetValue(identifier->value().value()))
3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value(function, true);
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return Value(function, false);
336d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
337d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// import ----------------------------------------------------------------------
339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport[] = "import";
341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kImport_Help[] =
342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "import: Import a file into the current scope.\n"
343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  The import command loads the rules and variables resulting from\n"
345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  executing the given file into the current scope.\n"
346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  By convention, imported files are named with a .gni extension.\n"
348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  It does not do an \"include\". The imported file is executed in a\n"
350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  standalone environment from the caller of the import command. The\n"
351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  results of this execution are cached for other files that import the\n"
352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  same .gni file.\n"
353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  Note that you can not import a BUILD.gn file that's otherwise used\n"
355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  in the build. Files must either be imported or implicitly loaded as\n"
356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  a result of deps rules, but not both.\n"
357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  The imported file's scope will be merged with the scope at the point\n"
359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import was called. If there is a conflict (both the current scope and\n"
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  the imported file define some variable or rule with the same name)\n"
361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  a runtime error will be thrown. Therefore, it's good practice to\n"
362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  minimize the stuff that an imported file defines.\n"
363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "Examples:\n"
365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import(\"//build/rules/idl_compilation_rule.gni\")\n"
367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  # Looks in the current directory.\n"
369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  import(\"my_vars.gni\")\n";
370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunImport(Scope* scope,
372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const FunctionCallNode* function,
373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                const std::vector<Value>& args,
374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                Err* err) {
375d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!EnsureSingleStringArg(function, args, err) ||
376d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      !EnsureNotProcessingImport(function, scope, err))
377d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return Value();
378d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const SourceDir& input_dir = scope->GetSourceDir();
380d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  SourceFile import_file =
381d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      input_dir.ResolveRelativeFile(args[0].string_value());
382d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scope->settings()->import_manager().DoImport(import_file, function,
383d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                                               scope, err);
384d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
386d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// set_sources_assignment_filter -----------------------------------------------
388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kSetSourcesAssignmentFilter_Help[] =
391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "TODO(brettw) write this.";
392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunSetSourcesAssignmentFilter(Scope* scope,
394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const FunctionCallNode* function,
395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    const std::vector<Value>& args,
396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    Err* err) {
397d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (args.size() != 1) {
398d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    *err = Err(function, "set_sources_assignment_filter takes one argument.");
399d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  } else {
400d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<PatternList> f(new PatternList);
401d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    f->SetFromValue(args[0], err);
402d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!err->has_error())
403d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      scope->set_sources_assignment_filter(f.Pass());
404d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
405d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
406d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
407d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// print -----------------------------------------------------------------------
409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint[] = "print";
411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const char kPrint_Help[] =
412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "print(...)\n"
413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  Prints all arguments to the console separated by spaces. A newline is\n"
414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  automatically appended to the end.\n"
415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  This function is intended for debugging. Note that build files are run\n"
417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  in parallel so you may get interleaved prints. A buildfile may also\n"
418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  be executed more than once in parallel in the context of different\n"
419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  toolchains so the prints from one file may be duplicated or\n"
420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  interleaved with itself.\n"
421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "Examples:\n"
423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  print(\"Hello world\")\n"
424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "\n"
425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    "  print(sources, deps)\n";
426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunPrint(Scope* scope,
428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               const FunctionCallNode* function,
429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               const std::vector<Value>& args,
430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               Err* err) {
431d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (size_t i = 0; i < args.size(); i++) {
432d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (i != 0)
433d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      std::cout << " ";
4343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    std::cout << args[i].ToString(false);
435d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
436d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::cout << std::endl;
437d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Value();
438d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
439d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// -----------------------------------------------------------------------------
441d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo()
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(NULL) {
448d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
449d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf, const char* in_help)
4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(seaf),
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      executed_block_runner(NULL),
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      no_block_runner(NULL),
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      help(in_help) {
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help)
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(gbf),
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(in_help) {
464d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
465d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help)
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(ebf),
470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(NULL),
471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(in_help) {
472d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
473d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help)
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : self_evaluating_args_runner(NULL),
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      generic_block_runner(NULL),
477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      executed_block_runner(NULL),
478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      no_block_runner(nbf),
479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      help(in_help) {
480d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
481d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Setup the function map via a static initializer. We use this because it
483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// avoids race conditions without having to do some global setup function or
484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// locking-heavy singleton checks at runtime. In practice, we always need this
485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// before we can do anything interesting, so it's OK to wait for the
486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// initializer.
487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)struct FunctionInfoInitializer {
488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoMap map;
489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
490a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoInitializer() {
491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    #define INSERT_FUNCTION(command) \
492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        map[k##command] = FunctionInfo(&Run##command, k##command##_Help);
493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Assert)
495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Component)
496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Config)
497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Copy)
498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Custom)
499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(DeclareArgs)
5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    INSERT_FUNCTION(Defined)
501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(ExecScript)
502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Executable)
503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Group)
504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Import)
505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Print)
506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(ProcessFileTemplate)
507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(ReadFile)
508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SetDefaults)
509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SetDefaultToolchain)
510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SetSourcesAssignmentFilter)
511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(SharedLibrary)
512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(StaticLibrary)
513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Template)
514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Test)
515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    INSERT_FUNCTION(ToBuildPath)
516a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Tool)
517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(Toolchain)
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    INSERT_FUNCTION(ToolchainArgs)
519a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    INSERT_FUNCTION(WriteFile)
520a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
521a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    #undef INSERT_FUNCTION
522a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
523a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
524a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoInitializer function_info;
525d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
526a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const FunctionInfoMap& GetFunctions() {
527a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return function_info.map;
528d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
529d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
530a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)Value RunFunction(Scope* scope,
531a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  const FunctionCallNode* function,
5323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  const ListNode* args_list,
533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  BlockNode* block,
534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  Err* err) {
535d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  const Token& name = function->function();
536d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
537a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const FunctionInfoMap& function_map = GetFunctions();
538a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  FunctionInfoMap::const_iterator found_function =
539a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      function_map.find(name.value());
540a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function == function_map.end()) {
541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // No build-in function matching this, check for a template.
542d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const FunctionCallNode* rule =
543d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        scope->GetTemplate(function->function().value().as_string());
5443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (rule) {
5453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Value args = args_list->Execute(scope, err);
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (err->has_error())
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return Value();
5483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return RunTemplateInvocation(scope, function, args.list_value(), block,
5493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                   rule, err);
5503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
551d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
552a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *err = Err(name, "Unknown function.");
553a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return Value();
554a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
555a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (found_function->second.self_evaluating_args_runner) {
5573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return found_function->second.self_evaluating_args_runner(
5583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        scope, function, args_list, err);
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // All other function types take a pre-executed set of args.
5623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Value args = args_list->Execute(scope, err);
5633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (err->has_error())
5643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return Value();
5653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
566a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function->second.generic_block_runner) {
567a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!block) {
568a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FillNeedsBlockError(function, err);
569a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return Value();
570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return found_function->second.generic_block_runner(
5723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        scope, function, args.list_value(), block, err);
573a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (found_function->second.executed_block_runner) {
576a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!block) {
577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FillNeedsBlockError(function, err);
578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return Value();
579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
580d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
581d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    Scope block_scope(scope);
582d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    block->ExecuteBlockInScope(&block_scope, err);
583d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (err->has_error())
584d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return Value();
585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return found_function->second.executed_block_runner(
5863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        function, args.list_value(), &block_scope, err);
587d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
588d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
589a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Otherwise it's a no-block function.
5903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return found_function->second.no_block_runner(scope, function,
5913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                args.list_value(), err);
592d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
593a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace functions
595