futils.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. from itertools import chain
  2. from sympy.codegen.fnodes import Module
  3. from sympy.core.symbol import Dummy
  4. from sympy.printing.fortran import FCodePrinter
  5. """ This module collects utilities for rendering Fortran code. """
  6. def render_as_module(definitions, name, declarations=(), printer_settings=None):
  7. """ Creates a ``Module`` instance and renders it as a string.
  8. This generates Fortran source code for a module with the correct ``use`` statements.
  9. Parameters
  10. ==========
  11. definitions : iterable
  12. Passed to :class:`sympy.codegen.fnodes.Module`.
  13. name : str
  14. Passed to :class:`sympy.codegen.fnodes.Module`.
  15. declarations : iterable
  16. Passed to :class:`sympy.codegen.fnodes.Module`. It will be extended with
  17. use statements, 'implicit none' and public list generated from ``definitions``.
  18. printer_settings : dict
  19. Passed to ``FCodePrinter`` (default: ``{'standard': 2003, 'source_format': 'free'}``).
  20. """
  21. printer_settings = printer_settings or {'standard': 2003, 'source_format': 'free'}
  22. printer = FCodePrinter(printer_settings)
  23. dummy = Dummy()
  24. if isinstance(definitions, Module):
  25. raise ValueError("This function expects to construct a module on its own.")
  26. mod = Module(name, chain(declarations, [dummy]), definitions)
  27. fstr = printer.doprint(mod)
  28. module_use_str = ' %s\n' % ' \n'.join(['use %s, only: %s' % (k, ', '.join(v)) for
  29. k, v in printer.module_uses.items()])
  30. module_use_str += ' implicit none\n'
  31. module_use_str += ' private\n'
  32. module_use_str += ' public %s\n' % ', '.join([str(node.name) for node in definitions if getattr(node, 'name', None)])
  33. return fstr.replace(printer.doprint(dummy), module_use_str)