def add_missing_destructors(tree): for node in ft.walk(tree): if not isinstance(node, ft.Type): continue for child in ft.iter_child_nodes(node): if isinstance(child, ft.Procedure): if 'destructor' in child.attributes: logging.info('found destructor %s' % child.name) break else: logging.info('adding missing destructor for %s' % node.name) new_node = ft.Subroutine( '%s_finalise' % node.name, node.filename, ['Automatically generated destructor for %s' % node.name], node.lineno, [ ft.Argument(name='this', filename=node.filename, doc=['Object to be destructed'], lineno=node.lineno, attributes=['intent(inout)'], type='type(%s)' % node.name) ], node.uses, ['destructor', 'skip_call'], mod_name=node.mod_name, type_name=node.name) new_node.method_name = '__del__' node.procedures.append(new_node) return tree
def write_constructor(self, node): handle_arg = ft.Argument(name='handle', filename=node.filename, doc=['Opaque reference to existing derived type instance'], lineno=node.lineno, attributes=['intent(in)', 'optional'], type='integer') handle_arg.py_name = 'handle' # special case for constructors: return value is 'self' argument, # plus we add an extra optional argument args = node.ret_val + node.arguments + [handle_arg] dct = dict(func_name=node.name, prefix=self.prefix, mod_name=self.f90_mod_name, py_arg_names=', '.join(['%s%s' % (arg.py_name, 'optional' in arg.attributes and '=None' or '') for arg in args ]), f90_arg_names=', '.join(['%s=%s' % (arg.name, arg.py_value) for arg in node.arguments])) self.write("def __init__(%(py_arg_names)s):" % dct) self.indent() self.write(format_doc_string(node)) self.write('f90wrap.runtime.FortranDerivedType.__init__(self)') self.write('self._handle = %(mod_name)s.%(prefix)s%(func_name)s(%(f90_arg_names)s)' % dct) self.dedent() self.write()
def visit_Procedure(self, node): n_dummy = 0 for arg in node.arguments: dims = [ attr for attr in arg.attributes if attr.startswith('dimension') ] if dims == []: continue if len(dims) != 1: raise ValueError( 'more than one dimension attribute found for arg %s' % arg.name) ds = ArrayDimensionConverter.split_dimensions(dims[0]) new_dummy_args = [] new_ds = [] for i, d in enumerate(ds): if ArrayDimensionConverter.valid_dim_re.match(d): if d.startswith('len'): arg.f2py_line = ('!f2py %s %s, dimension(%s) :: %s' % \ (arg.type, ','.join([attr for attr in arg.attributes if not attr.startswith('dimension')]), d.replace('len', 'slen'), arg.name)) new_ds.append(d) continue dummy_arg = ft.Argument(name='n%d' % n_dummy, type='integer', attributes=['intent(hide)']) if 'intent(out)' not in arg.attributes: dummy_arg.f2py_line = ( '!f2py intent(hide), depend(%s) :: %s = shape(%s,%d)' % (arg.name, dummy_arg.name, arg.name, i)) new_dummy_args.append(dummy_arg) new_ds.append(dummy_arg.name) n_dummy += 1 if new_dummy_args != []: logging.debug('adding dummy arguments %r to %s' % (new_dummy_args, node.name)) arg.attributes = ([ attr for attr in arg.attributes if not attr.startswith('dimension') ] + ['dimension(%s)' % ','.join(new_ds)]) node.arguments.extend(new_dummy_args)