// See the file "COPYING" in the main distribution directory for copyright. // Methods for generating declarations of functions and lambdas. // The counterpart to GenFunc.cc. // // This file is included by Compile.h to insert into the CPPCompiler class. // Generates declarations (class, forward reference to C++ function) for the // given script function. void DeclareFunc(const FuncInfo& func); // Similar, but for lambdas. void DeclareLambda(const LambdaExpr* l, const ProfileFunc* pf); // Generates code to declare the compiled version of a script function. // "ft" gives the functions type, "pf" its profile, "fname" its C++ name, // "body" its AST, "l" if non-nil its corresponding lambda expression, and // "flavor" whether it's a hook/event/function. // // We use two basic approaches. Most functions are represented by a // "CPPDynStmt" object that's parameterized by a void* pointer to the // underlying C++ function and an index used to dynamically cast the pointer // to having the correct type for then calling it. Lambdas, however // (including "implicit" lambdas used to associate complex expressions with // &attributes), each have a unique subclass derived from CPPStmt that calls // the underlying C++ function without requiring a cast, and that holds the // values of the lambda's captures. // // It would be cleanest to use the latter approach for all functions, but // the hundreds/thousands of additional classes required for doing so // significantly slows down C++ compilation, so we instead opt for the uglier // dynamic casting approach, which only requires one additional class. void CreateFunction(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const StmtPtr& body, int priority, const LambdaExpr* l, FunctionFlavor flavor, const std::forward_list* e_g = nullptr); // Used for the case of creating a custom subclass of CPPStmt. void DeclareSubclass(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const std::string& args, const IDPList* lambda_ids); // Used for the case of employing an instance of a CPPDynStmt object. void DeclareDynCPPStmt(); // Generates the declarations (and in-line definitions) associated with // compiling a lambda. void BuildLambda(const FuncTypePtr& ft, const ProfileFunc* pf, const std::string& fname, const StmtPtr& body, const LambdaExpr* l, const IDPList* lambda_ids); // For a call to the C++ version of a function of type "ft" and with lambda // captures lambda_ids (nil if not applicable), generates code that binds the // Interpreter arguments (i.e., Frame offsets) to C++ function arguments, as // well as passing in the captures. std::string BindArgs(const FuncTypePtr& ft, const IDPList* lambda_ids); // Generates the declaration for the parameters for a function with the given // type, lambda captures (if non-nil), and profile. std::string ParamDecl(const FuncTypePtr& ft, const IDPList* lambda_ids, const ProfileFunc* pf); // Returns in p_types the types associated with the parameters for a function // of the given type, set of lambda captures (if any), and profile. void GatherParamTypes(std::vector& p_types, const FuncTypePtr& ft, const IDPList* lambda_ids, const ProfileFunc* pf); // Same, but instead returns the parameter's names. void GatherParamNames(std::vector& p_names, const FuncTypePtr& ft, const IDPList* lambda_ids, const ProfileFunc* pf); // Inspects the given profile to find the i'th parameter (starting at 0). // Returns nil if the profile indicates that the parameter is not used by the // function. IDPtr FindParam(int i, const ProfileFunc* pf); // Information associated with a CPPDynStmt dynamic dispatch. struct DispatchInfo { std::string cast; // C++ cast to use for function pointer std::string args; // arguments to pass to the function bool is_hook; // whether the function is a hook TypePtr yield; // what type the function returns, if any }; // An array of cast/invocation pairs used to generate the CPPDynStmt Exec // method. std::vector func_casting_glue; // Maps casting strings to indices into func_casting_glue. The index is // what's used to dynamically switch to the right dispatch. std::unordered_map casting_index; // Maps functions (using their C++ name) to their casting strings. std::unordered_map func_index; // Names for lambda capture ID's. These require a separate space that // incorporates the lambda's name, to deal with nested lambda's that refer // to the identifiers with the same name. std::unordered_map lambda_names; // The function's parameters. Tracked so we don't re-declare them. IDSet params; // Whether we're compiling a hook. bool in_hook = false;