11/* ******************************************************************\
22
3- Module: MODULE NAME
3+ Module: Generate Java Generic Type - Instantiate a generic class with
4+ concrete type information.
45
56 Author: DiffBlue Limited. All rights reserved.
67
1011#include < java_bytecode/java_types.h>
1112#include < java_bytecode/java_utils.h>
1213
13- #include < iostream>
14- #include < sstream>
1514
1615generate_java_generic_typet::generate_java_generic_typet (
17- symbol_tablet &symbol_table,
1816 message_handlert &message_handler):
19- symbol_table(symbol_table),
2017 message_handler(message_handler)
2118{}
2219
20+ // / Generate a concrete instantiation of a generic type.
21+ // / \param existing_generic_type The type to be concretised
22+ // / \param symbol_table The symbol table that the concrete type will be
23+ // / inserted into.
24+ // / \return The symbol as it was retrieved from the symbol table after
25+ // / it has been inserted into.
2326symbolt generate_java_generic_typet::operator ()(
24- const java_type_with_generic_typet &existing_generic_type)
27+ const java_generic_typet &existing_generic_type,
28+ symbol_tablet &symbol_table) const
2529{
2630 namespacet ns (symbol_table);
2731
@@ -30,58 +34,90 @@ symbolt generate_java_generic_typet::operator()(
3034 INVARIANT (
3135 pointer_subtype.id ()==ID_struct, " Only pointers to classes in java" );
3236
33- const java_class_typet &java_class=to_java_class_type (pointer_subtype);
34-
35- java_class_typet replacement_type=java_class;
36- replacement_type.components ().clear ();
37-
38- const irep_idt new_tag=build_generic_tag (existing_generic_type, java_class);
39- replacement_type.set_tag (new_tag);
40-
41- for (const struct_union_typet::componentt &component_type :
42- java_class.components ())
43- {
44- if (!is_java_generic_type (component_type.type ()))
37+ const java_class_typet &replacement_type=
38+ to_java_class_type (pointer_subtype);
39+ const irep_idt new_tag=build_generic_tag (
40+ existing_generic_type, replacement_type);
41+ struct_union_typet::componentst replacement_components=
42+ replacement_type.components ();
43+
44+ // Small auxiliary function, to perform the inplace
45+ // modification of the generic fields.
46+ auto replace_type_for_generic_field=
47+ [&](struct_union_typet::componentt &component)
4548 {
46- replacement_type.components ().push_back (component_type);
47- continue ;
48- }
49+ if (is_java_generic_parameter (component.type ()))
50+ {
51+ auto replacement_type_param=
52+ to_java_generics_class_type (replacement_type);
53+
54+ auto component_identifier=
55+ to_java_generic_parameter (component.type ()).type_variable ()
56+ .get_identifier ();
57+
58+ optionalt<size_t > results=java_generics_get_index_for_subtype (
59+ replacement_type_param, component_identifier);
60+
61+ INVARIANT (
62+ results.has_value (),
63+ " generic component type not found" );
64+
65+ if (results)
66+ {
67+ component.type ()=
68+ existing_generic_type.generic_type_variables ()[*results];
69+ }
70+ }
71+ return component;
72+ };
73+
74+ std::size_t pre_modification_size=to_java_class_type (
75+ ns.follow (existing_generic_type.subtype ())).components ().size ();
76+
77+ std::for_each (
78+ replacement_components.begin (),
79+ replacement_components.end (),
80+ replace_type_for_generic_field);
81+
82+ std::size_t after_modification_size=
83+ replacement_type.components ().size ();
4984
50- INVARIANT (
51- existing_generic_type.type_parameters .size ()==1 ,
52- " Must have a type parameter" );
53-
54- struct_union_typet::componentt replacement_comp=component_type;
55- replacement_comp.type ()=existing_generic_type.type_parameters [0 ];
56-
57- replacement_type.components ().push_back (replacement_comp);
58-
59- }
6085 INVARIANT (
61- replacement_type. components (). size ()==java_class. components (). size () ,
86+ pre_modification_size==after_modification_size ,
6287 " All components in the original class should be in the new class" );
6388
64- generate_class_stub (new_tag, symbol_table, message_handler);
65- INVARIANT (symbol_table.has_symbol (" java::" +id2string (new_tag)), " New class not created" );
66- return symbol_table.lookup (" java::" +id2string (new_tag));
89+ const auto expected_symbol=" java::" +id2string (new_tag);
90+
91+ generate_class_stub (
92+ new_tag,
93+ symbol_table,
94+ message_handler,
95+ replacement_components);
96+ auto symbol=symbol_table.lookup (expected_symbol);
97+ INVARIANT (symbol, " New class not created" );
98+ return *symbol;
6799}
68100
101+ // / Build a unique tag for the generic to be instantiated.
102+ // / \param existing_generic_type The type we want to concretise
103+ // / \param original_class
104+ // / \return A tag for the new generic we want a unique tag for.
69105irep_idt generate_java_generic_typet::build_generic_tag (
70- const java_type_with_generic_typet &existing_generic_type,
71- const java_class_typet &original_class)
106+ const java_generic_typet &existing_generic_type,
107+ const java_class_typet &original_class) const
72108{
73109 std::ostringstream new_tag_buffer;
74110 new_tag_buffer << original_class.get_tag ();
75111 new_tag_buffer << " <" ;
76112 bool first=true ;
77- for (const typet ¶m : existing_generic_type.type_parameters )
113+ for (const typet ¶m : existing_generic_type.generic_type_variables () )
78114 {
79115 if (!first)
80- new_tag_buffer << " , " ;
116+ new_tag_buffer << " ," ;
81117 first=false ;
82118
83119 INVARIANT (
84- is_java_inst_generic_type (param),
120+ is_java_generic_inst_parameter (param),
85121 " Only create full concretized generic types" );
86122 new_tag_buffer << param.subtype ().get (ID_identifier);
87123 }
@@ -90,3 +126,46 @@ irep_idt generate_java_generic_typet::build_generic_tag(
90126
91127 return new_tag_buffer.str ();
92128}
129+
130+
131+ // / Activate the generic instantiation code.
132+ // / \param message_handler
133+ // / \param symbol_table The symbol table so far.
134+ void
135+ instantiate_generics (
136+ message_handlert &message_handler,
137+ symbol_tablet &symbol_table)
138+ {
139+ generate_java_generic_typet instantiate_generic_type (message_handler);
140+ // check out the symbols in the symbol table at this point to see if we
141+ // have a a generic type in.
142+ for (const auto &symbol : symbol_table.symbols )
143+ {
144+ if (symbol.second .type .id ()==ID_struct)
145+ {
146+ auto symbol_struct=to_struct_type (symbol.second .type );
147+ auto &components=symbol_struct.components ();
148+
149+ for (const auto &component : components)
150+ {
151+ if (is_java_generic_type (component.type ()))
152+ {
153+ const auto &type_vars=to_java_generic_type (component.type ()).
154+ generic_type_variables ();
155+
156+ // Before we can instantiate a generic component, we need
157+ // its type variables to be instantiated parameters
158+ if (all_of (type_vars.cbegin (), type_vars.cend (),
159+ [](const typet &type)
160+ {
161+ return is_java_generic_inst_parameter (type);
162+ }))
163+ {
164+ instantiate_generic_type (
165+ to_java_generic_type (component.type ()), symbol_table);
166+ }
167+ }
168+ }
169+ }
170+ }
171+ }
0 commit comments