// 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 <string_view>

#include <vector>



class Err;

class BlockNode;

class FunctionCallNode;

class Label;

class ListNode;

class ParseNode;

class Scope;

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.

using SelfEvaluatingArgsFunction = Value (*)(Scope* scope,

                                             const FunctionCallNode* function,

                                             const ListNode* args_list,

                                             Err* err);



// This type of function invocation takes a block node that it will execute.

using GenericBlockFunction = Value (*)(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.

using ExecutedBlockFunction = Value (*)(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.

using NoBlockFunction = Value (*)(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 kBundleData[];

extern const char kBundleData_HelpShort[];

extern const char kBundleData_Help[];

Value RunBundleData(Scope* scope,

                    const FunctionCallNode* function,

                    const std::vector<Value>& args,

                    BlockNode* block,

                    Err* err);



extern const char kCreateBundle[];

extern const char kCreateBundle_HelpShort[];

extern const char kCreateBundle_Help[];

Value RunCreateBundle(Scope* scope,

                      const FunctionCallNode* function,

                      const std::vector<Value>& args,

                      BlockNode* block,

                      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 kFilterExclude[];

extern const char kFilterExclude_HelpShort[];

extern const char kFilterExclude_Help[];

Value RunFilterExclude(Scope* scope,

                       const FunctionCallNode* function,

                       const std::vector<Value>& args,

                       Err* err);



extern const char kFilterInclude[];

extern const char kFilterInclude_HelpShort[];

extern const char kFilterInclude_Help[];

Value RunFilterInclude(Scope* scope,

                       const FunctionCallNode* function,

                       const std::vector<Value>& args,

                       Err* err);



extern const char kFilterLabelsInclude[];

extern const char kFilterLabelsInclude_HelpShort[];

extern const char kFilterLabelsInclude_Help[];

Value RunFilterLabelsInclude(Scope* scope,

                             const FunctionCallNode* function,

                             const std::vector<Value>& args,

                             Err* err);



extern const char kFilterLabelsExclude[];

extern const char kFilterLabelsExclude_HelpShort[];

extern const char kFilterLabelsExclude_Help[];

Value RunFilterLabelsExclude(Scope* scope,

                             const FunctionCallNode* function,

                             const std::vector<Value>& args,

                             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 kGeneratedFile[];

extern const char kGeneratedFile_HelpShort[];

extern const char kGeneratedFile_Help[];

Value RunGeneratedFile(Scope* scope,

                       const FunctionCallNode* function,

                       const std::vector<Value>& args,

                       BlockNode* block,

                       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 kLabelMatches[];

extern const char kLabelMatches_HelpShort[];

extern const char kLabelMatches_Help[];

Value RunLabelMatches(Scope* scope,

                      const FunctionCallNode* function,

                      const std::vector<Value>& args,

                      Err* err);



extern const char kLen[];

extern const char kLen_HelpShort[];

extern const char kLen_Help[];

Value RunLen(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 kNotNeeded[];

extern const char kNotNeeded_HelpShort[];

extern const char kNotNeeded_Help[];

Value RunNotNeeded(Scope* scope,

                   const FunctionCallNode* function,

                   const ListNode* args_list,

                   Err* err);



extern const char kPathExists[];

extern const char kPathExists_HelpShort[];

extern const char kPathExists_Help[];

Value RunPathExists(Scope* scope,

                    const FunctionCallNode* function,

                    const std::vector<Value>& args,

                    Err* err);



extern const char kGlobFiles[];

extern const char kGlobFiles_HelpShort[];

extern const char kGlobFiles_Help[];

Value RunGlobFiles(Scope* scope,

                    const FunctionCallNode* function,

                    const std::vector<Value>& args,

                    Err* err);



extern const char kPool[];

extern const char kPool_HelpShort[];

extern const char kPool_Help[];

Value RunPool(const FunctionCallNode* function,

              const std::vector<Value>& args,

              Scope* block_scope,

              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 kRustLibrary[];

extern const char kRustLibrary_HelpShort[];

extern const char kRustLibrary_Help[];

Value RunRustLibrary(Scope* scope,

                     const FunctionCallNode* function,

                     const std::vector<Value>& args,

                     BlockNode* block,

                     Err* err);



extern const char kRustProcMacro[];

extern const char kRustProcMacro_HelpShort[];

extern const char kRustProcMacro_Help[];

Value RunRustProcMacro(Scope* scope,

                       const FunctionCallNode* function,

                       const std::vector<Value>& args,

                       BlockNode* block,

                       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 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 kSplitList[];

extern const char kSplitList_HelpShort[];

extern const char kSplitList_Help[];

Value RunSplitList(Scope* scope,

                   const FunctionCallNode* function,

                   const ListNode* args_list,

                   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 kReplaceSubstr[];

extern const char kReplaceSubstr_HelpShort[];

extern const char kReplaceSubstr_Help[];

Value RunReplaceSubstr(Scope* scope,

                       const FunctionCallNode* function,

                       const std::vector<Value>& args_list,

                       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 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;

};



using FunctionInfoMap = std::map<std::string_view, FunctionInfo>;



// 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 -----------------------------------------------------------



// Validates that the scope that a value is defined in is not the scope

// of the current declare_args() call, if that's what we're in. It is

// illegal to read a value from inside the same declare_args() call, since

// the overrides will not have been applied yet (see `gn help declare_args`

// for more).

bool EnsureNotReadingFromSameDeclareArgs(const ParseNode* node,

                                         const Scope* cur_scope,

                                         const Scope* val_scope,

                                         Err* err);



// 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 types 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 nonexistent keys which will cause assertions.

  bool key_added_;

};



#endif  // TOOLS_GN_FUNCTIONS_H_