OpenDDS  Snapshot(2023/04/28-20:55)
itl_generator.cpp
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.opendds.org/license.html
4  */
5 
6 #include "itl_generator.h"
7 
8 #include "be_extern.h"
9 #include "global_extern.h"
10 
11 #include <dds/DCPS/Definitions.h>
12 
13 #include <utl_identifier.h>
14 #include <utl_labellist.h>
15 #include <ast_fixed.h>
16 
17 using namespace AstTypeClassification;
18 
19 std::ostream&
20 operator<<(std::ostream& out,
21  const itl_generator::Indent& i)
22 {
23  out << std::string(static_cast<size_t> (i.generator->level_ * 2), ' ');
24  return out;
25 }
26 
27 std::ostream&
28 operator<<(std::ostream& out,
29  const itl_generator::Open& i)
30 {
31  i.generator->level_ += 1;
32  return out;
33 }
34 
35 std::ostream&
36 operator<<(std::ostream& out,
37  const itl_generator::Close& i)
38 {
39  i.generator->level_ -= 1;
40  return out;
41 }
42 
43 struct InlineType {
44  AST_Type* type;
45 
46  explicit InlineType(AST_Type* t)
47  : type(t)
48  { }
49 };
50 
51 std::ostream&
52 operator<<(std::ostream& out,
53  const InlineType& it)
54 {
55  AST_Typedef* td = dynamic_cast<AST_Typedef*>(it.type);
56  if (td) {
57  be_global->itl_ << '"' << it.type->repoID() << '"';
58  return out;
59  }
60 
62  if (c & CL_STRING) {
63  // TODO: Support bounded strings.
64  if (c & CL_WIDE) {
65  be_global->itl_ << "{ \"kind\" : \"string\", \"note\" : { \"idl\" : { \"type\" : \"wstring\" } } }";
66  }
67  else {
68  be_global->itl_ << "{ \"kind\" : \"string\" }";
69  }
70  }
71  else if (c & CL_PRIMITIVE) {
72  switch (dynamic_cast<AST_PredefinedType*>(it.type)->pt()) {
73  case AST_PredefinedType::PT_long:
74  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 32 }";
75  break;
76  case AST_PredefinedType::PT_ulong:
77  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 32, \"unsigned\" : true}";
78  break;
79  case AST_PredefinedType::PT_longlong:
80  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 64 }";
81  break;
82  case AST_PredefinedType::PT_ulonglong:
83  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 64, \"unsigned\" : true}";
84  break;
85  case AST_PredefinedType::PT_short:
86  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 16 }";
87  break;
88  case AST_PredefinedType::PT_ushort:
89  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 16, \"unsigned\" : true}";
90  break;
91  case AST_PredefinedType::PT_float:
92  be_global->itl_ << "{ \"kind\" : \"float\", \"model\" : \"binary32\" }";
93  break;
94  case AST_PredefinedType::PT_double:
95  be_global->itl_ << "{ \"kind\" : \"float\", \"model\" : \"binary64\" }";
96  break;
97  case AST_PredefinedType::PT_longdouble:
98  be_global->itl_ << "{ \"kind\" : \"float\", \"model\" : \"binary128\" }";
99  break;
100  case AST_PredefinedType::PT_char:
101  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 8, \"note\" : { \"presentation\" : { \"type\" : \"char\" } } }";
102  break;
103  case AST_PredefinedType::PT_wchar:
104  be_global->itl_ << "{ \"kind\" : \"int\", \"note\" : { \"presentation\" : { \"type\" : \"char\" }, \"idl\" : { \"type\" : \"wchar\" } } }";
105  break;
106  case AST_PredefinedType::PT_boolean:
107  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 1, \"note\" : { \"presentation\" : { \"type\" : \"bool\" } } }";
108  break;
109  case AST_PredefinedType::PT_octet:
110  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 8, \"unsigned\" : true, "
111  "\"note\" : { \"presentation\" : { \"type\" : \"byte\" } } }";
112  break;
113 #if OPENDDS_HAS_EXPLICIT_INTS
114  case AST_PredefinedType::PT_uint8:
115  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 8, \"unsigned\" : true }";
116  break;
117  case AST_PredefinedType::PT_int8:
118  be_global->itl_ << "{ \"kind\" : \"int\", \"bits\" : 8 }";
119  break;
120 #endif
121  case AST_PredefinedType::PT_any:
122  case AST_PredefinedType::PT_object:
123  case AST_PredefinedType::PT_value:
124  case AST_PredefinedType::PT_abstract:
125  case AST_PredefinedType::PT_void:
126  case AST_PredefinedType::PT_pseudo:
127  // TODO
128  break;
129  }
130  }
131  else {
132  be_global->itl_ << '"' << it.type->repoID() << '"';
133  }
134 
135  return out;
136 }
137 
139 {
140  be_global->itl_ << Indent(this) << "{\n"
141  << Open(this)
142  << Indent(this) << "\"types\" :\n"
143  << Open(this)
144  << Indent(this) << "[\n";
145 }
146 
148 {
149  be_global->itl_ << Indent(this) << "]\n"
150  << Close(this)
151  << Close(this)
152  << Indent(this) << "}\n";
153 }
154 
156 {
157  if (count_ > 0)
158  be_global->itl_ << Indent(this) << ",\n";
159  ++count_;
160 }
161 
162 bool itl_generator::gen_enum(AST_Enum*, UTL_ScopedName* /*name*/,
163  const std::vector<AST_EnumVal*>& contents, const char* repoid)
164 {
165  new_type();
166 
167  be_global->itl_ << Open(this)
168  << Indent(this) << "{\n"
169  << Open(this)
170  << Indent(this) << "\"kind\" : \"alias\",\n"
171  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
172  << Indent(this) << "\"type\" :\n"
173  << Open(this)
174  << Indent(this) << "{\n"
175  << Open(this)
176  << Indent(this) << "\"kind\" : \"int\",\n"
177  << Indent(this) << "\"bits\" : 32,\n"
178  << Indent(this) << "\"unsigned\" : true,\n"
179  << Indent(this) << "\"constrained\" : true,\n"
180  << Indent(this) << "\"values\" : {";
181 
182  for (size_t i = 0; i < contents.size(); ++i) {
183  if (i > 0)
184  be_global->itl_ << ", ";
185  be_global->itl_ << '"' << contents[i]->local_name()->get_string() << '"'
186  << " : "
187  << '"' << i << '"';
188  }
189 
190  be_global->itl_ << "}\n";
191  be_global->itl_ << Close(this)
192  << Indent(this) << "}\n"
193  << Close(this);
194 
195  be_global->itl_ << Close(this)
196  << Indent(this) << "}\n"
197  << Close(this);
198 
199  return true;
200 }
201 
202 bool itl_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* /*name*/,
203  AST_Type* base,
204  const char* repoid)
205 {
206  new_type();
207 
208  switch (base->node_type()) {
209  case AST_Decl::NT_sequence:
210  {
211  AST_Sequence *seq = dynamic_cast<AST_Sequence*>(base);
212  be_global->itl_ << Open(this)
213  << Indent(this) << "{\n"
214  << Open(this)
215  << Indent(this) << "\"kind\" : \"alias\",\n"
216  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
217  << Indent(this) << "\"type\" :\n"
218  << Open(this)
219  << Indent(this) << "{\n"
220  << Open(this)
221  << Indent(this) << "\"kind\" : \"sequence\",\n";
222  if (!seq->unbounded()) {
223  be_global->itl_ << Indent(this) << "\"capacity\" : " << seq->max_size()->ev()->u.ulval << ",\n";
224  }
225  be_global->itl_ << Indent(this) << "\"type\" : " << InlineType(seq->base_type()) << "\n"
226  << Close(this)
227  << Indent(this) << "}\n"
228  << Close(this)
229  << Close(this)
230  << Indent(this) << "}\n"
231  << Close(this);
232  break;
233  }
234  case AST_Decl::NT_array:
235  {
236  AST_Array* arr = dynamic_cast<AST_Array*>(base);
237  be_global->itl_ << Open(this)
238  << Indent(this) << "{\n"
239  << Open(this)
240  << Indent(this) << "\"kind\" : \"alias\",\n"
241  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
242  << Indent(this) << "\"type\" :\n"
243  << Open(this)
244  << Indent(this) << "{\n"
245  << Open(this)
246  << Indent(this) << "\"kind\" : \"sequence\",\n"
247  << Indent(this) << "\"type\" : " << InlineType(arr->base_type()) << ",\n"
248  << Indent(this) << "\"size\" : [";
249  ACE_CDR::ULong dims = arr->n_dims();
250  for (size_t i = 0; i < dims; ++i) {
251  if (i > 0)
252  be_global->itl_ << ", ";
253  be_global->itl_ << arr->dims()[i]->ev()->u.ulval;
254  }
255  be_global->itl_ << "]\n"
256  << Close(this)
257  << Indent(this) << "}\n"
258  << Close(this)
259  << Close(this)
260  << Indent(this) << "}\n"
261  << Close(this);
262  break;
263  }
264  case AST_Decl::NT_fixed:
265  {
266  AST_Fixed* fixed = dynamic_cast<AST_Fixed*>(base);
267  unsigned digits = fixed->digits()->ev()->u.ulval;
268  unsigned scale = fixed->scale()->ev()->u.ulval;
269  be_global->itl_
270  << Open(this) << Indent(this) << "{\n" << Open(this)
271  << Indent(this) << "\"kind\" : \"alias\",\n"
272  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
273  << Indent(this) << "\"type\" : { "
274  << "\"kind\" : \"fixed\", "
275  << "\"digits\" : " << digits << ", "
276  << "\"scale\" : " << scale << ", "
277  << "\"base\" : 10 }\n"
278  << Close(this) << Indent(this) << "}\n" << Close(this);
279  break;
280  }
281  default:
282  {
283  be_global->itl_ << Open(this)
284  << Indent(this) << "{\n"
285  << Open(this)
286  << Indent(this) << "\"kind\" : \"alias\",\n"
287  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
288  << Indent(this) << "\"type\" : " << InlineType(base) << "\n"
289  << Close(this)
290  << Indent(this) << "}\n"
291  << Close(this);
292 
293  return true;
294  }
295  }
296  return true;
297 }
298 
299 bool itl_generator::gen_struct(AST_Structure* node, UTL_ScopedName*,
300  const std::vector<AST_Field*>& fields,
301  AST_Type::SIZE_TYPE, const char* repoid)
302 {
303  if (!be_global->itl())
304  return true;
305 
306  const bool is_topic_type =
307  idl_global->is_dcps_type(node->name()) || be_global->is_topic_type(node);
308 
309  new_type();
310 
311  be_global->itl_ << Open(this)
312  << Indent(this) << "{\n"
313  << Open(this)
314  << Indent(this) << "\"kind\" : \"alias\",\n"
315  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
316 
317  // Check if this is defined as a primary data type
318  << Indent(this) << "\"note\" : { \"is_dcps_data_type\" : "
319  << (is_topic_type ? "true" : "false")
320  << " },\n"
321 
322  << Indent(this) << "\"type\" :\n"
323  << Open(this)
324  << Indent(this) << "{\n"
325  << Open(this)
326  << Indent(this) << "\"kind\" : \"record\",\n"
327  << Indent(this) << "\"fields\" :\n"
328  << Open(this)
329  << Indent(this) << "[\n";
330 
331  bool comma_flag = false;
332  for (std::vector<AST_Field*>::const_iterator pos = fields.begin(), limit = fields.end();
333  pos != limit;
334  ++pos) {
335  AST_Field* field = *pos;
336  if (comma_flag) {
337  be_global->itl_ << Indent(this) << ",\n";
338  }
339  be_global->itl_ << Open(this)
340  << Indent(this) << "{\n"
341  << Open(this)
342  << Indent(this) << "\"name\" : \"" << field->local_name()->get_string() << "\",\n"
343  << Indent(this) << "\"type\" : " << InlineType(field->field_type()) << "\n"
344  << Close(this)
345  << Indent(this) << "}\n"
346  << Close(this);
347  comma_flag = true;
348  }
349 
350  be_global->itl_ << Indent(this) << "]\n"
351  << Close(this)
352  << Close(this)
353  << Indent(this) << "}\n"
354  << Close(this)
355  << Close(this)
356  << Indent(this) << "}\n"
357  << Close(this);
358 
359 
360  return true;
361 }
362 
363 
364 bool itl_generator::gen_union(AST_Union* node, UTL_ScopedName* /*name*/,
365  const std::vector<AST_UnionBranch*>& cases,
366  AST_Type* _d,
367  const char* repoid)
368 {
369  new_type();
370 
371  be_global->itl_ << Open(this)
372  << Indent(this) << "{\n"
373  << Open(this)
374  << Indent(this) << "\"kind\" : \"alias\",\n"
375  << Indent(this) << "\"name\" : \"" << repoid << "\",\n"
376  << Indent(this) << "\"type\" :\n"
377  << Open(this)
378  << Indent(this) << "{\n"
379  << Open(this)
380  << Indent(this) << "\"kind\" : \"union\",\n"
381  << Indent(this) << "\"discriminator\" : " << InlineType(_d) << ",\n"
382  << Indent(this) << "\"note\" : { \"is_dcps_data_type\" : "
383  << (be_global->is_topic_type(node) ? "true" : "false")
384  << " },\n"
385  << Indent(this) << "\"fields\" :\n"
386  << Open(this)
387  << Indent(this) << "[\n";
388 
389  for (std::vector<AST_UnionBranch*>::const_iterator pos = cases.begin(), limit = cases.end();
390  pos != limit;
391  ++pos) {
392  if (pos != cases.begin())
393  be_global->itl_ << Indent(this) << ",\n";
394 
395  AST_UnionBranch *branch = *pos;
396 
397  be_global->itl_ << Open(this)
398  << Indent(this) << "{\n"
399  << Open(this)
400  << Indent(this) << "\"name\" : \"" << branch->local_name()->get_string() << "\",\n"
401  << Indent(this) << "\"type\" : " << InlineType(branch->field_type()) << ",\n"
402 
403  << Indent(this) << "\"labels\" : [";
404 
405 
406  unsigned long count = branch->label_list_length();
407  for (unsigned long i = 0; i < count; i++)
408  {
409  if (i > 0)
410  be_global->itl_ << ", ";
411  AST_UnionLabel *label = branch->label(i);
412  if (label->label_kind() == AST_UnionLabel::UL_default)
413  {
414  continue;
415  }
416  be_global->itl_ << "\"" << label->label_val()->n()->last_component()->get_string() << "\"";
417  }
418 
419  be_global->itl_ << "]\n"
420  << Close(this)
421  << Indent(this) << "}\n"
422  << Close(this);
423  }
424 
425  be_global->itl_ << Indent(this) << "]\n"
426  << Close(this)
427  << Close(this)
428  << Indent(this) << "}\n"
429  << Close(this)
430  << Close(this)
431  << Indent(this) << "}\n"
432  << Close(this);
433 
434  return true;
435 }
itl_generator * generator
Definition: itl_generator.h:47
Classification classify(AST_Type *type)
const Classification CL_STRING
bool gen_typedef(AST_Typedef *, UTL_ScopedName *, AST_Type *, const char *)
const Classification CL_WIDE
const Classification CL_PRIMITIVE
bool gen_struct(AST_Structure *node, UTL_ScopedName *name, const std::vector< AST_Field *> &fields, AST_Type::SIZE_TYPE size, const char *repoid)
bool gen_enum(AST_Enum *, UTL_ScopedName *name, const std::vector< AST_EnumVal *> &contents, const char *repoid)
std::ostream & operator<<(std::ostream &out, const itl_generator::Indent &i)
ACE_UINT32 ULong
itl_generator * generator
Definition: itl_generator.h:55
AST_Type * type
BE_GlobalData * be_global
Definition: be_global.cpp:44
itl_generator * generator
Definition: itl_generator.h:39
bool gen_union(AST_Union *, UTL_ScopedName *, const std::vector< AST_UnionBranch *> &, AST_Type *, const char *)
InlineType(AST_Type *t)