Commit a64a8f2f by Daniel Kraft Committed by Daniel Kraft

gfc-internals.texi (F2003 OOP), [...]): New chapter and section to document the…

gfc-internals.texi (F2003 OOP), [...]): New chapter and section to document the internals of type-bound procedures.

2008-09-01  Daniel Kraft  <d@domob.eu>

	* gfc-internals.texi (F2003 OOP), (Type-bound Procedures): New chapter
	and section to document the internals of type-bound procedures.
	(gfc_expr): Document EXPR_COMPCALL.
	* gfortran.h (struct gfc_expr): Remove unused `derived' from compcall.
	* dump-parse-tree.c (show_compcall): New method.
	(show_expr): Call it for EXPR_COMPCALL.
	(show_typebound), (show_f2k_derived): New methods.
	(show_symbol): Call show_f2k_derived.
	(show_code_node): Handle EXEC_COMPCALL.
	* primary.c (gfc_match_varspec): Don't initialize removed `derived' in
	primary->value.compcall.

From-SVN: r139857
parent f69bbb46
2008-09-01 Daniel Kraft <d@domob.eu>
* gfc-internals.texi (F2003 OOP), (Type-bound Procedures): New chapter
and section to document the internals of type-bound procedures.
(gfc_expr): Document EXPR_COMPCALL.
* gfortran.h (struct gfc_expr): Remove unused `derived' from compcall.
* dump-parse-tree.c (show_compcall): New method.
(show_expr): Call it for EXPR_COMPCALL.
(show_typebound), (show_f2k_derived): New methods.
(show_symbol): Call show_f2k_derived.
(show_code_node): Handle EXEC_COMPCALL.
* primary.c (gfc_match_varspec): Don't initialize removed `derived' in
primary->value.compcall.
2008-08-31 Richard Guenther <rguenther@suse.de> 2008-08-31 Richard Guenther <rguenther@suse.de>
* trans-expr.c (gfc_trans_string_copy): Use the correct types * trans-expr.c (gfc_trans_string_copy): Use the correct types
......
...@@ -316,6 +316,22 @@ show_char_const (const gfc_char_t *c, int length) ...@@ -316,6 +316,22 @@ show_char_const (const gfc_char_t *c, int length)
fputc ('\'', dumpfile); fputc ('\'', dumpfile);
} }
/* Show a component-call expression. */
static void
show_compcall (gfc_expr* p)
{
gcc_assert (p->expr_type == EXPR_COMPCALL);
fprintf (dumpfile, "%s", p->symtree->n.sym->name);
show_ref (p->ref);
fprintf (dumpfile, "%s", p->value.compcall.name);
show_actual_arglist (p->value.compcall.actual);
}
/* Show an expression. */ /* Show an expression. */
static void static void
...@@ -539,6 +555,10 @@ show_expr (gfc_expr *p) ...@@ -539,6 +555,10 @@ show_expr (gfc_expr *p)
break; break;
case EXPR_COMPCALL:
show_compcall (p);
break;
default: default:
gfc_internal_error ("show_expr(): Don't know how to show expr"); gfc_internal_error ("show_expr(): Don't know how to show expr");
} }
...@@ -646,6 +666,76 @@ show_components (gfc_symbol *sym) ...@@ -646,6 +666,76 @@ show_components (gfc_symbol *sym)
} }
/* Show the f2k_derived namespace with procedure bindings. */
static void
show_typebound (gfc_symtree* st)
{
if (!st->typebound)
return;
show_indent ();
if (st->typebound->is_generic)
fputs ("GENERIC", dumpfile);
else
{
fputs ("PROCEDURE, ", dumpfile);
if (st->typebound->nopass)
fputs ("NOPASS", dumpfile);
else
{
if (st->typebound->pass_arg)
fprintf (dumpfile, "PASS(%s)", st->typebound->pass_arg);
else
fputs ("PASS", dumpfile);
}
if (st->typebound->non_overridable)
fputs (", NON_OVERRIDABLE", dumpfile);
}
if (st->typebound->access == ACCESS_PUBLIC)
fputs (", PUBLIC", dumpfile);
else
fputs (", PRIVATE", dumpfile);
fprintf (dumpfile, " :: %s => ", st->n.sym->name);
if (st->typebound->is_generic)
{
gfc_tbp_generic* g;
for (g = st->typebound->u.generic; g; g = g->next)
{
fputs (g->specific_st->name, dumpfile);
if (g->next)
fputs (", ", dumpfile);
}
}
else
fputs (st->typebound->u.specific->n.sym->name, dumpfile);
}
static void
show_f2k_derived (gfc_namespace* f2k)
{
gfc_finalizer* f;
++show_level;
/* Finalizer bindings. */
for (f = f2k->finalizers; f; f = f->next)
{
show_indent ();
fprintf (dumpfile, "FINAL %s", f->proc_sym->name);
}
/* Type-bound procedures. */
gfc_traverse_symtree (f2k->sym_root, &show_typebound);
--show_level;
}
/* Show a symbol. If a symbol is an ENTRY, SUBROUTINE or FUNCTION, we /* Show a symbol. If a symbol is an ENTRY, SUBROUTINE or FUNCTION, we
show the interface. Information needed to reconstruct the list of show the interface. Information needed to reconstruct the list of
specific interfaces associated with a generic symbol is done within specific interfaces associated with a generic symbol is done within
...@@ -701,6 +791,13 @@ show_symbol (gfc_symbol *sym) ...@@ -701,6 +791,13 @@ show_symbol (gfc_symbol *sym)
show_components (sym); show_components (sym);
} }
if (sym->f2k_derived)
{
show_indent ();
fputs ("Procedure bindings:\n", dumpfile);
show_f2k_derived (sym->f2k_derived);
}
if (sym->formal) if (sym->formal)
{ {
show_indent (); show_indent ();
...@@ -1110,6 +1207,11 @@ show_code_node (int level, gfc_code *c) ...@@ -1110,6 +1207,11 @@ show_code_node (int level, gfc_code *c)
show_actual_arglist (c->ext.actual); show_actual_arglist (c->ext.actual);
break; break;
case EXEC_COMPCALL:
fputs ("CALL ", dumpfile);
show_compcall (c->expr);
break;
case EXEC_RETURN: case EXEC_RETURN:
fputs ("RETURN ", dumpfile); fputs ("RETURN ", dumpfile);
if (c->expr) if (c->expr)
......
...@@ -118,6 +118,7 @@ not accurately reflect the status of the most recent GNU Fortran compiler. ...@@ -118,6 +118,7 @@ not accurately reflect the status of the most recent GNU Fortran compiler.
* User Interface:: Code that Interacts with the User. * User Interface:: Code that Interacts with the User.
* Frontend Data Structures:: * Frontend Data Structures::
Data structures used by the frontend Data structures used by the frontend
* Object Orientation:: Internals of Fortran 2003 OOP features.
* LibGFortran:: The LibGFortran Runtime Library. * LibGFortran:: The LibGFortran Runtime Library.
* GNU Free Documentation License:: * GNU Free Documentation License::
How you can copy and share this manual. How you can copy and share this manual.
...@@ -466,6 +467,13 @@ function symbol if the call is to an intrinsic or external function, ...@@ -466,6 +467,13 @@ function symbol if the call is to an intrinsic or external function,
respectively. These values are determined during resolution-phase from the respectively. These values are determined during resolution-phase from the
structure's @code{symtree} member. structure's @code{symtree} member.
A special case of function calls are ``component calls'' to type-bound
procedures; those have the @code{expr_type} @code{EXPR_COMPCALL} with
@code{value.compcall} containing the argument list and the procedure called,
while @code{symtree} and @code{ref} describe the object on which the procedure
was called in the same way as a @code{EXPR_VARIABLE} expression would.
@xref{Type-bound Procedures}.
@subsection Array- and Structure-Constructors @subsection Array- and Structure-Constructors
...@@ -552,6 +560,96 @@ substring reference as described in the subsection above. ...@@ -552,6 +560,96 @@ substring reference as described in the subsection above.
@c --------------------------------------------------------------------- @c ---------------------------------------------------------------------
@c F2003 OOP
@c ---------------------------------------------------------------------
@node Object Orientation
@chapter Internals of Fortran 2003 OOP Features
@menu
* Type-bound Procedures:: Type-bound procedures.
@end menu
@c Type-bound procedures
@c ---------------------
@node Type-bound Procedures
@section Type-bound Procedures
Type-bound procedures are stored in the @code{sym_root} of the namespace
@code{f2k_derived} associated with the derived-type symbol as @code{gfc_symtree}
nodes. The name and symbol of these symtrees corresponds to the binding-name
of the procedure, i.e. the name that is used to call it from the context of an
object of the derived-type.
In addition, those and only those symtrees representing a type-bound procedure
have their @code{typebound} member set; @code{typebound} points to a struct of
type @code{gfc_typebound_proc} containing the additional data needed: The
binding attributes (like @code{PASS} and @code{NOPASS}, @code{NON_OVERRIDABLE}
or the access-specifier), the binding's target(s) and, if the current binding
overrides or extends an inherited binding of the same name, @code{overridden}
points to this binding's @code{gfc_typebound_proc} structure.
@subsection Specific Bindings
@c --------------------------
For specific bindings (declared with @code{PROCEDURE}), if they have a
passed-object argument, the passed-object dummy argument is first saved by its
name, and later during resolution phase the corresponding argument is looked for
and its position remembered as @code{pass_arg_num} in @code{gfc_typebound_proc}.
The binding's target procedure is pointed-to by @code{u.specific}.
At the moment, all type-bound procedure calls are statically dispatched and
transformed into ordinary procedure calls at resolution time; their actual
argument list is updated to include at the right position the passed-object
argument, if applicable, and then a simple procedure call to the binding's
target procedure is built. To handle dynamic dispatch in the future, this will
be extended to allow special code generation during the trans-phase to dispatch
based on the object's dynamic type.
@subsection Generic Bindings
@c -------------------------
Bindings declared as @code{GENERIC} store the specific bindings they target as
a linked list using nodes of type @code{gfc_tbp_generic} in @code{u.generic}.
For each specific target, the parser records its symtree and during resolution
this symtree is bound to the corresponding @code{gfc_typebound_proc} structure
of the specific target.
Calls to generic bindings are handled entirely in the resolution-phase, where
for the actual argument list present the matching specific binding is found
and the call's target procedure (@code{value.compcall.tbp}) is re-pointed to
the found specific binding and this call is subsequently handled by the logic
for specific binding calls.
@subsection Calls to Type-bound Procedures
@c ---------------------------------------
Calls to type-bound procedures are stored in the parse-tree as @code{gfc_expr}
nodes of type @code{EXPR_COMPCALL}. Their @code{value.compcall.actual} saves
the actual argument list of the call and @code{value.compcall.tbp} points to the
@code{gfc_typebound_proc} structure of the binding to be called. The object
in whose context the procedure was called is saved by combination of
@code{symtree} and @code{ref}, as if the expression was of type
@code{EXPR_VARIABLE}.
For code like this:
@smallexample
CALL myobj%procedure (arg1, arg2)
@end smallexample
@noindent
the @code{CALL} is represented in the parse-tree as a @code{gfc_code} node of
type @code{EXEC_COMPCALL}. The @code{expr} member of this node holds an
expression of type @code{EXPR_COMPCALL} of the same structure as mentioned above
except that its target procedure is of course a @code{SUBROUTINE} and not a
@code{FUNCTION}.
@c ---------------------------------------------------------------------
@c LibGFortran @c LibGFortran
@c --------------------------------------------------------------------- @c ---------------------------------------------------------------------
......
...@@ -1593,7 +1593,6 @@ typedef struct gfc_expr ...@@ -1593,7 +1593,6 @@ typedef struct gfc_expr
{ {
gfc_actual_arglist* actual; gfc_actual_arglist* actual;
gfc_typebound_proc* tbp; gfc_typebound_proc* tbp;
gfc_symbol* derived;
const char* name; const char* name;
} }
compcall; compcall;
......
...@@ -1779,7 +1779,6 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag) ...@@ -1779,7 +1779,6 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag)
primary->expr_type = EXPR_COMPCALL; primary->expr_type = EXPR_COMPCALL;
primary->value.compcall.tbp = tbp->typebound; primary->value.compcall.tbp = tbp->typebound;
primary->value.compcall.derived = sym;
primary->value.compcall.name = tbp->name; primary->value.compcall.name = tbp->name;
gcc_assert (primary->symtree->n.sym->attr.referenced); gcc_assert (primary->symtree->n.sym->attr.referenced);
if (tbp_sym) if (tbp_sym)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment