Merge pull request #2220 from DOCGroup/revert-2217-jwi-inetwraning
[ACE_TAO.git] / TAO / TAO_IDL / be / be_visitor_amh_pre_proc.cpp
blob27bbd0f0e13e2ac7ed4014c701fff15ddde36e12
1 /**
2 * @file be_visitor_amh_pre_proc.cpp
4 * This visitor creates for AMH implied IDL constructs the appropriate AST
5 * (Abstract Syntax Tree) node, sets the corresponding interface or operation
6 * strategy on it and enteres the nodes into the AST.
8 * @author Darrell Brunsch <brunsch@cs.wustl.edu>
9 * @author Mayur Deshpande <mayur@ics.uci.edu>
10 * @author Carlos O'Ryan <coryan@uci.edu>
12 //=============================================================================
14 #include "be_visitor_amh_pre_proc.h"
15 #include "be_visitor_context.h"
16 #include "be_root.h"
17 #include "be_module.h"
18 #include "be_interface.h"
19 #include "be_valuetype.h"
20 #include "be_attribute.h"
21 #include "be_operation.h"
22 #include "be_predefined_type.h"
23 #include "be_argument.h"
24 #include "be_extern.h"
25 #include "utl_identifier.h"
26 #include "utl_exceptlist.h"
27 #include "global_extern.h"
28 #include "ace/Log_Msg.h"
30 be_visitor_amh_pre_proc::be_visitor_amh_pre_proc (be_visitor_context *ctx)
31 : be_visitor_scope (ctx)
35 be_visitor_amh_pre_proc::~be_visitor_amh_pre_proc ()
39 int
40 be_visitor_amh_pre_proc::visit_root (be_root *node)
42 if (this->visit_scope (node) == -1)
44 ACE_ERROR_RETURN ((LM_ERROR,
45 "(%N:%l) be_visitor_amh_pre_proc::"
46 "visit_root - visit scope failed\n"),
47 -1);
50 return 0;
53 int
54 be_visitor_amh_pre_proc::visit_module (be_module *node)
56 if (!node->imported () && this->visit_scope (node) == -1)
58 ACE_ERROR_RETURN ((LM_ERROR,
59 "(%N:%l) be_visitor_amh_pre_proc::"
60 "visit_module - visit scope failed\n"),
61 -1);
64 return 0;
67 int
68 be_visitor_amh_pre_proc::visit_interface (be_interface *node)
70 // Do not generate AMH classes for any sort of implied IDL.
71 if (node->original_interface () != nullptr)
73 return 0;
76 // Don't generate AMH classes for imported, local or abstract interfaces
77 // either...
78 // @@ Mayur, maybe we do want to insert the AMH node for imported
79 // interfaces, not because we want to generate code for them, but
80 // because the (imported-AMH-) node could be needed to generate a
81 // non-imported, AMH node, for example, for a derived interface.
83 // (JP) Havinq AMH_* nodes inherit directly from AMH_* base classes
84 // is also a problem if the base interface is abstract, since at
85 // the moment, no AMH code is generated for such interfaces. It
86 // would be desirable to mimic the AMI design, where all AMI-related
87 // classes inherit from a single base class, no matter what the
88 // parentage of the IDL interface. Until we solve the problem of
89 // AMH for abstract interfaces, I'm disabling all AMH generation
90 // for interfaces having an abstract ancestor.
91 if (node->imported ()
92 || node->is_local ()
93 || node->is_abstract ()
94 || node->has_mixed_parentage ())
96 return 0;
99 // Create the exception holder, it needs to go before the response
100 // handler, because the response handler uses an exception holder as
101 // argument for some of its operations....
102 be_valuetype *excep_holder =
103 this->create_exception_holder (node);
104 excep_holder->set_defined_in (node->defined_in ());
105 excep_holder->original_interface (node);
106 excep_holder->is_amh_excep_holder (true);
108 AST_Module *module =
109 dynamic_cast<AST_Module*> (node->defined_in ());
110 module->set_has_nested_valuetype ();
112 // Create the ResponseHandler class
113 be_interface *response_handler =
114 this->create_response_handler (node,
115 excep_holder);
116 if (response_handler == nullptr)
118 ACE_ERROR_RETURN ((LM_ERROR,
119 "(%N:%l) be_visitor_amh_pre_proc::"
120 "visit_interface - "
121 "creating the response handler failed\n"),
122 -1);
124 response_handler->set_defined_in (node->defined_in ());
126 // Insert the response handler after the node.
127 module->be_add_interface (response_handler,
128 node);
130 // Remember from whom we were cloned
131 response_handler->original_interface (node);
133 module->be_add_interface (excep_holder, node);
135 return 0;
138 be_interface *
139 be_visitor_amh_pre_proc::create_response_handler (
140 be_interface *node,
141 be_valuetype *exception_holder
144 // Generate 'AMH_InterfaceResponseHandler'
145 ACE_CString class_name;
146 class_name += "AMH_";
147 class_name += node->local_name ();
148 class_name += "ResponseHandler";
150 UTL_ScopedName * const amh_name =
151 dynamic_cast<UTL_ScopedName*> (node->name ()->copy ());
153 if (!amh_name)
154 ACE_ERROR_RETURN ((LM_ERROR,
155 "be_visitor_amh_pre_proc::create_response_handler"
156 " - Scope downcast failed.\n"),
158 Identifier *local_name = amh_name->last_component ();
159 local_name->replace_string (class_name.c_str ());
161 UTL_Scope *s = node->defined_in ();
162 idl_global->scopes ().push (s);
164 // @@ Mayur, you are not filling up the list of inherited classes,
165 // however, you *are* using that same list in the amh_rh_sh.cpp and
166 // amh_rh_sh.cpp file... you need to fill up the list, i.e. discover
167 // the inherited classes in the original interface, change their
168 // names and then use the symbol table to look up the
169 // AMH-response-handler nodes.
170 be_interface *response_handler = nullptr;
171 ACE_NEW_RETURN (response_handler,
172 be_interface (amh_name, // name
173 nullptr, // list of inherited
174 0, // number of inherited
175 nullptr, // list of ancestors
176 0, // number of ancestors
177 1, // local
178 0), // non-abstract
179 nullptr);
181 idl_global->scopes ().pop ();
183 response_handler->set_name (amh_name);
184 response_handler->set_defined_in (node->defined_in ());
185 response_handler->set_imported (node->imported ());
186 response_handler->set_line (node->line ());
187 response_handler->set_file_name (node->file_name ());
189 // Set repo id to 0, so it will be recomputed on the next access,
190 // and set the prefix to the node's prefix. All this is
191 // necessary in case the node's prefix was modified after
192 // its declaration.
193 response_handler->AST_Decl::repoID (nullptr);
194 response_handler->prefix (const_cast<char*> (node->prefix ()));
196 response_handler->gen_fwd_helper_name ();
197 this->add_rh_node_members (node, response_handler, exception_holder);
198 return response_handler;
202 be_visitor_amh_pre_proc::add_rh_node_members ( be_interface *node,
203 be_interface *response_handler,
204 be_valuetype *exception_holder)
206 // Now our customized valuetype is created, we have to
207 // add now the operations and attributes to the scope.
209 this->elem_number_ = 0;
211 // Initialize an iterator to iterate thru our scope.
212 for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
213 !si.is_done ();
214 si.next ())
216 AST_Decl *d = si.item ();
218 if (!d)
220 ACE_ERROR_RETURN ((LM_ERROR,
221 "(%N:%l) be_visitor_amh_pre_proc::"
222 "add_rh_node_members - "
223 "bad node in this scope\n"),
227 AST_Decl::NodeType nt = d->node_type ();
228 int status = 0;
230 if (nt == AST_Decl::NT_attr)
232 be_attribute *attr = dynamic_cast<be_attribute*> (d);
234 if (attr != nullptr)
236 status =
237 this->create_response_handler_attribute (attr,
238 response_handler,
239 exception_holder);
241 if (status == -1)
243 ACE_ERROR_RETURN ((LM_ERROR,
244 "(%N:%l) be_visitor_amh_pre_proc::"
245 "add_rh_node_members - "
246 "attribute creation failed\n"),
251 else if (nt == AST_Decl::NT_op)
253 be_operation* operation = dynamic_cast<be_operation*> (d);
255 if (operation != nullptr)
257 status =
258 this->create_response_handler_operation (operation,
259 response_handler,
260 exception_holder);
262 if (status == -1)
264 ACE_ERROR_RETURN ((LM_ERROR,
265 "(%N:%l) be_visitor_amh_pre_proc::"
266 "add_rh_node_members - "
267 "operation creation failed\n"),
272 else
274 continue;
278 return 1;
282 be_visitor_amh_pre_proc::create_response_handler_operation (
283 be_operation *node,
284 be_interface *response_handler,
285 be_valuetype *exception_holder
288 if (node == nullptr)
290 return -1;
293 /// These are for the stub side only.
294 if (node->is_sendc_ami ())
296 return 0;
299 if (this->add_normal_reply (node, response_handler) == -1)
301 return -1;
304 return this->add_exception_reply (node,
305 response_handler,
306 exception_holder);
310 be_visitor_amh_pre_proc::create_response_handler_attribute (
311 be_attribute *node,
312 be_interface *response_handler,
313 be_valuetype *exception_holder
316 // Temporarily generate the get operation.
317 be_operation *get_operation = this->generate_get_operation (node);
319 this->visit_operation (get_operation);
321 int status =
322 this->create_response_handler_operation (get_operation,
323 response_handler,
324 exception_holder);
326 get_operation->destroy ();
327 delete get_operation;
328 get_operation = nullptr;
330 if (status == -1)
332 return -1;
335 if (node->readonly ())
337 return 0;
340 // Temporarily generate the set operation.
341 be_operation *set_operation = this->generate_set_operation (node);
343 this->visit_operation (set_operation);
345 status =
346 this->create_response_handler_operation (set_operation,
347 response_handler,
348 exception_holder);
350 set_operation->destroy ();
351 delete set_operation;
352 set_operation = nullptr;
354 return status;
358 be_visitor_amh_pre_proc::add_exception_reply (be_operation *node,
359 be_interface *response_handler,
360 be_valuetype *exception_holder)
362 UTL_ScopedName *operation_name = node->compute_name ("",
363 "_excep");
365 be_operation *node_excep = nullptr;
366 ACE_NEW_RETURN (node_excep,
367 be_operation (be_global->void_type (),
368 AST_Operation::OP_noflags,
369 operation_name,
372 -1);
374 node_excep->set_name (operation_name);
376 Identifier *arg_id = nullptr;
377 ACE_NEW_RETURN (arg_id,
378 Identifier ("holder"),
379 -1);
381 UTL_ScopedName *arg_name = nullptr;
382 ACE_NEW_RETURN (arg_name,
383 UTL_ScopedName (arg_id, nullptr),
384 -1);
386 be_argument *argument = nullptr;
387 ACE_NEW_RETURN (argument,
388 be_argument (AST_Argument::dir_IN,
389 exception_holder,
390 arg_name),
391 -1);
393 argument->set_name (arg_name);
394 argument->set_defined_in (node_excep);
395 node_excep->be_add_argument (argument);
397 node_excep->set_defined_in (response_handler);
399 if (nullptr == response_handler->be_add_operation (node_excep))
401 return -1;
404 return 0;
408 be_visitor_amh_pre_proc::add_normal_reply (be_operation *node,
409 be_interface *response_handler)
411 Identifier *id = nullptr;
412 UTL_ScopedName *sn = nullptr;
414 ACE_CString original_op_name (
415 node->name ()->last_component ()->get_string ()
418 UTL_ScopedName *op_name =
419 static_cast<UTL_ScopedName *> (response_handler->name ()->copy ());
421 ACE_NEW_RETURN (id,
422 Identifier (original_op_name.c_str ()),
423 -1);
425 ACE_NEW_RETURN (sn,
426 UTL_ScopedName (id,
427 nullptr),
428 -1);
430 op_name->nconc (sn);
432 // Create the operation
433 be_operation *operation = nullptr;
434 ACE_NEW_RETURN (operation,
435 be_operation (be_global->void_type (),
436 AST_Operation::OP_noflags,
437 op_name,
440 -1);
442 operation->set_name (op_name);
444 // If return type is non-void add it as first argument
446 if (!node->void_return_type ())
448 Identifier *arg_id = nullptr;
449 ACE_NEW_RETURN (arg_id,
450 Identifier ("return_value"),
451 -1);
453 UTL_ScopedName *arg_name = nullptr;
454 ACE_NEW_RETURN (arg_name,
455 UTL_ScopedName (arg_id, nullptr),
456 -1);
458 // Create the argument
459 be_argument *arg = nullptr;
460 ACE_NEW_RETURN (arg,
461 be_argument (AST_Argument::dir_IN,
462 node->return_type (),
463 arg_name),
464 -1);
466 arg->set_name (arg_name);
468 // Add the response handler to the argument list
469 operation->be_add_argument (arg);
472 // Iterate over the arguments and put all the out and inout arguments
473 // into the new method.
474 for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
475 !si.is_done ();
476 si.next ())
478 AST_Decl *d = si.item ();
480 if (!d)
482 operation->destroy ();
483 delete operation;
484 operation = nullptr;
486 ACE_ERROR_RETURN ((LM_ERROR,
487 ACE_TEXT ("be_visitor_amh_pre_proc::")
488 ACE_TEXT ("add_normal_reply - ")
489 ACE_TEXT ("bad node in this scope\n")),
490 -1);
493 //be_decl *arg = dynamic_cast<be_decl*> (d);
494 AST_Argument *original_arg = dynamic_cast<AST_Argument*> (d);
496 if (original_arg->direction () == AST_Argument::dir_INOUT ||
497 original_arg->direction () == AST_Argument::dir_OUT)
499 // Create the argument
500 be_argument *arg = nullptr;
501 ACE_NEW_RETURN (arg,
502 be_argument (AST_Argument::dir_IN,
503 original_arg->field_type (),
504 original_arg->name ()),
505 -1);
507 operation->be_add_argument (arg);
511 operation->set_defined_in (response_handler);
513 // We do not copy the exceptions because the exceptions
514 // are delivered by the excep methods.
516 // After having generated the operation we insert it into the
517 // response handler interface.
518 if (nullptr == response_handler->be_add_operation (operation))
520 return -1;
523 return 0;
527 be_visitor_amh_pre_proc::visit_operation (be_operation *node)
529 // @@ Mayur, we do want to generate code for oneways! This is
530 // needed to support reliable oneways with the SYNC_WITH_TARGET
531 // policy.
532 // We do nothing for oneways!
533 if (node->flags () == AST_Operation::OP_oneway)
535 return 0;
538 return 0;
541 be_valuetype *
542 be_visitor_amh_pre_proc::create_exception_holder (be_interface *node)
544 // AMH exception holders require both of these.
545 idl_global->valuetype_seen_ = true;
547 idl_global->valuefactory_seen_ = true;
549 const int inherit_count = 0;
550 AST_Type **p_intf = nullptr;
552 UTL_ScopedName *excep_holder_name =
553 node->compute_name ("AMH_",
554 "ExceptionHolder");
556 UTL_Scope *s = node->defined_in ();
557 idl_global->scopes ().push (s);
559 be_valuetype *excep_holder = nullptr;
560 ACE_NEW_RETURN (excep_holder,
561 be_valuetype (excep_holder_name,
562 p_intf,
563 inherit_count,
564 nullptr,
565 nullptr,
567 nullptr,
569 nullptr,
573 nullptr);
575 idl_global->scopes ().pop ();
577 excep_holder->set_name (excep_holder_name);
578 excep_holder->set_defined_in (node->defined_in ());
580 // Set repo id to 0, so it will be recomputed on the next access,
581 // and set the prefix to the node's prefix. All this is
582 // necessary in case the node's prefix was modified after
583 // its declaration.
584 excep_holder->AST_Decl::repoID (nullptr);
585 excep_holder->prefix (const_cast<char*> (node->prefix ()));
587 excep_holder->gen_fwd_helper_name ();
589 // Now our customized valuetype is created, we have to
590 // add now the operations and attributes to the scope.
592 // initialize an iterator to iterate thru our scope
593 for (UTL_ScopeActiveIterator si (node, UTL_Scope::IK_decls);
594 !si.is_done ();
595 si.next ())
597 AST_Decl *d = si.item ();
599 if (d == nullptr)
601 ACE_ERROR_RETURN ((LM_ERROR,
602 "(%N:%l) be_visitor_amh_pre_proc::"
603 "visit_interface - "
604 "bad node in this scope\n"),
608 be_decl *op = dynamic_cast<be_decl*> (d);
609 AST_Decl::NodeType nt = d->node_type ();
611 if (nt == AST_Decl::NT_attr)
613 AST_Attribute *attribute = dynamic_cast<AST_Attribute*> (d);
615 if (attribute == nullptr)
617 return nullptr;
620 this->create_raise_operation (op,
621 excep_holder,
622 GET_OPERATION);
624 if (!attribute->readonly ())
626 this->create_raise_operation (op,
627 excep_holder,
628 SET_OPERATION);
631 else if (nt == AST_Decl::NT_op)
633 this->create_raise_operation (op,
634 excep_holder,
635 NORMAL);
637 else
639 continue;
643 return excep_holder;
647 be_visitor_amh_pre_proc::create_raise_operation (
648 be_decl *node,
649 be_valuetype *excep_holder,
650 Operation_Kind operation_kind
653 Identifier *id = nullptr;
654 UTL_ScopedName *sn = nullptr;
655 be_operation *orig_op = nullptr;
657 if (operation_kind == NORMAL)
659 orig_op = dynamic_cast<be_operation*> (node);
662 // Name the operation properly
663 UTL_ScopedName *op_name =
664 static_cast<UTL_ScopedName *> (excep_holder->name ()->copy ());
666 ACE_CString new_local_name ("raise_");
668 if (operation_kind == SET_OPERATION)
670 new_local_name += "set_";
672 else if (operation_kind == GET_OPERATION)
674 new_local_name += "get_";
677 new_local_name += node->name ()->last_component ()->get_string ();
679 ACE_NEW_RETURN (id,
680 Identifier (new_local_name.c_str ()),
681 -1);
683 ACE_NEW_RETURN (sn,
684 UTL_ScopedName (id,
685 nullptr),
686 -1);
688 op_name->nconc (sn);
690 be_operation *operation = nullptr;
691 ACE_NEW_RETURN (operation,
692 be_operation (be_global->void_type (),
693 AST_Operation::OP_noflags,
694 op_name,
697 -1);
699 operation->set_name (op_name);
700 operation->set_defined_in (excep_holder);
702 if (operation_kind == NORMAL)
704 if (orig_op)
706 // Copy the exceptions.
707 UTL_ExceptList *exceptions = orig_op->exceptions ();
709 if (nullptr != exceptions)
711 operation->be_add_exceptions (exceptions->copy ());
716 // After having generated the operation we insert it into the
717 // exceptionholder valuetype.
718 if (nullptr == excep_holder->be_add_operation (operation))
720 return -1;
723 return 0;
728 be_visitor_amh_pre_proc::generate_name (ACE_CString &destination,
729 const char *prefix,
730 const char *middle_name,
731 const char *suffix)
733 destination = prefix;
734 destination += middle_name;
735 destination += suffix;
736 return 0;
740 be_operation *
741 be_visitor_amh_pre_proc::generate_get_operation (be_attribute *node)
743 ACE_CString original_op_name (
744 node->name ()->last_component ()->get_string ()
746 ACE_CString new_op_name = ACE_CString ("get_") + original_op_name;
748 UTL_ScopedName *get_name =
749 static_cast<UTL_ScopedName *> (node->name ()-> copy ());
750 get_name->last_component ()->replace_string (new_op_name.c_str ());
752 be_operation *operation = nullptr;
753 ACE_NEW_RETURN (operation,
754 be_operation (node->field_type (),
755 AST_Operation::OP_noflags,
756 get_name,
759 nullptr);
761 operation->set_name (get_name);
762 operation->set_defined_in (node->defined_in ());
764 return operation;
767 be_operation *
768 be_visitor_amh_pre_proc::generate_set_operation (be_attribute *node)
770 ACE_CString original_op_name (
771 node->name ()->last_component ()->get_string ()
773 ACE_CString new_op_name = ACE_CString ("set_") + original_op_name;
775 UTL_ScopedName *set_op_name =
776 dynamic_cast<UTL_ScopedName *> (node->name ()-> copy ());
777 set_op_name->last_component ()->replace_string (new_op_name.c_str ());
779 // argument type is the same as the attribute type
780 be_argument *arg = nullptr;
781 ACE_NEW_RETURN (arg,
782 be_argument (AST_Argument::dir_IN,
783 node->field_type (),
784 set_op_name),
785 nullptr);
787 arg->set_name (dynamic_cast<UTL_ScopedName *> (node->name ()->copy ()));
789 // create the operation
790 be_operation *operation = nullptr;
791 ACE_NEW_RETURN (operation,
792 be_operation (be_global->void_type (),
793 AST_Operation::OP_noflags,
794 set_op_name,
797 nullptr);
799 operation->set_name (set_op_name);
800 operation->set_defined_in (node->defined_in ());
801 operation->be_add_argument (arg);
803 return operation;