Fortran-FOSS-Programmers / ford

Automatically generates FORtran Documentation from comments within the code.
https://forddocs.readthedocs.io
GNU General Public License v3.0
410 stars 134 forks source link

Failure in generating HTML with procedure statement #202

Closed sfilippone closed 6 years ago

sfilippone commented 7 years ago

Hi there, First of all, let me say that in general this tool rocks! However, I am getting this error with version 5.0.6

[sfilippo@localhost psblas3]$ ford --debug psblas-ford-doc.md
Reading file base/modules/psblas/psb_d_psblas_mod.F90

Processing documentation comments...
Correlating information from different parts of your project...

Generating graphs...
Creating HTML documentation...
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/ford/output.py", line 111, in __init__
    self.docs.append(ProcPage(data,project,item))
  File "/usr/lib/python2.7/site-packages/ford/output.py", line 208, in __init__
    self.html = self.render(data,proj,obj)
  File "/usr/lib/python2.7/site-packages/ford/output.py", line 358, in render
    return template.render(data,interface=obj,project=proj)
  File "/usr/lib/python2.7/site-packages/jinja2/environment.py", line 989, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/lib/python2.7/site-packages/jinja2/environment.py", line 754, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/python2.7/site-packages/ford/templates/genint_page.html", line 1, in top-level template code
    {% extends "base.html" %}
  File "/usr/lib/python2.7/site-packages/ford/templates/base.html", line 138, in top-level template code
    {% block body %}
  File "/usr/lib/python2.7/site-packages/ford/templates/genint_page.html", line 55, in block "body"
    {{ macros.proc_entry(proc.procedure) }}
  File "/usr/lib/python2.7/site-packages/ford/templates/macros.html", line 707, in template
    <div class="panel-heading codesum"><span class="anchor" id="{{ proc.anchor }}"></span><h3>{{ proc_line(proc) }}</h3></div>
  File "/usr/lib/python2.7/site-packages/ford/templates/macros.html", line 563, in template
    {% if proc.meta['deprecated'] and proc.meta['deprecated'].lower() == 'true' %}
  File "/usr/lib/python2.7/site-packages/jinja2/environment.py", line 389, in getitem
    return obj[argument]
UndefinedError: 'None' has no attribute 'meta'
Error encountered.

with the attached source file psbd_psblas_mod.F90, when I specify as preprocessor the string gfortran -E.


module psb_d_psblas_mod
  use psb_desc_mod, only : psb_desc_type, psb_dpk_, psb_ipk_
  use psb_d_vect_mod, only : psb_d_vect_type
  use psb_d_mat_mod, only : psb_dspmat_type

  interface psb_geamax
    function psb_damax(x, desc_a, info, jx)
      import :: psb_desc_type, psb_dpk_, psb_ipk_, &
           & psb_d_vect_type, psb_dspmat_type
      real(psb_dpk_)   psb_damax
      real(psb_dpk_), intent (in)       :: x(:,:)
      type(psb_desc_type), intent (in)    :: desc_a
      integer(psb_ipk_), optional, intent (in)      :: jx
      integer(psb_ipk_), intent(out)                :: info
    end function psb_damax
    function psb_damaxv(x, desc_a,info)
      import :: psb_desc_type, psb_dpk_, psb_ipk_, &
           & psb_d_vect_type, psb_dspmat_type
      real(psb_dpk_) psb_damaxv
      real(psb_dpk_), intent (in)       :: x(:)
      type(psb_desc_type), intent (in)    :: desc_a
      integer(psb_ipk_), intent(out)                :: info
    end function psb_damaxv
    function psb_damax_vect(x, desc_a, info) result(res)
      import :: psb_desc_type, psb_dpk_, psb_ipk_, &
           & psb_d_vect_type, psb_dspmat_type
      real(psb_dpk_)                        :: res
      type(psb_d_vect_type), intent (inout) :: x
      type(psb_desc_type), intent (in)      :: desc_a
      integer(psb_ipk_), intent(out)                  :: info
    end function psb_damax_vect
  end interface

#if ! defined(HAVE_BUGGY_GENERICS)
  interface psb_genrmi
    procedure psb_damax, psb_damaxv, psb_damax_vect
  end interface 
  interface psb_normi
    procedure psb_damax, psb_damaxv, psb_damax_vect
  end interface 
#endif

end module psb_d_psblas_mod

The problem seems to be the procedure statement, because if I change the preprocessor to gfortran -E -DHAVE_BUGGY_GENERICS it works. (as an aside, from the name of the variable, you can see that I have encountered compilers that fail to honour the specification....) Thanks Salvatore

zbeekman commented 7 years ago

Hi Salvatore,

No idea whether or not this will be a useful suggestion, as I have yet to test it, but I'm wondering if a temporary workaround might be to add a double colon after the procedure declaration. Or even declare with the f90/f95 syntax as module procedure ::.

Just FYI, the formatting makes your comment somewhat difficult to read. If you put ``` on lines before and after your code this will create a "fenced code block" which will use a mono-space font and preserve all input without trying to render it as markdown. e.g.,

```bash
[sfilippo@localhost psblas3]$ ford --debug psblas-ford-doc.md
Reading file base/modules/psblas/psb_d_psblas_mod.F90

Processing documentation comments...
Correlating information from different parts of your project...
# etc.
```

As you can see in the above example, you can optionally embed the language name immediately following the first ```and this will give colored syntax highlighting:

[sfilippo@localhost psblas3]$ ford --debug psblas-ford-doc.md
Reading file base/modules/psblas/psb_d_psblas_mod.F90

Processing documentation comments...
Correlating information from different parts of your project...
# etc.
sfilippone commented 7 years ago

Sorry for the bad formatting, this is my first issue raised here, I'll have to go study the interface. Your suggestion of using

procedure ::

does not cure the ICE. As for using

module procedure

that would not work because those symbols are referring to interfaces for subroutines implemented elsewhere. All this predates the availability of submodules, so at some point I'll bite the bullet and move to submodules. Salvatore (Let's see if this post is formatted decently)

cmacmackin commented 7 years ago

I can't investigate this right now, as my laptop is currently away being repaired. Hopefully it will be fixed by next weekend and, since doing so is long overdue, I will start going through bug reports then.

zbeekman commented 7 years ago

Salvatore (Let's see if this post is formatted decently)

Beautiful! (It just makes it a bit easier to follow, and without the formatting, Github will eat certain characters that it believes to be for formatting)

sfilippone commented 7 years ago

Hi Any news on this issue? Thanks

zbeekman commented 7 years ago

Is the FORD project file available anywhere? Were you running it from the root of https://github.com/sfilippone/psblas3 on the master branch?

If you help me reproduce this (and I have time) I may try running it with a more up to date fork of FORD and also seeing if I can debug it.

sfilippone commented 7 years ago

Minimum file attached. Ideally I would want to parse the entire project, but this is sufficent to reproduce the bug, and yes, it's from the root of the master branch of https://github.com/sfilippone/psblas3 Thanks S.

---
project: PSBLAS
summary: Parallel Sparse Basic Linear Algebra Subroutines
src_dir: base/modules/serial
src_dir: base/modules/desc
output_dir: ford-doc
preprocessor: gfortran -E -DHAVE_BUGGY_GENERICS
preprocess: true
display: public
         protected
         private
source: true
graph: true
sort: alpha
extra_mods: iso_fortran_env:https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fFORTRAN_005fENV.html
print_creation_date: true
creation_date: %Y-%m-%d %H:%M %z
project_download: https://github.com/sfilippone/psblas3
license: bsd
author: Salvatore Filippone
email: salvatore.filippone@cranfield.ac.uk
author_description: Lecturer
author_pic: https://www.cranfield.ac.uk/~/media/people/794215.ashx?w=200
website: https://www.cranfield.ac.uk/people/dr-salvatore-filippone-794215
---

[source: display source code corresponding to item being documented]:#
[graph: generate call graphs, module dependency graphs, derive type composition/inheritance graphs ]:#
[sort: different sorting schemes for the modules or procedures or programs or derived types (alpha = alphabetical see wiki).]:#
[extra_mods: documentation for intrinsic modules]:#

[This document is a FORD project file, formatted with Pythonic Markdown                                      ]:#
[See https://github.com/cmacmackin/ford/wiki/Project-File-Options for more info on writing FORD project files]:#

--------------------

Brief description
-----------------

@warning
This archive uses advaned features of Fortran 2015.  As of October 2016, only GNU Fortran compiler supports all features employed.

### ToDo

X marks directories being documented:

 - [X] Done [pargen](./test/pargen)
 - [X] Done [krylov](./krylov)
 - [ ] To Do [something](./prec)

Compilers
---------

This archive has been tested with GNU Fortran compiler (gfortran) 6.3.0 with the MPICH implementation of MPI 
cmacmackin commented 6 years ago

Sorry it has taken me so long to work on this bug. Life seemed to keep getting in the way. Is this legal syntax? I wasn't aware that procedures specified within generic interfaces could be accessed on their own. I've looked through section 12.4.3.4 of the draft 2008 standard and can't find anything which says either way.

zbeekman commented 6 years ago

@cmacmackin I'm not sure I 100% follow what you're asking---are you wondering if it is legal for psb_damax to be used in the psb_genrmi and/or psb_normi interface blocks?

In 12.4.3.2 of F2008:

3 The name of the entity declared by an interface body is the function-name in the function-stmt or the subroutine-name in the subroutine-stmt that begins the interface body

My reading of this is that this is true with or without a generic-spec. Then 12.4.3.4.1(2) says:

The generic-spec in an interface-stmt is a generic identifier for all the procedures in the interface block. ...

Personal experience also seems to indicated that this is perfectly legal. After all, you can have a module procedure that you specify a generic interface for, but you can still reference the module procedure on its own. (Module procedures have explicit interfaces.)

cmacmackin commented 6 years ago

@zbeekman Yes, that's what I'm asking. Module procedures within a generic interface have their explicit interface defined elsewhere. To me it feels wrong to use an explicit interface defined withing a generic interface because it's like you're doing two things at once (declaring explicit interfaces for those procedures while also declaring a generic interface). It feels tidier to me to define the explicit interfaces in their own block and then have a separate generic interface block. Doesn't make it illegal syntax, mind, just how I'd lay out my code.

cmacmackin commented 6 years ago

I've updated FORD so it now knows to consider non-module procedure entries to generic interfaces. This fixes the bug. These changes will be in the next release.