├── .gitignore ├── INSTALL.txt ├── LICENSE.txt ├── MANIFEST.in ├── README.txt ├── USAGE.txt ├── bin └── fwrapc ├── doc ├── NOTES.txt ├── TODO-ARRAYS.txt ├── TODO.txt └── sphinxdocs │ ├── Makefile │ ├── NOTES.txt │ ├── make.bat │ ├── source │ ├── _static │ │ ├── default.css │ │ ├── fwrap_logo.png │ │ ├── fwrap_logo_big.png │ │ └── fwrap_logo_med.png │ ├── _templates │ │ ├── indexsidebar.html │ │ ├── layout.html │ │ └── mplexample.html │ ├── conf.py │ └── index.rst │ └── upload.sh ├── examples ├── Makefile ├── arrays │ └── source.f90 ├── functions │ └── source.f90 ├── intents │ └── source.f90 ├── kinds │ └── source.f90 └── scalars │ └── source.f90 ├── fwrap ├── __init__.py ├── code.py ├── constants.py ├── cy_wrap.py ├── default.config ├── fc_wrap.py ├── fort_expr.py ├── fwrap_parse.py ├── fwrap_wscript ├── fwrapc.py ├── fwrapper.py ├── gen_config.py ├── intrinsics.py ├── log.config ├── pyf_iface.py ├── pyparsing_py2.py ├── tests │ ├── __init__.py │ ├── test_code.py │ ├── test_cy_wrap.py │ ├── test_dimension.py │ ├── test_fc_wrap.py │ ├── test_fort_expr.py │ ├── test_fwrap_parse.py │ ├── test_fwrapper.py │ ├── test_gen_config.py │ ├── test_parameters.py │ ├── test_pyf_iface.py │ └── tutils.py ├── version.py └── visitor.py ├── fwrapc.py ├── fwrapper.py ├── runnose.py ├── runtests.py ├── setup.py └── tests ├── bugs.txt ├── compile ├── all_char.f90 ├── char_args.f90 ├── cmplx_array.f90 ├── default_types.f90 ├── int_args.f90 ├── intargs_stuff │ ├── drive_int_args.c │ └── wrap_int_args.f95 ├── many_args.f90 ├── old_decl.f90 ├── py_kw_arg.f90 └── simple_array.f90 ├── run ├── all_char.f90 ├── all_char_arrays.f90 ├── all_char_arrays_fwrap_doctest.py ├── all_char_fwrap_doctest.py ├── all_complex.f90 ├── all_complex_arrays.f90 ├── all_complex_arrays_fwrap_doctest.py ├── all_complex_fwrap_doctest.py ├── all_integer_arrays.f90 ├── all_integer_arrays_fwrap_doctest.py ├── all_ints.f90 ├── all_ints_fwrap_doctest.py ├── all_logical_arrays.f90 ├── all_logical_arrays_fwrap_doctest.py ├── all_logicals.f90 ├── all_logicals_fwrap_doctest.py ├── all_real_arrays.f90 ├── all_real_arrays_fwrap_doctest.py ├── all_reals.f90 ├── all_reals_fwrap_doctest.py ├── array_intents.f90 ├── array_intents_fwrap_doctest.py ├── array_types.f90 ├── array_types_fwrap_doctest.py ├── char_array.f90 ├── char_array_fwrap_doctest.py ├── default_types.f90 ├── default_types_fwrap_doctest.py ├── dim_expr.f90 ├── dim_expr_fwrap_doctest.py ├── func_returns.f90 ├── func_returns_fwrap_doctest.py ├── int_args.f90 ├── int_args_fwrap_doctest.py ├── ndims.f90 ├── ndims_fwrap_doctest.py ├── old_decl.f90 └── old_decl_fwrap_doctest.py └── todo ├── arr_mem_layout.f90 ├── arr_mem_layout_fwrap_doctest.py ├── func_return_arr.f90 ├── func_return_arr_fwrap_doctest.py ├── kind_params.f90 ├── kind_params_fwrap_doctest.py ├── othermod.f95 ├── test_scope.f95 ├── use_mod.f90 ├── use_module.f95 └── use_module_fwrap_doctest.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | BUILD/* 3 | fwrap/fparser 4 | fwrap.log 5 | fwrap/waf 6 | -------------------------------------------------------------------------------- /INSTALL.txt: -------------------------------------------------------------------------------- 1 | Fwrap - Installation Instructions 2 | ================================= 3 | 4 | You first need to install fparser, then you can install fwrap. 5 | 6 | Install fparser 7 | --------------- 8 | 9 | From the fwrap root git repository:: 10 | 11 | hg clone http://f2py.googlecode.com/hg/ f2py 12 | ln -s ../f2py/fparser fwrap/fparser 13 | 14 | Install fwrap 15 | ------------- 16 | 17 | You have two installation options: 18 | 19 | 1. Run the setup.py script in this directory as follows: 20 | 21 | $ python setup.py install 22 | 23 | This will install the Fwrap package into your Python system. 24 | 25 | OR 26 | 27 | 2. If you prefer not to modify your Python installation, arrange for the 28 | directory containing this file (INSTALL.txt) to be in your PYTHONPATH. On 29 | unix, also put the bin directory on your PATH. 30 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Fwrap 2 | ===== 3 | 4 | Copyright (c) 2010, Kurt W. Smith 5 | 6 | All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | * Neither the name of the Fwrap project nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | ============================================================================= 32 | 33 | Fparser 34 | ======= 35 | 36 | Copyright (c) 1999-2008 Pearu Peterson 37 | 38 | All rights reserved. 39 | 40 | Redistribution and use in source and binary forms, with or without 41 | modification, are permitted provided that the following conditions are met: 42 | 43 | a. Redistributions of source code must retain the above copyright notice, 44 | this list of conditions and the following disclaimer. 45 | b. Redistributions in binary form must reproduce the above copyright notice, 46 | this list of conditions and the following disclaimer in the documentation 47 | and/or other materials provided with the distribution. 48 | c. Neither the name of the F2PY project nor the names of its contributors may 49 | be used to endorse or promote products derived from this software without 50 | specific prior written permission. 51 | 52 | 53 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 54 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 55 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 56 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 57 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 58 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 59 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 60 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 61 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 62 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63 | 64 | ============================================================================= 65 | 66 | Pyparsing 67 | ========= 68 | 69 | Permission is hereby granted, free of charge, to any person obtaining a copy of 70 | this software and associated documentation files (the "Software"), to deal in 71 | the Software without restriction, including without limitation the rights to 72 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 73 | of the Software, and to permit persons to whom the Software is furnished to do 74 | so, subject to the following conditions: 75 | 76 | The above copyright notice and this permission notice shall be included in all 77 | copies or substantial portions of the Software. 78 | 79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 80 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 81 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 82 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 83 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 84 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 85 | SOFTWARE. 86 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include fwrap/*.config 2 | include fwrap/fparser/*.config 3 | recursive-include fwrap/tests *.py 4 | 5 | include runnose.py runtests.py fwrapc.py *.txt MANIFEST.in 6 | 7 | recursive-include tests *.f90 *.py *.txt 8 | recursive-include examples Makefile *.f90 9 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ================================================== 2 | Fwrap: Wrap Fortran 77/90/95 in C, Cython & Python 3 | ================================================== 4 | 5 | Fwrap is a utility that takes Fortran 77/90/95 source code and 6 | provides cross-platform & cross-compiler wrappers in C, Cython & 7 | Python. 8 | 9 | It wraps the basic functionality you'd expect (functions, 10 | subroutines, scalar and array arguments for intrinsic types) and will 11 | eventually support all features of Fortran 90/95 (derived types, 12 | C/Cython/Python callbacks, wrap modules in Python classes). 13 | 14 | It is currently under heavy construction and is to be considered beta 15 | software until otherwise indicated. All commandline options, APIs 16 | etc. are subject to change. 17 | 18 | 19 | Requirements 20 | ------------ 21 | 22 | Note: these requirements will loosen as more components are tested; 23 | if you would like an earlier version of these requirements tested 24 | please email the developers. 25 | 26 | Fwrap has been sucessfully tested with: 27 | 28 | * Python 2.5 and 2.6 (2.4 likely coming soon, Py3 support is 29 | planned) 30 | 31 | * Cython >= 0.11.1 32 | 33 | * NumPy >= 1.3.0 34 | 35 | * Nose (fairly recent version) for running unittests. The 36 | *integration* tests (see below) do not require nose. 37 | 38 | * A sufficiently modern Fortran 90 compiler. 39 | 40 | Fwrap has been tested on three fortran compilers to date (see below), 41 | but could benefit from more testing on other compilers/other 42 | versions. If you have another version or a different compiler and 43 | use fwrap, please let the devs know. 44 | 45 | Tested Fortran 90 compilers: 46 | 47 | * gfortran >= 4.4.1 (see note) 48 | 49 | * g95 >= 0.92 50 | 51 | * ifort >= 11.1 52 | 53 | Note on gfortran: The gfortran series 4.3.x >= 4.3.3 (widely 54 | distributed with many OSes) has a C binding bug that renders the 55 | compiler unusable for N-D arrays of type logical or character, where 56 | N >= 3. If you can avoid logical and character arrays more than 2 57 | dimensions, then there's no problem. (Gfortran works in 4.4.1 and 58 | later.) 59 | 60 | 61 | Running the Integration Tests 62 | ----------------------------- 63 | 64 | Fwrap has a pretty good testsuite. Getting it running will indicate 65 | if everything is working on your system and is highly recommended 66 | while Fwrap is in beta stage. 67 | 68 | For a failsafe setup, it is necessary to set environment flags to 69 | tell Fwrap where to find your system's fortran runtime libraries and 70 | executable. For a bash shell, do the following: 71 | 72 | $ export F90=/path/to/fortran/executable 73 | 74 | $ export LDFLAGS='-L/path/to/fortran/runtime/lib -l' 75 | 76 | For gfortran: 77 | 78 | $ export F90=/usr/local/bin/gfortran 79 | 80 | $ export LDFLAGS='-L/usr/local/lib -lgfortran' 81 | 82 | Then you can run the tests from the directory containing this 83 | README.txt file: 84 | 85 | $ python runtests.py -vv --fcompiler=gnu95 --no-cleanup 86 | 87 | All the build products will be placed in a directory 'BUILD' which 88 | can be safely removed. 89 | 90 | If you have success or failure, we'd love to know. 91 | 92 | 93 | More Information & Resources 94 | ---------------------------- 95 | 96 | See USAGE.txt for basic commandline use. 97 | 98 | See the examples directory for some samples to get started. 99 | 100 | Project homepage: 101 | 102 | http://fwrap.sourceforge.net/ 103 | 104 | Fwrap-users mailing list, for all questions & support: 105 | 106 | http://groups.google.com/group/fwrap-users 107 | 108 | For fwrap news: 109 | 110 | http://fortrancython.wordpress.com/ 111 | 112 | .. vim:tw=69 ft=rst 113 | -------------------------------------------------------------------------------- /USAGE.txt: -------------------------------------------------------------------------------- 1 | Using Fwrap 2 | =========== 3 | 4 | 1. Ensure you have all the requirements installed (see README.txt). 5 | 6 | 2. Ensure that the tests pass (see README.txt). 7 | 8 | 3. Install fwrap or set up your PYTHONPATH accordingly (see 9 | INSTALL.txt). 10 | 11 | Suppose you have a fortran source file `source.f90` and you would 12 | like to generate wrappers for every procedure in it along with an 13 | extension module. 14 | 15 | You can check and see what fortran compilers fwrap can find: 16 | 17 | $ fwrapc --help-fcompiler 18 | 19 | If it can't find your compiler, you'll need to give it some help: 20 | 21 | $ fwrapc --help-fcompiler --fcompiler= \ 22 | --f90exec=/path/to/executable 23 | 24 | If it still cannot find your compiler, please email the user's list 25 | for assistance. 26 | 27 | Assuming it can find your compiler, you would generate wrappers and 28 | an extension module with this command: 29 | 30 | $ fwrapc source.f90 --build \ 31 | --name=test_fw --fcompiler=gnu95 \ 32 | --f90exec=/path/to/executable \ 33 | -L/path/to/runtime/libs -l 34 | 35 | This will create a directory ./test_fw and place the wrapper files 36 | there, along with an extension module `test_fw.so` (the file 37 | extension is platform dependent). 38 | 39 | From within Python: 40 | 41 | >>> import test_fw 42 | >>> help(test_fw) 43 | >>> # ... 44 | >>> # for subroutine bessel inside test_fw 45 | >>> help(test_fw.bessel) 46 | >>> # ... 47 | 48 | The generated docstrings are viewable with the 'help' builtin 49 | function and should suffice for using the extension module from 50 | Python. 51 | -------------------------------------------------------------------------------- /bin/fwrapc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | #------------------------------------------------------------------------------ 4 | # Copyright (c) 2010, Kurt W. Smith 5 | # 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, 12 | # this list of conditions and the following disclaimer. 13 | # * Redistributions in binary form must reproduce the above copyright 14 | # notice, this list of conditions and the following disclaimer in the 15 | # documentation and/or other materials provided with the distribution. 16 | # * Neither the name of the Fwrap project nor the names of its contributors 17 | # may be used to endorse or promote products derived from this software 18 | # without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | # POSSIBILITY OF SUCH DAMAGE. 31 | #------------------------------------------------------------------------------ 32 | 33 | 34 | import sys 35 | from fwrap.main import main 36 | 37 | sys.exit(main(use_cmdline=True)) 38 | -------------------------------------------------------------------------------- /doc/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | In this file you will find the working documentation for fwrap, a fortran wrapping tool. 4 | 5 | == Fortran and Python namespaces, and implications for fwrap == 6 | 7 | Fwrap requires that all argument kind-type-parameters (the "DP" parameter in 8 | the declaration "real(DP) :: arr") be single-valued for the entire project. 9 | This allows fwrap to make a single C header file with all the project's 10 | kind-type-parameters defined. Redefinitions of argument kind-type-parameters 11 | won't work. 12 | 13 | Fortran does not impose this restriction; it is entirely possible to have 14 | multiple "DP" parameters defined differently in different modules, and use them 15 | as ktps for arguments to your Fortran procedures. To accomodate one-to-many 16 | parameter names (one name, many values), fwrap would have to complicate its 17 | type-resolution algorithm, with complications extending down to every level of 18 | wrappers. 19 | 20 | In the author's experience of Fortran projects kind-type-parameters are global 21 | to a project -- almost always defined in one simple type module and made 22 | available via `use' statements. It is difficult to imagine a scenario where 23 | redefining ktps would be a benefit. 24 | -------------------------------------------------------------------------------- /doc/TODO-ARRAYS.txt: -------------------------------------------------------------------------------- 1 | For every numeric type & logical: 2 | 3 | n1, n2 integer arguments 4 | dimension(n1, n2) 5 | intent(in) 6 | intent(inout) 7 | intent(out) 8 | 9 | 10 | Pass in arrays with correct shape (n1, n2) 11 | 12 | Pass in arrays with wrong shape -- should raise AttributeError exception. 13 | 14 | dimension(n1, *) 15 | intent(in) 16 | intent(inout) 17 | intent(out) 18 | 19 | 20 | Check correct shape & raise exception with wrong shape. 21 | 22 | dimension(:,:) 23 | intent(in) 24 | intent(inout) 25 | intent(out) 26 | 27 | 28 | There is no wrong shape in this case. 29 | 30 | For character arrays: 31 | 32 | character(len=3), dimension(:,:) 33 | intent(in) 34 | intent(inout) 35 | intent(out) 36 | 37 | 38 | Raise exception if 'itemsize' of dtype object != 3 (len of character dtype) 39 | 40 | character(len=3), dimension(n1, n2) 41 | intent(in) 42 | intent(inout) 43 | intent(out) 44 | 45 | 46 | Raise exception if 'itemsize' of dtype object != 3 (len of character dtype) 47 | Raise exception if shape does not match. 48 | 49 | character(len=*), dimension(:,:) 50 | intent(in) 51 | intent(inout) 52 | intent(out) 53 | 54 | 55 | No shape / itemsize related exceptions should result. 56 | -------------------------------------------------------------------------------- /doc/TODO.txt: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | intent(out) scalar variables can't be passed through the argument list at Cython level. 4 | 5 | Need to be returned in return tuple. 6 | 7 | What about intent(out) arrays? Best solution -- do like 'out' variable for numpy ufuncs. 8 | 9 | def sum(a, b, out=None): 10 | cdef np.ndarray[, ndim=, mode='fortran'] out_ 11 | if out is None: 12 | out_ = np.empty(, ) 13 | else: 14 | out_ = out 15 | inner_sum(a, b, out_) 16 | return (out_,) 17 | 18 | for scalar intent(out) arguments: 19 | 20 | cpdef api ffunc(fwrap_default_int in_var): 21 | cdef fwrap_default_real out_var 22 | cdef fwrap_default_real ret_val 23 | ret_val = ffunc_c(&in_var, &out_var) 24 | return (ret_val, out_var) 25 | 26 | --- 27 | 28 | Detect when a ktp/argument/variable/parameter is given with an 'fwrap_' prefix 29 | and either raise an error or emit a warning. 30 | 31 | --- 32 | 33 | One ktp module per project. 34 | 35 | All ktps for entire project collected here, generated at compile time. 36 | 37 | Requires ktps to be in project global namespace -- only a single definition per 38 | ktp is allowed. 39 | 40 | User must be made aware of this. 41 | 42 | function foo(a, b, b1, c, d, e, f, g) 43 | implicit none 44 | integer, parameter :: a_ktp = selected_int_kind(10) 45 | integer, parameter :: d_ktp = kind(.true.) 46 | integer, parameter :: e_ktp = kind(0.0D0) 47 | integer(a_ktp) :: a 48 | integer*4 :: b 49 | integer(4) :: b1 50 | integer :: c 51 | logical(d_ktp) :: d 52 | real(e_ktp) :: e 53 | real*8 :: f 54 | double precision :: g 55 | end function foo 56 | 57 | subroutine bar(e) 58 | implicit none 59 | integer, parameter :: e_ktp = kind(0.0D0) 60 | real(e_ktp) :: e ! This is allowed since e_ktp has same value OR raise an error, even though redeclared the same??? 61 | end subroutine bar 62 | 63 | The respective names for the ktps: 64 | 65 | fwrap_a_ktp 66 | fwrap_integer_x4 67 | fwrap_integer_4 68 | fwrap_default_integer 69 | fwrap_default_logical 70 | fwrap_e_ktp 71 | fwrap_real_x8 72 | fwrap_double_precision 73 | 74 | Summarized in a dictionary (??): 75 | 76 | { 77 | 'fwrap_a_ktp' : ('integer', 'selected_int_kind(10)'), 78 | 'fwrap_integer_x4' : ('integer', '*4'), # ?? 79 | 'fwrap_integer_4' : ('integer', '4'), 80 | 'fwrap_default_integer' : ('integer', ''), 81 | 'fwrap_default_logical' : ('logical', ''), 82 | 'fwrap_e_ktp' : ('real', 'kind(0.0D0)'), 83 | 'fwrap_real_x8' : ('real', '*8'), 84 | 'fwrap_double_precision' : ('double precision', '') 85 | } 86 | 87 | The compilation phase is responsible for generating the config module: 88 | 89 | module fwrap_ktp_mod 90 | use iso_c_binding 91 | implicit none 92 | integer, parameter :: fwrap_a_ktp = ... 93 | integer, parameter :: fwrap_integer_4 = ... 94 | integer, parameter :: fwrap_default_integer = ... 95 | integer, parameter :: fwrap_default_logical = ... 96 | integer, parameter :: fwrap_e_ktp = ... 97 | integer, parameter :: fwrap_real_8 = ... 98 | integer, parameter :: fwrap_double_precision = ... 99 | end module fwrap_ktp_mod 100 | 101 | --- 102 | 103 | Name collisions when mangling -- 104 | When mangling 'empty_func' to 'empty_func_c', need to ensure there aren't 105 | any pre-existent 'empty_func_c's lying around. 106 | 107 | However, Fortran will mangle procedure names itself (trailing underscores, 108 | etc.). As long as our name-mangling convention doesn't overlap a Fortran 109 | compiler's name-mangling, we'll be okay. 110 | 111 | --- 112 | 113 | when array extents are passed explicitly like this: 114 | 115 | subroutine s(arr, d) 116 | integer, dimension(d) :: arr 117 | integer :: d 118 | ... 119 | end subroutine s 120 | 121 | And the user specifies (somehow?) that `d' is to be hidden in the C prototype, 122 | the wrapped subroutine should look something like: 123 | 124 | subroutine s_c(arr_d1, arr) bind(c, 's_c') 125 | integer(fwrap_default_int), intent(in) :: arr_d1 126 | integer(fwrap_default_int), dimension(arr_d1) :: arr 127 | interface 128 | ... 129 | end interface 130 | call s(arr, arr_d1) 131 | end subroutine s_c 132 | 133 | Perhaps the argument specification can take another parameter, 134 | 'optional=' where expr is something like 'shape(arr, 1)'. 135 | 136 | --- 137 | 138 | Name collisions: 139 | 140 | Test temporary variables. 141 | Test array extents. 142 | Test for any name that's injected in the procedure's namespace. 143 | 144 | --- 145 | 146 | A procedure-local parameter that is used as a ktp or in an array extent 147 | expression: 148 | 149 | ... 150 | integer, parameter :: FOO=kind(1.0)+1, DIM=12-3 151 | real(FOO), dimension(DIM), intent(inout) :: arg 152 | ... 153 | 154 | The config module will have a section that looks like: 155 | 156 | ... 157 | integer, parameter :: _FOO = 158 | integer, parameter :: _DIM = 12-3 159 | ... 160 | 161 | The interface will look like: 162 | 163 | ... 164 | use config !!! only clause here? 165 | real(_FOO), dimension(_DIM), intent(inout) :: arg 166 | ... 167 | 168 | The wrapper will have: 169 | 170 | use config 171 | integer(_default_int), intent(in) :: arg_d1 172 | real(_FOO), dimension(arg_d1), intent(inout) :: arg 173 | 174 | Further down the wrapper (can, optionally?, or should?) generate a dimension check: 175 | 176 | assert arg_d1 .eq. _DIM 177 | 178 | If this is false, an error code needs to be returned. 179 | 180 | (How do we do that? It'll change the procedure's signature and adds an error argument...) 181 | 182 | --- 183 | 184 | Config module generation: 185 | 186 | One problem is that we'll have one big namespace for all parameters -- possible collisions. 187 | 188 | Solution (1) a separate config module per external subprogram; can put all of these in one file. 189 | -- possible speed hit; more complicated... 190 | 191 | Solution (2) one module with procedure-specific name mangling. 192 | -- if use procedure name to mangle, very long parameter names. 193 | 194 | 195 | Config module(s) options: 196 | 197 | (1) Gather together all 'base' expressions used as kind type parameters. 198 | 199 | --- 200 | 201 | intent('hide') arguments, ala f2py: 202 | 203 | Argument('arg', intent='hide', value='shape(a, 0)') 204 | 205 | value is a fortran expression that will be assigned to the argument and used in the call. 206 | 207 | NB: this changes the intent of the argument! We're assigning to it so it has 208 | to be declared as intent('inout') or something. 209 | 210 | DONE 3.9.2010 211 | 212 | --- 213 | 214 | Hide argument can only be a scalar -- no dimension allowed. 215 | 216 | --- 217 | 218 | 'check' attribute (ala f2py): 219 | 220 | For complicated array extents, we need to allow runtime checking. E.g: 221 | 222 | function f(iarr, ck, nk) 223 | integer, intent(in) :: ck, nk 224 | integer, dimension((ck-nk+1)*(ck-nk+1)) :: iarr 225 | !... 226 | end function f 227 | 228 | Declared with: 229 | 230 | Argument('iarr', default_int, dimension=['(ck-nk+1)*(ck-nk+1)']) 231 | Argument('ck', default_int, check='shape(iarr, 1) == (ck-nk+1)*(ck-nk+1)') 232 | (can have an 'assertion' argument to procedures, eqiv. to checks?) 233 | 234 | Generates the code: 235 | 236 | function f_c(iarr_d1, iarr, ck, nk, fw_err) bind(...) 237 | use config 238 | implicit none 239 | integer, intent(in) :: iarr_d1 240 | integer, dimension(iarr_d1) :: iarr 241 | integer, intent(in) :: ck 242 | integer, intent(in) :: nk 243 | integer, intent(out) :: fw_err (or appropriate name...) 244 | integer :: f_c 245 | fw_err = 0 246 | if ( .not. (shape(iarr, 1) == (ck-nk+1)*(ck-nk+1))) then 247 | fw_err = 1 248 | return 249 | endif 250 | 251 | 252 | --- 253 | 254 | Parameters (defined in the procedure) & literal constants. 255 | This is a biggie... 256 | 257 | --- 258 | 259 | Use statements & symbol resolution. 260 | After procedure parameters & constants. 261 | 262 | --- 263 | 264 | Derived types 265 | Later version 266 | 267 | --- 268 | 269 | Config module / header generation. 270 | 271 | --- 272 | gfortran does not allow a bind(c) procedure to have a non-bind(c) derived type 273 | argument. To wrap a procedure with a derived-type that is non-bind(c) requires 274 | a copy-in/copy-out. If the type is bind(c) then no copy is necessary. 275 | 276 | This is probably good for safety, and ensures alignment & padding issues won't 277 | bite us later. Since compilers can do crazy things in optimizations of structs 278 | (reordering? padding?), this could be the source of nasty bugs. 279 | 280 | If the end user wants fast derived-type interoperability, he'll have to declare 281 | derived-types with bind(c). 282 | 283 | --- 284 | 285 | gfortran does not allow this in a bind(c) procedure: 286 | 287 | integer, parameter :: fwrap_default_logical=c_int 288 | logical(fwrap_default_logical), intent(in) :: l 289 | 290 | Rather, gfortran requires: 291 | 292 | integer, parameter :: fwrap_default_logical=kind(.true.) 293 | logical(fwrap_default_logical), intent(in) :: l 294 | 295 | which will yield a warning. 296 | 297 | This will not yield a warning, but will require copying: 298 | 299 | integer, parameter :: fwrap_default_logical=c_bool 300 | logical(fwrap_default_logical), intent(in) :: l 301 | 302 | Perhaps have a `strict' mode with the understanding that there will be a 303 | performance hit. 304 | 305 | --- 306 | 307 | -------------------------------------------------------------------------------- /doc/sphinxdocs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = ./sphinx-build 7 | PAPER = 8 | 9 | # Internal variables. 10 | PAPEROPT_a4 = -D latex_paper_size=a4 11 | PAPEROPT_letter = -D latex_paper_size=letter 12 | ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 13 | 14 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 15 | 16 | help: 17 | @echo "Please use \`make ' where is one of" 18 | @echo " html to make standalone HTML files" 19 | @echo " dirhtml to make HTML files named index.html in directories" 20 | @echo " pickle to make pickle files" 21 | @echo " json to make JSON files" 22 | @echo " htmlhelp to make HTML files and a HTML help project" 23 | @echo " qthelp to make HTML files and a qthelp project" 24 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 25 | @echo " changes to make an overview of all changed/added/deprecated items" 26 | @echo " linkcheck to check all external links for integrity" 27 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 28 | 29 | clean: 30 | -rm -rf build/* 31 | 32 | html: 33 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html 34 | @echo 35 | @echo "Build finished. The HTML pages are in build/html." 36 | 37 | dirhtml: 38 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) build/dirhtml 39 | @echo 40 | @echo "Build finished. The HTML pages are in build/dirhtml." 41 | 42 | pickle: 43 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle 44 | @echo 45 | @echo "Build finished; now you can process the pickle files." 46 | 47 | json: 48 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) build/json 49 | @echo 50 | @echo "Build finished; now you can process the JSON files." 51 | 52 | htmlhelp: 53 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp 54 | @echo 55 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 56 | ".hhp project file in build/htmlhelp." 57 | 58 | qthelp: 59 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) build/qthelp 60 | @echo 61 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 62 | ".qhcp project file in build/qthelp, like this:" 63 | @echo "# qcollectiongenerator build/qthelp/fwrap.qhcp" 64 | @echo "To view the help file:" 65 | @echo "# assistant -collectionFile build/qthelp/fwrap.qhc" 66 | 67 | latex: 68 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex 69 | @echo 70 | @echo "Build finished; the LaTeX files are in build/latex." 71 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 72 | "run these through (pdf)latex." 73 | 74 | changes: 75 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes 76 | @echo 77 | @echo "The overview file is in build/changes." 78 | 79 | linkcheck: 80 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck 81 | @echo 82 | @echo "Link check complete; look for any errors in the above output " \ 83 | "or in build/linkcheck/output.txt." 84 | 85 | doctest: 86 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) build/doctest 87 | @echo "Testing of doctests in the sources finished, look at the " \ 88 | "results in build/doctest/output.txt." 89 | -------------------------------------------------------------------------------- /doc/sphinxdocs/NOTES.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | to administer via ssh: 4 | 5 | $ ssh -t kwmsmith,fwrap@shell.sourceforge.net create 6 | -------------------------------------------------------------------------------- /doc/sphinxdocs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | set SPHINXBUILD=sphinx-build 6 | set ALLSPHINXOPTS=-d build/doctrees %SPHINXOPTS% source 7 | if NOT "%PAPER%" == "" ( 8 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 9 | ) 10 | 11 | if "%1" == "" goto help 12 | 13 | if "%1" == "help" ( 14 | :help 15 | echo.Please use `make ^` where ^ is one of 16 | echo. html to make standalone HTML files 17 | echo. dirhtml to make HTML files named index.html in directories 18 | echo. pickle to make pickle files 19 | echo. json to make JSON files 20 | echo. htmlhelp to make HTML files and a HTML help project 21 | echo. qthelp to make HTML files and a qthelp project 22 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 23 | echo. changes to make an overview over all changed/added/deprecated items 24 | echo. linkcheck to check all external links for integrity 25 | echo. doctest to run all doctests embedded in the documentation if enabled 26 | goto end 27 | ) 28 | 29 | if "%1" == "clean" ( 30 | for /d %%i in (build\*) do rmdir /q /s %%i 31 | del /q /s build\* 32 | goto end 33 | ) 34 | 35 | if "%1" == "html" ( 36 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% build/html 37 | echo. 38 | echo.Build finished. The HTML pages are in build/html. 39 | goto end 40 | ) 41 | 42 | if "%1" == "dirhtml" ( 43 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% build/dirhtml 44 | echo. 45 | echo.Build finished. The HTML pages are in build/dirhtml. 46 | goto end 47 | ) 48 | 49 | if "%1" == "pickle" ( 50 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% build/pickle 51 | echo. 52 | echo.Build finished; now you can process the pickle files. 53 | goto end 54 | ) 55 | 56 | if "%1" == "json" ( 57 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% build/json 58 | echo. 59 | echo.Build finished; now you can process the JSON files. 60 | goto end 61 | ) 62 | 63 | if "%1" == "htmlhelp" ( 64 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% build/htmlhelp 65 | echo. 66 | echo.Build finished; now you can run HTML Help Workshop with the ^ 67 | .hhp project file in build/htmlhelp. 68 | goto end 69 | ) 70 | 71 | if "%1" == "qthelp" ( 72 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% build/qthelp 73 | echo. 74 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 75 | .qhcp project file in build/qthelp, like this: 76 | echo.^> qcollectiongenerator build\qthelp\fwrap.qhcp 77 | echo.To view the help file: 78 | echo.^> assistant -collectionFile build\qthelp\fwrap.ghc 79 | goto end 80 | ) 81 | 82 | if "%1" == "latex" ( 83 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% build/latex 84 | echo. 85 | echo.Build finished; the LaTeX files are in build/latex. 86 | goto end 87 | ) 88 | 89 | if "%1" == "changes" ( 90 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% build/changes 91 | echo. 92 | echo.The overview file is in build/changes. 93 | goto end 94 | ) 95 | 96 | if "%1" == "linkcheck" ( 97 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% build/linkcheck 98 | echo. 99 | echo.Link check complete; look for any errors in the above output ^ 100 | or in build/linkcheck/output.txt. 101 | goto end 102 | ) 103 | 104 | if "%1" == "doctest" ( 105 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% build/doctest 106 | echo. 107 | echo.Testing of doctests in the sources finished, look at the ^ 108 | results in build/doctest/output.txt. 109 | goto end 110 | ) 111 | 112 | :end 113 | -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_static/default.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Alternate Sphinx design 3 | * Originally created by Armin Ronacher for Werkzeug, adapted by Georg Brandl. 4 | */ 5 | 6 | body { 7 | font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif; 8 | font-size: 14px; 9 | letter-spacing: -0.01em; 10 | line-height: 150%; 11 | text-align: center; 12 | /*background-color: #AFC1C4; */ 13 | background-color: #BFD1D4; 14 | color: black; 15 | padding: 0; 16 | border: 1px solid #aaa; 17 | 18 | margin: 0px 80px 0px 80px; 19 | min-width: 740px; 20 | } 21 | 22 | a { 23 | color: #CA7900; 24 | text-decoration: none; 25 | } 26 | 27 | a:hover { 28 | color: #2491CF; 29 | } 30 | 31 | pre { 32 | font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 33 | font-size: 0.95em; 34 | letter-spacing: 0.015em; 35 | padding: 0.5em; 36 | border: 1px solid #ccc; 37 | background-color: #f8f8f8; 38 | } 39 | 40 | td.linenos pre { 41 | padding: 0.5em 0; 42 | border: 0; 43 | background-color: transparent; 44 | color: #aaa; 45 | } 46 | 47 | table.highlighttable { 48 | margin-left: 0.5em; 49 | } 50 | 51 | table.highlighttable td { 52 | padding: 0 0.5em 0 0.5em; 53 | } 54 | 55 | cite, code, tt { 56 | font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 57 | font-size: 0.95em; 58 | letter-spacing: 0.01em; 59 | } 60 | 61 | hr { 62 | border: 1px solid #abc; 63 | margin: 2em; 64 | } 65 | 66 | tt { 67 | background-color: #f2f2f2; 68 | border-bottom: 1px solid #ddd; 69 | color: #333; 70 | } 71 | 72 | tt.descname { 73 | background-color: transparent; 74 | font-weight: bold; 75 | font-size: 1.2em; 76 | border: 0; 77 | } 78 | 79 | tt.descclassname { 80 | background-color: transparent; 81 | border: 0; 82 | } 83 | 84 | tt.xref { 85 | background-color: transparent; 86 | font-weight: bold; 87 | border: 0; 88 | } 89 | 90 | a tt { 91 | background-color: transparent; 92 | font-weight: bold; 93 | border: 0; 94 | color: #CA7900; 95 | } 96 | 97 | a tt:hover { 98 | color: #2491CF; 99 | } 100 | 101 | dl { 102 | margin-bottom: 15px; 103 | } 104 | 105 | dd p { 106 | margin-top: 0px; 107 | } 108 | 109 | dd ul, dd table { 110 | margin-bottom: 10px; 111 | } 112 | 113 | dd { 114 | margin-top: 3px; 115 | margin-bottom: 10px; 116 | margin-left: 30px; 117 | } 118 | 119 | .refcount { 120 | color: #060; 121 | } 122 | 123 | dt:target, 124 | .highlight { 125 | background-color: #fbe54e; 126 | } 127 | 128 | dl.class, dl.function { 129 | border-top: 2px solid #888; 130 | } 131 | 132 | dl.method, dl.attribute { 133 | border-top: 1px solid #aaa; 134 | } 135 | 136 | dl.glossary dt { 137 | font-weight: bold; 138 | font-size: 1.1em; 139 | } 140 | 141 | pre { 142 | line-height: 120%; 143 | } 144 | 145 | pre a { 146 | color: inherit; 147 | text-decoration: underline; 148 | } 149 | 150 | .first { 151 | margin-top: 0 !important; 152 | } 153 | 154 | div.document { 155 | background-color: white; 156 | text-align: left; 157 | background-image: url(contents.png); 158 | background-repeat: repeat-x; 159 | } 160 | 161 | /* 162 | div.documentwrapper { 163 | width: 100%; 164 | } 165 | */ 166 | 167 | div.clearer { 168 | clear: both; 169 | } 170 | 171 | div.related h3 { 172 | display: none; 173 | } 174 | 175 | div.related ul { 176 | background-image: url(navigation.png); 177 | height: 2em; 178 | list-style: none; 179 | border-top: 1px solid #ddd; 180 | border-bottom: 1px solid #ddd; 181 | margin: 0; 182 | padding-left: 10px; 183 | } 184 | 185 | div.related ul li { 186 | margin: 0; 187 | padding: 0; 188 | height: 2em; 189 | float: left; 190 | } 191 | 192 | div.related ul li.right { 193 | float: right; 194 | margin-right: 5px; 195 | } 196 | 197 | div.related ul li a { 198 | margin: 0; 199 | padding: 0 5px 0 5px; 200 | line-height: 1.75em; 201 | color: #EE9816; 202 | } 203 | 204 | div.related ul li a:hover { 205 | color: #3CA8E7; 206 | } 207 | 208 | div.body { 209 | margin: 0; 210 | padding: 0.5em 20px 20px 20px; 211 | } 212 | 213 | div.bodywrapper { 214 | margin: 0 240px 0 0; 215 | border-right: 1px solid #ccc; 216 | } 217 | 218 | div.body a { 219 | text-decoration: underline; 220 | } 221 | 222 | div.sphinxsidebar { 223 | margin: 0; 224 | padding: 0.5em 15px 15px 0; 225 | width: 210px; 226 | float: right; 227 | text-align: left; 228 | /* margin-left: -100%; */ 229 | } 230 | 231 | div.sphinxsidebar h4, div.sphinxsidebar h3 { 232 | margin: 1em 0 0.5em 0; 233 | font-size: 0.9em; 234 | padding: 0.1em 0 0.1em 0.5em; 235 | color: white; 236 | border: 1px solid #86989B; 237 | background-color: #AFC1C4; 238 | } 239 | 240 | div.sphinxsidebar ul { 241 | padding-left: 1.5em; 242 | margin-top: 7px; 243 | list-style: none; 244 | padding: 0; 245 | line-height: 130%; 246 | } 247 | 248 | div.sphinxsidebar ul ul { 249 | list-style: square; 250 | margin-left: 20px; 251 | } 252 | 253 | p { 254 | margin: 0.8em 0 0.5em 0; 255 | } 256 | 257 | p.rubric { 258 | font-weight: bold; 259 | } 260 | 261 | h1 { 262 | margin: 0; 263 | padding: 0.7em 0 0.3em 0; 264 | font-size: 1.5em; 265 | color: #11557C; 266 | } 267 | 268 | h2 { 269 | margin: 1.3em 0 0.2em 0; 270 | font-size: 1.35em; 271 | padding: 0; 272 | } 273 | 274 | h3 { 275 | margin: 1em 0 -0.3em 0; 276 | font-size: 1.2em; 277 | } 278 | 279 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { 280 | color: black!important; 281 | } 282 | 283 | h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor { 284 | display: none; 285 | margin: 0 0 0 0.3em; 286 | padding: 0 0.2em 0 0.2em; 287 | color: #aaa!important; 288 | } 289 | 290 | h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, 291 | h5:hover a.anchor, h6:hover a.anchor { 292 | display: inline; 293 | } 294 | 295 | h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover, 296 | h5 a.anchor:hover, h6 a.anchor:hover { 297 | color: #777; 298 | background-color: #eee; 299 | } 300 | 301 | table { 302 | border-collapse: collapse; 303 | margin: 0 -0.5em 0 -0.5em; 304 | } 305 | 306 | table td, table th { 307 | padding: 0.2em 0.5em 0.2em 0.5em; 308 | } 309 | 310 | div.footer { 311 | background-color: #E3EFF1; 312 | color: #86989B; 313 | padding: 3px 8px 3px 0; 314 | clear: both; 315 | font-size: 0.8em; 316 | text-align: right; 317 | } 318 | 319 | div.footer a { 320 | color: #86989B; 321 | text-decoration: underline; 322 | } 323 | 324 | div.pagination { 325 | margin-top: 2em; 326 | padding-top: 0.5em; 327 | border-top: 1px solid black; 328 | text-align: center; 329 | } 330 | 331 | div.sphinxsidebar ul.toc { 332 | margin: 1em 0 1em 0; 333 | padding: 0 0 0 0.5em; 334 | list-style: none; 335 | } 336 | 337 | div.sphinxsidebar ul.toc li { 338 | margin: 0.5em 0 0.5em 0; 339 | font-size: 0.9em; 340 | line-height: 130%; 341 | } 342 | 343 | div.sphinxsidebar ul.toc li p { 344 | margin: 0; 345 | padding: 0; 346 | } 347 | 348 | div.sphinxsidebar ul.toc ul { 349 | margin: 0.2em 0 0.2em 0; 350 | padding: 0 0 0 1.8em; 351 | } 352 | 353 | div.sphinxsidebar ul.toc ul li { 354 | padding: 0; 355 | } 356 | 357 | div.admonition, div.warning { 358 | font-size: 0.9em; 359 | margin: 1em 0 0 0; 360 | border: 1px solid #86989B; 361 | background-color: #f7f7f7; 362 | } 363 | 364 | div.admonition p, div.warning p { 365 | margin: 0.5em 1em 0.5em 1em; 366 | padding: 0; 367 | } 368 | 369 | div.admonition pre, div.warning pre { 370 | margin: 0.4em 1em 0.4em 1em; 371 | } 372 | 373 | div.admonition p.admonition-title, 374 | div.warning p.admonition-title { 375 | margin: 0; 376 | padding: 0.1em 0 0.1em 0.5em; 377 | color: white; 378 | border-bottom: 1px solid #86989B; 379 | font-weight: bold; 380 | background-color: #AFC1C4; 381 | } 382 | 383 | div.warning { 384 | border: 1px solid #940000; 385 | } 386 | 387 | div.warning p.admonition-title { 388 | background-color: #CF0000; 389 | border-bottom-color: #940000; 390 | } 391 | 392 | div.admonition ul, div.admonition ol, 393 | div.warning ul, div.warning ol { 394 | margin: 0.1em 0.5em 0.5em 3em; 395 | padding: 0; 396 | } 397 | 398 | div.versioninfo { 399 | margin: 1em 0 0 0; 400 | border: 1px solid #ccc; 401 | background-color: #DDEAF0; 402 | padding: 8px; 403 | line-height: 1.3em; 404 | font-size: 0.9em; 405 | } 406 | 407 | 408 | a.headerlink { 409 | color: #c60f0f!important; 410 | font-size: 1em; 411 | margin-left: 6px; 412 | padding: 0 4px 0 4px; 413 | text-decoration: none!important; 414 | visibility: hidden; 415 | } 416 | 417 | h1:hover > a.headerlink, 418 | h2:hover > a.headerlink, 419 | h3:hover > a.headerlink, 420 | h4:hover > a.headerlink, 421 | h5:hover > a.headerlink, 422 | h6:hover > a.headerlink, 423 | dt:hover > a.headerlink { 424 | visibility: visible; 425 | } 426 | 427 | a.headerlink:hover { 428 | background-color: #ccc; 429 | color: white!important; 430 | } 431 | 432 | table.indextable td { 433 | text-align: left; 434 | vertical-align: top; 435 | } 436 | 437 | table.indextable dl, table.indextable dd { 438 | margin-top: 0; 439 | margin-bottom: 0; 440 | } 441 | 442 | table.indextable tr.pcap { 443 | height: 10px; 444 | } 445 | 446 | table.indextable tr.cap { 447 | margin-top: 10px; 448 | background-color: #f2f2f2; 449 | } 450 | 451 | img.toggler { 452 | margin-right: 3px; 453 | margin-top: 3px; 454 | cursor: pointer; 455 | } 456 | 457 | img.inheritance { 458 | border: 0px 459 | } 460 | 461 | form.pfform { 462 | margin: 10px 0 20px 0; 463 | } 464 | 465 | table.contentstable { 466 | width: 90%; 467 | } 468 | 469 | table.contentstable p.biglink { 470 | line-height: 150%; 471 | } 472 | 473 | a.biglink { 474 | font-size: 1.3em; 475 | } 476 | 477 | span.linkdescr { 478 | font-style: italic; 479 | padding-top: 5px; 480 | font-size: 90%; 481 | } 482 | 483 | ul.search { 484 | margin: 10px 0 0 20px; 485 | padding: 0; 486 | } 487 | 488 | ul.search li { 489 | padding: 5px 0 5px 20px; 490 | background-image: url(file.png); 491 | background-repeat: no-repeat; 492 | background-position: 0 7px; 493 | } 494 | 495 | ul.search li a { 496 | font-weight: bold; 497 | } 498 | 499 | ul.search li div.context { 500 | color: #888; 501 | margin: 2px 0 0 30px; 502 | text-align: left; 503 | } 504 | 505 | ul.keywordmatches li.goodmatch a { 506 | font-weight: bold; 507 | } 508 | -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_static/fwrap_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kwmsmith/fwrap/f2e20eb55eaa3de72905e2ef28198da00eebe262/doc/sphinxdocs/source/_static/fwrap_logo.png -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_static/fwrap_logo_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kwmsmith/fwrap/f2e20eb55eaa3de72905e2ef28198da00eebe262/doc/sphinxdocs/source/_static/fwrap_logo_big.png -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_static/fwrap_logo_med.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kwmsmith/fwrap/f2e20eb55eaa3de72905e2ef28198da00eebe262/doc/sphinxdocs/source/_static/fwrap_logo_med.png -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_templates/indexsidebar.html: -------------------------------------------------------------------------------- 1 |

License

2 | 3 |

Fwrap is licensed under the 4 | new BSD license.

5 | 6 |

Git Repository

7 | 8 |

Get the latest development version 9 | here.

10 | -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | 4 | {% block rootrellink %} 5 |
  • home
  • 6 | {#
  • search
  • #} 7 | {#
  • documentation »
  • #} 8 | {% endblock %} 9 | 10 | 11 | {% block relbar1 %} 12 | 13 |
    14 | py4sci 16 |
    17 | {{ super() }} 18 | {% endblock %} 19 | 20 | {# put the sidebar before the body #} 21 | {% block sidebar1 %}{{ sidebar() }}{% endblock %} 22 | {% block sidebar2 %}{% endblock %} 23 | 24 | -------------------------------------------------------------------------------- /doc/sphinxdocs/source/_templates/mplexample.html: -------------------------------------------------------------------------------- 1 |

    matplotlib 0.99.1 is available for download. See what's new and tips on installing 3 |

    4 | 5 |

    Sandro Tosi has a new book 6 | Matplotlib for python 7 | developers 8 | also 9 | at amazon.

    10 | 11 |

    Build websites like matplotlib's, 12 | with sphinx and extensions for 13 | mpl plots, math, inheritance diagrams -- try 14 | the sampledoc 15 | tutorial. 16 |

    17 | 18 |

    Videos

    19 | 20 |

    Watch the SciPy 2009 intro and advanced matplotlib tutorials 21 |

    22 | 23 |

    Watch a talk about matplotlib presented at NIPS 08 Workshop MLOSS. 24 |

    25 | 26 | 27 |

    Toolkits

    28 | 29 |

    There are several matplotlib addon toolkits, including the projection 31 | and mapping toolkit 32 | basemap, 3d plotting with mplot3d, axes and axis helpers in axes_grid and more. 35 |

    36 | 37 |

    Need help?

    38 | 39 |

    Check the user guide, 40 | the faq, the api docs, 42 | archives, 43 | and join the matplotlib 44 | mailing lists. 45 | The search tool searches all of 46 | the documentation, including full text search of over 350 complete 47 | examples which exercise almost every corner of matplotlib.

    48 | 49 |

    You can file bugs, patches and feature requests on the 50 | sourceforge 51 | tracker, 52 | but it is a good idea to ping us on the mailing list too.

    53 | 54 |

    For details on what's new, see the detailed changelog or browse the source code. Anything that could 56 | require changes to your existing codes is logged in the api changes file.

    58 | 59 |

    Other stuff

    60 | 61 |

    The matplotlib license 62 | is based on the Python Software Foundation 63 | (PSF) license.

    64 | 65 |

    There is an active developer community and a long list of people 66 | who have made significant contributions.

    68 | 69 | -------------------------------------------------------------------------------- /doc/sphinxdocs/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # fwrap documentation build configuration file, created by 4 | # sphinx-quickstart on Tue May 18 21:00:46 2010. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.append(os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # Add any Sphinx extension module names here, as strings. They can be extensions 24 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 25 | extensions = [] 26 | 27 | # Add any paths that contain templates here, relative to this directory. 28 | templates_path = ['_templates'] 29 | 30 | # The suffix of source filenames. 31 | source_suffix = '.rst' 32 | 33 | # The encoding of source files. 34 | #source_encoding = 'utf-8' 35 | 36 | # The master toctree document. 37 | master_doc = 'index' 38 | 39 | # General information about the project. 40 | project = u'fwrap' 41 | copyright = u'2010, K. W. Smith' 42 | 43 | # The version info for the project you're documenting, acts as replacement for 44 | # |version| and |release|, also used in various other places throughout the 45 | # built documents. 46 | # 47 | # The short X.Y version. 48 | version = '0.1' 49 | # The full version, including alpha/beta/rc tags. 50 | release = '0.1.0' 51 | 52 | # The language for content autogenerated by Sphinx. Refer to documentation 53 | # for a list of supported languages. 54 | #language = None 55 | 56 | # There are two options for replacing |today|: either, you set today to some 57 | # non-false value, then it is used: 58 | #today = '' 59 | # Else, today_fmt is used as the format for a strftime call. 60 | #today_fmt = '%B %d, %Y' 61 | 62 | # List of documents that shouldn't be included in the build. 63 | #unused_docs = [] 64 | 65 | # List of directories, relative to source directory, that shouldn't be searched 66 | # for source files. 67 | exclude_trees = [] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. Major themes that come with 93 | # Sphinx are currently 'default' and 'sphinxdoc'. 94 | html_theme = 'sphinxdoc' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | html_theme_options = {'nosidebar' : 'false'} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | html_title = "%s v%s" % (project, release) 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | html_sidebars = {'index' : 'indexsidebar.html'} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | html_use_modindex = False 142 | 143 | # If false, no index is generated. 144 | html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | html_show_sourcelink = False 151 | 152 | # If true, an OpenSearch description file will be output, and all pages will 153 | # contain a tag referring to it. The value of this option must be the 154 | # base URL from which the finished HTML is served. 155 | #html_use_opensearch = '' 156 | 157 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 158 | #html_file_suffix = '' 159 | 160 | # Output file base name for HTML help builder. 161 | htmlhelp_basename = 'fwrapdoc' 162 | 163 | 164 | # -- Options for LaTeX output -------------------------------------------------- 165 | 166 | # The paper size ('letter' or 'a4'). 167 | #latex_paper_size = 'letter' 168 | 169 | # The font size ('10pt', '11pt' or '12pt'). 170 | #latex_font_size = '10pt' 171 | 172 | # Grouping the document tree into LaTeX files. List of tuples 173 | # (source start file, target name, title, author, documentclass [howto/manual]). 174 | latex_documents = [ 175 | ('index', 'fwrap.tex', u'fwrap Documentation', 176 | u'K. W. Smith', 'manual'), 177 | ] 178 | 179 | # The name of an image file (relative to this directory) to place at the top of 180 | # the title page. 181 | #latex_logo = None 182 | 183 | # For "manual" documents, if this is true, then toplevel headings are parts, 184 | # not chapters. 185 | #latex_use_parts = False 186 | 187 | # Additional stuff for the LaTeX preamble. 188 | #latex_preamble = '' 189 | 190 | # Documents to append as an appendix to all manuals. 191 | #latex_appendices = [] 192 | 193 | # If false, no module index is generated. 194 | #latex_use_modindex = True 195 | -------------------------------------------------------------------------------- /doc/sphinxdocs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. fwrap documentation master file, created by 2 | sphinx-quickstart on Tue May 18 21:00:46 2010. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | +++++++++++++++++++++++++++++++++++++ 7 | Fortran for Speed, Python for Comfort 8 | +++++++++++++++++++++++++++++++++++++ 9 | 10 | .. .. .. toctree:: 11 | .. .. :maxdepth: 2 12 | 13 | Fwrap wraps Fortran code in C, Cython and Python. It focuses on Fortran 90 and 14 | 95, and will work with Fortran 77 so long as you limit yourself to "sane" 15 | Fortran 77. [#sane-def]_ 16 | 17 | Fwrap is licensed under the new BSD license. 18 | 19 | Fwrap is in beta-stage until otherwise indicated. All commandline options and 20 | public APIs are subject to change. 21 | 22 | Fwrap changed its SCM from Mercurial to Git (github with a mirror on 23 | sourceforge). You can access the main development repository 24 | `here on github `_. 25 | 26 | Download Fwrap 27 | ============== 28 | 29 | Get the lastest version `here `_. 30 | https://sourceforge.net/projects/fwrap/files/ 31 | 32 | Dependencies 33 | ============ 34 | 35 | `Python `_ 36 | Tested with 2.5 & 2.6 (2.4 in the near future, 3.x planned) 37 | 38 | `NumPy `_ 39 | Tested with NumPy >= 1.3.0 40 | 41 | `Cython `_ 42 | Tested with Cython >= 0.11 43 | 44 | **A Fortran 90 compiler** 45 | 46 | Known to work with: 47 | 48 | * ``gfortran`` >= 4.4.1 49 | 50 | * ``ifort`` >= 11.1 51 | 52 | * ``g95`` >= 0.92 53 | 54 | 55 | Bug reports, Wiki & Mailing list 56 | ================================ 57 | 58 | `Fwrap trac `_ 59 | For bug reports, wiki pages, etc. 60 | 61 | ``_ 62 | Questions, comments, patches, help... 63 | 64 | Development 65 | =========== 66 | 67 | `Git repository `_ 68 | To get the latest development version 69 | 70 | `Development blog `_ 71 | For all fwrap-related news 72 | 73 | Some helpful links 74 | ------------------ 75 | 76 | `Sourceforge support wiki `_ 77 | 78 | `Fortran standards `_ 79 | 80 | .. rubric:: Footnotes 81 | 82 | .. [#sane-def] 83 | By "sane", we mean don't use `ENTRY`, `EQUIVALENCE`, STATEMENT functions, or 84 | other dark corners of Fortran 77. If you don't know what these are, count 85 | yourself lucky. 86 | 87 | 88 | .. Indices and tables 89 | .. ================== 90 | 91 | .. * :ref:`genindex` 92 | 93 | .. * :ref:`modindex` 94 | -------------------------------------------------------------------------------- /doc/sphinxdocs/upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | scp -r build/html/* kwmsmith,fwrap@web.sourceforge.net:htdocs 4 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # Change this to your fortran vendor; see 2 | # fwrapc.py --help-fcompiler 3 | FCOMP = gnu95 4 | 5 | DIRS = arrays \ 6 | scalars \ 7 | intents \ 8 | functions \ 9 | kinds \ 10 | 11 | all: arrays_ext scalars_ext intents_ext functions_ext kinds_ext 12 | 13 | clean: 14 | @for dir in $(DIRS) ;\ 15 | do \ 16 | rm -r "$${dir}/$${dir}_ext" ;\ 17 | done 18 | 19 | arrays_ext: 20 | ../fwrapc.py arrays/source.f90 --build --fcompiler=$(FCOMP) \ 21 | --name=arrays_ext --out_dir=arrays --override 22 | 23 | scalars_ext: 24 | ../fwrapc.py scalars/source.f90 --build --fcompiler=$(FCOMP) \ 25 | --name=scalars_ext --out_dir=scalars --override 26 | 27 | intents_ext: 28 | ../fwrapc.py intents/source.f90 --build --fcompiler=$(FCOMP) \ 29 | --name=intents_ext --out_dir=intents --override 30 | 31 | functions_ext: 32 | ../fwrapc.py functions/source.f90 --build --fcompiler=$(FCOMP) \ 33 | --name=functions_ext --out_dir=functions --override 34 | 35 | kinds_ext: 36 | ../fwrapc.py kinds/source.f90 --build --fcompiler=$(FCOMP) \ 37 | --name=kinds_ext --out_dir=kinds --override 38 | 39 | -------------------------------------------------------------------------------- /examples/arrays/source.f90: -------------------------------------------------------------------------------- 1 | subroutine array_args(iarg, rarg, carg, larg, charg) 2 | implicit none 3 | integer, dimension(:), intent(inout) :: iarg 4 | real, dimension(:), intent(inout) :: rarg 5 | complex, dimension(:), intent(inout) :: carg 6 | logical, dimension(:), intent(inout) :: larg 7 | character(len=10), dimension(:), intent(inout) :: charg 8 | 9 | iarg = 1 10 | rarg = 2.0E0 11 | carg = (3.0E0, 4.0E0) 12 | larg = .true. 13 | charg = "0123456789" 14 | 15 | end subroutine array_args 16 | -------------------------------------------------------------------------------- /examples/functions/source.f90: -------------------------------------------------------------------------------- 1 | function func(a) 2 | implicit none 3 | integer func 4 | integer, intent(in) :: a 5 | func = a + 10 6 | end function 7 | -------------------------------------------------------------------------------- /examples/intents/source.f90: -------------------------------------------------------------------------------- 1 | subroutine intents(inarg, inoutarg, outarg, nointent) 2 | implicit none 3 | integer, intent(in) :: inarg 4 | integer, intent(inout) :: inoutarg 5 | integer, intent(out) :: outarg 6 | integer :: nointent 7 | 8 | outarg = inarg + inoutarg 9 | inoutarg = inarg 10 | nointent = 3 11 | 12 | end subroutine intents 13 | -------------------------------------------------------------------------------- /examples/kinds/source.f90: -------------------------------------------------------------------------------- 1 | subroutine non_default(iarg, rarg, carg, larg) 2 | implicit none 3 | integer*8 :: iarg 4 | real(kind=8) :: rarg 5 | complex(kind=8) :: carg 6 | logical*8 :: larg 7 | 8 | iarg = 3 9 | rarg = 4.0_8 10 | carg = (10.0_8, 11.0_8) 11 | larg = logical(.true., kind=kind(larg)) 12 | 13 | end subroutine non_default 14 | -------------------------------------------------------------------------------- /examples/scalars/source.f90: -------------------------------------------------------------------------------- 1 | subroutine simple_subr(iarg, rarg, larg, carg, charg) 2 | implicit none 3 | integer, intent(inout) :: iarg 4 | real, intent(inout) :: rarg 5 | logical, intent(inout) :: larg 6 | complex, intent(inout) :: carg 7 | character(len=1), intent(inout) :: charg 8 | 9 | iarg = 1 10 | rarg = 2.0E0 11 | larg = .true. 12 | carg = (3.0E0, 4.0E0) 13 | charg = "E" 14 | 15 | end subroutine simple_subr 16 | -------------------------------------------------------------------------------- /fwrap/__init__.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | #!/usr/bin/env python 7 | # encoding: utf-8 8 | 9 | import os 10 | import sys 11 | 12 | 13 | __all__ = [] 14 | -------------------------------------------------------------------------------- /fwrap/code.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from cStringIO import StringIO 7 | from math import ceil, floor 8 | 9 | INDENT = " " 10 | LINE_LENGTH = 77 # leave room for two '&' characters 11 | BREAK_CHARS = (' ', '\t', ',', '!') 12 | COMMENT_CHAR = '!' 13 | 14 | def reflow_fort(code, level=0, max_len=LINE_LENGTH): 15 | newcode = ['\n'.join(reflow_line(line)) for line in code.splitlines()] 16 | return '\n'.join(newcode) 17 | 18 | def reflow_line(text, level=0, max_len=LINE_LENGTH): 19 | line_len = max_len - len(INDENT)*level 20 | broken_text = [] 21 | lim = int(ceil(len(text)/float(line_len))) 22 | for i in range(lim): 23 | broken_text.append('&'+text[i*line_len:(i+1)*line_len]+'&') 24 | 25 | # strip off the beginning & ending continuations. 26 | broken_text[0] = broken_text[0][1:] 27 | broken_text[-1] = broken_text[-1][:-1] 28 | 29 | # prepend the indent 30 | broken_text = [INDENT*level + txt for txt in broken_text] 31 | 32 | return broken_text 33 | 34 | def _break_line(line, level, max_len): 35 | 36 | line = INDENT*level+line 37 | 38 | if len(line) <= max_len: 39 | # return line 40 | return [line] 41 | 42 | # break up line. 43 | in_comment = False 44 | in_string = False 45 | in_escape = False 46 | last_break_pos = -1 47 | for idx, ch in enumerate(line): 48 | if idx+1 > max_len: 49 | if last_break_pos < 0: 50 | raise RuntimeError("line too long and unable to break it up.") 51 | return [line[:last_break_pos]] + \ 52 | break_line(line[last_break_pos:], level, max_len) 53 | 54 | if ch in BREAK_CHARS and not in_comment and not in_string: 55 | last_break_pos = idx 56 | 57 | if ch == COMMENT_CHAR and not in_comment and not in_string: 58 | in_comment = True 59 | elif ch in ('"', "'") and not in_string and not in_comment: 60 | in_string = True 61 | elif (ch in ('"', "'") and in_string and not 62 | in_escape and not in_comment): 63 | in_string = False 64 | 65 | if ch == '\\' and not in_escape: 66 | in_escape = True 67 | elif in_escape: 68 | in_escape = False 69 | 70 | class CodeBuffer(object): 71 | def __init__(self, level=0, indent=" "): 72 | self.sio = StringIO() 73 | self._level = level 74 | self.indent_tok = indent 75 | 76 | def putempty(self): 77 | self.sio.write('\n') 78 | 79 | def putlines(self, lines): 80 | if isinstance(lines, basestring): 81 | lines = lines.splitlines() 82 | for line in lines: 83 | self.putln(line) 84 | 85 | def putline(self, line): 86 | self.putln(line) 87 | 88 | def putln(self, line): 89 | line = line.rstrip() 90 | if line: 91 | self.sio.write(self.indent_tok * self._level + line + '\n') 92 | else: 93 | self.putempty() 94 | 95 | def indent(self): 96 | self._level += 1 97 | 98 | def dedent(self): 99 | self._level -= 1 100 | 101 | def getvalue(self): 102 | return self.sio.getvalue() 103 | 104 | def write(self, s): 105 | self.sio.write(s) 106 | -------------------------------------------------------------------------------- /fwrap/constants.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | PROC_SUFFIX_TMPL = "%s_c" 7 | 8 | KTP_MOD_NAME = "fwrap_ktp_mod" 9 | KTP_MOD_SRC = "%s.f90" % KTP_MOD_NAME 10 | KTP_HEADER_SRC = "fwrap_ktp_header.h" 11 | KTP_PXD_HEADER_SRC = "fwrap_ktp.pxd" 12 | 13 | FC_HDR_TMPL = "%s_fc.h" 14 | FC_PXD_TMPL = "%s_fc.pxd" 15 | FC_F_TMPL = "%s_fc.f90" 16 | 17 | CY_PXD_TMPL = "%s.pxd" 18 | CY_PYX_TMPL = "%s.pyx" 19 | 20 | GENCONFIG_SRC = "genconfig.f90" 21 | TYPE_SPECS_SRC = "fwrap_type_specs.in" 22 | MAP_SRC = "fwrap_type_map.out" 23 | 24 | RETURN_ARG_NAME = "fw_ret_arg" 25 | ERR_NAME = "fw_iserr__" 26 | ERRSTR_NAME = "fw_errstr__" 27 | ERRSTR_LEN = "fw_errstr_len" 28 | FORT_MAX_ARG_NAME_LEN = 63 29 | 30 | ERR_CODES = { 31 | ERRSTR_LEN : FORT_MAX_ARG_NAME_LEN, 32 | 'FW_NO_ERR__' : 0, 33 | 'FW_INIT_ERR__' : -1, 34 | 'FW_CHAR_SIZE__' : 1, 35 | 'FW_ARR_DIM__' : 2, 36 | } 37 | 38 | -------------------------------------------------------------------------------- /fwrap/default.config: -------------------------------------------------------------------------------- 1 | [general] 2 | source = 3 | exclude = 4 | only = 5 | name = fwproj 6 | out_dir = ./ 7 | recompile = True 8 | build = False 9 | override = False 10 | verbose = False 11 | 12 | [compiler] 13 | f90 = gfortran 14 | fcompiler = gnu95 15 | fflags = 16 | libraries = 17 | library_dirs = 18 | extra_objects = 19 | -------------------------------------------------------------------------------- /fwrap/fort_expr.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | # Modifed beyond all recognition from example parser in fourFn.py, distributed 7 | # with pyparsing. 8 | # 9 | # Original fourFn.py is Copyright 2003-2009 by Paul McGuire 10 | 11 | 12 | from pyparsing_py2 import (Literal, CaselessLiteral, Word, Group, Optional, 13 | ZeroOrMore, Forward, nums, alphas, Regex, Combine, TokenConverter, 14 | QuotedString, FollowedBy, Empty) 15 | 16 | from visitor import TreeVisitor 17 | 18 | class ExtractNames(TreeVisitor): 19 | 20 | def __init__(self): 21 | super(ExtractNames, self).__init__() 22 | self.namenodes = [] 23 | self.funcnamenodes = [] 24 | 25 | visit_ExprNode = TreeVisitor.visitchildren 26 | 27 | #XXX: slight hack here... 28 | visit_str = lambda self, x: None 29 | 30 | def visit_FuncRefNode(self, node): 31 | self.funcnamenodes.append(node.name) 32 | self.visitchildren(node, ["arg_spec_list"]) 33 | 34 | def visit_NameNode(self, node): 35 | self.namenodes.append(node) 36 | 37 | def visit_ArgSpecNode(self, node): 38 | self.visitchildren(node, ["arg"]) 39 | 40 | def _get_names(self): 41 | return [node.name for node in self.namenodes] 42 | names = property(_get_names) 43 | 44 | def _get_funcnames(self): 45 | return [node.name for node in self.funcnamenodes] 46 | funcnames = property(_get_funcnames) 47 | 48 | 49 | class ExprNode(object): 50 | 51 | child_attrs = ["subexpr"] 52 | 53 | def __init__(self, s, loc, toks): 54 | self.subexpr = toks.asList()[:] 55 | 56 | 57 | class AssumedShapeSpec(ExprNode): 58 | 59 | child_attrs = [] 60 | 61 | def __init__(self, s, loc, toks): 62 | self.star, = toks.asList() 63 | assert self.star == '*' 64 | 65 | 66 | class CharLiteralConst(ExprNode): 67 | 68 | child_attrs = ["kind"] 69 | 70 | def __init__(self, s, loc, toks): 71 | toks = toks.asList() 72 | self.kind = None 73 | if len(toks) == 3: 74 | self.kind, under, self.string = toks 75 | elif len(toks) == 2: 76 | self.kind, self.string = toks 77 | kind_str = self.kind.param.name 78 | assert kind_str.endswith('_') 79 | self.kind.param.name = self.kind.param.name.rstrip("_") 80 | elif len(toks) == 1: 81 | self.string, = toks 82 | else: 83 | raise ValueError("wrong number of tokens %s" % toks) 84 | 85 | 86 | class RealLitConst(ExprNode): 87 | 88 | child_attrs = ["sign", "real", "kind"] 89 | 90 | def __init__(self, s, loc, toks): 91 | self.sign, self.real, self.kind = None, None, None 92 | toks = toks.asList() 93 | if str(toks[0]) in "+-": 94 | self.sign, self.real = toks[0], toks[1] 95 | else: 96 | self.sign, self.real = None, toks[0] 97 | if len(toks) > 2: 98 | under, self.kind = toks[-2:] 99 | else: 100 | assert len(toks) < 4 101 | 102 | 103 | class FuncRefNode(ExprNode): 104 | 105 | child_attrs = ["name", "arg_spec_list"] 106 | 107 | def __init__(self, s, loc, toks): 108 | self.name, self.arg_spec_list = toks.asList()[0], toks.asList()[1:] 109 | 110 | 111 | class ArgSpecNode(ExprNode): 112 | 113 | child_attrs = ["kw", "arg"] 114 | 115 | def __init__(self, s, loc, toks): 116 | self.kw = None 117 | if len(toks) == 3: 118 | self.kw, eq, self.arg = toks.asList() 119 | else: 120 | self.arg, = toks.asList() 121 | 122 | 123 | class KindParam(ExprNode): 124 | 125 | child_attrs = ["param"] 126 | 127 | def __init__(self, s, loc, toks): 128 | assert len(toks) == 1 129 | self.param = toks.asList()[0] 130 | 131 | 132 | class ComplexLitConst(ExprNode): 133 | 134 | child_attrs = ["realpart", "imagpart"] 135 | 136 | def __init__(self, s, loc, toks): 137 | assert len(toks) == 3 138 | self.realpart, comma, self.imagpart = toks.asList() 139 | 140 | 141 | class LogicalLitConst(ExprNode): 142 | 143 | child_attrs = ["value", "kind"] 144 | 145 | def __init__(self, s, loc, toks): 146 | if len(toks) == 3: 147 | self.value, under, self.kind = toks.asList() 148 | elif len(toks) == 1: 149 | self.value, self.kind = toks.asList(), None 150 | else: 151 | raise ValueError("wrong number of tokens") 152 | 153 | 154 | class NameNode(ExprNode): 155 | 156 | child_attrs = [] 157 | 158 | def __init__(self, s, loc, toks): 159 | self.name = toks.asList()[0] 160 | 161 | 162 | class SignNode(ExprNode): 163 | 164 | child_attrs = [] 165 | 166 | def __init__(self, s, loc, toks): 167 | self.sign, = toks.asList() 168 | 169 | def __str__(self): 170 | return str(self.sign) 171 | 172 | 173 | class DigitStringNode(ExprNode): 174 | 175 | child_attrs = [] 176 | 177 | def __init__(self, s, loc, toks): 178 | self.digit_string, = toks.asList() 179 | 180 | def __str__(self): 181 | return str(self.digit_string) 182 | 183 | class LiteralNode(ExprNode): 184 | 185 | child_attrs = [] 186 | 187 | def __init__(self, s, loc, toks): 188 | self.val, = toks.asList() 189 | 190 | def __str__(self): 191 | return str(self.val) 192 | 193 | fort_expr_bnf = None 194 | def get_fort_expr_bnf(): 195 | global fort_expr_bnf 196 | if fort_expr_bnf: 197 | return fort_expr_bnf 198 | 199 | expr = Forward() 200 | 201 | lpar = Literal("(").suppress() 202 | rpar = Literal(")").suppress() 203 | 204 | under = Literal("_").setParseAction(LiteralNode) 205 | dot = Literal(".").setParseAction(LiteralNode) 206 | comma = Literal(",").setParseAction(LiteralNode) 207 | concat_op = Literal("//") 208 | power_op = Literal("**") 209 | expo_letter = Regex(r"[eEdD]") 210 | mult_op = (Literal("*") | Literal("/")) 211 | sign = (Literal("+") | Literal("-")).setParseAction(SignNode) 212 | add_op = sign 213 | 214 | name = Regex(r"[a-zA-Z]\w*").setParseAction(NameNode) 215 | 216 | # int literals 217 | digit_string = Word(nums).setParseAction(DigitStringNode) 218 | signed_digit_string = Combine(Optional(sign) + digit_string) 219 | 220 | kind_param = (digit_string | name).setParseAction(KindParam) 221 | 222 | int_literal_constant = ((digit_string + Optional("_" + kind_param)) | name) 223 | signed_int_literal_constant = (Optional(sign) + int_literal_constant) 224 | 225 | exponent = signed_digit_string 226 | 227 | # real literal 228 | sig1st = (digit_string + dot + Optional(digit_string)) 229 | sig2nd = (dot + digit_string) 230 | significand = (sig1st | sig2nd) 231 | real_lit_const_1st = (Combine( 232 | significand + 233 | Optional(expo_letter + exponent)) + 234 | Optional(under + kind_param)) 235 | 236 | real_lit_const_2nd = (Combine( 237 | digit_string + 238 | expo_letter + 239 | exponent) + 240 | Optional(under + kind_param)) 241 | real_literal_constant = (real_lit_const_1st | real_lit_const_2nd) 242 | signed_real_literal_constant = \ 243 | (Optional(sign) + 244 | real_literal_constant).setParseAction(RealLitConst) 245 | 246 | # complex literals 247 | cmplx_part = ( signed_real_literal_constant 248 | | signed_int_literal_constant 249 | | name) 250 | complex_literal_constant = \ 251 | (lpar + cmplx_part + 252 | comma + cmplx_part + rpar).setParseAction(ComplexLitConst) 253 | 254 | # character literals 255 | squotedString = QuotedString(quoteChar="'", escQuote="''") 256 | dquotedString = QuotedString(quoteChar='"', escQuote='""') 257 | 258 | #XXX: this is kind of cheating... 259 | char_literal_constant = \ 260 | (Optional(kind_param + Optional("_")) + 261 | (squotedString | dquotedString)).setParseAction(CharLiteralConst) 262 | 263 | # logical literals 264 | logical_literal_constant = \ 265 | ( (CaselessLiteral(".TRUE.") + 266 | Optional(under + kind_param)) 267 | | (CaselessLiteral(".FALSE.") + 268 | Optional(under + kind_param))).setParseAction(LogicalLitConst) 269 | 270 | constant = ( char_literal_constant 271 | | complex_literal_constant 272 | | signed_real_literal_constant 273 | | logical_literal_constant 274 | | signed_int_literal_constant) 275 | 276 | arg = (expr | name) 277 | arg_spec = (Optional(name + Literal("=")) 278 | + arg).setParseAction(ArgSpecNode) 279 | arg_spec_list = (arg_spec + ZeroOrMore(comma + arg_spec)) 280 | function_reference = (name + lpar + Optional(arg_spec_list) 281 | + rpar).setParseAction(FuncRefNode) 282 | 283 | #R701 284 | primary = (function_reference ^ constant ^ name ^ (lpar + expr + rpar)) 285 | 286 | #R702 we ignore defined unary ops for now. 287 | level1_expr = primary 288 | 289 | #R704 - R709 290 | mult_operand = Forward() 291 | mult_operand << (level1_expr + Optional((power_op + mult_operand))) 292 | add_operand = (mult_operand + ZeroOrMore(mult_op + mult_operand)) 293 | level2_expr = (ZeroOrMore(sign) + 294 | add_operand + ZeroOrMore(add_op + add_operand)) 295 | 296 | #R710 - R711 297 | level3_expr = (level2_expr + ZeroOrMore(concat_op + level2_expr)) 298 | 299 | # We skip level 4 and level 5 expressions, since they aren't valid in a 300 | # dimension or ktp context. 301 | 302 | # expr << (Literal('*').setParseAction(AssumedShapeSpec) | level3_expr.setParseAction(ExprNode)) 303 | expr << ( level3_expr.setParseAction(ExprNode) 304 | | Literal('*').setParseAction(AssumedShapeSpec) 305 | | Empty().setParseAction(ExprNode)) 306 | 307 | fort_expr_bnf = expr 308 | return fort_expr_bnf 309 | 310 | def parse(s): 311 | return get_fort_expr_bnf().parseString(s, parseAll=False).asList()[0] 312 | -------------------------------------------------------------------------------- /fwrap/fwrap_parse.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import pyf_iface as pyf 7 | from fparser import api 8 | 9 | def generate_ast(fsrcs): 10 | ast = [] 11 | for src in fsrcs: 12 | block = api.parse(src, analyze=True) 13 | tree = block.content 14 | for proc in tree: 15 | 16 | if not is_proc(proc): 17 | # we ignore non-top-level procedures until modules are supported. 18 | continue 19 | 20 | args = _get_args(proc) 21 | params = _get_params(proc) 22 | 23 | if proc.blocktype == 'subroutine': 24 | ast.append(pyf.Subroutine( 25 | name=proc.name, 26 | args=args, 27 | params=params)) 28 | elif proc.blocktype == 'function': 29 | ast.append(pyf.Function( 30 | name=proc.name, 31 | args=args, 32 | params=params, 33 | return_arg=_get_ret_arg(proc))) 34 | return ast 35 | 36 | 37 | def is_proc(proc): 38 | return proc.blocktype in ('subroutine', 'function') 39 | 40 | def _get_ret_arg(proc): 41 | ret_var = proc.get_variable(proc.result) 42 | ret_arg = _get_arg(ret_var) 43 | ret_arg.intent = None 44 | return ret_arg 45 | 46 | def _get_param(p_param): 47 | if not p_param.is_parameter(): 48 | raise ValueError("argument %r is not a parameter" % p_param) 49 | if not p_param.init: 50 | raise ValueError("parameter %r does not have an initialization " 51 | "expression." % p_param) 52 | p_typedecl = p_param.get_typedecl() 53 | dtype = _get_dtype(p_typedecl) 54 | name = p_param.name 55 | intent = _get_intent(p_param) 56 | if not p_param.is_scalar(): 57 | raise RuntimeError("do not support array or derived-type " 58 | "parameters at the moment...") 59 | return pyf.Parameter(name=name, dtype=dtype, expr=p_param.init) 60 | 61 | def _get_arg(p_arg): 62 | p_typedecl = p_arg.get_typedecl() 63 | dtype = _get_dtype(p_typedecl) 64 | name = p_arg.name 65 | intent = _get_intent(p_arg) 66 | if p_arg.is_scalar(): 67 | return pyf.Argument(name=name, dtype=dtype, intent=intent) 68 | elif p_arg.is_array(): 69 | p_dims = p_arg.get_array_spec() 70 | dimspec = pyf.Dimension(p_dims) 71 | return pyf.Argument(name=name, 72 | dtype=dtype, intent=intent, dimension=dimspec) 73 | else: 74 | raise RuntimeError( 75 | "argument %s is neither " 76 | "a scalar or an array (derived type?)" % p_arg) 77 | 78 | def _get_args(proc): 79 | args = [] 80 | for argname in proc.args: 81 | p_arg = proc.get_variable(argname) 82 | args.append(_get_arg(p_arg)) 83 | return args 84 | 85 | def _get_params(proc): 86 | params = [] 87 | for varname in proc.a.variables: 88 | var = proc.a.variables[varname] 89 | if var.is_parameter(): 90 | params.append(_get_param(var)) 91 | return params 92 | 93 | def _get_intent(arg): 94 | intents = [] 95 | if not arg.intent: 96 | intents.append("inout") 97 | else: 98 | if arg.is_intent_in(): 99 | intents.append("in") 100 | if arg.is_intent_inout(): 101 | intents.append("inout") 102 | if arg.is_intent_out(): 103 | intents.append("out") 104 | if not intents: 105 | raise RuntimeError("argument has no intent specified, '%s'" % arg) 106 | if len(intents) > 1: 107 | raise RuntimeError( 108 | "argument has multiple " 109 | "intents specified, '%s', %s" % (arg, intents)) 110 | return intents[0] 111 | 112 | name2default = { 113 | 'integer' : pyf.default_integer, 114 | 'real' : pyf.default_real, 115 | 'doubleprecision' : pyf.default_dbl, 116 | 'complex' : pyf.default_complex, 117 | 'doublecomplex' : pyf.default_double_complex, 118 | 'character' : pyf.default_character, 119 | 'logical' : pyf.default_logical, 120 | } 121 | 122 | name2type = { 123 | 'integer' : pyf.IntegerType, 124 | 'real' : pyf.RealType, 125 | 'complex' : pyf.ComplexType, 126 | 'character' : pyf.CharacterType, 127 | 'logical' : pyf.LogicalType, 128 | } 129 | 130 | def _get_dtype(typedecl): 131 | if not typedecl.is_intrinsic(): 132 | raise RuntimeError( 133 | "only intrinsic types supported ATM... [%s]" % str(typedecl)) 134 | length, kind = typedecl.selector 135 | if not kind and not length: 136 | return name2default[typedecl.name] 137 | if length and kind and typedecl.name != 'character': 138 | raise RuntimeError("both length and kind specified for " 139 | "non-character intrinsic type: " 140 | "length: %s kind: %s" % (length, kind)) 141 | if typedecl.name == 'character': 142 | if length == '*': 143 | fw_ktp = '%s_xX' % (typedecl.name) 144 | else: 145 | fw_ktp = '%s_x%s' % (typedecl.name, length) 146 | return pyf.CharacterType(fw_ktp=fw_ktp, 147 | len=length, kind=kind) 148 | if length and not kind: 149 | return name2type[typedecl.name](fw_ktp="%s_x%s" % 150 | (typedecl.name, length), 151 | length=length) 152 | try: 153 | int(kind) 154 | except ValueError: 155 | raise RuntimeError( 156 | "only integer constant kind " 157 | "parameters supported ATM, given '%s'" % kind) 158 | if typedecl.name == 'doubleprecision': 159 | return pyf.default_dbl 160 | return name2type[typedecl.name](fw_ktp="%s_%s" % 161 | (typedecl.name, kind), kind=kind) 162 | -------------------------------------------------------------------------------- /fwrap/fwrapc.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | # encoding: utf-8 7 | 8 | import os, sys, shutil 9 | import subprocess 10 | from optparse import OptionParser, OptionGroup 11 | 12 | PROJECT_OUTDIR = 'fwproj' 13 | PROJECT_NAME = PROJECT_OUTDIR 14 | 15 | def setup_dirs(dirname): 16 | p = os.path 17 | fwrap_path = p.abspath(p.dirname(__file__)) 18 | # set up the project directory. 19 | try: 20 | os.mkdir(dirname) 21 | except OSError: 22 | pass 23 | src_dir = os.path.join(dirname, 'src') 24 | try: 25 | os.mkdir(src_dir) 26 | except OSError: 27 | pass 28 | 29 | # cp waf and wscript into the project dir. 30 | fw_wscript = os.path.join( 31 | fwrap_path, 32 | 'fwrap_wscript') 33 | 34 | shutil.copy( 35 | fw_wscript, 36 | os.path.join(dirname, 'wscript')) 37 | 38 | waf_path = os.path.join( 39 | fwrap_path, 40 | 'waf') 41 | 42 | shutil.copy( 43 | waf_path, 44 | dirname) 45 | 46 | def wipe_out(dirname): 47 | # wipe out everything and start over. 48 | shutil.rmtree(dirname, ignore_errors=True) 49 | 50 | def proj_dir(name): 51 | return os.path.abspath(name) 52 | 53 | def configure_cb(opts, args, orig_args): 54 | wipe_out(proj_dir(opts.outdir)) 55 | setup_dirs(proj_dir(opts.outdir)) 56 | 57 | def build_cb(opts, args, argv): 58 | srcs = [] 59 | for arg in args: 60 | larg = arg.lower() 61 | if larg.endswith('.f') or larg.endswith('.f90'): 62 | srcs.append(os.path.abspath(arg)) 63 | argv.remove(arg) 64 | 65 | dst = os.path.join(proj_dir(opts.outdir), 'src') 66 | for src in srcs: 67 | shutil.copy(src, dst) 68 | 69 | def call_waf(opts, args, orig_args): 70 | if 'configure' in args: 71 | configure_cb(opts, args, orig_args) 72 | 73 | if 'build' in args: 74 | build_cb(opts, args, orig_args) 75 | 76 | py_exe = sys.executable 77 | 78 | waf_path = os.path.join(proj_dir(opts.outdir), 'waf') 79 | 80 | cmd = [py_exe, waf_path] + orig_args 81 | odir = os.path.abspath(os.curdir) 82 | os.chdir(proj_dir(opts.outdir)) 83 | try: 84 | subprocess.check_call(cmd) 85 | finally: 86 | os.chdir(odir) 87 | 88 | return 0 89 | 90 | def print_version(): 91 | from fwrap.version import get_version 92 | vandl = """\ 93 | fwrap v%s 94 | Copyright (C) 2010 Kurt W. Smith 95 | Fwrap is distributed under an open-source license. See the source for 96 | licensing information. There is NO warranty, not even for MERCHANTABILITY or 97 | FITNESS FOR A PARTICULAR PURPOSE. 98 | """ % get_version() 99 | print vandl 100 | 101 | def fwrapc(argv): 102 | """ 103 | Main entry point -- called by cmdline script. 104 | """ 105 | 106 | subcommands = ('configure', 'gen', 'build') 107 | 108 | parser = OptionParser() 109 | parser.add_option('--version', dest="version", 110 | action="store_true", default=False, 111 | help="get version and license info and exit") 112 | 113 | # configure options 114 | configure_opts = OptionGroup(parser, "Configure Options") 115 | configure_opts.add_option("--name", 116 | help='name for the extension module [default %default]') 117 | configure_opts.add_option("--outdir", 118 | help='directory for the intermediate files [default %default]') 119 | parser.add_option_group(configure_opts) 120 | 121 | conf_defaults = dict(name=PROJECT_NAME, outdir=PROJECT_OUTDIR) 122 | parser.set_defaults(**conf_defaults) 123 | 124 | opts, args = parser.parse_args(args=argv) 125 | 126 | if opts.version: 127 | print_version() 128 | return 0 129 | 130 | if not ('configure' in args or 'build' in args): 131 | parser.print_usage() 132 | return 1 133 | 134 | return call_waf(opts, args, argv) 135 | -------------------------------------------------------------------------------- /fwrap/fwrapper.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | # encoding: utf-8 7 | 8 | import os 9 | from optparse import OptionParser 10 | 11 | from fwrap import constants 12 | from fwrap import gen_config as gc 13 | from fwrap import fc_wrap 14 | from fwrap import cy_wrap 15 | from fwrap.code import CodeBuffer, reflow_fort 16 | 17 | PROJNAME = 'fwproj' 18 | 19 | def wrap(sources, name=PROJNAME): 20 | r"""Generate wrappers for sources. 21 | 22 | The core wrapping routine for fwrap. Generates wrappers for the sources 23 | list. Compilation of the wrappers is left to external utilities, whether 24 | distutils or waf. 25 | 26 | :Input: 27 | - *sources* - (id) Path to source or a list of paths to source to be 28 | wrapped. 29 | - *name* - (string) Name of the project and the name of the resulting 30 | python module 31 | """ 32 | 33 | # validate name 34 | name = name.strip() 35 | name = name.replace(' ', '_') 36 | 37 | # Check to see if each source exists and expand to full paths 38 | source_files = [] 39 | def check(s): 40 | return os.path.exists(s) 41 | if isinstance(sources, basestring): 42 | if check(sources): 43 | source_files = [sources] 44 | elif isinstance(sources, (list, tuple)): 45 | for src in sources: 46 | if check(src): 47 | source_files.append(src) 48 | if not source_files: 49 | raise ValueError("Invalid source list. %r" % (sources)) 50 | 51 | # Parse fortran using fparser, get fortran ast. 52 | f_ast = parse(source_files) 53 | 54 | # Generate wrapper files 55 | generate(f_ast, name) 56 | 57 | def parse(source_files): 58 | r"""Parse fortran code returning parse tree 59 | 60 | :Input: 61 | - *source_files* - (list) List of valid source files 62 | """ 63 | from fwrap import fwrap_parse 64 | ast = fwrap_parse.generate_ast(source_files) 65 | 66 | return ast 67 | 68 | def generate(fort_ast, name): 69 | r"""Given a fortran abstract syntax tree ast, generate wrapper files 70 | 71 | :Input: 72 | - *fort_ast* - (`fparser.ProgramBlock`) Abstract syntax tree from parser 73 | - *name* - (string) Name of the library module 74 | 75 | Raises `Exception.IOError` if writing the generated code fails. 76 | """ 77 | 78 | # Generate wrapping abstract syntax trees 79 | # logger.info("Generating abstract syntax tress for c and cython.") 80 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 81 | cython_ast = cy_wrap.wrap_fc(c_ast) 82 | 83 | # Generate files and write them out 84 | generators = ( (generate_type_specs,(c_ast,name)), 85 | (generate_fc_f,(c_ast,name)), 86 | (generate_fc_h,(c_ast,name)), 87 | (generate_fc_pxd,(c_ast,name)), 88 | (generate_cy_pxd,(cython_ast,name)), 89 | (generate_cy_pyx,(cython_ast,name)) ) 90 | 91 | for (generator,args) in generators: 92 | file_name, buf = generator(*args) 93 | write_to_dir(os.getcwd(), file_name, buf) 94 | 95 | def write_to_dir(dir, file_name, buf): 96 | fh = open(os.path.join(dir, file_name), 'w') 97 | try: 98 | if isinstance(buf, basestring): 99 | fh.write(buf) 100 | else: 101 | fh.write(buf.getvalue()) 102 | finally: 103 | fh.close() 104 | 105 | def generate_type_specs(f_ast, name): 106 | buf = CodeBuffer() 107 | gc.generate_type_specs(f_ast, buf) 108 | return constants.TYPE_SPECS_SRC, buf 109 | 110 | def generate_cy_pxd(cy_ast, name): 111 | buf = CodeBuffer() 112 | fc_pxd_name = (constants.FC_PXD_TMPL % name).split('.')[0] 113 | cy_wrap.generate_cy_pxd(cy_ast, fc_pxd_name, buf) 114 | return constants.CY_PXD_TMPL % name, buf 115 | 116 | def generate_cy_pyx(cy_ast, name): 117 | buf = CodeBuffer() 118 | cy_wrap.generate_cy_pyx(cy_ast, name, buf) 119 | return constants.CY_PYX_TMPL % name, buf 120 | 121 | def generate_fc_pxd(fc_ast, name): 122 | buf = CodeBuffer() 123 | fc_header_name = constants.FC_HDR_TMPL % name 124 | fc_wrap.generate_fc_pxd(fc_ast, fc_header_name, buf) 125 | return constants.FC_PXD_TMPL % name, buf 126 | 127 | def generate_fc_f(fc_ast, name): 128 | buf = CodeBuffer() 129 | for proc in fc_ast: 130 | proc.generate_wrapper(buf) 131 | ret_buf = CodeBuffer() 132 | ret_buf.putlines(reflow_fort(buf.getvalue())) 133 | return constants.FC_F_TMPL % name, ret_buf 134 | 135 | def generate_fc_h(fc_ast, name): 136 | buf = CodeBuffer() 137 | fc_wrap.generate_fc_h(fc_ast, constants.KTP_HEADER_SRC, buf) 138 | return constants.FC_HDR_TMPL % name, buf 139 | 140 | def fwrapper(use_cmdline, sources=None, **options): 141 | """ 142 | Main entry point, called by cmdline script. 143 | """ 144 | 145 | if sources is None: 146 | sources = [] 147 | defaults = dict(name=PROJNAME) 148 | if options: 149 | defaults.update(options) 150 | usage ='''\ 151 | Usage: %prog --name=NAME fortran-source [fortran-source ...] 152 | ''' 153 | description = '''\ 154 | %prog is a commandline utility that automatically wraps Fortran code in C, 155 | Cython, & Python. 156 | ''' 157 | parser = OptionParser(usage=usage, description=description) 158 | parser.set_defaults(**defaults) 159 | if use_cmdline: 160 | parser.add_option('-n', '--name', dest='name', 161 | help='name for the project directory and extension module ' 162 | '[default: %default]') 163 | args = None 164 | else: 165 | args = sources 166 | parsed_options, source_files = parser.parse_args(args=args) 167 | if not source_files: 168 | parser.error("no source files") 169 | wrap(source_files, parsed_options.name) 170 | return 0 171 | -------------------------------------------------------------------------------- /fwrap/intrinsics.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | intrinsics = """\ 7 | ABS 8 | ACHAR 9 | ACOS 10 | ADJUSTL 11 | ADJUSTR 12 | AIMAG 13 | AINT 14 | ALL 15 | ALLOCATED 16 | ANINT 17 | ANY 18 | ASIN 19 | ASSOCIATED 20 | ATAN 21 | ATAN2 22 | BIT_SIZE 23 | BTEST 24 | CEILING 25 | CHAR 26 | CHARACTER 27 | CMPLX 28 | COMMAND_ARGUMENT_COUNT 29 | COMPLEX 30 | CONJG 31 | COS 32 | COSH 33 | COUNT 34 | CPU_TIME 35 | CSHIFT 36 | DATE_AND_TIME 37 | DBLE 38 | DIGITS 39 | DIM 40 | DOT_PRODUCT 41 | DPROD 42 | EOSHIFT 43 | EPSILON 44 | EXP 45 | EXPONENT 46 | EXTENDS 47 | FLOOR 48 | FRACTION 49 | GET_COMMAND 50 | GET_COMMAND_ARGUMENT 51 | GET_ENVIRONMENT_VARIABLE 52 | HUGE 53 | IACHAR 54 | IAND 55 | IBCLR 56 | IBITS 57 | IBSET 58 | ICHAR 59 | IEOR 60 | INDEX 61 | INT 62 | INTEGER 63 | IOR 64 | ISHFT 65 | ISHFTC 66 | IS_IOSTAT_END 67 | IS_IOSTAT_EOR 68 | KIND 69 | LBOUND 70 | LEN 71 | LEN_TRIM 72 | LGE 73 | LGT 74 | LLE 75 | LLT 76 | LOG 77 | LOG10 78 | LOGICAL 79 | MATMUL 80 | MAX 81 | MAXEXPONENT 82 | MAXLOC 83 | MAXVAL 84 | MERGE 85 | MIN 86 | MINEXPONENT 87 | MINLOC 88 | MINVAL 89 | MOD 90 | MODULO 91 | MOVE_ALLOC 92 | MVBITS 93 | NEAREST 94 | NEW_LINE 95 | NINT 96 | NOT 97 | NULL 98 | PACK 99 | PRECISION 100 | PRESENT 101 | PRODUCT 102 | RADIX 103 | RANDOM_NUMBER 104 | RANDOM_SEED 105 | RANGE 106 | REAL 107 | REPEAT 108 | RESHAPE 109 | RRSPACING 110 | SAME_TYPE_AS 111 | SCALE 112 | SCAN 113 | SELECTED_CHAR_KIND 114 | SELECTED_INT_KIND 115 | SELECTED_REAL_KIND 116 | SET 117 | SHAPE 118 | SIGN 119 | SIN 120 | SINH 121 | SIZE 122 | SPACING 123 | SPREAD 124 | SQRT 125 | SUM 126 | SYSTEM_CLOCK 127 | TAN 128 | TANH 129 | TINY 130 | TRANSFER 131 | TRANSPOSE 132 | TRIM 133 | UBOUND 134 | UNPACK 135 | VERIFY\ 136 | """ 137 | 138 | intrinsics = set(intrinsics.split('\n')) 139 | intrinsics = set([intrins.lower() for intrins in intrinsics]) 140 | -------------------------------------------------------------------------------- /fwrap/log.config: -------------------------------------------------------------------------------- 1 | # fwrap default logging configuration 2 | 3 | # ---------------------------------------------------------------------------- 4 | # This section defines the names of the loggers, handlers and formatters 5 | # 6 | 7 | # These are the names of the different loggers 8 | [loggers] 9 | keys=root,fwrap 10 | 11 | # These are the names of the different handlers that we will setup later 12 | [handlers] 13 | keys=file,console,syslog 14 | 15 | # These are the formatters used for the formatters, here we only define one 16 | # but multiple may be defined for different tasks 17 | [formatters] 18 | keys=default,detailed 19 | 20 | # ---------------------------------------------------------------------------- 21 | # Logger settings 22 | # 23 | [logger_root] 24 | level=DEBUG 25 | handlers=file,console 26 | 27 | [logger_fwrap] 28 | level=NOTSET 29 | propagate=0 30 | qualname=fwrap 31 | handlers=file,console 32 | channel=fwrap 33 | parent=(root) 34 | 35 | # ---------------------------------------------------------------------------- 36 | 37 | # ---------------------------------------------------------------------------- 38 | # Handlers 39 | # 40 | [handler_file] 41 | class=FileHandler 42 | level=DEBUG 43 | formatter=detailed 44 | args=('fwrap.log','w') 45 | 46 | [handler_console] 47 | class=StreamHandler 48 | level=INFO 49 | formatter=default 50 | args=(sys.stdout,) 51 | 52 | [handler_syslog] 53 | class=handlers.SysLogHandler 54 | level=NOTSET 55 | formatter=detailed 56 | args=(('localhost',handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER) 57 | # ---------------------------------------------------------------------------- 58 | 59 | # ---------------------------------------------------------------------------- 60 | # Formatters 61 | # 62 | [formatter_default] 63 | # format=%(asctime)s %(levelname)s: %(message)s 64 | format=%(levelname)s: %(message)s 65 | datefmt= 66 | 67 | [formatter_detailed] 68 | format=%(asctime)s %(name)s %(levelname)s: %(lineno)d - %(message)s 69 | datefmt= 70 | 71 | # ---------------------------------------------------------------------------- 72 | -------------------------------------------------------------------------------- /fwrap/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | 7 | -------------------------------------------------------------------------------- /fwrap/tests/test_code.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import code 7 | 8 | from nose.tools import ok_, eq_, set_trace 9 | 10 | import sys 11 | from pprint import pprint 12 | 13 | # 1) Any non-comment line can be broken anywhere -- in the middle of words, 14 | # etc. 15 | # 2) Comments are stripped out of the source and are to be ignored in reflowing 16 | # text. 17 | 18 | def test_breakup(): 19 | line = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " 20 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 21 | 22 | for chunk in (1, 2, 3, 5, 10, 20, 50, len(line)): 23 | yield breakup_gen, line, chunk 24 | 25 | def breakup_gen(line, chunk): 26 | ret = code.reflow_line(line, 0, chunk) 27 | eq_(simple_break(line, chunk), ret) 28 | for part in ret[1:-1]: 29 | eq_(len(part), chunk+2) 30 | if len(ret) == 1: 31 | eq_(len(ret[0]), len(line)) 32 | else: 33 | eq_(len(ret[0]), chunk+1) 34 | ok_(len(ret[-1]) <= chunk+1) 35 | orig = ''.join(ret) 36 | orig = orig.replace('&', '') 37 | eq_(orig, line) 38 | 39 | def simple_break(text, chunk): 40 | i = 0 41 | test_ret = [] 42 | while True: 43 | test_ret.append('&'+text[i*chunk:(i+1)*chunk]+'&') 44 | if (i+1)*chunk >= len(text): 45 | break 46 | i += 1 47 | 48 | test_ret[0] = test_ret[0][1:] 49 | test_ret[-1] = test_ret[-1][:-1] 50 | # set_trace() 51 | return test_ret 52 | 53 | def test_nobreak(): 54 | line = ("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 55 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 56 | ret = code.reflow_line(line, 0, 100) 57 | eq_(ret, [line]) 58 | 59 | def test_indent(): 60 | line = "12345678901234567890" 61 | ret = code.reflow_line(line, 1, 100) 62 | eq_(ret, [code.INDENT+line]) 63 | ret = code.reflow_line(line, 1, 10) 64 | eq_(ret, [code.INDENT+line[:8]+'&', 65 | code.INDENT+'&'+line[8:16]+'&', 66 | code.INDENT+'&'+line[16:]]) 67 | def test_reflow(): 68 | reflow_src = ("subroutine many_args(a0, a1, a2, a3, a4, a5, a6, a7, a8, " 69 | "a9, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30" 70 | ", a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, " 71 | "a42, a43, a44, a45, a46, a47, a48, a49)\n" 72 | " implicit none\n" 73 | " integer, intent(in) :: a0, a1, a2, a3, a4, a5, a6, " 74 | "a7, a8, a9, a20, a21, a22, a23, a24, a25, a26, a27, a28, " 75 | "a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, " 76 | "a40, a41, a42, a43, a44, a45, a46, a47, a48, a49\n" 77 | "end subroutine many_args") 78 | 79 | buf = code.CodeBuffer() 80 | buf.putline(code.reflow_fort(reflow_src)) 81 | for line in buf.getvalue().splitlines(): 82 | ok_(len(line) <= 79, "len('%s') > 79" % line) 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /fwrap/tests/test_dimension.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import pyf_iface as pyf 7 | 8 | from nose.tools import raises, ok_, eq_ 9 | 10 | def _test_scal_int_expr(): 11 | sie = pyf.ScalarIntExpr("kind('a')") 12 | eq_(sie.find_names(), set(['kind'])) 13 | 14 | def _setup(self): 15 | self.colon = pyf.Dim(':') 16 | self.colon_parsed = pyf.Dim(('','')) 17 | self.lbound = pyf.Dim('n:') 18 | self.lubound = pyf.Dim('10:20') 19 | self.lubound_parsed = pyf.Dim(('1', '1')) 20 | self.e1, self.e2 =('nx%y + 1', 'size(a, 3-N) + kind(NX%Z)') 21 | self.expr = pyf.Dim((self.e1, self.e2)) 22 | self.explicit1 = pyf.Dim('10') 23 | self.explicit2 = pyf.Dim('anteohusatnheuo%asnotehusaeontuh') 24 | self.explicit3 = pyf.Dim(('LDIM',)) 25 | 26 | self.assumed_size1 = pyf.Dim(('0:*')) 27 | self.assumed_size2 = pyf.Dim(('n','*')) 28 | 29 | class test_dim(object): 30 | 31 | def setup(self): 32 | _setup(self) 33 | 34 | @raises(ValueError) 35 | def test_ubound(self): 36 | pyf.Dim(':10') 37 | 38 | def test_sizeexpr(self): 39 | eq_(self.colon.sizeexpr, None) 40 | eq_(self.colon_parsed.sizeexpr, None) 41 | eq_(self.lbound.sizeexpr, None) 42 | eq_(self.assumed_size1.sizeexpr, None) 43 | eq_(self.assumed_size2.sizeexpr, None) 44 | eq_(self.lubound.sizeexpr, '((20) - (10) + 1)') 45 | eq_(self.lubound_parsed.sizeexpr, '((1) - (1) + 1)') 46 | eq_(self.expr.sizeexpr, "((%s) - (%s) + 1)" % (self.e2.lower(), self.e1.lower())) 47 | eq_(self.explicit1.sizeexpr, "(10)") 48 | 49 | 50 | def test_names(self): 51 | epty = set() 52 | eq_(self.colon.depnames, epty) 53 | eq_(self.colon_parsed.depnames, epty) 54 | eq_(self.lbound.depnames, set(['n'])) 55 | eq_(self.lubound.depnames, epty) 56 | eq_(self.expr.depnames, set(['nx', 'size', 'a', 'n', 'kind'])) 57 | 58 | 59 | def test_isassumedshape(self): 60 | ok_(self.colon.is_assumed_shape) 61 | ok_(self.colon_parsed.is_assumed_shape) 62 | ok_(self.lbound.is_assumed_shape) 63 | ok_(not self.lubound.is_assumed_shape) 64 | ok_(not self.lubound_parsed.is_assumed_shape) 65 | ok_(not self.expr.is_assumed_shape) 66 | 67 | 68 | class test_dimension(object): 69 | 70 | def setup(self): 71 | _setup(self) 72 | self.dims = pyf.Dimension((self.colon, self.lbound, self.lubound, self.expr)) 73 | 74 | def test_names(self): 75 | eq_(self.dims.depnames, self.lbound.depnames.union(self.expr.depnames)) 76 | 77 | def test_dimspec(self): 78 | eq_(self.dims.attrspec, 79 | ('dimension(:, n:, 10:20, %s:%s)' % 80 | (self.e1.lower(), self.e2.lower()))) 81 | 82 | def test_len(self): 83 | eq_(len(self.dims), 4) 84 | -------------------------------------------------------------------------------- /fwrap/tests/test_fort_expr.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap.fort_expr import parse, ExtractNames 7 | 8 | from nose.tools import eq_, ok_ 9 | 10 | class test_fort_expr(object): 11 | 12 | def test_signed_int_lit(self): 13 | istr = str(310130813080138) 14 | s = "+%s" % istr 15 | skp = "%s_8 + 10_abc" % s 16 | 17 | def test_func_ref(self): 18 | ss = "foo(a, b-3+x(14), c=d+1)" 19 | expr = parse(ss) 20 | 21 | def test_extractnames(self): 22 | ss = "-+12354.5678E-12_aoeu" 23 | expr = parse(ss) 24 | 25 | xtor = ExtractNames() 26 | xtor.visit(expr) 27 | eq_(xtor.names, ['aoeu']) 28 | 29 | ss2 = ".02808_a123_45" 30 | expr = parse(ss2) 31 | 32 | xtor = ExtractNames() 33 | xtor.visit(expr) 34 | eq_(xtor.names, ['a123_45']) 35 | 36 | funccall = parse("foo(a, b-3+x(14), c=d+1)") 37 | xtor = ExtractNames() 38 | xtor.visit(funccall) 39 | eq_(xtor.names, ['a', 'b', 'd']) 40 | eq_(xtor.funcnames, ['foo', 'x']) 41 | 42 | power = parse("+1**2_a8") 43 | xtor = ExtractNames() 44 | xtor.visit(power) 45 | eq_(xtor.names, ['a8']) 46 | eq_(xtor.funcnames, []) 47 | 48 | def test_char_lit_const(self): 49 | clc2 = parse("aoeu_'1202\"04''028'").subexpr[0] 50 | clc3 = parse('1_"as ""onthu\'sanetu"').subexpr[0] 51 | eq_(clc2.kind.param.name, 'aoeu') 52 | eq_(clc2.string, '1202"04\'028') 53 | eq_(clc3.kind.param.digit_string, '1') 54 | eq_(clc3.string, 'as "onthu\'sanetu') 55 | 56 | 57 | def _tester(tstr, res, funcs=None): 58 | expr = parse(tstr) 59 | xtor = ExtractNames() 60 | xtor.visit(expr) 61 | eq_(xtor.names, res) 62 | if funcs: 63 | eq_(xtor.funcnames, funcs) 64 | 65 | def test_gen(): 66 | 67 | for args in _tests: 68 | if len(args) == 2: 69 | tstr, res = args 70 | funcs = [] 71 | elif len(args) == 3: 72 | tstr, res, funcs = args 73 | yield _tester, tstr, res, funcs 74 | 75 | _tests = [ 76 | ("9", []), 77 | ("-9", []), 78 | ("3.1415926", []), 79 | ("3.1415926E10", []), 80 | ("3.1415926_8", []), 81 | ("--9", []), 82 | ("-E", ['E']), 83 | ("9 + 3 + 6", []), 84 | ("9 + 3 / 11", []), 85 | ("(9 + 3)", []), 86 | ("(9+3) / 11", []), 87 | ("9 - 12 - 6", []), 88 | ("9 - (12 - 6)", []), 89 | ("2*3.14159", []), 90 | ("3.1415926535*3.1415926535 / 10", []), 91 | ("PI * PI / 10", ["PI", "PI"]), 92 | ("PI*PI/10", ["PI", "PI"]), 93 | ("PI**2", ["PI"]), 94 | ("round(PI**2)", ["PI"], ["round"]), 95 | ("6.02E23 * 8.048", []), 96 | ("e / 3", ["e"]), 97 | ("sin(PI/2)", ['PI'], ["sin"]), 98 | ("trunc(E)", ['E'], ["trunc"]), 99 | ("trunc(-E)", ['E'], ["trunc"]), 100 | ("round(E)", ['E'], ["round"]), 101 | ("round(-E)", ['E'], ["round"]), 102 | ("E**PI", ['E', 'PI']), 103 | ("2**3**2", [], []), 104 | ("2**3+2", []), 105 | ("2**3+5", []), 106 | ("2**9", []), 107 | ("sgn(-2)", [], ["sgn"]), 108 | ("sgn(0)", [], ["sgn"]), 109 | ("sgn(0.1)", [], ["sgn"]), 110 | ("(0.0)", []), 111 | ("(abc, def)", ['abc', 'def']), 112 | ("(0.0, 0.0)", []), 113 | ("3 -(-(+9))", []), 114 | ("3 -(-(+(-(-(+9)))))", []), 115 | ("kind('a')", [], ["kind"]), 116 | ("(123456_'aosentuh' // aoeu_'aosnteh')", ['aoeu']), 117 | ("(0.0_r8, 1.0_d12)", ["r8", "d12"]), 118 | ("1234.567E12_g_1 + .35009_f13_ / (-.9D3_D__3 + 1._a1)", ['g_1', 'f13_', 'D__3', 'a1']), 119 | ("*", [], []), 120 | ("", [], []), 121 | # ("(1.0E+0, 0.0E+0)", [], []), 122 | # ("(1.0D+0, 0.0D+0)", [], []), 123 | # ("(-1.0D+00, 0.0D+00)", [], []), 124 | ] 125 | 126 | def test_regr_reallitconst(): 127 | tests = [("(1.0E+0, 0.0E+0)", [], []), 128 | ("(1.0D+0, 0.0D+0)", [], []), 129 | ("(-1.0D+00, 0.0D+00)", [], []),] 130 | for t in tests: 131 | tstr, res, funcs = t 132 | yield _tester, tstr, res, funcs 133 | -------------------------------------------------------------------------------- /fwrap/tests/test_fwrap_parse.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import fwrap_parse as fp 7 | from fwrap import pyf_iface as pyf 8 | 9 | from cStringIO import StringIO 10 | 11 | from nose.tools import ok_, eq_, set_trace 12 | 13 | def test_parse_many(): 14 | buf = '''\ 15 | subroutine subr1(a, b, c) 16 | implicit none 17 | integer, intent(in) :: a 18 | complex :: b 19 | double precision, intent(out) :: c 20 | 21 | c = a + aimag(b) 22 | 23 | end subroutine subr1 24 | 25 | 26 | function func1(a, b, c) 27 | implicit none 28 | integer, intent(in) :: a 29 | real :: b 30 | complex, intent(in) :: c 31 | double precision :: func1 32 | 33 | func1 = a + aimag(c) - b 34 | 35 | end function func1 36 | ''' 37 | subr, func = fp.generate_ast([buf]) 38 | eq_(subr.name, 'subr1') 39 | eq_(func.name, 'func1') 40 | eq_([arg.name for arg in subr.args], ['a', 'b', 'c']) 41 | eq_([arg.dtype for arg in subr.args], [pyf.default_integer, 42 | pyf.default_complex, 43 | pyf.default_dbl]) 44 | # eq_([arg.name for arg in subr.args], ['a', 'b', 'c']) 45 | 46 | def test_parse_array_args(): 47 | buf = '''\ 48 | SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, 49 | $ LWORK, IWORK, INFO ) 50 | * 51 | * -- LAPACK driver routine (version 3.2.1) -- 52 | * -- LAPACK is a software package provided by Univ. of Tennessee, -- 53 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 54 | * March 2009 55 | * 56 | * .. Scalar Arguments .. 57 | CHARACTER JOBZ 58 | INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N 59 | * .. 60 | * .. Array Arguments .. 61 | INTEGER IWORK( * ) 62 | DOUBLE PRECISION A( LDA, * ), S( * ), U( LDU, * ), 63 | $ VT( LDVT, * ), WORK( * ) 64 | END SUBROUTINE DGESDD''' 65 | subr = fp.generate_ast([buf])[0] 66 | eq_(subr.name, 'dgesdd') 67 | eq_([arg.name for arg in subr.args], 68 | "jobz m n a lda s u ldu vt ldvt work lwork iwork info".split()) 69 | 70 | def test_parse_kind_args(): 71 | fcode = '''\ 72 | function int_args_func(a,b,c,d) 73 | integer(kind=8) :: int_args_func 74 | integer(kind=1), intent(in) :: a 75 | integer(kind=2), intent(in) :: b 76 | integer(kind=4), intent(in) :: c 77 | integer(kind=8), intent(out) :: d 78 | 79 | d = a + b + c 80 | int_args_func = 10 81 | 82 | end function int_args_func 83 | ''' 84 | func = fp.generate_ast([fcode])[0] 85 | eq_([arg.dtype.odecl 86 | for arg in func.args], 87 | ["integer(kind=%d)" % i 88 | for i in (1,2,4,8)]) 89 | -------------------------------------------------------------------------------- /fwrap/tests/test_fwrapper.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | import os 7 | import tempfile 8 | 9 | from fwrap import fc_wrap 10 | from fwrap import cy_wrap 11 | from fwrap import constants 12 | from fwrap import fwrapper 13 | from cStringIO import StringIO 14 | from fwrap import pyf_iface as pyf 15 | from fwrap.code import CodeBuffer 16 | 17 | from nose.tools import ok_, eq_, set_trace 18 | 19 | from tutils import compare 20 | 21 | class test_fwrapper(object): 22 | 23 | fsrc = '''\ 24 | function empty_func() 25 | implicit none 26 | integer :: empty_func 27 | empty_func = 1 28 | end function empty_func 29 | ''' 30 | 31 | def setup(self): 32 | self.name = 'test' 33 | self.source_file_lst = [self.fsrc] 34 | 35 | 36 | 37 | 38 | def test_parse(self): 39 | ast = fwrapper.parse(self.source_file_lst) 40 | return_arg = pyf.Argument('empty_func', dtype=pyf.default_integer) 41 | empty_func = pyf.Function(name='empty_func', 42 | args=(), 43 | return_arg=return_arg) 44 | eq_(ast[0].name, empty_func.name) 45 | eq_(ast[0].return_arg.name, empty_func.return_arg.name) 46 | eq_(len(ast[0].args), len(empty_func.args)) 47 | 48 | def test_generate_fc_f(self): 49 | fort_ast = fwrapper.parse(self.source_file_lst) 50 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 51 | fname, buf = fwrapper.generate_fc_f(c_ast, self.name) 52 | fc = '''\ 53 | subroutine empty_func_c(fw_ret_arg, fw_iserr__, fw_errstr__) bind(c, name="em& 54 | &pty_func_c") 55 | use fwrap_ktp_mod 56 | implicit none 57 | integer(kind=fwi_integer_t), intent(out) :: fw_ret_arg 58 | integer(kind=fwi_integer_t), intent(out) :: fw_iserr__ 59 | character(kind=fw_character_t, len=1), dimension(fw_errstr_len) :: fw_err& 60 | &str__ 61 | interface 62 | function empty_func() 63 | use fwrap_ktp_mod 64 | implicit none 65 | integer(kind=fwi_integer_t) :: empty_func 66 | end function empty_func 67 | end interface 68 | fw_iserr__ = FW_INIT_ERR__ 69 | fw_ret_arg = empty_func() 70 | fw_iserr__ = FW_NO_ERR__ 71 | end subroutine empty_func_c 72 | ''' 73 | compare(fc, buf.getvalue()) 74 | 75 | def test_generate_fc_h(self): 76 | fort_ast = fwrapper.parse(self.source_file_lst) 77 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 78 | fname, buf = fwrapper.generate_fc_h(c_ast, self.name) 79 | header = '''\ 80 | #include "fwrap_ktp_header.h" 81 | 82 | void empty_func_c(fwi_integer_t *, fwi_integer_t *, fw_character_t *); 83 | ''' 84 | compare(buf.getvalue(), header) 85 | eq_(fname, constants.FC_HDR_TMPL % self.name) 86 | 87 | def test_generate_fc_pxd(self): 88 | fort_ast = fwrapper.parse(self.source_file_lst) 89 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 90 | fname, buf = fwrapper.generate_fc_pxd(c_ast, self.name) 91 | header = '''\ 92 | from fwrap_ktp cimport * 93 | 94 | cdef extern from "test_fc.h": 95 | void empty_func_c(fwi_integer_t *, fwi_integer_t *, fw_character_t *) 96 | ''' 97 | compare(header, buf.getvalue()) 98 | 99 | def test_generate_cy_pxd(self): 100 | fort_ast = fwrapper.parse(self.source_file_lst) 101 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 102 | cython_ast = cy_wrap.wrap_fc(c_ast) 103 | fname, buf = fwrapper.generate_cy_pxd(cython_ast, self.name) 104 | pxd = '''\ 105 | cimport numpy as np 106 | from test_fc cimport * 107 | 108 | cpdef api object empty_func() 109 | ''' 110 | compare(pxd, buf.getvalue()) 111 | 112 | def test_generate_cy_pyx(self): 113 | from fwrap.version import get_version 114 | fort_ast = fwrapper.parse(self.source_file_lst) 115 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 116 | cython_ast = cy_wrap.wrap_fc(c_ast) 117 | fname, buf = fwrapper.generate_cy_pyx(cython_ast, self.name) 118 | test_str = '''\ 119 | """ 120 | The test module was generated with Fwrap v%s. 121 | 122 | Below is a listing of functions and data types. 123 | For usage information see the function docstrings. 124 | 125 | Functions 126 | --------- 127 | empty_func(...) 128 | 129 | Data Types 130 | ---------- 131 | fw_character 132 | fwi_integer 133 | 134 | """ 135 | np.import_array() 136 | include 'fwrap_ktp.pxi' 137 | cdef extern from "string.h": 138 | void *memcpy(void *dest, void *src, size_t n) 139 | cpdef api object empty_func(): 140 | """ 141 | empty_func() -> fw_ret_arg 142 | 143 | Parameters 144 | ---------- 145 | None 146 | 147 | Returns 148 | ------- 149 | fw_ret_arg : fwi_integer, intent out 150 | 151 | """ 152 | cdef fwi_integer_t fw_ret_arg 153 | cdef fwi_integer_t fw_iserr__ 154 | cdef fw_character_t fw_errstr__[fw_errstr_len] 155 | empty_func_c(&fw_ret_arg, &fw_iserr__, fw_errstr__) 156 | if fw_iserr__ != FW_NO_ERR__: 157 | raise RuntimeError("an error was encountered when calling the 'empty_func' wrapper.") 158 | return fw_ret_arg 159 | ''' % get_version() 160 | compare(test_str, buf.getvalue()) 161 | 162 | def test_generate_type_specs(self): 163 | from cPickle import loads 164 | fort_ast = fwrapper.parse(self.source_file_lst) 165 | c_ast = fc_wrap.wrap_pyf_iface(fort_ast) 166 | cython_ast = cy_wrap.wrap_fc(c_ast) 167 | fname, buf = fwrapper.generate_type_specs(fort_ast, self.name) 168 | ctps = loads(buf.getvalue()) 169 | for ctp in ctps: 170 | ok_(isinstance(ctp, dict)) 171 | eq_(sorted(ctp.keys()), 172 | ['basetype', 'fwrap_name', 'lang', 'npy_enum', 'odecl']) 173 | -------------------------------------------------------------------------------- /fwrap/tests/test_gen_config.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import pyf_iface 7 | from fwrap import gen_config as gc 8 | from fwrap.code import CodeBuffer 9 | 10 | from nose.tools import assert_raises, ok_, eq_, set_trace 11 | 12 | from tutils import compare 13 | 14 | def mock_f2c_types(ctps, *args): 15 | mp = {'fwrap_default_integer' : 'c_int', 16 | 'fwrap_default_real' : 'c_float', 17 | 'fwrap_default_logical' : 'c_int', 18 | 'fwrap_default_complex' : 'c_float_complex', 19 | 'fwrap_default_character' : 'c_char' 20 | } 21 | for ctp in ctps: 22 | ctp.fc_type = mp[ctp.fwrap_name] 23 | 24 | class test_genconfig(object): 25 | 26 | def setup(self): 27 | self.ctps = [ 28 | gc.ConfigTypeParam(basetype="integer", 29 | odecl="integer(kind=kind(0))", 30 | fwrap_name="fwrap_default_integer", 31 | npy_enum="fwrap_default_integer_enum"), 32 | gc.ConfigTypeParam(basetype="real", 33 | odecl="real(kind=kind(0.0))", 34 | fwrap_name="fwrap_default_real", 35 | npy_enum="fwrap_default_real_enum"), 36 | gc.ConfigTypeParam(basetype="logical", 37 | odecl="logical(kind=kind(.true.))", 38 | fwrap_name="fwrap_default_logical", 39 | npy_enum="fwrap_default_logical_enum"), 40 | gc.ConfigTypeParam(basetype="complex", 41 | odecl="complex(kind=kind((0.0,0.0)))", 42 | fwrap_name="fwrap_default_complex", 43 | npy_enum="fwrap_default_complex_enum"), 44 | gc.ConfigTypeParam(basetype="character", 45 | odecl="character(kind=kind('a'))", 46 | fwrap_name="fwrap_default_character", 47 | npy_enum="fwrap_default_character_enum") 48 | ] 49 | self.int, self.real, self.log, self.cmplx, self.char = self.ctps 50 | mock_f2c_types(self.ctps) 51 | 52 | def test_gen_f_mod(self): 53 | eq_(self.int.gen_f_mod(), 54 | ['integer, parameter :: fwrap_default_integer = c_int']) 55 | eq_(self.cmplx.gen_f_mod(), 56 | ['integer, parameter :: ' 57 | 'fwrap_default_complex = c_float_complex']) 58 | 59 | def test_gen_header(self): 60 | eq_(self.int.gen_c_typedef(), ['typedef int fwrap_default_integer;']) 61 | eq_(self.cmplx.gen_c_typedef(), ['typedef float _Complex fwrap_default_complex;']) 62 | 63 | def test_gen_pxd(self): 64 | eq_(self.int.gen_pxd_extern_typedef(), 65 | ['ctypedef int fwrap_default_integer']) 66 | eq_(self.cmplx.gen_pxd_extern_typedef(), []) 67 | 68 | eq_(self.int.gen_pxd_intern_typedef(), []) 69 | eq_(self.cmplx.gen_pxd_intern_typedef(), 70 | ['ctypedef float complex fwrap_default_complex']) 71 | 72 | eq_(self.int.gen_pxd_extern_extra(), []) 73 | eq_(self.cmplx.gen_pxd_extern_extra(), []) 74 | 75 | def test_gen_type_spec(self): 76 | 77 | def _compare(ctp_dict, ctp): 78 | cd = ctp_dict 79 | x_ = gc.ConfigTypeParam(cd['basetype'], 80 | cd['odecl'], cd['fwrap_name'], cd['npy_enum']) 81 | eq_(x_,y) 82 | 83 | from cPickle import loads 84 | buf = CodeBuffer() 85 | gc._generate_type_specs(self.ctps[:2], buf) 86 | ctps = loads(buf.getvalue()) 87 | for x,y in zip(ctps, self.ctps[:2]): 88 | _compare(x,y) 89 | 90 | buf = CodeBuffer() 91 | gc._generate_type_specs(self.ctps[2:], buf) 92 | ctps = loads(buf.getvalue()) 93 | for x,y in zip(ctps, self.ctps[2:]): 94 | _compare(x,y) 95 | -------------------------------------------------------------------------------- /fwrap/tests/test_parameters.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import pyf_iface as pyf 7 | 8 | from nose.tools import eq_, ok_ 9 | 10 | class test_parameter(object): 11 | 12 | def setup(self): 13 | self.lit_int = pyf.Parameter('int_param', 14 | dtype=pyf.default_integer, expr="10+20") 15 | self.var_param = pyf.Parameter("var_param", 16 | dtype=pyf.default_integer, expr="int_param + 30") 17 | self.call_func = pyf.Parameter("call_func", 18 | dtype=pyf.default_integer, expr="selected_int_kind(10)") 19 | 20 | def test_depends(self): 21 | eq_(self.lit_int.depends(), set()) 22 | eq_(self.var_param.depends(), set(["int_param"])) 23 | eq_(self.call_func.depends(), set([])) 24 | 25 | class test_proc_params(object): 26 | 27 | def setup(self): 28 | self.lit_int = pyf.Parameter("lit_int", 29 | dtype=pyf.default_integer, expr="30-10") 30 | self.sik = pyf.Parameter("sik_10", 31 | dtype=pyf.default_integer, expr="selected_int_kind(10)") 32 | self.srk = pyf.Parameter( 33 | "srk_10_20", 34 | dtype=pyf.default_integer, 35 | expr="selected_real_kind(10, lit_int)") 36 | srk_real = pyf.RealType("srk_10_20", kind="srk_10_20") 37 | self.real_arg = pyf.Argument("real_arg", 38 | dtype=srk_real, intent='inout') 39 | sik_int = pyf.IntegerType("sik_10", kind="sik_10") 40 | self.int_arg = pyf.Argument("int_arg", 41 | dtype=sik_int, dimension=[("lit_int",)]) 42 | subr = pyf.Subroutine( 43 | name="subr", 44 | args=[self.real_arg, self.int_arg], 45 | params=[self.lit_int, self.sik, self.srk]) 46 | self.ret_arg = pyf.Argument("func", dtype=srk_real) 47 | func = pyf.Function( 48 | name="func", 49 | args=[self.real_arg, self.int_arg], 50 | params=[self.lit_int, self.sik, self.srk], 51 | return_arg=self.ret_arg) 52 | self.args = [self.real_arg, self.int_arg] 53 | self.params = [self.lit_int, self.sik, self.srk] 54 | 55 | def test_arg_man(self): 56 | sub_am = pyf.ArgManager(args=self.args, params=self.params) 57 | func_am = pyf.ArgManager(args=self.args, 58 | return_arg=self.ret_arg, params=self.params) 59 | eq_(sub_am.arg_declarations(), 60 | ['integer(kind=fwi_integer_t), ' 61 | 'parameter :: lit_int = 30-10', 62 | 'integer(kind=fwi_integer_t), ' 63 | 'parameter :: sik_10 = selected_int_kind(10)', 64 | 'integer(kind=fwi_integer_t), ' 65 | 'parameter :: srk_10_20 = ' 66 | 'selected_real_kind(10, lit_int)', 67 | 'real(kind=fwr_srk_10_20_t), ' 68 | 'intent(inout) :: real_arg', 69 | 'integer(kind=fwi_sik_10_t), ' 70 | 'dimension(lit_int) :: int_arg']) 71 | 72 | def test_unneeded_param(self): 73 | unp = pyf.Parameter("unneeded", dtype=pyf.default_integer, expr="srk_10_20 + lit_int") 74 | sub_am = pyf.ArgManager(args=self.args, params=self.params+[unp]) 75 | eq_(sub_am.arg_declarations(), 76 | ['integer(kind=fwi_integer_t), ' 77 | 'parameter :: lit_int = 30-10', 78 | 'integer(kind=fwi_integer_t), ' 79 | 'parameter :: sik_10 = selected_int_kind(10)', 80 | 'integer(kind=fwi_integer_t), ' 81 | 'parameter :: srk_10_20 = ' 82 | 'selected_real_kind(10, lit_int)', 83 | 'real(kind=fwr_srk_10_20_t), ' 84 | 'intent(inout) :: real_arg', 85 | 'integer(kind=fwi_sik_10_t), ' 86 | 'dimension(lit_int) :: int_arg']) 87 | -------------------------------------------------------------------------------- /fwrap/tests/test_pyf_iface.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from fwrap import pyf_iface as pyf 7 | from nose.tools import ok_, eq_, set_trace, assert_raises, raises 8 | 9 | class test_dtype_selector(object): 10 | 11 | def test_create(self): 12 | real_star = pyf.RealType("real_star", length="8") 13 | eq_(real_star.odecl, "real*8") 14 | 15 | class test_program_units(object): 16 | def test_function(self): 17 | return_arg = pyf.Argument('fort_function', dtype=pyf.default_integer) 18 | ffun = pyf.Function(name="fort_function", 19 | args=(), 20 | return_arg=return_arg) 21 | ok_(ffun.name == 'fort_function') 22 | ok_(ffun.return_arg.dtype is pyf.default_integer) 23 | 24 | def test_function_args(self): 25 | name = 'ffun' 26 | return_arg = pyf.Argument(name, dtype=pyf.default_integer) 27 | pyf.Function(name=name, 28 | args=(pyf.Argument('a', dtype=pyf.default_integer),), 29 | return_arg=return_arg) 30 | 31 | def test_subroutine(self): 32 | pyf.Subroutine(name='subr', 33 | args=()) 34 | 35 | def test_module(self): 36 | pyf.Module(name='mod') 37 | 38 | def test_module_use(self): 39 | mod1 = pyf.Module( 40 | name='mod1', 41 | mod_objects=[ 42 | pyf.Var(name='i', dtype=pyf.default_integer), 43 | pyf.Var(name='r', dtype=pyf.default_real), 44 | pyf.Var(name='c', dtype=pyf.default_complex), 45 | ] 46 | ) 47 | 48 | pyf.Module( 49 | name='mod', 50 | uses=[ 51 | pyf.Use(mod1, only=('i', 'r')), 52 | ] 53 | ) 54 | 55 | def test_func_return_array(): 56 | args = [pyf.Argument(name='a', dtype=pyf.default_integer, intent='in'), 57 | pyf.Argument(name='b', dtype=pyf.default_integer, intent='in')] 58 | return_arg = pyf.Argument(name="arr_fun", 59 | dtype=pyf.default_real, 60 | dimension=('a', 'b')) 61 | arrfun = pyf.Function(name="arr_fun", 62 | args=args, 63 | return_arg=return_arg) 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | def test_valid_proc_name(): 72 | ok_(pyf.Procedure('name', ())) 73 | assert_raises(pyf.InvalidNameException, pyf.Procedure, '_a', ()) 74 | 75 | def test_valid_arg_name(): 76 | ok_(pyf.Argument('name', pyf.default_integer)) 77 | assert_raises(pyf.InvalidNameException, 78 | pyf.Argument, '_a', pyf.default_integer) 79 | 80 | class test_arg_manager(object): 81 | 82 | def test_declaration_order(self): 83 | array_arg = pyf.Argument('arr', 84 | pyf.default_integer, 'in', dimension=('d1', 'd2')) 85 | d1 = pyf.Argument('d1', pyf.default_integer, 'in') 86 | d2 = pyf.Argument('d2', pyf.default_integer, 'in') 87 | am = pyf.ArgManager([array_arg, d2, d1]) 88 | decls = '''\ 89 | integer(kind=fwi_integer_t), intent(in) :: d2 90 | integer(kind=fwi_integer_t), intent(in) :: d1 91 | integer(kind=fwi_integer_t), dimension(d1, d2), intent(in) :: arr 92 | ''' 93 | eq_(am.arg_declarations(), decls.splitlines()) 94 | 95 | def test_parameter(): 96 | param = pyf.Parameter(name='FOO', 97 | dtype=pyf.default_integer, expr='kind(1.0D0)') 98 | arg = pyf.Argument(name="fooarg", 99 | dtype=pyf.RealType("foo_real", kind="FOO"), 100 | intent="inout") 101 | subr = pyf.Subroutine(name="foosubr", 102 | args=[arg], 103 | params=[param]) 104 | 105 | def test_dtype(): 106 | assert_raises(pyf.InvalidNameException, 107 | pyf.IntegerType, 'selected_int_kind(10)') 108 | assert_raises(pyf.InvalidNameException, 109 | pyf.RealType, 'selected_real_kind(10)') 110 | 111 | def test_valid_fort_name(): 112 | ok_(pyf.valid_fort_name('F12_bar')) 113 | ok_(pyf.valid_fort_name('a'*63)) 114 | ok_(not pyf.valid_fort_name('a'*64)) 115 | ok_(not pyf.valid_fort_name('_a')) 116 | ok_(not pyf.valid_fort_name('1a')) 117 | ok_(not pyf.valid_fort_name(' a')) 118 | -------------------------------------------------------------------------------- /fwrap/tests/tutils.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from nose.tools import eq_ 7 | 8 | def remove_common_indent(s): 9 | if not s: 10 | return s 11 | lines_ = s.splitlines() 12 | 13 | # remove spaces from ws lines 14 | lines = [] 15 | for line in lines_: 16 | if line.rstrip(): 17 | lines.append(line.rstrip()) 18 | else: 19 | lines.append("") 20 | 21 | fst_line = None 22 | for line in lines: 23 | if line: 24 | fst_line = line 25 | break 26 | 27 | ws_count = 0 28 | for ch in fst_line: 29 | if ch == ' ': 30 | ws_count += 1 31 | else: 32 | break 33 | 34 | if not ws_count: return s 35 | 36 | ret = [] 37 | for line in lines: 38 | line = line.rstrip() 39 | if line: 40 | assert line.startswith(' '*ws_count) 41 | ret.append(line[ws_count:]) 42 | else: 43 | ret.append('') 44 | return '\n'.join(ret) 45 | 46 | def compare(s1, s2): 47 | ss1 = remove_common_indent(s1.rstrip()) 48 | ss2 = remove_common_indent(s2.rstrip()) 49 | for idx, lines in enumerate(zip(ss1.splitlines(), ss2.splitlines())): 50 | L1, L2 = lines 51 | assert L1 == L2, "\n%s\n != \n%s\nat line %d: '%s' != '%s'" % (ss1, ss2, idx, L1, L2) 52 | -------------------------------------------------------------------------------- /fwrap/version.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | import os 7 | from os import path 8 | 9 | # Set isrelease = True for release version. 10 | isrelease = False 11 | base_version = "0.2.0" 12 | 13 | def get_version(): 14 | 15 | if isrelease: return base_version 16 | 17 | from subprocess import Popen, PIPE 18 | git_dir = path.join(path.dirname(path.dirname(__file__)), '.git') 19 | cmd = "git --git-dir=%s rev-parse --short HEAD" % git_dir 20 | try: 21 | pp = Popen(cmd.split(), stdout=PIPE, stderr=PIPE) 22 | pp.wait() 23 | global_id = pp.stdout.read().strip() 24 | err_txt = pp.stderr.read() 25 | except OSError: 26 | global_id = "unknown" 27 | return "%sdev_%s" % (base_version, global_id) 28 | -------------------------------------------------------------------------------- /fwrapc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | #------------------------------------------------------------------------------ 4 | # Copyright (c) 2010, Kurt W. Smith 5 | # 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, 12 | # this list of conditions and the following disclaimer. 13 | # * Redistributions in binary form must reproduce the above copyright 14 | # notice, this list of conditions and the following disclaimer in the 15 | # documentation and/or other materials provided with the distribution. 16 | # * Neither the name of the Fwrap project nor the names of its contributors 17 | # may be used to endorse or promote products derived from this software 18 | # without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | # POSSIBILITY OF SUCH DAMAGE. 31 | #------------------------------------------------------------------------------ 32 | 33 | import sys 34 | from fwrap.fwrapc import fwrapc 35 | 36 | sys.exit(fwrapc(sys.argv[1:])) 37 | -------------------------------------------------------------------------------- /fwrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | #------------------------------------------------------------------------------ 4 | # Copyright (c) 2010, Kurt W. Smith 5 | # 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without 9 | # modification, are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, 12 | # this list of conditions and the following disclaimer. 13 | # * Redistributions in binary form must reproduce the above copyright 14 | # notice, this list of conditions and the following disclaimer in the 15 | # documentation and/or other materials provided with the distribution. 16 | # * Neither the name of the Fwrap project nor the names of its contributors 17 | # may be used to endorse or promote products derived from this software 18 | # without specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | # POSSIBILITY OF SUCH DAMAGE. 31 | #------------------------------------------------------------------------------ 32 | 33 | import sys 34 | from fwrap.fwrapper import fwrapper 35 | 36 | sys.exit(fwrapper(use_cmdline=True)) 37 | -------------------------------------------------------------------------------- /runnose.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | from subprocess import call 7 | import sys 8 | 9 | call(("%s/bin/nosetests -s fwrap/tests" % sys.exec_prefix).split()) 10 | -------------------------------------------------------------------------------- /runtests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os, sys, re, shutil, unittest, doctest 4 | 5 | WITH_CYTHON = True 6 | 7 | TEST_DIRS = ['compile', 'errors', 'run', 'pyregr'] 8 | TEST_RUN_DIRS = ['run', 'pyregr'] 9 | 10 | class FwrapTestBuilder(object): 11 | def __init__(self, rootdir, workdir, selectors, exclude_selectors, 12 | cleanup_workdir, cleanup_sharedlibs, verbosity=0): 13 | self.rootdir = rootdir 14 | self.workdir = workdir 15 | self.selectors = selectors 16 | self.exclude_selectors = exclude_selectors 17 | self.cleanup_workdir = cleanup_workdir 18 | self.cleanup_sharedlibs = cleanup_sharedlibs 19 | self.verbosity = verbosity 20 | 21 | def build_suite(self): 22 | suite = unittest.TestSuite() 23 | test_dirs = TEST_DIRS 24 | filenames = os.listdir(self.rootdir) 25 | filenames.sort() 26 | for filename in filenames: 27 | path = os.path.join(self.rootdir, filename) 28 | if os.path.isdir(path) and filename in test_dirs: 29 | suite.addTest( 30 | self.handle_directory(path, filename)) 31 | return suite 32 | 33 | def handle_directory(self, path, context): 34 | workdir = os.path.join(self.workdir, context) 35 | if not os.path.exists(workdir): 36 | os.makedirs(workdir) 37 | 38 | suite = unittest.TestSuite() 39 | filenames = os.listdir(path) 40 | filenames.sort() 41 | for filename in filenames: 42 | if os.path.splitext(filename)[1].lower() not in (".f", ".f77", ".f90", ".f95"): 43 | continue 44 | if filename.startswith('.'): continue # certain emacs backup files 45 | basename = os.path.splitext(filename)[0] 46 | fqbasename = "%s.%s" % (context, basename) 47 | if not [1 for match in self.selectors if match(fqbasename)]: 48 | continue 49 | if self.exclude_selectors: 50 | if [1 for match in self.exclude_selectors if match(fqbasename)]: 51 | continue 52 | if context in TEST_RUN_DIRS: 53 | test_class = FwrapRunTestCase 54 | else: 55 | test_class = FwrapCompileTestCase 56 | suite.addTest(self.build_test(test_class, path, workdir, filename)) 57 | return suite 58 | 59 | def build_test(self, test_class, path, workdir, filename): 60 | return test_class(path, workdir, filename, 61 | cleanup_workdir=self.cleanup_workdir, 62 | cleanup_sharedlibs=self.cleanup_sharedlibs, 63 | verbosity=self.verbosity) 64 | 65 | class _devnull(object): 66 | 67 | def flush(self): pass 68 | def write(self, s): pass 69 | 70 | def read(self): return '' 71 | 72 | 73 | class FwrapCompileTestCase(unittest.TestCase): 74 | def __init__(self, directory, workdir, filename, 75 | cleanup_workdir=True, cleanup_sharedlibs=True, 76 | verbosity=0): 77 | self.directory = directory 78 | self.workdir = workdir 79 | self.filename = filename 80 | self.cleanup_workdir = cleanup_workdir 81 | self.cleanup_sharedlibs = cleanup_sharedlibs 82 | self.verbosity = verbosity 83 | unittest.TestCase.__init__(self) 84 | 85 | def shortDescription(self): 86 | return "wrapping %s" % self.filename 87 | 88 | def setUp(self): 89 | if self.workdir not in sys.path: 90 | sys.path.insert(0, self.workdir) 91 | 92 | def tearDown(self): 93 | try: 94 | sys.path.remove(self.workdir) 95 | except ValueError: 96 | pass 97 | if os.path.exists(self.workdir): 98 | if self.cleanup_workdir: 99 | for rmfile in os.listdir(self.workdir): 100 | try: 101 | rmfile = os.path.join(self.workdir, rmfile) 102 | if os.path.isdir(rmfile): 103 | shutil.rmtree(rmfile, ignore_errors=True) 104 | else: 105 | os.remove(rmfile) 106 | except IOError: 107 | pass 108 | else: 109 | os.makedirs(self.workdirs) 110 | 111 | def runTest(self): 112 | # fwrapc.py configure build fsrc... 113 | self.projname = os.path.splitext(self.filename)[0] + '_fwrap' 114 | self.projdir = os.path.join(self.workdir, self.projname) 115 | fq_fname = os.path.join(os.path.abspath(self.directory), self.filename) 116 | argv = ['configure', 'build', 117 | '--name=%s' % self.projname, 118 | '--outdir=%s' % self.projdir, 119 | fq_fname, 120 | 'install'] 121 | fwrapc(argv=argv) 122 | 123 | def compile(self, directory, filename, workdir, incdir): 124 | self.run_wrapper(directory, filename, workdir, incdir) 125 | 126 | def run_wrapper(self, directory, filename, workdir, incdir): 127 | wrap(filename, directory, workdir) 128 | 129 | 130 | class FwrapRunTestCase(FwrapCompileTestCase): 131 | def shortDescription(self): 132 | return "compiling and running %s" % self.filename 133 | 134 | def run(self, result=None): 135 | if result is None: 136 | result = self.defaultTestResult() 137 | result.startTest(self) 138 | try: 139 | self.setUp() 140 | self.runTest() 141 | if self.projdir not in sys.path: 142 | sys.path.insert(0, self.projdir) 143 | doctest_mod_base = self.projname+'_doctest' 144 | doctest_mod_fqpath = os.path.join(self.directory, doctest_mod_base+'.py') 145 | shutil.copy(doctest_mod_fqpath, self.projdir) 146 | doctest.DocTestSuite(self.projname+'_doctest').run(result) #?? 147 | except Exception: 148 | result.addError(self, sys.exc_info()) 149 | result.stopTest(self) 150 | try: 151 | self.tearDown() 152 | except Exception: 153 | pass 154 | 155 | 156 | class FileListExcluder: 157 | 158 | def __init__(self, list_file): 159 | self.excludes = {} 160 | for line in open(list_file).readlines(): 161 | line = line.strip() 162 | if line and line[0] != '#': 163 | self.excludes[line.split()[0]] = True 164 | 165 | def __call__(self, testname): 166 | return testname.split('.')[-1] in self.excludes 167 | 168 | if __name__ == '__main__': 169 | from optparse import OptionParser 170 | parser = OptionParser() 171 | parser.add_option("--no-cleanup", dest="cleanup_workdir", 172 | action="store_false", default=True, 173 | help="do not delete the generated C files (allows passing --no-cython on next run)") 174 | parser.add_option("--no-cleanup-sharedlibs", dest="cleanup_sharedlibs", 175 | action="store_false", default=True, 176 | help="do not delete the generated shared libary files (allows manual module experimentation)") 177 | parser.add_option("-x", "--exclude", dest="exclude", 178 | action="append", metavar="PATTERN", 179 | help="exclude tests matching the PATTERN") 180 | parser.add_option("-v", "--verbose", dest="verbosity", 181 | action="count", 182 | default=0, 183 | help="display test progress, more v's for more output") 184 | parser.add_option("-T", "--ticket", dest="tickets", 185 | action="append", 186 | help="a bug ticket number to run the respective test in 'tests/bugs'") 187 | 188 | options, cmd_args = parser.parse_args() 189 | 190 | 191 | # RUN ALL TESTS! 192 | ROOTDIR = os.path.join(os.getcwd(), os.path.dirname(sys.argv[0]), 'tests') 193 | WORKDIR = os.path.join(os.getcwd(), 'BUILD') 194 | if os.path.exists(WORKDIR): 195 | for path in os.listdir(WORKDIR): 196 | if path in ("support",): continue 197 | shutil.rmtree(os.path.join(WORKDIR, path), ignore_errors=True) 198 | if not os.path.exists(WORKDIR): 199 | os.makedirs(WORKDIR) 200 | 201 | from fwrap.fwrapc import fwrapc 202 | 203 | sys.stderr.write("Python %s\n" % sys.version) 204 | sys.stderr.write("\n") 205 | 206 | # insert cython.py/Cython source directory into sys.path 207 | cython_dir = os.path.abspath(os.path.join(os.path.pardir, os.path.pardir)) 208 | sys.path.insert(0, cython_dir) 209 | 210 | test_bugs = False 211 | if options.tickets: 212 | for ticket_number in options.tickets: 213 | test_bugs = True 214 | cmd_args.append('.*T%s$' % ticket_number) 215 | if not test_bugs: 216 | for selector in cmd_args: 217 | if selector.startswith('bugs'): 218 | test_bugs = True 219 | 220 | selectors = [ re.compile(r, re.I|re.U).search for r in cmd_args ] 221 | if not selectors: 222 | selectors = [ lambda x:True ] 223 | 224 | # Check which external modules are not present and exclude tests 225 | # which depends on them (by prefix) 226 | 227 | exclude_selectors = [] 228 | 229 | if options.exclude: 230 | exclude_selectors += [ re.compile(r, re.I|re.U).search for r in options.exclude ] 231 | 232 | if not test_bugs: 233 | exclude_selectors += [ FileListExcluder("tests/bugs.txt") ] 234 | 235 | test_suite = unittest.TestSuite() 236 | 237 | filetests = FwrapTestBuilder(ROOTDIR, WORKDIR, selectors, exclude_selectors, 238 | options.cleanup_workdir, options.cleanup_sharedlibs, options.verbosity) 239 | test_suite.addTest(filetests.build_suite()) 240 | 241 | unittest.TextTestRunner(verbosity=options.verbosity).run(test_suite) 242 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Copyright (c) 2010, Kurt W. Smith 3 | # All rights reserved. See LICENSE.txt. 4 | #------------------------------------------------------------------------------ 5 | 6 | import os 7 | from distutils.core import setup 8 | 9 | scripts = [] 10 | 11 | scripts = ['fwrapc.py', 'fwrapper.py'] 12 | 13 | from fwrap.version import get_version 14 | 15 | setup(name="fwrap", 16 | version=get_version(), 17 | description="Tool to wrap Fortran 77/90/95 code in C, Cython & Python.", 18 | author="Kurt W. Smith & contributors", 19 | author_email="kwmsmith@gmail.com", 20 | url="http://fwrap.sourceforge.net/", 21 | packages=[ 22 | "fwrap", 23 | "fwrap.fparser" 24 | ], 25 | package_data = { 26 | "fwrap" : ["default.config", "log.config"], 27 | "fwrap.fparser" : ["log.config"], 28 | }, 29 | scripts=scripts, 30 | classifiers = [ 31 | "Development Status :: 4 - Beta", 32 | "Intended Audience :: Developers", 33 | "Intended Audience :: Science/Research", 34 | "License :: OSI Approved :: BSD License", 35 | "Operating System :: OS Independent", 36 | "Programming Language :: Python", 37 | "Programming Language :: Python :: 2", 38 | "Programming Language :: Fortran", 39 | "Programming Language :: C", 40 | "Programming Language :: Cython", 41 | "Topic :: Software Development :: Code Generators", 42 | "Topic :: Software Development :: Libraries :: Python Modules" 43 | ], 44 | ) 45 | -------------------------------------------------------------------------------- /tests/bugs.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kwmsmith/fwrap/f2e20eb55eaa3de72905e2ef28198da00eebe262/tests/bugs.txt -------------------------------------------------------------------------------- /tests/compile/all_char.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | subroutine char_arg(ch, ch_in) 4 | implicit none 5 | character(len=20) :: ch 6 | character(*) :: ch_in 7 | 8 | ch = ch_in 9 | 10 | end subroutine char_arg 11 | 12 | subroutine char_star(ch, ch_in, ch_out, ch_inout) 13 | implicit none 14 | character(*) ch 15 | character(len=*), intent(in) :: ch_in 16 | character(*), intent(out) :: ch_out 17 | character(*), intent(inout) :: ch_inout 18 | 19 | ch = ch_in 20 | 21 | ch_out = ch_inout 22 | 23 | end subroutine char_star 24 | 25 | subroutine char_len_x(ch, ch_in, ch_out, ch_inout) 26 | implicit none 27 | character*20 :: ch 28 | character*10, intent(in) :: ch_in 29 | character(len=5), intent(out) :: ch_out 30 | character(len=1), intent(inout) :: ch_inout 31 | 32 | ch_inout = ch(2:2) 33 | ch_out = ch_in(1:5) 34 | ch = ch_in // ch_out // ch_out 35 | 36 | end subroutine char_len_x 37 | -------------------------------------------------------------------------------- /tests/compile/char_args.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | subroutine char_args(ch, ch_in, ch_inout, ch_out) 4 | implicit none 5 | character*20 ch 6 | character(30), intent(in) :: ch_in 7 | character(len=10), intent(inout) :: ch_inout 8 | character(len=10), intent(out) :: ch_out 9 | 10 | ch = ch_in(1:19) 11 | ch_inout = ch_in(21:30) 12 | ch_out = ch_in(15:24) 13 | 14 | end subroutine char_args 15 | -------------------------------------------------------------------------------- /tests/compile/cmplx_array.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | subroutine complex_array(c) 4 | implicit none 5 | complex(kind=8), dimension(:,:), intent(inout) :: c 6 | 7 | c = cmplx(1, 2) 8 | 9 | end subroutine complex_array 10 | -------------------------------------------------------------------------------- /tests/compile/default_types.f90: -------------------------------------------------------------------------------- 1 | subroutine bar(a,b,d) 2 | implicit none 3 | integer :: a 4 | real :: b 5 | ! complex :: c 6 | double precision :: d 7 | ! logical :: e 8 | ! character :: f 9 | a = 1 10 | b = 2.0 11 | d = 3.0 12 | end subroutine bar 13 | -------------------------------------------------------------------------------- /tests/compile/int_args.f90: -------------------------------------------------------------------------------- 1 | 2 | function int_args_func(a,b,c,d) 3 | integer(kind=8) :: int_args_func 4 | integer(kind=1), intent(in) :: a 5 | integer(kind=2), intent(in) :: b 6 | integer(kind=4), intent(in) :: c 7 | integer(kind=8), intent(out) :: d 8 | 9 | d = a + b + c 10 | int_args_func = 10 11 | 12 | end function int_args_func 13 | 14 | subroutine int_args_subr(a,b,c,d) 15 | integer(kind=1), intent(in) :: a 16 | integer(kind=2), intent(in) :: b 17 | integer(kind=4), intent(in) :: c 18 | integer(kind=8), intent(out) :: d 19 | 20 | d = a + b + c 21 | 22 | end subroutine int_args_subr 23 | 24 | ! module dummy 25 | ! use iso_c_binding 26 | ! use kind_type_params 27 | ! integer, parameter :: fortran_int_1 = c_signed_char 28 | 29 | ! contains 30 | 31 | ! subroutine int_args_subr_wrap(a,b,c,d) bind(c,name="int_args_subr") 32 | ! implicit none 33 | ! integer(kind=fortran_int_1), intent(in) :: a 34 | ! integer(kind=c_short), intent(in) :: b 35 | ! integer(kind=c_int), intent(in) :: c 36 | ! integer(kind=c_int64_t), intent(out) :: d 37 | ! ! integer(kind=c_long), intent(in) :: a 38 | ! ! integer(kind=c_long), intent(in) :: b 39 | ! ! integer(kind=c_long), intent(in) :: c 40 | ! ! integer(kind=c_long), intent(out) :: d 41 | 42 | ! ! integer(kind=1) :: convert_a 43 | ! ! integer(kind=2) :: convert_b 44 | ! ! integer(kind=4) :: convert_c 45 | ! ! integer(kind=8) :: convert_d 46 | 47 | ! interface 48 | ! subroutine int_args_subr(a,b,c,d) 49 | ! use kind_type_params 50 | ! integer(kind=1), intent(in) :: a 51 | ! integer(kind=2), intent(in) :: b 52 | ! integer(kind=4), intent(in) :: c 53 | ! integer(kind=sik10), intent(out) :: d 54 | ! end subroutine int_args_subr 55 | ! end interface 56 | 57 | ! print *, "before call in wrapper in fortran" 58 | ! print *, a,b,c,d 59 | 60 | ! ! convert_a = a 61 | ! ! convert_b = b 62 | ! ! convert_c = c 63 | ! ! convert_d = d 64 | 65 | ! print *, "before call in wrapper in fortran, converted vals." 66 | ! print *, convert_a, convert_b, convert_c, convert_d 67 | 68 | ! ! call int_args_subr(convert_a,convert_b,convert_c,convert_d) 69 | ! call int_args_subr(a,b,c,d) 70 | 71 | ! ! d = convert_d 72 | 73 | ! ! print *, "after call in wrapper in fortran, converted vals." 74 | ! ! print *, convert_a, convert_b, convert_c, convert_d 75 | 76 | ! end subroutine int_args_subr_wrap 77 | ! end module dummy 78 | 79 | ! program blargh 80 | ! use dummy 81 | ! integer(kind=1) :: a 82 | ! integer(kind=2) :: b 83 | ! integer(kind=4) :: c 84 | ! integer(kind=8) :: d 85 | ! ! integer(kind=8) :: a 86 | ! ! integer(kind=8) :: b 87 | ! ! integer(kind=8) :: c 88 | ! ! integer(kind=8) :: d 89 | ! a = 1; b = 2; c = 3; d = 4 90 | ! call int_args_subr_wrap(a,b,c,d) 91 | ! print *, a,b,c,d 92 | ! end program blargh 93 | 94 | ! ==================== 95 | ! integer types 96 | ! -------------------- 97 | 98 | ! c_int 4 99 | ! c_short 2 100 | ! c_long 8 101 | ! c_long_long 8 102 | ! c_signed_char 1 103 | ! c_size_t 8 104 | ! c_int8_t 1 105 | ! c_int16_t 2 106 | ! c_int32_t 4 107 | ! c_int64_t 8 108 | ! c_int_least8_t 1 109 | ! c_int_least16_t 2 110 | ! c_int_least32_t 4 111 | ! c_int_least64_t 8 112 | ! c_int_fast8_t -2 113 | ! c_int_fast16_t -2 114 | ! c_int_fast32_t -2 115 | ! c_int_fast64_t -2 116 | ! c_intmax_t 8 117 | ! c_intptr_t 8 118 | 119 | ! ==================== 120 | ! real types 121 | ! -------------------- 122 | 123 | ! c_float 4 124 | ! c_double 8 125 | ! c_long_double 10 126 | 127 | ! ==================== 128 | ! complex types 129 | ! -------------------- 130 | 131 | ! c_float_complex 4 132 | ! c_double_complex 8 133 | ! c_long_double_complex 10 134 | 135 | ! ==================== 136 | ! logical types 137 | ! -------------------- 138 | 139 | ! c_bool 1 140 | 141 | ! ==================== 142 | ! character types 143 | ! -------------------- 144 | 145 | ! c_char 1 146 | 147 | ! module kind_type_params 148 | ! implicit none 149 | ! integer, parameter :: sik10 = selected_int_kind(10) 150 | 151 | ! end module kind_type_params 152 | -------------------------------------------------------------------------------- /tests/compile/intargs_stuff/drive_int_args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void *int_args_subr(signed char *, short *, int *, long *); 4 | long int_args_func(signed char *, short *, int *, long *); 5 | 6 | int main(int argc, char **argv) { 7 | 8 | signed char a = 1; 9 | short b = 2; 10 | int c = 4; 11 | long d = 8; 12 | long result = 0; 13 | 14 | printf("before subr call in c\n"); 15 | printf("%hhd %hd %d %ld\n", a,b,c,d); 16 | int_args_subr(&a, &b, &c, &d); 17 | printf("after subr call in c\n"); 18 | printf("%hhd %hd %d %ld\n", a,b,c,d); 19 | 20 | printf("before func call in c\n"); 21 | printf("%hhd %hd %d %ld\n", a,b,c,d); 22 | result = int_args_func(&a, &b, &c, &d); 23 | printf("after func call in c\n"); 24 | printf("%hhd %hd %d %ld result=%ld\n", a,b,c,d, result); 25 | 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /tests/compile/intargs_stuff/wrap_int_args.f95: -------------------------------------------------------------------------------- 1 | subroutine wrapsubr_int_args_subr(a,b,c,d) bind(c,name="int_args_subr") 2 | use iso_c_binding 3 | implicit none 4 | integer(kind=c_signed_char), intent(in) :: a 5 | integer(kind=c_short), intent(in) :: b 6 | integer(kind=c_int), intent(in) :: c 7 | integer(kind=c_long), intent(out) :: d 8 | 9 | interface 10 | subroutine int_args_subr(a,b,c,d) 11 | integer(kind=1), intent(in) :: a 12 | integer(kind=2), intent(in) :: b 13 | integer(kind=4), intent(in) :: c 14 | integer(kind=8), intent(out) :: d 15 | end subroutine int_args_subr 16 | end interface 17 | 18 | call int_args_subr(a,b,c,d) 19 | end subroutine wrapsubr_int_args_subr 20 | 21 | function wrapfunc_int_args_func(a,b,c,d) bind(c,name="int_args_func") 22 | use iso_c_binding 23 | implicit none 24 | integer(kind=c_long) :: wrapfunc_int_args_func 25 | integer(kind=c_signed_char), intent(in) :: a 26 | integer(kind=c_short), intent(in) :: b 27 | integer(kind=c_int), intent(in) :: c 28 | integer(kind=c_long), intent(out) :: d 29 | 30 | interface 31 | function int_args_func(a,b,c,d) 32 | integer(kind=8) :: int_args_func 33 | integer(kind=1), intent(in) :: a 34 | integer(kind=2), intent(in) :: b 35 | integer(kind=4), intent(in) :: c 36 | integer(kind=8), intent(out) :: d 37 | end function int_args_func 38 | end interface 39 | 40 | wrapfunc_int_args_func = int_args_func(a,b,c,d) 41 | end function wrapfunc_int_args_func 42 | 43 | ! module dummy 44 | ! use iso_c_binding 45 | ! use kind_type_params 46 | ! integer, parameter :: fortran_int_1 = c_signed_char 47 | 48 | ! contains 49 | 50 | ! subroutine int_args_subr_wrap(a,b,c,d) bind(c,name="int_args_subr") 51 | ! implicit none 52 | ! integer(kind=fortran_int_1), intent(in) :: a 53 | ! integer(kind=c_short), intent(in) :: b 54 | ! integer(kind=c_int), intent(in) :: c 55 | ! integer(kind=c_int64_t), intent(out) :: d 56 | ! ! integer(kind=c_long), intent(in) :: a 57 | ! ! integer(kind=c_long), intent(in) :: b 58 | ! ! integer(kind=c_long), intent(in) :: c 59 | ! ! integer(kind=c_long), intent(out) :: d 60 | 61 | ! ! integer(kind=1) :: convert_a 62 | ! ! integer(kind=2) :: convert_b 63 | ! ! integer(kind=4) :: convert_c 64 | ! ! integer(kind=8) :: convert_d 65 | 66 | ! interface 67 | ! subroutine int_args_subr(a,b,c,d) 68 | ! use kind_type_params 69 | ! integer(kind=1), intent(in) :: a 70 | ! integer(kind=2), intent(in) :: b 71 | ! integer(kind=4), intent(in) :: c 72 | ! integer(kind=sik10), intent(out) :: d 73 | ! end subroutine int_args_subr 74 | ! end interface 75 | 76 | ! print *, "before call in wrapper in fortran" 77 | ! print *, a,b,c,d 78 | 79 | ! ! convert_a = a 80 | ! ! convert_b = b 81 | ! ! convert_c = c 82 | ! ! convert_d = d 83 | 84 | ! print *, "before call in wrapper in fortran, converted vals." 85 | ! print *, convert_a, convert_b, convert_c, convert_d 86 | 87 | ! ! call int_args_subr(convert_a,convert_b,convert_c,convert_d) 88 | ! call int_args_subr(a,b,c,d) 89 | 90 | ! ! d = convert_d 91 | 92 | ! ! print *, "after call in wrapper in fortran, converted vals." 93 | ! ! print *, convert_a, convert_b, convert_c, convert_d 94 | 95 | ! end subroutine int_args_subr_wrap 96 | ! end module dummy 97 | -------------------------------------------------------------------------------- /tests/compile/many_args.f90: -------------------------------------------------------------------------------- 1 | subroutine many_args(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a20, a21, a22,& 2 | a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37,& 3 | a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49) 4 | implicit none 5 | integer, intent(in) :: a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a20, a21, a22,& 6 | a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37,& 7 | a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49 8 | end subroutine many_args 9 | -------------------------------------------------------------------------------- /tests/compile/old_decl.f90: -------------------------------------------------------------------------------- 1 | subroutine bar(a,b,c,d,e,f) 2 | implicit none 3 | integer*4, intent(inout) :: a 4 | real*4, intent(inout) :: b,c 5 | real*8, intent(inout) :: d 6 | integer*8, intent(inout) :: e 7 | double precision, intent(inout) :: f 8 | 9 | a = 1 10 | b = 2 11 | c = 2 12 | d = 3 13 | e = 4 14 | f = 5 15 | 16 | end subroutine bar 17 | -------------------------------------------------------------------------------- /tests/compile/py_kw_arg.f90: -------------------------------------------------------------------------------- 1 | function try(lambda, in, as, for, del) 2 | 3 | try = 2.0 4 | 5 | end function try 6 | -------------------------------------------------------------------------------- /tests/compile/simple_array.f90: -------------------------------------------------------------------------------- 1 | subroutine assumed_size(arr, d1) 2 | implicit none 3 | integer, intent(in) :: d1 4 | complex*16, intent(inout) :: arr(d1, *) 5 | 6 | arr(1:d1, 1) = cmplx(10,20,kind=kind(arr)) 7 | end subroutine assumed_size 8 | subroutine explicit_shape(arr, d1, d2) 9 | implicit none 10 | integer, intent(in) :: d1, d2 11 | real(kind=8), intent(inout) :: arr(d1,d2) 12 | 13 | arr = 10.0 14 | 15 | end subroutine explicit_shape 16 | 17 | subroutine pass_array(arr0, arr1, arr2) 18 | implicit none 19 | integer, dimension(:,:), intent(in) :: arr0 20 | integer, dimension(:,:), intent(inout) :: arr1 21 | integer, dimension(:,:), intent(out) :: arr2 22 | 23 | print *, arr0 24 | print *, arr1 25 | 26 | arr2 = arr1 + arr0 27 | 28 | end subroutine pass_array 29 | 30 | subroutine pass_5D(arr0, arr1, arr2) 31 | implicit none 32 | integer :: i,j,k,l,m 33 | integer, dimension(:,:,:,:,:), intent(in) :: arr0 34 | integer, dimension(:,:,:,:,:), intent(inout) :: arr1 35 | integer, dimension(:,:,:,:,:), intent(out) :: arr2 36 | 37 | print *, shape(arr0) 38 | print *, shape(arr1) 39 | print *, shape(arr2) 40 | ! print *, arr0 41 | ! print *, arr1 42 | 43 | do i = 1, size(arr0,1) 44 | do j = 1, size(arr0,2) 45 | do k = 1, size(arr0,3) 46 | do l = 1, size(arr0,4) 47 | do m = 1, size(arr0,5) 48 | print *, arr0(m,l,k,j,i) 49 | enddo 50 | enddo 51 | enddo 52 | enddo 53 | enddo 54 | 55 | arr2 = arr1 + arr0 56 | 57 | end subroutine pass_5D 58 | 59 | subroutine pass_3D(arr0, arr1, arr2) 60 | implicit none 61 | integer :: i,j,k,l,m 62 | integer, dimension(:,:,:), intent(in) :: arr0 63 | integer, dimension(:,:,:), intent(inout) :: arr1 64 | integer, dimension(:,:,:), intent(out) :: arr2 65 | 66 | print *, shape(arr0) 67 | print *, shape(arr1) 68 | print *, shape(arr2) 69 | ! print *, arr0 70 | ! print *, arr1 71 | 72 | do k = 1, size(arr0,1) 73 | do l = 1, size(arr0,2) 74 | do m = 1, size(arr0,3) 75 | print *, arr0(m,l,k) 76 | enddo 77 | enddo 78 | enddo 79 | 80 | arr2 = arr1 + arr0 81 | 82 | end subroutine pass_3D 83 | 84 | subroutine pass_2D(arr0, arr1, arr2) 85 | implicit none 86 | integer :: i,j,k,l,m 87 | integer, dimension(:,:,:), intent(in) :: arr0 88 | integer, dimension(:,:,:), intent(inout) :: arr1 89 | integer, dimension(:,:,:), intent(out) :: arr2 90 | 91 | print *, shape(arr0) 92 | print *, shape(arr1) 93 | print *, shape(arr2) 94 | ! print *, arr0 95 | ! print *, arr1 96 | 97 | do l = 1, size(arr0,1) 98 | do m = 1, size(arr0,2) 99 | print *, arr0(m,l,1) 100 | enddo 101 | enddo 102 | 103 | arr2 = arr1 + arr0 104 | 105 | end subroutine pass_2D 106 | -------------------------------------------------------------------------------- /tests/run/all_char.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine char_arg(ch, ch_in) 3 | implicit none 4 | character(len=20) :: ch 5 | character(*) :: ch_in 6 | 7 | ch = ch_in 8 | 9 | end subroutine char_arg 10 | 11 | subroutine char_star(ch, ch_in, ch_out, ch_inout) 12 | implicit none 13 | character(*) ch 14 | character(len=*), intent(in) :: ch_in 15 | character(*), intent(out) :: ch_out 16 | character(*), intent(inout) :: ch_inout 17 | 18 | ch = ch_in 19 | 20 | ch_out = ch_inout 21 | 22 | end subroutine char_star 23 | 24 | subroutine char1(ch) 25 | implicit none 26 | character*20 :: ch 27 | ch = "aoeuidhtns" 28 | end subroutine char1 29 | 30 | subroutine char2(ch) 31 | implicit none 32 | character*10, intent(in) :: ch 33 | character*10 :: dummy 34 | dummy = ch 35 | end subroutine char2 36 | 37 | subroutine char3(ch) 38 | implicit none 39 | character(len=5), intent(out) :: ch 40 | ch = "',.py" 41 | end subroutine char3 42 | 43 | subroutine char4(ch) 44 | implicit none 45 | character(len=1), intent(inout) :: ch 46 | character(*), parameter :: cp = "a^eu" 47 | ch = cp(2:2) 48 | end subroutine char4 49 | 50 | subroutine char_len_x(ch, ch_in, ch_out, ch_inout) 51 | implicit none 52 | character*20 :: ch 53 | character*10, intent(in) :: ch_in 54 | character(len=5), intent(out) :: ch_out 55 | character(len=1), intent(inout) :: ch_inout 56 | 57 | ch_out = ch_inout // ch_in(1:4) 58 | ch = ch_in // ch_out // ch_out 59 | ch_inout = 'a' 60 | 61 | end subroutine char_len_x 62 | 63 | subroutine len_1_args(a, b, c) 64 | implicit none 65 | character :: a 66 | character, intent(inout) :: b 67 | character, intent(out) :: c 68 | 69 | a = b 70 | c = b 71 | end subroutine len_1_args 72 | -------------------------------------------------------------------------------- /tests/run/all_char_arrays.f90: -------------------------------------------------------------------------------- 1 | subroutine explicit_shape(ll, n1, n2, ain, aout, ainout, ano) 2 | implicit none 3 | integer, intent(in) :: ll, n1, n2 4 | character(len=ll), dimension(n1, n2), intent(in) :: ain 5 | character(len=ll), dimension(n1, n2), intent(out) :: aout 6 | character(len=ll), dimension(n1, n2), intent(inout) :: ainout 7 | character(len=ll), dimension(n1, n2) :: ano 8 | 9 | aout = ain 10 | ano = ainout 11 | ainout = ain(:,:)(1:ll/2) // ano(:,:)(ll/2+1:ll) 12 | end subroutine explicit_shape 13 | 14 | subroutine assumed_shape(ain, aout, ainout, ano) 15 | implicit none 16 | character(*), dimension(:, :), intent(in) :: ain 17 | character(*), dimension(:, :), intent(out) :: aout 18 | character(*), dimension(:, :), intent(inout) :: ainout 19 | character(*), dimension(:, :) :: ano 20 | 21 | integer ll 22 | 23 | ll = len(ain) 24 | 25 | aout = ain 26 | ano = ainout 27 | ainout = ain(:,:)(1:ll/2) // ano(:,:)(ll/2+1:ll) 28 | end subroutine assumed_shape 29 | 30 | subroutine assumed_size(n1, n2, ain, aout, ainout, ano) 31 | implicit none 32 | integer, intent(in) :: n1, n2 33 | character(*), dimension(n1, *), intent(in) :: ain 34 | character(*), dimension(n1, *), intent(out) :: aout 35 | character(*), dimension(n1, *), intent(inout) :: ainout 36 | character(*), dimension(n1, *) :: ano 37 | 38 | integer ll 39 | 40 | ll = len(ain) 41 | 42 | aout(:,1:n2) = ain(:,1:n2) 43 | ano(:,1:n2) = ainout(:,1:n2) 44 | ainout(:,1:n2) = ain(:,1:n2)(1:ll/2) // ano(:,1:n2)(ll/2+1:ll) 45 | end subroutine assumed_size 46 | -------------------------------------------------------------------------------- /tests/run/all_char_arrays_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_char_arrays_fwrap import * 2 | import numpy as np 3 | 4 | ll, n1, n2 = 6, 3, 4 5 | ain = np.empty((n1,n2), dtype='S%d' % ll, order='F') 6 | aout = ain.copy('F') 7 | ainout = ain.copy('F') 8 | ano = ain.copy('F') 9 | 10 | aout_ = aout.copy('F') 11 | ainout_ = ainout.copy('F') 12 | ano_ = ano.copy('F') 13 | 14 | def init(ain, aout, ainout, ano, aout_, ainout_, ano_): 15 | ain.fill('ABCDEF') 16 | aout.fill(' ') 17 | ainout.fill('123456') 18 | ano.fill(' ') 19 | 20 | aout_[...] = ain 21 | ano_[...] = ainout 22 | ainout_.fill(ain[0,0][:3] + ano_[0,0][3:]) 23 | 24 | def test_results(func, args, results): 25 | res_ = func(*args) 26 | for r1, r2 in zip(res_, results): 27 | if not np.all(r1 == r2): 28 | print r1 29 | print r2 30 | return False 31 | return True 32 | 33 | __doc__ = u''' 34 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 35 | >>> test_results(assumed_shape, (ain, aout, ainout, ano), (aout_, ainout_, ano_)) 36 | True 37 | 38 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 39 | >>> test_results(explicit_shape, (ll, n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 40 | True 41 | 42 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 43 | >>> test_results(assumed_size, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 44 | True 45 | 46 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 47 | >>> test_results(assumed_size, (n1+1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 48 | Traceback (most recent call last): 49 | ... 50 | RuntimeError: an error was encountered when calling the 'assumed_size' wrapper. 51 | 52 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 53 | >>> test_results(explicit_shape, (ll+1, n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 54 | Traceback (most recent call last): 55 | ... 56 | RuntimeError: an error was encountered when calling the 'explicit_shape' wrapper. 57 | 58 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 59 | >>> test_results(explicit_shape, (ll, n1+1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 60 | Traceback (most recent call last): 61 | ... 62 | RuntimeError: an error was encountered when calling the 'explicit_shape' wrapper. 63 | 64 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 65 | >>> test_results(explicit_shape, (ll, n1, n2+1, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 66 | Traceback (most recent call last): 67 | ... 68 | RuntimeError: an error was encountered when calling the 'explicit_shape' wrapper. 69 | ''' 70 | -------------------------------------------------------------------------------- /tests/run/all_char_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_char_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> char_arg('foobar', 'ch_in') 5 | ('ch_in ', 'ch_in') 6 | >>> char_star('aaaaa', 'bb', 'cccccccccc', 'dddddddd') 7 | ('bb ', 'dddddddd ', 'dddddddd') 8 | >>> char1("1234567890") 9 | 'aoeuidhtns ' 10 | >>> char2("1234567890") 11 | >>> char3() 12 | "',.py" 13 | >>> char4("a") 14 | '^' 15 | >>> char_len_x(ch='a'*20, ch_in='b'*10, ch_inout='_') 16 | ('bbbbbbbbbb_bbbb_bbbb', '_bbbb', 'a') 17 | >>> len_1_args('a', 'b') 18 | ('b', 'b', 'b') 19 | ''' 20 | -------------------------------------------------------------------------------- /tests/run/all_complex.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine complex_default(r1,r2,r3) 3 | implicit none 4 | complex, intent(in) :: r1 5 | complex, intent(inout) :: r2 6 | complex, intent(out) :: r3 7 | r2 = 2*r1 8 | r3 = 2*r2 - 5*r1 9 | end subroutine 10 | subroutine complex_x_len(r10,r11,r12,r13,r14,r15) 11 | implicit none 12 | complex*8, intent(in) :: r10 13 | complex*8, intent(inout) :: r11 14 | complex*8, intent(out) :: r12 15 | complex*16, intent(in) :: r13 16 | complex*16, intent(inout) :: r14 17 | complex*16, intent(out) :: r15 18 | r11 = 2*r10 19 | r12 = 3*r11 - 5*r10 20 | r14 = conjg(r13) 21 | r15 = r14 - r13 22 | end subroutine 23 | subroutine complex_kind_x(r7,r8,r9,r10,r11,r12) 24 | implicit none 25 | complex(kind=4), intent(in) :: r7 26 | complex(kind=4), intent(inout) :: r8 27 | complex(kind=4), intent(out) :: r9 28 | complex(kind=8), intent(in) :: r10 29 | complex(kind=8), intent(inout) :: r11 30 | complex(kind=8), intent(out) :: r12 31 | r8 = r7 32 | r9 = r8 * r7 / 2.0 33 | r11 = r10**3 34 | r12 = r11 - conjg(r10) 35 | end subroutine 36 | ! subroutine complex_kind_call(r1,r2,r3,r4,r5,r6) 37 | ! implicit none 38 | ! complex(kind=kind((0.0,0.0))), intent(in) :: r1 39 | ! complex(kind=kind((0.0,0.0))), intent(inout) :: r2 40 | ! complex(kind=kind((0.0,0.0))), intent(out) :: r3 41 | ! complex(kind=kind((0.0D0,0.0D0))), intent(in) :: r4 42 | ! complex(kind=kind((0.0D0,0.0D0))), intent(inout) :: r5 43 | ! complex(kind=kind((0.0D0,0.0D0))), intent(out) :: r6 44 | ! end subroutine 45 | ! subroutine complex_srk_call(r1,r2,r3,r4,r5,r6,r7,r8,r9) 46 | ! implicit none 47 | ! complex(kind=selected_real_kind(1)), intent(in) :: r1 48 | ! complex(kind=selected_real_kind(1)), intent(inout) :: r2 49 | ! complex(kind=selected_real_kind(1)), intent(out) :: r3 50 | ! complex(kind=selected_real_kind(7)), intent(in) :: r4 51 | ! complex(kind=selected_real_kind(7)), intent(inout) :: r5 52 | ! complex(kind=selected_real_kind(7)), intent(out) :: r6 53 | ! complex(kind=selected_real_kind(14)), intent(in) :: r7 54 | ! complex(kind=selected_real_kind(14)), intent(inout) :: r8 55 | ! complex(kind=selected_real_kind(14)), intent(out) :: r9 56 | ! end subroutine 57 | -------------------------------------------------------------------------------- /tests/run/all_complex_arrays.f90: -------------------------------------------------------------------------------- 1 | subroutine explicit_shape(n1, n2, ain, aout, ainout, ano) 2 | implicit none 3 | integer, intent(in) :: n1, n2 4 | complex, dimension(n1, n2), intent(in) :: ain 5 | complex, dimension(n1, n2), intent(out) :: aout 6 | complex, dimension(n1, n2), intent(inout) :: ainout 7 | complex, dimension(n1, n2) :: ano 8 | 9 | aout = ain 10 | ano = ainout 11 | ainout = ain + ano 12 | end subroutine explicit_shape 13 | 14 | subroutine assumed_shape(ain, aout, ainout, ano) 15 | implicit none 16 | complex, dimension(:, :), intent(in) :: ain 17 | complex, dimension(:, :), intent(out) :: aout 18 | complex, dimension(:, :), intent(inout) :: ainout 19 | complex, dimension(:, :) :: ano 20 | 21 | aout = ain 22 | ano = ainout 23 | ainout = ain + ano 24 | end subroutine assumed_shape 25 | 26 | subroutine assumed_size(n1, n2, ain, aout, ainout, ano) 27 | implicit none 28 | integer, intent(in) :: n1, n2 29 | complex, dimension(n1, *), intent(in) :: ain 30 | complex, dimension(n1, *), intent(out) :: aout 31 | complex, dimension(n1, *), intent(inout) :: ainout 32 | complex, dimension(n1, *) :: ano 33 | 34 | aout(:,1:n2) = ain(:,1:n2) 35 | ano(:,1:n2) = ainout(:,1:n2) 36 | ainout(:,1:n2) = ain(:,1:n2) + ano(:,1:n2) 37 | end subroutine assumed_size 38 | -------------------------------------------------------------------------------- /tests/run/all_complex_arrays_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_complex_arrays_fwrap import * 2 | import numpy as np 3 | 4 | n1, n2 = 3, 4 5 | ain = np.empty((n1,n2), dtype=np.complex64, order='F') 6 | aout = ain.copy('F') 7 | ainout = ain.copy('F') 8 | ano = ain.copy('F') 9 | 10 | aout_ = aout.copy('F') 11 | ainout_ = ainout.copy('F') 12 | ano_ = ano.copy('F') 13 | 14 | def init(ain, aout, ainout, ano, aout_, ainout_, ano_): 15 | ain.fill(2.0+2.0j) 16 | aout.fill(0.0+0.0j) 17 | ainout.fill(34.0+10.0j) 18 | ano.fill(0.0+0.0j) 19 | 20 | aout_[...] = ain 21 | ano_[...] = ainout 22 | ainout_[...] = ain + ano_ 23 | 24 | 25 | def test_results(func, args, results): 26 | res_ = func(*args) 27 | for r1, r2 in zip(res_, results): 28 | if not np.all(r1 == r2): 29 | print r1 30 | print r2 31 | return False 32 | return True 33 | 34 | __doc__ = u''' 35 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 36 | >>> test_results(assumed_shape, (ain, aout, ainout, ano), (aout_, ainout_, ano_)) 37 | True 38 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 39 | >>> test_results(explicit_shape, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 40 | True 41 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 42 | >>> test_results(assumed_size, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 43 | True 44 | ''' 45 | -------------------------------------------------------------------------------- /tests/run/all_complex_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_complex_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> complex_default(1+1j,2+2j) == ((2+2j), (-1-1j)) 5 | True 6 | >>> complex_x_len(10+10j,11+11j,13+13j,14+14j) == ((20+20j), (10+10j), (13-13j), -26j) 7 | True 8 | >>> complex_kind_x(7+7j,8+8j,10+10j,11+11j) == ((7+7j), 49j, (-2000+2000j), (-2010+2010j)) 9 | True 10 | ''' 11 | -------------------------------------------------------------------------------- /tests/run/all_integer_arrays.f90: -------------------------------------------------------------------------------- 1 | subroutine explicit_shape(n1, n2, ain, aout, ainout, ano) 2 | implicit none 3 | integer, intent(in) :: n1, n2 4 | integer, dimension(n1, n2), intent(in) :: ain 5 | integer, dimension(n1, n2), intent(out) :: aout 6 | integer, dimension(n1, n2), intent(inout) :: ainout 7 | integer, dimension(n1, n2) :: ano 8 | 9 | aout = ain 10 | ano = ainout 11 | ainout = ain + ano 12 | end subroutine explicit_shape 13 | 14 | subroutine assumed_shape(ain, aout, ainout, ano) 15 | implicit none 16 | integer, dimension(:, :), intent(in) :: ain 17 | integer, dimension(:, :), intent(out) :: aout 18 | integer, dimension(:, :), intent(inout) :: ainout 19 | integer, dimension(:, :) :: ano 20 | 21 | aout = ain 22 | ano = ainout 23 | ainout = ain + ano 24 | end subroutine assumed_shape 25 | 26 | subroutine assumed_size(n1, n2, ain, aout, ainout, ano) 27 | implicit none 28 | integer, intent(in) :: n1, n2 29 | integer, dimension(n1, *), intent(in) :: ain 30 | integer, dimension(n1, *), intent(out) :: aout 31 | integer, dimension(n1, *), intent(inout) :: ainout 32 | integer, dimension(n1, *) :: ano 33 | 34 | aout(:,1:n2) = ain(:,1:n2) 35 | ano(:,1:n2) = ainout(:,1:n2) 36 | ainout(:,1:n2) = ain(:,1:n2) + ano(:,1:n2) 37 | end subroutine assumed_size 38 | -------------------------------------------------------------------------------- /tests/run/all_integer_arrays_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_integer_arrays_fwrap import * 2 | import numpy as np 3 | 4 | n1, n2 = 3, 4 5 | ain = np.empty((n1,n2), dtype=np.int32, order='F') 6 | aout = ain.copy('F') 7 | ainout = ain.copy('F') 8 | ano = ain.copy('F') 9 | 10 | aout_ = aout.copy('F') 11 | ainout_ = ainout.copy('F') 12 | ano_ = ano.copy('F') 13 | 14 | def init(ain, aout, ainout, ano, aout_, ainout_, ano_): 15 | ain.fill(2) 16 | aout.fill(0) 17 | ainout.fill(34) 18 | ano.fill(0) 19 | 20 | aout_[...] = ain 21 | ano_[...] = ainout 22 | ainout_[...] = ain + ano_ 23 | 24 | def test_results(func, args, results): 25 | res_ = func(*args) 26 | for r1, r2 in zip(res_, results): 27 | if not np.all(r1 == r2): 28 | print r1 29 | print r2 30 | return False 31 | return True 32 | 33 | __doc__ = u''' 34 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 35 | >>> test_results(assumed_shape, (ain, aout, ainout, ano), (aout_, ainout_, ano_)) 36 | True 37 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 38 | >>> test_results(explicit_shape, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 39 | True 40 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 41 | >>> test_results(assumed_size, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 42 | True 43 | ''' 44 | -------------------------------------------------------------------------------- /tests/run/all_ints.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine int_default(i1,i2,i3) 3 | implicit none 4 | integer, intent(in) :: i1 5 | integer, intent(inout) :: i2 6 | integer, intent(out) :: i3 7 | i3 = i1 + i1 8 | i2 = i2 + 2*i3 9 | end subroutine 10 | subroutine int_x_len(i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15) 11 | implicit none 12 | integer*1, intent(in) :: i4 13 | integer*1, intent(inout) :: i5 14 | integer*1, intent(out) :: i6 15 | integer*2, intent(in) :: i7 16 | integer*2, intent(inout) :: i8 17 | integer*2, intent(out) :: i9 18 | integer*4, intent(in) :: i10 19 | integer*4, intent(inout) :: i11 20 | integer*4, intent(out) :: i12 21 | integer*8, intent(in) :: i13 22 | integer*8, intent(inout) :: i14 23 | integer*8, intent(out) :: i15 24 | i6 = i4 + i5 25 | i9 = i7 + i8 26 | i12 = i10 + i11 27 | i15 = i13 + i14 28 | end subroutine 29 | subroutine int_kind_x(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12) 30 | implicit none 31 | integer(kind=1), intent(in) :: i1 32 | integer(kind=1), intent(inout) :: i2 33 | integer(kind=1), intent(out) :: i3 34 | integer(kind=2), intent(in) :: i4 35 | integer(kind=2), intent(inout) :: i5 36 | integer(kind=2), intent(out) :: i6 37 | integer(kind=4), intent(in) :: i7 38 | integer(kind=4), intent(inout) :: i8 39 | integer(kind=4), intent(out) :: i9 40 | integer(kind=8), intent(in) :: i10 41 | integer(kind=8), intent(inout) :: i11 42 | integer(kind=8), intent(out) :: i12 43 | i3 = i1 + i2 44 | i6 = i4 + i5 45 | i9 = i7 + i8 46 | i12 = i10 + i11 47 | end subroutine 48 | ! subroutine int_kind_call(i1,i2,i3) 49 | ! implicit none 50 | ! integer(kind=kind(0)), intent(in) :: i1 51 | ! integer(kind=kind(0)), intent(inout) :: i2 52 | ! integer(kind=kind(0)), intent(out) :: i3 53 | ! i3 = i1 + i2 54 | ! end subroutine 55 | ! subroutine int_sik_call(i1,i2,i3,i4,i5,i6,i7,i8,i9) 56 | ! implicit none 57 | ! integer(kind=selected_int_kind(1)), intent(in) :: i1 58 | ! integer(kind=selected_int_kind(1)), intent(inout) :: i2 59 | ! integer(kind=selected_int_kind(1)), intent(out) :: i3 60 | ! integer(kind=selected_int_kind(5)), intent(in) :: i4 61 | ! integer(kind=selected_int_kind(5)), intent(inout) :: i5 62 | ! integer(kind=selected_int_kind(5)), intent(out) :: i6 63 | ! integer(kind=selected_int_kind(10)), intent(in) :: i7 64 | ! integer(kind=selected_int_kind(10)), intent(inout) :: i8 65 | ! integer(kind=selected_int_kind(10)), intent(out) :: i9 66 | ! i3 = i1 + i2 67 | ! i6 = i4 + i5 68 | ! i9 = i7 + i8 69 | ! end subroutine 70 | -------------------------------------------------------------------------------- /tests/run/all_ints_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_ints_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> int_default(1,2) == (6, 2) 5 | True 6 | >>> int_x_len(1,2,4,5,7,8,10,11) == (2, 3, 5, 9, 8, 15, 11L, 21L) 7 | True 8 | >>> int_kind_x(1,2,4,5,7,8,10,11) == (2, 3, 5, 9, 8, 15, 11L, 21L) 9 | True 10 | ''' 11 | -------------------------------------------------------------------------------- /tests/run/all_logical_arrays.f90: -------------------------------------------------------------------------------- 1 | subroutine explicit_shape(n1, n2, ain, aout, ainout, ano) 2 | implicit none 3 | integer, intent(in) :: n1, n2 4 | logical, dimension(n1, n2), intent(in) :: ain 5 | logical, dimension(n1, n2), intent(out) :: aout 6 | logical, dimension(n1, n2), intent(inout) :: ainout 7 | logical, dimension(n1, n2) :: ano 8 | 9 | aout = ain 10 | ano = ainout 11 | where(ain) 12 | ainout = .false. 13 | endwhere 14 | end subroutine explicit_shape 15 | 16 | subroutine assumed_shape(ain, aout, ainout, ano) 17 | implicit none 18 | logical, dimension(:, :), intent(in) :: ain 19 | logical, dimension(:, :), intent(out) :: aout 20 | logical, dimension(:, :), intent(inout) :: ainout 21 | logical, dimension(:, :) :: ano 22 | 23 | aout = ain 24 | ano = ainout 25 | where(ain) 26 | ainout = .false. 27 | endwhere 28 | end subroutine assumed_shape 29 | 30 | subroutine assumed_size(n1, n2, ain, aout, ainout, ano) 31 | implicit none 32 | integer, intent(in) :: n1, n2 33 | logical, dimension(n1, *), intent(in) :: ain 34 | logical, dimension(n1, *), intent(out) :: aout 35 | logical, dimension(n1, *), intent(inout) :: ainout 36 | logical, dimension(n1, *) :: ano 37 | 38 | aout(:,1:n2) = ain(:,1:n2) 39 | ano(:,1:n2) = ainout(:,1:n2) 40 | where(ain(:,1:n2)) 41 | ainout(:,1:n2) = .false. 42 | endwhere 43 | end subroutine assumed_size 44 | -------------------------------------------------------------------------------- /tests/run/all_logical_arrays_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_logical_arrays_fwrap import * 2 | import numpy as np 3 | 4 | n1, n2 = 3, 4 5 | ain = np.empty((n1,n2), dtype=np.int32, order='F') 6 | aout = ain.copy('F') 7 | ainout = ain.copy('F') 8 | ano = ain.copy('F') 9 | 10 | aout_ = aout.copy('F') 11 | ainout_ = ainout.copy('F') 12 | ano_ = ano.copy('F') 13 | 14 | def init(ain, aout, ainout, ano, aout_, ainout_, ano_): 15 | ain.fill(1) 16 | ain[0,0] = 0 17 | aout.fill(0) 18 | ainout.fill(1) 19 | ano.fill(0) 20 | 21 | aout_[:,:] = ain 22 | ano_[:,:] = ainout 23 | ainout_[:,:] = ainout 24 | ainout_[ain.astype(np.bool)] = 0 25 | 26 | def test_results(func, args, results): 27 | res_ = func(*args) 28 | for r1, r2 in zip(res_, results): 29 | if not np.all(r1 == r2): 30 | print r1 31 | print r2 32 | return False 33 | return True 34 | 35 | __doc__ = u''' 36 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 37 | >>> test_results(assumed_shape, (ain, aout, ainout, ano), (aout_, ainout_, ano_)) 38 | True 39 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 40 | >>> test_results(explicit_shape, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 41 | True 42 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 43 | >>> test_results(assumed_size, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 44 | True 45 | ''' 46 | -------------------------------------------------------------------------------- /tests/run/all_logicals.f90: -------------------------------------------------------------------------------- 1 | subroutine log_default(i1,i2,i3) 2 | implicit none 3 | logical, intent(in) :: i1 4 | logical, intent(inout) :: i2 5 | logical, intent(out) :: i3 6 | i2 = .false. .and. i1 7 | i3 = .false. 8 | end subroutine 9 | subroutine log_x_len(i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15) 10 | implicit none 11 | logical*1, intent(in) :: i4 12 | logical*1, intent(inout) :: i5 13 | logical*1, intent(out) :: i6 14 | logical*2, intent(in) :: i7 15 | logical*2, intent(inout) :: i8 16 | logical*2, intent(out) :: i9 17 | logical*4, intent(in) :: i10 18 | logical*4, intent(inout) :: i11 19 | logical*4, intent(out) :: i12 20 | logical*8, intent(in) :: i13 21 | logical*8, intent(inout) :: i14 22 | logical*8, intent(out) :: i15 23 | 24 | i5= .false. .and. i4 25 | i6= .false. .and. i7 26 | i8= .false. 27 | i9= .false. .and. i10 28 | i11= .false. 29 | i12= .false. 30 | i14= .false. .and. i13 31 | i15= .false. 32 | 33 | end subroutine 34 | subroutine log_kind_x(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12) 35 | implicit none 36 | logical(kind=1), intent(in) :: i1 37 | logical(kind=1), intent(inout) :: i2 38 | logical(kind=1), intent(out) :: i3 39 | logical(kind=2), intent(in) :: i4 40 | logical(kind=2), intent(inout) :: i5 41 | logical(kind=2), intent(out) :: i6 42 | logical(kind=4), intent(in) :: i7 43 | logical(kind=4), intent(inout) :: i8 44 | logical(kind=4), intent(out) :: i9 45 | logical(kind=8), intent(in) :: i10 46 | logical(kind=8), intent(inout) :: i11 47 | logical(kind=8), intent(out) :: i12 48 | 49 | i2= .false. .and. i1 50 | i3= .false. 51 | i5= .false. .and. i4 52 | i6= .false. 53 | i8= .false. .and. i7 54 | i9= .false. 55 | i11= .false. .and. i10 56 | i12= .false. 57 | 58 | end subroutine 59 | ! subroutine log_kind_call(i1,i2,i3,i4,i5,i6) 60 | ! implicit none 61 | ! logical(kind=kind(.true.)), intent(in) :: i1 62 | ! logical(kind=kind(.true.)), intent(inout) :: i2 63 | ! logical(kind=kind(.true.)), intent(out) :: i3 64 | ! logical(kind=kind(0)), intent(in) :: i4 65 | ! logical(kind=kind(0)), intent(inout) :: i5 66 | ! logical(kind=kind(0)), intent(out) :: i6 67 | 68 | ! i2= .false. .and. i1 69 | ! i3= .false. 70 | ! i5= .false. .and. i4 71 | ! i6= .false. 72 | 73 | ! end subroutine 74 | ! subroutine log_sik_call(i1,i2,i3,i4,i5,i6,i7,i8,i9) 75 | ! implicit none 76 | ! logical(kind=selected_int_kind(1)), intent(in) :: i1 77 | ! logical(kind=selected_int_kind(1)), intent(inout) :: i2 78 | ! logical(kind=selected_int_kind(1)), intent(out) :: i3 79 | ! logical(kind=selected_int_kind(5)), intent(in) :: i4 80 | ! logical(kind=selected_int_kind(5)), intent(inout) :: i5 81 | ! logical(kind=selected_int_kind(5)), intent(out) :: i6 82 | ! logical(kind=selected_int_kind(10)), intent(in) :: i7 83 | ! logical(kind=selected_int_kind(10)), intent(inout) :: i8 84 | ! logical(kind=selected_int_kind(10)), intent(out) :: i9 85 | 86 | ! i2= .false. .and. i1 87 | ! i3= .false. 88 | ! i5= .false. .and. i4 89 | ! i6= .false. 90 | ! i8= .false. .and. i7 91 | ! i9= .false. 92 | 93 | ! end subroutine 94 | -------------------------------------------------------------------------------- /tests/run/all_logicals_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_logicals_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> log_default(1,0) == (0, 0) 5 | True 6 | >>> print log_x_len(1,2,4,5,7,8,10,11) == (0, 0, 0, 0, 0, 0, 0L, 0L) 7 | True 8 | >>> print log_kind_x(1,2,4,5,7,8,10,11) == (0, 0, 0, 0, 0, 0, 0L, 0L) 9 | True 10 | ''' 11 | -------------------------------------------------------------------------------- /tests/run/all_real_arrays.f90: -------------------------------------------------------------------------------- 1 | subroutine explicit_shape(n1, n2, ain, aout, ainout, ano) 2 | implicit none 3 | integer, intent(in) :: n1, n2 4 | real, dimension(n1, n2), intent(in) :: ain 5 | real, dimension(n1, n2), intent(out) :: aout 6 | real, dimension(n1, n2), intent(inout) :: ainout 7 | real, dimension(n1, n2) :: ano 8 | 9 | aout = ain 10 | ano = ainout 11 | ainout = ain + ano 12 | end subroutine explicit_shape 13 | 14 | subroutine assumed_shape(ain, aout, ainout, ano) 15 | implicit none 16 | real, dimension(:, :), intent(in) :: ain 17 | real, dimension(:, :), intent(out) :: aout 18 | real, dimension(:, :), intent(inout) :: ainout 19 | real, dimension(:, :) :: ano 20 | 21 | aout = ain 22 | ano = ainout 23 | ainout = ain + ano 24 | end subroutine assumed_shape 25 | 26 | subroutine assumed_size(n1, n2, ain, aout, ainout, ano) 27 | implicit none 28 | integer, intent(in) :: n1, n2 29 | real, dimension(n1, *), intent(in) :: ain 30 | real, dimension(n1, *), intent(out) :: aout 31 | real, dimension(n1, *), intent(inout) :: ainout 32 | real, dimension(n1, *) :: ano 33 | 34 | aout(:,1:n2) = ain(:,1:n2) 35 | ano(:,1:n2) = ainout(:,1:n2) 36 | ainout(:,1:n2) = ain(:,1:n2) + ano(:,1:n2) 37 | end subroutine assumed_size 38 | -------------------------------------------------------------------------------- /tests/run/all_real_arrays_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_real_arrays_fwrap import * 2 | import numpy as np 3 | 4 | n1, n2 = 3, 4 5 | ain = np.empty((n1,n2), dtype=np.float32, order='F') 6 | aout = ain.copy('F') 7 | ainout = ain.copy('F') 8 | ano = ain.copy('F') 9 | 10 | aout_ = aout.copy('F') 11 | ainout_ = ainout.copy('F') 12 | ano_ = ano.copy('F') 13 | 14 | def init(ain, aout, ainout, ano, aout_, ainout_, ano_): 15 | ain.fill(2.0) 16 | aout.fill(0.0) 17 | ainout.fill(34.0) 18 | ano.fill(0.0) 19 | 20 | aout_[...] = ain 21 | ano_[...] = ainout 22 | ainout_[...] = ain + ano_ 23 | 24 | 25 | def test_results(func, args, results): 26 | res_ = func(*args) 27 | for r1, r2 in zip(res_, results): 28 | if not np.all(r1 == r2): 29 | print r1 30 | print r2 31 | return False 32 | return True 33 | 34 | __doc__ = u''' 35 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 36 | >>> test_results(assumed_shape, (ain, aout, ainout, ano), (aout_, ainout_, ano_)) 37 | True 38 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 39 | >>> test_results(explicit_shape, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 40 | True 41 | >>> init(ain, aout, ainout, ano, aout_, ainout_, ano_) 42 | >>> test_results(assumed_size, (n1, n2, ain, aout, ainout, ano), (aout_, ainout_, ano_)) 43 | True 44 | ''' 45 | -------------------------------------------------------------------------------- /tests/run/all_reals.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine real_default(r1,r2,r3) 3 | implicit none 4 | real, intent(in) :: r1 5 | real, intent(inout) :: r2 6 | real, intent(out) :: r3 7 | r3 = r1 + r2 8 | end subroutine 9 | subroutine real_x_len(r10,r11,r12,r13,r14,r15) 10 | implicit none 11 | real*4, intent(in) :: r10 12 | real*4, intent(inout) :: r11 13 | real*4, intent(out) :: r12 14 | real*8, intent(in) :: r13 15 | real*8, intent(inout) :: r14 16 | real*8, intent(out) :: r15 17 | r12 = r10 + r11 18 | r15 = r13 + r14 19 | end subroutine 20 | subroutine real_kind_x(r7,r8,r9,r10,r11,r12) 21 | implicit none 22 | real(kind=4), intent(in) :: r7 23 | real(kind=4), intent(inout) :: r8 24 | real(kind=4), intent(out) :: r9 25 | real(kind=8), intent(in) :: r10 26 | real(kind=8), intent(inout) :: r11 27 | real(kind=8), intent(out) :: r12 28 | r9 = r7 + r8 29 | r12 = r11 + r10 30 | end subroutine 31 | ! subroutine real_kind_call(r1,r2,r3,r4,r5,r6) 32 | ! implicit none 33 | ! real(kind=kind(0.0)), intent(in) :: r1 34 | ! real(kind=kind(0.0)), intent(inout) :: r2 35 | ! real(kind=kind(0.0)), intent(out) :: r3 36 | ! real(kind=kind(0.0D0)), intent(in) :: r4 37 | ! real(kind=kind(0.0D0)), intent(inout) :: r5 38 | ! real(kind=kind(0.0D0)), intent(out) :: r6 39 | ! r3 = r2 + r1 40 | ! r6 = r4 + r5 41 | ! end subroutine 42 | ! subroutine real_srk_call(r1,r2,r3,r4,r5,r6,r7,r8,r9) 43 | ! implicit none 44 | ! real(kind=selected_real_kind(1)), intent(in) :: r1 45 | ! real(kind=selected_real_kind(1)), intent(inout) :: r2 46 | ! real(kind=selected_real_kind(1)), intent(out) :: r3 47 | ! real(kind=selected_real_kind(7)), intent(in) :: r4 48 | ! real(kind=selected_real_kind(7)), intent(inout) :: r5 49 | ! real(kind=selected_real_kind(7)), intent(out) :: r6 50 | ! real(kind=selected_real_kind(14)), intent(in) :: r7 51 | ! real(kind=selected_real_kind(14)), intent(inout) :: r8 52 | ! real(kind=selected_real_kind(14)), intent(out) :: r9 53 | ! r3 = r1 + r2 54 | ! r6 = r4 + r5 55 | ! r9 = r7 + r8 56 | ! end subroutine 57 | -------------------------------------------------------------------------------- /tests/run/all_reals_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from all_reals_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> real_default(1,2) == (2.0, 3.0) 5 | True 6 | >>> real_x_len(10,11,13,14) == (11.0, 21.0, 14.0, 27.0) 7 | True 8 | >>> real_kind_x(7,8,10,11) == (8.0, 15.0, 11.0, 21.0) 9 | True 10 | ''' 11 | -------------------------------------------------------------------------------- /tests/run/array_intents.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine assumed_shape_intents(a1, a2, a3, a4) 3 | implicit none 4 | real, dimension(:,:), intent(in) :: a1 5 | real, dimension(:,:), intent(inout) :: a2 6 | real, dimension(:,:), intent(out) :: a3 7 | real, dimension(:,:) :: a4 8 | 9 | a3 = a1 * 32 10 | a4 = a2 / 4.0 11 | 12 | end subroutine assumed_shape_intents 13 | -------------------------------------------------------------------------------- /tests/run/array_intents_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from array_intents_fwrap import * 3 | 4 | N = 2 5 | arrs = [np.ones((N,N), dtype=np.float32, order='F') for x in range(4)] 6 | 7 | __doc__ = u''' 8 | >>> a,b,c = assumed_shape_intents(*arrs) 9 | >>> np.all(a == np.array([[ 1., 1.], 10 | ... [ 1., 1.]], dtype=np.float32)) 11 | True 12 | >>> np.all(b == np.array([[ 32., 32.], 13 | ... [ 32., 32.]], dtype=np.float32)) 14 | True 15 | >>> np.all(c == np.array([[ 0.25, 0.25], 16 | ... [ 0.25, 0.25]], dtype=np.float32)) 17 | True 18 | ''' 19 | -------------------------------------------------------------------------------- /tests/run/array_types.f90: -------------------------------------------------------------------------------- 1 | subroutine array_types(a) 2 | implicit none 3 | real(kind=8), dimension(:,:), intent(inout) :: a 4 | 5 | a = 1.0D0 6 | 7 | end subroutine array_types 8 | -------------------------------------------------------------------------------- /tests/run/array_types_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from array_types_fwrap import * 2 | import numpy as np 3 | 4 | real64 = np.empty((2,2), dtype=np.float64, order='F') 5 | real32 = np.empty((2,2), dtype=np.float32, order='F') 6 | 7 | __doc__ = u'''\ 8 | >>> np.all(array_types(real64)[0] == np.array([[ 1., 1.], [ 1., 1.]])) 9 | True 10 | >>> np.all(array_types(real32)[0] == np.array([[ 1., 1.], [ 1., 1.]])) 11 | True 12 | ''' 13 | -------------------------------------------------------------------------------- /tests/run/char_array.f90: -------------------------------------------------------------------------------- 1 | subroutine char_array(charr) 2 | implicit none 3 | character(len=3), dimension(:,:), intent(inout) :: charr 4 | 5 | charr = "abc" 6 | 7 | end subroutine char_array 8 | 9 | subroutine char1_arr(charr) 10 | implicit none 11 | character, dimension(:,:), intent(inout) :: charr 12 | 13 | charr = "%" 14 | 15 | end subroutine char1_arr 16 | 17 | subroutine char_star(charr) 18 | implicit none 19 | character(*), dimension(:,:), intent(inout) :: charr 20 | 21 | charr = "123" 22 | end subroutine char_star 23 | -------------------------------------------------------------------------------- /tests/run/char_array_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from char_array_fwrap import * 2 | import numpy as np 3 | 4 | charr = np.empty((2,3), dtype='|S3', order='F') 5 | charr1 = np.empty((2,3), dtype='|S1', order='F') 6 | 7 | __doc__ = u'''\ 8 | >>> np.all(char_array(charr) == np.array([['abc', 'abc', 'abc'], ['abc', 'abc', 'abc']], dtype='|S3')) 9 | True 10 | >>> np.all(char1_arr(charr1) == np.array([['%', '%', '%'], ['%', '%', '%']], dtype='|S1')) 11 | True 12 | >>> np.all(char_star(charr) == np.array([['123', '123', '123'], ['123', '123', '123']], dtype='|S3')) 13 | True 14 | ''' 15 | 16 | # FIXME: 17 | # Yields a bus error -- passing an 'S3' when Fortran expects a character(len=1) 18 | # dtype. 19 | # Requires a runtime check to make sure the 'itemsize' of the dtype string 20 | # passed in == the 'len' of the fortran character dtype. 21 | # >>> np.all(char1_arr(charr) == np.array([['%', '%', '%'], ['%', '%', '%']], dtype='|S1')) 22 | -------------------------------------------------------------------------------- /tests/run/default_types.f90: -------------------------------------------------------------------------------- 1 | subroutine bar(a,b,d) 2 | implicit none 3 | integer :: a 4 | real :: b 5 | ! complex :: c 6 | double precision :: d 7 | ! logical :: e 8 | ! character :: f 9 | a = 1 10 | b = 2.0 11 | d = 3.0 12 | end subroutine bar 13 | -------------------------------------------------------------------------------- /tests/run/default_types_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from default_types_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> bar(100,200,300) == (1, 2.0, 3.0) 5 | True 6 | ''' 7 | -------------------------------------------------------------------------------- /tests/run/dim_expr.f90: -------------------------------------------------------------------------------- 1 | subroutine assumed_size(a) 2 | implicit none 3 | integer, dimension(10:*), intent(inout) :: a 4 | 5 | a(10:20) = 5 6 | 7 | end subroutine 8 | 9 | subroutine const_expr(a) 10 | implicit none 11 | integer, dimension(10:20), intent(inout) :: a 12 | integer i 13 | 14 | do i = 10, 20 15 | a(i) = i 16 | enddo 17 | 18 | end subroutine const_expr 19 | 20 | subroutine arg_expr(a, n1, n2) 21 | implicit none 22 | integer, intent(in) :: n1, n2 23 | integer, dimension(n1-n1+3:n1+n2*2) :: a 24 | 25 | a = 12 26 | 27 | end subroutine arg_expr 28 | 29 | subroutine param_expr(a) 30 | implicit none 31 | integer, parameter :: d1=1 32 | integer, parameter :: d2=d1+2+int(3.0) 33 | integer, parameter :: d3=d1+d2 34 | integer, dimension(d1:d2+d3, d2:d3+1, -d3:0) :: a 35 | 36 | integer i,j,k 37 | 38 | do k = lbound(a, 3), ubound(a, 3) 39 | do j = lbound(a, 2), ubound(a, 2) 40 | do i = lbound(a, 1), ubound(a, 1) 41 | a(i,j,k) = k + j + i 42 | enddo 43 | enddo 44 | enddo 45 | 46 | end subroutine param_expr 47 | -------------------------------------------------------------------------------- /tests/run/dim_expr_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from dim_expr_fwrap import * 2 | import numpy as np 3 | from numpy import array 4 | 5 | def test_const_expr(bad_size=False): 6 | u''' 7 | >>> test_const_expr() 8 | True 9 | 10 | >>> test_const_expr(bad_size=True) # doctest: +ELLIPSIS 11 | Traceback (most recent call last): 12 | ... 13 | RuntimeError: ... 14 | ''' 15 | lbound, ubound = 10, 20 16 | extent = ubound-lbound+1 17 | if bad_size: 18 | extent -= 2 19 | arr = np.empty(extent, dtype=np.int32, order='F') 20 | arr.fill(0) 21 | 22 | arr = const_expr(arr) 23 | return np.all(arr == array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])) 24 | 25 | def test_arg_expr(bad_size=False): 26 | u""" 27 | >>> test_arg_expr() 28 | True 29 | 30 | >>> test_arg_expr(bad_size=True) # doctest: +ELLIPSIS 31 | Traceback (most recent call last): 32 | ... 33 | RuntimeError: ... 34 | """ 35 | n1, n2 = 2, 3 36 | extent = (n1+n2*2) - (n1-n1+3) + 1 37 | if bad_size: 38 | extent -= 1 39 | arr = np.empty(extent, dtype=np.int32, order='F') 40 | res = arg_expr(arr, n1, n2) 41 | return np.all(res == 12) 42 | 43 | def test_param_expr(): 44 | u''' 45 | >>> test_param_expr() 46 | True 47 | ''' 48 | # integer, parameter :: d1=1, d2=d1+2+int(3.0), d3=d1+d2 49 | # integer, dimension(d1:d2+d3, d2:d3+1, -d3:0) :: a 50 | d1 = 1; d2 = d1+2+3; d3 = d1 + d2 51 | dim1 = (d2+d3)-(d1)+1 52 | dim2 = (d3+1)-(d2)+1 53 | dim3 = (0)-(-d3)+1 54 | 55 | arr = np.empty((dim1, dim2, dim3), dtype=np.int32, order='F') 56 | compare = arr.copy('F') 57 | 58 | for i_ in range(dim1): 59 | i = d1 + i_ 60 | for j_ in range(dim2): 61 | j = d2 + j_ 62 | for k_ in range(dim3): 63 | k = -d3 + k_ 64 | compare[i_,j_,k_] = i + j + k 65 | 66 | res = param_expr(arr) 67 | 68 | return np.all(res == compare) 69 | 70 | 71 | def test_assumed_size(): 72 | u''' 73 | >>> test_assumed_size() 74 | True 75 | ''' 76 | dim = 20-10+1 77 | arr = np.empty((dim,), dtype=fwi_integer, order='F') 78 | 79 | assumed_size(arr) 80 | 81 | return np.all(arr == 5) 82 | -------------------------------------------------------------------------------- /tests/run/func_returns.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | function lgcl_ret() 4 | implicit none 5 | logical :: lgcl_ret 6 | 7 | lgcl_ret = .true. 8 | 9 | end function 10 | 11 | function char_ret() 12 | implicit none 13 | character :: char_ret 14 | 15 | char_ret = 'k' 16 | 17 | end function 18 | -------------------------------------------------------------------------------- /tests/run/func_returns_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from func_returns_fwrap import * 2 | 3 | def test_rets(): 4 | u''' 5 | >>> test_rets() 6 | (True, 'k') 7 | ''' 8 | return (bool(lgcl_ret()), char_ret()) 9 | -------------------------------------------------------------------------------- /tests/run/int_args.f90: -------------------------------------------------------------------------------- 1 | 2 | function int_args_func(a,b,c,d) 3 | integer(kind=8) :: int_args_func 4 | integer(kind=1), intent(in) :: a 5 | integer(kind=2), intent(in) :: b 6 | integer(kind=4), intent(in) :: c 7 | integer(kind=8), intent(out) :: d 8 | 9 | d = a + b + c 10 | int_args_func = 10 11 | 12 | end function int_args_func 13 | 14 | subroutine int_args_subr(a,b,c,d) 15 | integer(kind=1), intent(in) :: a 16 | integer(kind=2), intent(in) :: b 17 | integer(kind=4), intent(in) :: c 18 | integer(kind=8), intent(out) :: d 19 | 20 | d = a + b + c 21 | 22 | end subroutine int_args_subr 23 | 24 | ! module dummy 25 | ! use iso_c_binding 26 | ! use kind_type_params 27 | ! integer, parameter :: fortran_int_1 = c_signed_char 28 | 29 | ! contains 30 | 31 | ! subroutine int_args_subr_wrap(a,b,c,d) bind(c,name="int_args_subr") 32 | ! implicit none 33 | ! integer(kind=fortran_int_1), intent(in) :: a 34 | ! integer(kind=c_short), intent(in) :: b 35 | ! integer(kind=c_int), intent(in) :: c 36 | ! integer(kind=c_int64_t), intent(out) :: d 37 | ! ! integer(kind=c_long), intent(in) :: a 38 | ! ! integer(kind=c_long), intent(in) :: b 39 | ! ! integer(kind=c_long), intent(in) :: c 40 | ! ! integer(kind=c_long), intent(out) :: d 41 | 42 | ! ! integer(kind=1) :: convert_a 43 | ! ! integer(kind=2) :: convert_b 44 | ! ! integer(kind=4) :: convert_c 45 | ! ! integer(kind=8) :: convert_d 46 | 47 | ! interface 48 | ! subroutine int_args_subr(a,b,c,d) 49 | ! use kind_type_params 50 | ! integer(kind=1), intent(in) :: a 51 | ! integer(kind=2), intent(in) :: b 52 | ! integer(kind=4), intent(in) :: c 53 | ! integer(kind=sik10), intent(out) :: d 54 | ! end subroutine int_args_subr 55 | ! end interface 56 | 57 | ! print *, "before call in wrapper in fortran" 58 | ! print *, a,b,c,d 59 | 60 | ! ! convert_a = a 61 | ! ! convert_b = b 62 | ! ! convert_c = c 63 | ! ! convert_d = d 64 | 65 | ! print *, "before call in wrapper in fortran, converted vals." 66 | ! print *, convert_a, convert_b, convert_c, convert_d 67 | 68 | ! ! call int_args_subr(convert_a,convert_b,convert_c,convert_d) 69 | ! call int_args_subr(a,b,c,d) 70 | 71 | ! ! d = convert_d 72 | 73 | ! ! print *, "after call in wrapper in fortran, converted vals." 74 | ! ! print *, convert_a, convert_b, convert_c, convert_d 75 | 76 | ! end subroutine int_args_subr_wrap 77 | ! end module dummy 78 | 79 | ! program blargh 80 | ! use dummy 81 | ! integer(kind=1) :: a 82 | ! integer(kind=2) :: b 83 | ! integer(kind=4) :: c 84 | ! integer(kind=8) :: d 85 | ! ! integer(kind=8) :: a 86 | ! ! integer(kind=8) :: b 87 | ! ! integer(kind=8) :: c 88 | ! ! integer(kind=8) :: d 89 | ! a = 1; b = 2; c = 3; d = 4 90 | ! call int_args_subr_wrap(a,b,c,d) 91 | ! print *, a,b,c,d 92 | ! end program blargh 93 | 94 | ! ==================== 95 | ! integer types 96 | ! -------------------- 97 | 98 | ! c_int 4 99 | ! c_short 2 100 | ! c_long 8 101 | ! c_long_long 8 102 | ! c_signed_char 1 103 | ! c_size_t 8 104 | ! c_int8_t 1 105 | ! c_int16_t 2 106 | ! c_int32_t 4 107 | ! c_int64_t 8 108 | ! c_int_least8_t 1 109 | ! c_int_least16_t 2 110 | ! c_int_least32_t 4 111 | ! c_int_least64_t 8 112 | ! c_int_fast8_t -2 113 | ! c_int_fast16_t -2 114 | ! c_int_fast32_t -2 115 | ! c_int_fast64_t -2 116 | ! c_intmax_t 8 117 | ! c_intptr_t 8 118 | 119 | ! ==================== 120 | ! real types 121 | ! -------------------- 122 | 123 | ! c_float 4 124 | ! c_double 8 125 | ! c_long_double 10 126 | 127 | ! ==================== 128 | ! complex types 129 | ! -------------------- 130 | 131 | ! c_float_complex 4 132 | ! c_double_complex 8 133 | ! c_long_double_complex 10 134 | 135 | ! ==================== 136 | ! logical types 137 | ! -------------------- 138 | 139 | ! c_bool 1 140 | 141 | ! ==================== 142 | ! character types 143 | ! -------------------- 144 | 145 | ! c_char 1 146 | 147 | ! module kind_type_params 148 | ! implicit none 149 | ! integer, parameter :: sik10 = selected_int_kind(10) 150 | 151 | ! end module kind_type_params 152 | -------------------------------------------------------------------------------- /tests/run/int_args_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from int_args_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> int_args_func(1,2,3) == (10, 6L) 5 | True 6 | >>> int_args_subr(1,2,3) == 6L 7 | True 8 | ''' 9 | -------------------------------------------------------------------------------- /tests/run/ndims.f90: -------------------------------------------------------------------------------- 1 | 2 | ! tests the number of dimensions with c_f_pointer since gfortran <=4.3.x 3 | ! has a buggy implementation. 4 | 5 | subroutine D1(a) 6 | implicit none 7 | logical*4, intent(out), dimension(:) :: a 8 | 9 | a = .true. 10 | a(::2) = .false. 11 | 12 | end subroutine D1 13 | 14 | subroutine D2(a) 15 | implicit none 16 | logical*4, intent(out), dimension(:,:) :: a 17 | 18 | a = .true. 19 | a(::2, ::2) = .false. 20 | 21 | end subroutine 22 | 23 | subroutine D3(a) 24 | implicit none 25 | logical*4, intent(out), dimension(:,:,:) :: a 26 | 27 | a = .true. 28 | a(::2, :, :) = .false. 29 | 30 | end subroutine 31 | -------------------------------------------------------------------------------- /tests/run/ndims_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from ndims_fwrap import * 2 | import numpy as np 3 | 4 | N = 5 5 | 6 | def test_D1(): 7 | ''' 8 | >>> test_D1() 9 | True 10 | ''' 11 | a = np.zeros((N,), dtype=np.bool_) 12 | acpy = a.copy() 13 | acpy[...] = True 14 | acpy[::2] = False 15 | ar = d1(a) 16 | return np.all(ar.astype(bool) == acpy) 17 | 18 | def test_D2(): 19 | ''' 20 | >>> test_D2() 21 | True 22 | ''' 23 | a = np.zeros((N,N), dtype=np.bool_) 24 | acpy = a.copy() 25 | acpy[...] = True 26 | acpy[::2, ::2] = False 27 | ar = d2(a) 28 | return np.all(ar.astype(bool) == acpy) 29 | 30 | def test_D3(): 31 | ''' 32 | >>> test_D3() 33 | True 34 | ''' 35 | a = np.zeros((N,N,N), dtype=np.bool_) 36 | acpy = a.copy() 37 | acpy[...] = True 38 | acpy[::2,:,:] = False 39 | ar = d3(a) 40 | return np.all(ar.astype(bool) == acpy.astype(bool)) 41 | -------------------------------------------------------------------------------- /tests/run/old_decl.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine bar(a,b,c,d,e,f) 3 | implicit none 4 | integer*4, intent(inout) :: a 5 | real*4, intent(inout) :: b,c 6 | real*8, intent(inout) :: d 7 | integer*8, intent(inout) :: e 8 | double precision, intent(inout) :: f 9 | 10 | a = 1 11 | b = 2 12 | c = 2 13 | d = 3 14 | e = 4 15 | f = 5 16 | 17 | end subroutine bar 18 | -------------------------------------------------------------------------------- /tests/run/old_decl_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from old_decl_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> bar(1,2,3,4,5,6) == (1, 2.0, 2.0, 3.0, 4L, 5.0) 5 | True 6 | ''' 7 | -------------------------------------------------------------------------------- /tests/todo/arr_mem_layout.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | subroutine mem_layout(arg) 4 | implicit none 5 | integer, dimension(:,:), intent(inout) :: arg 6 | 7 | integer i,j 8 | 9 | ! iterate through the array 2nd dimension first, in 'C' order 10 | do i = 1, size(arg, 1) 11 | do j = 1, size(arg, 2) 12 | print *, arg(i,j) 13 | enddo 14 | enddo 15 | 16 | end subroutine mem_layout 17 | -------------------------------------------------------------------------------- /tests/todo/arr_mem_layout_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from arr_mem_layout_fwrap import mem_layout 2 | import numpy as np 3 | 4 | __doc__ = u''' 5 | >>> a = np.arange(10).reshape(5,2).copy() 6 | >>> mem_layout(a.T) 7 | >>> mem_layout(a.T.copy()) 8 | ''' 9 | -------------------------------------------------------------------------------- /tests/todo/func_return_arr.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | function ret_arr(a, b) 4 | implicit none 5 | integer, intent(in) :: a, b 6 | integer, dimension(a, b) :: ret_arr 7 | 8 | ret_arr = 100 9 | ret_arr(1,:) = 0 10 | 11 | end function ret_arr 12 | -------------------------------------------------------------------------------- /tests/todo/func_return_arr_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from func_return_arr_fwrap import * 2 | import numpy as np 3 | 4 | a, b = 3, 5 5 | outarr = np.empty((a,b), dtype=np.int32, order='F') 6 | outarr.fill(-20) 7 | 8 | __doc__ = u''' 9 | >>> ret_arr(a, b) 10 | ''' 11 | -------------------------------------------------------------------------------- /tests/todo/kind_params.f90: -------------------------------------------------------------------------------- 1 | 2 | 3 | subroutine kind_params(a, b, c) 4 | implicit none 5 | integer, parameter :: int_ktp = kind(0), real_ktp = kind(0.0) 6 | integer, parameter :: dbl_ktp = kind(0.0D0) 7 | integer(kind=int_ktp), intent(inout) :: a 8 | real(kind=real_ktp), intent(inout) :: b 9 | real(kind=dbl_ktp), intent(inout) :: c 10 | 11 | a = int(a + b + c + 1, kind=int_ktp) 12 | b = a + 1.0 13 | c = b + 1.0D0 14 | 15 | end subroutine 16 | -------------------------------------------------------------------------------- /tests/todo/kind_params_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from kind_params_fwrap import * 2 | 3 | def test_kind_params(): 4 | ''' 5 | >>> test_kind_params() 6 | True 7 | ''' 8 | return kind_params(5, 5, 5) == (16, 17.0, 18.0) 9 | -------------------------------------------------------------------------------- /tests/todo/othermod.f95: -------------------------------------------------------------------------------- 1 | 2 | module other 3 | implicit none 4 | 5 | integer, parameter :: other_int = selected_real_kind(14) 6 | 7 | end module other 8 | -------------------------------------------------------------------------------- /tests/todo/test_scope.f95: -------------------------------------------------------------------------------- 1 | module mod1 2 | implicit none 3 | integer, parameter :: GP = 6 4 | ! module_provides = {GP} 5 | ! use_provides = {} 6 | end module mod1 7 | 8 | module mod2 9 | implicit none 10 | integer, parameter :: SP = 5 11 | ! module_provides = {SP} 12 | ! use_provides = {} 13 | end module mod2 14 | 15 | module mod3 16 | use mod1 17 | implicit none 18 | integer, parameter :: DP = 0 19 | ! module_provides = {DP} 20 | ! use_provides = {GP} 21 | end module mod3 22 | 23 | module mod4 24 | use mod2 25 | implicit none 26 | ! module_provides = {} 27 | ! use_provides = {SP} 28 | end module mod4 29 | 30 | module mod5 31 | use mod3, lGP => GP 32 | use mod4 33 | implicit none 34 | 35 | integer, parameter :: FP = 1000 36 | integer(kind=kind(0)) :: dummy 37 | parameter (dummy = 20) 38 | 39 | ! module_provides = {FP, dummy} 40 | ! use_provides = {lGP, DP, SP} 41 | end module mod5 42 | 43 | program driver 44 | use mod5 45 | implicit none 46 | 47 | print *, DP 48 | print *, SP 49 | print *, lGP 50 | print *, FP 51 | 52 | end program driver 53 | -------------------------------------------------------------------------------- /tests/todo/use_mod.f90: -------------------------------------------------------------------------------- 1 | module used 2 | implicit none 3 | 4 | integer, parameter :: dflt_int = kind(0) 5 | 6 | end module used 7 | 8 | subroutine s1(a) 9 | use used 10 | implicit none 11 | integer(kind=dflt_int), intent(inout) :: a 12 | a = 10 13 | end subroutine s1 14 | -------------------------------------------------------------------------------- /tests/todo/use_module.f95: -------------------------------------------------------------------------------- 1 | module other 2 | implicit none 3 | 4 | integer, parameter :: other_int = selected_real_kind(14) 5 | public :: other_int 6 | end module other 7 | 8 | module used 9 | use other, used_int => other_int 10 | implicit none 11 | 12 | integer, parameter :: r8 = selected_real_kind(10,10) 13 | integer, parameter :: foo = 4 14 | 15 | end module used 16 | 17 | module sub1 18 | use used 19 | implicit none 20 | end module sub1 21 | 22 | module sub2 23 | use used 24 | implicit none 25 | end module sub2 26 | 27 | module diamond 28 | use sub1 29 | use sub2 30 | implicit none 31 | end module diamond 32 | 33 | ! function user(arg0) 34 | ! use diamond, r4 => foo 35 | ! implicit none 36 | ! ! real(kind=r8), intent(in) :: arg0 37 | ! ! real(kind=r4), intent(in) :: arg0 38 | ! real(kind=used_int), intent(in) :: arg0 39 | ! real(kind=r8) user 40 | 41 | ! user = arg0 42 | 43 | ! end function user 44 | 45 | module conflict 46 | use sub2 47 | implicit none 48 | 49 | integer, parameter :: r8 = 4 50 | 51 | ! contains 52 | 53 | ! subroutine user(arg0) 54 | ! use sub2 55 | ! implicit none 56 | ! real(kind=r8), intent(inout) :: arg0 57 | 58 | ! arg0 = 10 59 | 60 | ! end subroutine 61 | 62 | end module 63 | 64 | 65 | 66 | 67 | ! program prog 68 | ! use diamond 69 | 70 | ! implicit none 71 | 72 | ! interface 73 | ! function user(arg) 74 | ! use diamond 75 | ! implicit none 76 | ! real(kind=r8), intent(in) :: arg 77 | ! real(kind=r8) user 78 | ! end function 79 | ! end interface 80 | 81 | ! print *, user(10.0_r8) 82 | 83 | ! end program 84 | -------------------------------------------------------------------------------- /tests/todo/use_module_fwrap_doctest.py: -------------------------------------------------------------------------------- 1 | from use_module_fwrap import * 2 | 3 | __doc__ = u''' 4 | >>> user(10.0) 5 | (10.0,) 6 | ''' 7 | --------------------------------------------------------------------------------