0
# Code Generation
1
2
Flexible code generation framework for producing both Fortran wrapper code and Python wrapper code with customizable formatting, structure, and output styles optimized for f2py compilation and Python integration.
3
4
## Capabilities
5
6
### Base Code Generator
7
8
Foundation class providing common code generation utilities and formatting capabilities.
9
10
```python { .api }
11
class CodeGenerator(object):
12
"""Base code generation utility with formatting and output management."""
13
14
def __init__(self, indent, max_length, continuation, comment):
15
"""
16
Initialize code generator.
17
18
Parameters:
19
- indent: str, indentation string (spaces or tabs)
20
- max_length: int, maximum line length before wrapping
21
- continuation: str, line continuation character
22
- comment: str, comment prefix character
23
"""
24
25
def indent(self):
26
"""Increase current indentation level."""
27
28
def dedent(self):
29
"""Decrease current indentation level."""
30
31
def write(self, *args):
32
"""
33
Write arbitrary string arguments to the instance's code, split by
34
newline characters and implied newline after last arg.
35
"""
36
37
def writelines(self, items, insert=None, level=None):
38
"""
39
Write the given code lines to the instance's code.
40
41
Parameters:
42
- items: list of strings, code lines to be appended
43
- insert: int or None, insert lines after index instead of appending
44
- level: int or None, override current indent level
45
46
Returns:
47
int, index for next line to be added
48
"""
49
50
def split_long_lines(self):
51
"""Split long lines using continuation characters."""
52
53
def __str__(self):
54
"""Get generated code as formatted string."""
55
```
56
57
### Fortran Wrapper Generator
58
59
Specialized generator for creating Fortran 90 wrapper code that interfaces with original Fortran code.
60
61
```python { .api }
62
class F90WrapperGenerator(FortranVisitor, CodeGenerator):
63
"""Generate Fortran 90 wrapper code for f2py compilation."""
64
```
65
66
The F90WrapperGenerator creates simplified Fortran interfaces that:
67
- Replace derived type arguments with opaque integer handles
68
- Provide C-compatible procedure signatures
69
- Handle string length parameters explicitly
70
- Manage memory allocation for derived types
71
- Enable exception handling through abort functions
72
73
### Python Wrapper Generator
74
75
Specialized generator for creating high-level Python wrapper code that provides a Pythonic interface.
76
77
```python { .api }
78
class PythonWrapperGenerator(FortranVisitor, CodeGenerator):
79
"""Generate Python wrapper code with object-oriented interface."""
80
```
81
82
The PythonWrapperGenerator creates Python classes and functions that:
83
- Provide object-oriented interfaces for derived types
84
- Handle automatic type conversion between Python and Fortran
85
- Manage memory allocation and cleanup transparently
86
- Offer Pythonic argument handling (keyword arguments, defaults)
87
- Include comprehensive docstrings with type information
88
89
### Python Wrapper Utilities
90
91
Utility functions supporting Python wrapper code generation.
92
93
```python { .api }
94
def py_arg_value(arg):
95
"""Get Python argument value representation for wrapper functions."""
96
97
def normalise_class_name(name, name_map):
98
"""Normalize class names according to Python conventions."""
99
100
def format_call_signature(node):
101
"""Format procedure call signature for Python wrapper functions."""
102
103
def format_doc_string(node):
104
"""Format comprehensive docstrings from Fortran documentation."""
105
```
106
107
## Usage Examples
108
109
### Basic Code Generation
110
111
```python
112
from f90wrap.codegen import CodeGenerator
113
114
# Create generator with custom formatting
115
generator = CodeGenerator(indent=' ', max_length=80,
116
continuation='&', comment='!')
117
118
# Generate code with proper formatting
119
generator.write('subroutine example(x, y)')
120
generator.indent()
121
generator.write('real, intent(in) :: x')
122
generator.write('real, intent(out) :: y')
123
generator.write('y = x * 2.0')
124
generator.dedent()
125
generator.write('end subroutine example')
126
127
# Get formatted code
128
code = str(generator)
129
print(code)
130
```
131
132
### Fortran Wrapper Generation
133
134
```python
135
from f90wrap.f90wrapgen import F90WrapperGenerator
136
from f90wrap.fortran import walk_procedures
137
138
# Create F90 wrapper generator
139
f90_gen = F90WrapperGenerator(indent=' ', max_length=72,
140
continuation='&', comment='!')
141
142
# Generate wrappers for all procedures
143
for proc in walk_procedures(tree):
144
f90_gen.visit(proc)
145
146
# Write to file
147
with open('f90wrap_module.f90', 'w') as f:
148
f.write(str(f90_gen))
149
```
150
151
### Python Wrapper Generation
152
153
```python
154
from f90wrap.pywrapgen import PythonWrapperGenerator
155
from f90wrap.fortran import walk_modules
156
157
# Create Python wrapper generator
158
py_gen = PythonWrapperGenerator(indent=' ', max_length=80,
159
continuation='\\', comment='#')
160
161
# Generate Python classes for modules
162
for module in walk_modules(tree):
163
py_gen.visit(module)
164
165
# Write to file
166
with open('wrapper_module.py', 'w') as f:
167
f.write(str(py_gen))
168
```
169
170
### Custom Code Generation
171
172
```python
173
from f90wrap.codegen import CodeGenerator
174
from f90wrap.fortran import FortranVisitor
175
176
class CustomGenerator(FortranVisitor, CodeGenerator):
177
def __init__(self):
178
CodeGenerator.__init__(self, ' ', 80, '&', '!')
179
180
def visit_Subroutine(self, node):
181
self.write(f'! Wrapper for {node.name}')
182
self.write(f'subroutine wrap_{node.name}()')
183
self.indent()
184
# Custom wrapper logic
185
self.write('! Custom code here')
186
self.dedent()
187
self.write('end subroutine')
188
189
# Use custom generator
190
gen = CustomGenerator()
191
gen.visit(tree)
192
print(str(gen))
193
```
194
195
## Code Generation Features
196
197
### Fortran Wrapper Features
198
199
**Derived Type Handling:**
200
- Converts derived type arguments to opaque integer handles
201
- Generates type construction and destruction wrappers
202
- Manages type component access through getter/setter routines
203
- Handles arrays of derived types with specialized wrappers
204
205
**Memory Management:**
206
- Automatic allocation/deallocation of temporary variables
207
- Proper handling of allocatable and pointer components
208
- Memory leak prevention through systematic cleanup
209
- Integration with Fortran's memory model
210
211
**String Handling:**
212
- Explicit string length parameter management
213
- Character array conversion for f2py compatibility
214
- Support for both fixed-length and allocatable strings
215
- Proper null-termination handling
216
217
**Exception Handling:**
218
- Integration with f90wrap_abort() for error propagation
219
- Proper cleanup on exception conditions
220
- Error code translation to Python exceptions
221
- Stack unwinding support
222
223
### Python Wrapper Features
224
225
**Object-Oriented Interface:**
226
- Classes for Fortran derived types with Python methods
227
- Inheritance hierarchies reflecting Fortran type relationships
228
- Property-based access to type components
229
- Context manager support for resource management
230
231
**Argument Handling:**
232
- Keyword argument support with defaults
233
- Optional argument handling matching Fortran semantics
234
- Automatic type conversion (numpy arrays, scalars)
235
- Validation of argument types and shapes
236
237
**Documentation Generation:**
238
- Comprehensive docstrings from Fortran comments
239
- Parameter documentation with types and descriptions
240
- Return value documentation
241
- Usage examples in docstrings
242
243
**Integration Features:**
244
- NumPy array integration with proper dtypes
245
- Support for both C and Fortran array ordering
246
- Automatic shape and type checking
247
- Memory view support for efficient data transfer
248
249
## Output File Organization
250
251
### Fortran Wrapper Files
252
253
```
254
f90wrap_<module>.f90 # Main module wrapper
255
f90wrap_toplevel.f90 # Top-level procedure wrappers
256
f90wrap_types.f90 # Type-specific wrappers
257
```
258
259
### Python Wrapper Files
260
261
```
262
<module>.py # Main Python interface
263
<module>_types.py # Type definitions and classes
264
__init__.py # Package initialization
265
```
266
267
## Customization Options
268
269
### Formatting Control
270
271
- **Indentation**: Spaces, tabs, or custom strings
272
- **Line Length**: Maximum line width with automatic wrapping
273
- **Continuation**: Line continuation characters and style
274
- **Comments**: Comment prefixes and formatting
275
276
### Naming Conventions
277
278
- **Prefix/Suffix**: Custom prefixes and suffixes for generated names
279
- **Case Conversion**: Automatic case conversion (snake_case, camelCase)
280
- **Reserved Words**: Automatic renaming of language keywords
281
- **Namespace Management**: Module and package name handling
282
283
### Code Structure
284
285
- **Module Organization**: Single file vs. multi-file output
286
- **Import Management**: Automatic import statement generation
287
- **Dependency Tracking**: Cross-module dependency resolution
288
- **Documentation Level**: Detailed vs. minimal documentation generation
289
290
## Integration with Build Systems
291
292
### f2py Integration
293
294
Generated Fortran wrappers are designed for seamless f2py compilation:
295
296
```bash
297
f2py -c -m _module f90wrap_*.f90 original_objects.o
298
```
299
300
### Meson Integration
301
302
Support for modern build systems through proper file organization:
303
304
```python
305
# meson.build configuration
306
f2py_sources = ['f90wrap_module.f90', 'f90wrap_types.f90']
307
```
308
309
### CMake Integration
310
311
Compatible with CMake-based Fortran projects:
312
313
```cmake
314
# CMakeLists.txt configuration
315
set(F90WRAP_SOURCES f90wrap_module.f90 f90wrap_types.f90)
316
```