text: // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef TOOLS_GN_FUNCTIONS_H_
  #define TOOLS_GN_FUNCTIONS_H_
  
  #include <map>
  #include <string>
  #include <vector>
  
  #include "base/strings/string_piece.h"
  
  class Err;
  class BlockNode;
  class FunctionCallNode;
  class Label;
  class ListNode;
  class ParseNode;
  class Scope;
  class Token;
  class Value;
  
  // -----------------------------------------------------------------------------
  
  namespace functions {
  
  // This type of function invocation has no block and evaluates its arguments
  // itself rather than taking a pre-executed list. This allows us to implement
  // certain built-in functions.
  typedef Value (*SelfEvaluatingArgsFunction)(Scope* scope,
                                              const FunctionCallNode* function,
                                              const ListNode* args_list,
                                              Err* err);
  
  // This type of function invocation takes a block node that it will execute.
  typedef Value (*GenericBlockFunction)(Scope* scope,
                                        const FunctionCallNode* function,
                                        const std::vector<Value>& args,
                                        BlockNode* block,
                                        Err* err);
  
  // This type of function takes a block, but does not need to control execution
  // of it. The dispatch function will pre-execute the block and pass the
  // resulting block_scope to the function.
  typedef Value(*ExecutedBlockFunction)(const FunctionCallNode* function,
                                        const std::vector<Value>& args,
                                        Scope* block_scope,
                                        Err* err);
  
  // This type of function does not take a block. It just has arguments.
  typedef Value (*NoBlockFunction)(Scope* scope,
                                   const FunctionCallNode* function,
                                   const std::vector<Value>& args,
                                   Err* err);
  
  extern const char kAction[];
  extern const char kAction_HelpShort[];
  extern const char kAction_Help[];
  Value RunAction(Scope* scope,
                  const FunctionCallNode* function,
                  const std::vector<Value>& args,
                  BlockNode* block,
                  Err* err);
  
  extern const char kActionForEach[];
  extern const char kActionForEach_HelpShort[];
  extern const char kActionForEach_Help[];
  Value RunActionForEach(Scope* scope,
                         const FunctionCallNode* function,
                         const std::vector<Value>& args,
                         BlockNode* block,
                         Err* err);
  
  extern const char kAssert[];
  extern const char kAssert_HelpShort[];
  extern const char kAssert_Help[];
  Value RunAssert(Scope* scope,
                  const FunctionCallNode* function,
                  const std::vector<Value>& args,
                  Err* err);
  
  extern const char kConfig[];
  extern const char kConfig_HelpShort[];
  extern const char kConfig_Help[];
  Value RunConfig(const FunctionCallNode* function,
                  const std::vector<Value>& args,
                  Scope* block_scope,
                  Err* err);
  
  extern const char kCopy[];
  extern const char kCopy_HelpShort[];
  extern const char kCopy_Help[];
  Value RunCopy(const FunctionCallNode* function,
                const std::vector<Value>& args,
                Scope* block_scope,
                Err* err);
  
  extern const char kDeclareArgs[];
  extern const char kDeclareArgs_HelpShort[];
  extern const char kDeclareArgs_Help[];
  Value RunDeclareArgs(Scope* scope,
                       const FunctionCallNode* function,
                       const std::vector<Value>& args,
                       BlockNode* block,
                       Err* err);
  
  extern const char kDefined[];
  extern const char kDefined_HelpShort[];
  extern const char kDefined_Help[];
  Value RunDefined(Scope* scope,
                   const FunctionCallNode* function,
                   const ListNode* args_list,
                   Err* err);
  
  extern const char kExecScript[];
  extern const char kExecScript_HelpShort[];
  extern const char kExecScript_Help[];
  Value RunExecScript(Scope* scope,
                      const FunctionCallNode* function,
                      const std::vector<Value>& args,
                      Err* err);
  
  extern const char kExecutable[];
  extern const char kExecutable_HelpShort[];
  extern const char kExecutable_Help[];
  Value RunExecutable(Scope* scope,
                      const FunctionCallNode* function,
                      const std::vector<Value>& args,
                      BlockNode* block,
                      Err* err);
  
  extern const char kForEach[];
  extern const char kForEach_HelpShort[];
  extern const char kForEach_Help[];
  Value RunForEach(Scope* scope,
                   const FunctionCallNode* function,
                   const ListNode* args_list,
                   Err* err);
  
  extern const char kForwardVariablesFrom[];
  extern const char kForwardVariablesFrom_HelpShort[];
  extern const char kForwardVariablesFrom_Help[];
  Value RunForwardVariablesFrom(Scope* scope,
                                const FunctionCallNode* function,
                                const ListNode* args_list,
                                Err* err);
  
  extern const char kGetEnv[];
  extern const char kGetEnv_HelpShort[];
  extern const char kGetEnv_Help[];
  Value RunGetEnv(Scope* scope,
                  const FunctionCallNode* function,
                  const std::vector<Value>& args,
                  Err* err);
  
  extern const char kGetLabelInfo[];
  extern const char kGetLabelInfo_HelpShort[];
  extern const char kGetLabelInfo_Help[];
  Value RunGetLabelInfo(Scope* scope,
                        const FunctionCallNode* function,
                        const std::vector<Value>& args,
                        Err* err);
  
  extern const char kGetPathInfo[];
  extern const char kGetPathInfo_HelpShort[];
  extern const char kGetPathInfo_Help[];
  Value RunGetPathInfo(Scope* scope,
                       const FunctionCallNode* function,
                       const std::vector<Value>& args,
                       Err* err);
  
  extern const char kGetTargetOutputs[];
  extern const char kGetTargetOutputs_HelpShort[];
  extern const char kGetTargetOutputs_Help[];
  Value RunGetTargetOutputs(Scope* scope,
                            const FunctionCallNode* function,
                            const std::vector<Value>& args,
                            Err* err);
  
  extern const char kGroup[];
  extern const char kGroup_HelpShort[];
  extern const char kGroup_Help[];
  Value RunGroup(Scope* scope,
                 const FunctionCallNode* function,
                 const std::vector<Value>& args,
                 BlockNode* block,
                 Err* err);
  
  extern const char kImport[];
  extern const char kImport_HelpShort[];
  extern const char kImport_Help[];
  Value RunImport(Scope* scope,
                  const FunctionCallNode* function,
                  const std::vector<Value>& args,
                  Err* err);
  
  extern const char kLoadableModule[];
  extern const char kLoadableModule_HelpShort[];
  extern const char kLoadableModule_Help[];
  Value RunLoadableModule(Scope* scope,
                          const FunctionCallNode* function,
                          const std::vector<Value>& args,
                          BlockNode* block,
                          Err* err);
  
  extern const char kPrint[];
  extern const char kPrint_HelpShort[];
  extern const char kPrint_Help[];
  Value RunPrint(Scope* scope,
                 const FunctionCallNode* function,
                 const std::vector<Value>& args,
                 Err* err);
  
  extern const char kProcessFileTemplate[];
  extern const char kProcessFileTemplate_HelpShort[];
  extern const char kProcessFileTemplate_Help[];
  Value RunProcessFileTemplate(Scope* scope,
                               const FunctionCallNode* function,
                               const std::vector<Value>& args,
                               Err* err);
  
  extern const char kReadFile[];
  extern const char kReadFile_HelpShort[];
  extern const char kReadFile_Help[];
  Value RunReadFile(Scope* scope,
                    const FunctionCallNode* function,
                    const std::vector<Value>& args,
                    Err* err);
  
  extern const char kRebasePath[];
  extern const char kRebasePath_HelpShort[];
  extern const char kRebasePath_Help[];
  Value RunRebasePath(Scope* scope,
                      const FunctionCallNode* function,
                      const std::vector<Value>& args,
                      Err* err);
  
  extern const char kSetDefaults[];
  extern const char kSetDefaults_HelpShort[];
  extern const char kSetDefaults_Help[];
  Value RunSetDefaults(Scope* scope,
                       const FunctionCallNode* function,
                       const std::vector<Value>& args,
                       BlockNode* block,
                       Err* err);
  
  extern const char kSetDefaultToolchain[];
  extern const char kSetDefaultToolchain_HelpShort[];
  extern const char kSetDefaultToolchain_Help[];
  Value RunSetDefaultToolchain(Scope* scope,
                               const FunctionCallNode* function,
                               const std::vector<Value>& args,
                               Err* err);
  
  extern const char kSetSourcesAssignmentFilter[];
  extern const char kSetSourcesAssignmentFilter_HelpShort[];
  extern const char kSetSourcesAssignmentFilter_Help[];
  Value RunSetSourcesAssignmentFilter(Scope* scope,
                                      const FunctionCallNode* function,
                                      const std::vector<Value>& args,
                                      Err* err);
  
  extern const char kSharedLibrary[];
  extern const char kSharedLibrary_HelpShort[];
  extern const char kSharedLibrary_Help[];
  Value RunSharedLibrary(Scope* scope,
                         const FunctionCallNode* function,
                         const std::vector<Value>& args,
                         BlockNode* block,
                         Err* err);
  
  extern const char kSourceSet[];
  extern const char kSourceSet_HelpShort[];
  extern const char kSourceSet_Help[];
  Value RunSourceSet(Scope* scope,
                     const FunctionCallNode* function,
                     const std::vector<Value>& args,
                     BlockNode* block,
                     Err* err);
  
  extern const char kStaticLibrary[];
  extern const char kStaticLibrary_HelpShort[];
  extern const char kStaticLibrary_Help[];
  Value RunStaticLibrary(Scope* scope,
                         const FunctionCallNode* function,
                         const std::vector<Value>& args,
                         BlockNode* block,
                         Err* err);
  
  extern const char kTarget[];
  extern const char kTarget_HelpShort[];
  extern const char kTarget_Help[];
  Value RunTarget(Scope* scope,
                  const FunctionCallNode* function,
                  const std::vector<Value>& args,
                  BlockNode* block,
                  Err* err);
  
  extern const char kTemplate[];
  extern const char kTemplate_HelpShort[];
  extern const char kTemplate_Help[];
  Value RunTemplate(Scope* scope,
                    const FunctionCallNode* function,
                    const std::vector<Value>& args,
                    BlockNode* block,
                    Err* err);
  
  extern const char kTool[];
  extern const char kTool_HelpShort[];
  extern const char kTool_Help[];
  Value RunTool(Scope* scope,
                const FunctionCallNode* function,
                const std::vector<Value>& args,
                BlockNode* block,
                Err* err);
  
  extern const char kToolchain[];
  extern const char kToolchain_HelpShort[];
  extern const char kToolchain_Help[];
  Value RunToolchain(Scope* scope,
                     const FunctionCallNode* function,
                     const std::vector<Value>& args,
                     BlockNode* block,
                     Err* err);
  
  extern const char kToolchainArgs[];
  extern const char kToolchainArgs_HelpShort[];
  extern const char kToolchainArgs_Help[];
  Value RunToolchainArgs(Scope* scope,
                         const FunctionCallNode* function,
                         const std::vector<Value>& args,
                         BlockNode* block,
                         Err* err);
  
  extern const char kWriteFile[];
  extern const char kWriteFile_HelpShort[];
  extern const char kWriteFile_Help[];
  Value RunWriteFile(Scope* scope,
                     const FunctionCallNode* function,
                     const std::vector<Value>& args,
                     Err* err);
  
  // -----------------------------------------------------------------------------
  
  // One function record. Only one of the given runner types will be non-null
  // which indicates the type of function it is.
  struct FunctionInfo {
    FunctionInfo();
    FunctionInfo(SelfEvaluatingArgsFunction seaf,
                 const char* in_help_short,
                 const char* in_help,
                 bool in_is_target);
    FunctionInfo(GenericBlockFunction gbf,
                 const char* in_help_short,
                 const char* in_help,
                 bool in_is_target);
    FunctionInfo(ExecutedBlockFunction ebf,
                 const char* in_help_short,
                 const char* in_help,
                 bool in_is_target);
    FunctionInfo(NoBlockFunction nbf,
                 const char* in_help_short,
                 const char* in_help,
                 bool in_is_target);
  
    SelfEvaluatingArgsFunction self_evaluating_args_runner;
    GenericBlockFunction generic_block_runner;
    ExecutedBlockFunction executed_block_runner;
    NoBlockFunction no_block_runner;
  
    const char* help_short;
    const char* help;
  
    bool is_target;
  };
  
  typedef std::map<base::StringPiece, FunctionInfo> FunctionInfoMap;
  
  // Returns the mapping of all built-in functions.
  const FunctionInfoMap& GetFunctions();
  
  // Runs the given function.
  Value RunFunction(Scope* scope,
                    const FunctionCallNode* function,
                    const ListNode* args_list,
                    BlockNode* block,  // Optional.
                    Err* err);
  
  }  // namespace functions
  
  // Helper functions -----------------------------------------------------------
  
  // Verifies that the current scope is not processing an import. If it is, it
  // will set the error, blame the given parse node for it, and return false.
  bool EnsureNotProcessingImport(const ParseNode* node,
                                 const Scope* scope,
                                 Err* err);
  
  // Like EnsureNotProcessingImport but checks for running the build config.
  bool EnsureNotProcessingBuildConfig(const ParseNode* node,
                                      const Scope* scope,
                                      Err* err);
  
  // Sets up the |block_scope| for executing a target (or something like it).
  // The |scope| is the containing scope. It should have been already set as the
  // parent for the |block_scope| when the |block_scope| was created.
  //
  // This will set up the target defaults and set the |target_name| variable in
  // the block scope to the current target name, which is assumed to be the first
  // argument to the function.
  //
  // On success, returns true. On failure, sets the error and returns false.
  bool FillTargetBlockScope(const Scope* scope,
                            const FunctionCallNode* function,
                            const std::string& target_type,
                            const BlockNode* block,
                            const std::vector<Value>& args,
                            Scope* block_scope,
                            Err* err);
  
  // Sets the given error to a message explaining that the function call requires
  // a block.
  void FillNeedsBlockError(const FunctionCallNode* function, Err* err);
  
  // Validates that the given function call has one string argument. This is
  // the most common function signature, so it saves space to have this helper.
  // Returns false and sets the error on failure.
  bool EnsureSingleStringArg(const FunctionCallNode* function,
                             const std::vector<Value>& args,
                             Err* err);
  
  // Returns the name of the toolchain for the given scope.
  const Label& ToolchainLabelForScope(const Scope* scope);
  
  // Generates a label for the given scope, using the current directory and
  // toolchain, and the given name.
  Label MakeLabelForScope(const Scope* scope,
                          const FunctionCallNode* function,
                          const std::string& name);
  
  // Some tyesp of blocks can't be nested inside other ones. For such cases,
  // instantiate this object upon entering the block and Enter() will fail if
  // there is already another non-nestable block on the stack.
  class NonNestableBlock {
   public:
    // type_description is a string that will be used in error messages
    // describing the type of the block, for example, "template" or "config".
    NonNestableBlock(Scope* scope,
                     const FunctionCallNode* function,
                     const char* type_description);
    ~NonNestableBlock();
  
    bool Enter(Err* err);
  
   private:
    // Used as a void* key for the Scope to track our property. The actual value
    // is never used.
    static const int kKey;
  
    Scope* scope_;
    const FunctionCallNode* function_;
    const char* type_description_;
  
    // Set to true when the key is added to the scope so we don't try to
    // delete nonexistant keys which will cause assertions.
    bool key_added_;
  };
  
  #endif  // TOOLS_GN_FUNCTIONS_H_
  