1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
#pragma once
#include "globalincs/pstypes.h"
#include "DynamicSEXP.h"
#include "SEXPParameterExtractor.h"
namespace sexp {
class EngineSEXP;
struct dummy_return {
};
using EngineSexpAction = std::function<int(SEXPParameterExtractor* extractor)>;
class EngineSEXPFactory {
std::unique_ptr<EngineSEXP> m_sexp;
SCP_string _helpText;
int _category = OP_CATEGORY_NONE;
SCP_string _categoryName;
int _subcategory = OP_SUBCATEGORY_NONE;
SCP_string _subcategoryName;
int _returnType = -1;
EngineSexpAction _action;
struct argument {
int type = -1;
SCP_string help_text;
bool optional_marker = false;
bool varargs_marker = false;
};
static bool isArgumentOptional(const argument& arg);
static bool isArgumentVarargsMarker(const argument& arg);
SCP_vector<argument> _arguments;
class ArgumentListBuilder {
EngineSEXPFactory* _parent;
public:
ArgumentListBuilder(EngineSEXPFactory* parent);
/**
* @brief Adds a parameter of the specified type with help text.
* @param type The type of this parameter
* @param help_text A helpful text for this parameter
* @return The arglist builder
*/
ArgumentListBuilder& arg(int type, SCP_string help_text);
/**
* @brief Specifies that all following arguments are optional
* @return The arglist builder
*/
ArgumentListBuilder& beginOptional();
/**
* @brief Begins the part of the parameter list which can be repeated
* @return The arglist builder
*/
ArgumentListBuilder& beginVarargs();
/**
* @brief Finishes the argument list
* @return The parent engine SEXP factory
*/
EngineSEXPFactory& finishArguments();
};
friend ArgumentListBuilder;
public:
EngineSEXPFactory(std::unique_ptr<EngineSEXP> sexp);
virtual ~EngineSEXPFactory();
EngineSEXPFactory(EngineSEXPFactory&&) noexcept = default;
EngineSEXPFactory& operator=(EngineSEXPFactory&&) noexcept = default;
/**
* @brief Specifies the help text of the SEXP
* @param text The help text
* @return The factory
*/
EngineSEXPFactory& helpText(SCP_string text);
/**
* @brief The return type of the SEXP
*
* This is a required value!
*
* @param type The OPR_ value
* @return The factory
*/
EngineSEXPFactory& returnType(int type);
/**
* @brief The category where this SEXP will be located
*
* This is a required value!
*
* @param cat The OP_CATEGORY_ value
* @return The factory
*/
EngineSEXPFactory& category(int cat);
/**
* @brief Sets the category of the SEXP.
*
* This can be a new category which will be created automatically.
*
* This or the number variant is a required value!
*
* @param cat The name of the category
* @return The factory
*/
EngineSEXPFactory& category(const SCP_string& cat);
/**
* @brief The subcategory of this SEXP
*
* This or the string variant is a required value!
*
* @param subcat The *_SUBCATEGORY_* value
* @return The factory
*/
EngineSEXPFactory& subcategory(int subcat);
/**
* @brief Sets the subcategory of the SEXP.
*
* This can be a new subcategory which will be created automatically.
*
* This or the number variant is a required value!
*
* @param subcat The name of the subcategory
* @return The factory
*/
EngineSEXPFactory& subcategory(const SCP_string& subcat);
/**
* @brief Begins specifying arguments for the SEXP
* @return
*/
ArgumentListBuilder beginArgList();
/**
* @brief The function that will be called for executing the SEXP
* @param act The function to execute
* @return The factory
*/
EngineSEXPFactory& action(EngineSexpAction act);
/**
* @brief Finishes the construction of the SEXP
* @return A dummy value to allow SEXPs to be added statically at application start
*/
dummy_return finish();
};
class EngineSEXP : public DynamicSEXP {
EngineSEXP(const SCP_string& name);
public:
void initialize() override;
int getMinimumArguments() const override;
int getMaximumArguments() const override;
int getArgumentType(int argnum) const override;
int execute(int node, int parent_node = -1) override;
int getReturnType() override;
int getSubcategory() override;
int getCategory() override;
/**
* @brief Start creating an engine SEXP.
*
* This returns a factory with which the various parameters of the SEXP can be configured
*
* @param name The name of the SEXP
* @return The engine SEXP factory
*/
static EngineSEXPFactory create(const SCP_string& name);
private:
void setCategory(int category);
void setCategoryName(SCP_string category);
void setSubcategory(int subcategory);
void setSubcategoryName(SCP_string subcategory);
void setHelpText(SCP_string helpText);
void setReturnType(int returnType);
void initArguments(int minArgs, int maxArgs, SCP_vector<int> argTypes, SCP_vector<int> varargsTypes);
void setAction(EngineSexpAction action);
int _category = OP_CATEGORY_NONE;
SCP_string _categoryName;
int _subcategory = OP_SUBCATEGORY_NONE;
SCP_string _subcategoryName;
int _returnType = -1;
int _minArgs = -1;
int _maxArgs = -1;
SCP_vector<int> _argumentTypes;
SCP_vector<int> _variableArgumentsTypes;
EngineSexpAction _action;
friend EngineSEXPFactory;
};
} // namespace sexp
|