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 (void)
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 () != 0)
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
== 0)
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
= 0;
171 ACE_NEW_RETURN (response_handler
,
172 be_interface (amh_name
, // name
173 0, // list of inherited
174 0, // number of inherited
175 0, // 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 (0);
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
);
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
;
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
;
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
= 0;
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
= 0;
377 ACE_NEW_RETURN (arg_id
,
378 Identifier ("holder"),
381 UTL_ScopedName
*arg_name
= 0;
382 ACE_NEW_RETURN (arg_name
,
383 UTL_ScopedName (arg_id
, 0),
386 be_argument
*argument
= 0;
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 (0 == response_handler
->be_add_operation (node_excep
))
408 be_visitor_amh_pre_proc::add_normal_reply (be_operation
*node
,
409 be_interface
*response_handler
)
412 UTL_ScopedName
*sn
= 0;
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
= 0;
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
= 0;
449 ACE_NEW_RETURN (arg_id
,
450 Identifier ("return_value"),
453 UTL_ScopedName
*arg_name
= 0;
454 ACE_NEW_RETURN (arg_name
,
455 UTL_ScopedName (arg_id
, 0),
458 // Create the argument
459 be_argument
*arg
= 0;
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")),
494 //be_decl *arg = dynamic_cast<be_decl*> (d);
495 AST_Argument
*original_arg
= dynamic_cast<AST_Argument
*> (d
);
497 if (original_arg
->direction () == AST_Argument::dir_INOUT
||
498 original_arg
->direction () == AST_Argument::dir_OUT
)
500 // Create the argument
501 be_argument
*arg
= 0;
503 be_argument (AST_Argument::dir_IN
,
504 original_arg
->field_type (),
505 original_arg
->name ()),
508 operation
->be_add_argument (arg
);
512 operation
->set_defined_in (response_handler
);
514 // We do not copy the exceptions because the exceptions
515 // are delivered by the excep methods.
517 // After having generated the operation we insert it into the
518 // response handler interface.
519 if (0 == response_handler
->be_add_operation (operation
))
528 be_visitor_amh_pre_proc::visit_operation (be_operation
*node
)
530 // @@ Mayur, we do want to generate code for oneways! This is
531 // needed to support reliable oneways with the SYNC_WITH_TARGET
533 // We do nothing for oneways!
534 if (node
->flags () == AST_Operation::OP_oneway
)
543 be_visitor_amh_pre_proc::create_exception_holder (be_interface
*node
)
545 // AMH exception holders require both of these.
546 idl_global
->valuetype_seen_
= true;
548 idl_global
->valuefactory_seen_
= true;
550 const int inherit_count
= 0;
551 AST_Type
**p_intf
= 0;
553 UTL_ScopedName
*excep_holder_name
=
554 node
->compute_name ("AMH_",
557 UTL_Scope
*s
= node
->defined_in ();
558 idl_global
->scopes ().push (s
);
560 be_valuetype
*excep_holder
= 0;
561 ACE_NEW_RETURN (excep_holder
,
562 be_valuetype (excep_holder_name
,
576 idl_global
->scopes ().pop ();
578 excep_holder
->set_name (excep_holder_name
);
579 excep_holder
->set_defined_in (node
->defined_in ());
581 // Set repo id to 0, so it will be recomputed on the next access,
582 // and set the prefix to the node's prefix. All this is
583 // necessary in case the node's prefix was modified after
585 excep_holder
->AST_Decl::repoID (0);
586 excep_holder
->prefix (const_cast<char*> (node
->prefix ()));
588 excep_holder
->gen_fwd_helper_name ();
590 // Now our customized valuetype is created, we have to
591 // add now the operations and attributes to the scope.
593 // initialize an iterator to iterate thru our scope
594 for (UTL_ScopeActiveIterator
si (node
, UTL_Scope::IK_decls
);
598 AST_Decl
*d
= si
.item ();
602 ACE_ERROR_RETURN ((LM_ERROR
,
603 "(%N:%l) be_visitor_amh_pre_proc::"
605 "bad node in this scope\n"),
609 be_decl
*op
= dynamic_cast<be_decl
*> (d
);
610 AST_Decl::NodeType nt
= d
->node_type ();
612 if (nt
== AST_Decl::NT_attr
)
614 AST_Attribute
*attribute
= dynamic_cast<AST_Attribute
*> (d
);
621 this->create_raise_operation (op
,
625 if (!attribute
->readonly ())
627 this->create_raise_operation (op
,
632 else if (nt
== AST_Decl::NT_op
)
634 this->create_raise_operation (op
,
648 be_visitor_amh_pre_proc::create_raise_operation (
650 be_valuetype
*excep_holder
,
651 Operation_Kind operation_kind
655 UTL_ScopedName
*sn
= 0;
656 be_operation
*orig_op
= 0;
658 if (operation_kind
== NORMAL
)
660 orig_op
= dynamic_cast<be_operation
*> (node
);
663 // Name the operation properly
664 UTL_ScopedName
*op_name
=
665 static_cast<UTL_ScopedName
*> (excep_holder
->name ()->copy ());
667 ACE_CString
new_local_name ("raise_");
669 if (operation_kind
== SET_OPERATION
)
671 new_local_name
+= "set_";
673 else if (operation_kind
== GET_OPERATION
)
675 new_local_name
+= "get_";
678 new_local_name
+= node
->name ()->last_component ()->get_string ();
681 Identifier (new_local_name
.c_str ()),
691 be_operation
*operation
= 0;
692 ACE_NEW_RETURN (operation
,
693 be_operation (be_global
->void_type (),
694 AST_Operation::OP_noflags
,
700 operation
->set_name (op_name
);
701 operation
->set_defined_in (excep_holder
);
703 if (operation_kind
== NORMAL
)
707 // Copy the exceptions.
708 UTL_ExceptList
*exceptions
= orig_op
->exceptions ();
712 operation
->be_add_exceptions (exceptions
->copy ());
717 // After having generated the operation we insert it into the
718 // exceptionholder valuetype.
719 if (0 == excep_holder
->be_add_operation (operation
))
729 be_visitor_amh_pre_proc::generate_name (ACE_CString
&destination
,
731 const char *middle_name
,
734 destination
= prefix
;
735 destination
+= middle_name
;
736 destination
+= suffix
;
743 be_visitor_amh_pre_proc::generate_get_operation (be_attribute
*node
)
745 ACE_CString
original_op_name (
746 node
->name ()->last_component ()->get_string ()
748 ACE_CString new_op_name
= ACE_CString ("get_") + original_op_name
;
750 UTL_ScopedName
*get_name
=
751 static_cast<UTL_ScopedName
*> (node
->name ()-> copy ());
752 get_name
->last_component ()->replace_string (new_op_name
.c_str ());
754 be_operation
*operation
= 0;
755 ACE_NEW_RETURN (operation
,
756 be_operation (node
->field_type (),
757 AST_Operation::OP_noflags
,
763 operation
->set_name (get_name
);
764 operation
->set_defined_in (node
->defined_in ());
770 be_visitor_amh_pre_proc::generate_set_operation (be_attribute
*node
)
772 ACE_CString
original_op_name (
773 node
->name ()->last_component ()->get_string ()
775 ACE_CString new_op_name
= ACE_CString ("set_") + original_op_name
;
777 UTL_ScopedName
*set_op_name
=
778 dynamic_cast<UTL_ScopedName
*> (node
->name ()-> copy ());
779 set_op_name
->last_component ()->replace_string (new_op_name
.c_str ());
781 // argument type is the same as the attribute type
782 be_argument
*arg
= 0;
784 be_argument (AST_Argument::dir_IN
,
789 arg
->set_name (dynamic_cast<UTL_ScopedName
*> (node
->name ()->copy ()));
791 // create the operation
792 be_operation
*operation
= 0;
793 ACE_NEW_RETURN (operation
,
794 be_operation (be_global
->void_type (),
795 AST_Operation::OP_noflags
,
801 operation
->set_name (set_op_name
);
802 operation
->set_defined_in (node
->defined_in ());
803 operation
->be_add_argument (arg
);