Merge pull request #1844 from jrw972/monterey
[ACE_TAO.git] / TAO / TAO_IDL / be / be_visitor_amh_pre_proc.cpp
bloba694dbc036f207655454f56cba21acfa22a98acf
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 (void)
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 () != 0)
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 == 0)
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 = 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
177 1, // local
178 0), // non-abstract
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 (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);
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 != 0)
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 != 0)
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 == 0)
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 = 0;
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 = 0;
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 = 0;
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 = 0;
377 ACE_NEW_RETURN (arg_id,
378 Identifier ("holder"),
379 -1);
381 UTL_ScopedName *arg_name = 0;
382 ACE_NEW_RETURN (arg_name,
383 UTL_ScopedName (arg_id, 0),
384 -1);
386 be_argument *argument = 0;
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 (0 == 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 = 0;
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 ());
421 ACE_NEW_RETURN (id,
422 Identifier (original_op_name.c_str ()),
423 -1);
425 ACE_NEW_RETURN (sn,
426 UTL_ScopedName (id,
428 -1);
430 op_name->nconc (sn);
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,
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 = 0;
449 ACE_NEW_RETURN (arg_id,
450 Identifier ("return_value"),
451 -1);
453 UTL_ScopedName *arg_name = 0;
454 ACE_NEW_RETURN (arg_name,
455 UTL_ScopedName (arg_id, 0),
456 -1);
458 // Create the argument
459 be_argument *arg = 0;
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 = 0;
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);
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;
502 ACE_NEW_RETURN (arg,
503 be_argument (AST_Argument::dir_IN,
504 original_arg->field_type (),
505 original_arg->name ()),
506 -1);
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))
521 return -1;
524 return 0;
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
532 // policy.
533 // We do nothing for oneways!
534 if (node->flags () == AST_Operation::OP_oneway)
536 return 0;
539 return 0;
542 be_valuetype *
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_",
555 "ExceptionHolder");
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,
563 p_intf,
564 inherit_count,
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
584 // its declaration.
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);
595 !si.is_done ();
596 si.next ())
598 AST_Decl *d = si.item ();
600 if (d == 0)
602 ACE_ERROR_RETURN ((LM_ERROR,
603 "(%N:%l) be_visitor_amh_pre_proc::"
604 "visit_interface - "
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);
616 if (attribute == 0)
618 return 0;
621 this->create_raise_operation (op,
622 excep_holder,
623 GET_OPERATION);
625 if (!attribute->readonly ())
627 this->create_raise_operation (op,
628 excep_holder,
629 SET_OPERATION);
632 else if (nt == AST_Decl::NT_op)
634 this->create_raise_operation (op,
635 excep_holder,
636 NORMAL);
638 else
640 continue;
644 return excep_holder;
648 be_visitor_amh_pre_proc::create_raise_operation (
649 be_decl *node,
650 be_valuetype *excep_holder,
651 Operation_Kind operation_kind
654 Identifier *id = 0;
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 ();
680 ACE_NEW_RETURN (id,
681 Identifier (new_local_name.c_str ()),
682 -1);
684 ACE_NEW_RETURN (sn,
685 UTL_ScopedName (id,
687 -1);
689 op_name->nconc (sn);
691 be_operation *operation = 0;
692 ACE_NEW_RETURN (operation,
693 be_operation (be_global->void_type (),
694 AST_Operation::OP_noflags,
695 op_name,
698 -1);
700 operation->set_name (op_name);
701 operation->set_defined_in (excep_holder);
703 if (operation_kind == NORMAL)
705 if (orig_op)
707 // Copy the exceptions.
708 UTL_ExceptList *exceptions = orig_op->exceptions ();
710 if (0 != 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))
721 return -1;
724 return 0;
729 be_visitor_amh_pre_proc::generate_name (ACE_CString &destination,
730 const char *prefix,
731 const char *middle_name,
732 const char *suffix)
734 destination = prefix;
735 destination += middle_name;
736 destination += suffix;
737 return 0;
742 be_operation *
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,
758 get_name,
763 operation->set_name (get_name);
764 operation->set_defined_in (node->defined_in ());
766 return operation;
769 be_operation *
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;
783 ACE_NEW_RETURN (arg,
784 be_argument (AST_Argument::dir_IN,
785 node->field_type (),
786 set_op_name),
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,
796 set_op_name,
801 operation->set_name (set_op_name);
802 operation->set_defined_in (node->defined_in ());
803 operation->be_add_argument (arg);
805 return operation;