1
1
/* ******************************************************************\
2
2
3
- Module: MODULE NAME
3
+ Module: Generate Java Generic Type - Instantiate a generic class with
4
+ concrete type information.
4
5
5
6
Author: DiffBlue Limited. All rights reserved.
6
7
10
11
#include < java_bytecode/java_types.h>
11
12
#include < java_bytecode/java_utils.h>
12
13
13
- #include < iostream>
14
- #include < sstream>
15
14
16
15
generate_java_generic_typet::generate_java_generic_typet (
17
- symbol_tablet &symbol_table,
18
16
message_handlert &message_handler):
19
- symbol_table(symbol_table),
20
17
message_handler(message_handler)
21
18
{}
22
19
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.
23
26
symbolt 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
25
29
{
26
30
namespacet ns (symbol_table);
27
31
@@ -30,58 +34,90 @@ symbolt generate_java_generic_typet::operator()(
30
34
INVARIANT (
31
35
pointer_subtype.id ()==ID_struct, " Only pointers to classes in java" );
32
36
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)
45
48
{
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 ();
49
84
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
- }
60
85
INVARIANT (
61
- replacement_type. components (). size ()==java_class. components (). size () ,
86
+ pre_modification_size==after_modification_size ,
62
87
" All components in the original class should be in the new class" );
63
88
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;
67
99
}
68
100
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.
69
105
irep_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
72
108
{
73
109
std::ostringstream new_tag_buffer;
74
110
new_tag_buffer << original_class.get_tag ();
75
111
new_tag_buffer << " <" ;
76
112
bool first=true ;
77
- for (const typet ¶m : existing_generic_type.type_parameters )
113
+ for (const typet ¶m : existing_generic_type.generic_type_variables () )
78
114
{
79
115
if (!first)
80
- new_tag_buffer << " , " ;
116
+ new_tag_buffer << " ," ;
81
117
first=false ;
82
118
83
119
INVARIANT (
84
- is_java_inst_generic_type (param),
120
+ is_java_generic_inst_parameter (param),
85
121
" Only create full concretized generic types" );
86
122
new_tag_buffer << param.subtype ().get (ID_identifier);
87
123
}
@@ -90,3 +126,46 @@ irep_idt generate_java_generic_typet::build_generic_tag(
90
126
91
127
return new_tag_buffer.str ();
92
128
}
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