Re: semantic-analyze-current-context for fortran functions and subroutine
Eric Ludlam <[email protected]> Tue, 10 Feb 2015 21:18:15 -0500
| Newsgroups | gmane.emacs.cedet |
|---|---|
| Message-ID | <[email protected]> |
On 02/10/2015 06:02 AM, Martin Stein wrote:
>> For the current-symbol, we could update elements related to looking at
>> the type relation separator and see if we can enable a language to
>> extend it to include looking at continuation symbols.
>
> That will not work, continuation lines are too complex, here is an example of a variable declaration:
>
> integer :: my_var
>
> can also be spread like this
>
> integer :: & ! i need a comment here
>
> ! empty lines as above are allowed as well
> my_var
That doesn't look too bad. MATLAB code has similar problems, and I
wrote a simple routine that just does a quick check for ... (the
continuation sequence) and then can skip over all intervening blank and
comments. Though I don't have this type of semantic support, the same
type of fcn could be used to skip intervening non-code. We'll just need
to call out to a routine for skipping such text.
> Moreover, I guess there is no chance to generalise up-list to something working for fortran. In fact, my semantic-up-context
> version can be viewed as an implementation of (up-list -1). It is almost as complex as lexing itself, so I have resolved to
> use tags among other things to find the context up one step. Same goes for forward-sexp...
Ok, that's too bad, and you will need some custom routines. I had to do
the same in MATLAB. If it turns out your lexer was taught how to find
fortran versions of blocks/lists then you could use that to help.
> Here are some more of the differences with which I have struggled, am currently struggling with or will need to face one day:
>
> * There is no "return" for function values in Fortran, instead a local variable is used for that. For two variants of function
> declarations the local variable has the same name as the function itself -> two tags of the same name, which requires the right
> choice depending on the context. (Currently resolved by adding a 'mustbefunction flag to semantic-analyze-find-tag-sequence.)
>
>
> * Subroutines (= void function) are invoked with a call -> a new derived context is required. Done.
>
>
> * 'use module_name' (a bit like 'using namespace namespace_name') would require a new context for completion. As far as I can see
> completion for C++ offers far more than the meaningful tags.
>
>
> * Functions and subroutines are not allowed at the beginning of a command. Hopefully just a proper choice of prefixclasses.
>
>
> * derived types (= struct in C) are declared like
>
> type(my_type_name) :: my_var
>
> Derived type my_type_name is defined somewhere and a tag ("my_type_name" 'type :type "derivedtype") exists. This looks a bit
> like a functionarg context, but I would rather like to generate a new context similar to the subroutine context. This is simple.
For the above, I have a couple thoughts.
One is that when it comes to parsing tags, or interpreting code, I let
the compile figure out what is "correct", and end up with a very
permissive code that will try to provide a tag set or completion
suggestion. This is for a few reasons.
First, most people try to write correct code, and don't want me
providing bad suggestions. Second, I'm kind of lazy. Third, the parser
or completion engine sometimes is missing some data, so I'll just try
for whatever I can figure out to work around the issue.
My second thought is around supplying new context types. If something
makes sense, we should consider supporting it in the core.
> * I guess there is no such concept as generic names in C. It looks like
>
> interface my_subr
> module procedure my_subr_array
> module procedure my_subr_list
> module procedure my_subr_string
> end interface my_fun
>
> The three subroutines my_subr_*** themselves are placed elsewhere.
> Now a user can (or even must depending on protection) call the three subroutines by their generic name my_subr.
> The choice which subroutine to call is done depending on the type signature. Now completion should take this
> into accout and merge the type signatures (including different number of arguments) of the three possible subroutines.
> Once some arguments are provided sort out non-fitting type signatures and offer only those still possible. To make matters
> worse my_subr interface declarations can be quite scattered and merging is required. This is for another day.
I can't claim to have completely followed this description, but a simple
solution is to just expand the one my_subr into three versions of the
same thing. Possibly in the tag expansion after parsing, or possibly
when producing the list of matching tags by name. That may be too messy
though.
An alternative would be to make `semantic-tag-of-type-p' an overloadable
method, and fortran could check all three versions for a type match
which should bubble back up into the completion engine. (I'm guessing)
> * As mentioned previously, in order to fit the contains part of functions and subroutines into the C tag structure a
> "contains" tag of class 'type and :type "contains" is generated, which solved quite a bit of problems. However, this now appears
> in the completion list and must be removed somehow. The same holds for modules, represented by type tags of :type "module".
> (This problem is partly due to the fact that there is no referencing like my_module::my_fun for a function my_fun contained
> within my_module as with namespaces.)
>
> In order to solve this a general tag predicate additionally or in place of prefixclass would be helpful.
> Prefixclass implicitely defines such a predicate by
>
> (lambda (tag) (memq (semantic-tag-class tag) prefixclass)).
>
> I am very well aware that some of the not too many uses of prefixclass are like
> (memq 'filename (oref context :prefixclass))
> and so do not fit the tag-predicate view. But I might have missed something.
>
> For contains/modules the predicate for sorting out those undesired tags would be
> (lambda (tag) (let ((type (semantic-tag-type tag))
> (not (and (string-p type)
> (or (string= type "module"))
> (string= type "contains"))))))
>
> The default semantic-analyze-possible-completions routine as well as the one overloaded by clang have some predicates of this kind as well
> (filtering out constructors, destructors, operators). I guess I will start experimenting with a new slot :prefixpredicate. However,
> I am a bit worried because these concepts (prefixclass, method semantic-analyze-type-constraint and a predicate) somewhat overlap with each other.
It probably makes sense to extract the inline code for constructors,
destructors, etc into a predicate that is an overloadable function. It
looks to me like I was just lazy when I put that together, and it was
harmless in cases where it wasn't relevant.
I would think a predicate of things to remove from a completion list
would be fine.
The different filters you listed do seem to overlap, but come from
different places. The prefixclass is basically from
`semantic-ctxt-current-class-list' is based on where you are. For
example, what you complete is different if you are in a fcn body, or in
declaration space.
The typeconstraint is if the value is being assigned somewhere.
Your predicate is much like the constructor/operator case. Those types
are just not relevant and should be skipped. Thus, I think refactoring
to make that behavior accessible to fortran modification makes sense.
I hope this helps.
Eric
------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/