1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
16 * Zalanyi, Balazs Andor
19 ******************************************************************************/
20 #include "TtcnTemplate.hh"
21 #include "../Identifier.hh"
22 #include "Templatestuff.hh"
24 #include "../TypeCompat.hh"
25 #include "../SigParam.hh"
26 #include "../CompField.hh"
27 #include "../Valuestuff.hh"
28 #include "ArrayDimensions.hh"
29 #include "PatternString.hh"
31 #include "../../common/dbgnew.hh"
32 #include "Attributes.hh"
36 // =================================
38 // =================================
40 Template::Template(const Template
& p
) : GovernedSimple(p
),
41 templatetype(p
.templatetype
), my_governor(p
.my_governor
),
42 is_ifpresent(p
.is_ifpresent
), specific_value_checked(false),
43 has_permutation(p
.has_permutation
), base_template(p
.base_template
)
45 switch (templatetype
) {
47 case TEMPLATE_NOTUSED
:
53 u
.specific_value
= p
.u
.specific_value
->clone();
56 u
.ref
.ref
= p
.u
.ref
.ref
->clone();
61 u
.invoke
.v
= p
.u
.invoke
.v
->clone();
62 u
.invoke
.t_list
= p
.u
.invoke
.t_list
? p
.u
.invoke
.t_list
->clone() : 0;
63 u
.invoke
.ap_list
= p
.u
.invoke
.ap_list
? p
.u
.invoke
.ap_list
->clone() : 0;
66 case VALUE_LIST_ALL_FROM
:
67 u
.all_from
= p
.u
.all_from
->clone();
71 case COMPLEMENTED_LIST
:
74 case PERMUTATION_MATCH
:
75 u
.templates
= p
.u
.templates
->clone(); // FATAL_ERROR
77 case NAMED_TEMPLATE_LIST
:
78 u
.named_templates
= p
.u
.named_templates
->clone();
80 case INDEXED_TEMPLATE_LIST
:
81 u
.indexed_templates
= p
.u
.indexed_templates
->clone();
84 u
.value_range
= p
.u
.value_range
->clone();
89 u
.pattern
= new string(*p
.u
.pattern
);
93 u
.pstring
= p
.u
.pstring
->clone();
96 // FATAL_ERROR("Template::Template()");
99 p
.length_restriction
? p
.length_restriction
->clone() : 0; // FATAL_ERR
102 void Template::clean_up()
104 switch(templatetype
) {
106 case TEMPLATE_NOTUSED
:
112 delete u
.specific_value
;
117 case TEMPLATE_INVOKE
:
119 delete u
.invoke
.t_list
;
120 delete u
.invoke
.ap_list
;
124 case COMPLEMENTED_LIST
:
127 case PERMUTATION_MATCH
:
131 case VALUE_LIST_ALL_FROM
:
134 case NAMED_TEMPLATE_LIST
:
135 delete u
.named_templates
;
137 case INDEXED_TEMPLATE_LIST
:
138 delete u
.indexed_templates
;
141 delete u
.value_range
;
153 // FATAL_ERROR("Template::clean_up()");
157 string
Template::create_stringRepr()
160 switch (templatetype
) {
162 ret_val
+= "<erroneous template>";
164 case TEMPLATE_NOTUSED
:
177 ret_val
+= u
.specific_value
->get_stringRepr();
179 case TEMPLATE_REFD
: {
180 Template
*t_last
= get_template_refd_last();
181 if (t_last
->templatetype
== TEMPLATE_REFD
)
182 ret_val
+= u
.ref
.ref
->get_dispname();
183 else ret_val
+= t_last
->get_stringRepr();
185 case TEMPLATE_INVOKE
: {
186 ret_val
+= u
.invoke
.v
->get_stringRepr();
187 ret_val
+= ".invoke(";
189 for(size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++) {
190 if(i
>0) ret_val
+= ", ";
191 ret_val
+= u
.invoke
.ap_list
->get_par(i
)->get_fullname();
196 if (u
.templates
->get_nof_ts() > 0) {
198 u
.templates
->append_stringRepr(ret_val
);
200 } else ret_val
+= "{ }";
202 case NAMED_TEMPLATE_LIST
:
204 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++) {
205 if (i
> 0) ret_val
+= ", ";
207 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
208 ret_val
+= nt
->get_name().get_dispname();
210 ret_val
+= nt
->get_template()->get_stringRepr();
214 case INDEXED_TEMPLATE_LIST
:
216 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
217 if (i
> 0) ret_val
+= ", ";
218 else ret_val
+= " [";
219 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
220 (it
->get_index()).append_stringRepr(ret_val
);
222 ret_val
+= it
->get_template()->get_stringRepr();
228 u
.templates
->append_stringRepr(ret_val
);
231 case COMPLEMENTED_LIST
:
232 ret_val
+= "complement(";
233 u
.templates
->append_stringRepr(ret_val
);
237 u
.value_range
->append_stringRepr(ret_val
);
240 ret_val
+= "superset(";
241 u
.templates
->append_stringRepr(ret_val
);
245 ret_val
+= "subset(";
246 u
.templates
->append_stringRepr(ret_val
);
249 case PERMUTATION_MATCH
:
250 ret_val
+= "permutation(";
251 u
.templates
->append_stringRepr(ret_val
);
256 ret_val
+= *u
.pattern
;
261 ret_val
+= *u
.pattern
;
266 ret_val
+= *u
.pattern
;
271 ret_val
+= "pattern \"";
272 ret_val
+= u
.pstring
->get_full_str();
276 ret_val
+= "<unknown template>";
279 if (length_restriction
) length_restriction
->append_stringRepr(ret_val
);
280 if (is_ifpresent
) ret_val
+= " ifpresent";
284 Template::Template(templatetype_t tt
)
285 : GovernedSimple(S_TEMPLATE
),
286 templatetype(tt
), my_governor(0), length_restriction(0),
287 is_ifpresent(false), specific_value_checked(false),
288 has_permutation(false), flattened(true), base_template(0)
292 case TEMPLATE_NOTUSED
:
298 FATAL_ERROR("Template::Template()");
302 Template::Template(Value
*v
)
303 : GovernedSimple(S_TEMPLATE
),
304 templatetype(SPECIFIC_VALUE
), my_governor(0), length_restriction(0),
305 is_ifpresent(false), specific_value_checked(false),
306 has_permutation(false), flattened(true), base_template(0)
308 if (!v
) FATAL_ERROR("Template::Template()");
309 u
.specific_value
= v
;
312 Template::Template(Ref_base
*p_ref
)
313 : GovernedSimple(S_TEMPLATE
),
314 templatetype(TEMPLATE_REFD
), my_governor(0), length_restriction(0),
315 is_ifpresent(false), specific_value_checked(false),
316 has_permutation(false), base_template(0)
318 if(!p_ref
) FATAL_ERROR("Template::Template()");
324 Template::Template(templatetype_t tt
, Templates
*ts
)
325 : GovernedSimple(S_TEMPLATE
),
326 templatetype(tt
), my_governor(0), length_restriction(0),
327 is_ifpresent(false), specific_value_checked(false),
328 has_permutation(false), flattened(true), base_template(0)
333 case COMPLEMENTED_LIST
:
336 case PERMUTATION_MATCH
:
339 FATAL_ERROR("Template::Template()");
341 if (!ts
) FATAL_ERROR("Template::Template()");
343 if (tt
== TEMPLATE_LIST
) {
344 size_t nof_ts
= ts
->get_nof_ts();
345 for (size_t i
= 0; i
< nof_ts
; i
++) {
346 if (ts
->get_t_byIndex(i
)->templatetype
== PERMUTATION_MATCH
) {
347 has_permutation
= true;
354 Template::Template(Template
*t
)
355 : GovernedSimple(S_TEMPLATE
)
356 , templatetype(ALL_FROM
), my_governor(0), length_restriction(0)
357 , is_ifpresent(false), specific_value_checked(false)
358 , has_permutation(false), flattened(true), base_template(0)
361 // t is usually a SPECIFIC_VALUE
362 // t->u.specific_value is a V_UNDEF_LOWERID
363 // calling set_lowerid_to_ref is too soon (my_scope is not set yet)
366 Template::Template(templatetype_t tt
, Template
*t
)
367 : GovernedSimple(S_TEMPLATE
)
368 , templatetype(VALUE_LIST_ALL_FROM
), my_governor(0), length_restriction(0)
369 , is_ifpresent(false), specific_value_checked(false)
370 , has_permutation(false), flattened(true), base_template(0)
372 if (tt
!= VALUE_LIST_ALL_FROM
) FATAL_ERROR("Template::Template()");
373 u
.all_from
= t
->u
.all_from
; // take it over
374 t
->u
.all_from
= NULL
;
378 Template::Template(NamedTemplates
*nts
)
379 : GovernedSimple(S_TEMPLATE
),
380 templatetype(NAMED_TEMPLATE_LIST
), my_governor(0), length_restriction(0),
381 is_ifpresent(false), specific_value_checked(false),
382 has_permutation(false), flattened(true), base_template(0)
384 if (!nts
) FATAL_ERROR("Template::Template()");
385 u
.named_templates
= nts
;
388 Template::Template(IndexedTemplates
*its
)
389 : GovernedSimple(S_TEMPLATE
),
390 templatetype(INDEXED_TEMPLATE_LIST
), my_governor(0),
391 length_restriction(0), is_ifpresent(false),
392 specific_value_checked(false), has_permutation(false), flattened(true),
395 if (!its
) FATAL_ERROR("Template::Template()");
396 u
.indexed_templates
= its
;
397 size_t nof_its
= its
->get_nof_its();
398 for (size_t i
= 0; i
< nof_its
; i
++) {
399 if (its
->get_it_byIndex(i
)->get_template()->templatetype
==
401 has_permutation
= true;
407 Template::Template(ValueRange
*vr
)
408 : GovernedSimple(S_TEMPLATE
),
409 templatetype(VALUE_RANGE
), my_governor(0), length_restriction(0),
410 is_ifpresent(false), specific_value_checked(false),
411 has_permutation(false), flattened(true), base_template(0)
413 if (!vr
) FATAL_ERROR("Template::Template()");
417 Template::Template(templatetype_t tt
, string
*p_patt
)
418 : GovernedSimple(S_TEMPLATE
),
419 templatetype(tt
), my_governor(0), length_restriction(0),
420 is_ifpresent(false), specific_value_checked(false),
421 has_permutation(false), flattened(true), base_template(0)
429 FATAL_ERROR("Template::Template()");
431 if (!p_patt
) FATAL_ERROR("Template::Template()");
435 Template::Template(PatternString
*p_ps
)
436 : GovernedSimple(S_TEMPLATE
),
437 templatetype(CSTR_PATTERN
), my_governor(0), length_restriction(0),
438 is_ifpresent(false), specific_value_checked(false),
439 has_permutation(false), flattened(true), base_template(0)
441 if (!p_ps
) FATAL_ERROR("Template::Template()");
445 Template::~Template()
448 delete length_restriction
;
451 Template
*Template::clone() const
453 return new Template(*this);
456 void Template::set_fullname(const string
& p_fullname
)
458 GovernedSimple::set_fullname(p_fullname
);
459 switch (templatetype
) {
461 case TEMPLATE_NOTUSED
:
470 u
.specific_value
->set_fullname(p_fullname
);
473 u
.ref
.ref
->set_fullname(p_fullname
);
475 case TEMPLATE_INVOKE
:
476 u
.invoke
.v
->set_fullname(p_fullname
);
477 if(u
.invoke
.t_list
) u
.invoke
.t_list
->set_fullname(p_fullname
);
478 if(u
.invoke
.ap_list
) u
.invoke
.ap_list
->set_fullname(p_fullname
);
481 u
.templates
->set_fullname(p_fullname
);
482 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
483 u
.templates
->get_t_byIndex(i
)->set_fullname(
484 p_fullname
+ "[" + Int2string(i
) + "]");
486 case INDEXED_TEMPLATE_LIST
:
487 u
.indexed_templates
->set_fullname(p_fullname
);
488 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
489 u
.indexed_templates
->get_it_byIndex(i
)->set_fullname(
490 p_fullname
+ "[" + Int2string(i
) + "]");
492 case NAMED_TEMPLATE_LIST
:
493 u
.named_templates
->set_fullname(p_fullname
);
496 case VALUE_LIST_ALL_FROM
:
497 u
.all_from
->set_fullname(p_fullname
);
500 case COMPLEMENTED_LIST
:
503 case PERMUTATION_MATCH
:
504 u
.templates
->set_fullname(p_fullname
);
505 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
506 u
.templates
->get_t_byIndex(i
)->set_fullname(
507 p_fullname
+ ".list_item(" + Int2string(i
) + ")");
510 u
.value_range
->set_fullname(p_fullname
);
514 u
.pstring
->set_fullname(p_fullname
);
517 // FATAL_ERROR("Template::set_fullname()");
519 if (length_restriction
)
520 length_restriction
->set_fullname(p_fullname
+ ".<length_restriction>");
523 void Template::set_my_scope(Scope
*p_scope
)
525 GovernedSimple::set_my_scope(p_scope
);
526 switch (templatetype
) {
528 case TEMPLATE_NOTUSED
:
537 u
.specific_value
->set_my_scope(p_scope
);
540 u
.ref
.ref
->set_my_scope(p_scope
);
542 case TEMPLATE_INVOKE
:
543 u
.invoke
.v
->set_my_scope(p_scope
);
544 if(u
.invoke
.t_list
) u
.invoke
.t_list
->set_my_scope(p_scope
);
545 if(u
.invoke
.ap_list
) u
.invoke
.ap_list
->set_my_scope(p_scope
);
548 case VALUE_LIST_ALL_FROM
:
549 u
.all_from
->set_my_scope(p_scope
);
553 case COMPLEMENTED_LIST
:
556 case PERMUTATION_MATCH
:
557 u
.templates
->set_my_scope(p_scope
);
559 case NAMED_TEMPLATE_LIST
:
560 u
.named_templates
->set_my_scope(p_scope
);
562 case INDEXED_TEMPLATE_LIST
:
563 u
.indexed_templates
->set_my_scope(p_scope
);
566 u
.value_range
->set_my_scope(p_scope
);
570 u
.pstring
->set_my_scope(p_scope
);
573 // FATAL_ERROR("Template::set_my_scope()");
575 if (length_restriction
) length_restriction
->set_my_scope(p_scope
);
578 void Template::set_genname_recursive(const string
& p_genname
)
580 set_genname(p_genname
);
581 switch (templatetype
) {
582 case TEMPLATE_LIST
: {
583 if (!my_governor
) return; // error recovery
584 Type
*type
= my_governor
->get_type_refd_last();
586 if (type
->get_typetype() == Type::T_ARRAY
)
587 offset
= type
->get_dimension()->get_offset();
589 size_t nof_ts
= u
.templates
->get_nof_ts();
590 for (size_t i
= 0; i
< nof_ts
; i
++) {
591 string
embedded_genname(p_genname
);
592 embedded_genname
+= '[';
593 embedded_genname
+= Int2string(offset
+ i
);
594 embedded_genname
+= ']';
595 u
.templates
->get_t_byIndex(i
)->set_genname_recursive(embedded_genname
);
598 case NAMED_TEMPLATE_LIST
: {
599 if (!my_governor
) return; // error recovery
600 Type
*type
= my_governor
->get_type_refd_last();
601 size_t nof_nts
= u
.named_templates
->get_nof_nts();
602 for (size_t i
= 0; i
< nof_nts
; i
++) {
603 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
604 string
embedded_genname(p_genname
);
605 embedded_genname
+= '.';
606 if (type
->get_typetype() == Type::T_ANYTYPE
)
607 embedded_genname
+= "AT_";
608 embedded_genname
+= nt
->get_name().get_name();
609 embedded_genname
+= "()";
610 nt
->get_template()->set_genname_recursive(embedded_genname
);
618 void Template::set_genname_prefix(const char *p_genname_prefix
)
620 GovernedSimple::set_genname_prefix(p_genname_prefix
);
621 switch (templatetype
) {
623 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
624 u
.templates
->get_t_byIndex(i
)->set_genname_prefix(p_genname_prefix
);
626 case NAMED_TEMPLATE_LIST
:
627 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
628 u
.named_templates
->get_nt_byIndex(i
)->get_template()
629 ->set_genname_prefix(p_genname_prefix
);
631 case INDEXED_TEMPLATE_LIST
:
632 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
633 u
.indexed_templates
->get_it_byIndex(i
)->get_template()
634 ->set_genname_prefix(p_genname_prefix
);
641 void Template::set_code_section(code_section_t p_code_section
)
643 GovernedSimple::set_code_section(p_code_section
);
644 switch (templatetype
) {
646 u
.specific_value
->set_code_section(p_code_section
);
649 u
.ref
.ref
->set_code_section(p_code_section
);
651 case TEMPLATE_INVOKE
:
652 u
.invoke
.v
->set_code_section(p_code_section
);
653 if(u
.invoke
.t_list
) u
.invoke
.t_list
->set_code_section(p_code_section
);
655 for(size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++)
656 u
.invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
660 case COMPLEMENTED_LIST
:
663 case PERMUTATION_MATCH
:
664 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
665 u
.templates
->get_t_byIndex(i
)->set_code_section(p_code_section
);
667 case NAMED_TEMPLATE_LIST
:
668 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
669 u
.named_templates
->get_nt_byIndex(i
)->get_template()
670 ->set_code_section(p_code_section
);
672 case INDEXED_TEMPLATE_LIST
:
673 for (size_t i
= 0; i
<u
.indexed_templates
->get_nof_its(); i
++)
674 u
.indexed_templates
->get_it_byIndex(i
)
675 ->set_code_section(p_code_section
);
678 u
.value_range
->set_code_section(p_code_section
);
682 u
.pstring
->set_code_section(p_code_section
);
687 if (length_restriction
)
688 length_restriction
->set_code_section(p_code_section
);
691 void Template::set_templatetype(templatetype_t p_templatetype
)
693 if (p_templatetype
== templatetype
) return;
694 if (p_templatetype
== TEMPLATE_ERROR
) {
696 templatetype
= TEMPLATE_ERROR
;
699 switch (templatetype
) {
700 case SPECIFIC_VALUE
: // current type
701 switch(p_templatetype
) {
702 case TEMPLATE_REFD
: {
703 Value
*v
= u
.specific_value
;
704 u
.ref
.ref
= v
->steal_ttcn_ref_base();
709 case TEMPLATE_INVOKE
: {
710 Value
*v
= u
.specific_value
;
711 v
->steal_invoke_data(u
.invoke
.v
, u
.invoke
.t_list
, u
.invoke
.ap_list
);
715 FATAL_ERROR("Template::set_templatetype()");
718 case TEMPLATE_LIST
: // current type
719 if (p_templatetype
== NAMED_TEMPLATE_LIST
) {
720 // TEMPLATE_LIST -> NAMED_TEMPLATE_LIST:
721 // value list -> assignment notation
722 // applicable to record types, signatures and empty set types
723 if (!my_governor
) FATAL_ERROR("Template::set_templatetype()");
724 Type
*t
= my_governor
->get_type_refd_last();
725 size_t nof_comps
= t
->get_nof_comps(); // "expected" nr of components
726 Templates
*sts
= u
.templates
;
727 size_t nof_temps
= sts
->get_nof_ts(); // "actual" nr in the list
728 Type::typetype_t tt
= t
->get_typetype();
732 case Type::T_SIGNATURE
:
736 if (nof_temps
== 0 && nof_comps
== 0) break;
738 FATAL_ERROR("Template::set_templatetype()");
740 // If it's a record or set template, allow fewer elements than
741 // what is required, because implicit omit may take care of it.
742 // If it's a signature template, be precise.
743 bool allow_fewer
= false;
744 switch (my_governor
->get_typetype()) {
745 case Type::T_SEQ_T
: case Type::T_SET_T
:
746 case Type::T_SEQ_A
: case Type::T_SET_A
:
749 case Type::T_SIGNATURE
: // be precise
751 default: // not possible, fatal error ?
754 if ( nof_temps
> nof_comps
755 || (!allow_fewer
&& (nof_temps
< nof_comps
))) {
756 error("Too %s elements in value list notation for type `%s': "
757 "%lu was expected instead of %lu",
758 nof_temps
> nof_comps
? "many" : "few",
759 t
->get_typename().c_str(),
760 (unsigned long) nof_comps
, (unsigned long) nof_temps
);
762 size_t upper_limit
; // min(nof_temps, nof_comps)
764 if (nof_temps
<= nof_comps
) {
765 upper_limit
= nof_temps
;
768 upper_limit
= nof_comps
;
771 u
.named_templates
= new NamedTemplates
;
772 for (size_t i
= 0; i
< upper_limit
; i
++) {
773 Template
*& temp
= sts
->get_t_byIndex(i
);
774 if (temp
->templatetype
== TEMPLATE_NOTUSED
) continue;
776 NamedTemplate
*nt
= new
777 NamedTemplate(t
->get_comp_id_byIndex(i
).clone(), temp
);
778 nt
->set_location(*temp
);
779 u
.named_templates
->add_nt(nt
);
782 u
.named_templates
->set_my_scope(get_my_scope());
783 u
.named_templates
->set_fullname(get_fullname());
785 if (all_notused
&& nof_temps
> 0 && tt
!= Type::T_SIGNATURE
)
786 warning("All elements of value list notation for type `%s' are "
787 "not used symbols (`-')", t
->get_typename().c_str());
788 } else FATAL_ERROR("Template::set_templatetype()");
790 case CSTR_PATTERN
: // current type
791 if (p_templatetype
== USTR_PATTERN
)
792 templatetype
= USTR_PATTERN
;
794 FATAL_ERROR("Template::set_templatetype()");
797 FATAL_ERROR("Template::set_templatetype()");
799 templatetype
= p_templatetype
;
802 const char *Template::get_templatetype_str() const
804 switch(templatetype
) {
806 return "erroneous template";
807 case TEMPLATE_NOTUSED
:
808 return "not used symbol";
814 return "any or omit";
816 return "specific value";
818 return "referenced template";
819 case TEMPLATE_INVOKE
:
820 return "template returning invoke";
822 case VALUE_LIST_ALL_FROM
:
823 return "template with 'all from'";
825 return "value list notation";
826 case NAMED_TEMPLATE_LIST
:
827 return "assignment notation";
828 case INDEXED_TEMPLATE_LIST
:
829 return "assignment notation with array indices";
831 return "value range match";
833 return "value list match";
834 case COMPLEMENTED_LIST
:
835 return "complemented list match";
837 return "superset match";
839 return "subset match";
840 case PERMUTATION_MATCH
:
841 return "permutation match";
843 return "bitstring pattern";
845 return "hexstring pattern";
847 return "octetstring pattern";
849 return "character string pattern";
851 return "universal string pattern";
853 return "unknown template";
857 bool Template::is_undef_lowerid()
859 return templatetype
== SPECIFIC_VALUE
&&
860 u
.specific_value
->is_undef_lowerid();
863 void Template::set_lowerid_to_ref()
865 switch (templatetype
) {
867 u
.specific_value
->set_lowerid_to_ref();
868 if (u
.specific_value
->get_valuetype() == Value::V_REFD
) {
869 Common::Assignment
*t_ass
=
870 u
.specific_value
->get_reference()->get_refd_assignment(false);
872 switch (t_ass
->get_asstype()) {
873 case Common::Assignment::A_MODULEPAR_TEMP
:
874 case Common::Assignment::A_TEMPLATE
:
875 case Common::Assignment::A_VAR_TEMPLATE
:
876 case Common::Assignment::A_PAR_TEMPL_IN
:
877 case Common::Assignment::A_PAR_TEMPL_OUT
:
878 case Common::Assignment::A_PAR_TEMPL_INOUT
:
879 case Common::Assignment::A_FUNCTION_RTEMP
:
880 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
881 set_templatetype(TEMPLATE_REFD
);
885 } else set_templatetype(TEMPLATE_ERROR
);
889 case COMPLEMENTED_LIST
:
890 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
891 u
.templates
->get_t_byIndex(i
)->set_lowerid_to_ref();
894 u
.value_range
->set_lowerid_to_ref();
901 Type::typetype_t
Template::get_expr_returntype(Type::expected_value_t exp_val
)
903 switch (templatetype
) {
905 return Type::T_ERROR
;
907 return u
.specific_value
->get_expr_returntype(exp_val
);
908 case TEMPLATE_REFD
: {
909 Type
*t
= get_expr_governor(exp_val
);
910 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
911 else return Type::T_ERROR
; }
912 case TEMPLATE_INVOKE
: {
913 Type
*t
= get_expr_governor(exp_val
);
914 if(t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
915 else return Type::T_ERROR
; }
917 case COMPLEMENTED_LIST
:
918 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
919 Type::typetype_t tt
= u
.templates
->get_t_byIndex(i
)
920 ->get_expr_returntype(exp_val
);
921 if (tt
!= Type::T_UNDEF
) return tt
;
923 return Type::T_UNDEF
;
925 return u
.value_range
->get_expr_returntype(exp_val
);
928 return Type::T_SETOF
;
940 return Type::T_UNDEF
;
944 Type
*Template::get_expr_governor(Type::expected_value_t exp_val
)
946 if (my_governor
) return my_governor
;
947 switch (templatetype
) {
949 return u
.specific_value
->get_expr_governor(exp_val
);
951 case COMPLEMENTED_LIST
:
952 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
953 Type
*t
= u
.templates
->get_t_byIndex(i
)->get_expr_governor(exp_val
);
958 return u
.value_range
->get_expr_governor(exp_val
);
959 case TEMPLATE_REFD
: {
960 Type
*t
= u
.ref
.ref
->get_refd_assignment()->get_Type()
961 ->get_field_type(u
.ref
.ref
->get_subrefs(), exp_val
);
962 if (!t
) set_templatetype(TEMPLATE_ERROR
);
965 case TEMPLATE_INVOKE
: {
966 Type
*t
= u
.invoke
.v
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
968 if(u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
969 u
.invoke
.v
->error("A value of type function expected");
972 t
= t
->get_type_refd_last();
973 switch(t
->get_typetype()) {
974 case Type::T_FUNCTION
:
975 if(exp_val
==Type::EXPECTED_DYNAMIC_VALUE
&& t
->get_returns_template()){
976 error("Reference to a value was expected instead of a "
977 "template of type `%s'"
978 , t
->get_function_return_type()->get_typename().c_str());
981 return t
->get_function_return_type();
982 case Type::T_ALTSTEP
:
985 u
.invoke
.v
->error("A value of type function expected instead of `%s'",
986 t
->get_typename().c_str());
991 return Type::get_pooltype(get_expr_returntype(exp_val
));
994 set_templatetype(TEMPLATE_ERROR
);
998 void Template::set_my_governor(Type
*p_gov
)
1001 FATAL_ERROR("Template::set_my_governor(): NULL parameter");
1005 Type
*Template::get_my_governor() const
1010 void Template::set_length_restriction(LengthRestriction
*p_lr
)
1012 if (length_restriction
) FATAL_ERROR("Template::set_length_restriction()");
1013 length_restriction
= p_lr
;
1016 Template::completeness_t
1017 Template::get_completeness_condition_seof(bool incomplete_allowed
)
1019 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1020 else if (!base_template
) return C_MAY_INCOMPLETE
;
1022 Template
*t
= base_template
->get_template_refd_last();
1023 switch (t
->templatetype
) {
1024 // partial overwriting is allowed
1025 case TEMPLATE_ERROR
: // to suppress more errors
1026 case TEMPLATE_NOTUSED
: // modifying a modified template
1027 case ANY_VALUE
: // in case of ?
1028 case ANY_OR_OMIT
: // in case of *
1029 case TEMPLATE_REFD
: // e.g. the actual value of a formal parameter
1030 case TEMPLATE_INVOKE
:
1031 case NAMED_TEMPLATE_LIST
: // t is erroneous
1032 case INDEXED_TEMPLATE_LIST
:
1033 return C_MAY_INCOMPLETE
;
1035 switch (my_governor
->get_type_refd_last()->get_typetype()) {
1038 // only the first elements can be incomplete
1041 // we are in error recovery
1042 return C_MAY_INCOMPLETE
;
1044 break; // should not get here
1046 // partial overwriting is not allowed for literal specific values,
1047 // matching ranges/lists/sets and patterns
1048 return C_MUST_COMPLETE
;
1053 Template::completeness_t
Template::get_completeness_condition_choice
1054 (bool incomplete_allowed
, const Identifier
& p_fieldname
)
1056 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1057 else if (!base_template
) return C_MAY_INCOMPLETE
;
1059 Template
*t
= base_template
->get_template_refd_last();
1060 switch (t
->templatetype
) {
1061 // partial overwriting is allowed
1062 case TEMPLATE_ERROR
: // to suppress more errors
1063 case TEMPLATE_NOTUSED
: // t is erroneous
1064 case ANY_VALUE
: // in case of ?
1065 case ANY_OR_OMIT
: // in case of *
1066 case TEMPLATE_REFD
: // e.g. the actual value of a formal parameter
1067 case TEMPLATE_INVOKE
:
1068 case TEMPLATE_LIST
: // t is erroneous
1069 return C_MAY_INCOMPLETE
;
1070 case NAMED_TEMPLATE_LIST
: // some fields may be missing
1071 if (t
->u
.named_templates
->has_nt_withName(p_fieldname
))
1072 return C_MAY_INCOMPLETE
;
1073 else return C_MUST_COMPLETE
;
1075 // partial overwriting is not allowed for literal specific values,
1076 // matching ranges/lists/sets and patterns
1077 return C_MUST_COMPLETE
;
1082 void Template::add_named_temp(NamedTemplate
* nt
) {
1083 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1084 FATAL_ERROR("Template::add_named_temp()");
1085 u
.named_templates
->add_nt(nt
);
1088 Value
*Template::get_specific_value() const
1090 if (templatetype
!= SPECIFIC_VALUE
)
1091 FATAL_ERROR("Template::get_specific_value()");
1092 return u
.specific_value
;
1095 Ref_base
*Template::get_reference() const
1097 if (templatetype
!= TEMPLATE_REFD
)
1098 FATAL_ERROR("Template::get_reference()");
1102 ValueRange
*Template::get_value_range() const
1104 if (templatetype
!= VALUE_RANGE
)
1105 FATAL_ERROR("Template::get_value_range()");
1106 return u
.value_range
;
1109 PatternString
* Template::get_cstr_pattern() const
1111 if (templatetype
!= CSTR_PATTERN
)
1112 FATAL_ERROR("Template::get_cstr_pattern()");
1116 PatternString
* Template::get_ustr_pattern() const
1118 if (templatetype
!= USTR_PATTERN
)
1119 FATAL_ERROR("Template::get_ustr_pattern()");
1123 size_t Template::get_nof_comps() const
1125 switch (templatetype
) {
1128 case COMPLEMENTED_LIST
:
1129 case SUPERSET_MATCH
:
1131 case PERMUTATION_MATCH
:
1132 return u
.templates
->get_nof_ts();
1133 case NAMED_TEMPLATE_LIST
:
1134 return u
.named_templates
->get_nof_nts();
1135 case INDEXED_TEMPLATE_LIST
:
1136 return u
.indexed_templates
->get_nof_its();
1138 FATAL_ERROR("Template::get_of_comps()");
1143 Template
*Template::get_temp_byIndex(size_t n
) const
1145 switch (templatetype
) {
1148 case COMPLEMENTED_LIST
:
1149 case SUPERSET_MATCH
:
1151 case PERMUTATION_MATCH
:
1152 return u
.templates
->get_t_byIndex(n
);
1154 FATAL_ERROR("Template::get_temp_byIndex()");
1159 IndexedTemplate
*Template::get_indexedtemp_byIndex(size_t n
) const
1161 if (templatetype
!= INDEXED_TEMPLATE_LIST
)
1162 FATAL_ERROR("Template::get_indexedtemp_byIndex()");
1163 return u
.indexed_templates
->get_it_byIndex(n
);
1166 NamedTemplate
*Template::get_namedtemp_byIndex(size_t n
) const
1168 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1169 FATAL_ERROR("Template::get_namedtemp_byIndex()");
1170 return u
.named_templates
->get_nt_byIndex(n
);
1173 Template
*Template::get_all_from() const
1175 if (templatetype
!= ALL_FROM
1176 &&templatetype
!= VALUE_LIST_ALL_FROM
)
1177 FATAL_ERROR("Template::get_all_from()");
1181 // Not applicable to INDEXED_TEMPLATE_LIST nodes. The actual number of
1182 // elements is not known.
1183 size_t Template::get_nof_listitems() const
1185 if (templatetype
!= TEMPLATE_LIST
)
1186 FATAL_ERROR("Template::get_nof_listitems()");
1187 if (has_permutation
) {
1188 size_t nof_ts
= u
.templates
->get_nof_ts(), ret_val
= 0;
1189 for (size_t i
= 0; i
< nof_ts
; i
++) {
1190 Template
*t
= u
.templates
->get_t_byIndex(i
);
1191 if (t
->templatetype
== PERMUTATION_MATCH
)
1192 ret_val
+= t
->u
.templates
->get_nof_ts();
1196 } else return u
.templates
->get_nof_ts();
1199 Template
*Template::get_listitem_byIndex(size_t n
) const
1201 if (templatetype
!= TEMPLATE_LIST
)
1202 FATAL_ERROR("Template::get_listitam_byIndex()");
1203 if (has_permutation
) {
1204 size_t nof_ts
= u
.templates
->get_nof_ts(), index
= 0;
1205 for (size_t i
= 0; i
< nof_ts
; i
++) {
1206 Template
*t
= u
.templates
->get_t_byIndex(i
);
1207 if (t
->templatetype
== PERMUTATION_MATCH
) {
1208 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
1209 if (n
< index
+ nof_perm_ts
)
1210 return t
->u
.templates
->get_t_byIndex(n
- index
);
1211 else index
+= nof_perm_ts
;
1213 if (n
== index
) return t
;
1217 FATAL_ERROR("Template::get_listitem_byIndex(): index overflow");
1219 } else return u
.templates
->get_t_byIndex(n
);
1222 /** \todo revise and merge with get_template_refd() */
1223 Template
* Template::get_template_refd_last(ReferenceChain
*refch
)
1225 // return this for non-referenced templates
1226 if (templatetype
!= TEMPLATE_REFD
) return this;
1227 // use the cached template if present
1228 else if (u
.ref
.refd_last
) return u
.ref
.refd_last
;
1230 Common::Assignment
*t_ass
= u
.ref
.ref
->get_refd_assignment();
1231 // escape from invalid recursion loops
1232 if (templatetype
!= TEMPLATE_REFD
) return this;
1233 if (!t_ass
) FATAL_ERROR("Template::get_template_refd_last()");
1234 if (t_ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) {
1235 // return this if the reference does not point to a template
1236 u
.ref
.refd_last
= this;
1237 return u
.ref
.refd_last
;
1240 // otherwise evaluate the reference
1243 refch
->mark_state();
1244 destroy_refch
= false;
1246 refch
= new ReferenceChain(this, "While searching referenced template");
1247 destroy_refch
= true;
1250 if (refch
->add(get_fullname())) {
1251 Template
*t_refd
= get_template_refd(refch
);
1252 // get_template_refd() may set u.ref.refd_last if there are unfoldable
1253 // sub-references in u.ref.ref
1254 if (!u
.ref
.refd_last
) {
1255 u
.ref
.refd_last
= t_refd
->get_template_refd_last(refch
);
1257 ret_val
= u
.ref
.refd_last
;
1259 // a circular reference was found
1260 set_templatetype(TEMPLATE_ERROR
);
1263 if (destroy_refch
) delete refch
;
1264 else refch
->prev_state();
1268 Template
* Template::get_refd_sub_template(Ttcn::FieldOrArrayRefs
*subrefs
,
1270 ReferenceChain
*refch
)
1272 if (!subrefs
) return this;
1274 for (size_t i
=0; i
<subrefs
->get_nof_refs(); i
++) {
1276 t
=t
->get_template_refd_last(refch
);
1277 t
->set_lowerid_to_ref();
1278 switch(t
->templatetype
) {
1279 case TEMPLATE_ERROR
:
1282 case INDEXED_TEMPLATE_LIST
:
1285 case SPECIFIC_VALUE
:
1286 (void)t
->u
.specific_value
->get_refd_sub_value(
1287 subrefs
, i
, usedInIsbound
, refch
); // only to report errors
1292 Ttcn::FieldOrArrayRef
*ref
=subrefs
->get_ref(i
);
1293 if(ref
->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF
)
1294 t
=t
->get_refd_field_template(*ref
->get_id(), *ref
, usedInIsbound
,
1296 else t
=t
->get_refd_array_template(ref
->get_val(), usedInIsbound
, refch
);
1301 Template
* Template::get_template_refd(ReferenceChain
*refch
)
1303 unsigned int const prev_err_count
= get_error_count();
1304 if (templatetype
!= TEMPLATE_REFD
)
1305 FATAL_ERROR("Template::get_template_refd()");
1306 // use the cached pointer if it is already set
1307 if (u
.ref
.refd
) return u
.ref
.refd
;
1308 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1309 if (!ass
) FATAL_ERROR("Template::get_template_refd()");
1310 if(ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
1311 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
1312 Template
*asst
= ass
->get_Template();
1313 Template
*t
= asst
->get_refd_sub_template(
1314 subrefs
, u
.ref
.ref
->getUsedInIsbound(), refch
);
1317 // Why do we not set u.ref.refd_last ?
1319 else if (subrefs
&& subrefs
->has_unfoldable_index()) {
1320 // some array indices could not be evaluated
1322 u
.ref
.refd_last
= this;
1323 } else if (u
.ref
.ref
->getUsedInIsbound()) {
1325 u
.ref
.refd_last
= this;
1327 // an error was found while resolving sub-references
1328 if (get_error_count() == prev_err_count
) {
1329 // it was not reported, report it now
1330 error("Using a template which refers to a non-template is not supported");
1331 asst
->note("Workaround: change the right hand side refer to a template");
1332 if (ass
->is_local()) {
1333 ass
->note("Workaround: change the template definition "
1334 "to a var template");
1337 set_templatetype(TEMPLATE_ERROR
);
1341 // the reference is unfoldable
1347 Template
* Template::get_refd_field_template(const Identifier
& field_id
,
1348 const Location
& loc
, bool usedInIsbound
, ReferenceChain
*refch
)
1350 switch (templatetype
) {
1355 case COMPLEMENTED_LIST
:
1356 // the above template types are valid matching mechanisms,
1357 // but they cannot be sub-referenced
1358 loc
.error("Reference to field `%s' of %s `%s'",
1359 field_id
.get_dispname().c_str(), get_templatetype_str(),
1360 get_fullname().c_str());
1365 if(!my_governor
) FATAL_ERROR("Template::get_refd_field_template()");
1366 Type
*t
= my_governor
->get_type_refd_last();
1367 const char *typetype_str
="set";
1368 switch(t
->get_typetype()) {
1372 case Type::T_CHOICE_A
:
1373 case Type::T_CHOICE_T
:
1374 case Type::T_OPENTYPE
:
1375 case Type::T_ANYTYPE
:
1376 if (!t
->has_comp_withName(field_id
)) {
1377 loc
.error("Reference to non-existent union field `%s' in type `%s'",
1378 field_id
.get_dispname().c_str(), t
->get_typename().c_str());
1380 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1381 // this is an invalid matching mechanism, the error is already reported
1382 //error("invalid matching mechanism (not template list) but %d", templatetype);
1384 } else if (u
.named_templates
->get_nof_nts() != 1) {
1385 // this is an invalid union template (more than one active field)
1386 // the error is already reported
1387 //error("invalid union template ");
1390 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(0);
1391 if (nt
->get_name() != field_id
) {
1392 if (!usedInIsbound
) {
1393 loc
.error("Reference to inactive field `%s' in a template of"
1394 " union type `%s'. The active field is `%s'.",
1395 field_id
.get_dispname().c_str(),
1396 t
->get_typename().c_str(),
1397 nt
->get_name().get_dispname().c_str());
1402 return nt
->get_template();
1407 typetype_str
="record";
1411 if (!t
->has_comp_withName(field_id
)) {
1412 loc
.error("Reference to non-existent %s field `%s' in type `%s'",
1413 typetype_str
, field_id
.get_dispname().c_str(),
1414 t
->get_typename().c_str());
1416 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1417 // this is an invalid matching mechanism
1418 // the error should be already reported
1420 } else if (u
.named_templates
->has_nt_withName(field_id
)) {
1421 // the field is found, everything is OK
1422 return u
.named_templates
->get_nt_byName(field_id
)->get_template();
1423 } else if (base_template
) {
1424 // take the field from the base template (recursively)
1425 return base_template
->get_template_refd_last(refch
)
1426 ->get_refd_field_template(field_id
, loc
, usedInIsbound
, refch
);
1428 if (!usedInIsbound
) {
1429 // this should not happen unless there is an error
1430 // (e.g. missing field)
1431 loc
.error("Reference to an unbound field `%s'",
1432 field_id
.get_dispname().c_str());
1437 loc
.error("Invalid field reference `%s': type `%s' "
1438 "does not have fields", field_id
.get_dispname().c_str(),
1439 t
->get_typename().c_str());
1444 Template
* Template::get_refd_array_template(Value
*array_index
,
1446 ReferenceChain
*refch
)
1448 switch (templatetype
) {
1453 case COMPLEMENTED_LIST
:
1454 case SUPERSET_MATCH
:
1456 // the above template types are valid matching mechanisms,
1457 // but they cannot be sub-referenced
1458 array_index
->error("Reference with index to an element of %s `%s'",
1459 get_templatetype_str(), get_fullname().c_str());
1464 Value
*v_index
= array_index
->get_value_refd_last(refch
);
1466 bool index_available
= false;
1467 if (!v_index
->is_unfoldable()) {
1468 if (v_index
->get_valuetype() == Value::V_INT
) {
1469 index
= v_index
->get_val_Int()->get_val();
1470 index_available
= true;
1472 array_index
->error("An integer value was expected as index");
1475 if (!my_governor
) FATAL_ERROR("Template::get_refd_array_template()");
1476 Type
*t
= my_governor
->get_type_refd_last();
1477 const char *typetype_str
="set";
1478 switch(t
->get_typetype()) {
1483 typetype_str
="record";
1486 if (index_available
) {
1488 array_index
->error("A non-negative integer value was expected "
1489 "instead of %s for indexing a template of `%s of' type `%s'",
1490 Int2string(index
).c_str(), typetype_str
,
1491 t
->get_typename().c_str());
1493 } else if (templatetype
!= TEMPLATE_LIST
) {
1494 // remain silent the error has been already reported
1497 size_t nof_elements
= get_nof_listitems();
1498 if (index
>= static_cast<Int
>(nof_elements
)) {
1499 array_index
->error("Index overflow in a template of `%s of' type "
1500 "`%s': the index is %s, but the template has only %lu elements",
1501 typetype_str
, t
->get_typename().c_str(),
1502 Int2string(index
).c_str(), (unsigned long) nof_elements
);
1507 // the index is not available or the error has been reported above
1512 if (index_available
) {
1513 ArrayDimension
*dim
= t
->get_dimension();
1514 dim
->chk_index(v_index
, Type::EXPECTED_DYNAMIC_VALUE
);
1515 if (templatetype
== TEMPLATE_LIST
&& !dim
->get_has_error()) {
1516 // perform the index transformation
1517 index
-= dim
->get_offset();
1518 // check for index underflow/overflow or too few elements in template
1519 if (index
< 0 || index
>= static_cast<Int
>(get_nof_listitems()))
1522 // remain silent, the error has been already reported
1526 // the index is not available or the error has been reported above
1531 array_index
->error("Invalid array element reference: type `%s' cannot "
1532 "be indexed", t
->get_typename().c_str());
1535 Template
*ret_val
= get_listitem_byIndex(index
);
1536 if (ret_val
->templatetype
== TEMPLATE_NOTUSED
) {
1537 if (base_template
) {
1538 // take the referred element from the base template
1539 return base_template
->get_template_refd_last(refch
)
1540 ->get_refd_array_template(v_index
, usedInIsbound
, refch
);
1542 if(ret_val
->get_templatetype() == TEMPLATE_NOTUSED
)
1543 error("Not used symbol is not allowed in this context");
1546 } else return ret_val
;
1549 bool Template::temps_contains_anyornone_symbol() const
1551 switch (templatetype
) {
1553 case SUPERSET_MATCH
:
1555 case PERMUTATION_MATCH
:
1558 FATAL_ERROR("Template::temps_contains_anyornone_symbol()");
1560 size_t nof_comps
= u
.templates
->get_nof_ts();
1561 for (size_t i
= 0; i
< nof_comps
; i
++) {
1562 Template
*t
= u
.templates
->get_t_byIndex(i
);
1563 switch (t
->templatetype
) {
1566 // 'all from' clauses not known at compile time are also considered
1569 case PERMUTATION_MATCH
:
1571 if (t
->temps_contains_anyornone_symbol()) return true;
1580 size_t Template::get_nof_comps_not_anyornone() const
1582 switch (templatetype
) {
1584 case SUPERSET_MATCH
:
1586 case PERMUTATION_MATCH
:
1589 FATAL_ERROR("Template::get_nof_comps_not_anyornone()");
1592 size_t nof_comps
= u
.templates
->get_nof_ts();
1593 for (size_t i
= 0; i
< nof_comps
; i
++) {
1594 Template
*t
= u
.templates
->get_t_byIndex(i
);
1595 switch (t
->templatetype
) {
1600 case PERMUTATION_MATCH
:
1602 ret_val
+= t
->get_nof_comps_not_anyornone();
1605 // other types are counted as 1
1613 bool Template::pattern_contains_anyornone_symbol() const
1615 switch (templatetype
) {
1619 return u
.pattern
->find('*') < u
.pattern
->size();
1624 FATAL_ERROR("Template::pattern_contains_anyornone_symbol()");
1629 size_t Template::get_min_length_of_pattern() const
1632 switch (templatetype
) {
1634 case HSTR_PATTERN
: {
1635 size_t pattern_len
= u
.pattern
->size();
1636 const char *pattern_ptr
= u
.pattern
->c_str();
1637 for (size_t i
= 0; i
< pattern_len
; i
++)
1638 if (pattern_ptr
[i
] != '*') ret_val
++;
1640 case OSTR_PATTERN
: {
1641 size_t pattern_len
= u
.pattern
->size();
1642 const char *pattern_ptr
= u
.pattern
->c_str();
1643 for (size_t i
= 0; i
< pattern_len
; i
++) {
1644 switch (pattern_ptr
[i
]) {
1653 // count as 1 and skip over the next hex digit
1663 FATAL_ERROR("Template::get_min_length_of_pattern()");
1668 bool Template::is_Value() const
1670 if (length_restriction
|| is_ifpresent
) return false;
1671 switch (templatetype
) {
1672 case TEMPLATE_ERROR
:
1673 case TEMPLATE_NOTUSED
:
1676 case SPECIFIC_VALUE
:
1677 if(u
.specific_value
->get_valuetype() == Value::V_INVOKE
) {
1678 Type
*t
= u
.specific_value
1679 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE
);
1680 if(t
&& t
->get_type_refd_last()->get_typetype() == Type::T_FUNCTION
&&
1681 t
->get_type_refd_last()->get_returns_template()) return false;
1684 case TEMPLATE_LIST
: {
1685 Templates
*ts
= u
.templates
;
1686 for (size_t i
= 0; i
< ts
->get_nof_ts(); i
++)
1687 if (!ts
->get_t_byIndex(i
)->is_Value()) return false;
1690 case NAMED_TEMPLATE_LIST
: {
1691 NamedTemplates
*ts
= u
.named_templates
;
1692 for (size_t i
= 0;i
< ts
->get_nof_nts(); i
++)
1693 if (!ts
->get_nt_byIndex(i
)->get_template()->is_Value()) return false;
1696 case INDEXED_TEMPLATE_LIST
: {
1697 IndexedTemplates
*ts
= u
.indexed_templates
;
1698 for (size_t i
= 0; i
< ts
->get_nof_its(); i
++)
1699 if (!ts
->get_it_byIndex(i
)->get_template()->is_Value()) return false;
1702 case TEMPLATE_REFD
: {
1703 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1704 switch (ass
->get_asstype()) {
1705 case Common::Assignment::A_EXT_CONST
:
1706 case Common::Assignment::A_PAR_VAL
:
1707 case Common::Assignment::A_PAR_VAL_IN
:
1708 case Common::Assignment::A_PAR_VAL_OUT
:
1709 case Common::Assignment::A_PAR_VAL_INOUT
:
1710 case Common::Assignment::A_VAR
:
1721 Value
*Template::get_Value()
1724 switch(templatetype
) {
1725 case TEMPLATE_ERROR
:
1726 ret_val
= new Value(Value::V_ERROR
);
1728 case TEMPLATE_NOTUSED
:
1729 ret_val
= new Value(Value::V_NOTUSED
);
1732 ret_val
= new Value(Value::V_OMIT
);
1734 case SPECIFIC_VALUE
:
1735 ret_val
= u
.specific_value
;
1736 u
.specific_value
= 0;
1737 set_templatetype(TEMPLATE_ERROR
);
1739 case TEMPLATE_LIST
: {
1740 Values
*vs
= new Values
;
1741 size_t nof_ts
= u
.templates
->get_nof_ts();
1743 for (size_t i
= 0; i
< nof_ts
; i
++) {
1744 Value
* v
= u
.templates
->get_t_byIndex(i
)->get_Value();
1745 if (!gov
) gov
= v
->get_my_governor();
1748 ret_val
= new Value(Value::V_SEQOF
, vs
);
1749 if (gov
) gov
= gov
->get_parent_type();
1750 if (gov
) ret_val
->set_my_governor(gov
);
1752 case NAMED_TEMPLATE_LIST
: {
1753 NamedValues
*nvs
= new NamedValues
;
1754 size_t nof_nts
= u
.named_templates
->get_nof_nts();
1756 for (size_t i
= 0; i
< nof_nts
; i
++) {
1757 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
1758 Value
* v
= nt
->get_template()->get_Value();
1759 if (!gov
) gov
= v
->get_my_governor();
1760 NamedValue
*nv
= new NamedValue(nt
->get_name().clone(), v
);
1761 nv
->set_location(*nt
);
1764 ret_val
= new Value(Value::V_SEQ
, nvs
);
1765 if (gov
) gov
= gov
->get_parent_type();
1766 if (gov
) ret_val
->set_my_governor(gov
);
1768 case INDEXED_TEMPLATE_LIST
: {
1769 Values
*ivs
= new Values(true);
1770 size_t nof_its
= u
.indexed_templates
->get_nof_its();
1772 for (size_t i
= 0; i
< nof_its
; i
++) {
1773 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
1774 Value
* v
= it
->get_template()->get_Value();
1775 if (!gov
) gov
= v
->get_my_governor();
1776 IndexedValue
*iv
= new IndexedValue(it
->get_index().clone(), v
);
1777 iv
->set_location(*it
);
1780 ret_val
= new Value(Value::V_SEQOF
, ivs
);
1781 if (gov
) gov
= gov
->get_parent_type();
1782 if (gov
) ret_val
->set_my_governor(gov
);
1785 FATAL_ERROR("Template::get_Value()");
1789 ret_val
->set_location(*this);
1790 ret_val
->set_my_scope(get_my_scope());
1791 ret_val
->set_fullname(get_fullname());
1795 bool Template::is_Ref() const
1797 if (length_restriction
|| is_ifpresent
|| templatetype
!= SPECIFIC_VALUE
)
1799 Value
*v
= u
.specific_value
;
1800 switch (v
->get_valuetype()) {
1801 case Value::V_UNDEF_LOWERID
:
1804 if (dynamic_cast<Ref_base
*>(v
->get_reference())) return true;
1811 Ref_base
*Template::get_Ref()
1813 if (templatetype
!= SPECIFIC_VALUE
)
1814 FATAL_ERROR("Template::get_Ref()");
1815 return u
.specific_value
->steal_ttcn_ref_base();
1818 void Template::chk_recursions(ReferenceChain
& refch
)
1820 if (recurs_checked
) return;
1823 if (t
->templatetype
== SPECIFIC_VALUE
) break;
1824 else if (!refch
.add(t
->get_fullname())) goto end
;
1825 else if (t
->templatetype
!= TEMPLATE_REFD
) break;
1826 t
->u
.ref
.ref
->get_refd_assignment(true); // make sure the parameter list is checked
1827 ActualParList
*parlist
= t
->u
.ref
.ref
->get_parlist();
1828 if (parlist
) parlist
->chk_recursions(refch
);
1829 Template
*t_refd
= t
->get_template_refd(&refch
);
1830 if (t_refd
== t
) break;
1833 t
->set_lowerid_to_ref();
1834 switch (t
->templatetype
) {
1835 case SPECIFIC_VALUE
:
1836 t
->u
.specific_value
->chk_recursions(refch
);
1840 case COMPLEMENTED_LIST
:
1841 case SUPERSET_MATCH
:
1843 case PERMUTATION_MATCH
:
1844 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++) {
1846 t
->u
.templates
->get_t_byIndex(i
)->chk_recursions(refch
);
1850 case NAMED_TEMPLATE_LIST
:
1851 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++) {
1853 t
->u
.named_templates
->get_nt_byIndex(i
)
1854 ->get_template()->chk_recursions(refch
);
1858 case INDEXED_TEMPLATE_LIST
:
1859 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++) {
1861 t
->u
.indexed_templates
->get_it_byIndex(i
)
1862 ->get_template()->chk_recursions(refch
);
1868 t
->u
.pstring
->chk_recursions(refch
);
1874 recurs_checked
= true;
1877 void Template::chk_specific_value(bool allow_omit
)
1879 Template
*t
= get_template_refd_last();
1880 if (!allow_omit
&& t
->templatetype
==OMIT_VALUE
) {
1881 t
->error("A specific value was expected instead of omit");
1883 chk_specific_value_generic();
1886 void Template::chk_specific_value_generic()
1888 if (specific_value_checked
) return;
1889 Template
*t
= get_template_refd_last();
1890 if (t
->specific_value_checked
) return;
1891 switch (t
->templatetype
) {
1892 case TEMPLATE_ERROR
:
1893 case TEMPLATE_NOTUSED
:
1894 case TEMPLATE_REFD
: // unfoldable reference
1896 case SPECIFIC_VALUE
:
1897 if(u
.specific_value
->get_valuetype() == Value::V_INVOKE
) {
1898 Type
*t_type
= u
.specific_value
1899 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE
);
1900 if(t_type
&& t_type
->get_type_refd_last()->get_returns_template()) {
1901 set_templatetype(TEMPLATE_INVOKE
);
1906 case TEMPLATE_INVOKE
:
1910 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++)
1911 t
->u
.templates
->get_t_byIndex(i
)->chk_specific_value_generic();
1913 case NAMED_TEMPLATE_LIST
:
1914 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++)
1915 t
->u
.named_templates
->get_nt_byIndex(i
)
1916 ->get_template()->chk_specific_value_generic();
1918 case INDEXED_TEMPLATE_LIST
:
1919 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++)
1920 t
->u
.indexed_templates
->get_it_byIndex(i
)
1921 ->get_template()->chk_specific_value_generic();
1926 t
->error("A specific value was expected instead of %s",
1927 t
->get_templatetype_str());
1930 t
->specific_value_checked
= true;
1931 specific_value_checked
= true;
1934 void Template::chk_invoke()
1936 if(templatetype
!= TEMPLATE_INVOKE
) FATAL_ERROR("Template::chk_invoke()");
1937 if(!u
.invoke
.t_list
) return; //already checked
1938 Error_Context
cntxt(this, "In `apply()' operation");
1939 Type
*t
= u
.invoke
.v
->get_expr_governor_last();
1941 if (t
->get_typetype() != Type::T_FUNCTION
) {
1942 u
.invoke
.v
->error("A value of type function was expected in the "
1943 "argument instead of `%s'", t
->get_typename().c_str());
1944 set_templatetype(TEMPLATE_ERROR
);
1948 if (u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
1949 u
.invoke
.v
->error("A value of type function was expected in the "
1951 set_templatetype(TEMPLATE_ERROR
);
1954 my_scope
->chk_runs_on_clause(t
, *this, "call");
1955 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
1956 Ttcn::ActualParList
*parlist
= new Ttcn::ActualParList
;
1957 bool is_erroneous
= fp_list
->fold_named_and_chk(u
.invoke
.t_list
,parlist
);
1958 delete u
.invoke
.t_list
;
1959 u
.invoke
.t_list
= 0;
1962 u
.invoke
.ap_list
= 0;
1964 parlist
->set_fullname(get_fullname());
1965 parlist
->set_my_scope(get_my_scope());
1966 u
.invoke
.ap_list
= parlist
;
1970 Templates
*Template::harbinger(Template
*t
, bool from_permutation
, bool killer
)
1972 Templates
*new_templates
= new Templates
;
1973 switch (t
->u
.all_from
->templatetype
) {
1974 case SPECIFIC_VALUE
: {
1975 Value
*innerv
= t
->u
.all_from
->get_specific_value();
1976 //if (v->get_valuetype() == Value::V_UNDEF_LOWERID)
1977 innerv
->set_lowerid_to_ref();
1978 // should be a ref now
1979 bool can_flatten
= true;
1980 Common::Reference
*ref
= innerv
->get_reference();
1981 if (dynamic_cast<Ttcn::Ref_pard
*>(ref
)) {
1982 // Cannot flatten at compile time if the template has parameters.
1983 can_flatten
= false;
1986 // check for subreferences in the 'all from' target
1987 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
1988 if (NULL
!= subrefs
) {
1989 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
1990 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
1991 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
1992 // set any array indexes from undefined lowerID to reference
1993 subref
->get_val()->set_lowerid_to_ref();
1998 Common::Assignment
*ass
= ref
->get_refd_assignment();
1999 if (ass
== NULL
) { // perhaps erroneous
2003 Common::Assignment::asstype_t asst
= ass
->get_asstype();
2005 case Common::Assignment::A_TEMPLATE
: {
2006 Template
*tpl
= ass
->get_Template();
2007 // tpl is the template whose name appears after the "all from"
2008 Common::Type
*type
= ass
->get_Type()->get_type_refd_last();
2009 if (NULL
!= subrefs
) {
2010 // walk through the subreferences to determine the type and value of the 'all from' target
2011 // Note: the templates referenced by the array indexes and field names
2012 // have not been checked yet
2013 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
2014 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
2015 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
2016 // check if the type can be indexed
2017 Common::Type::typetype_t tt
= type
->get_typetype();
2018 if (Common::Type::T_SEQOF
!= tt
&& Common::Type::T_SETOF
!= tt
&&
2019 Common::Type::T_ARRAY
!= tt
) {
2020 subref
->error("Cannot apply an array index to type '%s'",
2021 type
->get_typename().c_str());
2022 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2026 if (can_flatten
&& !subref
->get_val()->is_unfoldable()) {
2027 switch(tpl
->get_templatetype()) {
2030 Int index
= subref
->get_val()->get_val_Int()->get_val();
2031 // check for index overflow
2032 if (index
>= static_cast<Int
>(tpl
->get_nof_comps())) {
2033 subref
->error("Index overflow in a template %s type `%s':"
2034 " the index is %s, but the template has only %lu elements",
2035 Common::Type::T_ARRAY
== tt
? "array of" :
2036 (Common::Type::T_SEQOF
== tt
? "of 'record of'" : "of 'set of'"),
2037 type
->get_typename().c_str(), Int2string(index
).c_str(),
2038 (unsigned long)tpl
->get_nof_comps());
2039 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2043 tpl
= tpl
->get_temp_byIndex(index
);
2044 // check if the element is initialized
2045 if (TEMPLATE_NOTUSED
== tpl
->get_templatetype()) {
2046 subref
->error("An uninitialized list element can not be used as target of 'all from'");
2047 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2052 case INDEXED_TEMPLATE_LIST
:
2053 can_flatten
= false; // currently not supported
2056 subref
->error("Expected a specific value of type '%s' instead of %s",
2057 type
->get_typename().c_str(), tpl
->get_templatetype_str());
2058 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2064 // one of the array indexes is a reference => cannot flatten
2065 can_flatten
= false;
2067 type
= type
->get_ofType()->get_type_refd_last();
2070 // check if the type can have fields
2071 Common::Type::typetype_t tt
= type
->get_typetype();
2072 if (Common::Type::T_SEQ_T
!= tt
&& Common::Type::T_SEQ_A
!= tt
&&
2073 Common::Type::T_SET_T
!= tt
&& Common::Type::T_SET_A
!= tt
&&
2074 Common::Type::T_CHOICE_T
!= tt
&& Common::Type::T_CHOICE_A
!= tt
) {
2075 subref
->error("Cannot apply a field name to type '%s'",
2076 type
->get_typename().c_str());
2080 // check if the field name is valid
2081 if (!type
->has_comp_withName(*subref
->get_id())) {
2082 subref
->error("Type '%s' does not have a field with name '%s'",
2083 type
->get_typename().c_str(), subref
->get_id()->get_dispname().c_str());
2088 switch(tpl
->get_templatetype()) {
2089 case NAMED_TEMPLATE_LIST
: {
2090 // check if there is any data in the template for this field
2091 // (no data means it's uninitialized)
2092 if (!tpl
->u
.named_templates
->has_nt_withName(*subref
->get_id())) {
2093 subref
->error("An uninitialized field can not be used as target of 'all from'");
2094 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2098 tpl
= tpl
->u
.named_templates
->get_nt_byName(*subref
->get_id())->get_template();
2099 // check if the field is initialized and present (not omitted)
2100 if (OMIT_VALUE
== tpl
->get_templatetype() || TEMPLATE_NOTUSED
== tpl
->get_templatetype()) {
2101 subref
->error("An %s field can not be used as target of 'all from'",
2102 OMIT_VALUE
== tpl
->get_templatetype() ? "omitted" : "uninitialized");
2103 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2109 subref
->error("Expected a specific value of type '%s' instead of %s",
2110 type
->get_typename().c_str(), tpl
->get_templatetype_str());
2111 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2116 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2120 if (NULL
!= tpl
) { // tpl is set to null if an error occurs
2122 Template::templatetype_t tpltt
= tpl
->get_templatetype();
2124 case INDEXED_TEMPLATE_LIST
: // currently not supported
2125 case TEMPLATE_REFD
: {
2126 delete new_templates
;
2134 size_t nvl
= tpl
->get_nof_comps();
2135 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2136 Template
*orig
= tpl
->get_temp_byIndex(ti
);
2137 switch (orig
->templatetype
) {
2138 case SPECIFIC_VALUE
: {
2139 Value
*val
= orig
->get_specific_value();
2140 if (val
->get_valuetype() == Value::V_REFD
) {
2141 if (dynamic_cast<Ttcn::Ref_pard
*>(val
->get_reference())) {
2142 // Cannot flatten at compile time if one of the values or templates has parameters.
2143 can_flatten
= false;
2148 if (from_permutation
) {
2149 break; // AnyElementOrNone allowed in "all from" now
2152 case PERMUTATION_MATCH
:
2153 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2154 t
->set_templatetype(TEMPLATE_ERROR
);
2160 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2161 Template
*orig
= tpl
->get_temp_byIndex(ti
);
2162 Template
*copy
= orig
->clone();
2163 copy
->set_my_scope(orig
->get_my_scope());
2164 new_templates
->add_t(copy
);
2168 // Cannot flatten at compile time
2169 delete new_templates
;
2175 case NAMED_TEMPLATE_LIST
: {
2176 size_t nvl
= tpl
->get_nof_comps();
2177 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2178 NamedTemplate
*orig
= tpl
->get_namedtemp_byIndex(ti
);
2179 switch (orig
->get_template()->get_templatetype()) {
2182 case PERMUTATION_MATCH
:
2183 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2184 t
->set_templatetype(TEMPLATE_ERROR
);
2189 delete new_templates
;
2196 tpl
->error("Matching mechanism can not be used as target of 'all from'");
2199 tpl
->error("A template of type '%s' can not be used as target of 'all from'",
2200 type
->get_typename().c_str());
2204 else { // cannot flatten
2205 switch (type
->get_typetype()) {
2206 case Common::Type::T_SEQOF
: case Common::Type::T_SETOF
:
2207 case Common::Type::T_ARRAY
:
2208 delete new_templates
;
2213 type
->error("A template of type `%s' can not be used as target of 'all from'",
2214 type
->get_typename().c_str());
2216 } // switch(typetype)
2220 if (killer
) delete t
;
2224 case Common::Assignment::A_CONST
: { // all from a constant definition
2225 Common::Value
*val
= ass
->get_Value();
2226 Common::Type
*type
= ass
->get_Type()->get_type_refd_last();
2227 if (NULL
!= subrefs
) {
2228 // walk through the subreferences to determine the type and value of the 'all from' target
2229 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
2230 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
2231 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
2232 // check if the type can be indexed
2233 Common::Type::typetype_t tt
= type
->get_typetype();
2234 if (Common::Type::T_SEQOF
!= tt
&& Common::Type::T_SETOF
!= tt
&&
2235 Common::Type::T_ARRAY
!= tt
) {
2236 subref
->error("Cannot apply an array index to type '%s'",
2237 type
->get_typename().c_str());
2241 if (can_flatten
&& !subref
->get_val()->is_unfoldable()) {
2242 Int index
= subref
->get_val()->get_val_Int()->get_val();
2243 // check for index overflow
2244 if (index
>= static_cast<Int
>(val
->get_nof_comps())) {
2245 subref
->error("Index overflow in a value %s type `%s':"
2246 " the index is %s, but the template has only %lu elements",
2247 Common::Type::T_ARRAY
== tt
? "array of" :
2248 (Common::Type::T_SEQOF
== tt
? "of 'record of'" : "of 'set of'"),
2249 type
->get_typename().c_str(), Int2string(index
).c_str(),
2250 (unsigned long)val
->get_nof_comps());
2254 val
= val
->get_comp_byIndex(index
);
2255 // check if the element is initialized
2256 if (Common::Value::V_NOTUSED
== val
->get_valuetype()) {
2257 subref
->error("An unbound list element can not be used as target of 'all from'");
2263 // one of the array indexes is a reference => cannot flatten
2264 can_flatten
= false;
2266 type
= type
->get_ofType()->get_type_refd_last();
2269 // check if the type can have fields
2270 Common::Type::typetype_t tt
= type
->get_typetype();
2271 if (Common::Type::T_SEQ_T
!= tt
&& Common::Type::T_SEQ_A
!= tt
&&
2272 Common::Type::T_SET_T
!= tt
&& Common::Type::T_SET_A
!= tt
&&
2273 Common::Type::T_CHOICE_T
!= tt
&& Common::Type::T_CHOICE_A
!= tt
) {
2274 subref
->error("Cannot apply a field name to type '%s'",
2275 type
->get_typename().c_str());
2279 // check if the field name is valid
2280 if (!type
->has_comp_withName(*subref
->get_id())) {
2281 subref
->error("Type '%s' does not have a field with name '%s'",
2282 type
->get_typename().c_str(), subref
->get_id()->get_dispname().c_str());
2286 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2288 // check if the value has any data for this field (no data = unbound)
2289 if (!val
->has_comp_withName(*subref
->get_id())) {
2290 subref
->error("An unbound field can not be used as target of 'all from'");
2294 val
= val
->get_comp_value_byName(*subref
->get_id());
2295 // check if the field is bound and present (not omitted)
2296 if (Common::Value::V_OMIT
== val
->get_valuetype() ||
2297 Common::Value::V_NOTUSED
== val
->get_valuetype()) {
2298 subref
->error("An %s field can not be used as target of 'all from'",
2299 Common::Value::V_OMIT
== val
->get_valuetype() ? "omitted" : "unbound");
2307 if (NULL
!= val
) { // val is set to null if an error occurs
2308 switch (type
->get_typetype()) {
2309 case Common::Type::T_SEQOF
: case Common::Type::T_SETOF
:
2310 case Common::Type::T_ARRAY
: {
2312 const size_t ncomp
= val
->get_nof_comps();
2313 for (size_t i
= 0; i
< ncomp
; ++i
) {
2314 Value
*v
= val
->get_comp_byIndex(i
);
2315 Template
*newt
= new Template(v
->clone());
2316 new_templates
->add_t(newt
);
2320 delete new_templates
;
2327 type
->error("A constant of type `%s' can not be used as target of 'all from'",
2328 type
->get_typename().c_str());
2330 } // switch(typetype)
2332 if (killer
) delete t
;
2335 case Common::Assignment::A_MODULEPAR_TEMP
:
2336 case Common::Assignment::A_VAR_TEMPLATE
:
2337 case Common::Assignment::A_FUNCTION_RTEMP
:
2338 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2339 case Common::Assignment::A_PAR_TEMPL_IN
:
2340 case Common::Assignment::A_PAR_TEMPL_INOUT
:
2341 case Common::Assignment::A_PAR_TEMPL_OUT
:
2342 //TODO: flatten if the actual par is const template
2343 case Common::Assignment::A_MODULEPAR
: // all from a module parameter
2344 case Common::Assignment::A_VAR
: // all from a variable
2345 case Common::Assignment::A_PAR_VAL_IN
:
2346 case Common::Assignment::A_PAR_VAL_INOUT
:
2347 case Common::Assignment::A_PAR_VAL_OUT
:
2348 case Common::Assignment::A_FUNCTION_RVAL
:
2349 case Common::Assignment::A_EXT_FUNCTION_RVAL
: {
2350 Common::Type
*type
= ass
->get_Type()->get_type_refd_last();
2351 if (NULL
!= subrefs
) {
2352 // walk through the subreferences to determine the type of the 'all from' target
2353 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
2354 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
2355 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
2356 // check if the type can be indexed
2357 Common::Type::typetype_t tt
= type
->get_typetype();
2358 if (Common::Type::T_SEQOF
!= tt
&& Common::Type::T_SETOF
!= tt
&&
2359 Common::Type::T_ARRAY
!= tt
) {
2360 subref
->error("Cannot apply an array index to type '%s'",
2361 type
->get_typename().c_str());
2365 type
= type
->get_ofType()->get_type_refd_last();
2368 // check if the type can have fields
2369 Common::Type::typetype_t tt
= type
->get_typetype();
2370 if (Common::Type::T_SEQ_T
!= tt
&& Common::Type::T_SEQ_A
!= tt
&&
2371 Common::Type::T_SET_T
!= tt
&& Common::Type::T_SET_A
!= tt
&&
2372 Common::Type::T_CHOICE_T
!= tt
&& Common::Type::T_CHOICE_A
!= tt
) {
2373 subref
->error("Cannot apply a field name to type '%s'",
2374 type
->get_typename().c_str());
2378 // check if the field name is valid
2379 if (!type
->has_comp_withName(*subref
->get_id())) {
2380 subref
->error("Type '%s' does not have a field with name '%s'",
2381 type
->get_typename().c_str(), subref
->get_id()->get_dispname().c_str());
2385 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2390 switch (type
->get_typetype()) {
2391 case Common::Type::T_SEQOF
: case Common::Type::T_SETOF
:
2392 case Common::Type::T_ARRAY
:
2393 delete new_templates
; // cannot flatten at compile time
2397 // not an array type => error
2398 const char* ass_name
= ass
->get_assname();
2401 case Common::Assignment::A_MODULEPAR_TEMP
:
2402 case Common::Assignment::A_VAR_TEMPLATE
:
2403 case Common::Assignment::A_MODULEPAR
:
2404 case Common::Assignment::A_VAR
:
2405 case Common::Assignment::A_PAR_TEMPL_IN
:
2406 case Common::Assignment::A_PAR_VAL_IN
:
2410 case Common::Assignment::A_PAR_TEMPL_INOUT
:
2411 case Common::Assignment::A_PAR_TEMPL_OUT
:
2412 case Common::Assignment::A_PAR_VAL_INOUT
:
2413 case Common::Assignment::A_PAR_VAL_OUT
:
2417 // the assignment name string for functions is no good here
2418 case Common::Assignment::A_FUNCTION_RTEMP
:
2419 descr
= "A function returning a template";
2421 case Common::Assignment::A_FUNCTION_RVAL
:
2422 descr
= "A function returning a value";
2424 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2425 descr
= "An external function returning a template";
2427 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2428 descr
= "An external function returning a value";
2433 type
->error("%s of type `%s' can not be used as target of 'all from'",
2434 descr
.c_str(), type
->get_typename().c_str());
2437 } // switch(typetype)
2441 FATAL_ERROR("harbinger asst %d", asst
);
2447 FATAL_ERROR("unexpected all from inside all from");
2450 FATAL_ERROR("tt %d", t
->u
.all_from
->templatetype
);
2453 return new_templates
;
2456 bool Template::flatten(bool from_permutation
)
2458 switch (templatetype
) {
2461 case COMPLEMENTED_LIST
:
2462 case SUPERSET_MATCH
:
2464 case PERMUTATION_MATCH
: {
2465 size_t num_t
= u
.templates
->get_nof_ts(); // one of these is the "all from"
2466 Templates
*new_templates
= new Templates
;
2467 for (size_t i
= 0; i
< num_t
; ++i
) {
2468 Template
*& t
= u
.templates
->get_t_byIndex(i
);
2469 // the element in the (,,,)
2470 switch (t
->templatetype
) {
2471 case VALUE_LIST_ALL_FROM
: {
2472 // the all from from something like subset(1, (all from...), 99)
2473 // value list: one out of many possible values^^^^^^^^^^^^^
2474 Location
tloc(*t
); // save the location info
2475 string
tname(t
->get_fullname());
2476 Templates
*ha
= harbinger(t
, from_permutation
, true);
2478 // Don't touch t from now on, it might have been deleted!
2479 Template
*qq
= new Template(VALUE_LIST
, ha
);
2480 qq
->set_location(tloc
);
2481 qq
->set_fullname(tname
+ ".all_from");
2482 new_templates
->add_t(qq
);
2485 new_templates
->add_t(t
); // transfer it unchanged
2490 case ALL_FROM
: { // subset(1, all from ..., 99)
2491 // some number of elements--^^^^^^^^^^^^
2492 if (t
->checked
) FATAL_ERROR("too late");
2493 Templates
*af
= harbinger(t
, from_permutation
, true);
2495 for (size_t a
= 0, num
= af
->get_nof_ts(); a
< num
; ++a
) {
2496 Template
*& t2
= af
->get_t_byIndex(a
);
2497 new_templates
->add_t(t2
);
2498 t2
= 0; // take it away from its current owner
2503 new_templates
->add_t(t
); // transfer it unchanged
2506 break; } // case ALL_FROM
2508 case PERMUTATION_MATCH
: {
2509 // permut inside a value list: { 1, permut(), 2 }
2510 flattened
&= t
->flatten(true);
2511 new_templates
->add_t(t
);
2515 // case COMPLEMENTED_LIST:
2516 // case SUPERSET_MATCH:
2517 // case SUBSET_MATCH:
2519 flattened
&=t
->flatten(false);
2520 new_templates
->add_t(t
);
2523 new_templates
->add_t(t
);
2526 t
= 0; // take it away from the original
2529 u
.templates
= new_templates
;
2530 //printf("!!! flattened from %lu to %lu at line %d\n",
2531 // (unsigned long)num_t, (unsigned long)new_templates->get_nof_ts(),
2532 // get_first_line());
2536 case VALUE_LIST_ALL_FROM
: {
2537 Templates
*new_templates
= harbinger(this, from_permutation
, false);
2538 if (new_templates
) {
2540 // now we can change the type
2541 templatetype
= VALUE_LIST
;
2542 u
.templates
= new_templates
;
2546 case TEMPLATE_ERROR
: case TEMPLATE_NOTUSED
:
2547 case OMIT_VALUE
: case ANY_VALUE
: case ANY_OR_OMIT
:
2548 case SPECIFIC_VALUE
:
2549 case TEMPLATE_REFD
: case TEMPLATE_INVOKE
:
2550 case NAMED_TEMPLATE_LIST
: case INDEXED_TEMPLATE_LIST
:
2553 case BSTR_PATTERN
: case HSTR_PATTERN
: case OSTR_PATTERN
:
2554 case CSTR_PATTERN
: case USTR_PATTERN
:
2558 set_fullname(get_fullname()); // recompute fullname (esp. for components)
2559 set_my_scope(get_my_scope());
2564 const char* Template::get_restriction_name(template_restriction_t tr
)
2576 FATAL_ERROR("Template::get_restriction_name()");
2581 template_restriction_t
Template::get_sub_restriction(
2582 template_restriction_t tr
, Ref_base
* ref
)
2584 if (!ref
) FATAL_ERROR("Template::get_sub_restriction()");
2585 if (!ref
->get_subrefs()) return tr
;
2586 bool is_optional
= true; // the referenced field is on an optional path
2587 Common::Assignment
* ass
= ref
->get_refd_assignment();
2589 Type
* t
= ass
->get_Type();
2591 ReferenceChain
refch(ref
, "While checking template restriction");
2592 t
= t
->get_field_type(ref
->get_subrefs(), Type::EXPECTED_TEMPLATE
,
2594 if (t
) is_optional
= false;
2603 return is_optional
? TR_OMIT
: TR_VALUE
;
2605 return is_optional
? TR_NONE
: TR_PRESENT
;
2607 FATAL_ERROR("Template::get_sub_restriction()");
2612 bool Template::is_less_restrictive(template_restriction_t needed_tr
,
2613 template_restriction_t refd_tr
)
2615 switch (needed_tr
) {
2619 return refd_tr
!=TR_VALUE
;
2621 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_OMIT
;
2623 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_PRESENT
;
2625 FATAL_ERROR("Template::is_less_restrictive()");
2630 char* Template::generate_restriction_check_code(char* str
, const char* name
,
2631 template_restriction_t tr
)
2633 const char* tr_name
;
2638 tr_name
= "TR_OMIT";
2641 tr_name
= "TR_VALUE";
2644 tr_name
= "TR_PRESENT";
2647 FATAL_ERROR("Template::generate_restriction_check_code()");
2649 return mputprintf(str
, "%s.check_restriction(%s%s);\n", name
, tr_name
,
2650 (omit_in_value_list
? ", NULL, TRUE" : ""));
2653 // embedded templates -> check needed only for case of TR_OMIT
2654 bool Template::chk_restriction_named_list(const char* definition_name
,
2655 map
<string
, void>& checked_map
, size_t needed_checked_cnt
,
2656 const Location
* usage_loc
)
2658 bool needs_runtime_check
= false;
2659 if (checked_map
.size()>=needed_checked_cnt
) return needs_runtime_check
;
2660 switch (templatetype
) {
2661 case NAMED_TEMPLATE_LIST
:
2662 for (size_t i
= 0;i
< u
.named_templates
->get_nof_nts(); i
++) {
2663 Template
* tmpl
= u
.named_templates
->get_nt_byIndex(i
)->get_template();
2664 const string
& name
=
2665 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name();
2666 if (!checked_map
.has_key(name
)) {
2667 bool nrc
= tmpl
->chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2668 needs_runtime_check
= needs_runtime_check
|| nrc
;
2669 checked_map
.add(name
, 0);
2672 if (base_template
) {
2673 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2674 checked_map
, needed_checked_cnt
, usage_loc
);
2675 needs_runtime_check
= needs_runtime_check
|| nrc
;
2680 error("Restriction on %s does not allow usage of %s",
2681 definition_name
, get_templatetype_str());
2684 // others will be converted to specific value
2687 return needs_runtime_check
;
2690 bool Template::chk_restriction_refd(const char* definition_name
,
2691 template_restriction_t template_restriction
, const Location
* usage_loc
)
2693 bool needs_runtime_check
= false;
2694 Common::Assignment
* ass
= u
.ref
.ref
->get_refd_assignment();
2695 if (!ass
) FATAL_ERROR("Template::chk_restriction_refd()");
2696 // get the restriction on the referenced template
2697 template_restriction_t refd_tr
= TR_NONE
;
2698 bool is_var_template
= false;
2699 switch (ass
->get_asstype()) {
2700 case Common::Assignment::A_TEMPLATE
: {
2701 Template
* t_last
= get_template_refd_last();
2703 bool nrc
= t_last
->chk_restriction(definition_name
,
2704 template_restriction
, usage_loc
);
2705 needs_runtime_check
= needs_runtime_check
|| nrc
;
2708 case Common::Assignment::A_MODULEPAR_TEMP
:
2709 is_var_template
= true;
2710 refd_tr
= TR_NONE
; // can't place restriction on this thing
2712 case Common::Assignment::A_VAR_TEMPLATE
: {
2713 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(ass
);
2714 if (!dvt
) FATAL_ERROR("Template::chk_restriction_refd()");
2715 is_var_template
= true;
2716 refd_tr
= dvt
->get_template_restriction();
2718 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2719 // we do not trust external functions because there is no generated
2720 // restriction check on their return value
2721 if (template_restriction
!=TR_NONE
) needs_runtime_check
= true;
2723 case Common::Assignment::A_FUNCTION_RTEMP
: {
2724 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(ass
);
2725 if (!dfb
) FATAL_ERROR("Template::chk_restriction_refd()");
2726 is_var_template
= true;
2727 refd_tr
= dfb
->get_template_restriction();
2729 case Common::Assignment::A_PAR_TEMPL_IN
:
2730 case Common::Assignment::A_PAR_TEMPL_OUT
:
2731 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
2732 FormalPar
* fp
= dynamic_cast<FormalPar
*>(ass
);
2733 if (!fp
) FATAL_ERROR("Template::chk_restriction_refd()");
2734 is_var_template
= true;
2735 refd_tr
= fp
->get_template_restriction();
2740 if (is_var_template
) {
2741 // check the restriction
2742 refd_tr
= get_sub_restriction(refd_tr
, u
.ref
.ref
);
2743 // if restriction not satisfied issue warning
2744 if (is_less_restrictive(template_restriction
, refd_tr
)) {
2745 needs_runtime_check
= true;
2746 warning("Inadequate restriction on the referenced %s `%s', this may "
2747 "cause a dynamic test case error at runtime", ass
->get_assname(),
2748 u
.ref
.ref
->get_dispname().c_str());
2749 ass
->note("Referenced %s is here", ass
->get_assname());
2752 return needs_runtime_check
;
2755 bool Template::chk_restriction(const char* definition_name
,
2756 template_restriction_t template_restriction
,
2757 const Location
* usage_loc
)
2759 bool needs_runtime_check
= false;
2760 bool erroneous
= false;
2761 switch (template_restriction
) {
2766 if (length_restriction
) {
2767 usage_loc
->error("Restriction on %s does not allow usage of length "
2768 "restriction", definition_name
);
2772 usage_loc
->error("Restriction on %s does not allow usage of `ifpresent'",
2776 switch(templatetype
) {
2777 case TEMPLATE_ERROR
:
2779 case TEMPLATE_NOTUSED
:
2780 if (base_template
) {
2781 bool nrc
= base_template
->chk_restriction(definition_name
,
2782 template_restriction
, usage_loc
);
2783 needs_runtime_check
= needs_runtime_check
|| nrc
;
2785 else needs_runtime_check
= true;
2787 case SPECIFIC_VALUE
:
2788 case TEMPLATE_INVOKE
:
2790 case TEMPLATE_REFD
: {
2791 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
,
2793 needs_runtime_check
= needs_runtime_check
|| nrc
;
2796 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2797 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2798 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2799 needs_runtime_check
= needs_runtime_check
|| nrc
;
2802 case NAMED_TEMPLATE_LIST
: {
2803 map
<string
, void> checked_map
;
2804 size_t needed_checked_cnt
= 0;
2805 if (base_template
&& my_governor
) {
2806 switch (my_governor
->get_typetype()) {
2811 case Type::T_SIGNATURE
:
2812 needed_checked_cnt
= my_governor
->get_nof_comps();
2818 for (size_t i
= 0;i
< u
.named_templates
->get_nof_nts(); i
++) {
2819 bool nrc
= u
.named_templates
->get_nt_byIndex(i
)->get_template()->
2820 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2821 needs_runtime_check
= needs_runtime_check
|| nrc
;
2822 if (needed_checked_cnt
)
2824 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name(), 0);
2826 if (needed_checked_cnt
) {
2827 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2828 checked_map
, needed_checked_cnt
, usage_loc
);
2829 needs_runtime_check
= needs_runtime_check
|| nrc
;
2830 checked_map
.clear();
2833 case INDEXED_TEMPLATE_LIST
:
2834 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
2835 bool nrc
= u
.indexed_templates
->get_it_byIndex(i
)->get_template()->
2836 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2837 needs_runtime_check
= needs_runtime_check
|| nrc
;
2839 needs_runtime_check
= true; // only basic check, needs runtime check
2842 if (template_restriction
==TR_OMIT
) break;
2843 // Else restriction is TR_VALUE, but template type is OMIT:
2844 // fall through to error.
2846 usage_loc
->error("Restriction on %s does not allow usage of %s",
2847 definition_name
, get_templatetype_str());
2854 usage_loc
->error("Restriction on %s does not allow usage of `ifpresent'",
2858 switch(templatetype
) {
2859 case TEMPLATE_REFD
: {
2860 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
,
2862 needs_runtime_check
= needs_runtime_check
|| nrc
;
2865 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2866 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2867 chk_restriction(definition_name
, template_restriction
, usage_loc
);
2868 needs_runtime_check
= needs_runtime_check
|| nrc
;
2871 case COMPLEMENTED_LIST
:
2872 // some basic check, always needs runtime check
2873 needs_runtime_check
= true;
2874 if (omit_in_value_list
) {
2875 bool has_any_or_omit
= false;
2876 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2877 templatetype_t item_templatetype
=
2878 u
.templates
->get_t_byIndex(i
)->templatetype
;
2879 if (item_templatetype
==OMIT_VALUE
|| item_templatetype
==ANY_OR_OMIT
) {
2880 has_any_or_omit
= true;
2884 if (!has_any_or_omit
) {
2885 usage_loc
->error("Restriction on %s does not allow usage of %s without "
2886 "omit or AnyValueOrNone in the list", definition_name
,
2887 get_templatetype_str());
2894 usage_loc
->error("Restriction on %s does not allow usage of %s",
2895 definition_name
, get_templatetype_str());
2899 break; // all others are ok
2903 FATAL_ERROR("Template::chk_restriction()");
2905 if (erroneous
&& usage_loc
!= this) {
2906 // display the template's location, too
2907 note("Referenced template is here");
2909 return needs_runtime_check
;
2912 void Template::generate_code_expr(expression_struct
*expr
,
2913 template_restriction_t template_restriction
)
2915 // Only templates without extra matching attributes can be directly
2916 // represented in a C++ expression.
2917 if (!length_restriction
&& !is_ifpresent
2918 && template_restriction
== TR_NONE
) {
2919 // The single expression must be tried first because this rule might
2920 // cover some referenced templates.
2921 if (has_single_expr()) {
2922 expr
->expr
= mputstr(expr
->expr
, get_single_expr(true).c_str());
2925 switch (templatetype
) {
2926 case SPECIFIC_VALUE
:
2927 // A simple specific value: use explicit cast.
2928 expr
->expr
= mputprintf(expr
->expr
, "%s(",
2929 my_governor
->get_genname_template(my_scope
).c_str());
2930 u
.specific_value
->generate_code_expr(expr
);
2931 expr
->expr
= mputc(expr
->expr
, ')');
2934 // A simple unfoldable referenced template.
2935 if (!get_needs_conversion()) {
2936 u
.ref
.ref
->generate_code(expr
);
2938 Type
*my_gov
= get_expr_governor(Type::EXPECTED_TEMPLATE
)
2939 ->get_type_refd_last();
2940 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
2941 ->get_field_type(u
.ref
.ref
->get_subrefs(),
2942 Type::EXPECTED_TEMPLATE
)->get_type_refd_last();
2943 if (!my_gov
|| !refd_gov
|| my_gov
== refd_gov
)
2944 FATAL_ERROR("Template::generate_code_expr()");
2945 expression_struct expr_tmp
;
2946 Code::init_expr(&expr_tmp
);
2947 const string
& tmp_id1
= get_temporary_id();
2948 const char *tmp_id_str1
= tmp_id1
.c_str();
2949 const string
& tmp_id2
= get_temporary_id();
2950 const char *tmp_id_str2
= tmp_id2
.c_str();
2951 expr
->preamble
= mputprintf(expr
->preamble
,
2952 "%s %s;\n", refd_gov
->get_genname_template(my_scope
).c_str(),
2954 expr_tmp
.expr
= mputprintf(expr_tmp
.expr
, "%s = ", tmp_id_str1
);
2955 u
.ref
.ref
->generate_code(&expr_tmp
);
2956 expr
->preamble
= Code::merge_free_expr(expr
->preamble
, &expr_tmp
);
2957 expr
->preamble
= mputprintf(expr
->preamble
,
2959 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
2960 "and `%s' are not compatible at run-time\");\n",
2961 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str2
,
2962 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
2963 ->get_scope_mod()).c_str(), tmp_id_str2
, tmp_id_str1
, my_gov
2964 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
2965 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_id_str2
);
2968 case TEMPLATE_INVOKE
:
2969 generate_code_expr_invoke(expr
);
2975 // if none of the above methods are applicable use the most generic and
2976 // least efficient solution
2977 // create a temporary object, initialize it and use it in the expression
2978 const string
& tmp_id
= get_temporary_id();
2979 const char *tmp_id_str
= tmp_id
.c_str();
2981 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
2982 my_governor
->get_genname_template(my_scope
).c_str(), tmp_id_str
);
2983 set_genname_recursive(tmp_id
);
2984 expr
->preamble
= generate_code_init(expr
->preamble
, tmp_id_str
);
2985 if (template_restriction
!= TR_NONE
)
2986 expr
->preamble
= Template::generate_restriction_check_code(expr
->preamble
,
2987 tmp_id_str
, template_restriction
);
2988 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
2991 char *Template::generate_code_init(char *str
, const char *name
)
2993 if (get_code_generated()) return str
;
2994 set_code_generated();
2996 str
= err_descr
->generate_code_init_str(str
, string(name
)+"_err_descr");
2998 switch (templatetype
) {
3007 str
= mputprintf(str
, "%s = %s;\n", name
, get_single_expr(false).c_str());
3009 case SPECIFIC_VALUE
:
3010 if (get_code_section() == CS_POST_INIT
)
3011 str
= u
.specific_value
->rearrange_init_code(str
, my_scope
->get_scope_mod_gen());
3012 str
= u
.specific_value
->generate_code_init(str
, name
);
3015 str
= generate_code_init_refd(str
, name
);
3017 case TEMPLATE_INVOKE
:
3018 if (get_code_section() == CS_POST_INIT
)
3019 str
= rearrange_init_code_invoke(str
, my_scope
->get_scope_mod_gen());
3020 str
= generate_code_init_invoke(str
, name
);
3023 case INDEXED_TEMPLATE_LIST
:
3024 str
= generate_code_init_seof(str
, name
);
3026 case NAMED_TEMPLATE_LIST
:
3027 str
= generate_code_init_se(str
, name
);
3029 case VALUE_LIST_ALL_FROM
:
3030 str
= generate_code_init_all_from_list(str
, name
);
3033 str
= generate_code_init_all_from(str
, name
);
3036 str
= generate_code_init_list(str
, name
, false);
3038 case COMPLEMENTED_LIST
:
3039 str
= generate_code_init_list(str
, name
, true);
3042 if (get_code_section() == CS_POST_INIT
)
3043 str
= u
.value_range
->rearrange_init_code(str
, my_scope
->get_scope_mod_gen());
3044 str
= u
.value_range
->generate_code_init(str
, name
);
3046 case SUPERSET_MATCH
:
3047 str
= generate_code_init_set(str
, name
, true);
3050 str
= generate_code_init_set(str
, name
, false);
3052 case PERMUTATION_MATCH
:
3053 warning("Don't know how to init PERMUT");
3054 str
= mputprintf(str
, "/* FIXME: PERMUT goes here, name=%s*/\n", name
);
3056 case TEMPLATE_NOTUSED
:
3058 case TEMPLATE_ERROR
:
3060 FATAL_ERROR("Template::generate_code_init()");
3062 if (length_restriction
) {
3063 if (get_code_section() == CS_POST_INIT
)
3064 str
= length_restriction
->rearrange_init_code(str
, my_scope
->get_scope_mod_gen());
3065 str
= length_restriction
->generate_code_init(str
, name
);
3067 if (is_ifpresent
) str
= mputprintf(str
, "%s.set_ifpresent();\n", name
);
3069 str
= mputprintf(str
, "%s.set_err_descr(&%s_err_descr);\n", name
, name
);
3074 char *Template::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
3076 switch (templatetype
) {
3077 case SPECIFIC_VALUE
:
3078 str
= u
.specific_value
->rearrange_init_code(str
, usage_mod
);
3081 str
= rearrange_init_code_refd(str
, usage_mod
);
3083 case TEMPLATE_INVOKE
:
3084 str
= rearrange_init_code_invoke(str
, usage_mod
);
3088 case COMPLEMENTED_LIST
:
3089 case SUPERSET_MATCH
:
3091 case PERMUTATION_MATCH
:
3092 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
3093 str
= u
.templates
->get_t_byIndex(i
)->rearrange_init_code(str
, usage_mod
);
3095 case NAMED_TEMPLATE_LIST
:
3096 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
3097 str
= u
.named_templates
->get_nt_byIndex(i
)->get_template()
3098 ->rearrange_init_code(str
, usage_mod
);
3100 case INDEXED_TEMPLATE_LIST
:
3101 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
3102 str
= u
.indexed_templates
->get_it_byIndex(i
)->get_template()
3103 ->rearrange_init_code(str
, usage_mod
);
3106 str
= u
.value_range
->rearrange_init_code(str
, usage_mod
);
3111 if (length_restriction
) str
= length_restriction
->rearrange_init_code(str
, usage_mod
);
3115 bool Template::use_single_expr_for_init()
3117 Template
*t_last
= get_template_refd_last();
3118 // return false in case of unfoldable references
3119 if (t_last
->templatetype
== TEMPLATE_REFD
) return false;
3120 // return false if t_last is in a different module
3121 if (t_last
->my_scope
->get_scope_mod_gen() != my_scope
->get_scope_mod_gen())
3123 // return false if t_last cannot be represented by a single expression
3124 if (!t_last
->has_single_expr()) return false;
3125 // return true if t_last is a generic wildcard, string pattern, etc.
3126 if (t_last
->templatetype
!= SPECIFIC_VALUE
) return true;
3127 // examine the specific value
3128 Value
*v_last
= t_last
->u
.specific_value
->get_value_refd_last();
3129 switch (v_last
->get_valuetype()) {
3131 // do not calculate expressions again
3133 case Value::V_REFD
: {
3134 // v_last is an unfoldable value reference
3135 // the scope of the definition that v_last refers to
3137 v_last
->get_reference()->get_refd_assignment()->get_my_scope();
3138 for (Scope
*t_scope
= my_scope
; t_scope
;
3139 t_scope
= t_scope
->get_parent_scope()) {
3140 // return true if the referred definition is in the same scope
3141 // as this or in one of the parent scopes of this
3142 if (t_scope
== v_scope
) return true;
3144 // otherwise return false
3147 // return true only if v_last is defined in the same module as this
3148 return v_last
->get_my_scope()->get_scope_mod_gen() ==
3149 my_scope
->get_scope_mod_gen();
3153 char *Template::generate_code_init_refd(char *str
, const char *name
)
3155 if (use_single_expr_for_init() && has_single_expr()) {
3156 str
= mputprintf(str
, "%s = %s;\n", name
,
3157 get_single_expr(false).c_str());
3159 expression_struct expr
;
3160 Code::init_expr(&expr
);
3161 bool use_ref_for_codegen
= true;
3162 if (get_code_section() == CS_POST_INIT
) {
3163 // the referencing template is a part of a non-parameterized template
3164 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
3165 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
3166 // the reference points to (a field of) a template
3167 if (ass
->get_FormalParList()) {
3168 // the referred template is parameterized
3169 // generate the initialization sequence first for all dependent
3170 // non-parameterized templates
3171 str
= rearrange_init_code_refd(str
, my_scope
->get_scope_mod_gen());
3172 } else if (ass
->get_my_scope()->get_scope_mod_gen() ==
3173 my_scope
->get_scope_mod_gen()) {
3174 // the referred template is non-parameterized
3175 // use a different algorithm for code generation
3176 str
= generate_rearrange_init_code_refd(str
, &expr
);
3177 use_ref_for_codegen
= false;
3181 if (use_ref_for_codegen
) u
.ref
.ref
->generate_code_const_ref(&expr
);
3182 if (expr
.preamble
|| expr
.postamble
) {
3183 // the expressions within reference need temporary objects
3184 str
= mputstr(str
, "{\n");
3185 str
= mputstr(str
, expr
.preamble
);
3186 if (use_runtime_2
&& get_needs_conversion()) {
3187 const string
& tmp_id
= get_temporary_id();
3188 const char *tmp_id_str
= tmp_id
.c_str();
3189 Type
*my_gov
= my_governor
->get_type_refd_last();
3190 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
3191 ->get_type_refd_last();
3192 if (!my_gov
|| !refd_gov
)
3193 FATAL_ERROR("Template::generate_code_init_refd()");
3194 str
= mputprintf(str
,
3196 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3197 "and `%s' are not compatible at run-time\");\n",
3198 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3199 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
3200 ->get_scope_mod()).c_str(), tmp_id_str
, expr
.expr
, my_gov
3201 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
3202 str
= mputprintf(str
, "%s = %s;\n", name
, tmp_id_str
);
3204 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
3206 str
= mputstr(str
, expr
.postamble
);
3207 str
= mputstr(str
, "}\n");
3209 // the reference does not need temporary objects
3210 if (use_runtime_2
&& get_needs_conversion()) {
3211 const string
& tmp_id
= get_temporary_id();
3212 const char *tmp_id_str
= tmp_id
.c_str();
3213 Type
*my_gov
= my_governor
->get_type_refd_last();
3214 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
3215 ->get_type_refd_last();
3216 if (!my_gov
|| !refd_gov
)
3217 FATAL_ERROR("Template::generate_code_init_refd()");
3218 str
= mputprintf(str
,
3220 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3221 "and `%s' are not compatible at run-time\");\n",
3222 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3223 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
3224 ->get_scope_mod()).c_str(), tmp_id_str
, expr
.expr
, my_gov
3225 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
3226 str
= mputprintf(str
, "%s = %s;\n", name
, tmp_id_str
);
3228 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
3231 Code::free_expr(&expr
);
3236 char *Template::generate_code_init_invoke(char *str
, const char *name
)
3238 expression_struct expr
;
3239 Code::init_expr(&expr
);
3240 expr
.expr
= mputprintf(expr
.expr
, "%s = ", name
);
3241 generate_code_expr_invoke(&expr
);
3242 return Code::merge_free_expr(str
, &expr
);
3245 char *Template::generate_rearrange_init_code_refd(char *str
,
3246 expression_struct
*expr
)
3248 /** Initially we can assume that:
3249 * - this is a referenced template and a part of a non-parameterized
3251 * - u.ref.ref points to (a field of) a non-parameterized template within
3252 * the same module as \a this.
3253 * - this ensures that the do-while loop will run at least twice (i.e. the
3254 * first continue statement will be reached in the first iteration) */
3255 stack
<FieldOrArrayRef
> refstack
;
3257 // first try to find the smallest dependent template
3259 if (t
->templatetype
== TEMPLATE_REFD
) {
3260 Common::Assignment
*ass
= t
->u
.ref
.ref
->get_refd_assignment();
3261 /** Don't follow the reference if:
3262 * - the referenced definition is not a template
3263 * - the referenced template is parameterized or
3264 * - the referenced template is in different module */
3265 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
&&
3266 ass
->get_FormalParList() == 0 &&
3267 ass
->get_my_scope()->get_scope_mod_gen() ==
3268 my_scope
->get_scope_mod_gen()) {
3269 // accumulate the sub-references of the referred reference
3270 FieldOrArrayRefs
*subrefs
= t
->u
.ref
.ref
->get_subrefs();
3272 for (size_t i
= subrefs
->get_nof_refs(); i
> 0; i
--)
3273 refstack
.push(subrefs
->get_ref(i
- 1));
3275 // jump to the referred top-level template
3276 t
= ass
->get_Template();
3277 // start the iteration from the beginning
3279 // stop otherwise: the reference cannot be followed
3282 // stop if there are no sub-references
3283 if (refstack
.empty()) break;
3284 // take the topmost sub-reference
3285 FieldOrArrayRef
*subref
= refstack
.top();
3286 if (subref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
3287 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
3288 // the field reference can be followed
3289 t
= t
->u
.named_templates
->get_nt_byName(*subref
->get_id())
3292 // trying to follow an array reference
3293 if (t
->templatetype
!= TEMPLATE_LIST
) break;
3294 Value
*array_index
= subref
->get_val()->get_value_refd_last();
3295 if (array_index
->get_valuetype() != Value::V_INT
) break;
3296 // the index is available at compilation time
3297 Int index
= array_index
->get_val_Int()->get_val();
3298 // index transformation in case of arrays
3299 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
3300 index
-= t
->my_governor
->get_dimension()->get_offset();
3301 t
= t
->get_listitem_byIndex(index
);
3303 // the topmost sub-reference was processed
3304 // it can be erased from the stack
3307 // the smallest dependent template is now in t
3308 // generate the initializer sequence for t
3309 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
3310 // the equivalent C++ code of the referenced template is composed of the
3311 // genname of t and the remained sub-references in refstack
3312 expr
->expr
= mputstr(expr
->expr
, t
->get_genname_own(my_scope
).c_str());
3313 while (!refstack
.empty()) {
3314 FieldOrArrayRef
*subref
= refstack
.pop();
3315 if (subref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
3316 expr
->expr
= mputprintf(expr
->expr
, ".%s()",
3317 subref
->get_id()->get_name().c_str());
3319 expr
->expr
= mputc(expr
->expr
, '[');
3320 subref
->get_val()->generate_code_expr(expr
);
3321 expr
->expr
= mputc(expr
->expr
, ']');
3327 bool Template::compile_time() const
3329 switch (templatetype
) {
3331 case VALUE_LIST_ALL_FROM
:
3333 case TEMPLATE_ERROR
: /**< erroneous template */
3334 case TEMPLATE_NOTUSED
: /**< not used symbol (-) */
3335 case OMIT_VALUE
: /**< omit */
3336 case ANY_VALUE
: /**< any value (?) */
3337 case ANY_OR_OMIT
: /**< any or omit (*) */
3338 case SPECIFIC_VALUE
: /**< specific value */
3339 case TEMPLATE_REFD
: /**< reference to another template */
3340 case VALUE_RANGE
: /**< value range match */
3341 case BSTR_PATTERN
: /**< bitstring pattern */
3342 case HSTR_PATTERN
: /**< hexstring pattern */
3343 case OSTR_PATTERN
: /**< octetstring pattern */
3344 case CSTR_PATTERN
: /**< character string pattern */
3345 case USTR_PATTERN
: /**< universal charstring pattern */
3346 case TEMPLATE_INVOKE
:
3347 // Simple templates can be computed at compile time
3350 // "Complex" templates need to look at all elements
3353 case COMPLEMENTED_LIST
:
3354 case SUPERSET_MATCH
:
3356 case PERMUTATION_MATCH
:
3357 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
3358 if (u
.templates
->get_t_byIndex(i
)->compile_time()) continue;
3361 case NAMED_TEMPLATE_LIST
:
3362 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
3363 if (!u
.named_templates
->get_nt_byIndex(i
)->get_template()->compile_time())
3366 case INDEXED_TEMPLATE_LIST
:
3367 for (size_t i
= 0; i
<u
.indexed_templates
->get_nof_its(); i
++)
3368 if (!u
.indexed_templates
->get_it_byIndex(i
)->get_template()->compile_time())
3373 return true; // not reached
3376 char *Template::generate_code_init_seof(char *str
, const char *name
)
3378 switch (templatetype
) {
3379 case TEMPLATE_LIST
: {
3380 size_t nof_ts
= u
.templates
->get_nof_ts();
3382 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3387 Type
*t_last
= my_governor
->get_type_refd_last();
3389 if (t_last
->get_typetype() == Type::T_ARRAY
) {
3390 // take the start index from the array dimension
3391 index_offset
= t_last
->get_dimension()->get_offset();
3393 // indexing always starts from zero
3397 const string
& oftype_name
=
3398 t_last
->get_ofType()->get_genname_template(my_scope
);
3399 const char *oftype_name_str
= oftype_name
.c_str();
3401 ReferenceChain
refch (this, "While searching template");
3402 if (!flattened
|| my_scope
->get_statementblock_scope()) { // this "if" may be redundant if all non-var templates are flattened
3403 str
= mputstr(str
, "// this is a var template\n");
3405 if (compile_time()) goto compile_time
;
3406 // run-time, variable sized init
3408 // This is a record-of var template, like this:
3409 // var template rec_of_int vt_r := {
3410 // 1, 2, 3, permutation(10, all from x, 20), 4, 5 }
3411 // ^^^^^^^--- these ------------------------^^^^^
3412 // are known at compile time, but the length of the "all from"
3413 // is only known at run time.
3414 // Collect the indices where there is an "all from".
3415 dynamic_array
<int> variables
;
3416 size_t fixed_part
= 0;
3417 if (has_permutation
) {
3418 for (size_t i
= 0; i
< nof_ts
; i
++) {
3419 Template
*t
= u
.templates
->get_t_byIndex(i
);
3420 if (t
->templatetype
== PERMUTATION_MATCH
) {
3421 size_t num_p
= t
->u
.templates
->get_nof_ts();
3422 // t->u.templates is 2: "hello" and all from ...
3423 for (size_t j
= 0; j
< num_p
; ++j
) {
3424 Template
*subt
= t
->u
.templates
->get_t_byIndex(j
);
3425 if (subt
->templatetype
== ALL_FROM
) {
3434 char* str_preamble
= 0;
3435 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3436 (unsigned long)fixed_part
);
3439 for (size_t i
= 0; i
< nof_ts
; i
++) {
3440 Template
*t
= u
.templates
->get_t_byIndex(i
);
3441 for (size_t k
= 0, v
= variables
.size(); k
< v
; ++k
) {
3442 if (t
->templatetype
!= PERMUTATION_MATCH
) continue; // ?? really nothing to do ??
3443 Template
*subt
= t
->u
.templates
->get_t_byIndex(variables
[k
]);
3444 if (subt
->templatetype
== ALL_FROM
) {
3445 Value
*refv
= subt
->u
.all_from
->u
.specific_value
;
3446 // don't call get_Value(), it rips out the value from the template
3448 if (refv
->get_valuetype()!=Value::V_REFD
) FATAL_ERROR("%s", __FUNCTION__
);
3449 Common::Reference
*ref
= refv
->get_reference();
3450 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3451 Common::Assignment
*ass
= ref
->get_refd_assignment();
3453 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3455 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3457 // in case of parametrised references:
3458 // - temporary parameters need to be declared (stored in str_preamble)
3459 // - the same temporary needs to be used at each call (generate_code_cached call)
3460 expression_struct expr
;
3461 Code::init_expr(&expr
);
3463 ref_pard
->generate_code_cached(&expr
);
3464 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3466 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3468 Code::free_expr(&expr
);
3471 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3473 expression_struct expr
;
3474 Code::init_expr(&expr
);
3476 subrefs
->generate_code(&expr
, ass
);
3477 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3479 Code::free_expr(&expr
);
3483 switch(ass
->get_asstype()) {
3484 case Common::Assignment::A_CONST
:
3485 case Common::Assignment::A_EXT_CONST
:
3486 case Common::Assignment::A_MODULEPAR
:
3487 case Common::Assignment::A_VAR
:
3488 case Common::Assignment::A_PAR_VAL_IN
:
3489 case Common::Assignment::A_PAR_VAL_OUT
:
3490 case Common::Assignment::A_PAR_VAL_INOUT
:
3491 case Common::Assignment::A_FUNCTION_RVAL
:
3492 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3493 if (ass
->get_Type()->field_is_optional(subrefs
)) {
3494 str_set_size
= mputstrn(str_set_size
, "()", 2);
3501 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3506 str
= mputstr(str
, str_preamble
);
3507 str
= mputstr(str
, str_set_size
);
3512 str
= mputstrn(str
, ");\n", 3); // finally done set_size
3515 string skipper
, hopper
;
3516 for (size_t i
= 0; i
< nof_ts
; i
++) {
3517 Template
*t
= u
.templates
->get_t_byIndex(i
);
3518 switch (t
->templatetype
) {
3521 case PERMUTATION_MATCH
: {
3522 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
3523 for (size_t j
= 0; j
< nof_perm_ts
; j
++) {
3524 Int
ix(index_offset
+ index
+ j
);
3525 Template
*permut_elem
= t
->u
.templates
->get_t_byIndex(j
);
3526 if (permut_elem
->templatetype
== ALL_FROM
) {
3527 expression_struct expr
;
3528 Code::init_expr(&expr
);
3529 switch (permut_elem
->u
.all_from
->templatetype
) {
3530 case SPECIFIC_VALUE
: {
3531 Value
*spec
= permut_elem
->u
.all_from
->u
.specific_value
;
3532 switch (spec
->get_valuetype()) {
3533 case Common::Value::V_REFD
: {
3534 Common::Reference
*ref
= spec
->get_reference();
3536 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3538 ref_pard
->generate_code_cached(&expr
);
3540 ref
->generate_code(&expr
);
3542 Common::Assignment
* ass
= ref
->get_refd_assignment();
3543 switch(ass
->get_asstype()) {
3544 case Common::Assignment::A_CONST
:
3545 case Common::Assignment::A_EXT_CONST
:
3546 case Common::Assignment::A_MODULEPAR
:
3547 case Common::Assignment::A_VAR
:
3548 case Common::Assignment::A_PAR_VAL_IN
:
3549 case Common::Assignment::A_PAR_VAL_OUT
:
3550 case Common::Assignment::A_PAR_VAL_INOUT
:
3551 case Common::Assignment::A_FUNCTION_RVAL
:
3552 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3553 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
3554 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
3563 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3570 FATAL_ERROR("ttype %d", permut_elem
->u
.all_from
->templatetype
);
3573 str
= mputprintf(str
,
3574 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3577 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3578 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3581 str
= mputstrn(str
, "}\n", 2);
3583 skipper
+= expr
.expr
;
3584 skipper
+= ".n_elem() /* 3005 */ ";
3585 Code::free_expr(&expr
);
3588 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3589 (Int2string(ix
) + skipper
).c_str(), oftype_name_str
);
3592 // do not consider index_offset in case of permutation indicators
3593 str
= mputprintf(str
, "%s.add_permutation(%lu%s, %lu%s);\n", name
,
3594 (unsigned long)index
, hopper
.c_str(),
3595 (unsigned long)(index
+ nof_perm_ts
- 1), skipper
.c_str());
3597 t
->set_code_generated();
3598 index
+= nof_perm_ts
;
3602 str
= t
->generate_code_init_seof_element(str
, name
,
3603 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3605 case TEMPLATE_NOTUSED
:
3616 if (!has_permutation
&& has_allfrom()) {
3617 for (size_t i
= 0; i
< nof_ts
; i
++) {
3618 Template
*t
= u
.templates
->get_t_byIndex(i
);
3619 if (t
->templatetype
== ALL_FROM
) {
3626 char* str_preamble
= 0;
3627 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3628 (unsigned long)fixed_part
);
3631 for (size_t i
= 0, v
= variables
.size(); i
< v
; ++i
) {
3632 Template
*t
= u
.templates
->get_t_byIndex(variables
[i
]);
3633 if (t
->templatetype
== ALL_FROM
) {
3634 Value
*refv
= t
->u
.all_from
->u
.specific_value
;
3635 // don't call get_Value(), it rips out the value from the template
3636 if (refv
->get_valuetype()!=Value::V_REFD
) FATAL_ERROR("%s", __FUNCTION__
);
3637 Common::Reference
*ref
= refv
->get_reference();
3638 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3639 Common::Assignment
*ass
= ref
->get_refd_assignment();
3640 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3641 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3643 // in case of parametrised references:
3644 // - temporary parameters need to be declared (stored in str_preamble)
3645 // - the same temporary needs to be used at each call (generate_code_cached call)
3646 expression_struct expr
;
3647 Code::init_expr(&expr
);
3649 ref_pard
->generate_code_cached(&expr
);
3650 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3652 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3653 Code::free_expr(&expr
);
3656 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3658 expression_struct expr
;
3659 Code::init_expr(&expr
);
3660 subrefs
->generate_code(&expr
, ass
);
3661 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3662 Code::free_expr(&expr
);
3666 switch(ass
->get_asstype()) {
3667 case Common::Assignment::A_CONST
:
3668 case Common::Assignment::A_EXT_CONST
:
3669 case Common::Assignment::A_MODULEPAR
:
3670 case Common::Assignment::A_VAR
:
3671 case Common::Assignment::A_PAR_VAL_IN
:
3672 case Common::Assignment::A_PAR_VAL_OUT
:
3673 case Common::Assignment::A_PAR_VAL_INOUT
:
3674 case Common::Assignment::A_FUNCTION_RVAL
:
3675 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3676 if (ass
->get_Type()->field_is_optional(subrefs
)) {
3677 str_set_size
= mputstrn(str_set_size
, "()", 2);
3684 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3687 str
= mputstr(str
, str_preamble
);
3688 str
= mputstr(str
, str_set_size
);
3691 str
= mputstrn(str
, ");\n", 3); // finally done set_size
3695 for (size_t i
= 0; i
< nof_ts
; i
++) {
3696 Template
*t
= u
.templates
->get_t_byIndex(i
);
3697 Int
ix(index_offset
+ i
);
3698 switch (t
->templatetype
) {
3700 expression_struct expr
;
3701 Code::init_expr(&expr
);
3702 switch (t
->u
.all_from
->templatetype
) {
3703 case SPECIFIC_VALUE
: {
3704 Value
*spec
= t
->u
.all_from
->u
.specific_value
;
3705 switch (spec
->get_valuetype()) {
3706 case Common::Value::V_REFD
: {
3707 Common::Reference
*ref
= spec
->get_reference();
3708 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3710 ref_pard
->generate_code_cached(&expr
);
3712 ref
->generate_code(&expr
);
3714 Common::Assignment
* ass
= ref
->get_refd_assignment();
3715 switch(ass
->get_asstype()) {
3716 case Common::Assignment::A_CONST
:
3717 case Common::Assignment::A_EXT_CONST
:
3718 case Common::Assignment::A_MODULEPAR
:
3719 case Common::Assignment::A_VAR
:
3720 case Common::Assignment::A_PAR_VAL_IN
:
3721 case Common::Assignment::A_PAR_VAL_OUT
:
3722 case Common::Assignment::A_PAR_VAL_INOUT
:
3723 case Common::Assignment::A_FUNCTION_RVAL
:
3724 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3725 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
3726 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
3735 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3740 FATAL_ERROR("ttype %d", t
->u
.all_from
->templatetype
);
3743 str
= mputprintf(str
,
3744 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3746 str
= t
->generate_code_init_seof_element(str
, name
,
3747 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3749 str
= mputstrn(str
, "}\n", 2);
3751 skipper
+= expr
.expr
;
3752 skipper
+= ".n_elem() ";
3753 Code::free_expr(&expr
);
3754 t
->set_code_generated();
3758 str
= t
->generate_code_init_seof_element(str
, name
,
3759 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3761 case TEMPLATE_NOTUSED
:
3772 // setting the size first
3774 str
= mputprintf(str
, "%s.set_size(%lu);\n", name
, (unsigned long) get_nof_listitems());
3775 // determining the index offset based on the governor
3778 for (size_t i
= 0; i
< nof_ts
; i
++) {
3779 Template
*t
= u
.templates
->get_t_byIndex(i
);
3780 switch (t
->templatetype
) {
3781 case PERMUTATION_MATCH
: {
3782 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
3783 for (size_t j
= 0; j
< nof_perm_ts
; j
++) {
3784 Int
ix(index_offset
+ index
+ j
);
3785 str
= t
->u
.templates
->get_t_byIndex(j
)
3786 ->generate_code_init_seof_element(str
, name
,
3787 Int2string(ix
).c_str(), oftype_name_str
);
3789 // do not consider index_offset in case of permutation indicators
3790 str
= mputprintf(str
, "%s.add_permutation(%lu, %lu);\n", name
,
3791 (unsigned long)index
, (unsigned long) (index
+ nof_perm_ts
- 1));
3792 t
->set_code_generated();
3793 index
+= nof_perm_ts
;
3797 str
= t
->generate_code_init_seof_element(str
, name
,
3798 Int2string(index_offset
+ index
).c_str(), oftype_name_str
);
3801 case TEMPLATE_NOTUSED
:
3806 case INDEXED_TEMPLATE_LIST
: {
3807 size_t nof_its
= u
.indexed_templates
->get_nof_its();
3809 Type
*t_last
= my_governor
->get_type_refd_last();
3810 const string
& oftype_name
=
3811 t_last
->get_ofType()->get_genname_template(my_scope
);
3812 const char *oftype_name_str
= oftype_name
.c_str();
3813 // There's no need to generate a set_size call here. To do that, we
3814 // should know the size of the base template, which is not available
3816 for (size_t i
= 0; i
< nof_its
; i
++) {
3817 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
3818 const string
& tmp_id_1
= get_temporary_id();
3819 str
= mputstr(str
, "{\n");
3820 Value
*index
= (it
->get_index()).get_val();
3821 if (index
->get_valuetype() != Value::V_INT
) {
3822 const string
& tmp_id_2
= get_temporary_id();
3823 str
= mputprintf(str
, "int %s;\n", tmp_id_2
.c_str());
3824 str
= index
->generate_code_init(str
, tmp_id_2
.c_str());
3825 str
= mputprintf(str
, "%s& %s = %s[%s];\n", oftype_name_str
,
3826 tmp_id_1
.c_str(), name
, tmp_id_2
.c_str());
3828 str
= mputprintf(str
, "%s& %s = %s[%s];\n", oftype_name_str
,
3829 tmp_id_1
.c_str(), name
,
3830 Int2string(index
->get_val_Int()->get_val()).c_str());
3832 str
= it
->get_template()->generate_code_init(str
, tmp_id_1
.c_str());
3833 str
= mputstr(str
, "}\n");
3836 // It seems to be impossible in this case.
3837 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3841 FATAL_ERROR("Template::generate_code_init_seof()");
3847 char *Template::generate_code_init_seof_element(char *str
, const char *name
,
3848 const char* index
, const char *element_type_genname
)
3850 if (needs_temp_ref()) {
3851 const string
& tmp_id
= get_temporary_id();
3852 str
= mputprintf(str
, "{\n"
3853 "%s& %s = %s[%s];\n",
3854 element_type_genname
, tmp_id
.c_str(), name
, index
);
3855 str
= generate_code_init(str
, tmp_id
.c_str());
3856 str
= mputstr(str
, "}\n");
3858 char *embedded_name
= mprintf("%s[%s]", name
, index
);
3859 str
= generate_code_init(str
, embedded_name
);
3860 Free(embedded_name
);
3865 char *Template::generate_code_init_all_from(char *str
, const char *name
)
3867 // we are ALL_FROM, hence u.all_from
3868 switch (u
.all_from
->templatetype
) {
3869 case SPECIFIC_VALUE
: {
3870 Value
*spec
= u
.all_from
->u
.specific_value
;
3871 switch (spec
->get_valuetype()) {
3872 case Common::Value::V_REFD
: {
3873 Common::Reference
*ref
= spec
->get_reference();
3874 expression_struct expr
;
3875 Code::init_expr(&expr
);
3876 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3878 ref_pard
->generate_code_cached(&expr
);
3880 ref
->generate_code(&expr
);
3882 Common::Assignment
* ass
= ref
->get_refd_assignment();
3883 switch(ass
->get_asstype()) {
3884 case Common::Assignment::A_CONST
:
3885 case Common::Assignment::A_EXT_CONST
:
3886 case Common::Assignment::A_MODULEPAR
:
3887 case Common::Assignment::A_VAR
:
3888 case Common::Assignment::A_PAR_VAL_IN
:
3889 case Common::Assignment::A_PAR_VAL_OUT
:
3890 case Common::Assignment::A_PAR_VAL_INOUT
:
3891 case Common::Assignment::A_FUNCTION_RVAL
:
3892 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3893 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
3894 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
3901 str
= mputprintf(str
, "%s = %s[i_i];\n", name
, expr
.expr
);
3902 // The caller will have to provide the for cycle with this variable
3903 Code::free_expr(&expr
);
3915 char *Template::generate_code_init_all_from_list(char *str
, const char *name
)
3917 // FIXME: this is the third instance
3918 expression_struct expr
;
3919 Code::init_expr(&expr
);
3920 switch (u
.all_from
->templatetype
) {
3921 case SPECIFIC_VALUE
: {
3922 Value
*spec
= u
.all_from
->u
.specific_value
;
3923 switch (spec
->get_valuetype()) {
3924 case Common::Value::V_REFD
: {
3925 Common::Reference
*ref
= spec
->get_reference();
3926 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3928 ref_pard
->generate_code_cached(&expr
);
3930 ref
->generate_code(&expr
);
3933 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3939 FATAL_ERROR("ttype %d", u
.all_from
->templatetype
);
3944 str
= mputstr(str
, expr
.preamble
);
3946 str
= mputprintf(str
,
3947 "%s.set_type(VALUE_LIST, %s.n_elem());\n"
3948 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3952 string
embedded_name(name
);
3953 embedded_name
+= ".list_item(i_i)";
3954 str
= generate_code_init_all_from(str
, embedded_name
.c_str());
3955 str
= mputstrn(str
, "}\n", 2);
3957 Code::free_expr(&expr
);
3961 char *Template::generate_code_init_se(char *str
, const char *name
)
3962 { // named template list
3963 size_t nof_nts
= u
.named_templates
->get_nof_nts();
3964 Type
*type
= my_governor
->get_type_refd_last();
3965 if (type
->get_nof_comps() > 0) {
3966 for (size_t i
= 0; i
< nof_nts
; i
++) {
3967 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
3968 const Identifier
& fieldname
= nt
->get_name();
3969 const char *fieldname_str
= 0;
3971 if (type
->get_typetype()==Type::T_ANYTYPE
) {
3972 at
+= fieldname
.get_name();
3973 fieldname_str
= at
.c_str();
3976 fieldname_str
= fieldname
.get_name().c_str();
3978 Template
*t
= nt
->get_template();
3979 if (t
->needs_temp_ref()) {
3981 if (type
->get_typetype() == Type::T_SIGNATURE
) {
3982 field_type
= type
->get_signature_parameters()
3983 ->get_param_byName(fieldname
)->get_type();
3985 field_type
= type
->get_comp_byName(fieldname
)->get_type();
3987 const string
& tmp_id
= get_temporary_id();
3988 const char *tmp_id_str
= tmp_id
.c_str();
3989 str
= mputprintf(str
, "{\n"
3990 "%s& %s = %s.%s();\n",
3991 field_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3992 name
, fieldname_str
);
3993 str
= t
->generate_code_init(str
, tmp_id_str
);
3994 str
= mputstr(str
, "}\n");
3996 char *embedded_name
= mprintf("%s.%s()", name
, fieldname_str
);
3997 str
= t
->generate_code_init(str
, embedded_name
);
3998 Free(embedded_name
);
4002 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
4007 char *Template::generate_code_init_list(char *str
, const char *name
,
4008 bool is_complemented
) // VALUE_LIST or COMPLEMENTED_LIST
4010 size_t nof_ts
= u
.templates
->get_nof_ts();
4011 const string
& type_name
= my_governor
->get_genname_template(my_scope
);
4012 const char *type_name_str
= type_name
.c_str();
4014 dynamic_array
<int> variables
;
4015 size_t fixed_part
= 0;
4016 for (size_t i
= 0; i
< nof_ts
; ++i
) {
4017 Template
*t
= u
.templates
->get_t_byIndex(i
);
4018 if (t
->templatetype
== ALL_FROM
) {
4024 if (variables
.size() > 0) {
4025 char* str_preamble
= 0;
4026 char* str_set_type
= mprintf("%s.set_type(%s, %lu", name
,
4027 (is_complemented
? "COMPLEMENTED_LIST" : "VALUE_LIST"),
4028 (unsigned long)fixed_part
);
4029 // The code to compute the number of elements at run time (the variable part).
4030 // This is the sum of sizes of "all from"s.
4031 for (size_t v
= 0, vs
= variables
.size(); v
< vs
; ++v
) {
4032 Template
*vt
= u
.templates
->get_t_byIndex(variables
[v
]);
4033 if (vt
->templatetype
!= ALL_FROM
) FATAL_ERROR("must be ALL_FROM");
4034 if (vt
->u
.all_from
->templatetype
!= SPECIFIC_VALUE
) FATAL_ERROR("not value");
4035 Value
*val
= vt
->u
.all_from
->u
.specific_value
;
4036 if (val
->get_valuetype() != Value::V_REFD
) FATAL_ERROR("ref expected from val");
4037 Common::Reference
*ref
= val
->get_reference();
4038 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
4039 Common::Assignment
*ass
= ref
->get_refd_assignment();
4040 if (!ass
) FATAL_ERROR("Could not grab ass!");
4042 str_set_type
= mputstrn(str_set_type
, " + ", 3);
4044 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4046 // in case of parametrised references:
4047 // - temporary parameters need to be declared (stored in str_preamble)
4048 // - the same temporary needs to be used at each call (generate_code_cached call)
4049 expression_struct expr
;
4050 Code::init_expr(&expr
);
4052 ref_pard
->generate_code_cached(&expr
);
4053 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4055 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
4057 Code::free_expr(&expr
);
4060 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
4062 expression_struct expr
;
4063 Code::init_expr(&expr
);
4065 subrefs
->generate_code(&expr
, ass
);
4066 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4068 Code::free_expr(&expr
);
4072 switch(ass
->get_asstype()) {
4073 case Common::Assignment::A_CONST
:
4074 case Common::Assignment::A_EXT_CONST
:
4075 case Common::Assignment::A_MODULEPAR
:
4076 case Common::Assignment::A_VAR
:
4077 case Common::Assignment::A_PAR_VAL_IN
:
4078 case Common::Assignment::A_PAR_VAL_OUT
:
4079 case Common::Assignment::A_PAR_VAL_INOUT
:
4080 case Common::Assignment::A_FUNCTION_RVAL
:
4081 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4082 if (ass
->get_Type()->field_is_optional(subrefs
)) {
4083 str_set_type
= mputstrn(str_set_type
, "()", 2);
4090 str_set_type
= mputstr(str_set_type
, ".n_elem()");
4093 str
= mputstr(str
, str_preamble
);
4094 str
= mputstr(str
, str_set_type
);
4099 str
= mputstrn(str
, ");\n", 3);
4101 string shifty
; // contains the expression used to calculate
4102 // the size increase due to the runtime expansion of "all from".
4103 // In nof_ts, each "all from" appears as 1, but actually contributes
4104 // more. So the increase (by which all elements after the "all from"
4105 // are shifted) is: target_of_all_from.n_elem()-1
4106 // This needs to be accumulated for each "all from".
4107 for (size_t vi
= 0; vi
< nof_ts
; ++vi
) {
4108 Template
*t
= u
.templates
->get_t_byIndex(vi
);
4109 switch (t
->templatetype
) {
4110 case VALUE_LIST_ALL_FROM
:
4111 FATAL_ERROR("VALUE_LIST_ALL_FROM not handled");
4113 expression_struct expr
;
4114 Code::init_expr(&expr
);
4116 switch (t
->u
.all_from
->templatetype
) {
4117 case SPECIFIC_VALUE
: {
4118 Value
*sv
= t
->u
.all_from
->u
.specific_value
;
4119 switch (sv
->get_valuetype()) {
4120 case Value::V_REFD
: {
4121 Common::Reference
*ref
= sv
->get_reference();
4122 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4124 ref_pard
->generate_code_cached(&expr
);
4126 ref
->generate_code(&expr
);
4128 Common::Assignment
* ass
= ref
->get_refd_assignment();
4129 switch(ass
->get_asstype()) {
4130 case Common::Assignment::A_CONST
:
4131 case Common::Assignment::A_EXT_CONST
:
4132 case Common::Assignment::A_MODULEPAR
:
4133 case Common::Assignment::A_VAR
:
4134 case Common::Assignment::A_PAR_VAL_IN
:
4135 case Common::Assignment::A_PAR_VAL_OUT
:
4136 case Common::Assignment::A_PAR_VAL_INOUT
:
4137 case Common::Assignment::A_FUNCTION_RVAL
:
4138 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4139 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
4140 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
4150 FATAL_ERROR("VT NOT HANDLED");
4151 } // switch valuetype
4155 FATAL_ERROR("ttype not handled");
4159 // All local variables should contain a single underscore,
4160 // to avoid potential clashes with field names.
4161 str
= mputprintf(str
, "for (int i_i= 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4164 if (t
->needs_temp_ref()) {
4165 // Not possible, because t->templatetype is ALL_FROM
4166 FATAL_ERROR("temp ref not handled");
4168 char *embedded_name
= mprintf("%s.list_item(%lu + i_i%s)", name
,
4169 (unsigned long) vi
, shifty
.c_str());
4170 str
= t
->generate_code_init(str
, embedded_name
);
4171 Free(embedded_name
);
4173 str
= mputstrn(str
, "}\n", 2);
4176 shifty
+= expr
.expr
;
4177 shifty
+= ".n_elem() /* 3303 */ ";
4179 Code::free_expr(&expr
);
4182 default: // "fixed one"
4183 if (t
->needs_temp_ref()) { // FIXME: this is copypasta from below / but may need to be changed
4184 const string
& tmp_id
= get_temporary_id();
4185 const char *tmp_id_str
= tmp_id
.c_str();
4186 str
= mputprintf(str
, "{\n"
4187 "%s& %s = %s.list_item(%lu);\n",
4188 type_name_str
, tmp_id_str
, name
, (unsigned long) vi
);
4189 str
= t
->generate_code_init(str
, tmp_id_str
);
4190 str
= mputstr(str
, "}\n");
4192 char *embedded_name
= mprintf("%s.list_item(%lu%s)", name
,
4193 (unsigned long) vi
, shifty
.c_str());
4194 str
= t
->generate_code_init(str
, embedded_name
);
4195 Free(embedded_name
);
4198 } // switch t->templatetype
4202 str
= mputprintf(str
, "%s.set_type(%s, %lu);\n", name
,
4203 is_complemented
? "COMPLEMENTED_LIST" : "VALUE_LIST",
4204 (unsigned long) nof_ts
);
4205 for (size_t i
= 0; i
< nof_ts
; i
++) {
4206 Template
*t
= u
.templates
->get_t_byIndex(i
);
4207 if (t
->needs_temp_ref()) {
4208 const string
& tmp_id
= get_temporary_id();
4209 const char *tmp_id_str
= tmp_id
.c_str();
4210 str
= mputprintf(str
, "{\n"
4211 "%s& %s = %s.list_item(%lu);\n",
4212 type_name_str
, tmp_id_str
, name
, (unsigned long) i
);
4213 str
= t
->generate_code_init(str
, tmp_id_str
);
4214 str
= mputstr(str
, "}\n");
4216 char *embedded_name
= mprintf("%s.list_item(%lu)", name
,
4218 str
= t
->generate_code_init(str
, embedded_name
);
4219 Free(embedded_name
);
4226 char *Template::generate_code_init_set(char *str
, const char *name
,
4227 bool is_superset
) // SUPERSET_MATCH and SUBSET_MATCH
4229 size_t nof_ts
= u
.templates
->get_nof_ts();
4230 const string
& oftype_name
=
4231 my_governor
->get_ofType()->get_genname_template(my_scope
);
4232 const char *oftype_name_str
= oftype_name
.c_str();
4234 dynamic_array
<int> variables
;
4235 size_t fixed_part
= 0;
4236 for (size_t i
= 0; i
< nof_ts
; ++i
) {
4237 Template
*t
= u
.templates
->get_t_byIndex(i
);
4238 if (t
->templatetype
== ALL_FROM
) {
4244 //warning("There are %lu set elements", nof_ts);
4245 if (variables
.size() > 0) {
4246 char* str_preamble
= 0;
4247 char* str_set_type
= mputprintf(0, "%s.set_type(%s, %lu", name
,
4248 is_superset
? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) fixed_part
);
4250 for (size_t v
= 0, vs
= variables
.size(); v
< vs
; ++v
) {
4251 Template
*vt
= u
.templates
->get_t_byIndex(variables
[v
]);
4252 if (vt
->templatetype
!= ALL_FROM
) FATAL_ERROR("must be ALL_FROM");
4253 if (vt
->u
.all_from
->templatetype
!= SPECIFIC_VALUE
) FATAL_ERROR("not value");
4254 Value
*val
= vt
->u
.all_from
->u
.specific_value
;
4255 if (val
->get_valuetype() != Value::V_REFD
) FATAL_ERROR("ref expected from val");
4256 Common::Reference
*ref
= val
->get_reference();
4257 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
4258 Common::Assignment
*ass
= ref
->get_refd_assignment();
4259 if (!ass
) FATAL_ERROR("Could not grab ass!");
4261 str_set_type
= mputstrn(str_set_type
, " + ", 3);
4263 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4265 // in case of parametrised references:
4266 // - temporary parameters need to be declared (stored in str_preamble)
4267 // - the same temporary needs to be used at each call (generate_code_cached call)
4268 expression_struct expr
;
4269 Code::init_expr(&expr
);
4271 ref_pard
->generate_code_cached(&expr
);
4272 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4274 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
4276 Code::free_expr(&expr
);
4279 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
4281 expression_struct expr
;
4282 Code::init_expr(&expr
);
4284 subrefs
->generate_code(&expr
, ass
);
4285 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4287 Code::free_expr(&expr
);
4291 switch(ass
->get_asstype()) {
4292 case Common::Assignment::A_CONST
:
4293 case Common::Assignment::A_EXT_CONST
:
4294 case Common::Assignment::A_MODULEPAR
:
4295 case Common::Assignment::A_VAR
:
4296 case Common::Assignment::A_PAR_VAL_IN
:
4297 case Common::Assignment::A_PAR_VAL_OUT
:
4298 case Common::Assignment::A_PAR_VAL_INOUT
:
4299 case Common::Assignment::A_FUNCTION_RVAL
:
4300 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4301 if (ass
->get_Type()->field_is_optional(subrefs
)) {
4302 str_set_type
= mputstrn(str_set_type
, "()", 2);
4309 str_set_type
= mputstr(str_set_type
, ".n_elem()");
4312 str
= mputstr(str
, str_preamble
);
4313 str
= mputstr(str
, str_set_type
);
4318 str
= mputstrn(str
, ");\n", 3);
4321 for (size_t i
= 0; i
< nof_ts
; i
++) {
4322 Template
*t
= u
.templates
->get_t_byIndex(i
);
4323 switch (t
->templatetype
) {
4325 expression_struct expr
; // FIXME copypasta from init_list above !
4326 Code::init_expr(&expr
);
4328 switch (t
->u
.all_from
->templatetype
) {
4329 case SPECIFIC_VALUE
: {
4330 Value
*sv
= t
->u
.all_from
->u
.specific_value
;
4331 switch (sv
->get_valuetype()) {
4332 case Value::V_REFD
: {
4333 Common::Reference
*ref
= sv
->get_reference();
4334 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4336 ref_pard
->generate_code_cached(&expr
);
4338 ref
->generate_code(&expr
);
4340 Common::Assignment
* ass
= ref
->get_refd_assignment();
4341 switch(ass
->get_asstype()) {
4342 case Common::Assignment::A_CONST
:
4343 case Common::Assignment::A_EXT_CONST
:
4344 case Common::Assignment::A_MODULEPAR
:
4345 case Common::Assignment::A_VAR
:
4346 case Common::Assignment::A_PAR_VAL_IN
:
4347 case Common::Assignment::A_PAR_VAL_OUT
:
4348 case Common::Assignment::A_PAR_VAL_INOUT
:
4349 case Common::Assignment::A_FUNCTION_RVAL
:
4350 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4351 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
4352 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
4362 FATAL_ERROR("VT NOT HANDLED");
4363 } // switch valuetype
4367 FATAL_ERROR("ttype not handled");
4371 str
= mputprintf(str
,
4372 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4376 char *embedded_name
= mprintf("%s.set_item(%lu%s + i_i)", name
,
4377 (unsigned long) i
, shifty
.c_str());
4378 str
= t
->generate_code_init_all_from(str
, embedded_name
);
4379 Free(embedded_name
);
4381 str
= mputstrn(str
, "}\n", 2);
4384 shifty
+= expr
.expr
;
4385 shifty
+= ".n_elem() /* 3442 */";
4386 Code::free_expr(&expr
);
4388 case VALUE_LIST_ALL_FROM
:
4389 FATAL_ERROR("Not possible");
4390 break; // not reached
4393 if (t
->needs_temp_ref()) {
4394 const string
& tmp_id
= get_temporary_id();
4395 const char *tmp_id_str
= tmp_id
.c_str();
4396 str
= mputprintf(str
, "{\n"
4397 "%s& %s = %s.set_item(%lu%s);\n",
4398 oftype_name_str
, tmp_id_str
, name
, (unsigned long) i
, shifty
.c_str());
4399 str
= t
->generate_code_init(str
, tmp_id_str
);
4400 str
= mputstr(str
, "}\n");
4402 char *embedded_name
= mprintf("%s.set_item(%lu%s)", name
,
4403 (unsigned long) i
, shifty
.c_str());
4404 str
= t
->generate_code_init(str
, embedded_name
);
4405 Free(embedded_name
);
4408 } // switch t->templatetype
4413 str
= mputprintf(str
, "%s.set_type(%s, %lu);\n", name
,
4414 is_superset
? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) nof_ts
);
4415 for (size_t i
= 0; i
< nof_ts
; i
++) {
4416 Template
*t
= u
.templates
->get_t_byIndex(i
);
4417 if (t
->needs_temp_ref()) {
4418 const string
& tmp_id
= get_temporary_id();
4419 const char *tmp_id_str
= tmp_id
.c_str();
4420 str
= mputprintf(str
, "{\n"
4421 "%s& %s = %s.set_item(%lu);\n",
4422 oftype_name_str
, tmp_id_str
, name
, (unsigned long) i
);
4423 str
= t
->generate_code_init(str
, tmp_id_str
);
4424 str
= mputstr(str
, "}\n");
4426 char *embedded_name
= mprintf("%s.set_item(%lu)", name
,
4428 str
= t
->generate_code_init(str
, embedded_name
);
4429 Free(embedded_name
);
4436 void Template::generate_code_expr_invoke(expression_struct
*expr
)
4438 Value
*last_v
= u
.invoke
.v
->get_value_refd_last();
4439 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
4440 Common::Assignment
*function
= last_v
->get_refd_fat();
4441 expr
->expr
= mputprintf(expr
->expr
, "%s(",
4442 function
->get_genname_from_scope(my_scope
).c_str());
4443 u
.invoke
.ap_list
->generate_code_alias(expr
,
4444 function
->get_FormalParList(), function
->get_RunsOnType(), false);
4446 u
.invoke
.v
->generate_code_expr_mandatory(expr
);
4447 expr
->expr
= mputstr(expr
->expr
, ".invoke(");
4448 Type
* gov_last
= u
.invoke
.v
->get_expr_governor_last();
4449 u
.invoke
.ap_list
->generate_code_alias(expr
, 0,
4450 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
4452 expr
->expr
= mputc(expr
->expr
, ')');
4455 char *Template::rearrange_init_code_refd(char *str
, Common::Module
* usage_mod
)
4457 if (templatetype
!= TEMPLATE_REFD
)
4458 FATAL_ERROR("Template::rearrange_init_code_refd()");
4459 ActualParList
*actual_parlist
= u
.ref
.ref
->get_parlist();
4460 // generate code for the templates that are used in the actual parameter
4461 // list of the reference
4462 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
4463 if (actual_parlist
) str
= actual_parlist
->rearrange_init_code(str
, usage_mod
);
4464 // do nothing if the reference does not point to a template definition
4465 if (ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) return str
;
4466 Template
*t
= ass
->get_Template();
4467 FormalParList
*formal_parlist
= ass
->get_FormalParList();
4468 if (formal_parlist
) {
4469 // the reference points to a parameterized template
4470 // we must perform the rearrangement for all non-parameterized templates
4471 // that are referred by the parameterized template regardless of the
4472 // sub-references of u.ref.ref
4473 str
= t
->rearrange_init_code(str
, usage_mod
);
4474 // the parameterized template's default values must also be generated
4475 // (this only generates their value assignments, their declarations will
4476 // be generated when the template's definition is reached)
4477 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
4478 str
= formal_parlist
->generate_code_defval(str
);
4481 // the reference points to a non-parameterized template
4482 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
4484 // we should follow the sub-references as much as we can
4485 // and perform the rearrangement for the referred field only
4486 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); i
++) {
4487 FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
4488 if (ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
4489 // stop if the body does not have fields
4490 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
4491 // get the sub-template of the referred field
4492 t
= t
->u
.named_templates
->get_nt_byName(*ref
->get_id())
4495 // stop if the body is not a list
4496 if (t
->templatetype
!= TEMPLATE_LIST
) break;
4497 Value
*array_index
= ref
->get_val()->get_value_refd_last();
4498 // stop if the index cannot be evaluated at compile time
4499 if (array_index
->get_valuetype() != Value::V_INT
) break;
4500 Int index
= array_index
->get_val_Int()->get_val();
4501 // index transformation in case of arrays
4502 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
4503 index
-= t
->my_governor
->get_dimension()->get_offset();
4504 // get the template with the given index
4505 t
= t
->get_listitem_byIndex(index
);
4509 // otherwise if the reference points to a top-level template
4510 // we should initialize its entire body
4511 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
4512 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
4518 char *Template::rearrange_init_code_invoke(char *str
, Common::Module
* usage_mod
)
4520 str
= u
.invoke
.v
->rearrange_init_code(str
, usage_mod
);
4521 str
= u
.invoke
.ap_list
->rearrange_init_code(str
, usage_mod
);
4525 bool Template::needs_temp_ref()
4527 if (length_restriction
|| is_ifpresent
) return true;
4528 switch (templatetype
) {
4532 case SPECIFIC_VALUE
:
4534 case TEMPLATE_INVOKE
:
4540 case TEMPLATE_NOTUSED
:
4543 // temporary reference is needed if the template has at least one
4544 // element (excluding not used symbols)
4545 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
4546 if (u
.templates
->get_t_byIndex(i
)->templatetype
!= TEMPLATE_NOTUSED
)
4550 case INDEXED_TEMPLATE_LIST
:
4551 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
4552 if (u
.indexed_templates
->get_it_byIndex(i
)->get_template()
4553 ->templatetype
!= TEMPLATE_NOTUSED
)
4557 case NAMED_TEMPLATE_LIST
:
4558 return u
.named_templates
->get_nof_nts() > 1;
4560 case VALUE_LIST_ALL_FROM
:
4563 case COMPLEMENTED_LIST
:
4565 case SUPERSET_MATCH
:
4568 case TEMPLATE_ERROR
:
4569 FATAL_ERROR("Template::needs_temp_ref()");
4570 case PERMUTATION_MATCH
:
4577 bool Template::has_single_expr()
4579 if (length_restriction
|| is_ifpresent
|| get_needs_conversion())
4581 switch (templatetype
) {
4590 case TEMPLATE_NOTUSED
:
4592 case SPECIFIC_VALUE
:
4593 return u
.specific_value
->has_single_expr();
4594 case TEMPLATE_REFD
: {
4595 Template
*t_last
= get_template_refd_last();
4596 if (t_last
!= this && t_last
->has_single_expr()) {
4597 for (Scope
*t_scope
= my_scope
; t_scope
;
4598 t_scope
= t_scope
->get_parent_scope()) {
4599 // return true if t_last is visible from my scope
4600 if (t_scope
== t_last
->my_scope
) return true;
4603 // otherwise consider the reference itself
4604 return u
.ref
.ref
->has_single_expr(); }
4605 case TEMPLATE_INVOKE
:
4606 if (!u
.invoke
.v
->has_single_expr()) return false;
4607 for (size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++)
4608 if (!u
.invoke
.ap_list
->get_par(i
)->has_single_expr()) return false;
4611 return u
.templates
->get_nof_ts() == 0;
4612 case NAMED_TEMPLATE_LIST
: {
4613 if (!my_governor
) FATAL_ERROR("Template::has_single_expr()");
4614 Type
*type
= my_governor
->get_type_refd_last();
4615 return type
->get_nof_comps() == 0; }
4616 case INDEXED_TEMPLATE_LIST
:
4617 return u
.indexed_templates
->get_nof_its() == 0;
4619 case COMPLEMENTED_LIST
:
4621 case SUPERSET_MATCH
:
4623 case PERMUTATION_MATCH
:
4626 case VALUE_LIST_ALL_FROM
:
4629 FATAL_ERROR("Template::has_single_expr()");
4634 string
Template::get_single_expr(bool cast_needed
)
4636 if (cast_needed
&& (length_restriction
|| is_ifpresent
))
4637 FATAL_ERROR("Template::get_single_expr()");
4639 switch (templatetype
) {
4641 ret_val
= "OMIT_VALUE";
4644 ret_val
= "ANY_VALUE";
4647 ret_val
= "ANY_OR_OMIT";
4649 case SPECIFIC_VALUE
:
4650 ret_val
= u
.specific_value
->get_single_expr();
4652 case TEMPLATE_REFD
: {
4653 // convert the reference to a single expression
4654 expression_struct expr
;
4655 Code::init_expr(&expr
);
4656 u
.ref
.ref
->generate_code(&expr
);
4657 if (expr
.preamble
|| expr
.postamble
)
4658 FATAL_ERROR("Template::get_single_expr()");
4659 ret_val
= expr
.expr
;
4660 Code::free_expr(&expr
);
4663 case TEMPLATE_INVOKE
: {
4664 expression_struct expr
;
4665 Code::init_expr(&expr
);
4666 generate_code_expr_invoke(&expr
);
4667 if (expr
.preamble
|| expr
.postamble
)
4668 FATAL_ERROR("Template::get_single_expr()");
4669 ret_val
= expr
.expr
;
4670 Code::free_expr(&expr
);
4673 if (u
.templates
->get_nof_ts() != 0)
4674 FATAL_ERROR("Template::get_single_expr()");
4675 ret_val
= "NULL_VALUE";
4677 case NAMED_TEMPLATE_LIST
:
4678 if (u
.named_templates
->get_nof_nts() != 0)
4679 FATAL_ERROR("Template::get_single_expr()");
4680 ret_val
= "NULL_VALUE";
4682 case INDEXED_TEMPLATE_LIST
:
4683 if (u
.indexed_templates
->get_nof_its() != 0)
4684 FATAL_ERROR("Template::get_single_expr()");
4685 ret_val
= "NULL_VALUE";
4688 return get_my_scope()->get_scope_mod_gen()
4689 ->add_bitstring_pattern(*u
.pattern
);
4691 return get_my_scope()->get_scope_mod_gen()
4692 ->add_hexstring_pattern(*u
.pattern
);
4694 return get_my_scope()->get_scope_mod_gen()
4695 ->add_octetstring_pattern(*u
.pattern
);
4699 ->create_charstring_literals(get_my_scope()->get_scope_mod_gen());
4701 FATAL_ERROR("Template::get_single_expr()");
4703 if (cast_needed
) ret_val
= my_governor
->get_genname_template(my_scope
) +
4704 "(" + ret_val
+ ")";
4708 void Template::dump(unsigned level
) const
4710 DEBUG(level
, "%s", get_templatetype_str());
4711 switch (templatetype
) {
4712 case TEMPLATE_ERROR
:
4717 case SPECIFIC_VALUE
:
4718 u
.specific_value
->dump(level
+1);
4721 u
.ref
.ref
->dump(level
+1);
4723 case TEMPLATE_INVOKE
:
4724 u
.invoke
.v
->dump(level
+1);
4725 if (u
.invoke
.ap_list
) u
.invoke
.ap_list
->dump(level
+ 1);
4726 else if (u
.invoke
.t_list
) u
.invoke
.t_list
->dump(level
+ 1);
4730 case COMPLEMENTED_LIST
:
4731 case SUPERSET_MATCH
:
4733 case PERMUTATION_MATCH
:
4734 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
4735 u
.templates
->get_t_byIndex(i
)->dump(level
+1);
4737 case NAMED_TEMPLATE_LIST
:
4738 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
4739 u
.named_templates
->get_nt_byIndex(i
)->dump(level
+1);
4741 case INDEXED_TEMPLATE_LIST
:
4742 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
4743 u
.indexed_templates
->get_it_byIndex(i
)->dump(level
+1);
4746 u
.value_range
->dump(level
);
4751 DEBUG(level
+1, "%s", u
.pattern
->c_str());
4755 u
.pstring
->dump(level
+1);
4758 case VALUE_LIST_ALL_FROM
:
4759 u
.all_from
->dump(level
+1);
4764 if (length_restriction
) length_restriction
->dump(level
+ 1);
4767 bool Template::has_allfrom() const
4768 { // the code generation of all from is not fully implemented. This helps avoid of using it.
4769 if (templatetype
!= TEMPLATE_LIST
) FATAL_ERROR("has_allfrom(): Templatetype shall be TEMPLATE_LIST");
4770 size_t nof_ts
= u
.templates
->get_nof_ts();
4771 for (size_t i
= 0; i
< nof_ts
; i
++) {
4772 if (u
.templates
->get_t_byIndex(i
)->templatetype
== ALL_FROM
) {
4779 // =================================
4780 // ===== TemplateInstance
4781 // =================================
4783 TemplateInstance::TemplateInstance(const TemplateInstance
& p
)
4784 : Node(p
), Location(p
)
4786 type
= p
.type
? p
.type
->clone() : 0;
4787 derived_reference
= p
.derived_reference
? p
.derived_reference
->clone() : 0;
4788 template_body
= p
.template_body
->clone();
4791 TemplateInstance::TemplateInstance(Type
*p_type
, Ref_base
*p_ref
,
4792 Template
*p_body
) : Node(), Location(), type(p_type
),
4793 derived_reference(p_ref
), template_body(p_body
)
4795 if (!p_body
) FATAL_ERROR("TemplateInstance::TemplateInstance()");
4796 if (type
) type
->set_ownertype(Type::OT_TEMPLATE_INST
, this);
4799 TemplateInstance::~TemplateInstance()
4802 delete derived_reference
;
4803 delete template_body
;
4806 void TemplateInstance::release()
4809 derived_reference
= 0;
4813 TemplateInstance
*TemplateInstance::clone() const
4815 return new TemplateInstance(*this);
4818 void TemplateInstance::set_fullname(const string
& p_fullname
)
4820 Node::set_fullname(p_fullname
);
4821 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
4822 if (derived_reference
)
4823 derived_reference
->set_fullname(p_fullname
+ ".<derived_reference>");
4824 template_body
->set_fullname(p_fullname
);
4827 void TemplateInstance::set_my_scope(Scope
*p_scope
)
4829 if (type
) type
->set_my_scope(p_scope
);
4830 if (derived_reference
) derived_reference
->set_my_scope(p_scope
);
4831 template_body
->set_my_scope(p_scope
);
4834 Type::typetype_t
TemplateInstance::get_expr_returntype
4835 (Type::expected_value_t exp_val
)
4837 Type
*t
= get_expr_governor(exp_val
);
4838 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
4839 else return template_body
->get_expr_returntype(exp_val
);
4842 Type
*TemplateInstance::get_expr_governor(Type::expected_value_t exp_val
)
4844 if (type
) return type
;
4845 if (derived_reference
) {
4846 Type
*ret_val
= chk_DerivedRef(0);
4847 if (ret_val
) return ret_val
;
4849 return template_body
->get_expr_governor(exp_val
);
4852 void TemplateInstance::chk(Type
*governor
)
4854 if (!governor
) FATAL_ERROR("TemplateInstance::chk()");
4855 governor
= chk_Type(governor
);
4856 governor
= chk_DerivedRef(governor
);
4857 template_body
->set_my_governor(governor
);
4858 governor
->chk_this_template_ref(template_body
);
4859 governor
->chk_this_template_generic(template_body
,
4860 (derived_reference
!= 0 ? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
4861 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
4864 Type
*TemplateInstance::chk_Type(Type
*governor
)
4866 if (!type
) return governor
;
4868 Error_Context
cntxt(type
, "In explicit type specification");
4871 TypeCompatInfo
info(template_body
->get_template_refd_last()
4872 ->get_my_scope()->get_scope_mod(), governor
, type
,
4876 if (!governor
) return type
;
4877 else if (governor
->is_compatible(type
, &info
, &l_chain
, &r_chain
, true)) {
4880 if (info
.is_subtype_error()) {
4881 type
->error("%s", info
.get_subtype_error().c_str());
4883 if (!info
.is_erroneous()) {
4884 type
->error("Incompatible explicit type specification: `%s' was "
4885 "expected instead of `%s'",
4886 governor
->get_typename().c_str(),
4887 type
->get_typename().c_str());
4889 type
->error("%s", info
.get_error_str_str().c_str());
4895 Type
*TemplateInstance::chk_DerivedRef(Type
*governor
)
4897 if (!derived_reference
) return governor
;
4898 Error_Context
cntxt(derived_reference
, "In derived reference");
4899 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4900 // the base template reference must not have sub-references
4901 if (derived_reference
->get_subrefs())
4902 FATAL_ERROR("TemplateInstance::chk_DerivedRef()");
4903 bool set_bt
= false;
4904 if (!ass
) goto error
;
4905 switch (ass
->get_asstype()) {
4906 case Common::Assignment::A_TEMPLATE
:
4909 case Common::Assignment::A_MODULEPAR_TEMP
:
4910 case Common::Assignment::A_VAR_TEMPLATE
:
4911 case Common::Assignment::A_PAR_TEMPL_IN
:
4912 case Common::Assignment::A_PAR_TEMPL_OUT
:
4913 case Common::Assignment::A_PAR_TEMPL_INOUT
:
4914 case Common::Assignment::A_FUNCTION_RTEMP
:
4915 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: {
4916 if (!governor
) governor
= type
;
4917 Type
*base_template_type
= ass
->get_Type();
4919 TypeCompatInfo
info(template_body
->get_template_refd_last()
4920 ->get_my_scope()->get_scope_mod(), governor
, type
,
4924 if (!governor
->is_compatible(base_template_type
, &info
, &l_chain
,
4926 if (info
.is_subtype_error()) {
4927 derived_reference
->error("%s", info
.get_subtype_error().c_str());
4929 if (!info
.is_erroneous()) {
4930 derived_reference
->error("Base template `%s' has incompatible "
4931 "type: `%s' was expected instead of `%s'",
4932 ass
->get_fullname().c_str(),
4933 governor
->get_typename().c_str(),
4934 base_template_type
->get_typename().c_str());
4936 derived_reference
->error("%s", info
.get_error_str_str().c_str());
4938 // if explicit type specification is omitted
4939 // check the template body against the type of the base template
4940 if (!type
) governor
= base_template_type
;
4943 if (info
.needs_conversion())
4944 template_body
->set_needs_conversion();
4946 } else governor
= base_template_type
;
4949 derived_reference
->error("Reference to a template was expected instead "
4950 "of %s", ass
->get_description().c_str());
4953 if (set_bt
) template_body
->set_base_template(ass
->get_Template());
4956 // drop the erroneous derived_reference to avoid further errors
4957 delete derived_reference
;
4958 derived_reference
= 0;
4962 void TemplateInstance::chk_recursions(ReferenceChain
& refch
)
4964 template_body
->chk_recursions(refch
);
4967 bool TemplateInstance::is_string_type(Type::expected_value_t exp_val
)
4969 switch (get_expr_returntype(exp_val
)) {
4981 bool TemplateInstance::chk_restriction(const char* definition_name
,
4982 template_restriction_t template_restriction
, const Location
* usage_loc
)
4984 bool needs_runtime_check
= false;
4985 if (derived_reference
) // if modified
4987 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4988 switch (ass
->get_asstype()) {
4989 case Common::Assignment::A_TEMPLATE
:
4990 // already added to template_body as base template by chk_DerivedRef()
4991 needs_runtime_check
= template_body
->chk_restriction(
4992 definition_name
, template_restriction
, usage_loc
);
4994 case Common::Assignment::A_MODULEPAR_TEMP
:
4995 case Common::Assignment::A_VAR_TEMPLATE
:
4996 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
4997 case Common::Assignment::A_FUNCTION_RTEMP
:
4998 case Common::Assignment::A_PAR_TEMPL_IN
:
4999 case Common::Assignment::A_PAR_TEMPL_OUT
:
5000 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
5001 // create a temporary Template to be added as the base template and
5002 // check, remove and delete after checked
5003 if (template_body
->get_base_template())
5004 FATAL_ERROR("TemplateInstance::chk_restriction()");
5005 template_body
->set_base_template(new Template(derived_reference
));
5006 needs_runtime_check
= template_body
->chk_restriction(
5007 definition_name
, template_restriction
, usage_loc
);
5008 delete template_body
->get_base_template();
5009 template_body
->set_base_template(0);
5015 needs_runtime_check
= template_body
->chk_restriction(definition_name
,
5016 template_restriction
, usage_loc
);
5018 return needs_runtime_check
;
5021 bool TemplateInstance::has_single_expr()
5023 if (derived_reference
) return false;
5024 else if (type
) return false;
5025 else return template_body
->has_single_expr();
5028 void TemplateInstance::set_code_section(
5029 GovernedSimple::code_section_t p_code_section
)
5031 if (derived_reference
) derived_reference
->set_code_section(p_code_section
);
5032 template_body
->set_code_section(p_code_section
);
5035 bool TemplateInstance::needs_temp_ref()
5037 if (template_body
->get_templatetype() != Template::SPECIFIC_VALUE
)
5039 Value
*val
= template_body
->get_specific_value();
5040 if (val
->get_valuetype() == Value::V_REFD
) {
5041 FieldOrArrayRefs
*refs
= val
->get_reference()->get_subrefs();
5042 if (!refs
) return false;
5043 // We need at least a 2-long reference chain. E.g. "a[0].b". 3.0.4
5044 // can't handle a normal reference following an indexed reference. The
5045 // indexed reference must be on the first place. Code like: "a.b[0].c"
5047 if (refs
->get_nof_refs() < 2
5048 || refs
->get_ref(0)->get_type() != FieldOrArrayRef::ARRAY_REF
)
5056 void TemplateInstance::generate_code(expression_struct
*expr
,
5057 template_restriction_t template_restriction
)
5059 if (derived_reference
) {
5060 // preserve the target expression
5061 char *expr_backup
= expr
->expr
;
5062 // reset the space for the target expression
5064 derived_reference
->generate_code(expr
);
5065 // now the C++ equivalent of the base template reference is in expr->expr
5066 const string
& tmp_id
= template_body
->get_temporary_id();
5067 const char *tmp_id_str
= tmp_id
.c_str();
5068 // create a temporary variable and copy the contents of base template
5070 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s(%s);\n",
5071 template_body
->get_my_governor()->get_genname_template(
5072 template_body
->get_my_scope()).c_str(), tmp_id_str
, expr
->expr
);
5073 // perform the modifications on the temporary variable
5074 expr
->preamble
= template_body
->generate_code_init(expr
->preamble
,
5076 // runtime template restriction check
5077 if (template_restriction
!=TR_NONE
)
5078 expr
->preamble
= Template::generate_restriction_check_code(
5079 expr
->preamble
, tmp_id_str
, template_restriction
);
5080 // the base template reference is no longer needed
5082 // restore the target expression append the name of the temporary
5084 expr
->expr
= mputstr(expr_backup
, tmp_id_str
);
5085 } else template_body
->generate_code_expr(expr
, template_restriction
);
5088 char *TemplateInstance::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
5090 if (derived_reference
) {
5091 ActualParList
*actual_parlist
= derived_reference
->get_parlist();
5092 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
5093 if (!ass
) FATAL_ERROR("TemplateInstance::rearrange_init_code()");
5094 if (actual_parlist
) str
= actual_parlist
->rearrange_init_code(str
, usage_mod
);
5095 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
5096 Template
*t
= ass
->get_Template();
5097 FormalParList
*formal_parlist
= ass
->get_FormalParList();
5098 if (formal_parlist
) {
5099 // the referred template is parameterized
5100 // the embedded referenced templates shall be visited
5101 str
= t
->rearrange_init_code(str
, usage_mod
);
5102 // the constants used for default values have to be initialized now
5103 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
5104 str
= formal_parlist
->generate_code_defval(str
);
5107 // the referred template is not parameterized
5108 // its entire body has to be initialized now
5109 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
5110 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
5115 str
= template_body
->rearrange_init_code(str
, usage_mod
);
5119 void TemplateInstance::append_stringRepr(string
& str
) const
5122 str
+= type
->get_typename();
5125 if (derived_reference
) {
5127 str
+= derived_reference
->get_dispname();
5130 str
+= template_body
->get_stringRepr();
5133 void TemplateInstance::dump(unsigned level
) const
5136 DEBUG(level
, "type:");
5137 type
->dump(level
+ 1);
5139 if (derived_reference
) {
5140 DEBUG(level
, "modifies:");
5141 derived_reference
->dump(level
+ 1);
5143 template_body
->dump(level
);
5146 Value
* TemplateInstance::get_specific_value() const
5148 if (type
) return NULL
;
5149 if (derived_reference
) return NULL
;
5150 if (template_body
->is_length_restricted() || template_body
->get_ifpresent())
5152 if (template_body
->get_templatetype()!=Template::SPECIFIC_VALUE
) return NULL
;
5153 return template_body
->get_specific_value();
5156 Def_Template
* TemplateInstance::get_Referenced_Base_Template()
5157 { // it may return 0
5158 if (!get_Template()) return NULL
;
5159 Ttcn::Template::templatetype_t tpt
= get_Template()->get_templatetype();
5160 if (Ttcn::Template::TEMPLATE_REFD
!= tpt
) return NULL
;
5161 Ttcn::Ref_base
* refbase
= get_Template()->get_reference();
5162 Ttcn::Reference
* ref
= dynamic_cast<Ttcn::Reference
*>(refbase
);
5163 if (!ref
) return NULL
;
5164 Common::Assignment
* ass
= ref
->get_refd_assignment();
5165 Ttcn::Definition
* def
= dynamic_cast<Ttcn::Definition
*>(ass
);
5166 if (!def
) return NULL
;
5167 Ttcn::Def_Template
* deftemp
= dynamic_cast<Ttcn::Def_Template
*>(def
);
5168 if (!deftemp
) return NULL
;