IncludeCPP 3.7.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- includecpp/__init__.py +59 -0
- includecpp/__init__.pyi +255 -0
- includecpp/__main__.py +4 -0
- includecpp/cli/__init__.py +4 -0
- includecpp/cli/commands.py +8270 -0
- includecpp/cli/config_parser.py +127 -0
- includecpp/core/__init__.py +19 -0
- includecpp/core/ai_integration.py +2132 -0
- includecpp/core/build_manager.py +2416 -0
- includecpp/core/cpp_api.py +376 -0
- includecpp/core/cpp_api.pyi +95 -0
- includecpp/core/cppy_converter.py +3448 -0
- includecpp/core/cssl/CSSL_DOCUMENTATION.md +2075 -0
- includecpp/core/cssl/__init__.py +42 -0
- includecpp/core/cssl/cssl_builtins.py +2271 -0
- includecpp/core/cssl/cssl_builtins.pyi +1393 -0
- includecpp/core/cssl/cssl_events.py +621 -0
- includecpp/core/cssl/cssl_modules.py +2803 -0
- includecpp/core/cssl/cssl_parser.py +2575 -0
- includecpp/core/cssl/cssl_runtime.py +3051 -0
- includecpp/core/cssl/cssl_syntax.py +488 -0
- includecpp/core/cssl/cssl_types.py +1512 -0
- includecpp/core/cssl_bridge.py +882 -0
- includecpp/core/cssl_bridge.pyi +488 -0
- includecpp/core/error_catalog.py +802 -0
- includecpp/core/error_formatter.py +1016 -0
- includecpp/core/exceptions.py +97 -0
- includecpp/core/path_discovery.py +77 -0
- includecpp/core/project_ui.py +3370 -0
- includecpp/core/settings_ui.py +326 -0
- includecpp/generator/__init__.py +1 -0
- includecpp/generator/parser.cpp +1903 -0
- includecpp/generator/parser.h +281 -0
- includecpp/generator/type_resolver.cpp +363 -0
- includecpp/generator/type_resolver.h +68 -0
- includecpp/py.typed +0 -0
- includecpp/templates/cpp.proj.template +18 -0
- includecpp/vscode/__init__.py +1 -0
- includecpp/vscode/cssl/__init__.py +1 -0
- includecpp/vscode/cssl/language-configuration.json +38 -0
- includecpp/vscode/cssl/package.json +50 -0
- includecpp/vscode/cssl/snippets/cssl.snippets.json +1080 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +341 -0
- includecpp-3.7.3.dist-info/METADATA +1076 -0
- includecpp-3.7.3.dist-info/RECORD +49 -0
- includecpp-3.7.3.dist-info/WHEEL +5 -0
- includecpp-3.7.3.dist-info/entry_points.txt +2 -0
- includecpp-3.7.3.dist-info/licenses/LICENSE +21 -0
- includecpp-3.7.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <string>
|
|
3
|
+
#include <vector>
|
|
4
|
+
#include <map>
|
|
5
|
+
#include <set>
|
|
6
|
+
#include <fstream>
|
|
7
|
+
#include <sstream>
|
|
8
|
+
#include <algorithm>
|
|
9
|
+
#include <filesystem>
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
This Api is made for Python <-> C++ communication via pybind11.
|
|
13
|
+
This Api Provides several API calls that can be extenden in other c++ modules or directly be imported as function in python.
|
|
14
|
+
For Adding External C++ Modules (simply plugins). Add a Announcer file '<modulename>.cp' in the folder 'src/plugins/'.
|
|
15
|
+
This file connects the external C++ module with the main application via this API. Allowing to also use the external C++ module functions in python via pybind11.
|
|
16
|
+
This API Manager will automatically load all plugins in the folder 'src/plugins/' on startup.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/* Basic ShowOff of .cp
|
|
20
|
+
|
|
21
|
+
SOURCE(<here_your_path_to_module.cpp>) && HEADER(<here_your_path_to_module.h>) <name_your_module>
|
|
22
|
+
|
|
23
|
+
~oder nur cpp ohne header~
|
|
24
|
+
SOURCE(<here_your_path_to_module.cpp>) <name_your_module>
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
PUBLIC(
|
|
28
|
+
<name_your_module> FUNC(<funcname>)
|
|
29
|
+
<name_your_module> FUNC2(<funcname>>)
|
|
30
|
+
<name_your_module> CLASS(<ClassName>)
|
|
31
|
+
<name_your_module> VAR(<VariableName>)
|
|
32
|
+
)
|
|
33
|
+
~ wenn alle dann~
|
|
34
|
+
PUBLIC(
|
|
35
|
+
ALL
|
|
36
|
+
)
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/* The Best is, you also can give and Take params! Here another Example based on real usecase:
|
|
40
|
+
fast_list.cp:
|
|
41
|
+
|
|
42
|
+
SOURCE(/src/include/fast_list.cpp) && HEADER(/src/include/fast_list.h) fast_list
|
|
43
|
+
PUBLIC(
|
|
44
|
+
fast_list CLASS(FastList) && PY_PARAM(list, "List to convert") && PY_PARAM(int, "Pointer count")
|
|
45
|
+
fast_list FUNC(fast_sort)
|
|
46
|
+
)
|
|
47
|
+
PY_PARAM ist rein optional und sollte nicht genutzt werden da Parameter auch von Pybind11 automatisch erkannt werden.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
// v2.3.5: Parameter metadata structure for IntelliSense
|
|
51
|
+
struct ParameterInfo {
|
|
52
|
+
std::string name;
|
|
53
|
+
std::string type;
|
|
54
|
+
std::string default_value; // Empty if no default
|
|
55
|
+
bool is_const = false;
|
|
56
|
+
bool is_reference = false;
|
|
57
|
+
bool is_pointer = false;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
struct FunctionBinding {
|
|
61
|
+
std::string module_name;
|
|
62
|
+
std::string function_name;
|
|
63
|
+
std::vector<std::pair<std::string, std::string>> params;
|
|
64
|
+
std::string documentation; // Function documentation from DOC()
|
|
65
|
+
|
|
66
|
+
// v2.3.5: Enhanced signature metadata for IntelliSense
|
|
67
|
+
std::string return_type = "void";
|
|
68
|
+
std::vector<ParameterInfo> parameters; // Enhanced parameter info
|
|
69
|
+
bool is_const = false;
|
|
70
|
+
bool is_static = false;
|
|
71
|
+
bool is_inline = false;
|
|
72
|
+
std::string full_signature; // Full C++ signature for reference
|
|
73
|
+
|
|
74
|
+
// v3.1.5: Template function support
|
|
75
|
+
bool is_template = false;
|
|
76
|
+
std::vector<std::string> template_types; // For TEMPLATE_FUNC(name) TYPES(int, float)
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// v2.3.5: Method signature metadata
|
|
80
|
+
// v2.4.13: Extended with param_types for overload resolution
|
|
81
|
+
struct MethodSignature {
|
|
82
|
+
std::string name;
|
|
83
|
+
std::string return_type;
|
|
84
|
+
std::vector<ParameterInfo> parameters;
|
|
85
|
+
std::vector<std::string> param_types; // v2.4.13: ["const Circle&", "const Rect&"] for overload_cast
|
|
86
|
+
bool is_const = false;
|
|
87
|
+
bool is_static = false;
|
|
88
|
+
bool is_virtual = false;
|
|
89
|
+
bool is_override = false;
|
|
90
|
+
std::string documentation;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// v2.3.5: Field metadata
|
|
94
|
+
struct FieldInfo {
|
|
95
|
+
std::string name;
|
|
96
|
+
std::string type;
|
|
97
|
+
bool is_static = false;
|
|
98
|
+
bool is_const = false;
|
|
99
|
+
std::string documentation;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// v2.4.3: Constructor parameter types
|
|
103
|
+
struct ConstructorInfo {
|
|
104
|
+
std::vector<std::string> param_types; // e.g., ["double", "double"] for Vector2D(double, double)
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
struct ClassBinding {
|
|
108
|
+
std::string module_name;
|
|
109
|
+
std::string class_name;
|
|
110
|
+
std::vector<std::pair<std::string, std::string>> params;
|
|
111
|
+
std::vector<std::string> methods; // Method names to bind
|
|
112
|
+
std::vector<std::string> fields; // Field names to bind
|
|
113
|
+
std::vector<ConstructorInfo> constructors; // v2.4.3: Constructor overloads
|
|
114
|
+
bool auto_bind_all; // Bind all methods automatically
|
|
115
|
+
std::string documentation; // Class documentation from DOC()
|
|
116
|
+
std::map<std::string, std::string> method_docs; // Method-specific docs: method_name -> doc
|
|
117
|
+
|
|
118
|
+
// v2.3.5: Enhanced method and field signatures
|
|
119
|
+
std::vector<MethodSignature> method_signatures;
|
|
120
|
+
std::vector<FieldInfo> field_infos;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
struct VariableBinding {
|
|
124
|
+
std::string module_name;
|
|
125
|
+
std::string variable_name;
|
|
126
|
+
std::string documentation; // Variable documentation from DOC()
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// v2.0: STRUCT() Bindings for Plain-Old-Data types
|
|
130
|
+
struct StructBinding {
|
|
131
|
+
std::string module_name;
|
|
132
|
+
std::string struct_name;
|
|
133
|
+
std::vector<std::pair<std::string, std::string>> fields; // <type, name>
|
|
134
|
+
std::vector<std::string> template_types; // For STRUCT(Point) TYPES(int, float)
|
|
135
|
+
bool is_template = false;
|
|
136
|
+
std::string documentation;
|
|
137
|
+
|
|
138
|
+
// Helper methods
|
|
139
|
+
std::string get_full_name() const {
|
|
140
|
+
return struct_name;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
std::string get_template_suffix(const std::string& type) const {
|
|
144
|
+
return "_" + type;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// v2.0: Enhanced Type Metadata for type resolution
|
|
149
|
+
struct TypeMetadata {
|
|
150
|
+
enum TypeCategory {
|
|
151
|
+
PRIMITIVE, // int, float, double, string, bool
|
|
152
|
+
STRUCT_TYPE, // User-defined struct
|
|
153
|
+
VECTOR_TYPE, // std::vector<T>
|
|
154
|
+
MAP_TYPE, // std::map<K,V>
|
|
155
|
+
CLASS_TYPE, // Full C++ class with methods
|
|
156
|
+
UNKNOWN
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
TypeCategory category = UNKNOWN;
|
|
160
|
+
std::string base_type; // "vector", "map", "Point"
|
|
161
|
+
std::string full_signature; // "std::vector<Point>", "std::map<string, int>"
|
|
162
|
+
std::vector<TypeMetadata> template_args; // Recursive for nested types
|
|
163
|
+
bool is_const = false;
|
|
164
|
+
bool is_reference = false;
|
|
165
|
+
bool is_pointer = false;
|
|
166
|
+
|
|
167
|
+
// Conversion methods
|
|
168
|
+
std::string to_python_type_hint() const;
|
|
169
|
+
std::string to_pybind11_type() const;
|
|
170
|
+
std::string to_cpp_type() const;
|
|
171
|
+
bool is_container() const {
|
|
172
|
+
return category == VECTOR_TYPE || category == MAP_TYPE;
|
|
173
|
+
}
|
|
174
|
+
bool requires_custom_converter() const {
|
|
175
|
+
return is_container() || category == STRUCT_TYPE;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// v2.0: Module Dependencies (DEPENDS keyword)
|
|
180
|
+
struct ModuleDependency {
|
|
181
|
+
std::string target_module; // Dependent module
|
|
182
|
+
std::vector<std::string> required_types; // Required Structs/Classes
|
|
183
|
+
bool is_optional = false; // Optional dependency
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// v2.0: Enhanced ModuleDescriptor with structs and dependencies
|
|
187
|
+
struct ModuleDescriptor {
|
|
188
|
+
std::string module_name;
|
|
189
|
+
std::string source_path;
|
|
190
|
+
std::string header_path;
|
|
191
|
+
bool has_header;
|
|
192
|
+
bool expose_all;
|
|
193
|
+
|
|
194
|
+
// Bindings Collections
|
|
195
|
+
std::vector<FunctionBinding> functions;
|
|
196
|
+
std::vector<ClassBinding> classes;
|
|
197
|
+
std::vector<StructBinding> structs; // v2.0: NEW
|
|
198
|
+
std::vector<VariableBinding> variables;
|
|
199
|
+
|
|
200
|
+
// Dependencies & Multi-Source (v2.0)
|
|
201
|
+
std::vector<ModuleDependency> dependencies; // v2.0: NEW
|
|
202
|
+
std::vector<std::string> additional_sources; // v2.0: NEW - SOURCES(a.cpp, b.cpp)
|
|
203
|
+
|
|
204
|
+
// Metadata
|
|
205
|
+
std::string version;
|
|
206
|
+
std::map<std::string, std::string> metadata;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// v2.0: Type Registry for Cross-Module Type Resolution
|
|
210
|
+
class TypeRegistry {
|
|
211
|
+
public:
|
|
212
|
+
// Type Registration
|
|
213
|
+
void register_struct(const std::string& module, const StructBinding& s);
|
|
214
|
+
void register_class(const std::string& module, const ClassBinding& c);
|
|
215
|
+
void register_dependency(const std::string& from_module, const ModuleDependency& dep);
|
|
216
|
+
|
|
217
|
+
// Type Resolution
|
|
218
|
+
TypeMetadata resolve_type(const std::string& type_string) const;
|
|
219
|
+
bool is_struct(const std::string& type_name) const;
|
|
220
|
+
bool is_class(const std::string& type_name) const;
|
|
221
|
+
bool type_exists(const std::string& type_name) const;
|
|
222
|
+
|
|
223
|
+
// Dependency Management
|
|
224
|
+
std::vector<std::string> get_dependencies(const std::string& module) const;
|
|
225
|
+
std::vector<std::string> get_dependency_order() const; // Topological sort
|
|
226
|
+
bool has_circular_dependency() const;
|
|
227
|
+
std::vector<std::string> get_circular_path() const;
|
|
228
|
+
|
|
229
|
+
// Module Info
|
|
230
|
+
std::string get_module_for_type(const std::string& type_name) const;
|
|
231
|
+
std::vector<std::string> get_all_modules() const;
|
|
232
|
+
|
|
233
|
+
private:
|
|
234
|
+
std::map<std::string, StructBinding> structs_;
|
|
235
|
+
std::map<std::string, ClassBinding> classes_;
|
|
236
|
+
std::map<std::string, std::string> type_to_module_;
|
|
237
|
+
std::map<std::string, std::vector<ModuleDependency>> dependencies_;
|
|
238
|
+
|
|
239
|
+
// Helper methods
|
|
240
|
+
std::vector<std::string> topological_sort() const;
|
|
241
|
+
bool has_cycle_dfs(const std::string& module,
|
|
242
|
+
std::set<std::string>& visited,
|
|
243
|
+
std::set<std::string>& rec_stack,
|
|
244
|
+
std::vector<std::string>& path) const;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
class API
|
|
248
|
+
{
|
|
249
|
+
public:
|
|
250
|
+
static int main(int argc, char* argv[]);
|
|
251
|
+
static std::vector<ModuleDescriptor> parse_all_cp_files(const std::string& plugins_dir);
|
|
252
|
+
static ModuleDescriptor parse_cp_file(const std::string& filepath);
|
|
253
|
+
static std::string generate_pybind11_code(const std::vector<ModuleDescriptor>& modules);
|
|
254
|
+
static std::string generate_class_bindings(const ClassBinding& cls, const ModuleDescriptor& mod);
|
|
255
|
+
static bool validate_bindings_code(const std::string& code);
|
|
256
|
+
static void validate_module_name(const std::string& name, int line_num);
|
|
257
|
+
static void validate_namespace_includecpp(const std::string& source_path, const std::string& module_name);
|
|
258
|
+
static bool write_files(const std::vector<ModuleDescriptor>& modules,
|
|
259
|
+
const std::string& bindings_path,
|
|
260
|
+
const std::string& sources_path);
|
|
261
|
+
static std::string compute_file_hash(const std::string& filepath);
|
|
262
|
+
static std::string generate_registry_json(const std::vector<ModuleDescriptor>& modules, const std::string& plugins_dir);
|
|
263
|
+
|
|
264
|
+
// v2.3.5: Signature extraction for IntelliSense
|
|
265
|
+
static std::vector<FunctionBinding> parse_cpp_function_signatures(const std::string& cpp_file_path);
|
|
266
|
+
static std::vector<ParameterInfo> parse_parameter_list(const std::string& params_str);
|
|
267
|
+
|
|
268
|
+
private:
|
|
269
|
+
static std::string trim(const std::string& str);
|
|
270
|
+
static std::vector<std::string> split(const std::string& str, char delimiter);
|
|
271
|
+
static std::string extract_between(const std::string& str, char open, char close);
|
|
272
|
+
static std::string safe_extract_between(const std::string& str,
|
|
273
|
+
size_t start_pos,
|
|
274
|
+
size_t end_pos,
|
|
275
|
+
const std::string& context);
|
|
276
|
+
static bool starts_with(const std::string& str, const std::string& prefix);
|
|
277
|
+
static std::string normalize_path(const std::string& path);
|
|
278
|
+
static std::string replace_all(std::string str, const std::string& from, const std::string& to);
|
|
279
|
+
static std::string extract_doc_string(const std::string& str);
|
|
280
|
+
static std::map<std::string, std::string> parse_doc_statements(const std::string& content);
|
|
281
|
+
};
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
#include "type_resolver.h"
|
|
2
|
+
#include <algorithm>
|
|
3
|
+
#include <cctype>
|
|
4
|
+
#include <sstream>
|
|
5
|
+
|
|
6
|
+
namespace includecpp {
|
|
7
|
+
namespace generator {
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// TypeResolver Implementation
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
TypeResolver::ParsedType TypeResolver::parse_type(const std::string& type_str) {
|
|
14
|
+
ParsedType result;
|
|
15
|
+
std::string working_str = type_str;
|
|
16
|
+
|
|
17
|
+
// Remove leading/trailing whitespace
|
|
18
|
+
working_str.erase(0, working_str.find_first_not_of(" \t\n\r"));
|
|
19
|
+
working_str.erase(working_str.find_last_not_of(" \t\n\r") + 1);
|
|
20
|
+
|
|
21
|
+
// Check for const qualifier
|
|
22
|
+
if (working_str.find("const") == 0) {
|
|
23
|
+
result.is_const = true;
|
|
24
|
+
working_str = working_str.substr(5);
|
|
25
|
+
working_str.erase(0, working_str.find_first_not_of(" \t"));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Check for reference (&) or pointer (*)
|
|
29
|
+
if (!working_str.empty() && working_str.back() == '&') {
|
|
30
|
+
result.is_reference = true;
|
|
31
|
+
working_str.pop_back();
|
|
32
|
+
working_str.erase(working_str.find_last_not_of(" \t") + 1);
|
|
33
|
+
} else if (!working_str.empty() && working_str.back() == '*') {
|
|
34
|
+
result.is_pointer = true;
|
|
35
|
+
working_str.pop_back();
|
|
36
|
+
working_str.erase(working_str.find_last_not_of(" \t") + 1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Check if template type
|
|
40
|
+
size_t template_start = working_str.find('<');
|
|
41
|
+
if (template_start != std::string::npos) {
|
|
42
|
+
result.is_template = true;
|
|
43
|
+
result.base_name = working_str.substr(0, template_start);
|
|
44
|
+
|
|
45
|
+
// Extract template arguments
|
|
46
|
+
std::string template_content = extract_template_content(working_str);
|
|
47
|
+
auto args = split_template_args(template_content);
|
|
48
|
+
|
|
49
|
+
for (const auto& arg : args) {
|
|
50
|
+
result.template_args.push_back(parse_type(arg));
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
result.base_name = working_str;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
std::string TypeResolver::ParsedType::to_cpp_string() const {
|
|
60
|
+
std::ostringstream oss;
|
|
61
|
+
|
|
62
|
+
if (is_const) oss << "const ";
|
|
63
|
+
|
|
64
|
+
oss << base_name;
|
|
65
|
+
|
|
66
|
+
if (is_template && !template_args.empty()) {
|
|
67
|
+
oss << "<";
|
|
68
|
+
for (size_t i = 0; i < template_args.size(); ++i) {
|
|
69
|
+
if (i > 0) oss << ", ";
|
|
70
|
+
oss << template_args[i].to_cpp_string();
|
|
71
|
+
}
|
|
72
|
+
oss << ">";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (is_pointer) oss << "*";
|
|
76
|
+
if (is_reference) oss << "&";
|
|
77
|
+
|
|
78
|
+
return oss.str();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
std::string TypeResolver::ParsedType::to_python_hint() const {
|
|
82
|
+
// Convert C++ types to Python type hints
|
|
83
|
+
static const std::map<std::string, std::string> type_map = {
|
|
84
|
+
{"int", "int"}, {"long", "int"}, {"short", "int"},
|
|
85
|
+
{"float", "float"}, {"double", "float"},
|
|
86
|
+
{"bool", "bool"},
|
|
87
|
+
{"string", "str"}, {"std::string", "str"},
|
|
88
|
+
{"void", "None"}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (type_map.count(base_name)) {
|
|
92
|
+
return type_map.at(base_name);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Handle containers
|
|
96
|
+
if (base_name == "vector" || base_name == "std::vector") {
|
|
97
|
+
if (!template_args.empty()) {
|
|
98
|
+
return "List[" + template_args[0].to_python_hint() + "]";
|
|
99
|
+
}
|
|
100
|
+
return "List[Any]";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (base_name == "map" || base_name == "std::map") {
|
|
104
|
+
if (template_args.size() >= 2) {
|
|
105
|
+
return "Dict[" + template_args[0].to_python_hint() + ", " +
|
|
106
|
+
template_args[1].to_python_hint() + "]";
|
|
107
|
+
}
|
|
108
|
+
return "Dict[Any, Any]";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Custom type (struct/class)
|
|
112
|
+
if (is_template && !template_args.empty()) {
|
|
113
|
+
std::string result = base_name + "_";
|
|
114
|
+
for (size_t i = 0; i < template_args.size(); ++i) {
|
|
115
|
+
if (i > 0) result += "_";
|
|
116
|
+
result += template_args[i].base_name;
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return base_name;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
std::string TypeResolver::to_python_hint(const ParsedType& type) {
|
|
125
|
+
return type.to_python_hint();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
std::string TypeResolver::to_pybind11_signature(const ParsedType& type) {
|
|
129
|
+
return type.to_cpp_string();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
std::string TypeResolver::strip_qualifiers(const std::string& type) {
|
|
133
|
+
std::string result = type;
|
|
134
|
+
|
|
135
|
+
// Remove const
|
|
136
|
+
size_t const_pos = result.find("const");
|
|
137
|
+
while (const_pos != std::string::npos) {
|
|
138
|
+
result.erase(const_pos, 5);
|
|
139
|
+
const_pos = result.find("const");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Remove &, *
|
|
143
|
+
result.erase(std::remove(result.begin(), result.end(), '&'), result.end());
|
|
144
|
+
result.erase(std::remove(result.begin(), result.end(), '*'), result.end());
|
|
145
|
+
|
|
146
|
+
// Remove leading/trailing whitespace
|
|
147
|
+
result.erase(0, result.find_first_not_of(" \t\n\r"));
|
|
148
|
+
result.erase(result.find_last_not_of(" \t\n\r") + 1);
|
|
149
|
+
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
std::string TypeResolver::normalize_type(const std::string& type) {
|
|
154
|
+
std::string normalized = strip_qualifiers(type);
|
|
155
|
+
|
|
156
|
+
// Normalize common types
|
|
157
|
+
if (normalized == "string") return "std::string";
|
|
158
|
+
if (normalized == "vector") return "std::vector";
|
|
159
|
+
if (normalized == "map") return "std::map";
|
|
160
|
+
|
|
161
|
+
return normalized;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
bool TypeResolver::is_container_type(const std::string& type) {
|
|
165
|
+
std::string lower = to_lower(type);
|
|
166
|
+
return lower.find("vector") != std::string::npos ||
|
|
167
|
+
lower.find("map") != std::string::npos ||
|
|
168
|
+
lower.find("set") != std::string::npos ||
|
|
169
|
+
lower.find("array") != std::string::npos ||
|
|
170
|
+
lower.find("list") != std::string::npos;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
bool TypeResolver::is_primitive_type(const std::string& type) {
|
|
174
|
+
static const std::set<std::string> primitives = {
|
|
175
|
+
"int", "long", "short", "char",
|
|
176
|
+
"float", "double",
|
|
177
|
+
"bool",
|
|
178
|
+
"void",
|
|
179
|
+
"unsigned", "signed"
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
std::string clean_type = strip_qualifiers(type);
|
|
183
|
+
return primitives.count(clean_type) > 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
bool TypeResolver::is_numeric_type(const std::string& type) {
|
|
187
|
+
static const std::set<std::string> numerics = {
|
|
188
|
+
"int", "long", "short", "char",
|
|
189
|
+
"float", "double",
|
|
190
|
+
"unsigned", "signed",
|
|
191
|
+
"int8_t", "int16_t", "int32_t", "int64_t",
|
|
192
|
+
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
|
|
193
|
+
"size_t"
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
std::string clean_type = strip_qualifiers(type);
|
|
197
|
+
return numerics.count(clean_type) > 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
bool TypeResolver::requires_custom_converter(const ParsedType& type) {
|
|
201
|
+
return is_container_type(type.base_name) ||
|
|
202
|
+
(!is_primitive_type(type.base_name) && !is_container_type(type.base_name));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
std::vector<std::string> TypeResolver::split_template_args(const std::string& args) {
|
|
206
|
+
std::vector<std::string> result;
|
|
207
|
+
std::string current;
|
|
208
|
+
int depth = 0;
|
|
209
|
+
|
|
210
|
+
for (char c : args) {
|
|
211
|
+
if (c == '<') {
|
|
212
|
+
depth++;
|
|
213
|
+
current += c;
|
|
214
|
+
} else if (c == '>') {
|
|
215
|
+
depth--;
|
|
216
|
+
current += c;
|
|
217
|
+
} else if (c == ',' && depth == 0) {
|
|
218
|
+
// Remove leading/trailing whitespace
|
|
219
|
+
current.erase(0, current.find_first_not_of(" \t"));
|
|
220
|
+
current.erase(current.find_last_not_of(" \t") + 1);
|
|
221
|
+
if (!current.empty()) {
|
|
222
|
+
result.push_back(current);
|
|
223
|
+
}
|
|
224
|
+
current.clear();
|
|
225
|
+
} else {
|
|
226
|
+
current += c;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Add last argument
|
|
231
|
+
current.erase(0, current.find_first_not_of(" \t"));
|
|
232
|
+
current.erase(current.find_last_not_of(" \t") + 1);
|
|
233
|
+
if (!current.empty()) {
|
|
234
|
+
result.push_back(current);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
std::string TypeResolver::extract_template_content(const std::string& type_str) {
|
|
241
|
+
size_t start = type_str.find('<');
|
|
242
|
+
if (start == std::string::npos) return "";
|
|
243
|
+
|
|
244
|
+
size_t end = type_str.rfind('>');
|
|
245
|
+
if (end == std::string::npos || end <= start) return "";
|
|
246
|
+
|
|
247
|
+
return type_str.substr(start + 1, end - start - 1);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
std::string TypeResolver::to_lower(const std::string& str) {
|
|
251
|
+
std::string result = str;
|
|
252
|
+
std::transform(result.begin(), result.end(), result.begin(),
|
|
253
|
+
[](unsigned char c) { return std::tolower(c); });
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// ============================================================================
|
|
258
|
+
// ContainerBindings Implementation
|
|
259
|
+
// ============================================================================
|
|
260
|
+
|
|
261
|
+
std::string ContainerBindings::generate_vector_binding(const std::string& element_type,
|
|
262
|
+
const std::string& module_var) {
|
|
263
|
+
std::ostringstream code;
|
|
264
|
+
std::string sanitized = sanitize_type_name(element_type);
|
|
265
|
+
|
|
266
|
+
code << " // Vector binding for " << element_type << "\n";
|
|
267
|
+
code << " py::bind_vector<std::vector<" << element_type << ">>(";
|
|
268
|
+
code << module_var << ", \"vector_" << sanitized << "\");\n\n";
|
|
269
|
+
|
|
270
|
+
return code.str();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
std::string ContainerBindings::generate_map_binding(const std::string& key_type,
|
|
274
|
+
const std::string& value_type,
|
|
275
|
+
const std::string& module_var) {
|
|
276
|
+
std::ostringstream code;
|
|
277
|
+
std::string sanitized_key = sanitize_type_name(key_type);
|
|
278
|
+
std::string sanitized_val = sanitize_type_name(value_type);
|
|
279
|
+
|
|
280
|
+
code << " // Map binding for " << key_type << " -> " << value_type << "\n";
|
|
281
|
+
code << " py::bind_map<std::map<" << key_type << ", " << value_type << ">>(";
|
|
282
|
+
code << module_var << ", \"map_" << sanitized_key << "_" << sanitized_val << "\");\n\n";
|
|
283
|
+
|
|
284
|
+
return code.str();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
std::string ContainerBindings::generate_nested_container_binding(const TypeMetadata& type,
|
|
288
|
+
const std::string& module_var) {
|
|
289
|
+
std::ostringstream code;
|
|
290
|
+
|
|
291
|
+
// For nested containers, we need to bind inner containers first
|
|
292
|
+
if (type.category == TypeMetadata::VECTOR_TYPE && !type.template_args.empty()) {
|
|
293
|
+
const auto& element = type.template_args[0];
|
|
294
|
+
|
|
295
|
+
// If element is also a container, bind it first
|
|
296
|
+
if (element.is_container()) {
|
|
297
|
+
code << generate_nested_container_binding(element, module_var);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
code << generate_vector_binding(element.base_type, module_var);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return code.str();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
std::set<std::string> ContainerBindings::find_used_containers(const ModuleDescriptor& module) {
|
|
307
|
+
std::set<std::string> containers;
|
|
308
|
+
|
|
309
|
+
// Check function parameters and return types
|
|
310
|
+
for (const auto& func : module.functions) {
|
|
311
|
+
for (const auto& [type, name] : func.params) {
|
|
312
|
+
if (TypeResolver::is_container_type(type)) {
|
|
313
|
+
containers.insert(type);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Check class fields
|
|
319
|
+
for (const auto& cls : module.classes) {
|
|
320
|
+
for (const auto& [type, name] : cls.params) {
|
|
321
|
+
if (TypeResolver::is_container_type(type)) {
|
|
322
|
+
containers.insert(type);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Check struct fields
|
|
328
|
+
for (const auto& st : module.structs) {
|
|
329
|
+
for (const auto& [type, name] : st.fields) {
|
|
330
|
+
if (TypeResolver::is_container_type(type)) {
|
|
331
|
+
containers.insert(type);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return containers;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
std::string ContainerBindings::sanitize_type_name(const std::string& type) {
|
|
340
|
+
std::string result = type;
|
|
341
|
+
|
|
342
|
+
// Replace problematic characters
|
|
343
|
+
std::replace(result.begin(), result.end(), ':', '_');
|
|
344
|
+
std::replace(result.begin(), result.end(), '<', '_');
|
|
345
|
+
std::replace(result.begin(), result.end(), '>', '_');
|
|
346
|
+
std::replace(result.begin(), result.end(), ',', '_');
|
|
347
|
+
std::replace(result.begin(), result.end(), ' ', '_');
|
|
348
|
+
std::replace(result.begin(), result.end(), '*', '_');
|
|
349
|
+
std::replace(result.begin(), result.end(), '&', '_');
|
|
350
|
+
|
|
351
|
+
// Remove consecutive underscores
|
|
352
|
+
auto new_end = std::unique(result.begin(), result.end(),
|
|
353
|
+
[](char a, char b) { return a == '_' && b == '_'; });
|
|
354
|
+
result.erase(new_end, result.end());
|
|
355
|
+
|
|
356
|
+
// Remove leading/trailing underscores
|
|
357
|
+
while (!result.empty() && result.front() == '_') result.erase(0, 1);
|
|
358
|
+
while (!result.empty() && result.back() == '_') result.pop_back();
|
|
359
|
+
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
}} // namespace includecpp::generator
|