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.
Files changed (49) hide show
  1. includecpp/__init__.py +59 -0
  2. includecpp/__init__.pyi +255 -0
  3. includecpp/__main__.py +4 -0
  4. includecpp/cli/__init__.py +4 -0
  5. includecpp/cli/commands.py +8270 -0
  6. includecpp/cli/config_parser.py +127 -0
  7. includecpp/core/__init__.py +19 -0
  8. includecpp/core/ai_integration.py +2132 -0
  9. includecpp/core/build_manager.py +2416 -0
  10. includecpp/core/cpp_api.py +376 -0
  11. includecpp/core/cpp_api.pyi +95 -0
  12. includecpp/core/cppy_converter.py +3448 -0
  13. includecpp/core/cssl/CSSL_DOCUMENTATION.md +2075 -0
  14. includecpp/core/cssl/__init__.py +42 -0
  15. includecpp/core/cssl/cssl_builtins.py +2271 -0
  16. includecpp/core/cssl/cssl_builtins.pyi +1393 -0
  17. includecpp/core/cssl/cssl_events.py +621 -0
  18. includecpp/core/cssl/cssl_modules.py +2803 -0
  19. includecpp/core/cssl/cssl_parser.py +2575 -0
  20. includecpp/core/cssl/cssl_runtime.py +3051 -0
  21. includecpp/core/cssl/cssl_syntax.py +488 -0
  22. includecpp/core/cssl/cssl_types.py +1512 -0
  23. includecpp/core/cssl_bridge.py +882 -0
  24. includecpp/core/cssl_bridge.pyi +488 -0
  25. includecpp/core/error_catalog.py +802 -0
  26. includecpp/core/error_formatter.py +1016 -0
  27. includecpp/core/exceptions.py +97 -0
  28. includecpp/core/path_discovery.py +77 -0
  29. includecpp/core/project_ui.py +3370 -0
  30. includecpp/core/settings_ui.py +326 -0
  31. includecpp/generator/__init__.py +1 -0
  32. includecpp/generator/parser.cpp +1903 -0
  33. includecpp/generator/parser.h +281 -0
  34. includecpp/generator/type_resolver.cpp +363 -0
  35. includecpp/generator/type_resolver.h +68 -0
  36. includecpp/py.typed +0 -0
  37. includecpp/templates/cpp.proj.template +18 -0
  38. includecpp/vscode/__init__.py +1 -0
  39. includecpp/vscode/cssl/__init__.py +1 -0
  40. includecpp/vscode/cssl/language-configuration.json +38 -0
  41. includecpp/vscode/cssl/package.json +50 -0
  42. includecpp/vscode/cssl/snippets/cssl.snippets.json +1080 -0
  43. includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +341 -0
  44. includecpp-3.7.3.dist-info/METADATA +1076 -0
  45. includecpp-3.7.3.dist-info/RECORD +49 -0
  46. includecpp-3.7.3.dist-info/WHEEL +5 -0
  47. includecpp-3.7.3.dist-info/entry_points.txt +2 -0
  48. includecpp-3.7.3.dist-info/licenses/LICENSE +21 -0
  49. 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