[gcjx] Patch: FYI: explicit type parameters
Tom Tromey
tromey@redhat.com
Fri Oct 21 22:23:00 GMT 2005
I'm checking this in on the gcjx branch.
This adds support for explicit type parameters to method invocations.
In particular it updates the parser, the model, semantic analysis, and
the visitors.
Here's an example of code using this feature:
public class gxi
{
public static <T> T whatever() { return null; }
public static void main(String[] args)
{
String x = gxi.<String> whatever();
System.out.println(x);
}
}
Tom
Index: gcjx/ChangeLog
from Tom Tromey <tromey@redhat.com>
* bytecode/generate.hh
(bytecode_generator::visit_generic_invocation): New method.
* dump.cc (dumper::visit_generic_invocation): New method.
* fold.cc (fold_visitor::visit_generic_invocation): New method.
* defassign.cc
(definite_assignment_visitor::visit_generic_invocation): New
method.
* visitor.hh (visitor::visit_generic_invocation): Declare.
* name.cc (classify_expression_name): Added 'type_args' argument.
* name.hh (classify_expression_name): Added argument.
* source/parse.cc (primary): Handle invocation with explicit type
parameters.
* model/invoke.cc: Added instantiation.
(visit): New method.
* model/invoke.hh (model_generic_method_invocation): New typedef.
* model/memberref.cc (resolve): Updated.
* model/memberref.hh (model_memberref_forward::type_parameters):
New field.
(model_memberref_forward::set_type_parameters): New method.
Index: gcjx/defassign.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/defassign.cc,v
retrieving revision 1.1.2.12
diff -u -r1.1.2.12 defassign.cc
--- gcjx/defassign.cc 13 Oct 2005 06:28:55 -0000 1.1.2.12
+++ gcjx/defassign.cc 21 Oct 2005 22:18:09 -0000
@@ -1864,6 +1864,16 @@
}
void
+ visit_generic_invocation (model_method_invocation *mi,
+ model_method *meth,
+ const ref_expression &qual,
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &)
+ {
+ visit_method_invocation (mi, meth, qual, args);
+ }
+
+ void
visit_generic_invocation (model_type_qualified_invocation *tqi,
const model_method *meth,
const std::list<ref_expression> &args,
Index: gcjx/dump.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/dump.cc,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 dump.cc
--- gcjx/dump.cc 19 Oct 2005 15:59:23 -0000 1.1.2.10
+++ gcjx/dump.cc 21 Oct 2005 22:18:10 -0000
@@ -1279,6 +1279,16 @@
}
void
+ visit_generic_invocation (model_method_invocation *mi,
+ model_method *meth,
+ const ref_expression &qual,
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &)
+ {
+ visit_method_invocation (mi, meth, qual, args);
+ }
+
+ void
visit_generic_invocation (model_type_qualified_invocation *tqi,
const model_method *meth,
const std::list<ref_expression> &args,
@@ -3089,6 +3099,16 @@
}
void
+ visit_generic_invocation (model_method_invocation *mi,
+ model_method *meth,
+ const ref_expression &qual,
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &)
+ {
+ visit_method_invocation (mi, meth, qual, args);
+ }
+
+ void
visit_generic_invocation (model_type_qualified_invocation *tqi,
const model_method *meth,
const std::list<ref_expression> &args,
Index: gcjx/fold.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/fold.cc,v
retrieving revision 1.1.2.7
diff -u -r1.1.2.7 fold.cc
--- gcjx/fold.cc 13 Oct 2005 06:28:55 -0000 1.1.2.7
+++ gcjx/fold.cc 21 Oct 2005 22:18:10 -0000
@@ -973,6 +973,16 @@
}
void
+ visit_generic_invocation (model_method_invocation *mi,
+ model_method *meth,
+ const ref_expression &qual,
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &)
+ {
+ visit_method_invocation (mi, meth, qual, args);
+ }
+
+ void
visit_generic_invocation (model_type_qualified_invocation *tqi,
const model_method *meth,
const std::list<ref_expression> &args,
Index: gcjx/name.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/name.cc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 name.cc
--- gcjx/name.cc 13 Jan 2005 03:18:33 -0000 1.1.2.1
+++ gcjx/name.cc 21 Oct 2005 22:18:10 -0000
@@ -1,6 +1,6 @@
// Meaning of a name.
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -406,7 +406,8 @@
classify_expression_name (resolution_scope *scope,
model_element *request,
const std::list<std::string> &name,
- const std::list<ref_expression> &args)
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &type_args)
{
assert (name.begin () != name.end ());
@@ -414,7 +415,9 @@
if (simple_name_p (name))
{
location w = request->get_location ();
- result = new model_method_invocation (w);
+ result = (type_args.empty ()
+ ? new model_method_invocation (w)
+ : new model_generic_method_invocation (w, type_args));
// result->set_qualifying_class (scope->get_current_class ());
}
else
@@ -432,15 +435,21 @@
% join (dropname, '.');
if (klass)
{
+ location where = request->get_location ();
model_type_qualified_invocation *tqi
- = new model_type_qualified_invocation (request->get_location ());
- tqi->set_class (new model_forwarding_resolved (LOCATION_UNKNOWN,
- klass));
+ = (type_args.empty ()
+ ? new model_type_qualified_invocation (where)
+ : new model_generic_type_qualified_invocation (where,
+ type_args));
+ tqi->set_class (new model_forwarding_resolved (where, klass));
result = tqi;
}
else
{
- result = new model_method_invocation (request->get_location ());
+ result = (type_args.empty ()
+ ? new model_method_invocation (request->get_location ())
+ : new model_generic_method_invocation (request->get_location (),
+ type_args));
result->set_expression (expr);
}
}
Index: gcjx/name.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/name.hh,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 name.hh
--- gcjx/name.hh 13 Jan 2005 03:18:33 -0000 1.1.2.1
+++ gcjx/name.hh 21 Oct 2005 22:18:10 -0000
@@ -1,6 +1,6 @@
// Meaning of a name.
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -69,7 +69,8 @@
ref_invocation_base classify_expression_name (resolution_scope *,
model_element *,
const std::list<std::string> &,
- const std::list<ref_expression> &);
+ const std::list<ref_expression> &,
+ const std::list<ref_forwarding_type> &);
/// Look up a primitive type by its one-character descriptor. Returns
/// NULL if it doesn't represent the descriptor of a primitive type.
Index: gcjx/visitor.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/visitor.hh,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 visitor.hh
--- gcjx/visitor.hh 13 Oct 2005 06:28:55 -0000 1.1.2.8
+++ gcjx/visitor.hh 21 Oct 2005 22:18:11 -0000
@@ -532,6 +532,13 @@
virtual void visit_javadoc (model_javadoc *, bool) = 0;
virtual void
+ visit_generic_invocation (model_method_invocation *,
+ model_method *,
+ const ref_expression &,
+ const std::list<ref_expression> &,
+ const std::list<ref_forwarding_type> &) = 0;
+
+ virtual void
visit_generic_invocation (model_type_qualified_invocation *,
const model_method *,
const std::list<ref_expression> &, bool,
Index: gcjx/bytecode/generate.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/generate.hh,v
retrieving revision 1.1.2.16
diff -u -r1.1.2.16 generate.hh
--- gcjx/bytecode/generate.hh 13 Oct 2005 06:28:55 -0000 1.1.2.16
+++ gcjx/bytecode/generate.hh 21 Oct 2005 22:18:11 -0000
@@ -1056,6 +1056,16 @@
}
void
+ visit_generic_invocation (model_method_invocation *mi,
+ model_method *meth,
+ const ref_expression &qual,
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &)
+ {
+ visit_method_invocation (mi, meth, qual, args);
+ }
+
+ void
visit_generic_invocation (model_type_qualified_invocation *tqi,
const model_method *meth,
const std::list<ref_expression> &args,
Index: gcjx/model/invoke.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/invoke.cc,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 invoke.cc
--- gcjx/model/invoke.cc 21 Oct 2005 21:40:53 -0000 1.1.2.10
+++ gcjx/model/invoke.cc 21 Oct 2005 22:18:11 -0000
@@ -676,6 +676,7 @@
// Instantiations.
+template class model_generic_invocation<model_method_invocation>;
template class model_generic_invocation<model_type_qualified_invocation>;
template class model_generic_invocation<model_super_invocation>;
template class model_generic_invocation<model_this_invocation>;
@@ -684,6 +685,14 @@
template<>
void
+model_generic_invocation<model_method_invocation>::visit (visitor *v)
+{
+ v->visit_generic_invocation (this, method, expression, arguments,
+ actual_type_params);
+}
+
+template<>
+void
model_generic_invocation<model_type_qualified_invocation>::visit (visitor *v)
{
v->visit_generic_invocation (this, method, arguments, super,
Index: gcjx/model/invoke.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/invoke.hh,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 invoke.hh
--- gcjx/model/invoke.hh 21 Oct 2005 21:40:53 -0000 1.1.2.5
+++ gcjx/model/invoke.hh 21 Oct 2005 22:18:11 -0000
@@ -301,6 +301,8 @@
/// These classes are used to represent explicitly-parameterized
/// invocations of generic methods.
+typedef class model_generic_invocation<model_method_invocation>
+ model_generic_method_invocation;
typedef class model_generic_invocation<model_type_qualified_invocation>
model_generic_type_qualified_invocation;
typedef class model_generic_invocation<model_super_invocation>
Index: gcjx/model/memberref.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/memberref.cc,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 memberref.cc
--- gcjx/model/memberref.cc 13 Oct 2005 06:28:55 -0000 1.1.2.3
+++ gcjx/model/memberref.cc 21 Oct 2005 22:18:11 -0000
@@ -27,7 +27,8 @@
if (is_call)
{
assert (! is_lhs);
- real = classify_expression_name (scope, this, ids, arguments);
+ real = classify_expression_name (scope, this, ids, arguments,
+ type_parameters);
if (ids.size () == 1)
{
model_invocation_base *iv
@@ -37,6 +38,7 @@
}
else
{
+ assert (type_parameters.empty ());
real = classify_expression_name (scope, this, ids);
if (dynamic_cast<model_field_ref *> (real.get ()) != NULL)
{
Index: gcjx/model/memberref.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/model/Attic/memberref.hh,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 memberref.hh
--- gcjx/model/memberref.hh 22 Jan 2005 07:56:25 -0000 1.1.2.2
+++ gcjx/model/memberref.hh 21 Oct 2005 22:18:11 -0000
@@ -61,6 +61,9 @@
// Arguments to a method.
std::list<ref_expression> arguments;
+ // Explicit type parameters. This list is empty if there are none.
+ std::list<ref_forwarding_type> type_parameters;
+
// True if left-hand-side of assignment.
bool is_lhs;
// True if compound assignment.
@@ -104,6 +107,11 @@
is_call = true;
}
+ void set_type_parameters (const std::list<ref_forwarding_type> ¶ms)
+ {
+ type_parameters = params;
+ }
+
void resolve (resolution_scope *);
void visit (visitor *v)
Index: gcjx/source/parse.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/source/Attic/parse.cc,v
retrieving revision 1.1.2.7
diff -u -r1.1.2.7 parse.cc
--- gcjx/source/parse.cc 9 Oct 2005 20:08:03 -0000 1.1.2.7
+++ gcjx/source/parse.cc 21 Oct 2005 22:18:12 -0000
@@ -646,20 +646,32 @@
if (! result)
{
- // FIXME: we must handle 'Type . <params> name ()'
- // and 'primary . <params> name ()' here.
- // This is tricky as it doesn't fit in well with our parsing
- // approach or the current model.
-
- // What's left are variable or field references. We use a
- // single kind of object to represent both of these, with
- // resolution later. We do this because a qualified-identifier
- // could have an arbitrary number of field references in it.
+ // What's left are variable or field references, or method
+ // invocations. We use a single kind of object to represent
+ // all of these, with resolution later. We do this because a
+ // qualified-identifier could have an arbitrary number of
+ // field references in it.
mark.backtrack ();
+
std::list<std::string> qual (qualified_identifier ());
+ std::list<ref_forwarding_type> type_params;
+ if (peek () == TOKEN_DOT && peek1 () == TOKEN_LESS_THAN)
+ {
+ assume (TOKEN_DOT);
+ // Generic invocation with explicit type parameters.
+ type_params = actual_type_parameters ();
+ // This is a goofy hack: fetch the method name and push it
+ // on the identifier list. FIXME: really we ought to make
+ // the model a little closer to the source here.
+ qual.push_back (identifier ());
+ }
+
ref_memberref_forward fwd (new model_memberref_forward (t, qual));
- if (peek () == TOKEN_OPEN_PAREN)
- fwd->set_arguments (arguments ());
+ if (! type_params.empty () || peek () == TOKEN_OPEN_PAREN)
+ {
+ fwd->set_arguments (arguments ());
+ fwd->set_type_parameters (type_params);
+ }
result = fwd;
}
}
@@ -694,11 +706,15 @@
}
else
{
- std::string name = identifier ();
- if (peek () == TOKEN_OPEN_PAREN)
+ if (peek () == TOKEN_LESS_THAN)
{
+ // Generic invocation with explicit type
+ // parameters.
+ std::list<ref_forwarding_type> type_params
+ = actual_type_parameters ();
+ std::string name = identifier ();
ref_method_invocation inv
- = new model_method_invocation (t);
+ = new model_generic_method_invocation (t, type_params);
inv->set_method (name);
inv->set_expression (result);
inv->set_arguments (arguments ());
@@ -706,11 +722,24 @@
}
else
{
- // Field reference.
- ref_field_ref fref (new model_field_ref (t));
- fref->set_field (name);
- fref->set_expression (result);
- result = fref;
+ std::string name = identifier ();
+ if (peek () == TOKEN_OPEN_PAREN)
+ {
+ ref_method_invocation inv
+ = new model_method_invocation (t);
+ inv->set_method (name);
+ inv->set_expression (result);
+ inv->set_arguments (arguments ());
+ result = inv;
+ }
+ else
+ {
+ // Field reference.
+ ref_field_ref fref (new model_field_ref (t));
+ fref->set_field (name);
+ fref->set_expression (result);
+ result = fref;
+ }
}
}
}
Index: gcc/java/ChangeLog
from Tom Tromey <tromey@redhat.com>
* tree.hh (tree_generator::visit_generic_invocation): New
overload.
Index: gcc/java/tree.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/tree.hh,v
retrieving revision 1.1.2.23
diff -u -r1.1.2.23 tree.hh
--- gcc/java/tree.hh 13 Oct 2005 06:30:58 -0000 1.1.2.23
+++ gcc/java/tree.hh 21 Oct 2005 22:18:19 -0000
@@ -844,6 +844,16 @@
}
void
+ visit_generic_invocation (model_method_invocation *mi,
+ model_method *meth,
+ const ref_expression &qual,
+ const std::list<ref_expression> &args,
+ const std::list<ref_forwarding_type> &)
+ {
+ visit_method_invocation (mi, meth, qual, args);
+ }
+
+ void
visit_generic_invocation (model_type_qualified_invocation *tqi,
const model_method *meth,
const std::list<ref_expression> &args,
More information about the Java-patches
mailing list