This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Type-bound procedure and procedure pointer component calls


Hi Janus,

thanks for the comments!

Janus Weil wrote:
Add a new ref-type REF_PROC or extend REF_COMPONENT with an attribute to
hold an actual arglist; then in match_varspec, if a component symbol is
found that is in the type-bound procedures namespace, parse an arglist
following it and build such a REF_PROC:

WRITE (*,*) val(1)%tbp_function (42)

will become

EXPR_VARIABLE(val) -> REF_ARRAY(1) -> REF_PROC(arglist(42), gfc_typebound*)

Sounds good. Alternatively the arglist could be stored in the top level gfc_expr, which already has a field for it (expr->value.function.actual). Then I think we also need a new expression type (EXPR_SUBROUTINE?) for the case that the TBP/PPC is a subroutine. For functions we can probably reuse the existing EXPR_FUNCTION.

Actually, so far I thought about the gfc_expr only as a means to reuse match_varspec and until we do something with the matched data after that in parsing or resolution. I don't quite like the idea of gfc_expr holding a SUBROUTINE "officially". This from my point of view somewhat defeats the purpose of an "expression". OTOH of course, this makes handling a bit easier.


I'd rather go for using EXPR_FUNCTION for both subroutines and functions and allow the exception that gfc_code->expr of a CALL statement can/must be an EXPR_FUNCTION expression referencing a SUBROUTINE. As for the arglist, if we do EXPR_FUNCTION it is of course a good idea to reuse value.function.actual (if we use another type, I don't think its a good idea to use the function-specific union).

I just realize that for EXPR_FUNCTION the symtree member will be treated as the function to call, won't it? Thus it is probably safer to use a new expr-type for "component-calls".

During resolution, we can transform such an expression easily into an
ordinary function call; the passed-object will be given by the expression
itself with the last reference removed, and the other things needed for the
call (the binding-target procedure and the arglist) are in the REF_PROC.

Ok. However, this "transforming to ordinary function call" does not work for PPCs of course. There we need dynamic calling, which will also be necessary for TBPs later to have fully dynamic polymorphism (once the other OOP bits are in place). So, at *some* point this will have to be implemented in a dynamic way. The question is: Should we already do this now, or rather start with a static transformation at resolution stage? The advantage of the dynamic approach would be that it's more or less the same for both TBPs and PPCs, so that we hopefully need only one implementation. And we wouldn't have to change it later for full OOP.

Agreed. However, for dynamic dispatch and TBPs to work, we need Paul's CLASS implementation. Until then, I think for TBPs it will be best to implement them at first the quick way and work out a dynamic implementation later; at least I do want to look how big the patch gets and how easy such an implementation will be.


But of course it is good to find a common strategy that can be used for that implementation and for PPCs. If we use a new expr-type as suggested above, it should not be too hard to integrate it into the trans-phase with whatever implementation we need for it, I think. That could be something like:

expr.expr_type = EXPR_COMPCALL;
expr.symtree = ...; expr.ref = ...;
expr.value.compcall.actual = arglist;
expr.value.compcall.derived = derived;
expr.value.compcall.comp = comp;

Where symtree/ref contain the originally parsed ref-chain leading to the called component, arglist is the actual arglist that is still resolved to contain the passed-object during resolution, derived is the declared derived-type of the passed-object and comp is the called component, either as symtree for TBPs or gfc_component for PPCs (some way to store it at least).

This would not change any existing code in respect to EXPR_FUNCTION of course and we would "simply" have to implement trans of EXPR_COMPCALL the way we need to do it. If possible (for now and maybe NON_OVERRIDABLE methods or something like this) we could also handle EXPR_COMPCALL in resolution.

For PPCs, we need to extend the expr.value.compcall structure and do the right trans'ing, but otherwise it should be fine?

For CALL's, we could add a new field

gfc_expr* tbp;

to gfc_code.  If not NULL it will hold such a reference-expression as above
encapsulating the TBP-call.  Once again, during resolution this will be
transformed into an ordinary CALL of a SUBROUTINE.

Do you think an extra field is necessary? gfc_code already has two gfc_expr fields ("expr" and "expr2"), none of which is being used for CALL. And the type of the expression will in any way be indicated by expr->expr_type (EXPR_SUBROUTINE/EXPR_FUNCTION/etc).

To implement CALL's, we need a way to distinguish between ordinary calls and component calls, too, maybe a flag or another EXEC_ type (I'm not sure how much change this would mean). Then once more again, in trans look at the type and either call the referenced symtree as we do now or call the EXPR_COMPCALL stored in expr.


Maybe it would be a good idea to start with a patch that changes the
way that ordinary functions and subroutines are called (by using
gfc_expr instead of gfc_symtree), so that this can more easily be
extended to TBPs and PPCs.

If we do so, we could as well call them through the completely new gfc_callee structure, couldn't we? If we don't want to go through all that code changes needed to accomplish that, I think we should stick to only extending by new means to call components with dynamic dispatching as written above. What would you change and what would you leave?


Maybe some of the more experienced gfortraners could try to comment on
all of this. I'm not sure if I'm overlooking all the consequences of
our design decisions right now.

That's a very good idea indeed :D


BTW, why can't we transform PPC-calls to calls to ordinary procedure-pointers with adapted arglist? I have to admit though that I know nearly nothing about procedure-pointers in Fortran nor about your implementation of them.

So far,
Daniel

--
Done:     Arc-Bar-Cav-Sam-Val-Wiz, Dwa-Elf-Gno-Hum-Orc, Law-Neu-Cha, Fem-Mal
To go:    Hea-Kni-Mon-Pri-Ran-Rog-Tou


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]