1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "TtcnTemplate.hh"
9 #include "../Identifier.hh"
10 #include "Templatestuff.hh"
12 #include "../TypeCompat.hh"
13 #include "../SigParam.hh"
14 #include "../CompField.hh"
15 #include "../Valuestuff.hh"
16 #include "ArrayDimensions.hh"
17 #include "PatternString.hh"
19 #include "../../common/dbgnew.hh"
20 #include "Attributes.hh"
24 // =================================
26 // =================================
28 Template::Template(const Template
& p
) : GovernedSimple(p
),
29 templatetype(p
.templatetype
), my_governor(p
.my_governor
),
30 is_ifpresent(p
.is_ifpresent
), specific_value_checked(false),
31 has_permutation(p
.has_permutation
), base_template(p
.base_template
)
33 switch (templatetype
) {
35 case TEMPLATE_NOTUSED
:
41 u
.specific_value
= p
.u
.specific_value
->clone();
44 u
.ref
.ref
= p
.u
.ref
.ref
->clone();
49 u
.invoke
.v
= p
.u
.invoke
.v
->clone();
50 u
.invoke
.t_list
= p
.u
.invoke
.t_list
? p
.u
.invoke
.t_list
->clone() : 0;
51 u
.invoke
.ap_list
= p
.u
.invoke
.ap_list
? p
.u
.invoke
.ap_list
->clone() : 0;
54 case VALUE_LIST_ALL_FROM
:
55 u
.all_from
= p
.u
.all_from
->clone();
59 case COMPLEMENTED_LIST
:
62 case PERMUTATION_MATCH
:
63 u
.templates
= p
.u
.templates
->clone(); // FATAL_ERROR
65 case NAMED_TEMPLATE_LIST
:
66 u
.named_templates
= p
.u
.named_templates
->clone();
68 case INDEXED_TEMPLATE_LIST
:
69 u
.indexed_templates
= p
.u
.indexed_templates
->clone();
72 u
.value_range
= p
.u
.value_range
->clone();
77 u
.pattern
= new string(*p
.u
.pattern
);
81 u
.pstring
= p
.u
.pstring
->clone();
84 // FATAL_ERROR("Template::Template()");
87 p
.length_restriction
? p
.length_restriction
->clone() : 0; // FATAL_ERR
90 void Template::clean_up()
92 switch(templatetype
) {
94 case TEMPLATE_NOTUSED
:
100 delete u
.specific_value
;
105 case TEMPLATE_INVOKE
:
107 delete u
.invoke
.t_list
;
108 delete u
.invoke
.ap_list
;
112 case COMPLEMENTED_LIST
:
115 case PERMUTATION_MATCH
:
119 case VALUE_LIST_ALL_FROM
:
122 case NAMED_TEMPLATE_LIST
:
123 delete u
.named_templates
;
125 case INDEXED_TEMPLATE_LIST
:
126 delete u
.indexed_templates
;
129 delete u
.value_range
;
141 // FATAL_ERROR("Template::clean_up()");
145 string
Template::create_stringRepr()
148 switch (templatetype
) {
150 ret_val
+= "<erroneous template>";
152 case TEMPLATE_NOTUSED
:
165 ret_val
+= u
.specific_value
->get_stringRepr();
167 case TEMPLATE_REFD
: {
168 Template
*t_last
= get_template_refd_last();
169 if (t_last
->templatetype
== TEMPLATE_REFD
)
170 ret_val
+= u
.ref
.ref
->get_dispname();
171 else ret_val
+= t_last
->get_stringRepr();
173 case TEMPLATE_INVOKE
: {
174 ret_val
+= u
.invoke
.v
->get_stringRepr();
175 ret_val
+= ".invoke(";
177 for(size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++) {
178 if(i
>0) ret_val
+= ", ";
179 ret_val
+= u
.invoke
.ap_list
->get_par(i
)->get_fullname();
184 if (u
.templates
->get_nof_ts() > 0) {
186 u
.templates
->append_stringRepr(ret_val
);
188 } else ret_val
+= "{ }";
190 case NAMED_TEMPLATE_LIST
:
192 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++) {
193 if (i
> 0) ret_val
+= ", ";
195 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
196 ret_val
+= nt
->get_name().get_dispname();
198 ret_val
+= nt
->get_template()->get_stringRepr();
202 case INDEXED_TEMPLATE_LIST
:
204 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
205 if (i
> 0) ret_val
+= ", ";
206 else ret_val
+= " [";
207 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
208 (it
->get_index()).append_stringRepr(ret_val
);
210 ret_val
+= it
->get_template()->get_stringRepr();
216 u
.templates
->append_stringRepr(ret_val
);
219 case COMPLEMENTED_LIST
:
220 ret_val
+= "complement(";
221 u
.templates
->append_stringRepr(ret_val
);
225 u
.value_range
->append_stringRepr(ret_val
);
228 ret_val
+= "superset(";
229 u
.templates
->append_stringRepr(ret_val
);
233 ret_val
+= "subset(";
234 u
.templates
->append_stringRepr(ret_val
);
237 case PERMUTATION_MATCH
:
238 ret_val
+= "permutation(";
239 u
.templates
->append_stringRepr(ret_val
);
244 ret_val
+= *u
.pattern
;
249 ret_val
+= *u
.pattern
;
254 ret_val
+= *u
.pattern
;
259 ret_val
+= "pattern \"";
260 ret_val
+= u
.pstring
->get_full_str();
264 ret_val
+= "<unknown template>";
267 if (length_restriction
) length_restriction
->append_stringRepr(ret_val
);
268 if (is_ifpresent
) ret_val
+= " ifpresent";
272 Template::Template(templatetype_t tt
)
273 : GovernedSimple(S_TEMPLATE
),
274 templatetype(tt
), my_governor(0), length_restriction(0),
275 is_ifpresent(false), specific_value_checked(false),
276 has_permutation(false), flattened(true), base_template(0)
280 case TEMPLATE_NOTUSED
:
286 FATAL_ERROR("Template::Template()");
290 Template::Template(Value
*v
)
291 : GovernedSimple(S_TEMPLATE
),
292 templatetype(SPECIFIC_VALUE
), my_governor(0), length_restriction(0),
293 is_ifpresent(false), specific_value_checked(false),
294 has_permutation(false), flattened(true), base_template(0)
296 if (!v
) FATAL_ERROR("Template::Template()");
297 u
.specific_value
= v
;
300 Template::Template(Ref_base
*p_ref
)
301 : GovernedSimple(S_TEMPLATE
),
302 templatetype(TEMPLATE_REFD
), my_governor(0), length_restriction(0),
303 is_ifpresent(false), specific_value_checked(false),
304 has_permutation(false), base_template(0)
306 if(!p_ref
) FATAL_ERROR("Template::Template()");
312 Template::Template(templatetype_t tt
, Templates
*ts
)
313 : GovernedSimple(S_TEMPLATE
),
314 templatetype(tt
), my_governor(0), length_restriction(0),
315 is_ifpresent(false), specific_value_checked(false),
316 has_permutation(false), flattened(true), base_template(0)
321 case COMPLEMENTED_LIST
:
324 case PERMUTATION_MATCH
:
327 FATAL_ERROR("Template::Template()");
329 if (!ts
) FATAL_ERROR("Template::Template()");
331 if (tt
== TEMPLATE_LIST
) {
332 size_t nof_ts
= ts
->get_nof_ts();
333 for (size_t i
= 0; i
< nof_ts
; i
++) {
334 if (ts
->get_t_byIndex(i
)->templatetype
== PERMUTATION_MATCH
) {
335 has_permutation
= true;
342 Template::Template(Template
*t
)
343 : GovernedSimple(S_TEMPLATE
)
344 , templatetype(ALL_FROM
), my_governor(0), length_restriction(0)
345 , is_ifpresent(false), specific_value_checked(false)
346 , has_permutation(false), flattened(true), base_template(0)
349 // t is usually a SPECIFIC_VALUE
350 // t->u.specific_value is a V_UNDEF_LOWERID
351 // calling set_lowerid_to_ref is too soon (my_scope is not set yet)
354 Template::Template(templatetype_t tt
, Template
*t
)
355 : GovernedSimple(S_TEMPLATE
)
356 , templatetype(VALUE_LIST_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)
360 if (tt
!= VALUE_LIST_ALL_FROM
) FATAL_ERROR("Template::Template()");
361 u
.all_from
= t
->u
.all_from
; // take it over
362 t
->u
.all_from
= NULL
;
366 Template::Template(NamedTemplates
*nts
)
367 : GovernedSimple(S_TEMPLATE
),
368 templatetype(NAMED_TEMPLATE_LIST
), 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 (!nts
) FATAL_ERROR("Template::Template()");
373 u
.named_templates
= nts
;
376 Template::Template(IndexedTemplates
*its
)
377 : GovernedSimple(S_TEMPLATE
),
378 templatetype(INDEXED_TEMPLATE_LIST
), my_governor(0),
379 length_restriction(0), is_ifpresent(false),
380 specific_value_checked(false), has_permutation(false), flattened(true),
383 if (!its
) FATAL_ERROR("Template::Template()");
384 u
.indexed_templates
= its
;
385 size_t nof_its
= its
->get_nof_its();
386 for (size_t i
= 0; i
< nof_its
; i
++) {
387 if (its
->get_it_byIndex(i
)->get_template()->templatetype
==
389 has_permutation
= true;
395 Template::Template(ValueRange
*vr
)
396 : GovernedSimple(S_TEMPLATE
),
397 templatetype(VALUE_RANGE
), my_governor(0), length_restriction(0),
398 is_ifpresent(false), specific_value_checked(false),
399 has_permutation(false), flattened(true), base_template(0)
401 if (!vr
) FATAL_ERROR("Template::Template()");
405 Template::Template(templatetype_t tt
, string
*p_patt
)
406 : GovernedSimple(S_TEMPLATE
),
407 templatetype(tt
), my_governor(0), length_restriction(0),
408 is_ifpresent(false), specific_value_checked(false),
409 has_permutation(false), flattened(true), base_template(0)
417 FATAL_ERROR("Template::Template()");
419 if (!p_patt
) FATAL_ERROR("Template::Template()");
423 Template::Template(PatternString
*p_ps
)
424 : GovernedSimple(S_TEMPLATE
),
425 templatetype(CSTR_PATTERN
), my_governor(0), length_restriction(0),
426 is_ifpresent(false), specific_value_checked(false),
427 has_permutation(false), flattened(true), base_template(0)
429 if (!p_ps
) FATAL_ERROR("Template::Template()");
433 Template::~Template()
436 delete length_restriction
;
439 Template
*Template::clone() const
441 return new Template(*this);
444 void Template::set_fullname(const string
& p_fullname
)
446 GovernedSimple::set_fullname(p_fullname
);
447 switch (templatetype
) {
449 case TEMPLATE_NOTUSED
:
458 u
.specific_value
->set_fullname(p_fullname
);
461 u
.ref
.ref
->set_fullname(p_fullname
);
463 case TEMPLATE_INVOKE
:
464 u
.invoke
.v
->set_fullname(p_fullname
);
465 if(u
.invoke
.t_list
) u
.invoke
.t_list
->set_fullname(p_fullname
);
466 if(u
.invoke
.ap_list
) u
.invoke
.ap_list
->set_fullname(p_fullname
);
469 u
.templates
->set_fullname(p_fullname
);
470 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
471 u
.templates
->get_t_byIndex(i
)->set_fullname(
472 p_fullname
+ "[" + Int2string(i
) + "]");
474 case INDEXED_TEMPLATE_LIST
:
475 u
.indexed_templates
->set_fullname(p_fullname
);
476 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
477 u
.indexed_templates
->get_it_byIndex(i
)->set_fullname(
478 p_fullname
+ "[" + Int2string(i
) + "]");
480 case NAMED_TEMPLATE_LIST
:
481 u
.named_templates
->set_fullname(p_fullname
);
484 case VALUE_LIST_ALL_FROM
:
485 u
.all_from
->set_fullname(p_fullname
);
488 case COMPLEMENTED_LIST
:
491 case PERMUTATION_MATCH
:
492 u
.templates
->set_fullname(p_fullname
);
493 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
494 u
.templates
->get_t_byIndex(i
)->set_fullname(
495 p_fullname
+ ".list_item(" + Int2string(i
) + ")");
498 u
.value_range
->set_fullname(p_fullname
);
502 u
.pstring
->set_fullname(p_fullname
);
505 // FATAL_ERROR("Template::set_fullname()");
507 if (length_restriction
)
508 length_restriction
->set_fullname(p_fullname
+ ".<length_restriction>");
511 void Template::set_my_scope(Scope
*p_scope
)
513 GovernedSimple::set_my_scope(p_scope
);
514 switch (templatetype
) {
516 case TEMPLATE_NOTUSED
:
525 u
.specific_value
->set_my_scope(p_scope
);
528 u
.ref
.ref
->set_my_scope(p_scope
);
530 case TEMPLATE_INVOKE
:
531 u
.invoke
.v
->set_my_scope(p_scope
);
532 if(u
.invoke
.t_list
) u
.invoke
.t_list
->set_my_scope(p_scope
);
533 if(u
.invoke
.ap_list
) u
.invoke
.ap_list
->set_my_scope(p_scope
);
536 case VALUE_LIST_ALL_FROM
:
537 u
.all_from
->set_my_scope(p_scope
);
541 case COMPLEMENTED_LIST
:
544 case PERMUTATION_MATCH
:
545 u
.templates
->set_my_scope(p_scope
);
547 case NAMED_TEMPLATE_LIST
:
548 u
.named_templates
->set_my_scope(p_scope
);
550 case INDEXED_TEMPLATE_LIST
:
551 u
.indexed_templates
->set_my_scope(p_scope
);
554 u
.value_range
->set_my_scope(p_scope
);
558 u
.pstring
->set_my_scope(p_scope
);
561 // FATAL_ERROR("Template::set_my_scope()");
563 if (length_restriction
) length_restriction
->set_my_scope(p_scope
);
566 void Template::set_genname_recursive(const string
& p_genname
)
568 set_genname(p_genname
);
569 switch (templatetype
) {
570 case TEMPLATE_LIST
: {
571 if (!my_governor
) return; // error recovery
572 Type
*type
= my_governor
->get_type_refd_last();
574 if (type
->get_typetype() == Type::T_ARRAY
)
575 offset
= type
->get_dimension()->get_offset();
577 size_t nof_ts
= u
.templates
->get_nof_ts();
578 for (size_t i
= 0; i
< nof_ts
; i
++) {
579 string
embedded_genname(p_genname
);
580 embedded_genname
+= '[';
581 embedded_genname
+= Int2string(offset
+ i
);
582 embedded_genname
+= ']';
583 u
.templates
->get_t_byIndex(i
)->set_genname_recursive(embedded_genname
);
586 case NAMED_TEMPLATE_LIST
: {
587 if (!my_governor
) return; // error recovery
588 Type
*type
= my_governor
->get_type_refd_last();
589 size_t nof_nts
= u
.named_templates
->get_nof_nts();
590 for (size_t i
= 0; i
< nof_nts
; i
++) {
591 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
592 string
embedded_genname(p_genname
);
593 embedded_genname
+= '.';
594 if (type
->get_typetype() == Type::T_ANYTYPE
)
595 embedded_genname
+= "AT_";
596 embedded_genname
+= nt
->get_name().get_name();
597 embedded_genname
+= "()";
598 nt
->get_template()->set_genname_recursive(embedded_genname
);
606 void Template::set_genname_prefix(const char *p_genname_prefix
)
608 GovernedSimple::set_genname_prefix(p_genname_prefix
);
609 switch (templatetype
) {
611 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
612 u
.templates
->get_t_byIndex(i
)->set_genname_prefix(p_genname_prefix
);
614 case NAMED_TEMPLATE_LIST
:
615 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
616 u
.named_templates
->get_nt_byIndex(i
)->get_template()
617 ->set_genname_prefix(p_genname_prefix
);
619 case INDEXED_TEMPLATE_LIST
:
620 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
621 u
.indexed_templates
->get_it_byIndex(i
)->get_template()
622 ->set_genname_prefix(p_genname_prefix
);
629 void Template::set_code_section(code_section_t p_code_section
)
631 GovernedSimple::set_code_section(p_code_section
);
632 switch (templatetype
) {
634 u
.specific_value
->set_code_section(p_code_section
);
637 u
.ref
.ref
->set_code_section(p_code_section
);
639 case TEMPLATE_INVOKE
:
640 u
.invoke
.v
->set_code_section(p_code_section
);
641 if(u
.invoke
.t_list
) u
.invoke
.t_list
->set_code_section(p_code_section
);
643 for(size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++)
644 u
.invoke
.ap_list
->get_par(i
)->set_code_section(p_code_section
);
648 case COMPLEMENTED_LIST
:
651 case PERMUTATION_MATCH
:
652 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
653 u
.templates
->get_t_byIndex(i
)->set_code_section(p_code_section
);
655 case NAMED_TEMPLATE_LIST
:
656 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
657 u
.named_templates
->get_nt_byIndex(i
)->get_template()
658 ->set_code_section(p_code_section
);
660 case INDEXED_TEMPLATE_LIST
:
661 for (size_t i
= 0; i
<u
.indexed_templates
->get_nof_its(); i
++)
662 u
.indexed_templates
->get_it_byIndex(i
)
663 ->set_code_section(p_code_section
);
666 u
.value_range
->set_code_section(p_code_section
);
670 u
.pstring
->set_code_section(p_code_section
);
675 if (length_restriction
)
676 length_restriction
->set_code_section(p_code_section
);
679 void Template::set_templatetype(templatetype_t p_templatetype
)
681 if (p_templatetype
== templatetype
) return;
682 if (p_templatetype
== TEMPLATE_ERROR
) {
684 templatetype
= TEMPLATE_ERROR
;
687 switch (templatetype
) {
688 case SPECIFIC_VALUE
: // current type
689 switch(p_templatetype
) {
690 case TEMPLATE_REFD
: {
691 Value
*v
= u
.specific_value
;
692 u
.ref
.ref
= v
->steal_ttcn_ref_base();
697 case TEMPLATE_INVOKE
: {
698 Value
*v
= u
.specific_value
;
699 v
->steal_invoke_data(u
.invoke
.v
, u
.invoke
.t_list
, u
.invoke
.ap_list
);
703 FATAL_ERROR("Template::set_templatetype()");
706 case TEMPLATE_LIST
: // current type
707 if (p_templatetype
== NAMED_TEMPLATE_LIST
) {
708 // TEMPLATE_LIST -> NAMED_TEMPLATE_LIST:
709 // value list -> assignment notation
710 // applicable to record types, signatures and empty set types
711 if (!my_governor
) FATAL_ERROR("Template::set_templatetype()");
712 Type
*t
= my_governor
->get_type_refd_last();
713 size_t nof_comps
= t
->get_nof_comps(); // "expected" nr of components
714 Templates
*sts
= u
.templates
;
715 size_t nof_temps
= sts
->get_nof_ts(); // "actual" nr in the list
716 Type::typetype_t tt
= t
->get_typetype();
720 case Type::T_SIGNATURE
:
724 if (nof_temps
== 0 && nof_comps
== 0) break;
726 FATAL_ERROR("Template::set_templatetype()");
728 // If it's a record or set template, allow fewer elements than
729 // what is required, because implicit omit may take care of it.
730 // If it's a signature template, be precise.
731 bool allow_fewer
= false;
732 switch (my_governor
->get_typetype()) {
733 case Type::T_SEQ_T
: case Type::T_SET_T
:
734 case Type::T_SEQ_A
: case Type::T_SET_A
:
737 case Type::T_SIGNATURE
: // be precise
739 default: // not possible, fatal error ?
742 if ( nof_temps
> nof_comps
743 || (!allow_fewer
&& (nof_temps
< nof_comps
))) {
744 error("Too %s elements in value list notation for type `%s': "
745 "%lu was expected instead of %lu",
746 nof_temps
> nof_comps
? "many" : "few",
747 t
->get_typename().c_str(),
748 (unsigned long) nof_comps
, (unsigned long) nof_temps
);
750 size_t upper_limit
; // min(nof_temps, nof_comps)
752 if (nof_temps
<= nof_comps
) {
753 upper_limit
= nof_temps
;
756 upper_limit
= nof_comps
;
759 u
.named_templates
= new NamedTemplates
;
760 for (size_t i
= 0; i
< upper_limit
; i
++) {
761 Template
*& temp
= sts
->get_t_byIndex(i
);
762 if (temp
->templatetype
== TEMPLATE_NOTUSED
) continue;
764 NamedTemplate
*nt
= new
765 NamedTemplate(t
->get_comp_id_byIndex(i
).clone(), temp
);
766 nt
->set_location(*temp
);
767 u
.named_templates
->add_nt(nt
);
770 u
.named_templates
->set_my_scope(get_my_scope());
771 u
.named_templates
->set_fullname(get_fullname());
773 if (all_notused
&& nof_temps
> 0 && tt
!= Type::T_SIGNATURE
)
774 warning("All elements of value list notation for type `%s' are "
775 "not used symbols (`-')", t
->get_typename().c_str());
776 } else FATAL_ERROR("Template::set_templatetype()");
778 case CSTR_PATTERN
: // current type
779 if (p_templatetype
== USTR_PATTERN
)
780 templatetype
= USTR_PATTERN
;
782 FATAL_ERROR("Template::set_templatetype()");
785 FATAL_ERROR("Template::set_templatetype()");
787 templatetype
= p_templatetype
;
790 const char *Template::get_templatetype_str() const
792 switch(templatetype
) {
794 return "erroneous template";
795 case TEMPLATE_NOTUSED
:
796 return "not used symbol";
802 return "any or omit";
804 return "specific value";
806 return "referenced template";
807 case TEMPLATE_INVOKE
:
808 return "template returning invoke";
810 case VALUE_LIST_ALL_FROM
:
811 return "template with 'all from'";
813 return "value list notation";
814 case NAMED_TEMPLATE_LIST
:
815 return "assignment notation";
816 case INDEXED_TEMPLATE_LIST
:
817 return "assignment notation with array indices";
819 return "value range match";
821 return "value list match";
822 case COMPLEMENTED_LIST
:
823 return "complemented list match";
825 return "superset match";
827 return "subset match";
828 case PERMUTATION_MATCH
:
829 return "permutation match";
831 return "bitstring pattern";
833 return "hexstring pattern";
835 return "octetstring pattern";
837 return "character string pattern";
839 return "universal string pattern";
841 return "unknown template";
845 bool Template::is_undef_lowerid()
847 return templatetype
== SPECIFIC_VALUE
&&
848 u
.specific_value
->is_undef_lowerid();
851 void Template::set_lowerid_to_ref()
853 switch (templatetype
) {
855 u
.specific_value
->set_lowerid_to_ref();
856 if (u
.specific_value
->get_valuetype() == Value::V_REFD
) {
857 Common::Assignment
*t_ass
=
858 u
.specific_value
->get_reference()->get_refd_assignment(false);
860 switch (t_ass
->get_asstype()) {
861 case Common::Assignment::A_MODULEPAR_TEMP
:
862 case Common::Assignment::A_TEMPLATE
:
863 case Common::Assignment::A_VAR_TEMPLATE
:
864 case Common::Assignment::A_PAR_TEMPL_IN
:
865 case Common::Assignment::A_PAR_TEMPL_OUT
:
866 case Common::Assignment::A_PAR_TEMPL_INOUT
:
867 case Common::Assignment::A_FUNCTION_RTEMP
:
868 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
869 set_templatetype(TEMPLATE_REFD
);
873 } else set_templatetype(TEMPLATE_ERROR
);
877 case COMPLEMENTED_LIST
:
878 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
879 u
.templates
->get_t_byIndex(i
)->set_lowerid_to_ref();
882 u
.value_range
->set_lowerid_to_ref();
889 Type::typetype_t
Template::get_expr_returntype(Type::expected_value_t exp_val
)
891 switch (templatetype
) {
893 return Type::T_ERROR
;
895 return u
.specific_value
->get_expr_returntype(exp_val
);
896 case TEMPLATE_REFD
: {
897 Type
*t
= get_expr_governor(exp_val
);
898 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
899 else return Type::T_ERROR
; }
900 case TEMPLATE_INVOKE
: {
901 Type
*t
= get_expr_governor(exp_val
);
902 if(t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
903 else return Type::T_ERROR
; }
905 case COMPLEMENTED_LIST
:
906 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
907 Type::typetype_t tt
= u
.templates
->get_t_byIndex(i
)
908 ->get_expr_returntype(exp_val
);
909 if (tt
!= Type::T_UNDEF
) return tt
;
911 return Type::T_UNDEF
;
913 return u
.value_range
->get_expr_returntype(exp_val
);
916 return Type::T_SETOF
;
928 return Type::T_UNDEF
;
932 Type
*Template::get_expr_governor(Type::expected_value_t exp_val
)
934 if (my_governor
) return my_governor
;
935 switch (templatetype
) {
937 return u
.specific_value
->get_expr_governor(exp_val
);
939 case COMPLEMENTED_LIST
:
940 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
941 Type
*t
= u
.templates
->get_t_byIndex(i
)->get_expr_governor(exp_val
);
946 return u
.value_range
->get_expr_governor(exp_val
);
947 case TEMPLATE_REFD
: {
948 Type
*t
= u
.ref
.ref
->get_refd_assignment()->get_Type()
949 ->get_field_type(u
.ref
.ref
->get_subrefs(), exp_val
);
950 if (!t
) set_templatetype(TEMPLATE_ERROR
);
953 case TEMPLATE_INVOKE
: {
954 Type
*t
= u
.invoke
.v
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
956 if(u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
957 u
.invoke
.v
->error("A value of type function expected");
960 t
= t
->get_type_refd_last();
961 switch(t
->get_typetype()) {
962 case Type::T_FUNCTION
:
963 if(exp_val
==Type::EXPECTED_DYNAMIC_VALUE
&& t
->get_returns_template()){
964 error("Reference to a value was expected instead of a "
965 "template of type `%s'"
966 , t
->get_function_return_type()->get_typename().c_str());
969 return t
->get_function_return_type();
970 case Type::T_ALTSTEP
:
973 u
.invoke
.v
->error("A value of type function expected instead of `%s'",
974 t
->get_typename().c_str());
979 return Type::get_pooltype(get_expr_returntype(exp_val
));
982 set_templatetype(TEMPLATE_ERROR
);
986 void Template::set_my_governor(Type
*p_gov
)
989 FATAL_ERROR("Template::set_my_governor(): NULL parameter");
993 Type
*Template::get_my_governor() const
998 void Template::set_length_restriction(LengthRestriction
*p_lr
)
1000 if (length_restriction
) FATAL_ERROR("Template::set_length_restriction()");
1001 length_restriction
= p_lr
;
1004 Template::completeness_t
1005 Template::get_completeness_condition_seof(bool incomplete_allowed
)
1007 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1008 else if (!base_template
) return C_MAY_INCOMPLETE
;
1010 Template
*t
= base_template
->get_template_refd_last();
1011 switch (t
->templatetype
) {
1012 // partial overwriting is allowed
1013 case TEMPLATE_ERROR
: // to suppress more errors
1014 case TEMPLATE_NOTUSED
: // modifying a modified template
1015 case ANY_VALUE
: // in case of ?
1016 case ANY_OR_OMIT
: // in case of *
1017 case TEMPLATE_REFD
: // e.g. the actual value of a formal parameter
1018 case TEMPLATE_INVOKE
:
1019 case NAMED_TEMPLATE_LIST
: // t is erroneous
1020 case INDEXED_TEMPLATE_LIST
:
1021 return C_MAY_INCOMPLETE
;
1023 switch (my_governor
->get_type_refd_last()->get_typetype()) {
1026 // only the first elements can be incomplete
1029 // we are in error recovery
1030 return C_MAY_INCOMPLETE
;
1032 break; // should not get here
1034 // partial overwriting is not allowed for literal specific values,
1035 // matching ranges/lists/sets and patterns
1036 return C_MUST_COMPLETE
;
1041 Template::completeness_t
Template::get_completeness_condition_choice
1042 (bool incomplete_allowed
, const Identifier
& p_fieldname
)
1044 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1045 else if (!base_template
) return C_MAY_INCOMPLETE
;
1047 Template
*t
= base_template
->get_template_refd_last();
1048 switch (t
->templatetype
) {
1049 // partial overwriting is allowed
1050 case TEMPLATE_ERROR
: // to suppress more errors
1051 case TEMPLATE_NOTUSED
: // t is erroneous
1052 case ANY_VALUE
: // in case of ?
1053 case ANY_OR_OMIT
: // in case of *
1054 case TEMPLATE_REFD
: // e.g. the actual value of a formal parameter
1055 case TEMPLATE_INVOKE
:
1056 case TEMPLATE_LIST
: // t is erroneous
1057 return C_MAY_INCOMPLETE
;
1058 case NAMED_TEMPLATE_LIST
: // some fields may be missing
1059 if (t
->u
.named_templates
->has_nt_withName(p_fieldname
))
1060 return C_MAY_INCOMPLETE
;
1061 else return C_MUST_COMPLETE
;
1063 // partial overwriting is not allowed for literal specific values,
1064 // matching ranges/lists/sets and patterns
1065 return C_MUST_COMPLETE
;
1070 void Template::add_named_temp(NamedTemplate
* nt
) {
1071 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1072 FATAL_ERROR("Template::add_named_temp()");
1073 u
.named_templates
->add_nt(nt
);
1076 Value
*Template::get_specific_value() const
1078 if (templatetype
!= SPECIFIC_VALUE
)
1079 FATAL_ERROR("Template::get_specific_value()");
1080 return u
.specific_value
;
1083 Ref_base
*Template::get_reference() const
1085 if (templatetype
!= TEMPLATE_REFD
)
1086 FATAL_ERROR("Template::get_reference()");
1090 ValueRange
*Template::get_value_range() const
1092 if (templatetype
!= VALUE_RANGE
)
1093 FATAL_ERROR("Template::get_value_range()");
1094 return u
.value_range
;
1097 PatternString
* Template::get_cstr_pattern() const
1099 if (templatetype
!= CSTR_PATTERN
)
1100 FATAL_ERROR("Template::get_cstr_pattern()");
1104 PatternString
* Template::get_ustr_pattern() const
1106 if (templatetype
!= USTR_PATTERN
)
1107 FATAL_ERROR("Template::get_ustr_pattern()");
1111 size_t Template::get_nof_comps() const
1113 switch (templatetype
) {
1116 case COMPLEMENTED_LIST
:
1117 case SUPERSET_MATCH
:
1119 case PERMUTATION_MATCH
:
1120 return u
.templates
->get_nof_ts();
1121 case NAMED_TEMPLATE_LIST
:
1122 return u
.named_templates
->get_nof_nts();
1123 case INDEXED_TEMPLATE_LIST
:
1124 return u
.indexed_templates
->get_nof_its();
1126 FATAL_ERROR("Template::get_of_comps()");
1131 Template
*Template::get_temp_byIndex(size_t n
) const
1133 switch (templatetype
) {
1136 case COMPLEMENTED_LIST
:
1137 case SUPERSET_MATCH
:
1139 case PERMUTATION_MATCH
:
1140 return u
.templates
->get_t_byIndex(n
);
1142 FATAL_ERROR("Template::get_temp_byIndex()");
1147 IndexedTemplate
*Template::get_indexedtemp_byIndex(size_t n
) const
1149 if (templatetype
!= INDEXED_TEMPLATE_LIST
)
1150 FATAL_ERROR("Template::get_indexedtemp_byIndex()");
1151 return u
.indexed_templates
->get_it_byIndex(n
);
1154 NamedTemplate
*Template::get_namedtemp_byIndex(size_t n
) const
1156 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1157 FATAL_ERROR("Template::get_namedtemp_byIndex()");
1158 return u
.named_templates
->get_nt_byIndex(n
);
1161 Template
*Template::get_all_from() const
1163 if (templatetype
!= ALL_FROM
1164 &&templatetype
!= VALUE_LIST_ALL_FROM
)
1165 FATAL_ERROR("Template::get_all_from()");
1169 // Not applicable to INDEXED_TEMPLATE_LIST nodes. The actual number of
1170 // elements is not known.
1171 size_t Template::get_nof_listitems() const
1173 if (templatetype
!= TEMPLATE_LIST
)
1174 FATAL_ERROR("Template::get_nof_listitems()");
1175 if (has_permutation
) {
1176 size_t nof_ts
= u
.templates
->get_nof_ts(), ret_val
= 0;
1177 for (size_t i
= 0; i
< nof_ts
; i
++) {
1178 Template
*t
= u
.templates
->get_t_byIndex(i
);
1179 if (t
->templatetype
== PERMUTATION_MATCH
)
1180 ret_val
+= t
->u
.templates
->get_nof_ts();
1184 } else return u
.templates
->get_nof_ts();
1187 Template
*Template::get_listitem_byIndex(size_t n
) const
1189 if (templatetype
!= TEMPLATE_LIST
)
1190 FATAL_ERROR("Template::get_listitam_byIndex()");
1191 if (has_permutation
) {
1192 size_t nof_ts
= u
.templates
->get_nof_ts(), index
= 0;
1193 for (size_t i
= 0; i
< nof_ts
; i
++) {
1194 Template
*t
= u
.templates
->get_t_byIndex(i
);
1195 if (t
->templatetype
== PERMUTATION_MATCH
) {
1196 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
1197 if (n
< index
+ nof_perm_ts
)
1198 return t
->u
.templates
->get_t_byIndex(n
- index
);
1199 else index
+= nof_perm_ts
;
1201 if (n
== index
) return t
;
1205 FATAL_ERROR("Template::get_listitem_byIndex(): index overflow");
1207 } else return u
.templates
->get_t_byIndex(n
);
1210 /** \todo revise and merge with get_template_refd() */
1211 Template
* Template::get_template_refd_last(ReferenceChain
*refch
)
1213 // return this for non-referenced templates
1214 if (templatetype
!= TEMPLATE_REFD
) return this;
1215 // use the cached template if present
1216 else if (u
.ref
.refd_last
) return u
.ref
.refd_last
;
1218 Common::Assignment
*t_ass
= u
.ref
.ref
->get_refd_assignment();
1219 // escape from invalid recursion loops
1220 if (templatetype
!= TEMPLATE_REFD
) return this;
1221 if (!t_ass
) FATAL_ERROR("Template::get_template_refd_last()");
1222 if (t_ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) {
1223 // return this if the reference does not point to a template
1224 u
.ref
.refd_last
= this;
1225 return u
.ref
.refd_last
;
1228 // otherwise evaluate the reference
1231 refch
->mark_state();
1232 destroy_refch
= false;
1234 refch
= new ReferenceChain(this, "While searching referenced template");
1235 destroy_refch
= true;
1238 if (refch
->add(get_fullname())) {
1239 Template
*t_refd
= get_template_refd(refch
);
1240 // get_template_refd() may set u.ref.refd_last if there are unfoldable
1241 // sub-references in u.ref.ref
1242 if (!u
.ref
.refd_last
) {
1243 u
.ref
.refd_last
= t_refd
->get_template_refd_last(refch
);
1245 ret_val
= u
.ref
.refd_last
;
1247 // a circular reference was found
1248 set_templatetype(TEMPLATE_ERROR
);
1251 if (destroy_refch
) delete refch
;
1252 else refch
->prev_state();
1256 Template
* Template::get_refd_sub_template(Ttcn::FieldOrArrayRefs
*subrefs
,
1258 ReferenceChain
*refch
)
1260 if (!subrefs
) return this;
1262 for (size_t i
=0; i
<subrefs
->get_nof_refs(); i
++) {
1264 t
=t
->get_template_refd_last(refch
);
1265 t
->set_lowerid_to_ref();
1266 switch(t
->templatetype
) {
1267 case TEMPLATE_ERROR
:
1270 case INDEXED_TEMPLATE_LIST
:
1273 case SPECIFIC_VALUE
:
1274 (void)t
->u
.specific_value
->get_refd_sub_value(
1275 subrefs
, i
, usedInIsbound
, refch
); // only to report errors
1280 Ttcn::FieldOrArrayRef
*ref
=subrefs
->get_ref(i
);
1281 if(ref
->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF
)
1282 t
=t
->get_refd_field_template(*ref
->get_id(), *ref
, usedInIsbound
,
1284 else t
=t
->get_refd_array_template(ref
->get_val(), usedInIsbound
, refch
);
1289 Template
* Template::get_template_refd(ReferenceChain
*refch
)
1291 unsigned int const prev_err_count
= get_error_count();
1292 if (templatetype
!= TEMPLATE_REFD
)
1293 FATAL_ERROR("Template::get_template_refd()");
1294 // use the cached pointer if it is already set
1295 if (u
.ref
.refd
) return u
.ref
.refd
;
1296 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1297 if (!ass
) FATAL_ERROR("Template::get_template_refd()");
1298 if(ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
1299 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
1300 Template
*asst
= ass
->get_Template();
1301 Template
*t
= asst
->get_refd_sub_template(
1302 subrefs
, u
.ref
.ref
->getUsedInIsbound(), refch
);
1305 // Why do we not set u.ref.refd_last ?
1307 else if (subrefs
&& subrefs
->has_unfoldable_index()) {
1308 // some array indices could not be evaluated
1310 u
.ref
.refd_last
= this;
1311 } else if (u
.ref
.ref
->getUsedInIsbound()) {
1313 u
.ref
.refd_last
= this;
1315 // an error was found while resolving sub-references
1316 if (get_error_count() == prev_err_count
) {
1317 // it was not reported, report it now
1318 error("Using a template which refers to a non-template is not supported");
1319 asst
->note("Workaround: change the right hand side refer to a template");
1320 if (ass
->is_local()) {
1321 ass
->note("Workaround: change the template definition "
1322 "to a var template");
1325 set_templatetype(TEMPLATE_ERROR
);
1329 // the reference is unfoldable
1335 Template
* Template::get_refd_field_template(const Identifier
& field_id
,
1336 const Location
& loc
, bool usedInIsbound
, ReferenceChain
*refch
)
1338 switch (templatetype
) {
1343 case COMPLEMENTED_LIST
:
1344 // the above template types are valid matching mechanisms,
1345 // but they cannot be sub-referenced
1346 loc
.error("Reference to field `%s' of %s `%s'",
1347 field_id
.get_dispname().c_str(), get_templatetype_str(),
1348 get_fullname().c_str());
1353 if(!my_governor
) FATAL_ERROR("Template::get_refd_field_template()");
1354 Type
*t
= my_governor
->get_type_refd_last();
1355 const char *typetype_str
="set";
1356 switch(t
->get_typetype()) {
1360 case Type::T_CHOICE_A
:
1361 case Type::T_CHOICE_T
:
1362 case Type::T_OPENTYPE
:
1363 case Type::T_ANYTYPE
:
1364 if (!t
->has_comp_withName(field_id
)) {
1365 loc
.error("Reference to non-existent union field `%s' in type `%s'",
1366 field_id
.get_dispname().c_str(), t
->get_typename().c_str());
1368 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1369 // this is an invalid matching mechanism, the error is already reported
1370 //error("invalid matching mechanism (not template list) but %d", templatetype);
1372 } else if (u
.named_templates
->get_nof_nts() != 1) {
1373 // this is an invalid union template (more than one active field)
1374 // the error is already reported
1375 //error("invalid union template ");
1378 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(0);
1379 if (nt
->get_name() != field_id
) {
1380 if (!usedInIsbound
) {
1381 loc
.error("Reference to inactive field `%s' in a template of"
1382 " union type `%s'. The active field is `%s'.",
1383 field_id
.get_dispname().c_str(),
1384 t
->get_typename().c_str(),
1385 nt
->get_name().get_dispname().c_str());
1390 return nt
->get_template();
1395 typetype_str
="record";
1399 if (!t
->has_comp_withName(field_id
)) {
1400 loc
.error("Reference to non-existent %s field `%s' in type `%s'",
1401 typetype_str
, field_id
.get_dispname().c_str(),
1402 t
->get_typename().c_str());
1404 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1405 // this is an invalid matching mechanism
1406 // the error should be already reported
1408 } else if (u
.named_templates
->has_nt_withName(field_id
)) {
1409 // the field is found, everything is OK
1410 return u
.named_templates
->get_nt_byName(field_id
)->get_template();
1411 } else if (base_template
) {
1412 // take the field from the base template (recursively)
1413 return base_template
->get_template_refd_last(refch
)
1414 ->get_refd_field_template(field_id
, loc
, usedInIsbound
, refch
);
1416 if (!usedInIsbound
) {
1417 // this should not happen unless there is an error
1418 // (e.g. missing field)
1419 loc
.error("Reference to an unbound field `%s'",
1420 field_id
.get_dispname().c_str());
1425 loc
.error("Invalid field reference `%s': type `%s' "
1426 "does not have fields", field_id
.get_dispname().c_str(),
1427 t
->get_typename().c_str());
1432 Template
* Template::get_refd_array_template(Value
*array_index
,
1434 ReferenceChain
*refch
)
1436 switch (templatetype
) {
1441 case COMPLEMENTED_LIST
:
1442 case SUPERSET_MATCH
:
1444 // the above template types are valid matching mechanisms,
1445 // but they cannot be sub-referenced
1446 array_index
->error("Reference with index to an element of %s `%s'",
1447 get_templatetype_str(), get_fullname().c_str());
1452 Value
*v_index
= array_index
->get_value_refd_last(refch
);
1454 bool index_available
= false;
1455 if (!v_index
->is_unfoldable()) {
1456 if (v_index
->get_valuetype() == Value::V_INT
) {
1457 index
= v_index
->get_val_Int()->get_val();
1458 index_available
= true;
1460 array_index
->error("An integer value was expected as index");
1463 if (!my_governor
) FATAL_ERROR("Template::get_refd_array_template()");
1464 Type
*t
= my_governor
->get_type_refd_last();
1465 const char *typetype_str
="set";
1466 switch(t
->get_typetype()) {
1471 typetype_str
="record";
1474 if (index_available
) {
1476 array_index
->error("A non-negative integer value was expected "
1477 "instead of %s for indexing a template of `%s of' type `%s'",
1478 Int2string(index
).c_str(), typetype_str
,
1479 t
->get_typename().c_str());
1481 } else if (templatetype
!= TEMPLATE_LIST
) {
1482 // remain silent the error has been already reported
1485 size_t nof_elements
= get_nof_listitems();
1486 if (index
>= static_cast<Int
>(nof_elements
)) {
1487 array_index
->error("Index overflow in a template of `%s of' type "
1488 "`%s': the index is %s, but the template has only %lu elements",
1489 typetype_str
, t
->get_typename().c_str(),
1490 Int2string(index
).c_str(), (unsigned long) nof_elements
);
1495 // the index is not available or the error has been reported above
1500 if (index_available
) {
1501 ArrayDimension
*dim
= t
->get_dimension();
1502 dim
->chk_index(v_index
, Type::EXPECTED_DYNAMIC_VALUE
);
1503 if (templatetype
== TEMPLATE_LIST
&& !dim
->get_has_error()) {
1504 // perform the index transformation
1505 index
-= dim
->get_offset();
1506 // check for index underflow/overflow or too few elements in template
1507 if (index
< 0 || index
>= static_cast<Int
>(get_nof_listitems()))
1510 // remain silent, the error has been already reported
1514 // the index is not available or the error has been reported above
1519 array_index
->error("Invalid array element reference: type `%s' cannot "
1520 "be indexed", t
->get_typename().c_str());
1523 Template
*ret_val
= get_listitem_byIndex(index
);
1524 if (ret_val
->templatetype
== TEMPLATE_NOTUSED
) {
1525 if (base_template
) {
1526 // take the referred element from the base template
1527 return base_template
->get_template_refd_last(refch
)
1528 ->get_refd_array_template(v_index
, usedInIsbound
, refch
);
1530 if(ret_val
->get_templatetype() == TEMPLATE_NOTUSED
)
1531 error("Not used symbol is not allowed in this context");
1534 } else return ret_val
;
1537 bool Template::temps_contains_anyornone_symbol() const
1539 switch (templatetype
) {
1541 case SUPERSET_MATCH
:
1543 case PERMUTATION_MATCH
:
1546 FATAL_ERROR("Template::temps_contains_anyornone_symbol()");
1548 size_t nof_comps
= u
.templates
->get_nof_ts();
1549 for (size_t i
= 0; i
< nof_comps
; i
++) {
1550 Template
*t
= u
.templates
->get_t_byIndex(i
);
1551 switch (t
->templatetype
) {
1554 // 'all from' clauses not known at compile time are also considered
1557 case PERMUTATION_MATCH
:
1559 if (t
->temps_contains_anyornone_symbol()) return true;
1568 size_t Template::get_nof_comps_not_anyornone() const
1570 switch (templatetype
) {
1572 case SUPERSET_MATCH
:
1574 case PERMUTATION_MATCH
:
1577 FATAL_ERROR("Template::get_nof_comps_not_anyornone()");
1580 size_t nof_comps
= u
.templates
->get_nof_ts();
1581 for (size_t i
= 0; i
< nof_comps
; i
++) {
1582 Template
*t
= u
.templates
->get_t_byIndex(i
);
1583 switch (t
->templatetype
) {
1588 case PERMUTATION_MATCH
:
1590 ret_val
+= t
->get_nof_comps_not_anyornone();
1593 // other types are counted as 1
1601 bool Template::pattern_contains_anyornone_symbol() const
1603 switch (templatetype
) {
1607 return u
.pattern
->find('*') < u
.pattern
->size();
1612 FATAL_ERROR("Template::pattern_contains_anyornone_symbol()");
1617 size_t Template::get_min_length_of_pattern() const
1620 switch (templatetype
) {
1622 case HSTR_PATTERN
: {
1623 size_t pattern_len
= u
.pattern
->size();
1624 const char *pattern_ptr
= u
.pattern
->c_str();
1625 for (size_t i
= 0; i
< pattern_len
; i
++)
1626 if (pattern_ptr
[i
] != '*') ret_val
++;
1628 case OSTR_PATTERN
: {
1629 size_t pattern_len
= u
.pattern
->size();
1630 const char *pattern_ptr
= u
.pattern
->c_str();
1631 for (size_t i
= 0; i
< pattern_len
; i
++) {
1632 switch (pattern_ptr
[i
]) {
1641 // count as 1 and skip over the next hex digit
1651 FATAL_ERROR("Template::get_min_length_of_pattern()");
1656 bool Template::is_Value() const
1658 if (length_restriction
|| is_ifpresent
) return false;
1659 switch (templatetype
) {
1660 case TEMPLATE_ERROR
:
1661 case TEMPLATE_NOTUSED
:
1664 case SPECIFIC_VALUE
:
1665 if(u
.specific_value
->get_valuetype() == Value::V_INVOKE
) {
1666 Type
*t
= u
.specific_value
1667 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE
);
1668 if(t
&& t
->get_type_refd_last()->get_typetype() == Type::T_FUNCTION
&&
1669 t
->get_type_refd_last()->get_returns_template()) return false;
1672 case TEMPLATE_LIST
: {
1673 Templates
*ts
= u
.templates
;
1674 for (size_t i
= 0; i
< ts
->get_nof_ts(); i
++)
1675 if (!ts
->get_t_byIndex(i
)->is_Value()) return false;
1678 case NAMED_TEMPLATE_LIST
: {
1679 NamedTemplates
*ts
= u
.named_templates
;
1680 for (size_t i
= 0;i
< ts
->get_nof_nts(); i
++)
1681 if (!ts
->get_nt_byIndex(i
)->get_template()->is_Value()) return false;
1684 case INDEXED_TEMPLATE_LIST
: {
1685 IndexedTemplates
*ts
= u
.indexed_templates
;
1686 for (size_t i
= 0; i
< ts
->get_nof_its(); i
++)
1687 if (!ts
->get_it_byIndex(i
)->get_template()->is_Value()) return false;
1690 case TEMPLATE_REFD
: {
1691 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1692 switch (ass
->get_asstype()) {
1693 case Common::Assignment::A_EXT_CONST
:
1694 case Common::Assignment::A_PAR_VAL
:
1695 case Common::Assignment::A_PAR_VAL_IN
:
1696 case Common::Assignment::A_PAR_VAL_OUT
:
1697 case Common::Assignment::A_PAR_VAL_INOUT
:
1698 case Common::Assignment::A_VAR
:
1709 Value
*Template::get_Value()
1712 switch(templatetype
) {
1713 case TEMPLATE_ERROR
:
1714 ret_val
= new Value(Value::V_ERROR
);
1716 case TEMPLATE_NOTUSED
:
1717 ret_val
= new Value(Value::V_NOTUSED
);
1720 ret_val
= new Value(Value::V_OMIT
);
1722 case SPECIFIC_VALUE
:
1723 ret_val
= u
.specific_value
;
1724 u
.specific_value
= 0;
1725 set_templatetype(TEMPLATE_ERROR
);
1727 case TEMPLATE_LIST
: {
1728 Values
*vs
= new Values
;
1729 size_t nof_ts
= u
.templates
->get_nof_ts();
1731 for (size_t i
= 0; i
< nof_ts
; i
++) {
1732 Value
* v
= u
.templates
->get_t_byIndex(i
)->get_Value();
1733 if (!gov
) gov
= v
->get_my_governor();
1736 ret_val
= new Value(Value::V_SEQOF
, vs
);
1737 if (gov
) gov
= gov
->get_parent_type();
1738 if (gov
) ret_val
->set_my_governor(gov
);
1740 case NAMED_TEMPLATE_LIST
: {
1741 NamedValues
*nvs
= new NamedValues
;
1742 size_t nof_nts
= u
.named_templates
->get_nof_nts();
1744 for (size_t i
= 0; i
< nof_nts
; i
++) {
1745 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
1746 Value
* v
= nt
->get_template()->get_Value();
1747 if (!gov
) gov
= v
->get_my_governor();
1748 NamedValue
*nv
= new NamedValue(nt
->get_name().clone(), v
);
1749 nv
->set_location(*nt
);
1752 ret_val
= new Value(Value::V_SEQ
, nvs
);
1753 if (gov
) gov
= gov
->get_parent_type();
1754 if (gov
) ret_val
->set_my_governor(gov
);
1756 case INDEXED_TEMPLATE_LIST
: {
1757 Values
*ivs
= new Values(true);
1758 size_t nof_its
= u
.indexed_templates
->get_nof_its();
1760 for (size_t i
= 0; i
< nof_its
; i
++) {
1761 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
1762 Value
* v
= it
->get_template()->get_Value();
1763 if (!gov
) gov
= v
->get_my_governor();
1764 IndexedValue
*iv
= new IndexedValue(it
->get_index().clone(), v
);
1765 iv
->set_location(*it
);
1768 ret_val
= new Value(Value::V_SEQOF
, ivs
);
1769 if (gov
) gov
= gov
->get_parent_type();
1770 if (gov
) ret_val
->set_my_governor(gov
);
1773 FATAL_ERROR("Template::get_Value()");
1777 ret_val
->set_location(*this);
1778 ret_val
->set_my_scope(get_my_scope());
1779 ret_val
->set_fullname(get_fullname());
1783 bool Template::is_Ref() const
1785 if (length_restriction
|| is_ifpresent
|| templatetype
!= SPECIFIC_VALUE
)
1787 Value
*v
= u
.specific_value
;
1788 switch (v
->get_valuetype()) {
1789 case Value::V_UNDEF_LOWERID
:
1792 if (dynamic_cast<Ref_base
*>(v
->get_reference())) return true;
1799 Ref_base
*Template::get_Ref()
1801 if (templatetype
!= SPECIFIC_VALUE
)
1802 FATAL_ERROR("Template::get_Ref()");
1803 return u
.specific_value
->steal_ttcn_ref_base();
1806 void Template::chk_recursions(ReferenceChain
& refch
)
1808 if (recurs_checked
) return;
1811 if (t
->templatetype
== SPECIFIC_VALUE
) break;
1812 else if (!refch
.add(t
->get_fullname())) goto end
;
1813 else if (t
->templatetype
!= TEMPLATE_REFD
) break;
1814 t
->u
.ref
.ref
->get_refd_assignment(true); // make sure the parameter list is checked
1815 ActualParList
*parlist
= t
->u
.ref
.ref
->get_parlist();
1816 if (parlist
) parlist
->chk_recursions(refch
);
1817 Template
*t_refd
= t
->get_template_refd(&refch
);
1818 if (t_refd
== t
) break;
1821 t
->set_lowerid_to_ref();
1822 switch (t
->templatetype
) {
1823 case SPECIFIC_VALUE
:
1824 t
->u
.specific_value
->chk_recursions(refch
);
1828 case COMPLEMENTED_LIST
:
1829 case SUPERSET_MATCH
:
1831 case PERMUTATION_MATCH
:
1832 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++) {
1834 t
->u
.templates
->get_t_byIndex(i
)->chk_recursions(refch
);
1838 case NAMED_TEMPLATE_LIST
:
1839 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++) {
1841 t
->u
.named_templates
->get_nt_byIndex(i
)
1842 ->get_template()->chk_recursions(refch
);
1846 case INDEXED_TEMPLATE_LIST
:
1847 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++) {
1849 t
->u
.indexed_templates
->get_it_byIndex(i
)
1850 ->get_template()->chk_recursions(refch
);
1856 t
->u
.pstring
->chk_recursions(refch
);
1862 recurs_checked
= true;
1865 void Template::chk_specific_value(bool allow_omit
)
1867 Template
*t
= get_template_refd_last();
1868 if (!allow_omit
&& t
->templatetype
==OMIT_VALUE
) {
1869 t
->error("A specific value was expected instead of omit");
1871 chk_specific_value_generic();
1874 void Template::chk_specific_value_generic()
1876 if (specific_value_checked
) return;
1877 Template
*t
= get_template_refd_last();
1878 if (t
->specific_value_checked
) return;
1879 switch (t
->templatetype
) {
1880 case TEMPLATE_ERROR
:
1881 case TEMPLATE_NOTUSED
:
1882 case TEMPLATE_REFD
: // unfoldable reference
1884 case SPECIFIC_VALUE
:
1885 if(u
.specific_value
->get_valuetype() == Value::V_INVOKE
) {
1886 Type
*t_type
= u
.specific_value
1887 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE
);
1888 if(t_type
&& t_type
->get_type_refd_last()->get_returns_template()) {
1889 set_templatetype(TEMPLATE_INVOKE
);
1894 case TEMPLATE_INVOKE
:
1898 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++)
1899 t
->u
.templates
->get_t_byIndex(i
)->chk_specific_value_generic();
1901 case NAMED_TEMPLATE_LIST
:
1902 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++)
1903 t
->u
.named_templates
->get_nt_byIndex(i
)
1904 ->get_template()->chk_specific_value_generic();
1906 case INDEXED_TEMPLATE_LIST
:
1907 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++)
1908 t
->u
.indexed_templates
->get_it_byIndex(i
)
1909 ->get_template()->chk_specific_value_generic();
1914 t
->error("A specific value was expected instead of %s",
1915 t
->get_templatetype_str());
1918 t
->specific_value_checked
= true;
1919 specific_value_checked
= true;
1922 void Template::chk_invoke()
1924 if(templatetype
!= TEMPLATE_INVOKE
) FATAL_ERROR("Template::chk_invoke()");
1925 if(!u
.invoke
.t_list
) return; //already checked
1926 Error_Context
cntxt(this, "In `apply()' operation");
1927 Type
*t
= u
.invoke
.v
->get_expr_governor_last();
1929 if (t
->get_typetype() != Type::T_FUNCTION
) {
1930 u
.invoke
.v
->error("A value of type function was expected in the "
1931 "argument instead of `%s'", t
->get_typename().c_str());
1932 set_templatetype(TEMPLATE_ERROR
);
1936 if (u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
1937 u
.invoke
.v
->error("A value of type function was expected in the "
1939 set_templatetype(TEMPLATE_ERROR
);
1942 my_scope
->chk_runs_on_clause(t
, *this, "call");
1943 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
1944 Ttcn::ActualParList
*parlist
= new Ttcn::ActualParList
;
1945 bool is_erroneous
= fp_list
->fold_named_and_chk(u
.invoke
.t_list
,parlist
);
1946 delete u
.invoke
.t_list
;
1947 u
.invoke
.t_list
= 0;
1950 u
.invoke
.ap_list
= 0;
1952 parlist
->set_fullname(get_fullname());
1953 parlist
->set_my_scope(get_my_scope());
1954 u
.invoke
.ap_list
= parlist
;
1958 Templates
*Template::harbinger(Template
*t
, bool from_permutation
, bool killer
)
1960 Templates
*new_templates
= new Templates
;
1961 switch (t
->u
.all_from
->templatetype
) {
1962 case SPECIFIC_VALUE
: {
1963 Value
*innerv
= t
->u
.all_from
->get_specific_value();
1964 //if (v->get_valuetype() == Value::V_UNDEF_LOWERID)
1965 innerv
->set_lowerid_to_ref();
1966 // should be a ref now
1967 bool can_flatten
= true;
1968 Common::Reference
*ref
= innerv
->get_reference();
1969 if (dynamic_cast<Ttcn::Ref_pard
*>(ref
)) {
1970 // Cannot flatten at compile time if the template has parameters.
1971 can_flatten
= false;
1974 // check for subreferences in the 'all from' target
1975 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
1976 if (NULL
!= subrefs
) {
1977 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
1978 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
1979 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
1980 // set any array indexes from undefined lowerID to reference
1981 subref
->get_val()->set_lowerid_to_ref();
1986 Common::Assignment
*ass
= ref
->get_refd_assignment();
1987 if (ass
== NULL
) { // perhaps erroneous
1991 Common::Assignment::asstype_t asst
= ass
->get_asstype();
1993 case Common::Assignment::A_TEMPLATE
: {
1994 Template
*tpl
= ass
->get_Template();
1995 // tpl is the template whose name appears after the "all from"
1996 Common::Type
*type
= ass
->get_Type()->get_type_refd_last();
1997 if (NULL
!= subrefs
) {
1998 // walk through the subreferences to determine the type and value of the 'all from' target
1999 // Note: the templates referenced by the array indexes and field names
2000 // have not been checked yet
2001 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
2002 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
2003 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
2004 // check if the type can be indexed
2005 Common::Type::typetype_t tt
= type
->get_typetype();
2006 if (Common::Type::T_SEQOF
!= tt
&& Common::Type::T_SETOF
!= tt
&&
2007 Common::Type::T_ARRAY
!= tt
) {
2008 subref
->error("Cannot apply an array index to type '%s'",
2009 type
->get_typename().c_str());
2010 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2014 if (can_flatten
&& !subref
->get_val()->is_unfoldable()) {
2015 switch(tpl
->get_templatetype()) {
2018 Int index
= subref
->get_val()->get_val_Int()->get_val();
2019 // check for index overflow
2020 if (index
>= static_cast<Int
>(tpl
->get_nof_comps())) {
2021 subref
->error("Index overflow in a template %s type `%s':"
2022 " the index is %s, but the template has only %lu elements",
2023 Common::Type::T_ARRAY
== tt
? "array of" :
2024 (Common::Type::T_SEQOF
== tt
? "of 'record of'" : "of 'set of'"),
2025 type
->get_typename().c_str(), Int2string(index
).c_str(),
2026 (unsigned long)tpl
->get_nof_comps());
2027 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2031 tpl
= tpl
->get_temp_byIndex(index
);
2032 // check if the element is initialized
2033 if (TEMPLATE_NOTUSED
== tpl
->get_templatetype()) {
2034 subref
->error("An uninitialized list element can not be used as target of 'all from'");
2035 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2040 case INDEXED_TEMPLATE_LIST
:
2041 can_flatten
= false; // currently not supported
2044 subref
->error("Expected a specific value of type '%s' instead of %s",
2045 type
->get_typename().c_str(), tpl
->get_templatetype_str());
2046 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2052 // one of the array indexes is a reference => cannot flatten
2053 can_flatten
= false;
2055 type
= type
->get_ofType()->get_type_refd_last();
2058 // check if the type can have fields
2059 Common::Type::typetype_t tt
= type
->get_typetype();
2060 if (Common::Type::T_SEQ_T
!= tt
&& Common::Type::T_SEQ_A
!= tt
&&
2061 Common::Type::T_SET_T
!= tt
&& Common::Type::T_SET_A
!= tt
&&
2062 Common::Type::T_CHOICE_T
!= tt
&& Common::Type::T_CHOICE_A
!= tt
) {
2063 subref
->error("Cannot apply a field name to type '%s'",
2064 type
->get_typename().c_str());
2068 // check if the field name is valid
2069 if (!type
->has_comp_withName(*subref
->get_id())) {
2070 subref
->error("Type '%s' does not have a field with name '%s'",
2071 type
->get_typename().c_str(), subref
->get_id()->get_dispname().c_str());
2076 switch(tpl
->get_templatetype()) {
2077 case NAMED_TEMPLATE_LIST
: {
2078 // check if there is any data in the template for this field
2079 // (no data means it's uninitialized)
2080 if (!tpl
->u
.named_templates
->has_nt_withName(*subref
->get_id())) {
2081 subref
->error("An uninitialized field can not be used as target of 'all from'");
2082 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2086 tpl
= tpl
->u
.named_templates
->get_nt_byName(*subref
->get_id())->get_template();
2087 // check if the field is initialized and present (not omitted)
2088 if (OMIT_VALUE
== tpl
->get_templatetype() || TEMPLATE_NOTUSED
== tpl
->get_templatetype()) {
2089 subref
->error("An %s field can not be used as target of 'all from'",
2090 OMIT_VALUE
== tpl
->get_templatetype() ? "omitted" : "uninitialized");
2091 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2097 subref
->error("Expected a specific value of type '%s' instead of %s",
2098 type
->get_typename().c_str(), tpl
->get_templatetype_str());
2099 i
= subrefs
->get_nof_refs(); // quit from the cycle, too
2104 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2108 if (NULL
!= tpl
) { // tpl is set to null if an error occurs
2110 Template::templatetype_t tpltt
= tpl
->get_templatetype();
2112 case INDEXED_TEMPLATE_LIST
: // currently not supported
2113 case TEMPLATE_REFD
: {
2114 delete new_templates
;
2122 size_t nvl
= tpl
->get_nof_comps();
2123 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2124 Template
*orig
= tpl
->get_temp_byIndex(ti
);
2125 switch (orig
->templatetype
) {
2126 case SPECIFIC_VALUE
: {
2127 Value
*val
= orig
->get_specific_value();
2128 if (val
->get_valuetype() == Value::V_REFD
) {
2129 if (dynamic_cast<Ttcn::Ref_pard
*>(val
->get_reference())) {
2130 // Cannot flatten at compile time if one of the values or templates has parameters.
2131 can_flatten
= false;
2136 if (from_permutation
) {
2137 break; // AnyElementOrNone allowed in "all from" now
2140 case PERMUTATION_MATCH
:
2141 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2142 t
->set_templatetype(TEMPLATE_ERROR
);
2148 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2149 Template
*orig
= tpl
->get_temp_byIndex(ti
);
2150 Template
*copy
= orig
->clone();
2151 copy
->set_my_scope(orig
->get_my_scope());
2152 new_templates
->add_t(copy
);
2156 // Cannot flatten at compile time
2157 delete new_templates
;
2163 case NAMED_TEMPLATE_LIST
: {
2164 size_t nvl
= tpl
->get_nof_comps();
2165 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2166 NamedTemplate
*orig
= tpl
->get_namedtemp_byIndex(ti
);
2167 switch (orig
->get_template()->get_templatetype()) {
2170 case PERMUTATION_MATCH
:
2171 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2172 t
->set_templatetype(TEMPLATE_ERROR
);
2177 delete new_templates
;
2184 tpl
->error("Matching mechanism can not be used as target of 'all from'");
2187 tpl
->error("A template of type '%s' can not be used as target of 'all from'",
2188 type
->get_typename().c_str());
2192 else { // cannot flatten
2193 switch (type
->get_typetype()) {
2194 case Common::Type::T_SEQOF
: case Common::Type::T_SETOF
:
2195 case Common::Type::T_ARRAY
:
2196 delete new_templates
;
2201 type
->error("A template of type `%s' can not be used as target of 'all from'",
2202 type
->get_typename().c_str());
2204 } // switch(typetype)
2208 if (killer
) delete t
;
2212 case Common::Assignment::A_CONST
: { // all from a constant definition
2213 Common::Value
*val
= ass
->get_Value();
2214 Common::Type
*type
= ass
->get_Type()->get_type_refd_last();
2215 if (NULL
!= subrefs
) {
2216 // walk through the subreferences to determine the type and value of the 'all from' target
2217 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
2218 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
2219 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
2220 // check if the type can be indexed
2221 Common::Type::typetype_t tt
= type
->get_typetype();
2222 if (Common::Type::T_SEQOF
!= tt
&& Common::Type::T_SETOF
!= tt
&&
2223 Common::Type::T_ARRAY
!= tt
) {
2224 subref
->error("Cannot apply an array index to type '%s'",
2225 type
->get_typename().c_str());
2229 if (can_flatten
&& !subref
->get_val()->is_unfoldable()) {
2230 Int index
= subref
->get_val()->get_val_Int()->get_val();
2231 // check for index overflow
2232 if (index
>= static_cast<Int
>(val
->get_nof_comps())) {
2233 subref
->error("Index overflow in a value %s type `%s':"
2234 " the index is %s, but the template has only %lu elements",
2235 Common::Type::T_ARRAY
== tt
? "array of" :
2236 (Common::Type::T_SEQOF
== tt
? "of 'record of'" : "of 'set of'"),
2237 type
->get_typename().c_str(), Int2string(index
).c_str(),
2238 (unsigned long)val
->get_nof_comps());
2242 val
= val
->get_comp_byIndex(index
);
2243 // check if the element is initialized
2244 if (Common::Value::V_NOTUSED
== val
->get_valuetype()) {
2245 subref
->error("An unbound list element can not be used as target of 'all from'");
2251 // one of the array indexes is a reference => cannot flatten
2252 can_flatten
= false;
2254 type
= type
->get_ofType()->get_type_refd_last();
2257 // check if the type can have fields
2258 Common::Type::typetype_t tt
= type
->get_typetype();
2259 if (Common::Type::T_SEQ_T
!= tt
&& Common::Type::T_SEQ_A
!= tt
&&
2260 Common::Type::T_SET_T
!= tt
&& Common::Type::T_SET_A
!= tt
&&
2261 Common::Type::T_CHOICE_T
!= tt
&& Common::Type::T_CHOICE_A
!= tt
) {
2262 subref
->error("Cannot apply a field name to type '%s'",
2263 type
->get_typename().c_str());
2267 // check if the field name is valid
2268 if (!type
->has_comp_withName(*subref
->get_id())) {
2269 subref
->error("Type '%s' does not have a field with name '%s'",
2270 type
->get_typename().c_str(), subref
->get_id()->get_dispname().c_str());
2274 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2276 // check if the value has any data for this field (no data = unbound)
2277 if (!val
->has_comp_withName(*subref
->get_id())) {
2278 subref
->error("An unbound field can not be used as target of 'all from'");
2282 val
= val
->get_comp_value_byName(*subref
->get_id());
2283 // check if the field is bound and present (not omitted)
2284 if (Common::Value::V_OMIT
== val
->get_valuetype() ||
2285 Common::Value::V_NOTUSED
== val
->get_valuetype()) {
2286 subref
->error("An %s field can not be used as target of 'all from'",
2287 Common::Value::V_OMIT
== val
->get_valuetype() ? "omitted" : "unbound");
2295 if (NULL
!= val
) { // val is set to null if an error occurs
2296 switch (type
->get_typetype()) {
2297 case Common::Type::T_SEQOF
: case Common::Type::T_SETOF
:
2298 case Common::Type::T_ARRAY
: {
2300 const size_t ncomp
= val
->get_nof_comps();
2301 for (size_t i
= 0; i
< ncomp
; ++i
) {
2302 Value
*v
= val
->get_comp_byIndex(i
);
2303 Template
*newt
= new Template(v
->clone());
2304 new_templates
->add_t(newt
);
2308 delete new_templates
;
2315 type
->error("A constant of type `%s' can not be used as target of 'all from'",
2316 type
->get_typename().c_str());
2318 } // switch(typetype)
2320 if (killer
) delete t
;
2323 case Common::Assignment::A_MODULEPAR_TEMP
:
2324 case Common::Assignment::A_VAR_TEMPLATE
:
2325 case Common::Assignment::A_FUNCTION_RTEMP
:
2326 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2327 case Common::Assignment::A_PAR_TEMPL_IN
:
2328 case Common::Assignment::A_PAR_TEMPL_INOUT
:
2329 case Common::Assignment::A_PAR_TEMPL_OUT
:
2330 //TODO: flatten if the actual par is const template
2331 case Common::Assignment::A_MODULEPAR
: // all from a module parameter
2332 case Common::Assignment::A_VAR
: // all from a variable
2333 case Common::Assignment::A_PAR_VAL_IN
:
2334 case Common::Assignment::A_PAR_VAL_INOUT
:
2335 case Common::Assignment::A_PAR_VAL_OUT
:
2336 case Common::Assignment::A_FUNCTION_RVAL
:
2337 case Common::Assignment::A_EXT_FUNCTION_RVAL
: {
2338 Common::Type
*type
= ass
->get_Type()->get_type_refd_last();
2339 if (NULL
!= subrefs
) {
2340 // walk through the subreferences to determine the type of the 'all from' target
2341 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); ++i
) {
2342 FieldOrArrayRef
* subref
= subrefs
->get_ref(i
);
2343 if (FieldOrArrayRef::ARRAY_REF
== subref
->get_type()) {
2344 // check if the type can be indexed
2345 Common::Type::typetype_t tt
= type
->get_typetype();
2346 if (Common::Type::T_SEQOF
!= tt
&& Common::Type::T_SETOF
!= tt
&&
2347 Common::Type::T_ARRAY
!= tt
) {
2348 subref
->error("Cannot apply an array index to type '%s'",
2349 type
->get_typename().c_str());
2353 type
= type
->get_ofType()->get_type_refd_last();
2356 // check if the type can have fields
2357 Common::Type::typetype_t tt
= type
->get_typetype();
2358 if (Common::Type::T_SEQ_T
!= tt
&& Common::Type::T_SEQ_A
!= tt
&&
2359 Common::Type::T_SET_T
!= tt
&& Common::Type::T_SET_A
!= tt
&&
2360 Common::Type::T_CHOICE_T
!= tt
&& Common::Type::T_CHOICE_A
!= tt
) {
2361 subref
->error("Cannot apply a field name to type '%s'",
2362 type
->get_typename().c_str());
2366 // check if the field name is valid
2367 if (!type
->has_comp_withName(*subref
->get_id())) {
2368 subref
->error("Type '%s' does not have a field with name '%s'",
2369 type
->get_typename().c_str(), subref
->get_id()->get_dispname().c_str());
2373 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2378 switch (type
->get_typetype()) {
2379 case Common::Type::T_SEQOF
: case Common::Type::T_SETOF
:
2380 case Common::Type::T_ARRAY
:
2381 delete new_templates
; // cannot flatten at compile time
2385 // not an array type => error
2386 const char* ass_name
= ass
->get_assname();
2389 case Common::Assignment::A_MODULEPAR_TEMP
:
2390 case Common::Assignment::A_VAR_TEMPLATE
:
2391 case Common::Assignment::A_MODULEPAR
:
2392 case Common::Assignment::A_VAR
:
2393 case Common::Assignment::A_PAR_TEMPL_IN
:
2394 case Common::Assignment::A_PAR_VAL_IN
:
2398 case Common::Assignment::A_PAR_TEMPL_INOUT
:
2399 case Common::Assignment::A_PAR_TEMPL_OUT
:
2400 case Common::Assignment::A_PAR_VAL_INOUT
:
2401 case Common::Assignment::A_PAR_VAL_OUT
:
2405 // the assignment name string for functions is no good here
2406 case Common::Assignment::A_FUNCTION_RTEMP
:
2407 descr
= "A function returning a template";
2409 case Common::Assignment::A_FUNCTION_RVAL
:
2410 descr
= "A function returning a value";
2412 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2413 descr
= "An external function returning a template";
2415 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2416 descr
= "An external function returning a value";
2421 type
->error("%s of type `%s' can not be used as target of 'all from'",
2422 descr
.c_str(), type
->get_typename().c_str());
2425 } // switch(typetype)
2429 FATAL_ERROR("harbinger asst %d", asst
);
2435 FATAL_ERROR("unexpected all from inside all from");
2438 FATAL_ERROR("tt %d", t
->u
.all_from
->templatetype
);
2441 return new_templates
;
2444 bool Template::flatten(bool from_permutation
)
2446 switch (templatetype
) {
2449 case COMPLEMENTED_LIST
:
2450 case SUPERSET_MATCH
:
2452 case PERMUTATION_MATCH
: {
2453 size_t num_t
= u
.templates
->get_nof_ts(); // one of these is the "all from"
2454 Templates
*new_templates
= new Templates
;
2455 for (size_t i
= 0; i
< num_t
; ++i
) {
2456 Template
*& t
= u
.templates
->get_t_byIndex(i
);
2457 // the element in the (,,,)
2458 switch (t
->templatetype
) {
2459 case VALUE_LIST_ALL_FROM
: {
2460 // the all from from something like subset(1, (all from...), 99)
2461 // value list: one out of many possible values^^^^^^^^^^^^^
2462 Location
tloc(*t
); // save the location info
2463 string
tname(t
->get_fullname());
2464 Templates
*ha
= harbinger(t
, from_permutation
, true);
2466 // Don't touch t from now on, it might have been deleted!
2467 Template
*qq
= new Template(VALUE_LIST
, ha
);
2468 qq
->set_location(tloc
);
2469 qq
->set_fullname(tname
+ ".all_from");
2470 new_templates
->add_t(qq
);
2473 new_templates
->add_t(t
); // transfer it unchanged
2478 case ALL_FROM
: { // subset(1, all from ..., 99)
2479 // some number of elements--^^^^^^^^^^^^
2480 if (t
->checked
) FATAL_ERROR("too late");
2481 Templates
*af
= harbinger(t
, from_permutation
, true);
2483 for (size_t a
= 0, num
= af
->get_nof_ts(); a
< num
; ++a
) {
2484 Template
*& t2
= af
->get_t_byIndex(a
);
2485 new_templates
->add_t(t2
);
2486 t2
= 0; // take it away from its current owner
2491 new_templates
->add_t(t
); // transfer it unchanged
2494 break; } // case ALL_FROM
2496 case PERMUTATION_MATCH
: {
2497 // permut inside a value list: { 1, permut(), 2 }
2498 flattened
&= t
->flatten(true);
2499 new_templates
->add_t(t
);
2503 // case COMPLEMENTED_LIST:
2504 // case SUPERSET_MATCH:
2505 // case SUBSET_MATCH:
2507 flattened
&=t
->flatten(false);
2508 new_templates
->add_t(t
);
2511 new_templates
->add_t(t
);
2514 t
= 0; // take it away from the original
2517 u
.templates
= new_templates
;
2518 //printf("!!! flattened from %lu to %lu at line %d\n",
2519 // (unsigned long)num_t, (unsigned long)new_templates->get_nof_ts(),
2520 // get_first_line());
2524 case VALUE_LIST_ALL_FROM
: {
2525 Templates
*new_templates
= harbinger(this, from_permutation
, false);
2526 if (new_templates
) {
2528 // now we can change the type
2529 templatetype
= VALUE_LIST
;
2530 u
.templates
= new_templates
;
2534 case TEMPLATE_ERROR
: case TEMPLATE_NOTUSED
:
2535 case OMIT_VALUE
: case ANY_VALUE
: case ANY_OR_OMIT
:
2536 case SPECIFIC_VALUE
:
2537 case TEMPLATE_REFD
: case TEMPLATE_INVOKE
:
2538 case NAMED_TEMPLATE_LIST
: case INDEXED_TEMPLATE_LIST
:
2541 case BSTR_PATTERN
: case HSTR_PATTERN
: case OSTR_PATTERN
:
2542 case CSTR_PATTERN
: case USTR_PATTERN
:
2546 set_fullname(get_fullname()); // recompute fullname (esp. for components)
2547 set_my_scope(get_my_scope());
2552 const char* Template::get_restriction_name(template_restriction_t tr
)
2564 FATAL_ERROR("Template::get_restriction_name()");
2569 template_restriction_t
Template::get_sub_restriction(
2570 template_restriction_t tr
, Ref_base
* ref
)
2572 if (!ref
) FATAL_ERROR("Template::get_sub_restriction()");
2573 if (!ref
->get_subrefs()) return tr
;
2574 bool is_optional
= true; // the referenced field is on an optional path
2575 Common::Assignment
* ass
= ref
->get_refd_assignment();
2577 Type
* t
= ass
->get_Type();
2579 ReferenceChain
refch(ref
, "While checking template restriction");
2580 t
= t
->get_field_type(ref
->get_subrefs(), Type::EXPECTED_TEMPLATE
,
2582 if (t
) is_optional
= false;
2591 return is_optional
? TR_OMIT
: TR_VALUE
;
2593 return is_optional
? TR_NONE
: TR_PRESENT
;
2595 FATAL_ERROR("Template::get_sub_restriction()");
2600 bool Template::is_less_restrictive(template_restriction_t needed_tr
,
2601 template_restriction_t refd_tr
)
2603 switch (needed_tr
) {
2607 return refd_tr
!=TR_VALUE
;
2609 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_OMIT
;
2611 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_PRESENT
;
2613 FATAL_ERROR("Template::is_less_restrictive()");
2618 char* Template::generate_restriction_check_code(char* str
, const char* name
,
2619 template_restriction_t tr
)
2621 const char* tr_name
;
2626 tr_name
= "TR_OMIT";
2629 tr_name
= "TR_VALUE";
2632 tr_name
= "TR_PRESENT";
2635 FATAL_ERROR("Template::generate_restriction_check_code()");
2637 return mputprintf(str
, "%s.check_restriction(%s%s);\n", name
, tr_name
,
2638 (omit_in_value_list
? ", NULL, TRUE" : ""));
2641 // embedded templates -> check needed only for case of TR_OMIT
2642 bool Template::chk_restriction_named_list(const char* definition_name
,
2643 map
<string
, void>& checked_map
, size_t needed_checked_cnt
,
2644 const Location
* usage_loc
)
2646 bool needs_runtime_check
= false;
2647 if (checked_map
.size()>=needed_checked_cnt
) return needs_runtime_check
;
2648 switch (templatetype
) {
2649 case NAMED_TEMPLATE_LIST
:
2650 for (size_t i
= 0;i
< u
.named_templates
->get_nof_nts(); i
++) {
2651 Template
* tmpl
= u
.named_templates
->get_nt_byIndex(i
)->get_template();
2652 const string
& name
=
2653 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name();
2654 if (!checked_map
.has_key(name
)) {
2655 bool nrc
= tmpl
->chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2656 needs_runtime_check
= needs_runtime_check
|| nrc
;
2657 checked_map
.add(name
, 0);
2660 if (base_template
) {
2661 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2662 checked_map
, needed_checked_cnt
, usage_loc
);
2663 needs_runtime_check
= needs_runtime_check
|| nrc
;
2668 error("Restriction on %s does not allow usage of %s",
2669 definition_name
, get_templatetype_str());
2672 // others will be converted to specific value
2675 return needs_runtime_check
;
2678 bool Template::chk_restriction_refd(const char* definition_name
,
2679 template_restriction_t template_restriction
, const Location
* usage_loc
)
2681 bool needs_runtime_check
= false;
2682 Common::Assignment
* ass
= u
.ref
.ref
->get_refd_assignment();
2683 if (!ass
) FATAL_ERROR("Template::chk_restriction_refd()");
2684 // get the restriction on the referenced template
2685 template_restriction_t refd_tr
= TR_NONE
;
2686 bool is_var_template
= false;
2687 switch (ass
->get_asstype()) {
2688 case Common::Assignment::A_TEMPLATE
: {
2689 Template
* t_last
= get_template_refd_last();
2691 bool nrc
= t_last
->chk_restriction(definition_name
,
2692 template_restriction
, usage_loc
);
2693 needs_runtime_check
= needs_runtime_check
|| nrc
;
2696 case Common::Assignment::A_MODULEPAR_TEMP
:
2697 is_var_template
= true;
2698 refd_tr
= TR_NONE
; // can't place restriction on this thing
2700 case Common::Assignment::A_VAR_TEMPLATE
: {
2701 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(ass
);
2702 if (!dvt
) FATAL_ERROR("Template::chk_restriction_refd()");
2703 is_var_template
= true;
2704 refd_tr
= dvt
->get_template_restriction();
2706 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2707 // we do not trust external functions because there is no generated
2708 // restriction check on their return value
2709 if (template_restriction
!=TR_NONE
) needs_runtime_check
= true;
2711 case Common::Assignment::A_FUNCTION_RTEMP
: {
2712 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(ass
);
2713 if (!dfb
) FATAL_ERROR("Template::chk_restriction_refd()");
2714 is_var_template
= true;
2715 refd_tr
= dfb
->get_template_restriction();
2717 case Common::Assignment::A_PAR_TEMPL_IN
:
2718 case Common::Assignment::A_PAR_TEMPL_OUT
:
2719 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
2720 FormalPar
* fp
= dynamic_cast<FormalPar
*>(ass
);
2721 if (!fp
) FATAL_ERROR("Template::chk_restriction_refd()");
2722 is_var_template
= true;
2723 refd_tr
= fp
->get_template_restriction();
2728 if (is_var_template
) {
2729 // check the restriction
2730 refd_tr
= get_sub_restriction(refd_tr
, u
.ref
.ref
);
2731 // if restriction not satisfied issue warning
2732 if (is_less_restrictive(template_restriction
, refd_tr
)) {
2733 needs_runtime_check
= true;
2734 warning("Inadequate restriction on the referenced %s `%s', this may "
2735 "cause a dynamic test case error at runtime", ass
->get_assname(),
2736 u
.ref
.ref
->get_dispname().c_str());
2737 ass
->note("Referenced %s is here", ass
->get_assname());
2740 return needs_runtime_check
;
2743 bool Template::chk_restriction(const char* definition_name
,
2744 template_restriction_t template_restriction
,
2745 const Location
* usage_loc
)
2747 bool needs_runtime_check
= false;
2748 bool erroneous
= false;
2749 switch (template_restriction
) {
2754 if (length_restriction
) {
2755 usage_loc
->error("Restriction on %s does not allow usage of length "
2756 "restriction", definition_name
);
2760 usage_loc
->error("Restriction on %s does not allow usage of `ifpresent'",
2764 switch(templatetype
) {
2765 case TEMPLATE_ERROR
:
2767 case TEMPLATE_NOTUSED
:
2768 if (base_template
) {
2769 bool nrc
= base_template
->chk_restriction(definition_name
,
2770 template_restriction
, usage_loc
);
2771 needs_runtime_check
= needs_runtime_check
|| nrc
;
2773 else needs_runtime_check
= true;
2775 case SPECIFIC_VALUE
:
2776 case TEMPLATE_INVOKE
:
2778 case TEMPLATE_REFD
: {
2779 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
,
2781 needs_runtime_check
= needs_runtime_check
|| nrc
;
2784 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2785 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2786 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2787 needs_runtime_check
= needs_runtime_check
|| nrc
;
2790 case NAMED_TEMPLATE_LIST
: {
2791 map
<string
, void> checked_map
;
2792 size_t needed_checked_cnt
= 0;
2793 if (base_template
&& my_governor
) {
2794 switch (my_governor
->get_typetype()) {
2799 case Type::T_SIGNATURE
:
2800 needed_checked_cnt
= my_governor
->get_nof_comps();
2806 for (size_t i
= 0;i
< u
.named_templates
->get_nof_nts(); i
++) {
2807 bool nrc
= u
.named_templates
->get_nt_byIndex(i
)->get_template()->
2808 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2809 needs_runtime_check
= needs_runtime_check
|| nrc
;
2810 if (needed_checked_cnt
)
2812 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name(), 0);
2814 if (needed_checked_cnt
) {
2815 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2816 checked_map
, needed_checked_cnt
, usage_loc
);
2817 needs_runtime_check
= needs_runtime_check
|| nrc
;
2818 checked_map
.clear();
2821 case INDEXED_TEMPLATE_LIST
:
2822 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
2823 bool nrc
= u
.indexed_templates
->get_it_byIndex(i
)->get_template()->
2824 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2825 needs_runtime_check
= needs_runtime_check
|| nrc
;
2827 needs_runtime_check
= true; // only basic check, needs runtime check
2830 if (template_restriction
==TR_OMIT
) break;
2831 // Else restriction is TR_VALUE, but template type is OMIT:
2832 // fall through to error.
2834 usage_loc
->error("Restriction on %s does not allow usage of %s",
2835 definition_name
, get_templatetype_str());
2842 usage_loc
->error("Restriction on %s does not allow usage of `ifpresent'",
2846 switch(templatetype
) {
2847 case TEMPLATE_REFD
: {
2848 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
,
2850 needs_runtime_check
= needs_runtime_check
|| nrc
;
2853 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2854 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2855 chk_restriction(definition_name
, template_restriction
, usage_loc
);
2856 needs_runtime_check
= needs_runtime_check
|| nrc
;
2859 case COMPLEMENTED_LIST
:
2860 // some basic check, always needs runtime check
2861 needs_runtime_check
= true;
2862 if (omit_in_value_list
) {
2863 bool has_any_or_omit
= false;
2864 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2865 templatetype_t item_templatetype
=
2866 u
.templates
->get_t_byIndex(i
)->templatetype
;
2867 if (item_templatetype
==OMIT_VALUE
|| item_templatetype
==ANY_OR_OMIT
) {
2868 has_any_or_omit
= true;
2872 if (!has_any_or_omit
) {
2873 usage_loc
->error("Restriction on %s does not allow usage of %s without "
2874 "omit or AnyValueOrNone in the list", definition_name
,
2875 get_templatetype_str());
2882 usage_loc
->error("Restriction on %s does not allow usage of %s",
2883 definition_name
, get_templatetype_str());
2887 break; // all others are ok
2891 FATAL_ERROR("Template::chk_restriction()");
2893 if (erroneous
&& usage_loc
!= this) {
2894 // display the template's location, too
2895 note("Referenced template is here");
2897 return needs_runtime_check
;
2900 void Template::generate_code_expr(expression_struct
*expr
,
2901 template_restriction_t template_restriction
)
2903 // Only templates without extra matching attributes can be directly
2904 // represented in a C++ expression.
2905 if (!length_restriction
&& !is_ifpresent
2906 && template_restriction
== TR_NONE
) {
2907 // The single expression must be tried first because this rule might
2908 // cover some referenced templates.
2909 if (has_single_expr()) {
2910 expr
->expr
= mputstr(expr
->expr
, get_single_expr(true).c_str());
2913 switch (templatetype
) {
2914 case SPECIFIC_VALUE
:
2915 // A simple specific value: use explicit cast.
2916 expr
->expr
= mputprintf(expr
->expr
, "%s(",
2917 my_governor
->get_genname_template(my_scope
).c_str());
2918 u
.specific_value
->generate_code_expr(expr
);
2919 expr
->expr
= mputc(expr
->expr
, ')');
2922 // A simple unfoldable referenced template.
2923 if (!get_needs_conversion()) {
2924 u
.ref
.ref
->generate_code(expr
);
2926 Type
*my_gov
= get_expr_governor(Type::EXPECTED_TEMPLATE
)
2927 ->get_type_refd_last();
2928 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
2929 ->get_field_type(u
.ref
.ref
->get_subrefs(),
2930 Type::EXPECTED_TEMPLATE
)->get_type_refd_last();
2931 if (!my_gov
|| !refd_gov
|| my_gov
== refd_gov
)
2932 FATAL_ERROR("Template::generate_code_expr()");
2933 expression_struct expr_tmp
;
2934 Code::init_expr(&expr_tmp
);
2935 const string
& tmp_id1
= get_temporary_id();
2936 const char *tmp_id_str1
= tmp_id1
.c_str();
2937 const string
& tmp_id2
= get_temporary_id();
2938 const char *tmp_id_str2
= tmp_id2
.c_str();
2939 expr
->preamble
= mputprintf(expr
->preamble
,
2940 "%s %s;\n", refd_gov
->get_genname_template(my_scope
).c_str(),
2942 expr_tmp
.expr
= mputprintf(expr_tmp
.expr
, "%s = ", tmp_id_str1
);
2943 u
.ref
.ref
->generate_code(&expr_tmp
);
2944 expr
->preamble
= Code::merge_free_expr(expr
->preamble
, &expr_tmp
);
2945 expr
->preamble
= mputprintf(expr
->preamble
,
2947 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
2948 "and `%s' are not compatible at run-time\");\n",
2949 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str2
,
2950 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
2951 ->get_scope_mod()).c_str(), tmp_id_str2
, tmp_id_str1
, my_gov
2952 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
2953 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_id_str2
);
2956 case TEMPLATE_INVOKE
:
2957 generate_code_expr_invoke(expr
);
2963 // if none of the above methods are applicable use the most generic and
2964 // least efficient solution
2965 // create a temporary object, initialize it and use it in the expression
2966 const string
& tmp_id
= get_temporary_id();
2967 const char *tmp_id_str
= tmp_id
.c_str();
2969 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
2970 my_governor
->get_genname_template(my_scope
).c_str(), tmp_id_str
);
2971 set_genname_recursive(tmp_id
);
2972 expr
->preamble
= generate_code_init(expr
->preamble
, tmp_id_str
);
2973 if (template_restriction
!= TR_NONE
)
2974 expr
->preamble
= Template::generate_restriction_check_code(expr
->preamble
,
2975 tmp_id_str
, template_restriction
);
2976 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
2979 char *Template::generate_code_init(char *str
, const char *name
)
2981 if (get_code_generated()) return str
;
2982 set_code_generated();
2984 str
= err_descr
->generate_code_init_str(str
, string(name
)+"_err_descr");
2986 switch (templatetype
) {
2995 str
= mputprintf(str
, "%s = %s;\n", name
, get_single_expr(false).c_str());
2997 case SPECIFIC_VALUE
:
2998 if (get_code_section() == CS_POST_INIT
)
2999 str
= u
.specific_value
->rearrange_init_code(str
);
3000 str
= u
.specific_value
->generate_code_init(str
, name
);
3003 str
= generate_code_init_refd(str
, name
);
3005 case TEMPLATE_INVOKE
:
3006 if (get_code_section() == CS_POST_INIT
)
3007 str
= rearrange_init_code_invoke(str
, my_scope
->get_scope_mod_gen());
3008 str
= generate_code_init_invoke(str
, name
);
3011 case INDEXED_TEMPLATE_LIST
:
3012 str
= generate_code_init_seof(str
, name
);
3014 case NAMED_TEMPLATE_LIST
:
3015 str
= generate_code_init_se(str
, name
);
3017 case VALUE_LIST_ALL_FROM
:
3018 str
= generate_code_init_all_from_list(str
, name
);
3021 str
= generate_code_init_all_from(str
, name
);
3024 str
= generate_code_init_list(str
, name
, false);
3026 case COMPLEMENTED_LIST
:
3027 str
= generate_code_init_list(str
, name
, true);
3030 if (get_code_section() == CS_POST_INIT
)
3031 str
= u
.value_range
->rearrange_init_code(str
);
3032 str
= u
.value_range
->generate_code_init(str
, name
);
3034 case SUPERSET_MATCH
:
3035 str
= generate_code_init_set(str
, name
, true);
3038 str
= generate_code_init_set(str
, name
, false);
3040 case PERMUTATION_MATCH
:
3041 warning("Don't know how to init PERMUT");
3042 str
= mputprintf(str
, "/* FIXME: PERMUT goes here, name=%s*/\n", name
);
3044 case TEMPLATE_ERROR
:
3045 case TEMPLATE_NOTUSED
:
3047 FATAL_ERROR("Template::generate_code_init()");
3049 if (length_restriction
) {
3050 if (get_code_section() == CS_POST_INIT
)
3051 str
= length_restriction
->rearrange_init_code(str
);
3052 str
= length_restriction
->generate_code_init(str
, name
);
3054 if (is_ifpresent
) str
= mputprintf(str
, "%s.set_ifpresent();\n", name
);
3056 str
= mputprintf(str
, "%s.set_err_descr(&%s_err_descr);\n", name
, name
);
3061 char *Template::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
3063 switch (templatetype
) {
3064 case SPECIFIC_VALUE
:
3065 str
= u
.specific_value
->rearrange_init_code(str
);
3068 str
= rearrange_init_code_refd(str
, usage_mod
);
3070 case TEMPLATE_INVOKE
:
3071 str
= rearrange_init_code_invoke(str
, usage_mod
);
3075 case COMPLEMENTED_LIST
:
3076 case SUPERSET_MATCH
:
3078 case PERMUTATION_MATCH
:
3079 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
3080 str
= u
.templates
->get_t_byIndex(i
)->rearrange_init_code(str
, usage_mod
);
3082 case NAMED_TEMPLATE_LIST
:
3083 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
3084 str
= u
.named_templates
->get_nt_byIndex(i
)->get_template()
3085 ->rearrange_init_code(str
, usage_mod
);
3087 case INDEXED_TEMPLATE_LIST
:
3088 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
3089 str
= u
.indexed_templates
->get_it_byIndex(i
)->get_template()
3090 ->rearrange_init_code(str
, usage_mod
);
3093 str
= u
.value_range
->rearrange_init_code(str
);
3098 if (length_restriction
) str
= length_restriction
->rearrange_init_code(str
);
3102 bool Template::use_single_expr_for_init()
3104 Template
*t_last
= get_template_refd_last();
3105 // return false in case of unfoldable references
3106 if (t_last
->templatetype
== TEMPLATE_REFD
) return false;
3107 // return false if t_last is in a different module
3108 if (t_last
->my_scope
->get_scope_mod_gen() != my_scope
->get_scope_mod_gen())
3110 // return false if t_last cannot be represented by a single expression
3111 if (!t_last
->has_single_expr()) return false;
3112 // return true if t_last is a generic wildcard, string pattern, etc.
3113 if (t_last
->templatetype
!= SPECIFIC_VALUE
) return true;
3114 // examine the specific value
3115 Value
*v_last
= t_last
->u
.specific_value
->get_value_refd_last();
3116 switch (v_last
->get_valuetype()) {
3118 // do not calculate expressions again
3120 case Value::V_REFD
: {
3121 // v_last is an unfoldable value reference
3122 // the scope of the definition that v_last refers to
3124 v_last
->get_reference()->get_refd_assignment()->get_my_scope();
3125 for (Scope
*t_scope
= my_scope
; t_scope
;
3126 t_scope
= t_scope
->get_parent_scope()) {
3127 // return true if the referred definition is in the same scope
3128 // as this or in one of the parent scopes of this
3129 if (t_scope
== v_scope
) return true;
3131 // otherwise return false
3134 // return true only if v_last is defined in the same module as this
3135 return v_last
->get_my_scope()->get_scope_mod_gen() ==
3136 my_scope
->get_scope_mod_gen();
3140 char *Template::generate_code_init_refd(char *str
, const char *name
)
3142 if (use_single_expr_for_init() && has_single_expr()) {
3143 str
= mputprintf(str
, "%s = %s;\n", name
,
3144 get_single_expr(false).c_str());
3146 expression_struct expr
;
3147 Code::init_expr(&expr
);
3148 bool use_ref_for_codegen
= true;
3149 if (get_code_section() == CS_POST_INIT
) {
3150 // the referencing template is a part of a non-parameterized template
3151 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
3152 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
3153 // the reference points to (a field of) a template
3154 if (ass
->get_FormalParList()) {
3155 // the referred template is parameterized
3156 // generate the initialization sequence first for all dependent
3157 // non-parameterized templates
3158 str
= rearrange_init_code_refd(str
, my_scope
->get_scope_mod_gen());
3159 } else if (ass
->get_my_scope()->get_scope_mod_gen() ==
3160 my_scope
->get_scope_mod_gen()) {
3161 // the referred template is non-parameterized
3162 // use a different algorithm for code generation
3163 str
= generate_rearrange_init_code_refd(str
, &expr
);
3164 use_ref_for_codegen
= false;
3168 if (use_ref_for_codegen
) u
.ref
.ref
->generate_code_const_ref(&expr
);
3169 if (expr
.preamble
|| expr
.postamble
) {
3170 // the expressions within reference need temporary objects
3171 str
= mputstr(str
, "{\n");
3172 str
= mputstr(str
, expr
.preamble
);
3173 if (use_runtime_2
&& get_needs_conversion()) {
3174 const string
& tmp_id
= get_temporary_id();
3175 const char *tmp_id_str
= tmp_id
.c_str();
3176 Type
*my_gov
= my_governor
->get_type_refd_last();
3177 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
3178 ->get_type_refd_last();
3179 if (!my_gov
|| !refd_gov
)
3180 FATAL_ERROR("Template::generate_code_init_refd()");
3181 str
= mputprintf(str
,
3183 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3184 "and `%s' are not compatible at run-time\");\n",
3185 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3186 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
3187 ->get_scope_mod()).c_str(), tmp_id_str
, expr
.expr
, my_gov
3188 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
3189 str
= mputprintf(str
, "%s = %s;\n", name
, tmp_id_str
);
3191 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
3193 str
= mputstr(str
, expr
.postamble
);
3194 str
= mputstr(str
, "}\n");
3196 // the reference does not need temporary objects
3197 if (use_runtime_2
&& get_needs_conversion()) {
3198 const string
& tmp_id
= get_temporary_id();
3199 const char *tmp_id_str
= tmp_id
.c_str();
3200 Type
*my_gov
= my_governor
->get_type_refd_last();
3201 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
3202 ->get_type_refd_last();
3203 if (!my_gov
|| !refd_gov
)
3204 FATAL_ERROR("Template::generate_code_init_refd()");
3205 str
= mputprintf(str
,
3207 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3208 "and `%s' are not compatible at run-time\");\n",
3209 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3210 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
3211 ->get_scope_mod()).c_str(), tmp_id_str
, expr
.expr
, my_gov
3212 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
3213 str
= mputprintf(str
, "%s = %s;\n", name
, tmp_id_str
);
3215 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
3218 Code::free_expr(&expr
);
3223 char *Template::generate_code_init_invoke(char *str
, const char *name
)
3225 expression_struct expr
;
3226 Code::init_expr(&expr
);
3227 expr
.expr
= mputprintf(expr
.expr
, "%s = ", name
);
3228 generate_code_expr_invoke(&expr
);
3229 return Code::merge_free_expr(str
, &expr
);
3232 char *Template::generate_rearrange_init_code_refd(char *str
,
3233 expression_struct
*expr
)
3235 /** Initially we can assume that:
3236 * - this is a referenced template and a part of a non-parameterized
3238 * - u.ref.ref points to (a field of) a non-parameterized template within
3239 * the same module as \a this.
3240 * - this ensures that the do-while loop will run at least twice (i.e. the
3241 * first continue statement will be reached in the first iteration) */
3242 stack
<FieldOrArrayRef
> refstack
;
3244 // first try to find the smallest dependent template
3246 if (t
->templatetype
== TEMPLATE_REFD
) {
3247 Common::Assignment
*ass
= t
->u
.ref
.ref
->get_refd_assignment();
3248 /** Don't follow the reference if:
3249 * - the referenced definition is not a template
3250 * - the referenced template is parameterized or
3251 * - the referenced template is in different module */
3252 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
&&
3253 ass
->get_FormalParList() == 0 &&
3254 ass
->get_my_scope()->get_scope_mod_gen() ==
3255 my_scope
->get_scope_mod_gen()) {
3256 // accumulate the sub-references of the referred reference
3257 FieldOrArrayRefs
*subrefs
= t
->u
.ref
.ref
->get_subrefs();
3259 for (size_t i
= subrefs
->get_nof_refs(); i
> 0; i
--)
3260 refstack
.push(subrefs
->get_ref(i
- 1));
3262 // jump to the referred top-level template
3263 t
= ass
->get_Template();
3264 // start the iteration from the beginning
3266 // stop otherwise: the reference cannot be followed
3269 // stop if there are no sub-references
3270 if (refstack
.empty()) break;
3271 // take the topmost sub-reference
3272 FieldOrArrayRef
*subref
= refstack
.top();
3273 if (subref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
3274 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
3275 // the field reference can be followed
3276 t
= t
->u
.named_templates
->get_nt_byName(*subref
->get_id())
3279 // trying to follow an array reference
3280 if (t
->templatetype
!= TEMPLATE_LIST
) break;
3281 Value
*array_index
= subref
->get_val()->get_value_refd_last();
3282 if (array_index
->get_valuetype() != Value::V_INT
) break;
3283 // the index is available at compilation time
3284 Int index
= array_index
->get_val_Int()->get_val();
3285 // index transformation in case of arrays
3286 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
3287 index
-= t
->my_governor
->get_dimension()->get_offset();
3288 t
= t
->get_listitem_byIndex(index
);
3290 // the topmost sub-reference was processed
3291 // it can be erased from the stack
3294 // the smallest dependent template is now in t
3295 // generate the initializer sequence for t
3296 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
3297 // the equivalent C++ code of the referenced template is composed of the
3298 // genname of t and the remained sub-references in refstack
3299 expr
->expr
= mputstr(expr
->expr
, t
->get_genname_own(my_scope
).c_str());
3300 while (!refstack
.empty()) {
3301 FieldOrArrayRef
*subref
= refstack
.pop();
3302 if (subref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
3303 expr
->expr
= mputprintf(expr
->expr
, ".%s()",
3304 subref
->get_id()->get_name().c_str());
3306 expr
->expr
= mputc(expr
->expr
, '[');
3307 subref
->get_val()->generate_code_expr(expr
);
3308 expr
->expr
= mputc(expr
->expr
, ']');
3314 bool Template::compile_time() const
3316 switch (templatetype
) {
3318 case VALUE_LIST_ALL_FROM
:
3320 case TEMPLATE_ERROR
: /**< erroneous template */
3321 case TEMPLATE_NOTUSED
: /**< not used symbol (-) */
3322 case OMIT_VALUE
: /**< omit */
3323 case ANY_VALUE
: /**< any value (?) */
3324 case ANY_OR_OMIT
: /**< any or omit (*) */
3325 case SPECIFIC_VALUE
: /**< specific value */
3326 case TEMPLATE_REFD
: /**< reference to another template */
3327 case VALUE_RANGE
: /**< value range match */
3328 case BSTR_PATTERN
: /**< bitstring pattern */
3329 case HSTR_PATTERN
: /**< hexstring pattern */
3330 case OSTR_PATTERN
: /**< octetstring pattern */
3331 case CSTR_PATTERN
: /**< character string pattern */
3332 case USTR_PATTERN
: /**< universal charstring pattern */
3333 case TEMPLATE_INVOKE
:
3334 // Simple templates can be computed at compile time
3337 // "Complex" templates need to look at all elements
3340 case COMPLEMENTED_LIST
:
3341 case SUPERSET_MATCH
:
3343 case PERMUTATION_MATCH
:
3344 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
3345 if (u
.templates
->get_t_byIndex(i
)->compile_time()) continue;
3348 case NAMED_TEMPLATE_LIST
:
3349 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
3350 if (!u
.named_templates
->get_nt_byIndex(i
)->get_template()->compile_time())
3353 case INDEXED_TEMPLATE_LIST
:
3354 for (size_t i
= 0; i
<u
.indexed_templates
->get_nof_its(); i
++)
3355 if (!u
.indexed_templates
->get_it_byIndex(i
)->get_template()->compile_time())
3360 return true; // not reached
3363 char *Template::generate_code_init_seof(char *str
, const char *name
)
3365 switch (templatetype
) {
3366 case TEMPLATE_LIST
: {
3367 size_t nof_ts
= u
.templates
->get_nof_ts();
3369 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3374 Type
*t_last
= my_governor
->get_type_refd_last();
3376 if (t_last
->get_typetype() == Type::T_ARRAY
) {
3377 // take the start index from the array dimension
3378 index_offset
= t_last
->get_dimension()->get_offset();
3380 // indexing always starts from zero
3384 const string
& oftype_name
=
3385 t_last
->get_ofType()->get_genname_template(my_scope
);
3386 const char *oftype_name_str
= oftype_name
.c_str();
3388 ReferenceChain
refch (this, "While searching template");
3389 if (!flattened
|| my_scope
->get_statementblock_scope()) { // this "if" may be redundant if all non-var templates are flattened
3390 str
= mputstr(str
, "// this is a var template\n");
3392 if (compile_time()) goto compile_time
;
3393 // run-time, variable sized init
3395 // This is a record-of var template, like this:
3396 // var template rec_of_int vt_r := {
3397 // 1, 2, 3, permutation(10, all from x, 20), 4, 5 }
3398 // ^^^^^^^--- these ------------------------^^^^^
3399 // are known at compile time, but the length of the "all from"
3400 // is only known at run time.
3401 // Collect the indices where there is an "all from".
3402 dynamic_array
<int> variables
;
3403 size_t fixed_part
= 0;
3404 if (has_permutation
) {
3405 for (size_t i
= 0; i
< nof_ts
; i
++) {
3406 Template
*t
= u
.templates
->get_t_byIndex(i
);
3407 if (t
->templatetype
== PERMUTATION_MATCH
) {
3408 size_t num_p
= t
->u
.templates
->get_nof_ts();
3409 // t->u.templates is 2: "hello" and all from ...
3410 for (size_t j
= 0; j
< num_p
; ++j
) {
3411 Template
*subt
= t
->u
.templates
->get_t_byIndex(j
);
3412 if (subt
->templatetype
== ALL_FROM
) {
3421 char* str_preamble
= 0;
3422 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3423 (unsigned long)fixed_part
);
3426 for (size_t i
= 0; i
< nof_ts
; i
++) {
3427 Template
*t
= u
.templates
->get_t_byIndex(i
);
3428 for (size_t k
= 0, v
= variables
.size(); k
< v
; ++k
) {
3429 if (t
->templatetype
!= PERMUTATION_MATCH
) continue; // ?? really nothing to do ??
3430 Template
*subt
= t
->u
.templates
->get_t_byIndex(variables
[k
]);
3431 if (subt
->templatetype
== ALL_FROM
) {
3432 Value
*refv
= subt
->u
.all_from
->u
.specific_value
;
3433 // don't call get_Value(), it rips out the value from the template
3435 if (refv
->get_valuetype()!=Value::V_REFD
) FATAL_ERROR("%s", __FUNCTION__
);
3436 Common::Reference
*ref
= refv
->get_reference();
3437 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3438 Common::Assignment
*ass
= ref
->get_refd_assignment();
3440 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3442 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3444 // in case of parametrised references:
3445 // - temporary parameters need to be declared (stored in str_preamble)
3446 // - the same temporary needs to be used at each call (generate_code_cached call)
3447 expression_struct expr
;
3448 Code::init_expr(&expr
);
3450 ref_pard
->generate_code_cached(&expr
);
3451 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3453 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3455 Code::free_expr(&expr
);
3458 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3460 expression_struct expr
;
3461 Code::init_expr(&expr
);
3463 subrefs
->generate_code(&expr
, ass
);
3464 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3466 Code::free_expr(&expr
);
3470 switch(ass
->get_asstype()) {
3471 case Common::Assignment::A_CONST
:
3472 case Common::Assignment::A_EXT_CONST
:
3473 case Common::Assignment::A_MODULEPAR
:
3474 case Common::Assignment::A_VAR
:
3475 case Common::Assignment::A_PAR_VAL_IN
:
3476 case Common::Assignment::A_PAR_VAL_OUT
:
3477 case Common::Assignment::A_PAR_VAL_INOUT
:
3478 case Common::Assignment::A_FUNCTION_RVAL
:
3479 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3480 if (ass
->get_Type()->field_is_optional(subrefs
)) {
3481 str_set_size
= mputstrn(str_set_size
, "()", 2);
3488 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3493 str
= mputstr(str
, str_preamble
);
3494 str
= mputstr(str
, str_set_size
);
3499 str
= mputstrn(str
, ");\n", 3); // finally done set_size
3502 string skipper
, hopper
;
3503 for (size_t i
= 0; i
< nof_ts
; i
++) {
3504 Template
*t
= u
.templates
->get_t_byIndex(i
);
3505 switch (t
->templatetype
) {
3508 case PERMUTATION_MATCH
: {
3509 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
3510 for (size_t j
= 0; j
< nof_perm_ts
; j
++) {
3511 Int
ix(index_offset
+ index
+ j
);
3512 Template
*permut_elem
= t
->u
.templates
->get_t_byIndex(j
);
3513 if (permut_elem
->templatetype
== ALL_FROM
) {
3514 expression_struct expr
;
3515 Code::init_expr(&expr
);
3516 switch (permut_elem
->u
.all_from
->templatetype
) {
3517 case SPECIFIC_VALUE
: {
3518 Value
*spec
= permut_elem
->u
.all_from
->u
.specific_value
;
3519 switch (spec
->get_valuetype()) {
3520 case Common::Value::V_REFD
: {
3521 Common::Reference
*ref
= spec
->get_reference();
3523 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3525 ref_pard
->generate_code_cached(&expr
);
3527 ref
->generate_code(&expr
);
3529 Common::Assignment
* ass
= ref
->get_refd_assignment();
3530 switch(ass
->get_asstype()) {
3531 case Common::Assignment::A_CONST
:
3532 case Common::Assignment::A_EXT_CONST
:
3533 case Common::Assignment::A_MODULEPAR
:
3534 case Common::Assignment::A_VAR
:
3535 case Common::Assignment::A_PAR_VAL_IN
:
3536 case Common::Assignment::A_PAR_VAL_OUT
:
3537 case Common::Assignment::A_PAR_VAL_INOUT
:
3538 case Common::Assignment::A_FUNCTION_RVAL
:
3539 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3540 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
3541 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
3550 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3557 FATAL_ERROR("ttype %d", permut_elem
->u
.all_from
->templatetype
);
3560 str
= mputprintf(str
,
3561 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3564 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3565 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3568 str
= mputstrn(str
, "}\n", 2);
3570 skipper
+= expr
.expr
;
3571 skipper
+= ".n_elem() /* 3005 */ ";
3572 Code::free_expr(&expr
);
3575 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3576 (Int2string(ix
) + skipper
).c_str(), oftype_name_str
);
3579 // do not consider index_offset in case of permutation indicators
3580 str
= mputprintf(str
, "%s.add_permutation(%lu%s, %lu%s);\n", name
,
3581 (unsigned long)index
, hopper
.c_str(),
3582 (unsigned long)(index
+ nof_perm_ts
- 1), skipper
.c_str());
3584 t
->set_code_generated();
3585 index
+= nof_perm_ts
;
3589 str
= t
->generate_code_init_seof_element(str
, name
,
3590 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3592 case TEMPLATE_NOTUSED
:
3603 if (!has_permutation
&& has_allfrom()) {
3604 for (size_t i
= 0; i
< nof_ts
; i
++) {
3605 Template
*t
= u
.templates
->get_t_byIndex(i
);
3606 if (t
->templatetype
== ALL_FROM
) {
3613 char* str_preamble
= 0;
3614 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3615 (unsigned long)fixed_part
);
3618 for (size_t i
= 0, v
= variables
.size(); i
< v
; ++i
) {
3619 Template
*t
= u
.templates
->get_t_byIndex(variables
[i
]);
3620 if (t
->templatetype
== ALL_FROM
) {
3621 Value
*refv
= t
->u
.all_from
->u
.specific_value
;
3622 // don't call get_Value(), it rips out the value from the template
3623 if (refv
->get_valuetype()!=Value::V_REFD
) FATAL_ERROR("%s", __FUNCTION__
);
3624 Common::Reference
*ref
= refv
->get_reference();
3625 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3626 Common::Assignment
*ass
= ref
->get_refd_assignment();
3627 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3628 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3630 // in case of parametrised references:
3631 // - temporary parameters need to be declared (stored in str_preamble)
3632 // - the same temporary needs to be used at each call (generate_code_cached call)
3633 expression_struct expr
;
3634 Code::init_expr(&expr
);
3636 ref_pard
->generate_code_cached(&expr
);
3637 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3639 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3640 Code::free_expr(&expr
);
3643 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3645 expression_struct expr
;
3646 Code::init_expr(&expr
);
3647 subrefs
->generate_code(&expr
, ass
);
3648 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3649 Code::free_expr(&expr
);
3653 switch(ass
->get_asstype()) {
3654 case Common::Assignment::A_CONST
:
3655 case Common::Assignment::A_EXT_CONST
:
3656 case Common::Assignment::A_MODULEPAR
:
3657 case Common::Assignment::A_VAR
:
3658 case Common::Assignment::A_PAR_VAL_IN
:
3659 case Common::Assignment::A_PAR_VAL_OUT
:
3660 case Common::Assignment::A_PAR_VAL_INOUT
:
3661 case Common::Assignment::A_FUNCTION_RVAL
:
3662 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3663 if (ass
->get_Type()->field_is_optional(subrefs
)) {
3664 str_set_size
= mputstrn(str_set_size
, "()", 2);
3671 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3674 str
= mputstr(str
, str_preamble
);
3675 str
= mputstr(str
, str_set_size
);
3678 str
= mputstrn(str
, ");\n", 3); // finally done set_size
3682 for (size_t i
= 0; i
< nof_ts
; i
++) {
3683 Template
*t
= u
.templates
->get_t_byIndex(i
);
3684 Int
ix(index_offset
+ i
);
3685 switch (t
->templatetype
) {
3687 expression_struct expr
;
3688 Code::init_expr(&expr
);
3689 switch (t
->u
.all_from
->templatetype
) {
3690 case SPECIFIC_VALUE
: {
3691 Value
*spec
= t
->u
.all_from
->u
.specific_value
;
3692 switch (spec
->get_valuetype()) {
3693 case Common::Value::V_REFD
: {
3694 Common::Reference
*ref
= spec
->get_reference();
3695 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3697 ref_pard
->generate_code_cached(&expr
);
3699 ref
->generate_code(&expr
);
3701 Common::Assignment
* ass
= ref
->get_refd_assignment();
3702 switch(ass
->get_asstype()) {
3703 case Common::Assignment::A_CONST
:
3704 case Common::Assignment::A_EXT_CONST
:
3705 case Common::Assignment::A_MODULEPAR
:
3706 case Common::Assignment::A_VAR
:
3707 case Common::Assignment::A_PAR_VAL_IN
:
3708 case Common::Assignment::A_PAR_VAL_OUT
:
3709 case Common::Assignment::A_PAR_VAL_INOUT
:
3710 case Common::Assignment::A_FUNCTION_RVAL
:
3711 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3712 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
3713 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
3722 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3727 FATAL_ERROR("ttype %d", t
->u
.all_from
->templatetype
);
3730 str
= mputprintf(str
,
3731 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3733 str
= t
->generate_code_init_seof_element(str
, name
,
3734 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3736 str
= mputstrn(str
, "}\n", 2);
3738 skipper
+= expr
.expr
;
3739 skipper
+= ".n_elem() ";
3740 Code::free_expr(&expr
);
3741 t
->set_code_generated();
3745 str
= t
->generate_code_init_seof_element(str
, name
,
3746 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3748 case TEMPLATE_NOTUSED
:
3759 // setting the size first
3761 str
= mputprintf(str
, "%s.set_size(%lu);\n", name
, (unsigned long) get_nof_listitems());
3762 // determining the index offset based on the governor
3765 for (size_t i
= 0; i
< nof_ts
; i
++) {
3766 Template
*t
= u
.templates
->get_t_byIndex(i
);
3767 switch (t
->templatetype
) {
3768 case PERMUTATION_MATCH
: {
3769 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
3770 for (size_t j
= 0; j
< nof_perm_ts
; j
++) {
3771 Int
ix(index_offset
+ index
+ j
);
3772 str
= t
->u
.templates
->get_t_byIndex(j
)
3773 ->generate_code_init_seof_element(str
, name
,
3774 Int2string(ix
).c_str(), oftype_name_str
);
3776 // do not consider index_offset in case of permutation indicators
3777 str
= mputprintf(str
, "%s.add_permutation(%lu, %lu);\n", name
,
3778 (unsigned long)index
, (unsigned long) (index
+ nof_perm_ts
- 1));
3779 t
->set_code_generated();
3780 index
+= nof_perm_ts
;
3784 str
= t
->generate_code_init_seof_element(str
, name
,
3785 Int2string(index_offset
+ index
).c_str(), oftype_name_str
);
3788 case TEMPLATE_NOTUSED
:
3793 case INDEXED_TEMPLATE_LIST
: {
3794 size_t nof_its
= u
.indexed_templates
->get_nof_its();
3796 Type
*t_last
= my_governor
->get_type_refd_last();
3797 const string
& oftype_name
=
3798 t_last
->get_ofType()->get_genname_template(my_scope
);
3799 const char *oftype_name_str
= oftype_name
.c_str();
3800 // There's no need to generate a set_size call here. To do that, we
3801 // should know the size of the base template, which is not available
3803 for (size_t i
= 0; i
< nof_its
; i
++) {
3804 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
3805 const string
& tmp_id_1
= get_temporary_id();
3806 str
= mputstr(str
, "{\n");
3807 Value
*index
= (it
->get_index()).get_val();
3808 if (index
->get_valuetype() != Value::V_INT
) {
3809 const string
& tmp_id_2
= get_temporary_id();
3810 str
= mputprintf(str
, "int %s;\n", tmp_id_2
.c_str());
3811 str
= index
->generate_code_init(str
, tmp_id_2
.c_str());
3812 str
= mputprintf(str
, "%s& %s = %s[%s];\n", oftype_name_str
,
3813 tmp_id_1
.c_str(), name
, tmp_id_2
.c_str());
3815 str
= mputprintf(str
, "%s& %s = %s[%s];\n", oftype_name_str
,
3816 tmp_id_1
.c_str(), name
,
3817 Int2string(index
->get_val_Int()->get_val()).c_str());
3819 str
= it
->get_template()->generate_code_init(str
, tmp_id_1
.c_str());
3820 str
= mputstr(str
, "}\n");
3823 // It seems to be impossible in this case.
3824 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3828 FATAL_ERROR("Template::generate_code_init_seof()");
3834 char *Template::generate_code_init_seof_element(char *str
, const char *name
,
3835 const char* index
, const char *element_type_genname
)
3837 if (needs_temp_ref()) {
3838 const string
& tmp_id
= get_temporary_id();
3839 str
= mputprintf(str
, "{\n"
3840 "%s& %s = %s[%s];\n",
3841 element_type_genname
, tmp_id
.c_str(), name
, index
);
3842 str
= generate_code_init(str
, tmp_id
.c_str());
3843 str
= mputstr(str
, "}\n");
3845 char *embedded_name
= mprintf("%s[%s]", name
, index
);
3846 str
= generate_code_init(str
, embedded_name
);
3847 Free(embedded_name
);
3852 char *Template::generate_code_init_all_from(char *str
, const char *name
)
3854 // we are ALL_FROM, hence u.all_from
3855 switch (u
.all_from
->templatetype
) {
3856 case SPECIFIC_VALUE
: {
3857 Value
*spec
= u
.all_from
->u
.specific_value
;
3858 switch (spec
->get_valuetype()) {
3859 case Common::Value::V_REFD
: {
3860 Common::Reference
*ref
= spec
->get_reference();
3861 expression_struct expr
;
3862 Code::init_expr(&expr
);
3863 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3865 ref_pard
->generate_code_cached(&expr
);
3867 ref
->generate_code(&expr
);
3869 Common::Assignment
* ass
= ref
->get_refd_assignment();
3870 switch(ass
->get_asstype()) {
3871 case Common::Assignment::A_CONST
:
3872 case Common::Assignment::A_EXT_CONST
:
3873 case Common::Assignment::A_MODULEPAR
:
3874 case Common::Assignment::A_VAR
:
3875 case Common::Assignment::A_PAR_VAL_IN
:
3876 case Common::Assignment::A_PAR_VAL_OUT
:
3877 case Common::Assignment::A_PAR_VAL_INOUT
:
3878 case Common::Assignment::A_FUNCTION_RVAL
:
3879 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
3880 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
3881 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
3888 str
= mputprintf(str
, "%s = %s[i_i];\n", name
, expr
.expr
);
3889 // The caller will have to provide the for cycle with this variable
3890 Code::free_expr(&expr
);
3902 char *Template::generate_code_init_all_from_list(char *str
, const char *name
)
3904 // FIXME: this is the third instance
3905 expression_struct expr
;
3906 Code::init_expr(&expr
);
3907 switch (u
.all_from
->templatetype
) {
3908 case SPECIFIC_VALUE
: {
3909 Value
*spec
= u
.all_from
->u
.specific_value
;
3910 switch (spec
->get_valuetype()) {
3911 case Common::Value::V_REFD
: {
3912 Common::Reference
*ref
= spec
->get_reference();
3913 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3915 ref_pard
->generate_code_cached(&expr
);
3917 ref
->generate_code(&expr
);
3920 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3926 FATAL_ERROR("ttype %d", u
.all_from
->templatetype
);
3931 str
= mputstr(str
, expr
.preamble
);
3933 str
= mputprintf(str
,
3934 "%s.set_type(VALUE_LIST, %s.n_elem());\n"
3935 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3939 string
embedded_name(name
);
3940 embedded_name
+= ".list_item(i_i)";
3941 str
= generate_code_init_all_from(str
, embedded_name
.c_str());
3942 str
= mputstrn(str
, "}\n", 2);
3944 Code::free_expr(&expr
);
3948 char *Template::generate_code_init_se(char *str
, const char *name
)
3949 { // named template list
3950 size_t nof_nts
= u
.named_templates
->get_nof_nts();
3951 Type
*type
= my_governor
->get_type_refd_last();
3952 if (type
->get_nof_comps() > 0) {
3953 for (size_t i
= 0; i
< nof_nts
; i
++) {
3954 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
3955 const Identifier
& fieldname
= nt
->get_name();
3956 const char *fieldname_str
= 0;
3958 if (type
->get_typetype()==Type::T_ANYTYPE
) {
3959 at
+= fieldname
.get_name();
3960 fieldname_str
= at
.c_str();
3963 fieldname_str
= fieldname
.get_name().c_str();
3965 Template
*t
= nt
->get_template();
3966 if (t
->needs_temp_ref()) {
3968 if (type
->get_typetype() == Type::T_SIGNATURE
) {
3969 field_type
= type
->get_signature_parameters()
3970 ->get_param_byName(fieldname
)->get_type();
3972 field_type
= type
->get_comp_byName(fieldname
)->get_type();
3974 const string
& tmp_id
= get_temporary_id();
3975 const char *tmp_id_str
= tmp_id
.c_str();
3976 str
= mputprintf(str
, "{\n"
3977 "%s& %s = %s.%s();\n",
3978 field_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3979 name
, fieldname_str
);
3980 str
= t
->generate_code_init(str
, tmp_id_str
);
3981 str
= mputstr(str
, "}\n");
3983 char *embedded_name
= mprintf("%s.%s()", name
, fieldname_str
);
3984 str
= t
->generate_code_init(str
, embedded_name
);
3985 Free(embedded_name
);
3989 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3994 char *Template::generate_code_init_list(char *str
, const char *name
,
3995 bool is_complemented
) // VALUE_LIST or COMPLEMENTED_LIST
3997 size_t nof_ts
= u
.templates
->get_nof_ts();
3998 const string
& type_name
= my_governor
->get_genname_template(my_scope
);
3999 const char *type_name_str
= type_name
.c_str();
4001 dynamic_array
<int> variables
;
4002 size_t fixed_part
= 0;
4003 for (size_t i
= 0; i
< nof_ts
; ++i
) {
4004 Template
*t
= u
.templates
->get_t_byIndex(i
);
4005 if (t
->templatetype
== ALL_FROM
) {
4011 if (variables
.size() > 0) {
4012 char* str_preamble
= 0;
4013 char* str_set_type
= mprintf("%s.set_type(%s, %lu", name
,
4014 (is_complemented
? "COMPLEMENTED_LIST" : "VALUE_LIST"),
4015 (unsigned long)fixed_part
);
4016 // The code to compute the number of elements at run time (the variable part).
4017 // This is the sum of sizes of "all from"s.
4018 for (size_t v
= 0, vs
= variables
.size(); v
< vs
; ++v
) {
4019 Template
*vt
= u
.templates
->get_t_byIndex(variables
[v
]);
4020 if (vt
->templatetype
!= ALL_FROM
) FATAL_ERROR("must be ALL_FROM");
4021 if (vt
->u
.all_from
->templatetype
!= SPECIFIC_VALUE
) FATAL_ERROR("not value");
4022 Value
*val
= vt
->u
.all_from
->u
.specific_value
;
4023 if (val
->get_valuetype() != Value::V_REFD
) FATAL_ERROR("ref expected from val");
4024 Common::Reference
*ref
= val
->get_reference();
4025 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
4026 Common::Assignment
*ass
= ref
->get_refd_assignment();
4027 if (!ass
) FATAL_ERROR("Could not grab ass!");
4029 str_set_type
= mputstrn(str_set_type
, " + ", 3);
4031 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4033 // in case of parametrised references:
4034 // - temporary parameters need to be declared (stored in str_preamble)
4035 // - the same temporary needs to be used at each call (generate_code_cached call)
4036 expression_struct expr
;
4037 Code::init_expr(&expr
);
4039 ref_pard
->generate_code_cached(&expr
);
4040 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4042 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
4044 Code::free_expr(&expr
);
4047 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
4049 expression_struct expr
;
4050 Code::init_expr(&expr
);
4052 subrefs
->generate_code(&expr
, ass
);
4053 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4055 Code::free_expr(&expr
);
4059 switch(ass
->get_asstype()) {
4060 case Common::Assignment::A_CONST
:
4061 case Common::Assignment::A_EXT_CONST
:
4062 case Common::Assignment::A_MODULEPAR
:
4063 case Common::Assignment::A_VAR
:
4064 case Common::Assignment::A_PAR_VAL_IN
:
4065 case Common::Assignment::A_PAR_VAL_OUT
:
4066 case Common::Assignment::A_PAR_VAL_INOUT
:
4067 case Common::Assignment::A_FUNCTION_RVAL
:
4068 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4069 if (ass
->get_Type()->field_is_optional(subrefs
)) {
4070 str_set_type
= mputstrn(str_set_type
, "()", 2);
4077 str_set_type
= mputstr(str_set_type
, ".n_elem()");
4080 str
= mputstr(str
, str_preamble
);
4081 str
= mputstr(str
, str_set_type
);
4086 str
= mputstrn(str
, ");\n", 3);
4088 string shifty
; // contains the expression used to calculate
4089 // the size increase due to the runtime expansion of "all from".
4090 // In nof_ts, each "all from" appears as 1, but actually contributes
4091 // more. So the increase (by which all elements after the "all from"
4092 // are shifted) is:Â target_of_all_from.n_elem()-1
4093 // This needs to be accumulated for each "all from".
4094 for (size_t vi
= 0; vi
< nof_ts
; ++vi
) {
4095 Template
*t
= u
.templates
->get_t_byIndex(vi
);
4096 switch (t
->templatetype
) {
4097 case VALUE_LIST_ALL_FROM
:
4098 FATAL_ERROR("VALUE_LIST_ALL_FROM not handled");
4100 expression_struct expr
;
4101 Code::init_expr(&expr
);
4103 switch (t
->u
.all_from
->templatetype
) {
4104 case SPECIFIC_VALUE
: {
4105 Value
*sv
= t
->u
.all_from
->u
.specific_value
;
4106 switch (sv
->get_valuetype()) {
4107 case Value::V_REFD
: {
4108 Common::Reference
*ref
= sv
->get_reference();
4109 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4111 ref_pard
->generate_code_cached(&expr
);
4113 ref
->generate_code(&expr
);
4115 Common::Assignment
* ass
= ref
->get_refd_assignment();
4116 switch(ass
->get_asstype()) {
4117 case Common::Assignment::A_CONST
:
4118 case Common::Assignment::A_EXT_CONST
:
4119 case Common::Assignment::A_MODULEPAR
:
4120 case Common::Assignment::A_VAR
:
4121 case Common::Assignment::A_PAR_VAL_IN
:
4122 case Common::Assignment::A_PAR_VAL_OUT
:
4123 case Common::Assignment::A_PAR_VAL_INOUT
:
4124 case Common::Assignment::A_FUNCTION_RVAL
:
4125 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4126 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
4127 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
4137 FATAL_ERROR("VT NOT HANDLED");
4138 } // switch valuetype
4142 FATAL_ERROR("ttype not handled");
4146 // All local variables should contain a single underscore,
4147 // to avoid potential clashes with field names.
4148 str
= mputprintf(str
, "for (int i_i= 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4151 if (t
->needs_temp_ref()) {
4152 // Not possible, because t->templatetype is ALL_FROM
4153 FATAL_ERROR("temp ref not handled");
4155 char *embedded_name
= mprintf("%s.list_item(%lu + i_i%s)", name
,
4156 (unsigned long) vi
, shifty
.c_str());
4157 str
= t
->generate_code_init(str
, embedded_name
);
4158 Free(embedded_name
);
4160 str
= mputstrn(str
, "}\n", 2);
4163 shifty
+= expr
.expr
;
4164 shifty
+= ".n_elem() /* 3303 */ ";
4166 Code::free_expr(&expr
);
4169 default: // "fixed one"
4170 if (t
->needs_temp_ref()) { // FIXME: this is copypasta from below / but may need to be changed
4171 const string
& tmp_id
= get_temporary_id();
4172 const char *tmp_id_str
= tmp_id
.c_str();
4173 str
= mputprintf(str
, "{\n"
4174 "%s& %s = %s.list_item(%lu);\n",
4175 type_name_str
, tmp_id_str
, name
, (unsigned long) vi
);
4176 str
= t
->generate_code_init(str
, tmp_id_str
);
4177 str
= mputstr(str
, "}\n");
4179 char *embedded_name
= mprintf("%s.list_item(%lu%s)", name
,
4180 (unsigned long) vi
, shifty
.c_str());
4181 str
= t
->generate_code_init(str
, embedded_name
);
4182 Free(embedded_name
);
4185 } // switch t->templatetype
4189 str
= mputprintf(str
, "%s.set_type(%s, %lu);\n", name
,
4190 is_complemented
? "COMPLEMENTED_LIST" : "VALUE_LIST",
4191 (unsigned long) nof_ts
);
4192 for (size_t i
= 0; i
< nof_ts
; i
++) {
4193 Template
*t
= u
.templates
->get_t_byIndex(i
);
4194 if (t
->needs_temp_ref()) {
4195 const string
& tmp_id
= get_temporary_id();
4196 const char *tmp_id_str
= tmp_id
.c_str();
4197 str
= mputprintf(str
, "{\n"
4198 "%s& %s = %s.list_item(%lu);\n",
4199 type_name_str
, tmp_id_str
, name
, (unsigned long) i
);
4200 str
= t
->generate_code_init(str
, tmp_id_str
);
4201 str
= mputstr(str
, "}\n");
4203 char *embedded_name
= mprintf("%s.list_item(%lu)", name
,
4205 str
= t
->generate_code_init(str
, embedded_name
);
4206 Free(embedded_name
);
4213 char *Template::generate_code_init_set(char *str
, const char *name
,
4214 bool is_superset
) // SUPERSET_MATCH and SUBSET_MATCH
4216 size_t nof_ts
= u
.templates
->get_nof_ts();
4217 const string
& oftype_name
=
4218 my_governor
->get_ofType()->get_genname_template(my_scope
);
4219 const char *oftype_name_str
= oftype_name
.c_str();
4221 dynamic_array
<int> variables
;
4222 size_t fixed_part
= 0;
4223 for (size_t i
= 0; i
< nof_ts
; ++i
) {
4224 Template
*t
= u
.templates
->get_t_byIndex(i
);
4225 if (t
->templatetype
== ALL_FROM
) {
4231 //warning("There are %lu set elements", nof_ts);
4232 if (variables
.size() > 0) {
4233 char* str_preamble
= 0;
4234 char* str_set_type
= mputprintf(0, "%s.set_type(%s, %lu", name
,
4235 is_superset
? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) fixed_part
);
4237 for (size_t v
= 0, vs
= variables
.size(); v
< vs
; ++v
) {
4238 Template
*vt
= u
.templates
->get_t_byIndex(variables
[v
]);
4239 if (vt
->templatetype
!= ALL_FROM
) FATAL_ERROR("must be ALL_FROM");
4240 if (vt
->u
.all_from
->templatetype
!= SPECIFIC_VALUE
) FATAL_ERROR("not value");
4241 Value
*val
= vt
->u
.all_from
->u
.specific_value
;
4242 if (val
->get_valuetype() != Value::V_REFD
) FATAL_ERROR("ref expected from val");
4243 Common::Reference
*ref
= val
->get_reference();
4244 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
4245 Common::Assignment
*ass
= ref
->get_refd_assignment();
4246 if (!ass
) FATAL_ERROR("Could not grab ass!");
4248 str_set_type
= mputstrn(str_set_type
, " + ", 3);
4250 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4252 // in case of parametrised references:
4253 // - temporary parameters need to be declared (stored in str_preamble)
4254 // - the same temporary needs to be used at each call (generate_code_cached call)
4255 expression_struct expr
;
4256 Code::init_expr(&expr
);
4258 ref_pard
->generate_code_cached(&expr
);
4259 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4261 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
4263 Code::free_expr(&expr
);
4266 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
4268 expression_struct expr
;
4269 Code::init_expr(&expr
);
4271 subrefs
->generate_code(&expr
, ass
);
4272 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4274 Code::free_expr(&expr
);
4278 switch(ass
->get_asstype()) {
4279 case Common::Assignment::A_CONST
:
4280 case Common::Assignment::A_EXT_CONST
:
4281 case Common::Assignment::A_MODULEPAR
:
4282 case Common::Assignment::A_VAR
:
4283 case Common::Assignment::A_PAR_VAL_IN
:
4284 case Common::Assignment::A_PAR_VAL_OUT
:
4285 case Common::Assignment::A_PAR_VAL_INOUT
:
4286 case Common::Assignment::A_FUNCTION_RVAL
:
4287 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4288 if (ass
->get_Type()->field_is_optional(subrefs
)) {
4289 str_set_type
= mputstrn(str_set_type
, "()", 2);
4296 str_set_type
= mputstr(str_set_type
, ".n_elem()");
4299 str
= mputstr(str
, str_preamble
);
4300 str
= mputstr(str
, str_set_type
);
4305 str
= mputstrn(str
, ");\n", 3);
4308 for (size_t i
= 0; i
< nof_ts
; i
++) {
4309 Template
*t
= u
.templates
->get_t_byIndex(i
);
4310 switch (t
->templatetype
) {
4312 expression_struct expr
; // FIXME copypasta from init_list above !
4313 Code::init_expr(&expr
);
4315 switch (t
->u
.all_from
->templatetype
) {
4316 case SPECIFIC_VALUE
: {
4317 Value
*sv
= t
->u
.all_from
->u
.specific_value
;
4318 switch (sv
->get_valuetype()) {
4319 case Value::V_REFD
: {
4320 Common::Reference
*ref
= sv
->get_reference();
4321 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
4323 ref_pard
->generate_code_cached(&expr
);
4325 ref
->generate_code(&expr
);
4327 Common::Assignment
* ass
= ref
->get_refd_assignment();
4328 switch(ass
->get_asstype()) {
4329 case Common::Assignment::A_CONST
:
4330 case Common::Assignment::A_EXT_CONST
:
4331 case Common::Assignment::A_MODULEPAR
:
4332 case Common::Assignment::A_VAR
:
4333 case Common::Assignment::A_PAR_VAL_IN
:
4334 case Common::Assignment::A_PAR_VAL_OUT
:
4335 case Common::Assignment::A_PAR_VAL_INOUT
:
4336 case Common::Assignment::A_FUNCTION_RVAL
:
4337 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
4338 if (ass
->get_Type()->field_is_optional(ref
->get_subrefs())) {
4339 expr
.expr
= mputstrn(expr
.expr
, "()", 2);
4349 FATAL_ERROR("VT NOT HANDLED");
4350 } // switch valuetype
4354 FATAL_ERROR("ttype not handled");
4358 str
= mputprintf(str
,
4359 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4363 char *embedded_name
= mprintf("%s.set_item(%lu%s + i_i)", name
,
4364 (unsigned long) i
, shifty
.c_str());
4365 str
= t
->generate_code_init_all_from(str
, embedded_name
);
4366 Free(embedded_name
);
4368 str
= mputstrn(str
, "}\n", 2);
4371 shifty
+= expr
.expr
;
4372 shifty
+= ".n_elem() /* 3442 */";
4373 Code::free_expr(&expr
);
4375 case VALUE_LIST_ALL_FROM
:
4376 FATAL_ERROR("Not possible");
4377 break; // not reached
4380 if (t
->needs_temp_ref()) {
4381 const string
& tmp_id
= get_temporary_id();
4382 const char *tmp_id_str
= tmp_id
.c_str();
4383 str
= mputprintf(str
, "{\n"
4384 "%s& %s = %s.set_item(%lu%s);\n",
4385 oftype_name_str
, tmp_id_str
, name
, (unsigned long) i
, shifty
.c_str());
4386 str
= t
->generate_code_init(str
, tmp_id_str
);
4387 str
= mputstr(str
, "}\n");
4389 char *embedded_name
= mprintf("%s.set_item(%lu%s)", name
,
4390 (unsigned long) i
, shifty
.c_str());
4391 str
= t
->generate_code_init(str
, embedded_name
);
4392 Free(embedded_name
);
4395 } // switch t->templatetype
4400 str
= mputprintf(str
, "%s.set_type(%s, %lu);\n", name
,
4401 is_superset
? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) nof_ts
);
4402 for (size_t i
= 0; i
< nof_ts
; i
++) {
4403 Template
*t
= u
.templates
->get_t_byIndex(i
);
4404 if (t
->needs_temp_ref()) {
4405 const string
& tmp_id
= get_temporary_id();
4406 const char *tmp_id_str
= tmp_id
.c_str();
4407 str
= mputprintf(str
, "{\n"
4408 "%s& %s = %s.set_item(%lu);\n",
4409 oftype_name_str
, tmp_id_str
, name
, (unsigned long) i
);
4410 str
= t
->generate_code_init(str
, tmp_id_str
);
4411 str
= mputstr(str
, "}\n");
4413 char *embedded_name
= mprintf("%s.set_item(%lu)", name
,
4415 str
= t
->generate_code_init(str
, embedded_name
);
4416 Free(embedded_name
);
4423 void Template::generate_code_expr_invoke(expression_struct
*expr
)
4425 Value
*last_v
= u
.invoke
.v
->get_value_refd_last();
4426 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
4427 Common::Assignment
*function
= last_v
->get_refd_fat();
4428 expr
->expr
= mputprintf(expr
->expr
, "%s(",
4429 function
->get_genname_from_scope(my_scope
).c_str());
4430 u
.invoke
.ap_list
->generate_code_alias(expr
,
4431 function
->get_FormalParList(), function
->get_RunsOnType(), false);
4433 u
.invoke
.v
->generate_code_expr_mandatory(expr
);
4434 expr
->expr
= mputstr(expr
->expr
, ".invoke(");
4435 Type
* gov_last
= u
.invoke
.v
->get_expr_governor_last();
4436 u
.invoke
.ap_list
->generate_code_alias(expr
, 0,
4437 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
4439 expr
->expr
= mputc(expr
->expr
, ')');
4442 char *Template::rearrange_init_code_refd(char *str
, Common::Module
* usage_mod
)
4444 if (templatetype
!= TEMPLATE_REFD
)
4445 FATAL_ERROR("Template::rearrange_init_code_refd()");
4446 ActualParList
*actual_parlist
= u
.ref
.ref
->get_parlist();
4447 // generate code for the templates that are used in the actual parameter
4448 // list of the reference
4449 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
4450 if (actual_parlist
) str
= actual_parlist
->rearrange_init_code(str
, usage_mod
);
4451 // do nothing if the reference does not point to a template definition
4452 if (ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) return str
;
4453 Template
*t
= ass
->get_Template();
4454 FormalParList
*formal_parlist
= ass
->get_FormalParList();
4455 if (formal_parlist
) {
4456 // the reference points to a parameterized template
4457 // we must perform the rearrangement for all non-parameterized templates
4458 // that are referred by the parameterized template regardless of the
4459 // sub-references of u.ref.ref
4460 str
= t
->rearrange_init_code(str
, usage_mod
);
4461 // the parameterized template's default values must also be generated
4462 // (this only generates their value assignments, their declarations will
4463 // be generated when the template's definition is reached)
4464 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
4465 str
= formal_parlist
->generate_code_defval(str
);
4468 // the reference points to a non-parameterized template
4469 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
4471 // we should follow the sub-references as much as we can
4472 // and perform the rearrangement for the referred field only
4473 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); i
++) {
4474 FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
4475 if (ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
4476 // stop if the body does not have fields
4477 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
4478 // get the sub-template of the referred field
4479 t
= t
->u
.named_templates
->get_nt_byName(*ref
->get_id())
4482 // stop if the body is not a list
4483 if (t
->templatetype
!= TEMPLATE_LIST
) break;
4484 Value
*array_index
= ref
->get_val()->get_value_refd_last();
4485 // stop if the index cannot be evaluated at compile time
4486 if (array_index
->get_valuetype() != Value::V_INT
) break;
4487 Int index
= array_index
->get_val_Int()->get_val();
4488 // index transformation in case of arrays
4489 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
4490 index
-= t
->my_governor
->get_dimension()->get_offset();
4491 // get the template with the given index
4492 t
= t
->get_listitem_byIndex(index
);
4496 // otherwise if the reference points to a top-level template
4497 // we should initialize its entire body
4498 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
4499 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
4505 char *Template::rearrange_init_code_invoke(char *str
, Common::Module
* usage_mod
)
4507 str
= u
.invoke
.v
->rearrange_init_code(str
);
4508 str
= u
.invoke
.ap_list
->rearrange_init_code(str
, usage_mod
);
4512 bool Template::needs_temp_ref()
4514 if (length_restriction
|| is_ifpresent
) return true;
4515 switch (templatetype
) {
4519 case SPECIFIC_VALUE
:
4521 case TEMPLATE_INVOKE
:
4529 // temporary reference is needed if the template has at least one
4530 // element (excluding not used symbols)
4531 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
4532 if (u
.templates
->get_t_byIndex(i
)->templatetype
!= TEMPLATE_NOTUSED
)
4536 case INDEXED_TEMPLATE_LIST
:
4537 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
4538 if (u
.indexed_templates
->get_it_byIndex(i
)->get_template()
4539 ->templatetype
!= TEMPLATE_NOTUSED
)
4543 case NAMED_TEMPLATE_LIST
:
4544 return u
.named_templates
->get_nof_nts() > 1;
4546 case VALUE_LIST_ALL_FROM
:
4549 case COMPLEMENTED_LIST
:
4551 case SUPERSET_MATCH
:
4554 case TEMPLATE_ERROR
:
4555 case TEMPLATE_NOTUSED
:
4556 FATAL_ERROR("Template::needs_temp_ref()");
4557 case PERMUTATION_MATCH
:
4564 bool Template::has_single_expr()
4566 if (length_restriction
|| is_ifpresent
|| get_needs_conversion())
4568 switch (templatetype
) {
4578 case SPECIFIC_VALUE
:
4579 return u
.specific_value
->has_single_expr();
4580 case TEMPLATE_REFD
: {
4581 Template
*t_last
= get_template_refd_last();
4582 if (t_last
!= this && t_last
->has_single_expr()) {
4583 for (Scope
*t_scope
= my_scope
; t_scope
;
4584 t_scope
= t_scope
->get_parent_scope()) {
4585 // return true if t_last is visible from my scope
4586 if (t_scope
== t_last
->my_scope
) return true;
4589 // otherwise consider the reference itself
4590 return u
.ref
.ref
->has_single_expr(); }
4591 case TEMPLATE_INVOKE
:
4592 if (!u
.invoke
.v
->has_single_expr()) return false;
4593 for (size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++)
4594 if (!u
.invoke
.ap_list
->get_par(i
)->has_single_expr()) return false;
4597 return u
.templates
->get_nof_ts() == 0;
4598 case NAMED_TEMPLATE_LIST
: {
4599 if (!my_governor
) FATAL_ERROR("Template::has_single_expr()");
4600 Type
*type
= my_governor
->get_type_refd_last();
4601 return type
->get_nof_comps() == 0; }
4602 case INDEXED_TEMPLATE_LIST
:
4603 return u
.indexed_templates
->get_nof_its() == 0;
4605 case COMPLEMENTED_LIST
:
4607 case SUPERSET_MATCH
:
4609 case PERMUTATION_MATCH
:
4612 case VALUE_LIST_ALL_FROM
:
4615 FATAL_ERROR("Template::has_single_expr()");
4620 string
Template::get_single_expr(bool cast_needed
)
4622 if (cast_needed
&& (length_restriction
|| is_ifpresent
))
4623 FATAL_ERROR("Template::get_single_expr()");
4625 switch (templatetype
) {
4627 ret_val
= "OMIT_VALUE";
4630 ret_val
= "ANY_VALUE";
4633 ret_val
= "ANY_OR_OMIT";
4635 case SPECIFIC_VALUE
:
4636 ret_val
= u
.specific_value
->get_single_expr();
4638 case TEMPLATE_REFD
: {
4639 // convert the reference to a single expression
4640 expression_struct expr
;
4641 Code::init_expr(&expr
);
4642 u
.ref
.ref
->generate_code(&expr
);
4643 if (expr
.preamble
|| expr
.postamble
)
4644 FATAL_ERROR("Template::get_single_expr()");
4645 ret_val
= expr
.expr
;
4646 Code::free_expr(&expr
);
4649 case TEMPLATE_INVOKE
: {
4650 expression_struct expr
;
4651 Code::init_expr(&expr
);
4652 generate_code_expr_invoke(&expr
);
4653 if (expr
.preamble
|| expr
.postamble
)
4654 FATAL_ERROR("Template::get_single_expr()");
4655 ret_val
= expr
.expr
;
4656 Code::free_expr(&expr
);
4659 if (u
.templates
->get_nof_ts() != 0)
4660 FATAL_ERROR("Template::get_single_expr()");
4661 ret_val
= "NULL_VALUE";
4663 case NAMED_TEMPLATE_LIST
:
4664 if (u
.named_templates
->get_nof_nts() != 0)
4665 FATAL_ERROR("Template::get_single_expr()");
4666 ret_val
= "NULL_VALUE";
4668 case INDEXED_TEMPLATE_LIST
:
4669 if (u
.indexed_templates
->get_nof_its() != 0)
4670 FATAL_ERROR("Template::get_single_expr()");
4671 ret_val
= "NULL_VALUE";
4674 return get_my_scope()->get_scope_mod_gen()
4675 ->add_bitstring_pattern(*u
.pattern
);
4677 return get_my_scope()->get_scope_mod_gen()
4678 ->add_hexstring_pattern(*u
.pattern
);
4680 return get_my_scope()->get_scope_mod_gen()
4681 ->add_octetstring_pattern(*u
.pattern
);
4685 ->create_charstring_literals(get_my_scope()->get_scope_mod_gen());
4687 FATAL_ERROR("Template::get_single_expr()");
4689 if (cast_needed
) ret_val
= my_governor
->get_genname_template(my_scope
) +
4690 "(" + ret_val
+ ")";
4694 void Template::dump(unsigned level
) const
4696 DEBUG(level
, "%s", get_templatetype_str());
4697 switch (templatetype
) {
4698 case TEMPLATE_ERROR
:
4703 case SPECIFIC_VALUE
:
4704 u
.specific_value
->dump(level
+1);
4707 u
.ref
.ref
->dump(level
+1);
4709 case TEMPLATE_INVOKE
:
4710 u
.invoke
.v
->dump(level
+1);
4711 if (u
.invoke
.ap_list
) u
.invoke
.ap_list
->dump(level
+ 1);
4712 else if (u
.invoke
.t_list
) u
.invoke
.t_list
->dump(level
+ 1);
4716 case COMPLEMENTED_LIST
:
4717 case SUPERSET_MATCH
:
4719 case PERMUTATION_MATCH
:
4720 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
4721 u
.templates
->get_t_byIndex(i
)->dump(level
+1);
4723 case NAMED_TEMPLATE_LIST
:
4724 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
4725 u
.named_templates
->get_nt_byIndex(i
)->dump(level
+1);
4727 case INDEXED_TEMPLATE_LIST
:
4728 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
4729 u
.indexed_templates
->get_it_byIndex(i
)->dump(level
+1);
4732 u
.value_range
->dump(level
);
4737 DEBUG(level
+1, "%s", u
.pattern
->c_str());
4741 u
.pstring
->dump(level
+1);
4744 case VALUE_LIST_ALL_FROM
:
4745 u
.all_from
->dump(level
+1);
4750 if (length_restriction
) length_restriction
->dump(level
+ 1);
4753 bool Template::has_allfrom() const
4754 { // the code generation of all from is not fully implemented. This helps avoid of using it.
4755 if (templatetype
!= TEMPLATE_LIST
) FATAL_ERROR("has_allfrom(): Templatetype shall be TEMPLATE_LIST");
4756 size_t nof_ts
= u
.templates
->get_nof_ts();
4757 for (size_t i
= 0; i
< nof_ts
; i
++) {
4758 if (u
.templates
->get_t_byIndex(i
)->templatetype
== ALL_FROM
) {
4765 // =================================
4766 // ===== TemplateInstance
4767 // =================================
4769 TemplateInstance::TemplateInstance(const TemplateInstance
& p
)
4770 : Node(p
), Location(p
)
4772 type
= p
.type
? p
.type
->clone() : 0;
4773 derived_reference
= p
.derived_reference
? p
.derived_reference
->clone() : 0;
4774 template_body
= p
.template_body
->clone();
4777 TemplateInstance::TemplateInstance(Type
*p_type
, Ref_base
*p_ref
,
4778 Template
*p_body
) : Node(), Location(), type(p_type
),
4779 derived_reference(p_ref
), template_body(p_body
)
4781 if (!p_body
) FATAL_ERROR("TemplateInstance::TemplateInstance()");
4782 if (type
) type
->set_ownertype(Type::OT_TEMPLATE_INST
, this);
4785 TemplateInstance::~TemplateInstance()
4788 delete derived_reference
;
4789 delete template_body
;
4792 void TemplateInstance::release()
4795 derived_reference
= 0;
4799 TemplateInstance
*TemplateInstance::clone() const
4801 return new TemplateInstance(*this);
4804 void TemplateInstance::set_fullname(const string
& p_fullname
)
4806 Node::set_fullname(p_fullname
);
4807 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
4808 if (derived_reference
)
4809 derived_reference
->set_fullname(p_fullname
+ ".<derived_reference>");
4810 template_body
->set_fullname(p_fullname
);
4813 void TemplateInstance::set_my_scope(Scope
*p_scope
)
4815 if (type
) type
->set_my_scope(p_scope
);
4816 if (derived_reference
) derived_reference
->set_my_scope(p_scope
);
4817 template_body
->set_my_scope(p_scope
);
4820 Type::typetype_t
TemplateInstance::get_expr_returntype
4821 (Type::expected_value_t exp_val
)
4823 Type
*t
= get_expr_governor(exp_val
);
4824 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
4825 else return template_body
->get_expr_returntype(exp_val
);
4828 Type
*TemplateInstance::get_expr_governor(Type::expected_value_t exp_val
)
4830 if (type
) return type
;
4831 if (derived_reference
) {
4832 Type
*ret_val
= chk_DerivedRef(0);
4833 if (ret_val
) return ret_val
;
4835 return template_body
->get_expr_governor(exp_val
);
4838 void TemplateInstance::chk(Type
*governor
)
4840 if (!governor
) FATAL_ERROR("TemplateInstance::chk()");
4841 governor
= chk_Type(governor
);
4842 governor
= chk_DerivedRef(governor
);
4843 template_body
->set_my_governor(governor
);
4844 governor
->chk_this_template_ref(template_body
);
4845 governor
->chk_this_template_generic(template_body
,
4846 (derived_reference
!= 0 ? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
4847 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
4850 Type
*TemplateInstance::chk_Type(Type
*governor
)
4852 if (!type
) return governor
;
4854 Error_Context
cntxt(type
, "In explicit type specification");
4857 TypeCompatInfo
info(template_body
->get_template_refd_last()
4858 ->get_my_scope()->get_scope_mod(), governor
, type
,
4862 if (!governor
) return type
;
4863 else if (governor
->is_compatible(type
, &info
, &l_chain
, &r_chain
, true)) {
4866 if (info
.is_subtype_error()) {
4867 type
->error("%s", info
.get_subtype_error().c_str());
4869 if (!info
.is_erroneous()) {
4870 type
->error("Incompatible explicit type specification: `%s' was "
4871 "expected instead of `%s'",
4872 governor
->get_typename().c_str(),
4873 type
->get_typename().c_str());
4875 type
->error("%s", info
.get_error_str_str().c_str());
4881 Type
*TemplateInstance::chk_DerivedRef(Type
*governor
)
4883 if (!derived_reference
) return governor
;
4884 Error_Context
cntxt(derived_reference
, "In derived reference");
4885 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4886 // the base template reference must not have sub-references
4887 if (derived_reference
->get_subrefs())
4888 FATAL_ERROR("TemplateInstance::chk_DerivedRef()");
4889 bool set_bt
= false;
4890 if (!ass
) goto error
;
4891 switch (ass
->get_asstype()) {
4892 case Common::Assignment::A_TEMPLATE
:
4895 case Common::Assignment::A_MODULEPAR_TEMP
:
4896 case Common::Assignment::A_VAR_TEMPLATE
:
4897 case Common::Assignment::A_PAR_TEMPL_IN
:
4898 case Common::Assignment::A_PAR_TEMPL_OUT
:
4899 case Common::Assignment::A_PAR_TEMPL_INOUT
:
4900 case Common::Assignment::A_FUNCTION_RTEMP
:
4901 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: {
4902 if (!governor
) governor
= type
;
4903 Type
*base_template_type
= ass
->get_Type();
4905 TypeCompatInfo
info(template_body
->get_template_refd_last()
4906 ->get_my_scope()->get_scope_mod(), governor
, type
,
4910 if (!governor
->is_compatible(base_template_type
, &info
, &l_chain
,
4912 if (info
.is_subtype_error()) {
4913 derived_reference
->error("%s", info
.get_subtype_error().c_str());
4915 if (!info
.is_erroneous()) {
4916 derived_reference
->error("Base template `%s' has incompatible "
4917 "type: `%s' was expected instead of `%s'",
4918 ass
->get_fullname().c_str(),
4919 governor
->get_typename().c_str(),
4920 base_template_type
->get_typename().c_str());
4922 derived_reference
->error("%s", info
.get_error_str_str().c_str());
4924 // if explicit type specification is omitted
4925 // check the template body against the type of the base template
4926 if (!type
) governor
= base_template_type
;
4929 if (info
.needs_conversion())
4930 template_body
->set_needs_conversion();
4932 } else governor
= base_template_type
;
4935 derived_reference
->error("Reference to a template was expected instead "
4936 "of %s", ass
->get_description().c_str());
4939 if (set_bt
) template_body
->set_base_template(ass
->get_Template());
4942 // drop the erroneous derived_reference to avoid further errors
4943 delete derived_reference
;
4944 derived_reference
= 0;
4948 void TemplateInstance::chk_recursions(ReferenceChain
& refch
)
4950 template_body
->chk_recursions(refch
);
4953 bool TemplateInstance::is_string_type(Type::expected_value_t exp_val
)
4955 switch (get_expr_returntype(exp_val
)) {
4967 bool TemplateInstance::chk_restriction(const char* definition_name
,
4968 template_restriction_t template_restriction
, const Location
* usage_loc
)
4970 bool needs_runtime_check
= false;
4971 if (derived_reference
) // if modified
4973 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4974 switch (ass
->get_asstype()) {
4975 case Common::Assignment::A_TEMPLATE
:
4976 // already added to template_body as base template by chk_DerivedRef()
4977 needs_runtime_check
= template_body
->chk_restriction(
4978 definition_name
, template_restriction
, usage_loc
);
4980 case Common::Assignment::A_MODULEPAR_TEMP
:
4981 case Common::Assignment::A_VAR_TEMPLATE
:
4982 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
4983 case Common::Assignment::A_FUNCTION_RTEMP
:
4984 case Common::Assignment::A_PAR_TEMPL_IN
:
4985 case Common::Assignment::A_PAR_TEMPL_OUT
:
4986 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
4987 // create a temporary Template to be added as the base template and
4988 // check, remove and delete after checked
4989 if (template_body
->get_base_template())
4990 FATAL_ERROR("TemplateInstance::chk_restriction()");
4991 template_body
->set_base_template(new Template(derived_reference
));
4992 needs_runtime_check
= template_body
->chk_restriction(
4993 definition_name
, template_restriction
, usage_loc
);
4994 delete template_body
->get_base_template();
4995 template_body
->set_base_template(0);
5001 needs_runtime_check
= template_body
->chk_restriction(definition_name
,
5002 template_restriction
, usage_loc
);
5004 return needs_runtime_check
;
5007 bool TemplateInstance::has_single_expr()
5009 if (derived_reference
) return false;
5010 else if (type
) return false;
5011 else return template_body
->has_single_expr();
5014 void TemplateInstance::set_code_section(
5015 GovernedSimple::code_section_t p_code_section
)
5017 if (derived_reference
) derived_reference
->set_code_section(p_code_section
);
5018 template_body
->set_code_section(p_code_section
);
5021 bool TemplateInstance::needs_temp_ref()
5023 if (template_body
->get_templatetype() != Template::SPECIFIC_VALUE
)
5025 Value
*val
= template_body
->get_specific_value();
5026 if (val
->get_valuetype() == Value::V_REFD
) {
5027 FieldOrArrayRefs
*refs
= val
->get_reference()->get_subrefs();
5028 if (!refs
) return false;
5029 // We need at least a 2-long reference chain. E.g. "a[0].b". 3.0.4
5030 // can't handle a normal reference following an indexed reference. The
5031 // indexed reference must be on the first place. Code like: "a.b[0].c"
5033 if (refs
->get_nof_refs() < 2
5034 || refs
->get_ref(0)->get_type() != FieldOrArrayRef::ARRAY_REF
)
5042 void TemplateInstance::generate_code(expression_struct
*expr
,
5043 template_restriction_t template_restriction
)
5045 if (derived_reference
) {
5046 // preserve the target expression
5047 char *expr_backup
= expr
->expr
;
5048 // reset the space for the target expression
5050 derived_reference
->generate_code(expr
);
5051 // now the C++ equivalent of the base template reference is in expr->expr
5052 const string
& tmp_id
= template_body
->get_temporary_id();
5053 const char *tmp_id_str
= tmp_id
.c_str();
5054 // create a temporary variable and copy the contents of base template
5056 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s(%s);\n",
5057 template_body
->get_my_governor()->get_genname_template(
5058 template_body
->get_my_scope()).c_str(), tmp_id_str
, expr
->expr
);
5059 // perform the modifications on the temporary variable
5060 expr
->preamble
= template_body
->generate_code_init(expr
->preamble
,
5062 // runtime template restriction check
5063 if (template_restriction
!=TR_NONE
)
5064 expr
->preamble
= Template::generate_restriction_check_code(
5065 expr
->preamble
, tmp_id_str
, template_restriction
);
5066 // the base template reference is no longer needed
5068 // restore the target expression append the name of the temporary
5070 expr
->expr
= mputstr(expr_backup
, tmp_id_str
);
5071 } else template_body
->generate_code_expr(expr
, template_restriction
);
5074 char *TemplateInstance::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
5076 if (derived_reference
) {
5077 ActualParList
*actual_parlist
= derived_reference
->get_parlist();
5078 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
5079 if (!ass
) FATAL_ERROR("TemplateInstance::rearrange_init_code()");
5080 if (actual_parlist
) str
= actual_parlist
->rearrange_init_code(str
, usage_mod
);
5081 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
5082 Template
*t
= ass
->get_Template();
5083 FormalParList
*formal_parlist
= ass
->get_FormalParList();
5084 if (formal_parlist
) {
5085 // the referred template is parameterized
5086 // the embedded referenced templates shall be visited
5087 str
= t
->rearrange_init_code(str
, usage_mod
);
5088 // the constants used for default values have to be initialized now
5089 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
5090 str
= formal_parlist
->generate_code_defval(str
);
5093 // the referred template is not parameterized
5094 // its entire body has to be initialized now
5095 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
5096 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
5101 str
= template_body
->rearrange_init_code(str
, usage_mod
);
5105 void TemplateInstance::append_stringRepr(string
& str
) const
5108 str
+= type
->get_typename();
5111 if (derived_reference
) {
5113 str
+= derived_reference
->get_dispname();
5116 str
+= template_body
->get_stringRepr();
5119 void TemplateInstance::dump(unsigned level
) const
5122 DEBUG(level
, "type:");
5123 type
->dump(level
+ 1);
5125 if (derived_reference
) {
5126 DEBUG(level
, "modifies:");
5127 derived_reference
->dump(level
+ 1);
5129 template_body
->dump(level
);
5132 Value
* TemplateInstance::get_specific_value() const
5134 if (type
) return NULL
;
5135 if (derived_reference
) return NULL
;
5136 if (template_body
->is_length_restricted() || template_body
->get_ifpresent())
5138 if (template_body
->get_templatetype()!=Template::SPECIFIC_VALUE
) return NULL
;
5139 return template_body
->get_specific_value();
5142 Def_Template
* TemplateInstance::get_Referenced_Base_Template()
5143 { // it may return 0
5144 if (!get_Template()) return NULL
;
5145 Ttcn::Template::templatetype_t tpt
= get_Template()->get_templatetype();
5146 if (Ttcn::Template::TEMPLATE_REFD
!= tpt
) return NULL
;
5147 Ttcn::Ref_base
* refbase
= get_Template()->get_reference();
5148 Ttcn::Reference
* ref
= dynamic_cast<Ttcn::Reference
*>(refbase
);
5149 if (!ref
) return NULL
;
5150 Common::Assignment
* ass
= ref
->get_refd_assignment();
5151 Ttcn::Definition
* def
= dynamic_cast<Ttcn::Definition
*>(ass
);
5152 if (!def
) return NULL
;
5153 Ttcn::Def_Template
* deftemp
= dynamic_cast<Ttcn::Def_Template
*>(def
);
5154 if (!deftemp
) return NULL
;