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"
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 ()
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"),
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"),
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)
76 // Don't generate AMH classes for imported, local or abstract interfaces
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.
93 || node
->is_abstract ()
94 || node
->has_mixed_parentage ())
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);
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
,
116 if (response_handler
== nullptr)
118 ACE_ERROR_RETURN ((LM_ERROR
,
119 "(%N:%l) be_visitor_amh_pre_proc::"
121 "creating the response handler failed\n"),
124 response_handler
->set_defined_in (node
->defined_in ());
126 // Insert the response handler after the node.
127 module
->be_add_interface (response_handler
,
130 // Remember from whom we were cloned
131 response_handler
->original_interface (node
);
133 module
->be_add_interface (excep_holder
, node
);
139 be_visitor_amh_pre_proc::create_response_handler (
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 ());
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
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
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
);
216 AST_Decl
*d
= si
.item ();
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 ();
230 if (nt
== AST_Decl::NT_attr
)
232 be_attribute
*attr
= dynamic_cast<be_attribute
*> (d
);
237 this->create_response_handler_attribute (attr
,
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)
258 this->create_response_handler_operation (operation
,
264 ACE_ERROR_RETURN ((LM_ERROR
,
265 "(%N:%l) be_visitor_amh_pre_proc::"
266 "add_rh_node_members - "
267 "operation creation failed\n"),
282 be_visitor_amh_pre_proc::create_response_handler_operation (
284 be_interface
*response_handler
,
285 be_valuetype
*exception_holder
293 /// These are for the stub side only.
294 if (node
->is_sendc_ami ())
299 if (this->add_normal_reply (node
, response_handler
) == -1)
304 return this->add_exception_reply (node
,
310 be_visitor_amh_pre_proc::create_response_handler_attribute (
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
);
322 this->create_response_handler_operation (get_operation
,
326 get_operation
->destroy ();
327 delete get_operation
;
328 get_operation
= nullptr;
335 if (node
->readonly ())
340 // Temporarily generate the set operation.
341 be_operation
*set_operation
= this->generate_set_operation (node
);
343 this->visit_operation (set_operation
);
346 this->create_response_handler_operation (set_operation
,
350 set_operation
->destroy ();
351 delete set_operation
;
352 set_operation
= nullptr;
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 ("",
365 be_operation
*node_excep
= nullptr;
366 ACE_NEW_RETURN (node_excep
,
367 be_operation (be_global
->void_type (),
368 AST_Operation::OP_noflags
,
374 node_excep
->set_name (operation_name
);
376 Identifier
*arg_id
= nullptr;
377 ACE_NEW_RETURN (arg_id
,
378 Identifier ("holder"),
381 UTL_ScopedName
*arg_name
= nullptr;
382 ACE_NEW_RETURN (arg_name
,
383 UTL_ScopedName (arg_id
, nullptr),
386 be_argument
*argument
= nullptr;
387 ACE_NEW_RETURN (argument
,
388 be_argument (AST_Argument::dir_IN
,
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
))
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 ());
422 Identifier (original_op_name
.c_str ()),
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
,
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"),
453 UTL_ScopedName
*arg_name
= nullptr;
454 ACE_NEW_RETURN (arg_name
,
455 UTL_ScopedName (arg_id
, nullptr),
458 // Create the argument
459 be_argument
*arg
= nullptr;
461 be_argument (AST_Argument::dir_IN
,
462 node
->return_type (),
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
);
478 AST_Decl
*d
= si
.item ();
482 operation
->destroy ();
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")),
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;
502 be_argument (AST_Argument::dir_IN
,
503 original_arg
->field_type (),
504 original_arg
->name ()),
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
))
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
532 // We do nothing for oneways!
533 if (node
->flags () == AST_Operation::OP_oneway
)
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_",
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
,
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
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
);
597 AST_Decl
*d
= si
.item ();
601 ACE_ERROR_RETURN ((LM_ERROR
,
602 "(%N:%l) be_visitor_amh_pre_proc::"
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)
620 this->create_raise_operation (op
,
624 if (!attribute
->readonly ())
626 this->create_raise_operation (op
,
631 else if (nt
== AST_Decl::NT_op
)
633 this->create_raise_operation (op
,
647 be_visitor_amh_pre_proc::create_raise_operation (
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 ();
680 Identifier (new_local_name
.c_str ()),
690 be_operation
*operation
= nullptr;
691 ACE_NEW_RETURN (operation
,
692 be_operation (be_global
->void_type (),
693 AST_Operation::OP_noflags
,
699 operation
->set_name (op_name
);
700 operation
->set_defined_in (excep_holder
);
702 if (operation_kind
== NORMAL
)
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
))
728 be_visitor_amh_pre_proc::generate_name (ACE_CString
&destination
,
730 const char *middle_name
,
733 destination
= prefix
;
734 destination
+= middle_name
;
735 destination
+= suffix
;
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
,
761 operation
->set_name (get_name
);
762 operation
->set_defined_in (node
->defined_in ());
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;
782 be_argument (AST_Argument::dir_IN
,
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
,
799 operation
->set_name (set_op_name
);
800 operation
->set_defined_in (node
->defined_in ());
801 operation
->be_add_argument (arg
);