diff --git a/.gitattributes b/.gitattributes
index baa7752304ec4cfea244e61def4ca33770a04fc6..180d44765d9c8ab95a37ac0856000963487dff15 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -388,3 +388,6 @@ tuning-competition-baseline/.venv/lib/python3.11/site-packages/nvidia/cudnn/lib/
.venv/lib/python3.11/site-packages/numpy/testing/_private/__pycache__/utils.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
.venv/lib/python3.11/site-packages/numpy/ma/__pycache__/core.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
.venv/lib/python3.11/site-packages/numpy/testing/tests/__pycache__/test_utils.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
+.venv/lib/python3.11/site-packages/numpy/lib/__pycache__/function_base.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
+.venv/lib/python3.11/site-packages/numpy/lib/__pycache__/npyio.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
+.venv/lib/python3.11/site-packages/numpy/lib/tests/__pycache__/test_function_base.cpython-311.pyc filter=lfs diff=lfs merge=lfs -text
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e583250f7060aaa909d43b28dcb7c0021d0175d4
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/__init__.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python3
+"""Fortran to Python Interface Generator.
+
+Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
+Copyright 2011 -- present NumPy Developers.
+Permission to use, modify, and distribute this software is given under the terms
+of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+"""
+__all__ = ['run_main', 'compile', 'get_include']
+
+import sys
+import subprocess
+import os
+import warnings
+
+from numpy.exceptions import VisibleDeprecationWarning
+from . import f2py2e
+from . import diagnose
+
+run_main = f2py2e.run_main
+main = f2py2e.main
+
+
+def compile(source,
+ modulename='untitled',
+ extra_args='',
+ verbose=True,
+ source_fn=None,
+ extension='.f',
+ full_output=False
+ ):
+ """
+ Build extension module from a Fortran 77 source string with f2py.
+
+ Parameters
+ ----------
+ source : str or bytes
+ Fortran source of module / subroutine to compile
+
+ .. versionchanged:: 1.16.0
+ Accept str as well as bytes
+
+ modulename : str, optional
+ The name of the compiled python module
+ extra_args : str or list, optional
+ Additional parameters passed to f2py
+
+ .. versionchanged:: 1.16.0
+ A list of args may also be provided.
+
+ verbose : bool, optional
+ Print f2py output to screen
+ source_fn : str, optional
+ Name of the file where the fortran source is written.
+ The default is to use a temporary file with the extension
+ provided by the ``extension`` parameter
+ extension : ``{'.f', '.f90'}``, optional
+ Filename extension if `source_fn` is not provided.
+ The extension tells which fortran standard is used.
+ The default is ``.f``, which implies F77 standard.
+
+ .. versionadded:: 1.11.0
+
+ full_output : bool, optional
+ If True, return a `subprocess.CompletedProcess` containing
+ the stdout and stderr of the compile process, instead of just
+ the status code.
+
+ .. versionadded:: 1.20.0
+
+
+ Returns
+ -------
+ result : int or `subprocess.CompletedProcess`
+ 0 on success, or a `subprocess.CompletedProcess` if
+ ``full_output=True``
+
+ Examples
+ --------
+ .. literalinclude:: ../../source/f2py/code/results/compile_session.dat
+ :language: python
+
+ """
+ import tempfile
+ import shlex
+
+ if source_fn is None:
+ f, fname = tempfile.mkstemp(suffix=extension)
+ # f is a file descriptor so need to close it
+ # carefully -- not with .close() directly
+ os.close(f)
+ else:
+ fname = source_fn
+
+ if not isinstance(source, str):
+ source = str(source, 'utf-8')
+ try:
+ with open(fname, 'w') as f:
+ f.write(source)
+
+ args = ['-c', '-m', modulename, f.name]
+
+ if isinstance(extra_args, str):
+ is_posix = (os.name == 'posix')
+ extra_args = shlex.split(extra_args, posix=is_posix)
+
+ args.extend(extra_args)
+
+ c = [sys.executable,
+ '-c',
+ 'import numpy.f2py as f2py2e;f2py2e.main()'] + args
+ try:
+ cp = subprocess.run(c, capture_output=True)
+ except OSError:
+ # preserve historic status code used by exec_command()
+ cp = subprocess.CompletedProcess(c, 127, stdout=b'', stderr=b'')
+ else:
+ if verbose:
+ print(cp.stdout.decode())
+ finally:
+ if source_fn is None:
+ os.remove(fname)
+
+ if full_output:
+ return cp
+ else:
+ return cp.returncode
+
+
+def get_include():
+ """
+ Return the directory that contains the ``fortranobject.c`` and ``.h`` files.
+
+ .. note::
+
+ This function is not needed when building an extension with
+ `numpy.distutils` directly from ``.f`` and/or ``.pyf`` files
+ in one go.
+
+ Python extension modules built with f2py-generated code need to use
+ ``fortranobject.c`` as a source file, and include the ``fortranobject.h``
+ header. This function can be used to obtain the directory containing
+ both of these files.
+
+ Returns
+ -------
+ include_path : str
+ Absolute path to the directory containing ``fortranobject.c`` and
+ ``fortranobject.h``.
+
+ Notes
+ -----
+ .. versionadded:: 1.21.1
+
+ Unless the build system you are using has specific support for f2py,
+ building a Python extension using a ``.pyf`` signature file is a two-step
+ process. For a module ``mymod``:
+
+ * Step 1: run ``python -m numpy.f2py mymod.pyf --quiet``. This
+ generates ``_mymodmodule.c`` and (if needed)
+ ``_fblas-f2pywrappers.f`` files next to ``mymod.pyf``.
+ * Step 2: build your Python extension module. This requires the
+ following source files:
+
+ * ``_mymodmodule.c``
+ * ``_mymod-f2pywrappers.f`` (if it was generated in Step 1)
+ * ``fortranobject.c``
+
+ See Also
+ --------
+ numpy.get_include : function that returns the numpy include directory
+
+ """
+ return os.path.join(os.path.dirname(__file__), 'src')
+
+
+def __getattr__(attr):
+
+ # Avoid importing things that aren't needed for building
+ # which might import the main numpy module
+ if attr == "test":
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__)
+ return test
+
+ else:
+ raise AttributeError("module {!r} has no attribute "
+ "{!r}".format(__name__, attr))
+
+
+def __dir__():
+ return list(globals().keys() | {"test"})
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__main__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__main__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..890930f4c3136bdef084056b686c4f724a860642
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__main__.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__version__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__version__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f02de0706a39f37be8fa73dbe861350b9aee01fb
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/__version__.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/_src_pyf.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/_src_pyf.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fdd42c81ddd04d5b6c398779442515ca6701e9de
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/_src_pyf.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cb_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cb_rules.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a3d84498fd725ecf103525e3c7fd4ecb89e522ee
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cb_rules.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cfuncs.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cfuncs.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..893cf569c353190a0c8a20bb5c2fbbabbf417a5d
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/cfuncs.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/common_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/common_rules.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ccbccb856e732a9b2748608a7ee2786e01683e4e
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/common_rules.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/diagnose.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/diagnose.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9f13ef2a0eda118355b15a1c69605e41904f20b8
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/diagnose.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f2py2e.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f2py2e.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..331826205b2ebfb7e343ffd1a049ba86e964d15e
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f2py2e.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f90mod_rules.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f90mod_rules.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..52d77e1c0c55c670160c0fb314285de5b2831a4e
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/f90mod_rules.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/func2subr.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/func2subr.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..392b103003a300d2a210f30b65603f9f5ec9c19b
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/__pycache__/func2subr.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e91393c14be39b20d5e94e262e91a05052681318
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__init__.py
@@ -0,0 +1,9 @@
+def f2py_build_generator(name):
+ if name == "meson":
+ from ._meson import MesonBackend
+ return MesonBackend
+ elif name == "distutils":
+ from ._distutils import DistutilsBackend
+ return DistutilsBackend
+ else:
+ raise ValueError(f"Unknown backend: {name}")
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/__init__.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7ab8902ce1288432c1837f1bad3f62d756bea77d
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/__init__.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_backend.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_backend.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fc2092ecb212b8006851e862619ce0357480b9f3
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_backend.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_distutils.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_distutils.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..eaa51f6ef28feb257af4273ac931920d02eab64f
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_distutils.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_meson.cpython-311.pyc b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_meson.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f82956c718c222365010db243d1a8180107965ce
Binary files /dev/null and b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/__pycache__/_meson.cpython-311.pyc differ
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.py
new file mode 100644
index 0000000000000000000000000000000000000000..a7d43d2587b2f4886372f44c9bac7f5b840d7612
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_backend.py
@@ -0,0 +1,46 @@
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+
+
+class Backend(ABC):
+ def __init__(
+ self,
+ modulename,
+ sources,
+ extra_objects,
+ build_dir,
+ include_dirs,
+ library_dirs,
+ libraries,
+ define_macros,
+ undef_macros,
+ f2py_flags,
+ sysinfo_flags,
+ fc_flags,
+ flib_flags,
+ setup_flags,
+ remove_build_dir,
+ extra_dat,
+ ):
+ self.modulename = modulename
+ self.sources = sources
+ self.extra_objects = extra_objects
+ self.build_dir = build_dir
+ self.include_dirs = include_dirs
+ self.library_dirs = library_dirs
+ self.libraries = libraries
+ self.define_macros = define_macros
+ self.undef_macros = undef_macros
+ self.f2py_flags = f2py_flags
+ self.sysinfo_flags = sysinfo_flags
+ self.fc_flags = fc_flags
+ self.flib_flags = flib_flags
+ self.setup_flags = setup_flags
+ self.remove_build_dir = remove_build_dir
+ self.extra_dat = extra_dat
+
+ @abstractmethod
+ def compile(self) -> None:
+ """Compile the wrapper."""
+ pass
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.py
new file mode 100644
index 0000000000000000000000000000000000000000..e9b22a3921a578758c92de19e3b77cf874d4e4ca
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_distutils.py
@@ -0,0 +1,75 @@
+from ._backend import Backend
+
+from numpy.distutils.core import setup, Extension
+from numpy.distutils.system_info import get_info
+from numpy.distutils.misc_util import dict_append
+from numpy.exceptions import VisibleDeprecationWarning
+import os
+import sys
+import shutil
+import warnings
+
+
+class DistutilsBackend(Backend):
+ def __init__(sef, *args, **kwargs):
+ warnings.warn(
+ "distutils has been deprecated since NumPy 1.26.x"
+ "Use the Meson backend instead, or generate wrappers"
+ "without -c and use a custom build script",
+ VisibleDeprecationWarning,
+ stacklevel=2,
+ )
+ super().__init__(*args, **kwargs)
+
+ def compile(self):
+ num_info = {}
+ if num_info:
+ self.include_dirs.extend(num_info.get("include_dirs", []))
+ ext_args = {
+ "name": self.modulename,
+ "sources": self.sources,
+ "include_dirs": self.include_dirs,
+ "library_dirs": self.library_dirs,
+ "libraries": self.libraries,
+ "define_macros": self.define_macros,
+ "undef_macros": self.undef_macros,
+ "extra_objects": self.extra_objects,
+ "f2py_options": self.f2py_flags,
+ }
+
+ if self.sysinfo_flags:
+ for n in self.sysinfo_flags:
+ i = get_info(n)
+ if not i:
+ print(
+ f"No {repr(n)} resources found"
+ "in system (try `f2py --help-link`)"
+ )
+ dict_append(ext_args, **i)
+
+ ext = Extension(**ext_args)
+
+ sys.argv = [sys.argv[0]] + self.setup_flags
+ sys.argv.extend(
+ [
+ "build",
+ "--build-temp",
+ self.build_dir,
+ "--build-base",
+ self.build_dir,
+ "--build-platlib",
+ ".",
+ "--disable-optimization",
+ ]
+ )
+
+ if self.fc_flags:
+ sys.argv.extend(["config_fc"] + self.fc_flags)
+ if self.flib_flags:
+ sys.argv.extend(["build_ext"] + self.flib_flags)
+
+ setup(ext_modules=[ext])
+
+ if self.remove_build_dir and os.path.exists(self.build_dir):
+ print(f"Removing build directory {self.build_dir}")
+ shutil.rmtree(self.build_dir)
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.py
new file mode 100644
index 0000000000000000000000000000000000000000..f324e0f595fbc6b5e2caa0959027f09495e4fecd
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/_meson.py
@@ -0,0 +1,205 @@
+from __future__ import annotations
+
+import os
+import errno
+import shutil
+import subprocess
+import sys
+from pathlib import Path
+
+from ._backend import Backend
+from string import Template
+from itertools import chain
+
+import warnings
+
+
+class MesonTemplate:
+ """Template meson build file generation class."""
+
+ def __init__(
+ self,
+ modulename: str,
+ sources: list[Path],
+ deps: list[str],
+ libraries: list[str],
+ library_dirs: list[Path],
+ include_dirs: list[Path],
+ object_files: list[Path],
+ linker_args: list[str],
+ c_args: list[str],
+ build_type: str,
+ python_exe: str,
+ ):
+ self.modulename = modulename
+ self.build_template_path = (
+ Path(__file__).parent.absolute() / "meson.build.template"
+ )
+ self.sources = sources
+ self.deps = deps
+ self.libraries = libraries
+ self.library_dirs = library_dirs
+ if include_dirs is not None:
+ self.include_dirs = include_dirs
+ else:
+ self.include_dirs = []
+ self.substitutions = {}
+ self.objects = object_files
+ self.pipeline = [
+ self.initialize_template,
+ self.sources_substitution,
+ self.deps_substitution,
+ self.include_substitution,
+ self.libraries_substitution,
+ ]
+ self.build_type = build_type
+ self.python_exe = python_exe
+
+ def meson_build_template(self) -> str:
+ if not self.build_template_path.is_file():
+ raise FileNotFoundError(
+ errno.ENOENT,
+ "Meson build template"
+ f" {self.build_template_path.absolute()}"
+ " does not exist.",
+ )
+ return self.build_template_path.read_text()
+
+ def initialize_template(self) -> None:
+ self.substitutions["modulename"] = self.modulename
+ self.substitutions["buildtype"] = self.build_type
+ self.substitutions["python"] = self.python_exe
+
+ def sources_substitution(self) -> None:
+ indent = " " * 21
+ self.substitutions["source_list"] = f",\n{indent}".join(
+ [f"{indent}'{source}'" for source in self.sources]
+ )
+
+ def deps_substitution(self) -> None:
+ indent = " " * 21
+ self.substitutions["dep_list"] = f",\n{indent}".join(
+ [f"{indent}dependency('{dep}')" for dep in self.deps]
+ )
+
+ def libraries_substitution(self) -> None:
+ self.substitutions["lib_dir_declarations"] = "\n".join(
+ [
+ f"lib_dir_{i} = declare_dependency(link_args : ['-L{lib_dir}'])"
+ for i, lib_dir in enumerate(self.library_dirs)
+ ]
+ )
+
+ self.substitutions["lib_declarations"] = "\n".join(
+ [
+ f"{lib} = declare_dependency(link_args : ['-l{lib}'])"
+ for lib in self.libraries
+ ]
+ )
+
+ indent = " " * 21
+ self.substitutions["lib_list"] = f"\n{indent}".join(
+ [f"{indent}{lib}," for lib in self.libraries]
+ )
+ self.substitutions["lib_dir_list"] = f"\n{indent}".join(
+ [f"{indent}lib_dir_{i}," for i in range(len(self.library_dirs))]
+ )
+
+ def include_substitution(self) -> None:
+ indent = " " * 21
+ self.substitutions["inc_list"] = f",\n{indent}".join(
+ [f"{indent}'{inc}'" for inc in self.include_dirs]
+ )
+
+ def generate_meson_build(self):
+ for node in self.pipeline:
+ node()
+ template = Template(self.meson_build_template())
+ return template.substitute(self.substitutions)
+
+
+class MesonBackend(Backend):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.dependencies = self.extra_dat.get("dependencies", [])
+ self.meson_build_dir = "bbdir"
+ self.build_type = (
+ "debug" if any("debug" in flag for flag in self.fc_flags) else "release"
+ )
+
+ def _move_exec_to_root(self, build_dir: Path):
+ walk_dir = Path(build_dir) / self.meson_build_dir
+ path_objects = chain(
+ walk_dir.glob(f"{self.modulename}*.so"),
+ walk_dir.glob(f"{self.modulename}*.pyd"),
+ )
+ # Same behavior as distutils
+ # https://github.com/numpy/numpy/issues/24874#issuecomment-1835632293
+ for path_object in path_objects:
+ dest_path = Path.cwd() / path_object.name
+ if dest_path.exists():
+ dest_path.unlink()
+ shutil.copy2(path_object, dest_path)
+ os.remove(path_object)
+
+ def write_meson_build(self, build_dir: Path) -> None:
+ """Writes the meson build file at specified location"""
+ meson_template = MesonTemplate(
+ self.modulename,
+ self.sources,
+ self.dependencies,
+ self.libraries,
+ self.library_dirs,
+ self.include_dirs,
+ self.extra_objects,
+ self.flib_flags,
+ self.fc_flags,
+ self.build_type,
+ sys.executable,
+ )
+ src = meson_template.generate_meson_build()
+ Path(build_dir).mkdir(parents=True, exist_ok=True)
+ meson_build_file = Path(build_dir) / "meson.build"
+ meson_build_file.write_text(src)
+ return meson_build_file
+
+ def _run_subprocess_command(self, command, cwd):
+ subprocess.run(command, cwd=cwd, check=True)
+
+ def run_meson(self, build_dir: Path):
+ setup_command = ["meson", "setup", self.meson_build_dir]
+ self._run_subprocess_command(setup_command, build_dir)
+ compile_command = ["meson", "compile", "-C", self.meson_build_dir]
+ self._run_subprocess_command(compile_command, build_dir)
+
+ def compile(self) -> None:
+ self.sources = _prepare_sources(self.modulename, self.sources, self.build_dir)
+ self.write_meson_build(self.build_dir)
+ self.run_meson(self.build_dir)
+ self._move_exec_to_root(self.build_dir)
+
+
+def _prepare_sources(mname, sources, bdir):
+ extended_sources = sources.copy()
+ Path(bdir).mkdir(parents=True, exist_ok=True)
+ # Copy sources
+ for source in sources:
+ if Path(source).exists() and Path(source).is_file():
+ shutil.copy(source, bdir)
+ generated_sources = [
+ Path(f"{mname}module.c"),
+ Path(f"{mname}-f2pywrappers2.f90"),
+ Path(f"{mname}-f2pywrappers.f"),
+ ]
+ bdir = Path(bdir)
+ for generated_source in generated_sources:
+ if generated_source.exists():
+ shutil.copy(generated_source, bdir / generated_source.name)
+ extended_sources.append(generated_source.name)
+ generated_source.unlink()
+ extended_sources = [
+ Path(source).name
+ for source in extended_sources
+ if not Path(source).suffix == ".pyf"
+ ]
+ return extended_sources
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/meson.build.template b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/meson.build.template
new file mode 100644
index 0000000000000000000000000000000000000000..8e34fdc8d4d6a29d62022e82ae92e787b73f941b
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_backends/meson.build.template
@@ -0,0 +1,54 @@
+project('${modulename}',
+ ['c', 'fortran'],
+ version : '0.1',
+ meson_version: '>= 1.1.0',
+ default_options : [
+ 'warning_level=1',
+ 'buildtype=${buildtype}'
+ ])
+fc = meson.get_compiler('fortran')
+
+py = import('python').find_installation('${python}', pure: false)
+py_dep = py.dependency()
+
+incdir_numpy = run_command(py,
+ ['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
+ check : true
+).stdout().strip()
+
+incdir_f2py = run_command(py,
+ ['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
+ check : true
+).stdout().strip()
+
+inc_np = include_directories(incdir_numpy)
+np_dep = declare_dependency(include_directories: inc_np)
+
+incdir_f2py = incdir_numpy / '..' / '..' / 'f2py' / 'src'
+inc_f2py = include_directories(incdir_f2py)
+fortranobject_c = incdir_f2py / 'fortranobject.c'
+
+inc_np = include_directories(incdir_numpy, incdir_f2py)
+# gh-25000
+quadmath_dep = fc.find_library('quadmath', required: false)
+
+${lib_declarations}
+${lib_dir_declarations}
+
+py.extension_module('${modulename}',
+ [
+${source_list},
+ fortranobject_c
+ ],
+ include_directories: [
+ inc_np,
+${inc_list}
+ ],
+ dependencies : [
+ py_dep,
+ quadmath_dep,
+${dep_list}
+${lib_list}
+${lib_dir_list}
+ ],
+ install : true)
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.py
new file mode 100644
index 0000000000000000000000000000000000000000..3043c5d9163f7101d165ca08e33adf0970547612
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_isocbind.py
@@ -0,0 +1,62 @@
+"""
+ISO_C_BINDING maps for f2py2e.
+Only required declarations/macros/functions will be used.
+
+Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
+Copyright 2011 -- present NumPy Developers.
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+"""
+# These map to keys in c2py_map, via forced casting for now, see gh-25229
+iso_c_binding_map = {
+ 'integer': {
+ 'c_int': 'int',
+ 'c_short': 'short', # 'short' <=> 'int' for now
+ 'c_long': 'long', # 'long' <=> 'int' for now
+ 'c_long_long': 'long_long',
+ 'c_signed_char': 'signed_char',
+ 'c_size_t': 'unsigned', # size_t <=> 'unsigned' for now
+ 'c_int8_t': 'signed_char', # int8_t <=> 'signed_char' for now
+ 'c_int16_t': 'short', # int16_t <=> 'short' for now
+ 'c_int32_t': 'int', # int32_t <=> 'int' for now
+ 'c_int64_t': 'long_long',
+ 'c_int_least8_t': 'signed_char', # int_least8_t <=> 'signed_char' for now
+ 'c_int_least16_t': 'short', # int_least16_t <=> 'short' for now
+ 'c_int_least32_t': 'int', # int_least32_t <=> 'int' for now
+ 'c_int_least64_t': 'long_long',
+ 'c_int_fast8_t': 'signed_char', # int_fast8_t <=> 'signed_char' for now
+ 'c_int_fast16_t': 'short', # int_fast16_t <=> 'short' for now
+ 'c_int_fast32_t': 'int', # int_fast32_t <=> 'int' for now
+ 'c_int_fast64_t': 'long_long',
+ 'c_intmax_t': 'long_long', # intmax_t <=> 'long_long' for now
+ 'c_intptr_t': 'long', # intptr_t <=> 'long' for now
+ 'c_ptrdiff_t': 'long', # ptrdiff_t <=> 'long' for now
+ },
+ 'real': {
+ 'c_float': 'float',
+ 'c_double': 'double',
+ 'c_long_double': 'long_double'
+ },
+ 'complex': {
+ 'c_float_complex': 'complex_float',
+ 'c_double_complex': 'complex_double',
+ 'c_long_double_complex': 'complex_long_double'
+ },
+ 'logical': {
+ 'c_bool': 'unsigned_char' # _Bool <=> 'unsigned_char' for now
+ },
+ 'character': {
+ 'c_char': 'char'
+ }
+}
+
+# TODO: See gh-25229
+isoc_c2pycode_map = {}
+iso_c2py_map = {}
+
+isoc_kindmap = {}
+for fortran_type, c_type_dict in iso_c_binding_map.items():
+ for c_type in c_type_dict.keys():
+ isoc_kindmap[c_type] = fortran_type
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.py b/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.py
new file mode 100644
index 0000000000000000000000000000000000000000..6247b95bfe4603e9b136ca0b8e0c2842d1c1d1cc
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/_src_pyf.py
@@ -0,0 +1,239 @@
+import re
+
+# START OF CODE VENDORED FROM `numpy.distutils.from_template`
+#############################################################
+"""
+process_file(filename)
+
+ takes templated file .xxx.src and produces .xxx file where .xxx
+ is .pyf .f90 or .f using the following template rules:
+
+ '<..>' denotes a template.
+
+ All function and subroutine blocks in a source file with names that
+ contain '<..>' will be replicated according to the rules in '<..>'.
+
+ The number of comma-separated words in '<..>' will determine the number of
+ replicates.
+
+ '<..>' may have two different forms, named and short. For example,
+
+ named:
+
where anywhere inside a block '
' will be replaced with
+ 'd', 's', 'z', and 'c' for each replicate of the block.
+
+ <_c> is already defined: <_c=s,d,c,z>
+ <_t> is already defined: <_t=real,double precision,complex,double complex>
+
+ short:
+ , a short form of the named, useful when no
appears inside
+ a block.
+
+ In general, '<..>' contains a comma separated list of arbitrary
+ expressions. If these expression must contain a comma|leftarrow|rightarrow,
+ then prepend the comma|leftarrow|rightarrow with a backslash.
+
+ If an expression matches '\\' then it will be replaced
+ by -th expression.
+
+ Note that all '<..>' forms in a block must have the same number of
+ comma-separated entries.
+
+ Predefined named template rules:
+
+
+
+
+
+"""
+
+routine_start_re = re.compile(r'(\n|\A)(( (\$|\*))|)\s*(subroutine|function)\b', re.I)
+routine_end_re = re.compile(r'\n\s*end\s*(subroutine|function)\b.*(\n|\Z)', re.I)
+function_start_re = re.compile(r'\n (\$|\*)\s*function\b', re.I)
+
+def parse_structure(astr):
+ """ Return a list of tuples for each function or subroutine each
+ tuple is the start and end of a subroutine or function to be
+ expanded.
+ """
+
+ spanlist = []
+ ind = 0
+ while True:
+ m = routine_start_re.search(astr, ind)
+ if m is None:
+ break
+ start = m.start()
+ if function_start_re.match(astr, start, m.end()):
+ while True:
+ i = astr.rfind('\n', ind, start)
+ if i==-1:
+ break
+ start = i
+ if astr[i:i+7]!='\n $':
+ break
+ start += 1
+ m = routine_end_re.search(astr, m.end())
+ ind = end = m and m.end()-1 or len(astr)
+ spanlist.append((start, end))
+ return spanlist
+
+template_re = re.compile(r"<\s*(\w[\w\d]*)\s*>")
+named_re = re.compile(r"<\s*(\w[\w\d]*)\s*=\s*(.*?)\s*>")
+list_re = re.compile(r"<\s*((.*?))\s*>")
+
+def find_repl_patterns(astr):
+ reps = named_re.findall(astr)
+ names = {}
+ for rep in reps:
+ name = rep[0].strip() or unique_key(names)
+ repl = rep[1].replace(r'\,', '@comma@')
+ thelist = conv(repl)
+ names[name] = thelist
+ return names
+
+def find_and_remove_repl_patterns(astr):
+ names = find_repl_patterns(astr)
+ astr = re.subn(named_re, '', astr)[0]
+ return astr, names
+
+item_re = re.compile(r"\A\\(?P\d+)\Z")
+def conv(astr):
+ b = astr.split(',')
+ l = [x.strip() for x in b]
+ for i in range(len(l)):
+ m = item_re.match(l[i])
+ if m:
+ j = int(m.group('index'))
+ l[i] = l[j]
+ return ','.join(l)
+
+def unique_key(adict):
+ """ Obtain a unique key given a dictionary."""
+ allkeys = list(adict.keys())
+ done = False
+ n = 1
+ while not done:
+ newkey = '__l%s' % (n)
+ if newkey in allkeys:
+ n += 1
+ else:
+ done = True
+ return newkey
+
+
+template_name_re = re.compile(r'\A\s*(\w[\w\d]*)\s*\Z')
+def expand_sub(substr, names):
+ substr = substr.replace(r'\>', '@rightarrow@')
+ substr = substr.replace(r'\<', '@leftarrow@')
+ lnames = find_repl_patterns(substr)
+ substr = named_re.sub(r"<\1>", substr) # get rid of definition templates
+
+ def listrepl(mobj):
+ thelist = conv(mobj.group(1).replace(r'\,', '@comma@'))
+ if template_name_re.match(thelist):
+ return "<%s>" % (thelist)
+ name = None
+ for key in lnames.keys(): # see if list is already in dictionary
+ if lnames[key] == thelist:
+ name = key
+ if name is None: # this list is not in the dictionary yet
+ name = unique_key(lnames)
+ lnames[name] = thelist
+ return "<%s>" % name
+
+ substr = list_re.sub(listrepl, substr) # convert all lists to named templates
+ # newnames are constructed as needed
+
+ numsubs = None
+ base_rule = None
+ rules = {}
+ for r in template_re.findall(substr):
+ if r not in rules:
+ thelist = lnames.get(r, names.get(r, None))
+ if thelist is None:
+ raise ValueError('No replicates found for <%s>' % (r))
+ if r not in names and not thelist.startswith('_'):
+ names[r] = thelist
+ rule = [i.replace('@comma@', ',') for i in thelist.split(',')]
+ num = len(rule)
+
+ if numsubs is None:
+ numsubs = num
+ rules[r] = rule
+ base_rule = r
+ elif num == numsubs:
+ rules[r] = rule
+ else:
+ print("Mismatch in number of replacements (base <{}={}>) "
+ "for <{}={}>. Ignoring.".format(base_rule, ','.join(rules[base_rule]), r, thelist))
+ if not rules:
+ return substr
+
+ def namerepl(mobj):
+ name = mobj.group(1)
+ return rules.get(name, (k+1)*[name])[k]
+
+ newstr = ''
+ for k in range(numsubs):
+ newstr += template_re.sub(namerepl, substr) + '\n\n'
+
+ newstr = newstr.replace('@rightarrow@', '>')
+ newstr = newstr.replace('@leftarrow@', '<')
+ return newstr
+
+def process_str(allstr):
+ newstr = allstr
+ writestr = ''
+
+ struct = parse_structure(newstr)
+
+ oldend = 0
+ names = {}
+ names.update(_special_names)
+ for sub in struct:
+ cleanedstr, defs = find_and_remove_repl_patterns(newstr[oldend:sub[0]])
+ writestr += cleanedstr
+ names.update(defs)
+ writestr += expand_sub(newstr[sub[0]:sub[1]], names)
+ oldend = sub[1]
+ writestr += newstr[oldend:]
+
+ return writestr
+
+include_src_re = re.compile(r"(\n|\A)\s*include\s*['\"](?P[\w\d./\\]+\.src)['\"]", re.I)
+
+def resolve_includes(source):
+ d = os.path.dirname(source)
+ with open(source) as fid:
+ lines = []
+ for line in fid:
+ m = include_src_re.match(line)
+ if m:
+ fn = m.group('name')
+ if not os.path.isabs(fn):
+ fn = os.path.join(d, fn)
+ if os.path.isfile(fn):
+ lines.extend(resolve_includes(fn))
+ else:
+ lines.append(line)
+ else:
+ lines.append(line)
+ return lines
+
+def process_file(source):
+ lines = resolve_includes(source)
+ return process_str(''.join(lines))
+
+_special_names = find_repl_patterns('''
+<_c=s,d,c,z>
+<_t=real,double precision,complex,double complex>
+
+
+
+
+
+''')
+
+# END OF CODE VENDORED FROM `numpy.distutils.from_template`
+###########################################################
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.py b/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa477a5b9aca4873c269b7e628dc50f4d58251b0
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/capi_maps.py
@@ -0,0 +1,819 @@
+"""
+Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
+Copyright 2011 -- present NumPy Developers.
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+"""
+from . import __version__
+f2py_version = __version__.version
+
+import copy
+import re
+import os
+from .crackfortran import markoutercomma
+from . import cb_rules
+from ._isocbind import iso_c_binding_map, isoc_c2pycode_map, iso_c2py_map
+
+# The environment provided by auxfuncs.py is needed for some calls to eval.
+# As the needed functions cannot be determined by static inspection of the
+# code, it is safest to use import * pending a major refactoring of f2py.
+from .auxfuncs import *
+
+__all__ = [
+ 'getctype', 'getstrlength', 'getarrdims', 'getpydocsign',
+ 'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map',
+ 'cb_sign2map', 'cb_routsign2map', 'common_sign2map', 'process_f2cmap_dict'
+]
+
+
+depargs = []
+lcb_map = {}
+lcb2_map = {}
+# forced casting: mainly caused by the fact that Python or Numeric
+# C/APIs do not support the corresponding C types.
+c2py_map = {'double': 'float',
+ 'float': 'float', # forced casting
+ 'long_double': 'float', # forced casting
+ 'char': 'int', # forced casting
+ 'signed_char': 'int', # forced casting
+ 'unsigned_char': 'int', # forced casting
+ 'short': 'int', # forced casting
+ 'unsigned_short': 'int', # forced casting
+ 'int': 'int', # forced casting
+ 'long': 'int',
+ 'long_long': 'long',
+ 'unsigned': 'int', # forced casting
+ 'complex_float': 'complex', # forced casting
+ 'complex_double': 'complex',
+ 'complex_long_double': 'complex', # forced casting
+ 'string': 'string',
+ 'character': 'bytes',
+ }
+
+c2capi_map = {'double': 'NPY_DOUBLE',
+ 'float': 'NPY_FLOAT',
+ 'long_double': 'NPY_LONGDOUBLE',
+ 'char': 'NPY_BYTE',
+ 'unsigned_char': 'NPY_UBYTE',
+ 'signed_char': 'NPY_BYTE',
+ 'short': 'NPY_SHORT',
+ 'unsigned_short': 'NPY_USHORT',
+ 'int': 'NPY_INT',
+ 'unsigned': 'NPY_UINT',
+ 'long': 'NPY_LONG',
+ 'unsigned_long': 'NPY_ULONG',
+ 'long_long': 'NPY_LONGLONG',
+ 'unsigned_long_long': 'NPY_ULONGLONG',
+ 'complex_float': 'NPY_CFLOAT',
+ 'complex_double': 'NPY_CDOUBLE',
+ 'complex_long_double': 'NPY_CDOUBLE',
+ 'string': 'NPY_STRING',
+ 'character': 'NPY_STRING'}
+
+c2pycode_map = {'double': 'd',
+ 'float': 'f',
+ 'long_double': 'g',
+ 'char': 'b',
+ 'unsigned_char': 'B',
+ 'signed_char': 'b',
+ 'short': 'h',
+ 'unsigned_short': 'H',
+ 'int': 'i',
+ 'unsigned': 'I',
+ 'long': 'l',
+ 'unsigned_long': 'L',
+ 'long_long': 'q',
+ 'unsigned_long_long': 'Q',
+ 'complex_float': 'F',
+ 'complex_double': 'D',
+ 'complex_long_double': 'G',
+ 'string': 'S',
+ 'character': 'c'}
+
+# https://docs.python.org/3/c-api/arg.html#building-values
+c2buildvalue_map = {'double': 'd',
+ 'float': 'f',
+ 'char': 'b',
+ 'signed_char': 'b',
+ 'short': 'h',
+ 'int': 'i',
+ 'long': 'l',
+ 'long_long': 'L',
+ 'complex_float': 'N',
+ 'complex_double': 'N',
+ 'complex_long_double': 'N',
+ 'string': 'y',
+ 'character': 'c'}
+
+f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double',
+ '12': 'long_double', '16': 'long_double'},
+ 'integer': {'': 'int', '1': 'signed_char', '2': 'short',
+ '4': 'int', '8': 'long_long',
+ '-1': 'unsigned_char', '-2': 'unsigned_short',
+ '-4': 'unsigned', '-8': 'unsigned_long_long'},
+ 'complex': {'': 'complex_float', '8': 'complex_float',
+ '16': 'complex_double', '24': 'complex_long_double',
+ '32': 'complex_long_double'},
+ 'complexkind': {'': 'complex_float', '4': 'complex_float',
+ '8': 'complex_double', '12': 'complex_long_double',
+ '16': 'complex_long_double'},
+ 'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int',
+ '8': 'long_long'},
+ 'double complex': {'': 'complex_double'},
+ 'double precision': {'': 'double'},
+ 'byte': {'': 'char'},
+ }
+
+# Add ISO_C handling
+c2pycode_map.update(isoc_c2pycode_map)
+c2py_map.update(iso_c2py_map)
+f2cmap_all, _ = process_f2cmap_dict(f2cmap_all, iso_c_binding_map, c2py_map)
+# End ISO_C handling
+f2cmap_default = copy.deepcopy(f2cmap_all)
+
+f2cmap_mapped = []
+
+def load_f2cmap_file(f2cmap_file):
+ global f2cmap_all, f2cmap_mapped
+
+ f2cmap_all = copy.deepcopy(f2cmap_default)
+
+ if f2cmap_file is None:
+ # Default value
+ f2cmap_file = '.f2py_f2cmap'
+ if not os.path.isfile(f2cmap_file):
+ return
+
+ # User defined additions to f2cmap_all.
+ # f2cmap_file must contain a dictionary of dictionaries, only. For
+ # example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
+ # interpreted as C 'float'. This feature is useful for F90/95 users if
+ # they use PARAMETERS in type specifications.
+ try:
+ outmess('Reading f2cmap from {!r} ...\n'.format(f2cmap_file))
+ with open(f2cmap_file) as f:
+ d = eval(f.read().lower(), {}, {})
+ f2cmap_all, f2cmap_mapped = process_f2cmap_dict(f2cmap_all, d, c2py_map, True)
+ outmess('Successfully applied user defined f2cmap changes\n')
+ except Exception as msg:
+ errmess('Failed to apply user defined f2cmap changes: %s. Skipping.\n' % (msg))
+
+
+cformat_map = {'double': '%g',
+ 'float': '%g',
+ 'long_double': '%Lg',
+ 'char': '%d',
+ 'signed_char': '%d',
+ 'unsigned_char': '%hhu',
+ 'short': '%hd',
+ 'unsigned_short': '%hu',
+ 'int': '%d',
+ 'unsigned': '%u',
+ 'long': '%ld',
+ 'unsigned_long': '%lu',
+ 'long_long': '%ld',
+ 'complex_float': '(%g,%g)',
+ 'complex_double': '(%g,%g)',
+ 'complex_long_double': '(%Lg,%Lg)',
+ 'string': '\\"%s\\"',
+ 'character': "'%c'",
+ }
+
+# Auxiliary functions
+
+
+def getctype(var):
+ """
+ Determines C type
+ """
+ ctype = 'void'
+ if isfunction(var):
+ if 'result' in var:
+ a = var['result']
+ else:
+ a = var['name']
+ if a in var['vars']:
+ return getctype(var['vars'][a])
+ else:
+ errmess('getctype: function %s has no return value?!\n' % a)
+ elif issubroutine(var):
+ return ctype
+ elif ischaracter_or_characterarray(var):
+ return 'character'
+ elif isstring_or_stringarray(var):
+ return 'string'
+ elif 'typespec' in var and var['typespec'].lower() in f2cmap_all:
+ typespec = var['typespec'].lower()
+ f2cmap = f2cmap_all[typespec]
+ ctype = f2cmap[''] # default type
+ if 'kindselector' in var:
+ if '*' in var['kindselector']:
+ try:
+ ctype = f2cmap[var['kindselector']['*']]
+ except KeyError:
+ errmess('getctype: "%s %s %s" not supported.\n' %
+ (var['typespec'], '*', var['kindselector']['*']))
+ elif 'kind' in var['kindselector']:
+ if typespec + 'kind' in f2cmap_all:
+ f2cmap = f2cmap_all[typespec + 'kind']
+ try:
+ ctype = f2cmap[var['kindselector']['kind']]
+ except KeyError:
+ if typespec in f2cmap_all:
+ f2cmap = f2cmap_all[typespec]
+ try:
+ ctype = f2cmap[str(var['kindselector']['kind'])]
+ except KeyError:
+ errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="")) in %s/.f2py_f2cmap file).\n'
+ % (typespec, var['kindselector']['kind'], ctype,
+ typespec, var['kindselector']['kind'], os.getcwd()))
+ else:
+ if not isexternal(var):
+ errmess('getctype: No C-type found in "%s", assuming void.\n' % var)
+ return ctype
+
+
+def f2cexpr(expr):
+ """Rewrite Fortran expression as f2py supported C expression.
+
+ Due to the lack of a proper expression parser in f2py, this
+ function uses a heuristic approach that assumes that Fortran
+ arithmetic expressions are valid C arithmetic expressions when
+ mapping Fortran function calls to the corresponding C function/CPP
+ macros calls.
+
+ """
+ # TODO: support Fortran `len` function with optional kind parameter
+ expr = re.sub(r'\blen\b', 'f2py_slen', expr)
+ return expr
+
+
+def getstrlength(var):
+ if isstringfunction(var):
+ if 'result' in var:
+ a = var['result']
+ else:
+ a = var['name']
+ if a in var['vars']:
+ return getstrlength(var['vars'][a])
+ else:
+ errmess('getstrlength: function %s has no return value?!\n' % a)
+ if not isstring(var):
+ errmess(
+ 'getstrlength: expected a signature of a string but got: %s\n' % (repr(var)))
+ len = '1'
+ if 'charselector' in var:
+ a = var['charselector']
+ if '*' in a:
+ len = a['*']
+ elif 'len' in a:
+ len = f2cexpr(a['len'])
+ if re.match(r'\(\s*(\*|:)\s*\)', len) or re.match(r'(\*|:)', len):
+ if isintent_hide(var):
+ errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % (
+ repr(var)))
+ len = '-1'
+ return len
+
+
+def getarrdims(a, var, verbose=0):
+ ret = {}
+ if isstring(var) and not isarray(var):
+ ret['size'] = getstrlength(var)
+ ret['rank'] = '0'
+ ret['dims'] = ''
+ elif isscalar(var):
+ ret['size'] = '1'
+ ret['rank'] = '0'
+ ret['dims'] = ''
+ elif isarray(var):
+ dim = copy.copy(var['dimension'])
+ ret['size'] = '*'.join(dim)
+ try:
+ ret['size'] = repr(eval(ret['size']))
+ except Exception:
+ pass
+ ret['dims'] = ','.join(dim)
+ ret['rank'] = repr(len(dim))
+ ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1]
+ for i in range(len(dim)): # solve dim for dependencies
+ v = []
+ if dim[i] in depargs:
+ v = [dim[i]]
+ else:
+ for va in depargs:
+ if re.match(r'.*?\b%s\b.*' % va, dim[i]):
+ v.append(va)
+ for va in v:
+ if depargs.index(va) > depargs.index(a):
+ dim[i] = '*'
+ break
+ ret['setdims'], i = '', -1
+ for d in dim:
+ i = i + 1
+ if d not in ['*', ':', '(*)', '(:)']:
+ ret['setdims'] = '%s#varname#_Dims[%d]=%s,' % (
+ ret['setdims'], i, d)
+ if ret['setdims']:
+ ret['setdims'] = ret['setdims'][:-1]
+ ret['cbsetdims'], i = '', -1
+ for d in var['dimension']:
+ i = i + 1
+ if d not in ['*', ':', '(*)', '(:)']:
+ ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
+ ret['cbsetdims'], i, d)
+ elif isintent_in(var):
+ outmess('getarrdims:warning: assumed shape array, using 0 instead of %r\n'
+ % (d))
+ ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
+ ret['cbsetdims'], i, 0)
+ elif verbose:
+ errmess(
+ 'getarrdims: If in call-back function: array argument %s must have bounded dimensions: got %s\n' % (repr(a), repr(d)))
+ if ret['cbsetdims']:
+ ret['cbsetdims'] = ret['cbsetdims'][:-1]
+# if not isintent_c(var):
+# var['dimension'].reverse()
+ return ret
+
+
+def getpydocsign(a, var):
+ global lcb_map
+ if isfunction(var):
+ if 'result' in var:
+ af = var['result']
+ else:
+ af = var['name']
+ if af in var['vars']:
+ return getpydocsign(af, var['vars'][af])
+ else:
+ errmess('getctype: function %s has no return value?!\n' % af)
+ return '', ''
+ sig, sigout = a, a
+ opt = ''
+ if isintent_in(var):
+ opt = 'input'
+ elif isintent_inout(var):
+ opt = 'in/output'
+ out_a = a
+ if isintent_out(var):
+ for k in var['intent']:
+ if k[:4] == 'out=':
+ out_a = k[4:]
+ break
+ init = ''
+ ctype = getctype(var)
+
+ if hasinitvalue(var):
+ init, showinit = getinit(a, var)
+ init = ', optional\\n Default: %s' % showinit
+ if isscalar(var):
+ if isintent_inout(var):
+ sig = '%s : %s rank-0 array(%s,\'%s\')%s' % (a, opt, c2py_map[ctype],
+ c2pycode_map[ctype], init)
+ else:
+ sig = '%s : %s %s%s' % (a, opt, c2py_map[ctype], init)
+ sigout = '%s : %s' % (out_a, c2py_map[ctype])
+ elif isstring(var):
+ if isintent_inout(var):
+ sig = '%s : %s rank-0 array(string(len=%s),\'c\')%s' % (
+ a, opt, getstrlength(var), init)
+ else:
+ sig = '%s : %s string(len=%s)%s' % (
+ a, opt, getstrlength(var), init)
+ sigout = '%s : string(len=%s)' % (out_a, getstrlength(var))
+ elif isarray(var):
+ dim = var['dimension']
+ rank = repr(len(dim))
+ sig = '%s : %s rank-%s array(\'%s\') with bounds (%s)%s' % (a, opt, rank,
+ c2pycode_map[
+ ctype],
+ ','.join(dim), init)
+ if a == out_a:
+ sigout = '%s : rank-%s array(\'%s\') with bounds (%s)'\
+ % (a, rank, c2pycode_map[ctype], ','.join(dim))
+ else:
+ sigout = '%s : rank-%s array(\'%s\') with bounds (%s) and %s storage'\
+ % (out_a, rank, c2pycode_map[ctype], ','.join(dim), a)
+ elif isexternal(var):
+ ua = ''
+ if a in lcb_map and lcb_map[a] in lcb2_map and 'argname' in lcb2_map[lcb_map[a]]:
+ ua = lcb2_map[lcb_map[a]]['argname']
+ if not ua == a:
+ ua = ' => %s' % ua
+ else:
+ ua = ''
+ sig = '%s : call-back function%s' % (a, ua)
+ sigout = sig
+ else:
+ errmess(
+ 'getpydocsign: Could not resolve docsignature for "%s".\n' % a)
+ return sig, sigout
+
+
+def getarrdocsign(a, var):
+ ctype = getctype(var)
+ if isstring(var) and (not isarray(var)):
+ sig = '%s : rank-0 array(string(len=%s),\'c\')' % (a,
+ getstrlength(var))
+ elif isscalar(var):
+ sig = '%s : rank-0 array(%s,\'%s\')' % (a, c2py_map[ctype],
+ c2pycode_map[ctype],)
+ elif isarray(var):
+ dim = var['dimension']
+ rank = repr(len(dim))
+ sig = '%s : rank-%s array(\'%s\') with bounds (%s)' % (a, rank,
+ c2pycode_map[
+ ctype],
+ ','.join(dim))
+ return sig
+
+
+def getinit(a, var):
+ if isstring(var):
+ init, showinit = '""', "''"
+ else:
+ init, showinit = '', ''
+ if hasinitvalue(var):
+ init = var['=']
+ showinit = init
+ if iscomplex(var) or iscomplexarray(var):
+ ret = {}
+
+ try:
+ v = var["="]
+ if ',' in v:
+ ret['init.r'], ret['init.i'] = markoutercomma(
+ v[1:-1]).split('@,@')
+ else:
+ v = eval(v, {}, {})
+ ret['init.r'], ret['init.i'] = str(v.real), str(v.imag)
+ except Exception:
+ raise ValueError(
+ 'getinit: expected complex number `(r,i)\' but got `%s\' as initial value of %r.' % (init, a))
+ if isarray(var):
+ init = '(capi_c.r=%s,capi_c.i=%s,capi_c)' % (
+ ret['init.r'], ret['init.i'])
+ elif isstring(var):
+ if not init:
+ init, showinit = '""', "''"
+ if init[0] == "'":
+ init = '"%s"' % (init[1:-1].replace('"', '\\"'))
+ if init[0] == '"':
+ showinit = "'%s'" % (init[1:-1])
+ return init, showinit
+
+
+def get_elsize(var):
+ if isstring(var) or isstringarray(var):
+ elsize = getstrlength(var)
+ # override with user-specified length when available:
+ elsize = var['charselector'].get('f2py_len', elsize)
+ return elsize
+ if ischaracter(var) or ischaracterarray(var):
+ return '1'
+ # for numerical types, PyArray_New* functions ignore specified
+ # elsize, so we just return 1 and let elsize be determined at
+ # runtime, see fortranobject.c
+ return '1'
+
+
+def sign2map(a, var):
+ """
+ varname,ctype,atype
+ init,init.r,init.i,pytype
+ vardebuginfo,vardebugshowvalue,varshowvalue
+ varrformat
+
+ intent
+ """
+ out_a = a
+ if isintent_out(var):
+ for k in var['intent']:
+ if k[:4] == 'out=':
+ out_a = k[4:]
+ break
+ ret = {'varname': a, 'outvarname': out_a, 'ctype': getctype(var)}
+ intent_flags = []
+ for f, s in isintent_dict.items():
+ if f(var):
+ intent_flags.append('F2PY_%s' % s)
+ if intent_flags:
+ # TODO: Evaluate intent_flags here.
+ ret['intent'] = '|'.join(intent_flags)
+ else:
+ ret['intent'] = 'F2PY_INTENT_IN'
+ if isarray(var):
+ ret['varrformat'] = 'N'
+ elif ret['ctype'] in c2buildvalue_map:
+ ret['varrformat'] = c2buildvalue_map[ret['ctype']]
+ else:
+ ret['varrformat'] = 'O'
+ ret['init'], ret['showinit'] = getinit(a, var)
+ if hasinitvalue(var) and iscomplex(var) and not isarray(var):
+ ret['init.r'], ret['init.i'] = markoutercomma(
+ ret['init'][1:-1]).split('@,@')
+ if isexternal(var):
+ ret['cbnamekey'] = a
+ if a in lcb_map:
+ ret['cbname'] = lcb_map[a]
+ ret['maxnofargs'] = lcb2_map[lcb_map[a]]['maxnofargs']
+ ret['nofoptargs'] = lcb2_map[lcb_map[a]]['nofoptargs']
+ ret['cbdocstr'] = lcb2_map[lcb_map[a]]['docstr']
+ ret['cblatexdocstr'] = lcb2_map[lcb_map[a]]['latexdocstr']
+ else:
+ ret['cbname'] = a
+ errmess('sign2map: Confused: external %s is not in lcb_map%s.\n' % (
+ a, list(lcb_map.keys())))
+ if isstring(var):
+ ret['length'] = getstrlength(var)
+ if isarray(var):
+ ret = dictappend(ret, getarrdims(a, var))
+ dim = copy.copy(var['dimension'])
+ if ret['ctype'] in c2capi_map:
+ ret['atype'] = c2capi_map[ret['ctype']]
+ ret['elsize'] = get_elsize(var)
+ # Debug info
+ if debugcapi(var):
+ il = [isintent_in, 'input', isintent_out, 'output',
+ isintent_inout, 'inoutput', isrequired, 'required',
+ isoptional, 'optional', isintent_hide, 'hidden',
+ iscomplex, 'complex scalar',
+ l_and(isscalar, l_not(iscomplex)), 'scalar',
+ isstring, 'string', isarray, 'array',
+ iscomplexarray, 'complex array', isstringarray, 'string array',
+ iscomplexfunction, 'complex function',
+ l_and(isfunction, l_not(iscomplexfunction)), 'function',
+ isexternal, 'callback',
+ isintent_callback, 'callback',
+ isintent_aux, 'auxiliary',
+ ]
+ rl = []
+ for i in range(0, len(il), 2):
+ if il[i](var):
+ rl.append(il[i + 1])
+ if isstring(var):
+ rl.append('slen(%s)=%s' % (a, ret['length']))
+ if isarray(var):
+ ddim = ','.join(
+ map(lambda x, y: '%s|%s' % (x, y), var['dimension'], dim))
+ rl.append('dims(%s)' % ddim)
+ if isexternal(var):
+ ret['vardebuginfo'] = 'debug-capi:%s=>%s:%s' % (
+ a, ret['cbname'], ','.join(rl))
+ else:
+ ret['vardebuginfo'] = 'debug-capi:%s %s=%s:%s' % (
+ ret['ctype'], a, ret['showinit'], ','.join(rl))
+ if isscalar(var):
+ if ret['ctype'] in cformat_map:
+ ret['vardebugshowvalue'] = 'debug-capi:%s=%s' % (
+ a, cformat_map[ret['ctype']])
+ if isstring(var):
+ ret['vardebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
+ a, a)
+ if isexternal(var):
+ ret['vardebugshowvalue'] = 'debug-capi:%s=%%p' % (a)
+ if ret['ctype'] in cformat_map:
+ ret['varshowvalue'] = '#name#:%s=%s' % (a, cformat_map[ret['ctype']])
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isstring(var):
+ ret['varshowvalue'] = '#name#:slen(%s)=%%d %s=\\"%%s\\"' % (a, a)
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
+ if hasnote(var):
+ ret['note'] = var['note']
+ return ret
+
+
+def routsign2map(rout):
+ """
+ name,NAME,begintitle,endtitle
+ rname,ctype,rformat
+ routdebugshowvalue
+ """
+ global lcb_map
+ name = rout['name']
+ fname = getfortranname(rout)
+ ret = {'name': name,
+ 'texname': name.replace('_', '\\_'),
+ 'name_lower': name.lower(),
+ 'NAME': name.upper(),
+ 'begintitle': gentitle(name),
+ 'endtitle': gentitle('end of %s' % name),
+ 'fortranname': fname,
+ 'FORTRANNAME': fname.upper(),
+ 'callstatement': getcallstatement(rout) or '',
+ 'usercode': getusercode(rout) or '',
+ 'usercode1': getusercode1(rout) or '',
+ }
+ if '_' in fname:
+ ret['F_FUNC'] = 'F_FUNC_US'
+ else:
+ ret['F_FUNC'] = 'F_FUNC'
+ if '_' in name:
+ ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC_US'
+ else:
+ ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC'
+ lcb_map = {}
+ if 'use' in rout:
+ for u in rout['use'].keys():
+ if u in cb_rules.cb_map:
+ for un in cb_rules.cb_map[u]:
+ ln = un[0]
+ if 'map' in rout['use'][u]:
+ for k in rout['use'][u]['map'].keys():
+ if rout['use'][u]['map'][k] == un[0]:
+ ln = k
+ break
+ lcb_map[ln] = un[1]
+ elif 'externals' in rout and rout['externals']:
+ errmess('routsign2map: Confused: function %s has externals %s but no "use" statement.\n' % (
+ ret['name'], repr(rout['externals'])))
+ ret['callprotoargument'] = getcallprotoargument(rout, lcb_map) or ''
+ if isfunction(rout):
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ ret['rname'] = a
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
+ ret['ctype'] = getctype(rout['vars'][a])
+ if hasresultnote(rout):
+ ret['resultnote'] = rout['vars'][a]['note']
+ rout['vars'][a]['note'] = ['See elsewhere.']
+ if ret['ctype'] in c2buildvalue_map:
+ ret['rformat'] = c2buildvalue_map[ret['ctype']]
+ else:
+ ret['rformat'] = 'O'
+ errmess('routsign2map: no c2buildvalue key for type %s\n' %
+ (repr(ret['ctype'])))
+ if debugcapi(rout):
+ if ret['ctype'] in cformat_map:
+ ret['routdebugshowvalue'] = 'debug-capi:%s=%s' % (
+ a, cformat_map[ret['ctype']])
+ if isstringfunction(rout):
+ ret['routdebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
+ a, a)
+ if isstringfunction(rout):
+ ret['rlength'] = getstrlength(rout['vars'][a])
+ if ret['rlength'] == '-1':
+ errmess('routsign2map: expected explicit specification of the length of the string returned by the fortran function %s; taking 10.\n' % (
+ repr(rout['name'])))
+ ret['rlength'] = '10'
+ if hasnote(rout):
+ ret['note'] = rout['note']
+ rout['note'] = ['See elsewhere.']
+ return ret
+
+
+def modsign2map(m):
+ """
+ modulename
+ """
+ if ismodule(m):
+ ret = {'f90modulename': m['name'],
+ 'F90MODULENAME': m['name'].upper(),
+ 'texf90modulename': m['name'].replace('_', '\\_')}
+ else:
+ ret = {'modulename': m['name'],
+ 'MODULENAME': m['name'].upper(),
+ 'texmodulename': m['name'].replace('_', '\\_')}
+ ret['restdoc'] = getrestdoc(m) or []
+ if hasnote(m):
+ ret['note'] = m['note']
+ ret['usercode'] = getusercode(m) or ''
+ ret['usercode1'] = getusercode1(m) or ''
+ if m['body']:
+ ret['interface_usercode'] = getusercode(m['body'][0]) or ''
+ else:
+ ret['interface_usercode'] = ''
+ ret['pymethoddef'] = getpymethoddef(m) or ''
+ if 'coutput' in m:
+ ret['coutput'] = m['coutput']
+ if 'f2py_wrapper_output' in m:
+ ret['f2py_wrapper_output'] = m['f2py_wrapper_output']
+ return ret
+
+
+def cb_sign2map(a, var, index=None):
+ ret = {'varname': a}
+ ret['varname_i'] = ret['varname']
+ ret['ctype'] = getctype(var)
+ if ret['ctype'] in c2capi_map:
+ ret['atype'] = c2capi_map[ret['ctype']]
+ ret['elsize'] = get_elsize(var)
+ if ret['ctype'] in cformat_map:
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isarray(var):
+ ret = dictappend(ret, getarrdims(a, var))
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
+ if hasnote(var):
+ ret['note'] = var['note']
+ var['note'] = ['See elsewhere.']
+ return ret
+
+
+def cb_routsign2map(rout, um):
+ """
+ name,begintitle,endtitle,argname
+ ctype,rctype,maxnofargs,nofoptargs,returncptr
+ """
+ ret = {'name': 'cb_%s_in_%s' % (rout['name'], um),
+ 'returncptr': ''}
+ if isintent_callback(rout):
+ if '_' in rout['name']:
+ F_FUNC = 'F_FUNC_US'
+ else:
+ F_FUNC = 'F_FUNC'
+ ret['callbackname'] = '%s(%s,%s)' \
+ % (F_FUNC,
+ rout['name'].lower(),
+ rout['name'].upper(),
+ )
+ ret['static'] = 'extern'
+ else:
+ ret['callbackname'] = ret['name']
+ ret['static'] = 'static'
+ ret['argname'] = rout['name']
+ ret['begintitle'] = gentitle(ret['name'])
+ ret['endtitle'] = gentitle('end of %s' % ret['name'])
+ ret['ctype'] = getctype(rout)
+ ret['rctype'] = 'void'
+ if ret['ctype'] == 'string':
+ ret['rctype'] = 'void'
+ else:
+ ret['rctype'] = ret['ctype']
+ if ret['rctype'] != 'void':
+ if iscomplexfunction(rout):
+ ret['returncptr'] = """
+#ifdef F2PY_CB_RETURNCOMPLEX
+return_value=
+#endif
+"""
+ else:
+ ret['returncptr'] = 'return_value='
+ if ret['ctype'] in cformat_map:
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isstringfunction(rout):
+ ret['strlength'] = getstrlength(rout)
+ if isfunction(rout):
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if hasnote(rout['vars'][a]):
+ ret['note'] = rout['vars'][a]['note']
+ rout['vars'][a]['note'] = ['See elsewhere.']
+ ret['rname'] = a
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
+ if iscomplexfunction(rout):
+ ret['rctype'] = """
+#ifdef F2PY_CB_RETURNCOMPLEX
+#ctype#
+#else
+void
+#endif
+"""
+ else:
+ if hasnote(rout):
+ ret['note'] = rout['note']
+ rout['note'] = ['See elsewhere.']
+ nofargs = 0
+ nofoptargs = 0
+ if 'args' in rout and 'vars' in rout:
+ for a in rout['args']:
+ var = rout['vars'][a]
+ if l_or(isintent_in, isintent_inout)(var):
+ nofargs = nofargs + 1
+ if isoptional(var):
+ nofoptargs = nofoptargs + 1
+ ret['maxnofargs'] = repr(nofargs)
+ ret['nofoptargs'] = repr(nofoptargs)
+ if hasnote(rout) and isfunction(rout) and 'result' in rout:
+ ret['routnote'] = rout['note']
+ rout['note'] = ['See elsewhere.']
+ return ret
+
+
+def common_sign2map(a, var): # obsolute
+ ret = {'varname': a, 'ctype': getctype(var)}
+ if isstringarray(var):
+ ret['ctype'] = 'char'
+ if ret['ctype'] in c2capi_map:
+ ret['atype'] = c2capi_map[ret['ctype']]
+ ret['elsize'] = get_elsize(var)
+ if ret['ctype'] in cformat_map:
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isarray(var):
+ ret = dictappend(ret, getarrdims(a, var))
+ elif isstring(var):
+ ret['size'] = getstrlength(var)
+ ret['rank'] = '1'
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
+ if hasnote(var):
+ ret['note'] = var['note']
+ var['note'] = ['See elsewhere.']
+ # for strings this returns 0-rank but actually is 1-rank
+ ret['arrdocstr'] = getarrdocsign(a, var)
+ return ret
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.py b/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.py
new file mode 100644
index 0000000000000000000000000000000000000000..64347b737454fe1bae544b6630de2729157d7f71
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/common_rules.py
@@ -0,0 +1,146 @@
+"""
+Build common block mechanism for f2py2e.
+
+Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
+Copyright 2011 -- present NumPy Developers.
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+"""
+from . import __version__
+f2py_version = __version__.version
+
+from .auxfuncs import (
+ hasbody, hascommon, hasnote, isintent_hide, outmess, getuseblocks
+)
+from . import capi_maps
+from . import func2subr
+from .crackfortran import rmbadname
+
+
+def findcommonblocks(block, top=1):
+ ret = []
+ if hascommon(block):
+ for key, value in block['common'].items():
+ vars_ = {v: block['vars'][v] for v in value}
+ ret.append((key, value, vars_))
+ elif hasbody(block):
+ for b in block['body']:
+ ret = ret + findcommonblocks(b, 0)
+ if top:
+ tret = []
+ names = []
+ for t in ret:
+ if t[0] not in names:
+ names.append(t[0])
+ tret.append(t)
+ return tret
+ return ret
+
+
+def buildhooks(m):
+ ret = {'commonhooks': [], 'initcommonhooks': [],
+ 'docs': ['"COMMON blocks:\\n"']}
+ fwrap = ['']
+
+ def fadd(line, s=fwrap):
+ s[0] = '%s\n %s' % (s[0], line)
+ chooks = ['']
+
+ def cadd(line, s=chooks):
+ s[0] = '%s\n%s' % (s[0], line)
+ ihooks = ['']
+
+ def iadd(line, s=ihooks):
+ s[0] = '%s\n%s' % (s[0], line)
+ doc = ['']
+
+ def dadd(line, s=doc):
+ s[0] = '%s\n%s' % (s[0], line)
+ for (name, vnames, vars) in findcommonblocks(m):
+ lower_name = name.lower()
+ hnames, inames = [], []
+ for n in vnames:
+ if isintent_hide(vars[n]):
+ hnames.append(n)
+ else:
+ inames.append(n)
+ if hnames:
+ outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n\t\t Hidden: %s\n' % (
+ name, ','.join(inames), ','.join(hnames)))
+ else:
+ outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n' % (
+ name, ','.join(inames)))
+ fadd('subroutine f2pyinit%s(setupfunc)' % name)
+ for usename in getuseblocks(m):
+ fadd(f'use {usename}')
+ fadd('external setupfunc')
+ for n in vnames:
+ fadd(func2subr.var2fixfortran(vars, n))
+ if name == '_BLNK_':
+ fadd('common %s' % (','.join(vnames)))
+ else:
+ fadd('common /%s/ %s' % (name, ','.join(vnames)))
+ fadd('call setupfunc(%s)' % (','.join(inames)))
+ fadd('end\n')
+ cadd('static FortranDataDef f2py_%s_def[] = {' % (name))
+ idims = []
+ for n in inames:
+ ct = capi_maps.getctype(vars[n])
+ elsize = capi_maps.get_elsize(vars[n])
+ at = capi_maps.c2capi_map[ct]
+ dm = capi_maps.getarrdims(n, vars[n])
+ if dm['dims']:
+ idims.append('(%s)' % (dm['dims']))
+ else:
+ idims.append('')
+ dms = dm['dims'].strip()
+ if not dms:
+ dms = '-1'
+ cadd('\t{\"%s\",%s,{{%s}},%s, %s},'
+ % (n, dm['rank'], dms, at, elsize))
+ cadd('\t{NULL}\n};')
+ inames1 = rmbadname(inames)
+ inames1_tps = ','.join(['char *' + s for s in inames1])
+ cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
+ cadd('\tint i_f2py=0;')
+ for n in inames1:
+ cadd('\tf2py_%s_def[i_f2py++].data = %s;' % (name, n))
+ cadd('}')
+ if '_' in lower_name:
+ F_FUNC = 'F_FUNC_US'
+ else:
+ F_FUNC = 'F_FUNC'
+ cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
+ % (F_FUNC, lower_name, name.upper(),
+ ','.join(['char*'] * len(inames1))))
+ cadd('static void f2py_init_%s(void) {' % name)
+ cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
+ % (F_FUNC, lower_name, name.upper(), name))
+ cadd('}\n')
+ iadd('\ttmp = PyFortranObject_New(f2py_%s_def,f2py_init_%s);' % (name, name))
+ iadd('\tif (tmp == NULL) return NULL;')
+ iadd('\tif (F2PyDict_SetItemString(d, \"%s\", tmp) == -1) return NULL;'
+ % name)
+ iadd('\tPy_DECREF(tmp);')
+ tname = name.replace('_', '\\_')
+ dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname))
+ dadd('\\begin{description}')
+ for n in inames:
+ dadd('\\item[]{{}\\verb@%s@{}}' %
+ (capi_maps.getarrdocsign(n, vars[n])))
+ if hasnote(vars[n]):
+ note = vars[n]['note']
+ if isinstance(note, list):
+ note = '\n'.join(note)
+ dadd('--- %s' % (note))
+ dadd('\\end{description}')
+ ret['docs'].append(
+ '"\t/%s/ %s\\n"' % (name, ','.join(map(lambda v, d: v + d, inames, idims))))
+ ret['commonhooks'] = chooks
+ ret['initcommonhooks'] = ihooks
+ ret['latexdoc'] = doc[0]
+ if len(ret['docs']) <= 1:
+ ret['docs'] = ''
+ return ret, fwrap[0]
diff --git a/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.py b/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.py
new file mode 100644
index 0000000000000000000000000000000000000000..8d3fc27608bd85f67867b66d39640a5167d7e5ee
--- /dev/null
+++ b/.venv/lib/python3.11/site-packages/numpy/f2py/crackfortran.py
@@ -0,0 +1,3767 @@
+#!/usr/bin/env python3
+"""
+crackfortran --- read fortran (77,90) code and extract declaration information.
+
+Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
+Copyright 2011 -- present NumPy Developers.
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+
+Usage of crackfortran:
+======================
+Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h
+ -m ,--ignore-contains
+Functions: crackfortran, crack2fortran
+The following Fortran statements/constructions are supported
+(or will be if needed):
+ block data,byte,call,character,common,complex,contains,data,
+ dimension,double complex,double precision,end,external,function,
+ implicit,integer,intent,interface,intrinsic,
+ logical,module,optional,parameter,private,public,
+ program,real,(sequence?),subroutine,type,use,virtual,
+ include,pythonmodule
+Note: 'virtual' is mapped to 'dimension'.
+Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug).
+Note: code after 'contains' will be ignored until its scope ends.
+Note: 'common' statement is extended: dimensions are moved to variable definitions
+Note: f2py directive: f2py is read as
+Note: pythonmodule is introduced to represent Python module
+
+Usage:
+ `postlist=crackfortran(files)`
+ `postlist` contains declaration information read from the list of files `files`.
+ `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file
+
+ `postlist` has the following structure:
+ *** it is a list of dictionaries containing `blocks':
+ B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
+ 'implicit','externals','interfaced','common','sortvars',
+ 'commonvars','note']}
+ B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
+ 'program' | 'block data' | 'type' | 'pythonmodule' |
+ 'abstract interface'
+ B['body'] --- list containing `subblocks' with the same structure as `blocks'
+ B['parent_block'] --- dictionary of a parent block:
+ C['body'][]['parent_block'] is C
+ B['vars'] --- dictionary of variable definitions
+ B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first)
+ B['name'] --- name of the block (not if B['block']=='interface')
+ B['prefix'] --- prefix string (only if B['block']=='function')
+ B['args'] --- list of argument names if B['block']== 'function' | 'subroutine'
+ B['result'] --- name of the return value (only if B['block']=='function')
+ B['implicit'] --- dictionary {'a':,'b':...} | None
+ B['externals'] --- list of variables being external
+ B['interfaced'] --- list of variables being external and defined
+ B['common'] --- dictionary of common blocks (list of objects)
+ B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions)
+ B['from'] --- string showing the 'parents' of the current block
+ B['use'] --- dictionary of modules used in current block:
+ {:{['only':<0|1>],['map':{:,...}]}}
+ B['note'] --- list of LaTeX comments on the block
+ B['f2pyenhancements'] --- optional dictionary
+ {'threadsafe':'','fortranname':,
+ 'callstatement':|,
+ 'callprotoargument':,
+ 'usercode':|,
+ 'pymethoddef:'
+ }
+ B['entry'] --- dictionary {entryname:argslist,..}
+ B['varnames'] --- list of variable names given in the order of reading the
+ Fortran code, useful for derived types.
+ B['saved_interface'] --- a string of scanned routine signature, defines explicit interface
+ *** Variable definition is a dictionary
+ D = B['vars'][] =
+ {'typespec'[,'attrspec','kindselector','charselector','=','typename']}
+ D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
+ 'double precision' | 'integer' | 'logical' | 'real' | 'type'
+ D['attrspec'] --- list of attributes (e.g. 'dimension()',
+ 'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)',
+ 'optional','required', etc)
+ K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
+ 'complex' | 'integer' | 'logical' | 'real' )
+ C = D['charselector'] = {['*','len','kind','f2py_len']}
+ (only if D['typespec']=='character')
+ D['='] --- initialization expression string
+ D['typename'] --- name of the type if D['typespec']=='type'
+ D['dimension'] --- list of dimension bounds
+ D['intent'] --- list of intent specifications
+ D['depend'] --- list of variable names on which current variable depends on
+ D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised
+ D['note'] --- list of LaTeX comments on the variable
+ *** Meaning of kind/char selectors (few examples):
+ D['typespec>']*K['*']
+ D['typespec'](kind=K['kind'])
+ character*C['*']
+ character(len=C['len'],kind=C['kind'], f2py_len=C['f2py_len'])
+ (see also fortran type declaration statement formats below)
+
+Fortran 90 type declaration statement format (F77 is subset of F90)
+====================================================================
+(Main source: IBM XL Fortran 5.1 Language Reference Manual)
+type declaration = [[]::]
+ = byte |
+ character[] |
+ complex[] |
+ double complex |
+ double precision |
+ integer[] |
+ logical[] |
+ real[] |
+ type()
+ = * |
+ ([len=][,[kind=]]) |
+ (kind=[,len=])
+ = * |
+ ([kind=])
+ = comma separated list of attributes.
+ Only the following attributes are used in
+ building up the interface:
+ external
+ (parameter --- affects '=' key)
+ optional
+ intent
+ Other attributes are ignored.
+ = in | out | inout
+ = comma separated list of dimension bounds.
+ = [[*][()] | [()]*]
+ [// | =] [,]
+
+In addition, the following attributes are used: check,depend,note
+
+TODO:
+ * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
+ -> 'real x(2)')
+ The above may be solved by creating appropriate preprocessor program, for example.
+
+"""
+import sys
+import string
+import fileinput
+import re
+import os
+import copy
+import platform
+import codecs
+from pathlib import Path
+try:
+ import charset_normalizer
+except ImportError:
+ charset_normalizer = None
+
+from . import __version__
+
+# The environment provided by auxfuncs.py is needed for some calls to eval.
+# As the needed functions cannot be determined by static inspection of the
+# code, it is safest to use import * pending a major refactoring of f2py.
+from .auxfuncs import *
+from . import symbolic
+
+f2py_version = __version__.version
+
+# Global flags:
+strictf77 = 1 # Ignore `!' comments unless line[0]=='!'
+sourcecodeform = 'fix' # 'fix','free'
+quiet = 0 # Be verbose if 0 (Obsolete: not used any more)
+verbose = 1 # Be quiet if 0, extra verbose if > 1.
+tabchar = 4 * ' '
+pyffilename = ''
+f77modulename = ''
+skipemptyends = 0 # for old F77 programs without 'program' statement
+ignorecontains = 1
+dolowercase = 1
+debug = []
+
+# Global variables
+beginpattern = ''
+currentfilename = ''
+expectbegin = 1
+f90modulevars = {}
+filepositiontext = ''
+gotnextfile = 1
+groupcache = None
+groupcounter = 0
+grouplist = {groupcounter: []}
+groupname = ''
+include_paths = []
+neededmodule = -1
+onlyfuncs = []
+previous_context = None
+skipblocksuntil = -1
+skipfuncs = []
+skipfunctions = []
+usermodules = []
+
+
+def reset_global_f2py_vars():
+ global groupcounter, grouplist, neededmodule, expectbegin
+ global skipblocksuntil, usermodules, f90modulevars, gotnextfile
+ global filepositiontext, currentfilename, skipfunctions, skipfuncs
+ global onlyfuncs, include_paths, previous_context
+ global strictf77, sourcecodeform, quiet, verbose, tabchar, pyffilename
+ global f77modulename, skipemptyends, ignorecontains, dolowercase, debug
+
+ # flags
+ strictf77 = 1
+ sourcecodeform = 'fix'
+ quiet = 0
+ verbose = 1
+ tabchar = 4 * ' '
+ pyffilename = ''
+ f77modulename = ''
+ skipemptyends = 0
+ ignorecontains = 1
+ dolowercase = 1
+ debug = []
+ # variables
+ groupcounter = 0
+ grouplist = {groupcounter: []}
+ neededmodule = -1
+ expectbegin = 1
+ skipblocksuntil = -1
+ usermodules = []
+ f90modulevars = {}
+ gotnextfile = 1
+ filepositiontext = ''
+ currentfilename = ''
+ skipfunctions = []
+ skipfuncs = []
+ onlyfuncs = []
+ include_paths = []
+ previous_context = None
+
+
+def outmess(line, flag=1):
+ global filepositiontext
+
+ if not verbose:
+ return
+ if not quiet:
+ if flag:
+ sys.stdout.write(filepositiontext)
+ sys.stdout.write(line)
+
+re._MAXCACHE = 50
+defaultimplicitrules = {}
+for c in "abcdefghopqrstuvwxyz$_":
+ defaultimplicitrules[c] = {'typespec': 'real'}
+for c in "ijklmn":
+ defaultimplicitrules[c] = {'typespec': 'integer'}
+badnames = {}
+invbadnames = {}
+for n in ['int', 'double', 'float', 'char', 'short', 'long', 'void', 'case', 'while',
+ 'return', 'signed', 'unsigned', 'if', 'for', 'typedef', 'sizeof', 'union',
+ 'struct', 'static', 'register', 'new', 'break', 'do', 'goto', 'switch',
+ 'continue', 'else', 'inline', 'extern', 'delete', 'const', 'auto',
+ 'len', 'rank', 'shape', 'index', 'slen', 'size', '_i',
+ 'max', 'min',
+ 'flen', 'fshape',
+ 'string', 'complex_double', 'float_double', 'stdin', 'stderr', 'stdout',
+ 'type', 'default']:
+ badnames[n] = n + '_bn'
+ invbadnames[n + '_bn'] = n
+
+
+def rmbadname1(name):
+ if name in badnames:
+ errmess('rmbadname1: Replacing "%s" with "%s".\n' %
+ (name, badnames[name]))
+ return badnames[name]
+ return name
+
+
+def rmbadname(names):
+ return [rmbadname1(_m) for _m in names]
+
+
+def undo_rmbadname1(name):
+ if name in invbadnames:
+ errmess('undo_rmbadname1: Replacing "%s" with "%s".\n'
+ % (name, invbadnames[name]))
+ return invbadnames[name]
+ return name
+
+
+def undo_rmbadname(names):
+ return [undo_rmbadname1(_m) for _m in names]
+
+
+_has_f_header = re.compile(r'-\*-\s*fortran\s*-\*-', re.I).search
+_has_f90_header = re.compile(r'-\*-\s*f90\s*-\*-', re.I).search
+_has_fix_header = re.compile(r'-\*-\s*fix\s*-\*-', re.I).search
+_free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]', re.I).match
+
+# Extensions
+COMMON_FREE_EXTENSIONS = ['.f90', '.f95', '.f03', '.f08']
+COMMON_FIXED_EXTENSIONS = ['.for', '.ftn', '.f77', '.f']
+
+
+def openhook(filename, mode):
+ """Ensures that filename is opened with correct encoding parameter.
+
+ This function uses charset_normalizer package, when available, for
+ determining the encoding of the file to be opened. When charset_normalizer
+ is not available, the function detects only UTF encodings, otherwise, ASCII
+ encoding is used as fallback.
+ """
+ # Reads in the entire file. Robust detection of encoding.
+ # Correctly handles comments or late stage unicode characters
+ # gh-22871
+ if charset_normalizer is not None:
+ encoding = charset_normalizer.from_path(filename).best().encoding
+ else:
+ # hint: install charset_normalizer for correct encoding handling
+ # No need to read the whole file for trying with startswith
+ nbytes = min(32, os.path.getsize(filename))
+ with open(filename, 'rb') as fhandle:
+ raw = fhandle.read(nbytes)
+ if raw.startswith(codecs.BOM_UTF8):
+ encoding = 'UTF-8-SIG'
+ elif raw.startswith((codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE)):
+ encoding = 'UTF-32'
+ elif raw.startswith((codecs.BOM_LE, codecs.BOM_BE)):
+ encoding = 'UTF-16'
+ else:
+ # Fallback, without charset_normalizer
+ encoding = 'ascii'
+ return open(filename, mode, encoding=encoding)
+
+
+def is_free_format(fname):
+ """Check if file is in free format Fortran."""
+ # f90 allows both fixed and free format, assuming fixed unless
+ # signs of free format are detected.
+ result = False
+ if Path(fname).suffix.lower() in COMMON_FREE_EXTENSIONS:
+ result = True
+ with openhook(fname, 'r') as fhandle:
+ line = fhandle.readline()
+ n = 15 # the number of non-comment lines to scan for hints
+ if _has_f_header(line):
+ n = 0
+ elif _has_f90_header(line):
+ n = 0
+ result = True
+ while n > 0 and line:
+ if line[0] != '!' and line.strip():
+ n -= 1
+ if (line[0] != '\t' and _free_f90_start(line[:5])) or line[-2:-1] == '&':
+ result = True
+ break
+ line = fhandle.readline()
+ return result
+
+
+# Read fortran (77,90) code
+def readfortrancode(ffile, dowithline=show, istop=1):
+ """
+ Read fortran codes from files and
+ 1) Get rid of comments, line continuations, and empty lines; lower cases.
+ 2) Call dowithline(line) on every line.
+ 3) Recursively call itself when statement \"include ''\" is met.
+ """
+ global gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77
+ global beginpattern, quiet, verbose, dolowercase, include_paths
+
+ if not istop:
+ saveglobals = gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+ beginpattern, quiet, verbose, dolowercase
+ if ffile == []:
+ return
+ localdolowercase = dolowercase
+ # cont: set to True when the content of the last line read
+ # indicates statement continuation
+ cont = False
+ finalline = ''
+ ll = ''
+ includeline = re.compile(
+ r'\s*include\s*(\'|")(?P[^\'"]*)(\'|")', re.I)
+ cont1 = re.compile(r'(?P.*)&\s*\Z')
+ cont2 = re.compile(r'(\s*&|)(?P.*)')
+ mline_mark = re.compile(r".*?'''")
+ if istop:
+ dowithline('', -1)
+ ll, l1 = '', ''
+ spacedigits = [' '] + [str(_m) for _m in range(10)]
+ filepositiontext = ''
+ fin = fileinput.FileInput(ffile, openhook=openhook)
+ while True:
+ try:
+ l = fin.readline()
+ except UnicodeDecodeError as msg:
+ raise Exception(
+ f'readfortrancode: reading {fin.filename()}#{fin.lineno()}'
+ f' failed with\n{msg}.\nIt is likely that installing charset_normalizer'
+ ' package will help f2py determine the input file encoding'
+ ' correctly.')
+ if not l:
+ break
+ if fin.isfirstline():
+ filepositiontext = ''
+ currentfilename = fin.filename()
+ gotnextfile = 1
+ l1 = l
+ strictf77 = 0
+ sourcecodeform = 'fix'
+ ext = os.path.splitext(currentfilename)[1]
+ if Path(currentfilename).suffix.lower() in COMMON_FIXED_EXTENSIONS and \
+ not (_has_f90_header(l) or _has_fix_header(l)):
+ strictf77 = 1
+ elif is_free_format(currentfilename) and not _has_fix_header(l):
+ sourcecodeform = 'free'
+ if strictf77:
+ beginpattern = beginpattern77
+ else:
+ beginpattern = beginpattern90
+ outmess('\tReading file %s (format:%s%s)\n'
+ % (repr(currentfilename), sourcecodeform,
+ strictf77 and ',strict' or ''))
+
+ l = l.expandtabs().replace('\xa0', ' ')
+ # Get rid of newline characters
+ while not l == '':
+ if l[-1] not in "\n\r\f":
+ break
+ l = l[:-1]
+ if not strictf77:
+ (l, rl) = split_by_unquoted(l, '!')
+ l += ' '
+ if rl[:5].lower() == '!f2py': # f2py directive
+ l, _ = split_by_unquoted(l + 4 * ' ' + rl[5:], '!')
+ if l.strip() == '': # Skip empty line
+ if sourcecodeform == 'free':
+ # In free form, a statement continues in the next line
+ # that is not a comment line [3.3.2.4^1], lines with
+ # blanks are comment lines [3.3.2.3^1]. Hence, the
+ # line continuation flag must retain its state.
+ pass
+ else:
+ # In fixed form, statement continuation is determined
+ # by a non-blank character at the 6-th position. Empty
+ # line indicates a start of a new statement
+ # [3.3.3.3^1]. Hence, the line continuation flag must
+ # be reset.
+ cont = False
+ continue
+ if sourcecodeform == 'fix':
+ if l[0] in ['*', 'c', '!', 'C', '#']:
+ if l[1:5].lower() == 'f2py': # f2py directive
+ l = ' ' + l[5:]
+ else: # Skip comment line
+ cont = False
+ continue
+ elif strictf77:
+ if len(l) > 72:
+ l = l[:72]
+ if not (l[0] in spacedigits):
+ raise Exception('readfortrancode: Found non-(space,digit) char '
+ 'in the first column.\n\tAre you sure that '
+ 'this code is in fix form?\n\tline=%s' % repr(l))
+
+ if (not cont or strictf77) and (len(l) > 5 and not l[5] == ' '):
+ # Continuation of a previous line
+ ll = ll + l[6:]
+ finalline = ''
+ origfinalline = ''
+ else:
+ if not strictf77:
+ # F90 continuation
+ r = cont1.match(l)
+ if r:
+ l = r.group('line') # Continuation follows ..
+ if cont:
+ ll = ll + cont2.match(l).group('line')
+ finalline = ''
+ origfinalline = ''
+ else:
+ # clean up line beginning from possible digits.
+ l = ' ' + l[5:]
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ ll = l
+ cont = (r is not None)
+ else:
+ # clean up line beginning from possible digits.
+ l = ' ' + l[5:]
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ ll = l
+
+ elif sourcecodeform == 'free':
+ if not cont and ext == '.pyf' and mline_mark.match(l):
+ l = l + '\n'
+ while True:
+ lc = fin.readline()
+ if not lc:
+ errmess(
+ 'Unexpected end of file when reading multiline\n')
+ break
+ l = l + lc
+ if mline_mark.match(lc):
+ break
+ l = l.rstrip()
+ r = cont1.match(l)
+ if r:
+ l = r.group('line') # Continuation follows ..
+ if cont:
+ ll = ll + cont2.match(l).group('line')
+ finalline = ''
+ origfinalline = ''
+ else:
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ ll = l
+ cont = (r is not None)
+ else:
+ raise ValueError(
+ "Flag sourcecodeform must be either 'fix' or 'free': %s" % repr(sourcecodeform))
+ filepositiontext = 'Line #%d in %s:"%s"\n\t' % (
+ fin.filelineno() - 1, currentfilename, l1)
+ m = includeline.match(origfinalline)
+ if m:
+ fn = m.group('name')
+ if os.path.isfile(fn):
+ readfortrancode(fn, dowithline=dowithline, istop=0)
+ else:
+ include_dirs = [
+ os.path.dirname(currentfilename)] + include_paths
+ foundfile = 0
+ for inc_dir in include_dirs:
+ fn1 = os.path.join(inc_dir, fn)
+ if os.path.isfile(fn1):
+ foundfile = 1
+ readfortrancode(fn1, dowithline=dowithline, istop=0)
+ break
+ if not foundfile:
+ outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n' % (
+ repr(fn), os.pathsep.join(include_dirs)))
+ else:
+ dowithline(finalline)
+ l1 = ll
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ filepositiontext = 'Line #%d in %s:"%s"\n\t' % (
+ fin.filelineno() - 1, currentfilename, l1)
+ m = includeline.match(origfinalline)
+ if m:
+ fn = m.group('name')
+ if os.path.isfile(fn):
+ readfortrancode(fn, dowithline=dowithline, istop=0)
+ else:
+ include_dirs = [os.path.dirname(currentfilename)] + include_paths
+ foundfile = 0
+ for inc_dir in include_dirs:
+ fn1 = os.path.join(inc_dir, fn)
+ if os.path.isfile(fn1):
+ foundfile = 1
+ readfortrancode(fn1, dowithline=dowithline, istop=0)
+ break
+ if not foundfile:
+ outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n' % (
+ repr(fn), os.pathsep.join(include_dirs)))
+ else:
+ dowithline(finalline)
+ filepositiontext = ''
+ fin.close()
+ if istop:
+ dowithline('', 1)
+ else:
+ gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+ beginpattern, quiet, verbose, dolowercase = saveglobals
+
+# Crack line
+beforethisafter = r'\s*(?P%s(?=\s*(\b(%s)\b)))' + \
+ r'\s*(?P(\b(%s)\b))' + \
+ r'\s*(?P%s)\s*\Z'
+##
+fortrantypes = r'character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte'
+typespattern = re.compile(
+ beforethisafter % ('', fortrantypes, fortrantypes, '.*'), re.I), 'type'
+typespattern4implicit = re.compile(beforethisafter % (
+ '', fortrantypes + '|static|automatic|undefined', fortrantypes + '|static|automatic|undefined', '.*'), re.I)
+#
+functionpattern = re.compile(beforethisafter % (
+ r'([a-z]+[\w\s(=*+-/)]*?|)', 'function', 'function', '.*'), re.I), 'begin'
+subroutinepattern = re.compile(beforethisafter % (
+ r'[a-z\s]*?', 'subroutine', 'subroutine', '.*'), re.I), 'begin'
+# modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin'
+#
+groupbegins77 = r'program|block\s*data'
+beginpattern77 = re.compile(
+ beforethisafter % ('', groupbegins77, groupbegins77, '.*'), re.I), 'begin'
+groupbegins90 = groupbegins77 + \
+ r'|module(?!\s*procedure)|python\s*module|(abstract|)\s*interface|' + \
+ r'type(?!\s*\()'
+beginpattern90 = re.compile(
+ beforethisafter % ('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
+groupends = (r'end|endprogram|endblockdata|endmodule|endpythonmodule|'
+ r'endinterface|endsubroutine|endfunction')
+endpattern = re.compile(
+ beforethisafter % ('', groupends, groupends, '.*'), re.I), 'end'
+# block, the Fortran 2008 construct needs special handling in the rest of the file
+endifs = r'end\s*(if|do|where|select|while|forall|associate|' + \
+ r'critical|enum|team)'
+endifpattern = re.compile(
+ beforethisafter % (r'[\w]*?', endifs, endifs, '.*'), re.I), 'endif'
+#
+moduleprocedures = r'module\s*procedure'
+moduleprocedurepattern = re.compile(
+ beforethisafter % ('', moduleprocedures, moduleprocedures, '.*'), re.I), \
+ 'moduleprocedure'
+implicitpattern = re.compile(
+ beforethisafter % ('', 'implicit', 'implicit', '.*'), re.I), 'implicit'
+dimensionpattern = re.compile(beforethisafter % (
+ '', 'dimension|virtual', 'dimension|virtual', '.*'), re.I), 'dimension'
+externalpattern = re.compile(
+ beforethisafter % ('', 'external', 'external', '.*'), re.I), 'external'
+optionalpattern = re.compile(
+ beforethisafter % ('', 'optional', 'optional', '.*'), re.I), 'optional'
+requiredpattern = re.compile(
+ beforethisafter % ('', 'required', 'required', '.*'), re.I), 'required'
+publicpattern = re.compile(
+ beforethisafter % ('', 'public', 'public', '.*'), re.I), 'public'
+privatepattern = re.compile(
+ beforethisafter % ('', 'private', 'private', '.*'), re.I), 'private'
+intrinsicpattern = re.compile(
+ beforethisafter % ('', 'intrinsic', 'intrinsic', '.*'), re.I), 'intrinsic'
+intentpattern = re.compile(beforethisafter % (
+ '', 'intent|depend|note|check', 'intent|depend|note|check', r'\s*\(.*?\).*'), re.I), 'intent'
+parameterpattern = re.compile(
+ beforethisafter % ('', 'parameter', 'parameter', r'\s*\(.*'), re.I), 'parameter'
+datapattern = re.compile(
+ beforethisafter % ('', 'data', 'data', '.*'), re.I), 'data'
+callpattern = re.compile(
+ beforethisafter % ('', 'call', 'call', '.*'), re.I), 'call'
+entrypattern = re.compile(
+ beforethisafter % ('', 'entry', 'entry', '.*'), re.I), 'entry'
+callfunpattern = re.compile(
+ beforethisafter % ('', 'callfun', 'callfun', '.*'), re.I), 'callfun'
+commonpattern = re.compile(
+ beforethisafter % ('', 'common', 'common', '.*'), re.I), 'common'
+usepattern = re.compile(
+ beforethisafter % ('', 'use', 'use', '.*'), re.I), 'use'
+containspattern = re.compile(
+ beforethisafter % ('', 'contains', 'contains', ''), re.I), 'contains'
+formatpattern = re.compile(
+ beforethisafter % ('', 'format', 'format', '.*'), re.I), 'format'
+# Non-fortran and f2py-specific statements
+f2pyenhancementspattern = re.compile(beforethisafter % ('', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef',
+ 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', '.*'), re.I | re.S), 'f2pyenhancements'
+multilinepattern = re.compile(
+ r"\s*(?P''')(?P.*?)(?P''')\s*\Z", re.S), 'multiline'
+##
+
+def split_by_unquoted(line, characters):
+ """
+ Splits the line into (line[:i], line[i:]),
+ where i is the index of first occurrence of one of the characters
+ not within quotes, or len(line) if no such index exists
+ """
+ assert not (set('"\'') & set(characters)), "cannot split by unquoted quotes"
+ r = re.compile(
+ r"\A(?P({single_quoted}|{double_quoted}|{not_quoted})*)"
+ r"(?P{char}.*)\Z".format(
+ not_quoted="[^\"'{}]".format(re.escape(characters)),
+ char="[{}]".format(re.escape(characters)),
+ single_quoted=r"('([^'\\]|(\\.))*')",
+ double_quoted=r'("([^"\\]|(\\.))*")'))
+ m = r.match(line)
+ if m:
+ d = m.groupdict()
+ return (d["before"], d["after"])
+ return (line, "")
+
+def _simplifyargs(argsline):
+ a = []
+ for n in markoutercomma(argsline).split('@,@'):
+ for r in '(),':
+ n = n.replace(r, '_')
+ a.append(n)
+ return ','.join(a)
+
+crackline_re_1 = re.compile(r'\s*(?P\b[a-z]+\w*\b)\s*=.*', re.I)
+crackline_bind_1 = re.compile(r'\s*(?P\b[a-z]+\w*\b)\s*=.*', re.I)
+crackline_bindlang = re.compile(r'\s*bind\(\s*(?P[^,]+)\s*,\s*name\s*=\s*"(?P[^"]+)"\s*\)', re.I)
+
+def crackline(line, reset=0):
+ """
+ reset=-1 --- initialize
+ reset=0 --- crack the line
+ reset=1 --- final check if mismatch of blocks occurred
+
+ Cracked data is saved in grouplist[0].
+ """
+ global beginpattern, groupcounter, groupname, groupcache, grouplist
+ global filepositiontext, currentfilename, neededmodule, expectbegin
+ global skipblocksuntil, skipemptyends, previous_context, gotnextfile
+
+ _, has_semicolon = split_by_unquoted(line, ";")
+ if has_semicolon and not (f2pyenhancementspattern[0].match(line) or
+ multilinepattern[0].match(line)):
+ # XXX: non-zero reset values need testing
+ assert reset == 0, repr(reset)
+ # split line on unquoted semicolons
+ line, semicolon_line = split_by_unquoted(line, ";")
+ while semicolon_line:
+ crackline(line, reset)
+ line, semicolon_line = split_by_unquoted(semicolon_line[1:], ";")
+ crackline(line, reset)
+ return
+ if reset < 0:
+ groupcounter = 0
+ groupname = {groupcounter: ''}
+ groupcache = {groupcounter: {}}
+ grouplist = {groupcounter: []}
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcache[groupcounter]['block'] = ''
+ groupcache[groupcounter]['name'] = ''
+ neededmodule = -1
+ skipblocksuntil = -1
+ return
+ if reset > 0:
+ fl = 0
+ if f77modulename and neededmodule == groupcounter:
+ fl = 2
+ while groupcounter > fl:
+ outmess('crackline: groupcounter=%s groupname=%s\n' %
+ (repr(groupcounter), repr(groupname)))
+ outmess(
+ 'crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n')
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1
+ if f77modulename and neededmodule == groupcounter:
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end interface
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end module
+ neededmodule = -1
+ return
+ if line == '':
+ return
+ flag = 0
+ for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern,
+ requiredpattern,
+ parameterpattern, datapattern, publicpattern, privatepattern,
+ intrinsicpattern,
+ endifpattern, endpattern,
+ formatpattern,
+ beginpattern, functionpattern, subroutinepattern,
+ implicitpattern, typespattern, commonpattern,
+ callpattern, usepattern, containspattern,
+ entrypattern,
+ f2pyenhancementspattern,
+ multilinepattern,
+ moduleprocedurepattern
+ ]:
+ m = pat[0].match(line)
+ if m:
+ break
+ flag = flag + 1
+ if not m:
+ re_1 = crackline_re_1
+ if 0 <= skipblocksuntil <= groupcounter:
+ return
+ if 'externals' in groupcache[groupcounter]:
+ for name in groupcache[groupcounter]['externals']:
+ if name in invbadnames:
+ name = invbadnames[name]
+ if 'interfaced' in groupcache[groupcounter] and name in groupcache[groupcounter]['interfaced']:
+ continue
+ m1 = re.match(
+ r'(?P[^"]*)\b%s\b\s*@\(@(?P[^@]*)@\)@.*\Z' % name, markouterparen(line), re.I)
+ if m1:
+ m2 = re_1.match(m1.group('before'))
+ a = _simplifyargs(m1.group('args'))
+ if m2:
+ line = 'callfun %s(%s) result (%s)' % (
+ name, a, m2.group('result'))
+ else:
+ line = 'callfun %s(%s)' % (name, a)
+ m = callfunpattern[0].match(line)
+ if not m:
+ outmess(
+ 'crackline: could not resolve function call for line=%s.\n' % repr(line))
+ return
+ analyzeline(m, 'callfun', line)
+ return
+ if verbose > 1 or (verbose == 1 and currentfilename.lower().endswith('.pyf')):
+ previous_context = None
+ outmess('crackline:%d: No pattern for line\n' % (groupcounter))
+ return
+ elif pat[1] == 'end':
+ if 0 <= skipblocksuntil < groupcounter:
+ groupcounter = groupcounter - 1
+ if skipblocksuntil <= groupcounter:
+ return
+ if groupcounter <= 0:
+ raise Exception('crackline: groupcounter(=%s) is nonpositive. '
+ 'Check the blocks.'
+ % (groupcounter))
+ m1 = beginpattern[0].match((line))
+ if (m1) and (not m1.group('this') == groupname[groupcounter]):
+ raise Exception('crackline: End group %s does not match with '
+ 'previous Begin group %s\n\t%s' %
+ (repr(m1.group('this')), repr(groupname[groupcounter]),
+ filepositiontext)
+ )
+ if skipblocksuntil == groupcounter:
+ skipblocksuntil = -1
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1
+ if not skipemptyends:
+ expectbegin = 1
+ elif pat[1] == 'begin':
+ if 0 <= skipblocksuntil <= groupcounter:
+ groupcounter = groupcounter + 1
+ return
+ gotnextfile = 0
+ analyzeline(m, pat[1], line)
+ expectbegin = 0
+ elif pat[1] == 'endif':
+ pass
+ elif pat[1] == 'moduleprocedure':
+ analyzeline(m, pat[1], line)
+ elif pat[1] == 'contains':
+ if ignorecontains:
+ return
+ if 0 <= skipblocksuntil <= groupcounter:
+ return
+ skipblocksuntil = groupcounter
+ else:
+ if 0 <= skipblocksuntil <= groupcounter:
+ return
+ analyzeline(m, pat[1], line)
+
+
+def markouterparen(line):
+ l = ''
+ f = 0
+ for c in line:
+ if c == '(':
+ f = f + 1
+ if f == 1:
+ l = l + '@(@'
+ continue
+ elif c == ')':
+ f = f - 1
+ if f == 0:
+ l = l + '@)@'
+ continue
+ l = l + c
+ return l
+
+
+def markoutercomma(line, comma=','):
+ l = ''
+ f = 0
+ before, after = split_by_unquoted(line, comma + '()')
+ l += before
+ while after:
+ if (after[0] == comma) and (f == 0):
+ l += '@' + comma + '@'
+ else:
+ l += after[0]
+ if after[0] == '(':
+ f += 1
+ elif after[0] == ')':
+ f -= 1
+ before, after = split_by_unquoted(after[1:], comma + '()')
+ l += before
+ assert not f, repr((f, line, l))
+ return l
+
+def unmarkouterparen(line):
+ r = line.replace('@(@', '(').replace('@)@', ')')
+ return r
+
+
+def appenddecl(decl, decl2, force=1):
+ if not decl:
+ decl = {}
+ if not decl2:
+ return decl
+ if decl is decl2:
+ return decl
+ for k in list(decl2.keys()):
+ if k == 'typespec':
+ if force or k not in decl:
+ decl[k] = decl2[k]
+ elif k == 'attrspec':
+ for l in decl2[k]:
+ decl = setattrspec(decl, l, force)
+ elif k == 'kindselector':
+ decl = setkindselector(decl, decl2[k], force)
+ elif k == 'charselector':
+ decl = setcharselector(decl, decl2[k], force)
+ elif k in ['=', 'typename']:
+ if force or k not in decl:
+ decl[k] = decl2[k]
+ elif k == 'note':
+ pass
+ elif k in ['intent', 'check', 'dimension', 'optional',
+ 'required', 'depend']:
+ errmess('appenddecl: "%s" not implemented.\n' % k)
+ else:
+ raise Exception('appenddecl: Unknown variable definition key: ' +
+ str(k))
+ return decl
+
+selectpattern = re.compile(
+ r'\s*(?P(@\(@.*?@\)@|\*[\d*]+|\*\s*@\(@.*?@\)@|))(?P.*)\Z', re.I)
+typedefpattern = re.compile(
+ r'(?:,(?P[\w(),]+))?(::)?(?P\b[a-z$_][\w$]*\b)'
+ r'(?:\((?P[\w,]*)\))?\Z', re.I)
+nameargspattern = re.compile(
+ r'\s*(?P\b[\w$]+\b)\s*(@\(@\s*(?P[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P(?:(?!@\)@).)*)\s*@\)@))*\s*\Z', re.I)
+operatorpattern = re.compile(
+ r'\s*(?P(operator|assignment))'
+ r'@\(@\s*(?P[^)]+)\s*@\)@\s*\Z', re.I)
+callnameargspattern = re.compile(
+ r'\s*(?P\b[\w$]+\b)\s*@\(@\s*(?P.*)\s*@\)@\s*\Z', re.I)
+real16pattern = re.compile(
+ r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)')
+real8pattern = re.compile(
+ r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))')
+
+_intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b', re.I)
+
+
+def _is_intent_callback(vdecl):
+ for a in vdecl.get('attrspec', []):
+ if _intentcallbackpattern.match(a):
+ return 1
+ return 0
+
+
+def _resolvetypedefpattern(line):
+ line = ''.join(line.split()) # removes whitespace
+ m1 = typedefpattern.match(line)
+ print(line, m1)
+ if m1:
+ attrs = m1.group('attributes')
+ attrs = [a.lower() for a in attrs.split(',')] if attrs else []
+ return m1.group('name'), attrs, m1.group('params')
+ return None, [], None
+
+def parse_name_for_bind(line):
+ pattern = re.compile(r'bind\(\s*(?P[^,]+)(?:\s*,\s*name\s*=\s*["\'](?P[^"\']+)["\']\s*)?\)', re.I)
+ match = pattern.search(line)
+ bind_statement = None
+ if match:
+ bind_statement = match.group(0)
+ # Remove the 'bind' construct from the line.
+ line = line[:match.start()] + line[match.end():]
+ return line, bind_statement
+
+def _resolvenameargspattern(line):
+ line, bind_cname = parse_name_for_bind(line)
+ line = markouterparen(line)
+ m1 = nameargspattern.match(line)
+ if m1:
+ return m1.group('name'), m1.group('args'), m1.group('result'), bind_cname
+ m1 = operatorpattern.match(line)
+ if m1:
+ name = m1.group('scheme') + '(' + m1.group('name') + ')'
+ return name, [], None, None
+ m1 = callnameargspattern.match(line)
+ if m1:
+ return m1.group('name'), m1.group('args'), None, None
+ return None, [], None, None
+
+
+def analyzeline(m, case, line):
+ """
+ Reads each line in the input file in sequence and updates global vars.
+
+ Effectively reads and collects information from the input file to the
+ global variable groupcache, a dictionary containing info about each part
+ of the fortran module.
+
+ At the end of analyzeline, information is filtered into the correct dict
+ keys, but parameter values and dimensions are not yet interpreted.
+ """
+ global groupcounter, groupname, groupcache, grouplist, filepositiontext
+ global currentfilename, f77modulename, neededinterface, neededmodule
+ global expectbegin, gotnextfile, previous_context
+
+ block = m.group('this')
+ if case != 'multiline':
+ previous_context = None
+ if expectbegin and case not in ['begin', 'call', 'callfun', 'type'] \
+ and not skipemptyends and groupcounter < 1:
+ newname = os.path.basename(currentfilename).split('.')[0]
+ outmess(
+ 'analyzeline: no group yet. Creating program group with name "%s".\n' % newname)
+ gotnextfile = 0
+ groupcounter = groupcounter + 1
+ groupname[groupcounter] = 'program'
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcache[groupcounter]['block'] = 'program'
+ groupcache[groupcounter]['name'] = newname
+ groupcache[groupcounter]['from'] = 'fromsky'
+ expectbegin = 0
+ if case in ['begin', 'call', 'callfun']:
+ # Crack line => block,name,args,result
+ block = block.lower()
+ if re.match(r'block\s*data', block, re.I):
+ block = 'block data'
+ elif re.match(r'python\s*module', block, re.I):
+ block = 'python module'
+ elif re.match(r'abstract\s*interface', block, re.I):
+ block = 'abstract interface'
+ if block == 'type':
+ name, attrs, _ = _resolvetypedefpattern(m.group('after'))
+ groupcache[groupcounter]['vars'][name] = dict(attrspec = attrs)
+ args = []
+ result = None
+ else:
+ name, args, result, bindcline = _resolvenameargspattern(m.group('after'))
+ if name is None:
+ if block == 'block data':
+ name = '_BLOCK_DATA_'
+ else:
+ name = ''
+ if block not in ['interface', 'block data', 'abstract interface']:
+ outmess('analyzeline: No name/args pattern found for line.\n')
+
+ previous_context = (block, name, groupcounter)
+ if args:
+ args = rmbadname([x.strip()
+ for x in markoutercomma(args).split('@,@')])
+ else:
+ args = []
+ if '' in args:
+ while '' in args:
+ args.remove('')
+ outmess(
+ 'analyzeline: argument list is malformed (missing argument).\n')
+
+ # end of crack line => block,name,args,result
+ needmodule = 0
+ needinterface = 0
+
+ if case in ['call', 'callfun']:
+ needinterface = 1
+ if 'args' not in groupcache[groupcounter]:
+ return
+ if name not in groupcache[groupcounter]['args']:
+ return
+ for it in grouplist[groupcounter]:
+ if it['name'] == name:
+ return
+ if name in groupcache[groupcounter]['interfaced']:
+ return
+ block = {'call': 'subroutine', 'callfun': 'function'}[case]
+ if f77modulename and neededmodule == -1 and groupcounter <= 1:
+ neededmodule = groupcounter + 2
+ needmodule = 1
+ if block not in ['interface', 'abstract interface']:
+ needinterface = 1
+ # Create new block(s)
+ groupcounter = groupcounter + 1
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ if needmodule:
+ if verbose > 1:
+ outmess('analyzeline: Creating module block %s\n' %
+ repr(f77modulename), 0)
+ groupname[groupcounter] = 'module'
+ groupcache[groupcounter]['block'] = 'python module'
+ groupcache[groupcounter]['name'] = f77modulename
+ groupcache[groupcounter]['from'] = ''
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['interfaced'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcounter = groupcounter + 1
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ if needinterface:
+ if verbose > 1:
+ outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % (
+ groupcounter), 0)
+ groupname[groupcounter] = 'interface'
+ groupcache[groupcounter]['block'] = 'interface'
+ groupcache[groupcounter]['name'] = 'unknown_interface'
+ groupcache[groupcounter]['from'] = '%s:%s' % (
+ groupcache[groupcounter - 1]['from'], groupcache[groupcounter - 1]['name'])
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['interfaced'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcounter = groupcounter + 1
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ groupname[groupcounter] = block
+ groupcache[groupcounter]['block'] = block
+ if not name:
+ name = 'unknown_' + block.replace(' ', '_')
+ groupcache[groupcounter]['prefix'] = m.group('before')
+ groupcache[groupcounter]['name'] = rmbadname1(name)
+ groupcache[groupcounter]['result'] = result
+ if groupcounter == 1:
+ groupcache[groupcounter]['from'] = currentfilename
+ else:
+ if f77modulename and groupcounter == 3:
+ groupcache[groupcounter]['from'] = '%s:%s' % (
+ groupcache[groupcounter - 1]['from'], currentfilename)
+ else:
+ groupcache[groupcounter]['from'] = '%s:%s' % (
+ groupcache[groupcounter - 1]['from'], groupcache[groupcounter - 1]['name'])
+ for k in list(groupcache[groupcounter].keys()):
+ if not groupcache[groupcounter][k]:
+ del groupcache[groupcounter][k]
+
+ groupcache[groupcounter]['args'] = args
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['interfaced'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcache[groupcounter]['entry'] = {}
+ # end of creation
+ if block == 'type':
+ groupcache[groupcounter]['varnames'] = []
+
+ if case in ['call', 'callfun']: # set parents variables
+ if name not in groupcache[groupcounter - 2]['externals']:
+ groupcache[groupcounter - 2]['externals'].append(name)
+ groupcache[groupcounter]['vars'] = copy.deepcopy(
+ groupcache[groupcounter - 2]['vars'])
+ try:
+ del groupcache[groupcounter]['vars'][name][
+ groupcache[groupcounter]['vars'][name]['attrspec'].index('external')]
+ except Exception:
+ pass
+ if block in ['function', 'subroutine']: # set global attributes
+ # name is fortran name
+ if bindcline:
+ bindcdat = re.search(crackline_bindlang, bindcline)
+ if bindcdat:
+ groupcache[groupcounter]['bindlang'] = {name : {}}
+ groupcache[groupcounter]['bindlang'][name]["lang"] = bindcdat.group('lang')
+ if bindcdat.group('lang_name'):
+ groupcache[groupcounter]['bindlang'][name]["name"] = bindcdat.group('lang_name')
+ try:
+ groupcache[groupcounter]['vars'][name] = appenddecl(
+ groupcache[groupcounter]['vars'][name], groupcache[groupcounter - 2]['vars'][''])
+ except Exception:
+ pass
+ if case == 'callfun': # return type
+ if result and result in groupcache[groupcounter]['vars']:
+ if not name == result:
+ groupcache[groupcounter]['vars'][name] = appenddecl(
+ groupcache[groupcounter]['vars'][name], groupcache[groupcounter]['vars'][result])
+ # if groupcounter>1: # name is interfaced
+ try:
+ groupcache[groupcounter - 2]['interfaced'].append(name)
+ except Exception:
+ pass
+ if block == 'function':
+ t = typespattern[0].match(m.group('before') + ' ' + name)
+ if t:
+ typespec, selector, attr, edecl = cracktypespec0(
+ t.group('this'), t.group('after'))
+ updatevars(typespec, selector, attr, edecl)
+
+ if case in ['call', 'callfun']:
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end routine
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end interface
+
+ elif case == 'entry':
+ name, args, result, _= _resolvenameargspattern(m.group('after'))
+ if name is not None:
+ if args:
+ args = rmbadname([x.strip()
+ for x in markoutercomma(args).split('@,@')])
+ else:
+ args = []
+ assert result is None, repr(result)
+ groupcache[groupcounter]['entry'][name] = args
+ previous_context = ('entry', name, groupcounter)
+ elif case == 'type':
+ typespec, selector, attr, edecl = cracktypespec0(
+ block, m.group('after'))
+ last_name = updatevars(typespec, selector, attr, edecl)
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrinsic']:
+ edecl = groupcache[groupcounter]['vars']
+ ll = m.group('after').strip()
+ i = ll.find('::')
+ if i < 0 and case == 'intent':
+ i = markouterparen(ll).find('@)@') - 2
+ ll = ll[:i + 1] + '::' + ll[i + 1:]
+ i = ll.find('::')
+ if ll[i:] == '::' and 'args' in groupcache[groupcounter]:
+ outmess('All arguments will have attribute %s%s\n' %
+ (m.group('this'), ll[:i]))
+ ll = ll + ','.join(groupcache[groupcounter]['args'])
+ if i < 0:
+ i = 0
+ pl = ''
+ else:
+ pl = ll[:i].strip()
+ ll = ll[i + 2:]
+ ch = markoutercomma(pl).split('@,@')
+ if len(ch) > 1:
+ pl = ch[0]
+ outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (
+ ','.join(ch[1:])))
+ last_name = None
+
+ for e in [x.strip() for x in markoutercomma(ll).split('@,@')]:
+ m1 = namepattern.match(e)
+ if not m1:
+ if case in ['public', 'private']:
+ k = ''
+ else:
+ print(m.groupdict())
+ outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n' % (
+ case, repr(e)))
+ continue
+ else:
+ k = rmbadname1(m1.group('name'))
+ if case in ['public', 'private'] and \
+ (k == 'operator' or k == 'assignment'):
+ k += m1.group('after')
+ if k not in edecl:
+ edecl[k] = {}
+ if case == 'dimension':
+ ap = case + m1.group('after')
+ if case == 'intent':
+ ap = m.group('this') + pl
+ if _intentcallbackpattern.match(ap):
+ if k not in groupcache[groupcounter]['args']:
+ if groupcounter > 1:
+ if '__user__' not in groupcache[groupcounter - 2]['name']:
+ outmess(
+ 'analyzeline: missing __user__ module (could be nothing)\n')
+ # fixes ticket 1693
+ if k != groupcache[groupcounter]['name']:
+ outmess('analyzeline: appending intent(callback) %s'
+ ' to %s arguments\n' % (k, groupcache[groupcounter]['name']))
+ groupcache[groupcounter]['args'].append(k)
+ else:
+ errmess(
+ 'analyzeline: intent(callback) %s is ignored\n' % (k))
+ else:
+ errmess('analyzeline: intent(callback) %s is already'
+ ' in argument list\n' % (k))
+ if case in ['optional', 'required', 'public', 'external', 'private', 'intrinsic']:
+ ap = case
+ if 'attrspec' in edecl[k]:
+ edecl[k]['attrspec'].append(ap)
+ else:
+ edecl[k]['attrspec'] = [ap]
+ if case == 'external':
+ if groupcache[groupcounter]['block'] == 'program':
+ outmess('analyzeline: ignoring program arguments\n')
+ continue
+ if k not in groupcache[groupcounter]['args']:
+ continue
+ if 'externals' not in groupcache[groupcounter]:
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['externals'].append(k)
+ last_name = k
+ groupcache[groupcounter]['vars'] = edecl
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case == 'moduleprocedure':
+ groupcache[groupcounter]['implementedby'] = \
+ [x.strip() for x in m.group('after').split(',')]
+ elif case == 'parameter':
+ edecl = groupcache[groupcounter]['vars']
+ ll = m.group('after').strip()[1:-1]
+ last_name = None
+ for e in markoutercomma(ll).split('@,@'):
+ try:
+ k, initexpr = [x.strip() for x in e.split('=')]
+ except Exception:
+ outmess(
+ 'analyzeline: could not extract name,expr in parameter statement "%s" of "%s"\n' % (e, ll))
+ continue
+ params = get_parameters(edecl)
+ k = rmbadname1(k)
+ if k not in edecl:
+ edecl[k] = {}
+ if '=' in edecl[k] and (not edecl[k]['='] == initexpr):
+ outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n' % (
+ k, edecl[k]['='], initexpr))
+ t = determineexprtype(initexpr, params)
+ if t:
+ if t.get('typespec') == 'real':
+ tt = list(initexpr)
+ for m in real16pattern.finditer(initexpr):
+ tt[m.start():m.end()] = list(
+ initexpr[m.start():m.end()].lower().replace('d', 'e'))
+ initexpr = ''.join(tt)
+ elif t.get('typespec') == 'complex':
+ initexpr = initexpr[1:].lower().replace('d', 'e').\
+ replace(',', '+1j*(')
+ try:
+ v = eval(initexpr, {}, params)
+ except (SyntaxError, NameError, TypeError) as msg:
+ errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n'
+ % (initexpr, msg))
+ continue
+ edecl[k]['='] = repr(v)
+ if 'attrspec' in edecl[k]:
+ edecl[k]['attrspec'].append('parameter')
+ else:
+ edecl[k]['attrspec'] = ['parameter']
+ last_name = k
+ groupcache[groupcounter]['vars'] = edecl
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case == 'implicit':
+ if m.group('after').strip().lower() == 'none':
+ groupcache[groupcounter]['implicit'] = None
+ elif m.group('after'):
+ if 'implicit' in groupcache[groupcounter]:
+ impl = groupcache[groupcounter]['implicit']
+ else:
+ impl = {}
+ if impl is None:
+ outmess(
+ 'analyzeline: Overwriting earlier "implicit none" statement.\n')
+ impl = {}
+ for e in markoutercomma(m.group('after')).split('@,@'):
+ decl = {}
+ m1 = re.match(
+ r'\s*(?P.*?)\s*(\(\s*(?P[a-z-, ]+)\s*\)\s*|)\Z', e, re.I)
+ if not m1:
+ outmess(
+ 'analyzeline: could not extract info of implicit statement part "%s"\n' % (e))
+ continue
+ m2 = typespattern4implicit.match(m1.group('this'))
+ if not m2:
+ outmess(
+ 'analyzeline: could not extract types pattern of implicit statement part "%s"\n' % (e))
+ continue
+ typespec, selector, attr, edecl = cracktypespec0(
+ m2.group('this'), m2.group('after'))
+ kindselect, charselect, typename = cracktypespec(
+ typespec, selector)
+ decl['typespec'] = typespec
+ decl['kindselector'] = kindselect
+ decl['charselector'] = charselect
+ decl['typename'] = typename
+ for k in list(decl.keys()):
+ if not decl[k]:
+ del decl[k]
+ for r in markoutercomma(m1.group('after')).split('@,@'):
+ if '-' in r:
+ try:
+ begc, endc = [x.strip() for x in r.split('-')]
+ except Exception:
+ outmess(
+ 'analyzeline: expected "-" instead of "%s" in range list of implicit statement\n' % r)
+ continue
+ else:
+ begc = endc = r.strip()
+ if not len(begc) == len(endc) == 1:
+ outmess(
+ 'analyzeline: expected "-" instead of "%s" in range list of implicit statement (2)\n' % r)
+ continue
+ for o in range(ord(begc), ord(endc) + 1):
+ impl[chr(o)] = decl
+ groupcache[groupcounter]['implicit'] = impl
+ elif case == 'data':
+ ll = []
+ dl = ''
+ il = ''
+ f = 0
+ fc = 1
+ inp = 0
+ for c in m.group('after'):
+ if not inp:
+ if c == "'":
+ fc = not fc
+ if c == '/' and fc:
+ f = f + 1
+ continue
+ if c == '(':
+ inp = inp + 1
+ elif c == ')':
+ inp = inp - 1
+ if f == 0:
+ dl = dl + c
+ elif f == 1:
+ il = il + c
+ elif f == 2:
+ dl = dl.strip()
+ if dl.startswith(','):
+ dl = dl[1:].strip()
+ ll.append([dl, il])
+ dl = c
+ il = ''
+ f = 0
+ if f == 2:
+ dl = dl.strip()
+ if dl.startswith(','):
+ dl = dl[1:].strip()
+ ll.append([dl, il])
+ vars = groupcache[groupcounter].get('vars', {})
+ last_name = None
+ for l in ll:
+ l[0], l[1] = l[0].strip(), l[1].strip()
+ if l[0].startswith(','):
+ l[0] = l[0][1:]
+ if l[0].startswith('('):
+ outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n' % l[0])
+ continue
+ for idx, v in enumerate(rmbadname([x.strip() for x in markoutercomma(l[0]).split('@,@')])):
+ if v.startswith('('):
+ outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n' % v)
+ # XXX: subsequent init expressions may get wrong values.
+ # Ignoring since data statements are irrelevant for
+ # wrapping.
+ continue
+ if '!' in l[1]:
+ # Fixes gh-24746 pyf generation
+ # XXX: This essentially ignores the value for generating the pyf which is fine:
+ # integer dimension(3) :: mytab
+ # common /mycom/ mytab
+ # Since in any case it is initialized in the Fortran code
+ outmess('Comment line in declaration "%s" is not supported. Skipping.\n' % l[1])
+ continue
+ vars.setdefault(v, {})
+ vtype = vars[v].get('typespec')
+ vdim = getdimension(vars[v])
+ matches = re.findall(r"\(.*?\)", l[1]) if vtype == 'complex' else l[1].split(',')
+ try:
+ new_val = "(/{}/)".format(", ".join(matches)) if vdim else matches[idx]
+ except IndexError:
+ # gh-24746
+ # Runs only if above code fails. Fixes the line
+ # DATA IVAR1, IVAR2, IVAR3, IVAR4, EVAR5 /4*0,0.0D0/
+ # by expanding to ['0', '0', '0', '0', '0.0d0']
+ if any("*" in m for m in matches):
+ expanded_list = []
+ for match in matches:
+ if "*" in match:
+ try:
+ multiplier, value = match.split("*")
+ expanded_list.extend([value.strip()] * int(multiplier))
+ except ValueError: # if int(multiplier) fails
+ expanded_list.append(match.strip())
+ else:
+ expanded_list.append(match.strip())
+ matches = expanded_list
+ new_val = "(/{}/)".format(", ".join(matches)) if vdim else matches[idx]
+ current_val = vars[v].get('=')
+ if current_val and (current_val != new_val):
+ outmess('analyzeline: changing init expression of "%s" ("%s") to "%s"\n' % (v, current_val, new_val))
+ vars[v]['='] = new_val
+ last_name = v
+ groupcache[groupcounter]['vars'] = vars
+ if last_name:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case == 'common':
+ line = m.group('after').strip()
+ if not line[0] == '/':
+ line = '//' + line
+ cl = []
+ f = 0
+ bn = ''
+ ol = ''
+ for c in line:
+ if c == '/':
+ f = f + 1
+ continue
+ if f >= 3:
+ bn = bn.strip()
+ if not bn:
+ bn = '_BLNK_'
+ cl.append([bn, ol])
+ f = f - 2
+ bn = ''
+ ol = ''
+ if f % 2:
+ bn = bn + c
+ else:
+ ol = ol + c
+ bn = bn.strip()
+ if not bn:
+ bn = '_BLNK_'
+ cl.append([bn, ol])
+ commonkey = {}
+ if 'common' in groupcache[groupcounter]:
+ commonkey = groupcache[groupcounter]['common']
+ for c in cl:
+ if c[0] not in commonkey:
+ commonkey[c[0]] = []
+ for i in [x.strip() for x in markoutercomma(c[1]).split('@,@')]:
+ if i:
+ commonkey[c[0]].append(i)
+ groupcache[groupcounter]['common'] = commonkey
+ previous_context = ('common', bn, groupcounter)
+ elif case == 'use':
+ m1 = re.match(
+ r'\A\s*(?P\b\w+\b)\s*((,(\s*\bonly\b\s*:|(?P))\s*(?P.*))|)\s*\Z', m.group('after'), re.I)
+ if m1:
+ mm = m1.groupdict()
+ if 'use' not in groupcache[groupcounter]:
+ groupcache[groupcounter]['use'] = {}
+ name = m1.group('name')
+ groupcache[groupcounter]['use'][name] = {}
+ isonly = 0
+ if 'list' in mm and mm['list'] is not None:
+ if 'notonly' in mm and mm['notonly'] is None:
+ isonly = 1
+ groupcache[groupcounter]['use'][name]['only'] = isonly
+ ll = [x.strip() for x in mm['list'].split(',')]
+ rl = {}
+ for l in ll:
+ if '=' in l:
+ m2 = re.match(
+ r'\A\s*(?P\b\w+\b)\s*=\s*>\s*(?P