1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
10 #include "ttcn3/AST_ttcn3.hh"
11 #include "ttcn3/Attributes.hh"
13 // implemented in comptype_attrib_la.l
14 extern void parseExtendsCompTypeRefList(Ttcn::AttributeSpec
const& attrib
,
15 Common::CompTypeRefList
*& attr_comp_refs
);
19 // =================================
20 // ===== ComponentTypeBody
21 // =================================
23 ComponentTypeBody::~ComponentTypeBody()
25 for(size_t i
= 0; i
< def_v
.size(); i
++) delete def_v
[i
];
28 delete attr_extends_refs
;
34 ComponentTypeBody
*ComponentTypeBody::clone() const
36 FATAL_ERROR("ComponentTypeBody::clone()");
39 void ComponentTypeBody::set_fullname(const string
& p_fullname
)
41 Scope::set_fullname(p_fullname
);
42 for(size_t i
= 0; i
< def_v
.size(); i
++) {
43 Ttcn::Definition
*def
= def_v
[i
];
44 def
->set_fullname(p_fullname
+ "." + def
->get_id().get_dispname());
47 extends_refs
->set_fullname(p_fullname
+".<extends>");
48 if (attr_extends_refs
)
49 attr_extends_refs
->set_fullname(get_fullname()+".<extends attribute>");
52 void ComponentTypeBody::set_my_scope(Scope
*p_scope
)
54 set_parent_scope(p_scope
);
55 if (extends_refs
) extends_refs
->set_my_scope(p_scope
);
56 if (attr_extends_refs
) attr_extends_refs
->set_my_scope(p_scope
);
59 void ComponentTypeBody::add_extends(CompTypeRefList
*p_crl
)
61 if (extends_refs
|| !p_crl
|| check_state
!=CHECK_INITIAL
)
62 FATAL_ERROR("ComponentTypeBody::add_extends()");
66 bool ComponentTypeBody::is_compatible(ComponentTypeBody
*other
)
68 if (other
==this) return true;
70 other
->chk(CHECK_EXTENDS
);
71 // a component with no definitions is compatible with all components
72 if (def_v
.size()==0 && !extends_refs
&& !attr_extends_refs
) return true;
73 return other
->compatible_m
.has_key(this);
76 void ComponentTypeBody::add_ass(Ttcn::Definition
*p_ass
)
78 if (check_state
!=CHECK_INITIAL
|| !p_ass
)
79 FATAL_ERROR("ComponentTypeBody::add_ass()");
80 p_ass
->set_my_scope(this);
84 bool ComponentTypeBody::has_local_ass_withId(const Identifier
& p_id
)
87 return all_defs_m
.has_key(p_id
.get_name());
90 Assignment
* ComponentTypeBody::get_local_ass_byId(const Identifier
& p_id
)
93 return all_defs_m
[p_id
.get_name()];
96 size_t ComponentTypeBody::get_nof_asss()
99 return all_defs_m
.size();
102 bool ComponentTypeBody::has_ass_withId(const Identifier
& p_id
)
104 if (has_local_ass_withId(p_id
)) return true;
105 else if (parent_scope
) return parent_scope
->has_ass_withId(p_id
);
109 Assignment
* ComponentTypeBody::get_ass_byIndex(size_t p_i
)
112 return all_defs_m
.get_nth_elem(p_i
);
115 bool ComponentTypeBody::is_own_assignment(const Assignment
* p_ass
)
117 for(size_t i
= 0; i
< def_v
.size(); i
++) {
118 if (def_v
[i
] == p_ass
) return true;
123 Assignment
* ComponentTypeBody::get_ass_bySRef(Ref_simple
*p_ref
)
125 if (!p_ref
|| !parent_scope
)
126 FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()");
127 if (!p_ref
->get_modid()) {
128 const Identifier
*id
= p_ref
->get_id();
129 if (id
&& has_local_ass_withId(*id
)) {
130 Assignment
* ass
= get_local_ass_byId(*id
);
131 if (!ass
) FATAL_ERROR("ComponentTypeBody::get_ass_bySRef()");
133 for(size_t i
= 0; i
< def_v
.size(); i
++) {
134 if (def_v
[i
] == ass
) return ass
;
137 if (ass
->get_visibility() == PUBLIC
) {
141 p_ref
->error("The member definition `%s' in component type `%s'"
142 " is not visible in this scope", id
->get_dispname().c_str(),
143 comp_id
->get_dispname().c_str());
147 return parent_scope
->get_ass_bySRef(p_ref
);
150 void ComponentTypeBody::dump(unsigned level
) const
153 DEBUG(level
, "Extends references:");
154 extends_refs
->dump(level
+1);
156 DEBUG(level
, "Definitions: (%lu pcs.)", (unsigned long) def_v
.size());
157 for(size_t i
= 0; i
< def_v
.size(); i
++) def_v
[i
]->dump(level
+ 1);
158 if (attr_extends_refs
) {
159 DEBUG(level
, "Extends attribute references:");
160 attr_extends_refs
->dump(level
+1);
164 // read out the contents of the with attribute extension,
165 // parse it to the the attr_extends_refs member variable,
166 // collects all extends components from all attributes along the attrib path
167 void ComponentTypeBody::chk_extends_attr()
169 if (check_state
>=CHECK_WITHATTRIB
) return;
170 check_state
= CHECK_WITHATTRIB
;
171 Ttcn::WithAttribPath
* w_attrib_path
= my_type
->get_attrib_path();
174 vector
<Ttcn::SingleWithAttrib
> const &real_attribs
=
175 w_attrib_path
->get_real_attrib();
176 for (size_t i
= 0; i
< real_attribs
.size(); i
++)
178 Ttcn::SingleWithAttrib
*act_attr
= real_attribs
[i
];
179 if (act_attr
->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_EXTENSION
)
180 parseExtendsCompTypeRefList(act_attr
->get_attribSpec(),
184 if (attr_extends_refs
)
186 attr_extends_refs
->set_fullname(get_fullname()+".<extends attribute>");
187 attr_extends_refs
->set_my_scope(parent_scope
);
191 void ComponentTypeBody::chk_recursion(ReferenceChain
& refch
)
193 if (refch
.add(get_fullname())) {
194 if (extends_refs
) extends_refs
->chk_recursion(refch
);
195 if (attr_extends_refs
) attr_extends_refs
->chk_recursion(refch
);
199 // contained components must already be checked,
200 // having valid compatible_m maps
201 void ComponentTypeBody::init_compatibility(CompTypeRefList
*crl
,
202 bool is_standard_extends
)
204 for (size_t i
= 0; i
< crl
->get_nof_comps(); i
++)
206 ComponentTypeBody
*cb
= crl
->get_nth_comp_body(i
);
207 if (!compatible_m
.has_key(cb
))
208 compatible_m
.add(cb
, is_standard_extends
? cb
: NULL
);
209 // compatible with all components which are compatible with the compatible
211 for (size_t j
= 0; j
< cb
->compatible_m
.size(); j
++)
213 ComponentTypeBody
*ccb
= cb
->compatible_m
.get_nth_key(j
);
214 ComponentTypeBody
*ccbval
= cb
->compatible_m
.get_nth_elem(j
);
215 if (!compatible_m
.has_key(ccb
))
216 compatible_m
.add(ccb
, is_standard_extends
? ccbval
: NULL
);
221 void ComponentTypeBody::chk_extends()
223 if (check_state
>=CHECK_EXTENDS
) return;
224 check_state
= CHECK_EXTENDS
;
225 // check the references in component extends parts (keyword and attribute)
226 if (extends_refs
) extends_refs
->chk(CHECK_EXTENDS
);
227 if (attr_extends_refs
) attr_extends_refs
->chk(CHECK_EXTENDS
);
228 // check for circular reference chains
229 ReferenceChain
refch(this, "While checking component type extensions");
230 chk_recursion(refch
);
231 // build compatibility map for faster is_compatible() and generate_code()
232 // contained components must already have valid compatible_m map
233 // keys used in is_compatible(), values used in generate_code()
234 if (extends_refs
) init_compatibility(extends_refs
, true);
235 if (attr_extends_refs
) init_compatibility(attr_extends_refs
, false);
238 void ComponentTypeBody::collect_defs_from_standard_extends()
240 Assignments
*module_defs
= parent_scope
->get_scope_asss();
241 for (size_t i
= 0; i
< extends_refs
->get_nof_comps(); i
++) {
242 ComponentTypeBody
*parent
= extends_refs
->get_nth_comp_body(i
);
243 // iterate through all definitions of the parent
244 // parent is already checked (has it's inherited defs included)
245 for (size_t j
= 0; j
< parent
->all_defs_m
.size(); j
++) {
246 Ttcn::Definition
*def
= parent
->all_defs_m
.get_nth_elem(j
);
247 const Identifier
& id
= def
->get_id();
248 const string
& name
= id
.get_name();
249 if (all_defs_m
.has_key(name
)) {
250 Ttcn::Definition
*my_def
= all_defs_m
[name
];
252 // it is not the same definition inherited on two paths
253 const char *dispname_str
= id
.get_dispname().c_str();
254 if (my_def
->get_my_scope() == this) {
255 my_def
->error("Local definition `%s' collides with definition "
256 "inherited from component type `%s'", dispname_str
,
257 def
->get_my_scope()->get_fullname().c_str());
258 def
->note("Inherited definition of `%s' is here", dispname_str
);
260 error("Definition `%s' inherited from component type `%s' "
261 "collides with definition inherited from `%s'", dispname_str
,
262 def
->get_my_scope()->get_fullname().c_str(),
263 my_def
->get_my_scope()->get_fullname().c_str());
264 def
->note("Definition of `%s' in `%s' is here", dispname_str
,
265 def
->get_my_scope()->get_fullname().c_str());
266 my_def
->note("Definition of `%s' in `%s' is here", dispname_str
,
267 my_def
->get_my_scope()->get_fullname().c_str());
271 all_defs_m
.add(name
, def
);
272 if (def
->get_my_scope()->get_scope_mod() !=
273 module_defs
->get_scope_mod()) {
274 // def comes from another module
275 if (module_defs
->has_local_ass_withId(id
)) {
276 const char *dispname_str
= id
.get_dispname().c_str();
277 error("The name of inherited definition `%s' is not unique in "
278 "the scope hierarchy", dispname_str
);
279 module_defs
->get_local_ass_byId(id
)->note("Symbol `%s' is "
280 "already defined here in a higher scope unit", dispname_str
);
281 def
->note("Definition `%s' inherited from component type `%s' "
282 "is here", dispname_str
,
283 def
->get_my_scope()->get_fullname().c_str());
284 } else if (module_defs
->is_valid_moduleid(id
)) {
285 def
->warning("Inherited definition with name `%s' hides a "
286 "module identifier", id
.get_dispname().c_str());
294 void ComponentTypeBody::collect_defs_from_attribute_extends()
296 for (size_t i
= 0; i
< attr_extends_refs
->get_nof_comps(); i
++) {
297 ComponentTypeBody
*parent
= attr_extends_refs
->get_nth_comp_body(i
);
298 // iterate through all definitions of the parent
299 // parent is already checked (has it's inherited defs included)
300 for (size_t j
= 0; j
< parent
->all_defs_m
.size(); j
++) {
301 Ttcn::Definition
*def
= parent
->all_defs_m
.get_nth_elem(j
);
302 const Identifier
& id
= def
->get_id();
303 const char *dispname_str
= id
.get_dispname().c_str();
304 const string
& name
= id
.get_name();
305 // the definition to be imported must be already in the all_defs_m map
306 // and must belong to owner (not be inherited)
307 // orig_defs_map contains backed up own definitions
308 if (all_defs_m
.has_key(name
)) {
309 Ttcn::Definition
*my_def
= all_defs_m
[name
];
310 if (my_def
->get_my_scope() == this) {
311 // my_def is a local definition
312 if (orig_defs_m
.has_key(name
)) FATAL_ERROR( \
313 "ComponentTypeBody::collect_defs_from_attribute_extends()");
314 orig_defs_m
.add(name
, my_def
); // backup for init
315 all_defs_m
[name
] = def
; // point to inherited def
317 // my_def comes from another component type
318 // exclude case when the same definition is inherited on different
319 // paths, there must be a local definition
320 if (def
!=my_def
|| !orig_defs_m
.has_key(name
)) {
321 error("Definition `%s' inherited from component type `%s' "
322 "collides with definition inherited from `%s'", dispname_str
,
323 def
->get_my_scope()->get_fullname().c_str(),
324 my_def
->get_my_scope()->get_fullname().c_str());
325 def
->note("Definition of `%s' in `%s' is here",
326 dispname_str
, def
->get_my_scope()->get_fullname().c_str());
327 my_def
->note("Definition of `%s' in `%s' is here",
328 dispname_str
, my_def
->get_my_scope()->get_fullname().c_str());
329 if (orig_defs_m
.has_key(name
)) {
330 // the same definition is also present locally
331 orig_defs_m
[name
]->note("Local definition of `%s' is here",
337 error("Missing local definition of `%s', which was inherited from "
338 "component type `%s'", dispname_str
,
339 def
->get_my_scope()->get_fullname().c_str());
340 def
->note("Inherited definition of `%s' is here", dispname_str
);
346 void ComponentTypeBody::chk_defs_uniq()
348 if (check_state
>=CHECK_DEFUNIQ
) return;
349 check_state
= CHECK_DEFUNIQ
;
350 if (extends_refs
) extends_refs
->chk(CHECK_DEFUNIQ
);
351 if (attr_extends_refs
) attr_extends_refs
->chk(CHECK_DEFUNIQ
);
352 size_t nof_defs
= def_v
.size();
354 Error_Context
cntxt(this, "While checking uniqueness of component "
355 "element definitions");
356 Assignments
*module_defs
= parent_scope
->get_scope_asss();
357 // add own definitions to all_def_m
358 for (size_t i
= 0; i
< nof_defs
; i
++) {
359 Ttcn::Definition
*def
= def_v
[i
];
360 const Identifier
& id
= def
->get_id();
361 const string
& name
= id
.get_name();
362 if (all_defs_m
.has_key(name
)) {
363 const char *dispname_str
= id
.get_dispname().c_str();
364 def
->error("Duplicate definition with name `%s'", dispname_str
);
365 all_defs_m
[name
]->note("Previous definition of `%s' is here",
368 all_defs_m
.add(name
, def
);
369 if (module_defs
->has_local_ass_withId(id
)) {
370 const char *dispname_str
= id
.get_dispname().c_str();
371 def
->error("Component element name `%s' is not unique in the "
372 "scope hierarchy", dispname_str
);
373 module_defs
->get_local_ass_byId(id
)->note("Symbol `%s' is "
374 "already defined here in a higher scope unit", dispname_str
);
375 } else if (module_defs
->is_valid_moduleid(id
)) {
376 def
->warning("Definition with name `%s' hides a module identifier",
377 id
.get_dispname().c_str());
382 if (extends_refs
|| attr_extends_refs
) {
383 // collect all inherited definitions
384 Error_Context
cntxt(this, "While checking uniqueness of inherited "
385 "component element definitions");
386 if (extends_refs
) collect_defs_from_standard_extends();
387 if (attr_extends_refs
) collect_defs_from_attribute_extends();
391 void ComponentTypeBody::chk_my_defs()
393 if (check_state
>=CHECK_OWNDEFS
) return;
394 check_state
= CHECK_OWNDEFS
;
395 Error_Context
cntxt(this, "In component element definitions");
396 for (size_t i
= 0; i
< def_v
.size(); i
++) def_v
[i
]->chk();
399 void ComponentTypeBody::chk_attr_ext_defs()
401 if (check_state
>=CHECK_EXTDEFS
) return;
402 check_state
= CHECK_EXTDEFS
;
403 size_t nof_inherited_defs
= orig_defs_m
.size();
404 if (nof_inherited_defs
> 0) {
405 Error_Context
cntxt(this, "While checking whether the local and "
406 "inherited component element definitions are identical");
407 // for definitions inherited with attribute extends check if
408 // local and inherited definitions are identical
409 for (size_t i
= 0; i
< nof_inherited_defs
; i
++) {
410 const string
& key
= orig_defs_m
.get_nth_key(i
);
411 Ttcn::Definition
*original_def
= orig_defs_m
.get_nth_elem(i
);
412 Ttcn::Definition
*inherited_def
= all_defs_m
[key
];
413 if (!original_def
->chk_identical(inherited_def
))
414 all_defs_m
[key
] = original_def
;
419 void ComponentTypeBody::chk(check_state_t required_check_state
)
421 if (checking
|| check_state
==CHECK_FINAL
) return;
427 if (required_check_state
==CHECK_WITHATTRIB
) break;
429 case CHECK_WITHATTRIB
:
431 if (required_check_state
==CHECK_EXTENDS
) break;
435 if (required_check_state
==CHECK_DEFUNIQ
) break;
439 if (required_check_state
==CHECK_OWNDEFS
) break;
443 if (required_check_state
==CHECK_EXTDEFS
) break;
446 check_state
= CHECK_FINAL
;
451 FATAL_ERROR("ComponentTypeBody::chk()");
456 void ComponentTypeBody::set_genname(const string
& prefix
)
458 for (size_t i
= 0; i
< def_v
.size(); i
++) {
459 Ttcn::Definition
*def
= def_v
[i
];
460 def
->set_genname(prefix
+ def
->get_id().get_name());
465 void ComponentTypeBody::generate_code(output_struct
* target
)
467 if (check_state
!= CHECK_FINAL
|| !comp_id
)
468 FATAL_ERROR("ComponentTypeBody::generate_code()");
469 // beginning of block in init_comp
470 target
->functions
.init_comp
= mputprintf(target
->functions
.init_comp
,
471 "if (!strcmp(component_type, \"%s\")) {\n",
472 comp_id
->get_dispname().c_str());
474 // call init_comp for all components which are compatible
475 // with this component along standard extends paths
477 bool has_base_comps
= false;
478 for (size_t i
= 0; i
< compatible_m
.size(); i
++) {
479 ComponentTypeBody
*cb
= compatible_m
.get_nth_elem(i
);
480 // recursive initialization is needed if the component type is
481 // inherited using the standard "extends" mechanism and the component
482 // type has its own definitions
483 if (cb
&& cb
->def_v
.size() > 0) {
484 if (!has_base_comps
) {
485 target
->functions
.init_comp
= mputstr(target
->functions
.init_comp
,
486 "if (init_base_comps) {\n");
487 has_base_comps
= true;
489 const char *ct_dispname_str
= cb
->get_id()->get_dispname().c_str();
490 Module
*ct_mod
= cb
->get_scope_mod_gen();
491 if (ct_mod
== get_scope_mod_gen()) {
492 // the other component type is in the same module
493 // call the initializer function recursively
494 target
->functions
.init_comp
= mputprintf(
495 target
->functions
.init_comp
, "init_comp_type(\"%s\", FALSE);\n",
498 // the other component type is imported from another module
499 // use the module list for initialization
500 target
->functions
.init_comp
= mputprintf(
501 target
->functions
.init_comp
,
502 "Module_List::initialize_component(\"%s\", \"%s\", FALSE);\n",
503 ct_mod
->get_modid().get_dispname().c_str(), ct_dispname_str
);
507 if (has_base_comps
) {
508 // closing of the if() above
509 target
->functions
.init_comp
= mputstr(target
->functions
.init_comp
,
514 // code generation for embedded definitions
515 size_t nof_defs
= def_v
.size();
516 for (size_t i
= 0; i
< nof_defs
; i
++) {
517 Ttcn::Definition
*def
= def_v
[i
];
518 const string
& name
= def
->get_id().get_name();
519 if (orig_defs_m
.has_key(name
)) {
520 // def is hidden by an inherited definiton
521 // only an initializer shall be generated
522 target
->functions
.init_comp
= def
->generate_code_init_comp(
523 target
->functions
.init_comp
, all_defs_m
[name
]);
525 // def is a normal (non-inherited) definition
526 def
->generate_code(target
, true);
530 // end of block in init_comp
531 target
->functions
.init_comp
= mputstr(target
->functions
.init_comp
,
536 char *ComponentTypeBody::generate_code_comptype_name(char *str
)
539 FATAL_ERROR("ComponentTypeBody::generate_code_comtype_name()");
540 return mputprintf(str
, "\"%s\", \"%s\"",
541 parent_scope
->get_scope_mod_gen()->get_modid().get_dispname().c_str(),
542 comp_id
->get_dispname().c_str());
545 void ComponentTypeBody::set_parent_path(Ttcn::WithAttribPath
* p_path
) {
546 for (size_t i
= 0; i
< def_v
.size(); i
++)
547 def_v
[i
]->set_parent_path(p_path
);
550 // =================================
551 // ===== CompTypeRefList
552 // =================================
554 CompTypeRefList::~CompTypeRefList()
556 for (size_t i
=0; i
<comp_ref_v
.size(); i
++) delete comp_ref_v
[i
];
562 CompTypeRefList
*CompTypeRefList::clone() const
564 FATAL_ERROR("CompTypeRefList::clone()");
567 void CompTypeRefList::add_ref(Ttcn::Reference
*p_ref
)
569 if (!p_ref
|| checked
) FATAL_ERROR("CompTypeRefList::add_ref()");
570 comp_ref_v
.add(p_ref
);
573 void CompTypeRefList::dump(unsigned level
) const
575 for(size_t i
= 0; i
< comp_ref_v
.size(); i
++) comp_ref_v
[i
]->dump(level
+1);
578 void CompTypeRefList::set_fullname(const string
& p_fullname
)
580 Node::set_fullname(p_fullname
);
581 for (size_t i
=0; i
<comp_ref_v
.size(); i
++)
582 comp_ref_v
[i
]->set_fullname(p_fullname
+ ".<ref" + Int2string(i
+1) + ">");
585 void CompTypeRefList::chk_uniq()
589 for (size_t i
= 0; i
< comp_ref_v
.size(); i
++)
591 Ttcn::Reference
*ref
= comp_ref_v
[i
];
592 Type
*type
= ref
->chk_comptype_ref();
595 // add the component body to the map or error if it's duplicate
596 ComponentTypeBody
*cb
= type
->get_CompBody();
599 if (comp_body_m
.has_key(cb
))
601 const string
& type_name
= type
->get_typename();
602 const char *name
= type_name
.c_str();
603 ref
->error("Duplicate reference to component with name `%s'", name
);
604 comp_body_m
[cb
]->note("Previous reference to `%s' is here", name
);
608 // map and vector must always have same content
609 comp_body_m
.add(cb
, ref
);
617 void CompTypeRefList::chk(ComponentTypeBody::check_state_t
618 required_check_state
)
621 for (size_t i
=0; i
<comp_body_v
.size(); i
++)
622 comp_body_v
[i
]->chk(required_check_state
);
625 void CompTypeRefList::chk_recursion(ReferenceChain
& refch
)
627 for (size_t i
= 0; i
< comp_body_v
.size(); i
++) {
629 comp_body_v
[i
]->chk_recursion(refch
);
634 void CompTypeRefList::set_my_scope(Scope
*p_scope
)
636 for (size_t i
=0; i
<comp_ref_v
.size(); i
++)
637 comp_ref_v
[i
]->set_my_scope(p_scope
);
640 size_t CompTypeRefList::get_nof_comps()
642 if (!checked
) chk_uniq();
643 return comp_body_v
.size();
646 ComponentTypeBody
*CompTypeRefList::get_nth_comp_body(size_t i
)
648 if (!checked
) chk_uniq();
649 return comp_body_v
[i
];
652 Ttcn::Reference
*CompTypeRefList::get_nth_comp_ref(size_t i
)
654 if (!checked
) chk_uniq();
655 return comp_body_m
[comp_body_v
[i
]];
658 bool CompTypeRefList::has_comp_body(ComponentTypeBody
*cb
)
660 if (!checked
) chk_uniq();
661 return comp_body_m
.has_key(cb
);
664 } /* namespace Common */