1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
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(); // FATAL_ERROR
68 case INDEXED_TEMPLATE_LIST
:
69 u
.indexed_templates
= p
.u
.indexed_templates
->clone(); // FATAL_ERROR
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
:
736 case Type::T_SIGNATURE
: // be precise
738 default: // not possible, fatal error ?
741 if ( nof_temps
> nof_comps
742 || (!allow_fewer
&& (nof_temps
< nof_comps
))) {
743 error("Too %s elements in value list notation for type `%s': "
744 "%lu was expected instead of %lu",
745 nof_temps
> nof_comps
? "many" : "few",
746 t
->get_typename().c_str(),
747 (unsigned long) nof_comps
, (unsigned long) nof_temps
);
749 size_t upper_limit
; // min(nof_temps, nof_comps)
751 if (nof_temps
<= nof_comps
) {
752 upper_limit
= nof_temps
;
755 upper_limit
= nof_comps
;
758 u
.named_templates
= new NamedTemplates
;
759 for (size_t i
= 0; i
< upper_limit
; i
++) {
760 Template
*& temp
= sts
->get_t_byIndex(i
);
761 if (temp
->templatetype
== TEMPLATE_NOTUSED
) continue;
763 NamedTemplate
*nt
= new
764 NamedTemplate(t
->get_comp_id_byIndex(i
).clone(), temp
);
765 nt
->set_location(*temp
);
766 u
.named_templates
->add_nt(nt
);
769 u
.named_templates
->set_my_scope(get_my_scope());
770 u
.named_templates
->set_fullname(get_fullname());
772 if (all_notused
&& nof_temps
> 0 && tt
!= Type::T_SIGNATURE
)
773 warning("All elements of value list notation for type `%s' are "
774 "not used symbols (`-')", t
->get_typename().c_str());
775 } else FATAL_ERROR("Template::set_templatetype()");
777 case CSTR_PATTERN
: // current type
778 if (p_templatetype
== USTR_PATTERN
)
779 templatetype
= USTR_PATTERN
;
781 FATAL_ERROR("Template::set_templatetype()");
784 FATAL_ERROR("Template::set_templatetype()");
786 templatetype
= p_templatetype
;
789 const char *Template::get_templatetype_str() const
791 switch(templatetype
) {
793 return "erroneous template";
794 case TEMPLATE_NOTUSED
:
795 return "not used symbol";
801 return "any or omit";
803 return "specific value";
805 return "referenced template";
806 case TEMPLATE_INVOKE
:
807 return "template returning invoke";
809 case VALUE_LIST_ALL_FROM
:
810 return "template with 'all from'";
812 return "value list notation";
813 case NAMED_TEMPLATE_LIST
:
814 return "assignment notation";
815 case INDEXED_TEMPLATE_LIST
:
816 return "assignment notation with array indices";
818 return "value range match";
820 return "value list match";
821 case COMPLEMENTED_LIST
:
822 return "complemented list match";
824 return "superset match";
826 return "subset match";
827 case PERMUTATION_MATCH
:
828 return "permutation match";
830 return "bitstring pattern";
832 return "hexstring pattern";
834 return "octetstring pattern";
836 return "character string pattern";
838 return "universal string pattern";
840 return "unknown template";
844 bool Template::is_undef_lowerid()
846 return templatetype
== SPECIFIC_VALUE
&&
847 u
.specific_value
->is_undef_lowerid();
850 void Template::set_lowerid_to_ref()
852 switch (templatetype
) {
854 u
.specific_value
->set_lowerid_to_ref();
855 if (u
.specific_value
->get_valuetype() == Value::V_REFD
) {
856 Common::Assignment
*t_ass
=
857 u
.specific_value
->get_reference()->get_refd_assignment(false);
859 switch (t_ass
->get_asstype()) {
860 case Common::Assignment::A_MODULEPAR_TEMP
:
861 case Common::Assignment::A_TEMPLATE
:
862 case Common::Assignment::A_VAR_TEMPLATE
:
863 case Common::Assignment::A_PAR_TEMPL_IN
:
864 case Common::Assignment::A_PAR_TEMPL_OUT
:
865 case Common::Assignment::A_PAR_TEMPL_INOUT
:
866 case Common::Assignment::A_FUNCTION_RTEMP
:
867 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
868 set_templatetype(TEMPLATE_REFD
);
872 } else set_templatetype(TEMPLATE_ERROR
);
876 case COMPLEMENTED_LIST
:
877 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
878 u
.templates
->get_t_byIndex(i
)->set_lowerid_to_ref();
881 u
.value_range
->set_lowerid_to_ref();
888 Type::typetype_t
Template::get_expr_returntype(Type::expected_value_t exp_val
)
890 switch (templatetype
) {
892 return Type::T_ERROR
;
894 return u
.specific_value
->get_expr_returntype(exp_val
);
895 case TEMPLATE_REFD
: {
896 Type
*t
= get_expr_governor(exp_val
);
897 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
898 else return Type::T_ERROR
; }
899 case TEMPLATE_INVOKE
: {
900 Type
*t
= get_expr_governor(exp_val
);
901 if(t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
902 else return Type::T_ERROR
; }
904 case COMPLEMENTED_LIST
:
905 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
906 Type::typetype_t tt
= u
.templates
->get_t_byIndex(i
)
907 ->get_expr_returntype(exp_val
);
908 if (tt
!= Type::T_UNDEF
) return tt
;
910 return Type::T_UNDEF
;
912 return u
.value_range
->get_expr_returntype(exp_val
);
915 return Type::T_SETOF
;
927 return Type::T_UNDEF
;
931 Type
*Template::get_expr_governor(Type::expected_value_t exp_val
)
933 if (my_governor
) return my_governor
;
934 switch (templatetype
) {
936 return u
.specific_value
->get_expr_governor(exp_val
);
938 case COMPLEMENTED_LIST
:
939 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
940 Type
*t
= u
.templates
->get_t_byIndex(i
)->get_expr_governor(exp_val
);
945 return u
.value_range
->get_expr_governor(exp_val
);
946 case TEMPLATE_REFD
: {
947 Type
*t
= u
.ref
.ref
->get_refd_assignment()->get_Type()
948 ->get_field_type(u
.ref
.ref
->get_subrefs(), exp_val
);
949 if (!t
) set_templatetype(TEMPLATE_ERROR
);
952 case TEMPLATE_INVOKE
: {
953 Type
*t
= u
.invoke
.v
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
955 if(u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
956 u
.invoke
.v
->error("A value of type function expected");
959 t
= t
->get_type_refd_last();
960 switch(t
->get_typetype()) {
961 case Type::T_FUNCTION
:
962 if(exp_val
==Type::EXPECTED_DYNAMIC_VALUE
&& t
->get_returns_template()){
963 error("Reference to a value was expected instead of a "
964 "template of type `%s'"
965 , t
->get_function_return_type()->get_typename().c_str());
968 return t
->get_function_return_type();
969 case Type::T_ALTSTEP
:
972 u
.invoke
.v
->error("A value of type function expected instead of `%s'",
973 t
->get_typename().c_str());
978 return Type::get_pooltype(get_expr_returntype(exp_val
));
981 set_templatetype(TEMPLATE_ERROR
);
985 void Template::set_my_governor(Type
*p_gov
)
988 FATAL_ERROR("Template::set_my_governor(): NULL parameter");
992 Type
*Template::get_my_governor() const
997 void Template::set_length_restriction(LengthRestriction
*p_lr
)
999 if (length_restriction
) FATAL_ERROR("Template::set_length_restriction()");
1000 length_restriction
= p_lr
;
1003 Template::completeness_t
1004 Template::get_completeness_condition_seof(bool incomplete_allowed
)
1006 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1007 else if (!base_template
) return C_MAY_INCOMPLETE
;
1009 Template
*t
= base_template
->get_template_refd_last();
1010 switch (t
->templatetype
) {
1011 // partial overwriting is allowed
1012 case TEMPLATE_ERROR
: // to suppress more errors
1013 case TEMPLATE_NOTUSED
: // modifying a modified template
1014 case ANY_VALUE
: // in case of ?
1015 case ANY_OR_OMIT
: // in case of *
1016 case TEMPLATE_REFD
: // e.g. the actual value of a formal parameter
1017 case TEMPLATE_INVOKE
:
1018 case NAMED_TEMPLATE_LIST
: // t is erroneous
1019 case INDEXED_TEMPLATE_LIST
:
1020 return C_MAY_INCOMPLETE
;
1022 switch (my_governor
->get_type_refd_last()->get_typetype()) {
1025 // only the first elements can be incomplete
1028 // we are in error recovery
1029 return C_MAY_INCOMPLETE
;
1031 break; // should not get here
1033 // partial overwriting is not allowed for literal specific values,
1034 // matching ranges/lists/sets and patterns
1035 return C_MUST_COMPLETE
;
1040 Template::completeness_t
Template::get_completeness_condition_choice
1041 (bool incomplete_allowed
, const Identifier
& p_fieldname
)
1043 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1044 else if (!base_template
) return C_MAY_INCOMPLETE
;
1046 Template
*t
= base_template
->get_template_refd_last();
1047 switch (t
->templatetype
) {
1048 // partial overwriting is allowed
1049 case TEMPLATE_ERROR
: // to suppress more errors
1050 case TEMPLATE_NOTUSED
: // t is erroneous
1051 case ANY_VALUE
: // in case of ?
1052 case ANY_OR_OMIT
: // in case of *
1053 case TEMPLATE_REFD
: // e.g. the actual value of a formal parameter
1054 case TEMPLATE_INVOKE
:
1055 case TEMPLATE_LIST
: // t is erroneous
1056 return C_MAY_INCOMPLETE
;
1057 case NAMED_TEMPLATE_LIST
: // some fields may be missing
1058 if (t
->u
.named_templates
->has_nt_withName(p_fieldname
))
1059 return C_MAY_INCOMPLETE
;
1060 else return C_MUST_COMPLETE
;
1062 // partial overwriting is not allowed for literal specific values,
1063 // matching ranges/lists/sets and patterns
1064 return C_MUST_COMPLETE
;
1069 void Template::add_named_temp(NamedTemplate
* nt
) {
1070 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1071 FATAL_ERROR("Template::add_named_temp()");
1072 u
.named_templates
->add_nt(nt
);
1075 Value
*Template::get_specific_value() const
1077 if (templatetype
!= SPECIFIC_VALUE
)
1078 FATAL_ERROR("Template::get_specific_value()");
1079 return u
.specific_value
;
1082 Ref_base
*Template::get_reference() const
1084 if (templatetype
!= TEMPLATE_REFD
)
1085 FATAL_ERROR("Template::get_reference()");
1089 ValueRange
*Template::get_value_range() const
1091 if (templatetype
!= VALUE_RANGE
)
1092 FATAL_ERROR("Template::get_value_range()");
1093 return u
.value_range
;
1096 PatternString
* Template::get_cstr_pattern() const
1098 if (templatetype
!= CSTR_PATTERN
)
1099 FATAL_ERROR("Template::get_cstr_pattern()");
1103 PatternString
* Template::get_ustr_pattern() const
1105 if (templatetype
!= USTR_PATTERN
)
1106 FATAL_ERROR("Template::get_ustr_pattern()");
1110 size_t Template::get_nof_comps() const
1112 switch (templatetype
) {
1115 case COMPLEMENTED_LIST
:
1116 case SUPERSET_MATCH
:
1118 case PERMUTATION_MATCH
:
1119 return u
.templates
->get_nof_ts();
1120 case NAMED_TEMPLATE_LIST
:
1121 return u
.named_templates
->get_nof_nts();
1122 case INDEXED_TEMPLATE_LIST
:
1123 return u
.indexed_templates
->get_nof_its();
1125 FATAL_ERROR("Template::get_of_comps()");
1130 Template
*Template::get_temp_byIndex(size_t n
) const
1132 switch (templatetype
) {
1135 case COMPLEMENTED_LIST
:
1136 case SUPERSET_MATCH
:
1138 case PERMUTATION_MATCH
:
1139 return u
.templates
->get_t_byIndex(n
);
1141 FATAL_ERROR("Template::get_temp_byIndex()");
1146 IndexedTemplate
*Template::get_indexedtemp_byIndex(size_t n
) const
1148 if (templatetype
!= INDEXED_TEMPLATE_LIST
)
1149 FATAL_ERROR("Template::get_indexedtemp_byIndex()");
1150 return u
.indexed_templates
->get_it_byIndex(n
);
1153 NamedTemplate
*Template::get_namedtemp_byIndex(size_t n
) const
1155 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1156 FATAL_ERROR("Template::get_namedtemp_byIndex()");
1157 return u
.named_templates
->get_nt_byIndex(n
);
1160 Template
*Template::get_all_from() const
1162 if (templatetype
!= ALL_FROM
1163 &&templatetype
!= VALUE_LIST_ALL_FROM
)
1164 FATAL_ERROR("Template::get_all_from()");
1168 // Not applicable to INDEXED_TEMPLATE_LIST nodes. The actual number of
1169 // elements is not known.
1170 size_t Template::get_nof_listitems() const
1172 if (templatetype
!= TEMPLATE_LIST
)
1173 FATAL_ERROR("Template::get_nof_listitems()");
1174 if (has_permutation
) {
1175 size_t nof_ts
= u
.templates
->get_nof_ts(), ret_val
= 0;
1176 for (size_t i
= 0; i
< nof_ts
; i
++) {
1177 Template
*t
= u
.templates
->get_t_byIndex(i
);
1178 if (t
->templatetype
== PERMUTATION_MATCH
)
1179 ret_val
+= t
->u
.templates
->get_nof_ts();
1183 } else return u
.templates
->get_nof_ts();
1186 Template
*Template::get_listitem_byIndex(size_t n
) const
1188 if (templatetype
!= TEMPLATE_LIST
)
1189 FATAL_ERROR("Template::get_listitam_byIndex()");
1190 if (has_permutation
) {
1191 size_t nof_ts
= u
.templates
->get_nof_ts(), index
= 0;
1192 for (size_t i
= 0; i
< nof_ts
; i
++) {
1193 Template
*t
= u
.templates
->get_t_byIndex(i
);
1194 if (t
->templatetype
== PERMUTATION_MATCH
) {
1195 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
1196 if (n
< index
+ nof_perm_ts
)
1197 return t
->u
.templates
->get_t_byIndex(n
- index
);
1198 else index
+= nof_perm_ts
;
1200 if (n
== index
) return t
;
1204 FATAL_ERROR("Template::get_listitem_byIndex(): index overflow");
1206 } else return u
.templates
->get_t_byIndex(n
);
1209 /** \todo revise and merge with get_template_refd() */
1210 Template
* Template::get_template_refd_last(ReferenceChain
*refch
)
1212 // return this for non-referenced templates
1213 if (templatetype
!= TEMPLATE_REFD
) return this;
1214 // use the cached template if present
1215 else if (u
.ref
.refd_last
) return u
.ref
.refd_last
;
1217 Common::Assignment
*t_ass
= u
.ref
.ref
->get_refd_assignment();
1218 // escape from invalid recursion loops
1219 if (templatetype
!= TEMPLATE_REFD
) return this;
1220 if (!t_ass
) FATAL_ERROR("Template::get_template_refd_last()");
1221 if (t_ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) {
1222 // return this if the reference does not point to a template
1223 u
.ref
.refd_last
= this;
1224 return u
.ref
.refd_last
;
1227 // otherwise evaluate the reference
1230 refch
->mark_state();
1231 destroy_refch
= false;
1233 refch
= new ReferenceChain(this, "While searching referenced template");
1234 destroy_refch
= true;
1237 if (refch
->add(get_fullname())) {
1238 Template
*t_refd
= get_template_refd(refch
);
1239 // get_template_refd() may set u.ref.refd_last if there are unfoldable
1240 // sub-references in u.ref.ref
1241 if (!u
.ref
.refd_last
) {
1242 u
.ref
.refd_last
= t_refd
->get_template_refd_last(refch
);
1244 ret_val
= u
.ref
.refd_last
;
1246 // a circular reference was found
1247 set_templatetype(TEMPLATE_ERROR
);
1250 if (destroy_refch
) delete refch
;
1251 else refch
->prev_state();
1255 Template
* Template::get_refd_sub_template(Ttcn::FieldOrArrayRefs
*subrefs
,
1257 ReferenceChain
*refch
)
1259 if (!subrefs
) return this;
1261 for (size_t i
=0; i
<subrefs
->get_nof_refs(); i
++) {
1263 t
=t
->get_template_refd_last(refch
);
1264 t
->set_lowerid_to_ref();
1265 switch(t
->templatetype
) {
1266 case TEMPLATE_ERROR
:
1269 case INDEXED_TEMPLATE_LIST
:
1272 case SPECIFIC_VALUE
:
1273 (void)t
->u
.specific_value
->get_refd_sub_value(
1274 subrefs
, i
, usedInIsbound
, refch
); // only to report errors
1279 Ttcn::FieldOrArrayRef
*ref
=subrefs
->get_ref(i
);
1280 if(ref
->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF
)
1281 t
=t
->get_refd_field_template(*ref
->get_id(), *ref
, usedInIsbound
,
1283 else t
=t
->get_refd_array_template(ref
->get_val(), usedInIsbound
, refch
);
1288 Template
* Template::get_template_refd(ReferenceChain
*refch
)
1290 unsigned int const prev_err_count
= get_error_count();
1291 if (templatetype
!= TEMPLATE_REFD
)
1292 FATAL_ERROR("Template::get_template_refd()");
1293 // use the cached pointer if it is already set
1294 if (u
.ref
.refd
) return u
.ref
.refd
;
1295 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1296 if (!ass
) FATAL_ERROR("Template::get_template_refd()");
1297 if(ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
1298 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
1299 Template
*asst
= ass
->get_Template();
1300 Template
*t
= asst
->get_refd_sub_template(
1301 subrefs
, u
.ref
.ref
->getUsedInIsbound(), refch
);
1304 // Why do we not set u.ref.refd_last ?
1306 else if (subrefs
&& subrefs
->has_unfoldable_index()) {
1307 // some array indices could not be evaluated
1309 u
.ref
.refd_last
= this;
1310 } else if (u
.ref
.ref
->getUsedInIsbound()) {
1312 u
.ref
.refd_last
= this;
1314 // an error was found while resolving sub-references
1315 if (get_error_count() == prev_err_count
) {
1316 // it was not reported, report it now
1317 error("Using a template which refers to a non-template is not supported");
1318 asst
->note("Workaround: change the right hand side refer to a template");
1319 if (ass
->is_local()) {
1320 ass
->note("Workaround: change the template definition "
1321 "to a var template");
1324 set_templatetype(TEMPLATE_ERROR
);
1328 // the reference is unfoldable
1334 Template
* Template::get_refd_field_template(const Identifier
& field_id
,
1335 const Location
& loc
, bool usedInIsbound
, ReferenceChain
*refch
)
1337 switch (templatetype
) {
1342 case COMPLEMENTED_LIST
:
1343 // the above template types are valid matching mechanisms,
1344 // but they cannot be sub-referenced
1345 loc
.error("Reference to field `%s' of %s `%s'",
1346 field_id
.get_dispname().c_str(), get_templatetype_str(),
1347 get_fullname().c_str());
1352 if(!my_governor
) FATAL_ERROR("Template::get_refd_field_template()");
1353 Type
*t
= my_governor
->get_type_refd_last();
1354 const char *typetype_str
="set";
1355 switch(t
->get_typetype()) {
1359 case Type::T_CHOICE_A
:
1360 case Type::T_CHOICE_T
:
1361 case Type::T_OPENTYPE
:
1362 case Type::T_ANYTYPE
:
1363 if (!t
->has_comp_withName(field_id
)) {
1364 loc
.error("Reference to non-existent union field `%s' in type `%s'",
1365 field_id
.get_dispname().c_str(), t
->get_typename().c_str());
1367 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1368 // this is an invalid matching mechanism, the error is already reported
1369 //error("invalid matching mechanism (not template list) but %d", templatetype);
1371 } else if (u
.named_templates
->get_nof_nts() != 1) {
1372 // this is an invalid union template (more than one active field)
1373 // the error is already reported
1374 //error("invalid union template ");
1377 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(0);
1378 if (nt
->get_name() != field_id
) {
1379 if (!usedInIsbound
) {
1380 loc
.error("Reference to inactive field `%s' in a template of"
1381 " union type `%s'. The active field is `%s'.",
1382 field_id
.get_dispname().c_str(),
1383 t
->get_typename().c_str(),
1384 nt
->get_name().get_dispname().c_str());
1389 return nt
->get_template();
1394 typetype_str
="record";
1398 if (!t
->has_comp_withName(field_id
)) {
1399 loc
.error("Reference to non-existent %s field `%s' in type `%s'",
1400 typetype_str
, field_id
.get_dispname().c_str(),
1401 t
->get_typename().c_str());
1403 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1404 // this is an invalid matching mechanism
1405 // the error should be already reported
1407 } else if (u
.named_templates
->has_nt_withName(field_id
)) {
1408 // the field is found, everything is OK
1409 return u
.named_templates
->get_nt_byName(field_id
)->get_template();
1410 } else if (base_template
) {
1411 // take the field from the base template (recursively)
1412 return base_template
->get_template_refd_last(refch
)
1413 ->get_refd_field_template(field_id
, loc
, usedInIsbound
, refch
);
1415 if (!usedInIsbound
) {
1416 // this should not happen unless there is an error
1417 // (e.g. missing field)
1418 loc
.error("Reference to an unbound field `%s'",
1419 field_id
.get_dispname().c_str());
1424 loc
.error("Invalid field reference `%s': type `%s' "
1425 "does not have fields", field_id
.get_dispname().c_str(),
1426 t
->get_typename().c_str());
1431 Template
* Template::get_refd_array_template(Value
*array_index
,
1433 ReferenceChain
*refch
)
1435 switch (templatetype
) {
1440 case COMPLEMENTED_LIST
:
1441 case SUPERSET_MATCH
:
1443 // the above template types are valid matching mechanisms,
1444 // but they cannot be sub-referenced
1445 array_index
->error("Reference with index to an element of %s `%s'",
1446 get_templatetype_str(), get_fullname().c_str());
1451 Value
*v_index
= array_index
->get_value_refd_last(refch
);
1453 bool index_available
= false;
1454 if (!v_index
->is_unfoldable()) {
1455 if (v_index
->get_valuetype() == Value::V_INT
) {
1456 index
= v_index
->get_val_Int()->get_val();
1457 index_available
= true;
1459 array_index
->error("An integer value was expected as index");
1462 if (!my_governor
) FATAL_ERROR("Template::get_refd_array_template()");
1463 Type
*t
= my_governor
->get_type_refd_last();
1464 const char *typetype_str
="set";
1465 switch(t
->get_typetype()) {
1470 typetype_str
="record";
1473 if (index_available
) {
1475 array_index
->error("A non-negative integer value was expected "
1476 "instead of %s for indexing a template of `%s of' type `%s'",
1477 Int2string(index
).c_str(), typetype_str
,
1478 t
->get_typename().c_str());
1480 } else if (templatetype
!= TEMPLATE_LIST
) {
1481 // remain silent the error has been already reported
1484 size_t nof_elements
= get_nof_listitems();
1485 if (index
>= static_cast<Int
>(nof_elements
)) {
1486 array_index
->error("Index overflow in a template of `%s of' type "
1487 "`%s': the index is %s, but the template has only %lu elements",
1488 typetype_str
, t
->get_typename().c_str(),
1489 Int2string(index
).c_str(), (unsigned long) nof_elements
);
1494 // the index is not available or the error has been reported above
1499 if (index_available
) {
1500 ArrayDimension
*dim
= t
->get_dimension();
1501 dim
->chk_index(v_index
, Type::EXPECTED_DYNAMIC_VALUE
);
1502 if (templatetype
== TEMPLATE_LIST
&& !dim
->get_has_error()) {
1503 // perform the index transformation
1504 index
-= dim
->get_offset();
1505 // check for index underflow/overflow or too few elements in template
1506 if (index
< 0 || index
>= static_cast<Int
>(get_nof_listitems()))
1509 // remain silent, the error has been already reported
1513 // the index is not available or the error has been reported above
1518 array_index
->error("Invalid array element reference: type `%s' cannot "
1519 "be indexed", t
->get_typename().c_str());
1522 Template
*ret_val
= get_listitem_byIndex(index
);
1523 if (ret_val
->templatetype
== TEMPLATE_NOTUSED
) {
1524 if (base_template
) {
1525 // take the referred element from the base template
1526 return base_template
->get_template_refd_last(refch
)
1527 ->get_refd_array_template(v_index
, usedInIsbound
, refch
);
1529 if(ret_val
->get_templatetype() == TEMPLATE_NOTUSED
)
1530 error("Not used symbol is not allowed in this context");
1533 } else return ret_val
;
1536 bool Template::temps_contains_anyornone_symbol() const
1538 switch (templatetype
) {
1540 case SUPERSET_MATCH
:
1542 case PERMUTATION_MATCH
:
1545 FATAL_ERROR("Template::temps_contains_anyornone_symbol()");
1547 size_t nof_comps
= u
.templates
->get_nof_ts();
1548 for (size_t i
= 0; i
< nof_comps
; i
++) {
1549 Template
*t
= u
.templates
->get_t_byIndex(i
);
1550 switch (t
->templatetype
) {
1553 case PERMUTATION_MATCH
:
1555 if (t
->temps_contains_anyornone_symbol()) return true;
1564 size_t Template::get_nof_comps_not_anyornone() const
1566 switch (templatetype
) {
1568 case SUPERSET_MATCH
:
1570 case PERMUTATION_MATCH
:
1573 FATAL_ERROR("Template::get_nof_comps_not_anyornone()");
1576 size_t nof_comps
= u
.templates
->get_nof_ts();
1577 for (size_t i
= 0; i
< nof_comps
; i
++) {
1578 Template
*t
= u
.templates
->get_t_byIndex(i
);
1579 switch (t
->templatetype
) {
1583 case PERMUTATION_MATCH
:
1585 ret_val
+= t
->get_nof_comps_not_anyornone();
1588 // other types are counted as 1
1596 bool Template::pattern_contains_anyornone_symbol() const
1598 switch (templatetype
) {
1602 return u
.pattern
->find('*') < u
.pattern
->size();
1607 FATAL_ERROR("Template::pattern_contains_anyornone_symbol()");
1612 size_t Template::get_min_length_of_pattern() const
1615 switch (templatetype
) {
1617 case HSTR_PATTERN
: {
1618 size_t pattern_len
= u
.pattern
->size();
1619 const char *pattern_ptr
= u
.pattern
->c_str();
1620 for (size_t i
= 0; i
< pattern_len
; i
++)
1621 if (pattern_ptr
[i
] != '*') ret_val
++;
1623 case OSTR_PATTERN
: {
1624 size_t pattern_len
= u
.pattern
->size();
1625 const char *pattern_ptr
= u
.pattern
->c_str();
1626 for (size_t i
= 0; i
< pattern_len
; i
++) {
1627 switch (pattern_ptr
[i
]) {
1636 // count as 1 and skip over the next hex digit
1646 FATAL_ERROR("Template::get_min_length_of_pattern()");
1651 bool Template::is_Value() const
1653 if (length_restriction
|| is_ifpresent
) return false;
1654 switch (templatetype
) {
1655 case TEMPLATE_ERROR
:
1656 case TEMPLATE_NOTUSED
:
1659 case SPECIFIC_VALUE
:
1660 if(u
.specific_value
->get_valuetype() == Value::V_INVOKE
) {
1661 Type
*t
= u
.specific_value
1662 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE
);
1663 if(t
&& t
->get_type_refd_last()->get_typetype() == Type::T_FUNCTION
&&
1664 t
->get_type_refd_last()->get_returns_template()) return false;
1667 case TEMPLATE_LIST
: {
1668 Templates
*ts
= u
.templates
;
1669 for (size_t i
= 0; i
< ts
->get_nof_ts(); i
++)
1670 if (!ts
->get_t_byIndex(i
)->is_Value()) return false;
1673 case NAMED_TEMPLATE_LIST
: {
1674 NamedTemplates
*ts
= u
.named_templates
;
1675 for (size_t i
= 0;i
< ts
->get_nof_nts(); i
++)
1676 if (!ts
->get_nt_byIndex(i
)->get_template()->is_Value()) return false;
1679 case INDEXED_TEMPLATE_LIST
: {
1680 IndexedTemplates
*ts
= u
.indexed_templates
;
1681 for (size_t i
= 0; i
< ts
->get_nof_its(); i
++)
1682 if (!ts
->get_it_byIndex(i
)->get_template()->is_Value()) return false;
1685 case TEMPLATE_REFD
: {
1686 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
1687 switch (ass
->get_asstype()) {
1688 case Common::Assignment::A_EXT_CONST
:
1689 case Common::Assignment::A_PAR_VAL
:
1690 case Common::Assignment::A_PAR_VAL_IN
:
1691 case Common::Assignment::A_PAR_VAL_OUT
:
1692 case Common::Assignment::A_PAR_VAL_INOUT
:
1693 case Common::Assignment::A_VAR
:
1704 Value
*Template::get_Value()
1707 switch(templatetype
) {
1708 case TEMPLATE_ERROR
:
1709 ret_val
= new Value(Value::V_ERROR
);
1711 case TEMPLATE_NOTUSED
:
1712 ret_val
= new Value(Value::V_NOTUSED
);
1715 ret_val
= new Value(Value::V_OMIT
);
1717 case SPECIFIC_VALUE
:
1718 ret_val
= u
.specific_value
;
1719 u
.specific_value
= 0;
1720 set_templatetype(TEMPLATE_ERROR
);
1722 case TEMPLATE_LIST
: {
1723 Values
*vs
= new Values
;
1724 size_t nof_ts
= u
.templates
->get_nof_ts();
1726 for (size_t i
= 0; i
< nof_ts
; i
++) {
1727 Value
* v
= u
.templates
->get_t_byIndex(i
)->get_Value();
1728 if (!gov
) gov
= v
->get_my_governor();
1731 ret_val
= new Value(Value::V_SEQOF
, vs
);
1732 if (gov
) gov
= gov
->get_parent_type();
1733 if (gov
) ret_val
->set_my_governor(gov
);
1735 case NAMED_TEMPLATE_LIST
: {
1736 NamedValues
*nvs
= new NamedValues
;
1737 size_t nof_nts
= u
.named_templates
->get_nof_nts();
1739 for (size_t i
= 0; i
< nof_nts
; i
++) {
1740 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
1741 Value
* v
= nt
->get_template()->get_Value();
1742 if (!gov
) gov
= v
->get_my_governor();
1743 NamedValue
*nv
= new NamedValue(nt
->get_name().clone(), v
);
1744 nv
->set_location(*nt
);
1747 ret_val
= new Value(Value::V_SEQ
, nvs
);
1748 if (gov
) gov
= gov
->get_parent_type();
1749 if (gov
) ret_val
->set_my_governor(gov
);
1751 case INDEXED_TEMPLATE_LIST
: {
1752 Values
*ivs
= new Values(true);
1753 size_t nof_its
= u
.indexed_templates
->get_nof_its();
1755 for (size_t i
= 0; i
< nof_its
; i
++) {
1756 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
1757 Value
* v
= it
->get_template()->get_Value();
1758 if (!gov
) gov
= v
->get_my_governor();
1759 IndexedValue
*iv
= new IndexedValue(it
->get_index().clone(), v
);
1760 iv
->set_location(*it
);
1763 ret_val
= new Value(Value::V_SEQOF
, ivs
);
1764 if (gov
) gov
= gov
->get_parent_type();
1765 if (gov
) ret_val
->set_my_governor(gov
);
1768 FATAL_ERROR("Template::get_Value()");
1772 ret_val
->set_location(*this);
1773 ret_val
->set_my_scope(get_my_scope());
1774 ret_val
->set_fullname(get_fullname());
1778 bool Template::is_Ref() const
1780 if (length_restriction
|| is_ifpresent
|| templatetype
!= SPECIFIC_VALUE
)
1782 Value
*v
= u
.specific_value
;
1783 switch (v
->get_valuetype()) {
1784 case Value::V_UNDEF_LOWERID
:
1787 if (dynamic_cast<Ref_base
*>(v
->get_reference())) return true;
1794 Ref_base
*Template::get_Ref()
1796 if (templatetype
!= SPECIFIC_VALUE
)
1797 FATAL_ERROR("Template::get_Ref()");
1798 return u
.specific_value
->steal_ttcn_ref_base();
1801 void Template::chk_recursions(ReferenceChain
& refch
)
1803 if (recurs_checked
) return;
1806 if (t
->templatetype
== SPECIFIC_VALUE
) break;
1807 else if (!refch
.add(t
->get_fullname())) goto end
;
1808 else if (t
->templatetype
!= TEMPLATE_REFD
) break;
1809 ActualParList
*parlist
= t
->u
.ref
.ref
->get_parlist();
1810 if (parlist
) parlist
->chk_recursions(refch
);
1811 Template
*t_refd
= t
->get_template_refd(&refch
);
1812 if (t_refd
== t
) break;
1815 t
->set_lowerid_to_ref();
1816 switch (t
->templatetype
) {
1817 case SPECIFIC_VALUE
:
1818 t
->u
.specific_value
->chk_recursions(refch
);
1822 case COMPLEMENTED_LIST
:
1823 case SUPERSET_MATCH
:
1825 case PERMUTATION_MATCH
:
1826 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++) {
1828 t
->u
.templates
->get_t_byIndex(i
)->chk_recursions(refch
);
1832 case NAMED_TEMPLATE_LIST
:
1833 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++) {
1835 t
->u
.named_templates
->get_nt_byIndex(i
)
1836 ->get_template()->chk_recursions(refch
);
1840 case INDEXED_TEMPLATE_LIST
:
1841 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++) {
1843 t
->u
.indexed_templates
->get_it_byIndex(i
)
1844 ->get_template()->chk_recursions(refch
);
1850 t
->u
.pstring
->chk_recursions(refch
);
1856 recurs_checked
= true;
1859 void Template::chk_specific_value(bool allow_omit
)
1861 Template
*t
= get_template_refd_last();
1862 if (!allow_omit
&& t
->templatetype
==OMIT_VALUE
) {
1863 t
->error("A specific value was expected instead of omit");
1865 chk_specific_value_generic();
1868 void Template::chk_specific_value_generic()
1870 if (specific_value_checked
) return;
1871 Template
*t
= get_template_refd_last();
1872 if (t
->specific_value_checked
) return;
1873 switch (t
->templatetype
) {
1874 case TEMPLATE_ERROR
:
1875 case TEMPLATE_NOTUSED
:
1876 case TEMPLATE_REFD
: // unfoldable reference
1878 case SPECIFIC_VALUE
:
1879 if(u
.specific_value
->get_valuetype() == Value::V_INVOKE
) {
1880 Type
*t_type
= u
.specific_value
1881 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE
);
1882 if(t_type
&& t_type
->get_type_refd_last()->get_returns_template()) {
1883 set_templatetype(TEMPLATE_INVOKE
);
1888 case TEMPLATE_INVOKE
:
1892 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++)
1893 t
->u
.templates
->get_t_byIndex(i
)->chk_specific_value_generic();
1895 case NAMED_TEMPLATE_LIST
:
1896 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++)
1897 t
->u
.named_templates
->get_nt_byIndex(i
)
1898 ->get_template()->chk_specific_value_generic();
1900 case INDEXED_TEMPLATE_LIST
:
1901 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++)
1902 t
->u
.indexed_templates
->get_it_byIndex(i
)
1903 ->get_template()->chk_specific_value_generic();
1908 t
->error("A specific value was expected instead of %s",
1909 t
->get_templatetype_str());
1912 t
->specific_value_checked
= true;
1913 specific_value_checked
= true;
1916 void Template::chk_invoke()
1918 if(templatetype
!= TEMPLATE_INVOKE
) FATAL_ERROR("Template::chk_invoke()");
1919 if(!u
.invoke
.t_list
) return; //already checked
1920 Error_Context
cntxt(this, "In `apply()' operation");
1921 Type
*t
= u
.invoke
.v
->get_expr_governor_last();
1923 if (t
->get_typetype() != Type::T_FUNCTION
) {
1924 u
.invoke
.v
->error("A value of type function was expected in the "
1925 "argument instead of `%s'", t
->get_typename().c_str());
1926 set_templatetype(TEMPLATE_ERROR
);
1930 if (u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
1931 u
.invoke
.v
->error("A value of type function was expected in the "
1933 set_templatetype(TEMPLATE_ERROR
);
1936 my_scope
->chk_runs_on_clause(t
, *this, "call");
1937 Ttcn::FormalParList
*fp_list
= t
->get_fat_parameters();
1938 Ttcn::ActualParList
*parlist
= new Ttcn::ActualParList
;
1939 bool is_erroneous
= fp_list
->fold_named_and_chk(u
.invoke
.t_list
,parlist
);
1940 delete u
.invoke
.t_list
;
1941 u
.invoke
.t_list
= 0;
1944 u
.invoke
.ap_list
= 0;
1946 parlist
->set_fullname(get_fullname());
1947 parlist
->set_my_scope(get_my_scope());
1948 u
.invoke
.ap_list
= parlist
;
1952 Templates
*Template::harbinger(Template
*t
, bool from_permutation
, bool killer
)
1954 Templates
*new_templates
= new Templates
;
1955 switch (t
->u
.all_from
->templatetype
) {
1956 case SPECIFIC_VALUE
: {
1957 Value
*innerv
= t
->u
.all_from
->get_specific_value();
1958 //if (v->get_valuetype() == Value::V_UNDEF_LOWERID)
1959 innerv
->set_lowerid_to_ref();
1960 // should be a ref now
1961 bool can_flatten
= true;
1962 Common::Reference
*ref
= innerv
->get_reference();
1963 if (dynamic_cast<Ttcn::Ref_pard
*>(ref
)) {
1964 // Cannot flatten at compile time if the template has parameters.
1965 can_flatten
= false;
1967 Common::Assignment
*ass
= ref
->get_refd_assignment();
1968 if (ass
== NULL
) { // perhaps erroneous
1972 Common::Assignment::asstype_t asst
= ass
->get_asstype();
1974 case Common::Assignment::A_MODULEPAR_TEMP
:
1975 case Common::Assignment::A_VAR_TEMPLATE
:
1976 case Common::Assignment::A_FUNCTION_RTEMP
:
1977 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: {
1978 // Cannot flatten at compile time
1979 delete new_templates
;
1983 case Common::Assignment::A_TEMPLATE
: {
1984 Template
*tpl
= ass
->get_Template();
1985 // tpl is the template whose name appears after the "all from"
1986 Template::templatetype_t tpltt
= tpl
->get_templatetype();
1988 case TEMPLATE_REFD
: {
1989 delete new_templates
;
1996 size_t nvl
= tpl
->get_nof_comps();
1997 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
1998 Template
*orig
= tpl
->get_temp_byIndex(ti
);
1999 switch (orig
->templatetype
) {
2000 case SPECIFIC_VALUE
: {
2002 Value
*val
= orig
->get_specific_value();
2003 if (val
->get_valuetype() == Value::V_REFD
) {
2004 if (dynamic_cast<Ttcn::Ref_pard
*>(val
->get_reference())) {
2005 // Cannot flatten at compile time if one of the values or templates has parameters.
2006 can_flatten
= false;
2012 if (from_permutation
) {
2013 break; // AnyElementOrNone allowed in "all from" now
2016 case PERMUTATION_MATCH
:
2017 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2018 t
->set_templatetype(TEMPLATE_ERROR
);
2024 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2025 Template
*orig
= tpl
->get_temp_byIndex(ti
);
2026 Template
*copy
= orig
->clone();
2027 copy
->set_my_scope(orig
->get_my_scope());
2028 new_templates
->add_t(copy
);
2032 // Cannot flatten at compile time
2033 delete new_templates
;
2039 case NAMED_TEMPLATE_LIST
: {
2040 size_t nvl
= tpl
->get_nof_comps();
2041 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2042 NamedTemplate
*orig
= tpl
->get_namedtemp_byIndex(ti
);
2043 switch (orig
->get_template()->get_templatetype()) {
2046 case PERMUTATION_MATCH
:
2047 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2048 t
->set_templatetype(TEMPLATE_ERROR
);
2053 delete new_templates
;
2060 tpl
->error("Matching mechanism can not be used as target of 'all from'");
2063 FATAL_ERROR("harbinger");
2067 if (killer
) delete t
;
2071 case Common::Assignment::A_CONST
: { // all from a constant definition
2072 Common::Value
*val
= ass
->get_Value();
2073 switch (val
->get_valuetype()) {
2074 case Common::Value::V_SEQOF
: case Common::Value::V_SETOF
:
2075 case Common::Value::V_ARRAY
: {
2076 const size_t ncomp
= val
->get_nof_comps();
2077 for (size_t i
= 0; i
< ncomp
; ++i
) {
2078 Value
*v
= val
->get_comp_byIndex(i
);
2079 Template
*newt
= new Template(v
->clone());
2080 new_templates
->add_t(newt
);
2085 val
->error("A constant of type `%s' can not be used as target of 'all from'",
2086 val
->get_my_governor()->get_typename().c_str());
2088 } // switch(valuetype)
2089 if (killer
) delete t
;
2092 case Common::Assignment::A_PAR_TEMPL_IN
:
2093 case Common::Assignment::A_PAR_TEMPL_INOUT
:
2094 //TODO: flatten if the actual par is const template
2095 case Common::Assignment::A_MODULEPAR
: // all from a module parameter
2096 case Common::Assignment::A_VAR
: // all from a variable
2097 case Common::Assignment::A_PAR_VAL_IN
:
2098 case Common::Assignment::A_PAR_VAL_INOUT
: {
2099 delete new_templates
; // cannot flatten at compile time
2104 FATAL_ERROR("harbinger asst %d", asst
);
2110 FATAL_ERROR("unexpected all from inside all from");
2113 FATAL_ERROR("tt %d", t
->u
.all_from
->templatetype
);
2116 return new_templates
;
2119 bool Template::flatten(bool from_permutation
)
2121 switch (templatetype
) {
2124 case COMPLEMENTED_LIST
:
2125 case SUPERSET_MATCH
:
2127 case PERMUTATION_MATCH
: {
2128 size_t num_t
= u
.templates
->get_nof_ts(); // one of these is the "all from"
2129 Templates
*new_templates
= new Templates
;
2130 for (size_t i
= 0; i
< num_t
; ++i
) {
2131 Template
*& t
= u
.templates
->get_t_byIndex(i
);
2132 // the element in the (,,,)
2133 switch (t
->templatetype
) {
2134 case VALUE_LIST_ALL_FROM
: {
2135 // the all from from something like subset(1, (all from...), 99)
2136 // value list: one out of many possible values^^^^^^^^^^^^^
2137 Location
tloc(*t
); // save the location info
2138 string
tname(t
->get_fullname());
2139 Templates
*ha
= harbinger(t
, from_permutation
, true);
2141 // Don't touch t from now on, it might have been deleted!
2142 Template
*qq
= new Template(VALUE_LIST
, ha
);
2143 qq
->set_location(tloc
);
2144 qq
->set_fullname(tname
+ ".all_from");
2145 new_templates
->add_t(qq
);
2148 new_templates
->add_t(t
); // transfer it unchanged
2153 case ALL_FROM
: { // subset(1, all from ..., 99)
2154 // some number of elements--^^^^^^^^^^^^
2155 if (t
->checked
) FATAL_ERROR("too late");
2156 Templates
*af
= harbinger(t
, from_permutation
, true);
2158 for (size_t a
= 0, num
= af
->get_nof_ts(); a
< num
; ++a
) {
2159 Template
*& t2
= af
->get_t_byIndex(a
);
2160 new_templates
->add_t(t2
);
2161 t2
= 0; // take it away from its current owner
2166 new_templates
->add_t(t
); // transfer it unchanged
2169 break; } // case ALL_FROM
2171 case PERMUTATION_MATCH
: {
2172 // permut inside a value list: { 1, permut(), 2 }
2173 flattened
&= t
->flatten(true);
2174 new_templates
->add_t(t
);
2178 // case COMPLEMENTED_LIST:
2179 // case SUPERSET_MATCH:
2180 // case SUBSET_MATCH:
2182 flattened
&=t
->flatten(false);
2183 new_templates
->add_t(t
);
2186 new_templates
->add_t(t
);
2189 t
= 0; // take it away from the original
2192 u
.templates
= new_templates
;
2193 //printf("!!! flattened from %lu to %lu at line %d\n",
2194 // (unsigned long)num_t, (unsigned long)new_templates->get_nof_ts(),
2195 // get_first_line());
2199 case VALUE_LIST_ALL_FROM
: {
2200 Templates
*new_templates
= harbinger(this, from_permutation
, false);
2201 if (new_templates
) {
2203 // now we can change the type
2204 templatetype
= VALUE_LIST
;
2205 u
.templates
= new_templates
;
2209 case TEMPLATE_ERROR
: case TEMPLATE_NOTUSED
:
2210 case OMIT_VALUE
: case ANY_VALUE
: case ANY_OR_OMIT
:
2211 case SPECIFIC_VALUE
:
2212 case TEMPLATE_REFD
: case TEMPLATE_INVOKE
:
2213 case NAMED_TEMPLATE_LIST
: case INDEXED_TEMPLATE_LIST
:
2216 case BSTR_PATTERN
: case HSTR_PATTERN
: case OSTR_PATTERN
:
2217 case CSTR_PATTERN
: case USTR_PATTERN
:
2221 set_fullname(get_fullname()); // recompute fullname (esp. for components)
2222 set_my_scope(get_my_scope());
2227 const char* Template::get_restriction_name(template_restriction_t tr
)
2239 FATAL_ERROR("Template::get_restriction_name()");
2244 template_restriction_t
Template::get_sub_restriction(
2245 template_restriction_t tr
, Ref_base
* ref
)
2247 if (!ref
) FATAL_ERROR("Template::get_sub_restriction()");
2248 if (!ref
->get_subrefs()) return tr
;
2249 bool is_optional
= true; // the referenced field is on an optional path
2250 Common::Assignment
* ass
= ref
->get_refd_assignment();
2252 Type
* t
= ass
->get_Type();
2254 ReferenceChain
refch(ref
, "While checking template restriction");
2255 t
= t
->get_field_type(ref
->get_subrefs(), Type::EXPECTED_TEMPLATE
,
2257 if (t
) is_optional
= false;
2266 return is_optional
? TR_OMIT
: TR_VALUE
;
2268 return is_optional
? TR_NONE
: TR_PRESENT
;
2270 FATAL_ERROR("Template::get_sub_restriction()");
2275 bool Template::is_less_restrictive(template_restriction_t needed_tr
,
2276 template_restriction_t refd_tr
)
2278 switch (needed_tr
) {
2282 return refd_tr
!=TR_VALUE
;
2284 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_OMIT
;
2286 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_PRESENT
;
2288 FATAL_ERROR("Template::is_less_restrictive()");
2293 char* Template::generate_restriction_check_code(char* str
, const char* name
,
2294 template_restriction_t tr
)
2296 const char* tr_name
;
2301 tr_name
= "TR_OMIT";
2304 tr_name
= "TR_VALUE";
2307 tr_name
= "TR_PRESENT";
2310 FATAL_ERROR("Template::generate_restriction_check_code()");
2312 return mputprintf(str
, "%s.check_restriction(%s);\n", name
, tr_name
);
2315 // embedded templates -> check needed only for case of TR_OMIT
2316 bool Template::chk_restriction_named_list(const char* definition_name
,
2317 map
<string
, void>& checked_map
, size_t needed_checked_cnt
)
2319 bool needs_runtime_check
= false;
2320 if (checked_map
.size()>=needed_checked_cnt
) return needs_runtime_check
;
2321 switch (templatetype
) {
2322 case NAMED_TEMPLATE_LIST
:
2323 for (size_t i
= 0;i
< u
.named_templates
->get_nof_nts(); i
++) {
2324 Template
* tmpl
= u
.named_templates
->get_nt_byIndex(i
)->get_template();
2325 const string
& name
=
2326 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name();
2327 if (!checked_map
.has_key(name
)) {
2328 bool nrc
= tmpl
->chk_restriction(definition_name
, TR_OMIT
);
2329 needs_runtime_check
= needs_runtime_check
|| nrc
;
2330 checked_map
.add(name
, 0);
2333 if (base_template
) {
2334 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2335 checked_map
, needed_checked_cnt
);
2336 needs_runtime_check
= needs_runtime_check
|| nrc
;
2341 error("Restriction on %s does not allow usage of %s",
2342 definition_name
, get_templatetype_str());
2345 // others will be converted to specific value
2348 return needs_runtime_check
;
2351 bool Template::chk_restriction_refd(const char* definition_name
,
2352 template_restriction_t template_restriction
)
2354 bool needs_runtime_check
= false;
2355 Common::Assignment
* ass
= u
.ref
.ref
->get_refd_assignment();
2356 if (!ass
) FATAL_ERROR("Template::chk_restriction_refd()");
2357 // get the restriction on the referenced template
2358 template_restriction_t refd_tr
= TR_NONE
;
2359 bool is_var_template
= false;
2360 switch (ass
->get_asstype()) {
2361 case Common::Assignment::A_TEMPLATE
: {
2362 Template
* t_last
= get_template_refd_last();
2364 bool nrc
= t_last
->chk_restriction(definition_name
,
2365 template_restriction
);
2366 needs_runtime_check
= needs_runtime_check
|| nrc
;
2369 case Common::Assignment::A_MODULEPAR_TEMP
:
2370 is_var_template
= true;
2371 refd_tr
= TR_NONE
; // can't place restriction on this thing
2373 case Common::Assignment::A_VAR_TEMPLATE
: {
2374 Def_Var_Template
* dvt
= dynamic_cast<Def_Var_Template
*>(ass
);
2375 if (!dvt
) FATAL_ERROR("Template::chk_restriction_refd()");
2376 is_var_template
= true;
2377 refd_tr
= dvt
->get_template_restriction();
2379 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2380 // we do not trust external functions because there is no generated
2381 // restriction check on their return value
2382 if (template_restriction
!=TR_NONE
) needs_runtime_check
= true;
2384 case Common::Assignment::A_FUNCTION_RTEMP
: {
2385 Def_Function_Base
* dfb
= dynamic_cast<Def_Function_Base
*>(ass
);
2386 if (!dfb
) FATAL_ERROR("Template::chk_restriction_refd()");
2387 is_var_template
= true;
2388 refd_tr
= dfb
->get_template_restriction();
2390 case Common::Assignment::A_PAR_TEMPL_IN
:
2391 case Common::Assignment::A_PAR_TEMPL_OUT
:
2392 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
2393 FormalPar
* fp
= dynamic_cast<FormalPar
*>(ass
);
2394 if (!fp
) FATAL_ERROR("Template::chk_restriction_refd()");
2395 is_var_template
= true;
2396 refd_tr
= fp
->get_template_restriction();
2401 if (is_var_template
) {
2402 // check the restriction
2403 refd_tr
= get_sub_restriction(refd_tr
, u
.ref
.ref
);
2404 // if restriction not satisfied issue warning
2405 if (is_less_restrictive(template_restriction
, refd_tr
)) {
2406 needs_runtime_check
= true;
2407 warning("Inadequate restriction on the referenced %s `%s', this may "
2408 "cause a dynamic test case error at runtime", ass
->get_assname(),
2409 u
.ref
.ref
->get_dispname().c_str());
2410 ass
->note("Referenced %s is here", ass
->get_assname());
2413 return needs_runtime_check
;
2416 bool Template::chk_restriction(const char* definition_name
,
2417 template_restriction_t template_restriction
)
2419 bool needs_runtime_check
= false;
2420 switch (template_restriction
) {
2425 if (length_restriction
)
2426 error("Restriction on %s does not allow usage of length restriction",
2429 error("Restriction on %s does not allow usage of `ifpresent'",
2431 switch(templatetype
) {
2432 case TEMPLATE_ERROR
:
2434 case TEMPLATE_NOTUSED
:
2435 if (base_template
) {
2436 bool nrc
= base_template
->chk_restriction(definition_name
,
2437 template_restriction
);
2438 needs_runtime_check
= needs_runtime_check
|| nrc
;
2440 else needs_runtime_check
= true;
2442 case SPECIFIC_VALUE
:
2443 case TEMPLATE_INVOKE
:
2445 case TEMPLATE_REFD
: {
2446 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
);
2447 needs_runtime_check
= needs_runtime_check
|| nrc
;
2450 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2451 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2452 chk_restriction(definition_name
, TR_OMIT
);
2453 needs_runtime_check
= needs_runtime_check
|| nrc
;
2456 case NAMED_TEMPLATE_LIST
: {
2457 map
<string
, void> checked_map
;
2458 size_t needed_checked_cnt
= 0;
2459 if (base_template
&& my_governor
) {
2460 switch (my_governor
->get_typetype()) {
2465 case Type::T_SIGNATURE
:
2466 needed_checked_cnt
= my_governor
->get_nof_comps();
2472 for (size_t i
= 0;i
< u
.named_templates
->get_nof_nts(); i
++) {
2473 bool nrc
= u
.named_templates
->get_nt_byIndex(i
)->get_template()->
2474 chk_restriction(definition_name
, TR_OMIT
);
2475 needs_runtime_check
= needs_runtime_check
|| nrc
;
2476 if (needed_checked_cnt
)
2478 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name(), 0);
2480 if (needed_checked_cnt
) {
2481 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2482 checked_map
, needed_checked_cnt
);
2483 needs_runtime_check
= needs_runtime_check
|| nrc
;
2484 checked_map
.clear();
2487 case INDEXED_TEMPLATE_LIST
:
2488 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
2489 bool nrc
= u
.indexed_templates
->get_it_byIndex(i
)->get_template()->
2490 chk_restriction(definition_name
, TR_OMIT
);
2491 needs_runtime_check
= needs_runtime_check
|| nrc
;
2493 needs_runtime_check
= true; // only basic check, needs runtime check
2496 if (template_restriction
==TR_OMIT
) break;
2497 // Else restriction is TR_VALUE, but template type is OMIT:
2498 // fall through to error.
2500 error("Restriction on %s does not allow usage of %s",
2501 definition_name
, get_templatetype_str());
2507 error("Restriction on %s does not allow usage of `ifpresent'",
2509 switch(templatetype
) {
2510 case TEMPLATE_REFD
: {
2511 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
);
2512 needs_runtime_check
= needs_runtime_check
|| nrc
;
2515 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2516 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2517 chk_restriction(definition_name
, template_restriction
);
2518 needs_runtime_check
= needs_runtime_check
|| nrc
;
2521 case COMPLEMENTED_LIST
: {
2522 // some basic check, always needs runtime check
2523 needs_runtime_check
= true;
2524 bool has_any_or_omit
= false;
2525 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2526 templatetype_t item_templatetype
=
2527 u
.templates
->get_t_byIndex(i
)->templatetype
;
2528 if (item_templatetype
==OMIT_VALUE
|| item_templatetype
==ANY_OR_OMIT
) {
2529 has_any_or_omit
= true;
2533 if (has_any_or_omit
) break;
2535 // FIXME really no break?
2538 error("Restriction on %s does not allow usage of %s",
2539 definition_name
, get_templatetype_str());
2542 break; // all others are ok
2546 FATAL_ERROR("Template::chk_restriction()");
2548 return needs_runtime_check
;
2551 void Template::generate_code_expr(expression_struct
*expr
,
2552 template_restriction_t template_restriction
)
2554 // Only templates without extra matching attributes can be directly
2555 // represented in a C++ expression.
2556 if (!length_restriction
&& !is_ifpresent
2557 && template_restriction
== TR_NONE
) {
2558 // The single expression must be tried first because this rule might
2559 // cover some referenced templates.
2560 if (has_single_expr()) {
2561 expr
->expr
= mputstr(expr
->expr
, get_single_expr(true).c_str());
2564 switch (templatetype
) {
2565 case SPECIFIC_VALUE
:
2566 // A simple specific value: use explicit cast.
2567 expr
->expr
= mputprintf(expr
->expr
, "%s(",
2568 my_governor
->get_genname_template(my_scope
).c_str());
2569 u
.specific_value
->generate_code_expr(expr
);
2570 expr
->expr
= mputc(expr
->expr
, ')');
2573 // A simple unfoldable referenced template.
2574 if (!get_needs_conversion()) {
2575 u
.ref
.ref
->generate_code(expr
);
2577 Type
*my_gov
= get_expr_governor(Type::EXPECTED_TEMPLATE
)
2578 ->get_type_refd_last();
2579 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
2580 ->get_field_type(u
.ref
.ref
->get_subrefs(),
2581 Type::EXPECTED_TEMPLATE
)->get_type_refd_last();
2582 if (!my_gov
|| !refd_gov
|| my_gov
== refd_gov
)
2583 FATAL_ERROR("Template::generate_code_expr()");
2584 expression_struct expr_tmp
;
2585 Code::init_expr(&expr_tmp
);
2586 const string
& tmp_id1
= get_temporary_id();
2587 const char *tmp_id_str1
= tmp_id1
.c_str();
2588 const string
& tmp_id2
= get_temporary_id();
2589 const char *tmp_id_str2
= tmp_id2
.c_str();
2590 expr
->preamble
= mputprintf(expr
->preamble
,
2591 "%s %s;\n", refd_gov
->get_genname_template(my_scope
).c_str(),
2593 expr_tmp
.expr
= mputprintf(expr_tmp
.expr
, "%s = ", tmp_id_str1
);
2594 u
.ref
.ref
->generate_code(&expr_tmp
);
2595 expr
->preamble
= Code::merge_free_expr(expr
->preamble
, &expr_tmp
);
2596 expr
->preamble
= mputprintf(expr
->preamble
,
2598 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
2599 "and `%s' are not compatible at run-time\");\n",
2600 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str2
,
2601 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
2602 ->get_scope_mod()).c_str(), tmp_id_str2
, tmp_id_str1
, my_gov
2603 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
2604 expr
->expr
= mputprintf(expr
->expr
, "%s", tmp_id_str2
);
2607 case TEMPLATE_INVOKE
:
2608 generate_code_expr_invoke(expr
);
2614 // if none of the above methods are applicable use the most generic and
2615 // least efficient solution
2616 // create a temporary object, initialize it and use it in the expression
2617 const string
& tmp_id
= get_temporary_id();
2618 const char *tmp_id_str
= tmp_id
.c_str();
2620 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s;\n",
2621 my_governor
->get_genname_template(my_scope
).c_str(), tmp_id_str
);
2622 set_genname_recursive(tmp_id
);
2623 expr
->preamble
= generate_code_init(expr
->preamble
, tmp_id_str
);
2624 if (template_restriction
!= TR_NONE
)
2625 expr
->preamble
= Template::generate_restriction_check_code(expr
->preamble
,
2626 tmp_id_str
, template_restriction
);
2627 expr
->expr
= mputstr(expr
->expr
, tmp_id_str
);
2630 char *Template::generate_code_init(char *str
, const char *name
)
2632 if (get_code_generated()) return str
;
2633 set_code_generated();
2635 str
= err_descr
->generate_code_init_str(str
, string(name
)+"_err_descr");
2637 switch (templatetype
) {
2646 str
= mputprintf(str
, "%s = %s;\n", name
, get_single_expr(false).c_str());
2648 case SPECIFIC_VALUE
:
2649 if (get_code_section() == CS_POST_INIT
)
2650 str
= u
.specific_value
->rearrange_init_code(str
);
2651 str
= u
.specific_value
->generate_code_init(str
, name
);
2654 str
= generate_code_init_refd(str
, name
);
2656 case TEMPLATE_INVOKE
:
2657 if (get_code_section() == CS_POST_INIT
)
2658 str
= rearrange_init_code_invoke(str
);
2659 str
= generate_code_init_invoke(str
, name
);
2662 case INDEXED_TEMPLATE_LIST
:
2663 str
= generate_code_init_seof(str
, name
);
2665 case NAMED_TEMPLATE_LIST
:
2666 str
= generate_code_init_se(str
, name
);
2668 case VALUE_LIST_ALL_FROM
:
2669 str
= generate_code_init_all_from_list(str
, name
);
2672 str
= generate_code_init_all_from(str
, name
);
2675 str
= generate_code_init_list(str
, name
, false);
2677 case COMPLEMENTED_LIST
:
2678 str
= generate_code_init_list(str
, name
, true);
2681 if (get_code_section() == CS_POST_INIT
)
2682 str
= u
.value_range
->rearrange_init_code(str
);
2683 str
= u
.value_range
->generate_code_init(str
, name
);
2685 case SUPERSET_MATCH
:
2686 str
= generate_code_init_set(str
, name
, true);
2689 str
= generate_code_init_set(str
, name
, false);
2691 case PERMUTATION_MATCH
:
2692 warning("Don't know how to init PERMUT");
2693 str
= mputprintf(str
, "/* FIXME: PERMUT goes here, name=%s*/\n", name
);
2695 case TEMPLATE_ERROR
:
2696 case TEMPLATE_NOTUSED
:
2698 FATAL_ERROR("Template::generate_code_init()");
2700 if (length_restriction
) {
2701 if (get_code_section() == CS_POST_INIT
)
2702 str
= length_restriction
->rearrange_init_code(str
);
2703 str
= length_restriction
->generate_code_init(str
, name
);
2705 if (is_ifpresent
) str
= mputprintf(str
, "%s.set_ifpresent();\n", name
);
2707 str
= mputprintf(str
, "%s.set_err_descr(&%s_err_descr);\n", name
, name
);
2712 char *Template::rearrange_init_code(char *str
)
2714 switch (templatetype
) {
2715 case SPECIFIC_VALUE
:
2716 str
= u
.specific_value
->rearrange_init_code(str
);
2719 str
= rearrange_init_code_refd(str
);
2721 case TEMPLATE_INVOKE
:
2722 str
= rearrange_init_code_invoke(str
);
2726 case COMPLEMENTED_LIST
:
2727 case SUPERSET_MATCH
:
2729 case PERMUTATION_MATCH
:
2730 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
2731 str
= u
.templates
->get_t_byIndex(i
)->rearrange_init_code(str
);
2733 case NAMED_TEMPLATE_LIST
:
2734 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
2735 str
= u
.named_templates
->get_nt_byIndex(i
)->get_template()
2736 ->rearrange_init_code(str
);
2738 case INDEXED_TEMPLATE_LIST
:
2739 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
2740 str
= u
.indexed_templates
->get_it_byIndex(i
)->get_template()
2741 ->rearrange_init_code(str
);
2744 str
= u
.value_range
->rearrange_init_code(str
);
2749 if (length_restriction
) str
= length_restriction
->rearrange_init_code(str
);
2753 bool Template::use_single_expr_for_init()
2755 Template
*t_last
= get_template_refd_last();
2756 // return false in case of unfoldable references
2757 if (t_last
->templatetype
== TEMPLATE_REFD
) return false;
2758 // return false if t_last is in a different module
2759 if (t_last
->my_scope
->get_scope_mod_gen() != my_scope
->get_scope_mod_gen())
2761 // return false if t_last cannot be represented by a single expression
2762 if (!t_last
->has_single_expr()) return false;
2763 // return true if t_last is a generic wildcard, string pattern, etc.
2764 if (t_last
->templatetype
!= SPECIFIC_VALUE
) return true;
2765 // examine the specific value
2766 Value
*v_last
= t_last
->u
.specific_value
->get_value_refd_last();
2767 switch (v_last
->get_valuetype()) {
2769 // do not calculate expressions again
2771 case Value::V_REFD
: {
2772 // v_last is an unfoldable value reference
2773 // the scope of the definition that v_last refers to
2775 v_last
->get_reference()->get_refd_assignment()->get_my_scope();
2776 for (Scope
*t_scope
= my_scope
; t_scope
;
2777 t_scope
= t_scope
->get_parent_scope()) {
2778 // return true if the referred definition is in the same scope
2779 // as this or in one of the parent scopes of this
2780 if (t_scope
== v_scope
) return true;
2782 // otherwise return false
2785 // return true only if v_last is defined in the same module as this
2786 return v_last
->get_my_scope()->get_scope_mod_gen() ==
2787 my_scope
->get_scope_mod_gen();
2791 char *Template::generate_code_init_refd(char *str
, const char *name
)
2793 if (use_single_expr_for_init() && has_single_expr()) {
2794 str
= mputprintf(str
, "%s = %s;\n", name
,
2795 get_single_expr(false).c_str());
2797 expression_struct expr
;
2798 Code::init_expr(&expr
);
2799 bool use_ref_for_codegen
= true;
2800 if (get_code_section() == CS_POST_INIT
) {
2801 // the referencing template is a part of a non-parameterized template
2802 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
2803 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
&&
2804 ass
->get_my_scope()->get_scope_mod_gen() ==
2805 my_scope
->get_scope_mod_gen()) {
2806 // the reference points to (a field of) a template
2807 // within the local module
2808 if (ass
->get_FormalParList()) {
2809 // the referred template is parameterized
2810 // generate the initialization sequence first for all dependent
2811 // non-parameterized templates
2812 str
= rearrange_init_code_refd(str
);
2814 // the referred template is non-parameterized
2815 // use a different algorithm for code generation
2816 str
= generate_rearrange_init_code_refd(str
, &expr
);
2817 use_ref_for_codegen
= false;
2821 if (use_ref_for_codegen
) u
.ref
.ref
->generate_code_const_ref(&expr
);
2822 if (expr
.preamble
|| expr
.postamble
) {
2823 // the expressions within reference need temporary objects
2824 str
= mputstr(str
, "{\n");
2825 str
= mputstr(str
, expr
.preamble
);
2826 if (use_runtime_2
&& get_needs_conversion()) {
2827 const string
& tmp_id
= get_temporary_id();
2828 const char *tmp_id_str
= tmp_id
.c_str();
2829 Type
*my_gov
= my_governor
->get_type_refd_last();
2830 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
2831 ->get_type_refd_last();
2832 if (!my_gov
|| !refd_gov
)
2833 FATAL_ERROR("Template::generate_code_init_refd()");
2834 str
= mputprintf(str
,
2836 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
2837 "and `%s' are not compatible at run-time\");\n",
2838 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
2839 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
2840 ->get_scope_mod()).c_str(), tmp_id_str
, expr
.expr
, my_gov
2841 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
2842 str
= mputprintf(str
, "%s = %s;\n", name
, tmp_id_str
);
2844 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
2846 str
= mputstr(str
, expr
.postamble
);
2847 str
= mputstr(str
, "}\n");
2849 // the reference does not need temporary objects
2850 if (use_runtime_2
&& get_needs_conversion()) {
2851 const string
& tmp_id
= get_temporary_id();
2852 const char *tmp_id_str
= tmp_id
.c_str();
2853 Type
*my_gov
= my_governor
->get_type_refd_last();
2854 Type
*refd_gov
= u
.ref
.ref
->get_refd_assignment()->get_Type()
2855 ->get_type_refd_last();
2856 if (!my_gov
|| !refd_gov
)
2857 FATAL_ERROR("Template::generate_code_init_refd()");
2858 str
= mputprintf(str
,
2860 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
2861 "and `%s' are not compatible at run-time\");\n",
2862 my_gov
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
2863 TypeConv::get_conv_func(refd_gov
, my_gov
, get_my_scope()
2864 ->get_scope_mod()).c_str(), tmp_id_str
, expr
.expr
, my_gov
2865 ->get_typename().c_str(), refd_gov
->get_typename().c_str());
2866 str
= mputprintf(str
, "%s = %s;\n", name
, tmp_id_str
);
2868 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
2871 Code::free_expr(&expr
);
2876 char *Template::generate_code_init_invoke(char *str
, const char *name
)
2878 expression_struct expr
;
2879 Code::init_expr(&expr
);
2880 expr
.expr
= mputprintf(expr
.expr
, "%s = ", name
);
2881 generate_code_expr_invoke(&expr
);
2882 return Code::merge_free_expr(str
, &expr
);
2885 char *Template::generate_rearrange_init_code_refd(char *str
,
2886 expression_struct
*expr
)
2888 /** Initially we can assume that:
2889 * - this is a referenced template and a part of a non-parameterized
2891 * - u.ref.ref points to (a field of) a non-parameterized template within
2892 * the same module as \a this.
2893 * - this ensures that the do-while loop will run at least twice (i.e. the
2894 * first continue statement will be reached in the first iteration) */
2895 stack
<FieldOrArrayRef
> refstack
;
2897 // first try to find the smallest dependent template
2899 if (t
->templatetype
== TEMPLATE_REFD
) {
2900 Common::Assignment
*ass
= t
->u
.ref
.ref
->get_refd_assignment();
2901 /** Don't follow the reference if:
2902 * - the referenced definition is not a template
2903 * - the referenced template is parameterized or
2904 * - the referenced template is in different module */
2905 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
&&
2906 ass
->get_FormalParList() == 0 &&
2907 ass
->get_my_scope()->get_scope_mod_gen() ==
2908 my_scope
->get_scope_mod_gen()) {
2909 // accumulate the sub-references of the referred reference
2910 FieldOrArrayRefs
*subrefs
= t
->u
.ref
.ref
->get_subrefs();
2912 for (size_t i
= subrefs
->get_nof_refs(); i
> 0; i
--)
2913 refstack
.push(subrefs
->get_ref(i
- 1));
2915 // jump to the referred top-level template
2916 t
= ass
->get_Template();
2917 // start the iteration from the beginning
2919 // stop otherwise: the reference cannot be followed
2922 // stop if there are no sub-references
2923 if (refstack
.empty()) break;
2924 // take the topmost sub-reference
2925 FieldOrArrayRef
*subref
= refstack
.top();
2926 if (subref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
2927 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
2928 // the field reference can be followed
2929 t
= t
->u
.named_templates
->get_nt_byName(*subref
->get_id())
2932 // trying to follow an array reference
2933 if (t
->templatetype
!= TEMPLATE_LIST
) break;
2934 Value
*array_index
= subref
->get_val()->get_value_refd_last();
2935 if (array_index
->get_valuetype() != Value::V_INT
) break;
2936 // the index is available at compilation time
2937 Int index
= array_index
->get_val_Int()->get_val();
2938 // index transformation in case of arrays
2939 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
2940 index
-= t
->my_governor
->get_dimension()->get_offset();
2941 t
= t
->get_listitem_byIndex(index
);
2943 // the topmost sub-reference was processed
2944 // it can be erased from the stack
2947 // the smallest dependent template is now in t
2948 // generate the initializer sequence for t
2949 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
2950 // the equivalent C++ code of the referenced template is composed of the
2951 // genname of t and the remained sub-references in refstack
2952 expr
->expr
= mputstr(expr
->expr
, t
->get_genname_own(my_scope
).c_str());
2953 while (!refstack
.empty()) {
2954 FieldOrArrayRef
*subref
= refstack
.pop();
2955 if (subref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
2956 expr
->expr
= mputprintf(expr
->expr
, ".%s()",
2957 subref
->get_id()->get_name().c_str());
2959 expr
->expr
= mputc(expr
->expr
, '[');
2960 subref
->get_val()->generate_code_expr(expr
);
2961 expr
->expr
= mputc(expr
->expr
, ']');
2967 bool Template::compile_time() const
2969 switch (templatetype
) {
2971 case VALUE_LIST_ALL_FROM
:
2973 case TEMPLATE_ERROR
: /**< erroneous template */
2974 case TEMPLATE_NOTUSED
: /**< not used symbol (-) */
2975 case OMIT_VALUE
: /**< omit */
2976 case ANY_VALUE
: /**< any value (?) */
2977 case ANY_OR_OMIT
: /**< any or omit (*) */
2978 case SPECIFIC_VALUE
: /**< specific value */
2979 case TEMPLATE_REFD
: /**< reference to another template */
2980 case VALUE_RANGE
: /**< value range match */
2981 case BSTR_PATTERN
: /**< bitstring pattern */
2982 case HSTR_PATTERN
: /**< hexstring pattern */
2983 case OSTR_PATTERN
: /**< octetstring pattern */
2984 case CSTR_PATTERN
: /**< character string pattern */
2985 case USTR_PATTERN
: /**< universal charstring pattern */
2986 case TEMPLATE_INVOKE
:
2987 // Simple templates can be computed at compile time
2990 // "Complex" templates need to look at all elements
2993 case COMPLEMENTED_LIST
:
2994 case SUPERSET_MATCH
:
2996 case PERMUTATION_MATCH
:
2997 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
2998 if (u
.templates
->get_t_byIndex(i
)->compile_time()) continue;
3001 case NAMED_TEMPLATE_LIST
:
3002 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
3003 if (!u
.named_templates
->get_nt_byIndex(i
)->get_template()->compile_time())
3006 case INDEXED_TEMPLATE_LIST
:
3007 for (size_t i
= 0; i
<u
.indexed_templates
->get_nof_its(); i
++)
3008 if (!u
.indexed_templates
->get_it_byIndex(i
)->get_template()->compile_time())
3013 return true; // not reached
3016 char *Template::generate_code_init_seof(char *str
, const char *name
)
3018 switch (templatetype
) {
3019 case TEMPLATE_LIST
: {
3020 size_t nof_ts
= u
.templates
->get_nof_ts();
3022 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3027 Type
*t_last
= my_governor
->get_type_refd_last();
3029 if (t_last
->get_typetype() == Type::T_ARRAY
) {
3030 // take the start index from the array dimension
3031 index_offset
= t_last
->get_dimension()->get_offset();
3033 // indexing always starts from zero
3037 const string
& oftype_name
=
3038 t_last
->get_ofType()->get_genname_template(my_scope
);
3039 const char *oftype_name_str
= oftype_name
.c_str();
3041 ReferenceChain
refch (this, "While searching template");
3042 if (!flattened
|| my_scope
->get_statementblock_scope()) { // this "if" may be redundant if all non-var templates are flattened
3043 str
= mputstr(str
, "// this is a var template\n");
3045 if (compile_time()) goto compile_time
;
3046 // run-time, variable sized init
3048 // This is a record-of var template, like this:
3049 // var template rec_of_int vt_r := {
3050 // 1, 2, 3, permutation(10, all from x, 20), 4, 5 }
3051 // ^^^^^^^--- these ------------------------^^^^^
3052 // are known at compile time, but the length of the "all from"
3053 // is only known at run time.
3054 // Collect the indices where there is an "all from".
3055 dynamic_array
<int> variables
;
3056 size_t fixed_part
= 0;
3057 if (has_permutation
) {
3058 for (size_t i
= 0; i
< nof_ts
; i
++) {
3059 Template
*t
= u
.templates
->get_t_byIndex(i
);
3060 if (t
->templatetype
== PERMUTATION_MATCH
) {
3061 size_t num_p
= t
->u
.templates
->get_nof_ts();
3062 // t->u.templates is 2: "hello" and all from ...
3063 for (size_t j
= 0; j
< num_p
; ++j
) {
3064 Template
*subt
= t
->u
.templates
->get_t_byIndex(j
);
3065 if (subt
->templatetype
== ALL_FROM
) {
3074 char* str_preamble
= 0;
3075 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3076 (unsigned long)fixed_part
);
3079 for (size_t i
= 0; i
< nof_ts
; i
++) {
3080 Template
*t
= u
.templates
->get_t_byIndex(i
);
3081 for (size_t k
= 0, v
= variables
.size(); k
< v
; ++k
) {
3082 if (t
->templatetype
!= PERMUTATION_MATCH
) continue; // ?? really nothing to do ??
3083 Template
*subt
= t
->u
.templates
->get_t_byIndex(variables
[k
]);
3084 if (subt
->templatetype
== ALL_FROM
) {
3085 Value
*refv
= subt
->u
.all_from
->u
.specific_value
;
3086 // don't call get_Value(), it rips out the value from the template
3088 if (refv
->get_valuetype()!=Value::V_REFD
) FATAL_ERROR("%s", __FUNCTION__
);
3089 Common::Reference
*ref
= refv
->get_reference();
3090 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3091 Common::Assignment
*ass
= ref
->get_refd_assignment();
3093 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3095 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3097 // in case of parametrised references:
3098 // - temporary parameters need to be declared (stored in str_preamble)
3099 // - the same temporary needs to be used at each call (generate_code_cached call)
3100 expression_struct expr
;
3101 Code::init_expr(&expr
);
3103 ref_pard
->generate_code_cached(&expr
);
3104 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3106 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3108 Code::free_expr(&expr
);
3111 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3113 expression_struct expr
;
3114 Code::init_expr(&expr
);
3116 subrefs
->generate_code(&expr
, ass
);
3117 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3119 Code::free_expr(&expr
);
3122 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3127 str
= mputstr(str
, str_preamble
);
3128 str
= mputstr(str
, str_set_size
);
3133 str
= mputstrn(str
, ");\n", 3); // finally done set_size
3136 string skipper
, hopper
;
3137 for (size_t i
= 0; i
< nof_ts
; i
++) {
3138 Template
*t
= u
.templates
->get_t_byIndex(i
);
3139 switch (t
->templatetype
) {
3142 case PERMUTATION_MATCH
: {
3143 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
3144 for (size_t j
= 0; j
< nof_perm_ts
; j
++) {
3145 Int
ix(index_offset
+ index
+ j
);
3146 Template
*permut_elem
= t
->u
.templates
->get_t_byIndex(j
);
3147 if (permut_elem
->templatetype
== ALL_FROM
) {
3148 expression_struct expr
;
3149 Code::init_expr(&expr
);
3150 switch (permut_elem
->u
.all_from
->templatetype
) {
3151 case SPECIFIC_VALUE
: {
3152 Value
*spec
= permut_elem
->u
.all_from
->u
.specific_value
;
3153 switch (spec
->get_valuetype()) {
3154 case Common::Value::V_REFD
: {
3155 Common::Reference
*ref
= spec
->get_reference();
3157 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3159 ref_pard
->generate_code_cached(&expr
);
3161 ref
->generate_code(&expr
);
3165 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3172 FATAL_ERROR("ttype %d", permut_elem
->u
.all_from
->templatetype
);
3175 str
= mputprintf(str
,
3176 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3179 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3180 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3183 str
= mputstrn(str
, "}\n", 2);
3185 skipper
+= expr
.expr
;
3186 skipper
+= ".n_elem() /* 3005 */ ";
3187 Code::free_expr(&expr
);
3190 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3191 (Int2string(ix
) + skipper
).c_str(), oftype_name_str
);
3194 // do not consider index_offset in case of permutation indicators
3195 str
= mputprintf(str
, "%s.add_permutation(%lu%s, %lu%s);\n", name
,
3196 (unsigned long)index
, hopper
.c_str(),
3197 (unsigned long)(index
+ nof_perm_ts
- 1), skipper
.c_str());
3199 t
->set_code_generated();
3200 index
+= nof_perm_ts
;
3204 str
= t
->generate_code_init_seof_element(str
, name
,
3205 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3207 case TEMPLATE_NOTUSED
:
3218 if (!has_permutation
&& has_allfrom()) {
3219 for (size_t i
= 0; i
< nof_ts
; i
++) {
3220 Template
*t
= u
.templates
->get_t_byIndex(i
);
3221 if (t
->templatetype
== ALL_FROM
) {
3228 char* str_preamble
= 0;
3229 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3230 (unsigned long)fixed_part
);
3233 for (size_t i
= 0; i
< nof_ts
; i
++) {
3234 Template
*t
= u
.templates
->get_t_byIndex(i
);
3235 printf("generate_code_init_seof ALL_FROM: temptype %u\n", t
->templatetype
);
3236 for (size_t k
= 0, v
= variables
.size(); k
< v
; ++k
) {
3237 if (t
->templatetype
== ALL_FROM
) {
3238 Value
*refv
= t
->u
.all_from
->u
.specific_value
;
3239 // don't call get_Value(), it rips out the value from the template
3240 if (refv
->get_valuetype()!=Value::V_REFD
) FATAL_ERROR("%s", __FUNCTION__
);
3241 Common::Reference
*ref
= refv
->get_reference();
3242 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3243 Common::Assignment
*ass
= ref
->get_refd_assignment();
3244 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3245 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3247 // in case of parametrised references:
3248 // - temporary parameters need to be declared (stored in str_preamble)
3249 // - the same temporary needs to be used at each call (generate_code_cached call)
3250 expression_struct expr
;
3251 Code::init_expr(&expr
);
3253 ref_pard
->generate_code_cached(&expr
);
3254 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3256 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3257 Code::free_expr(&expr
);
3260 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3262 expression_struct expr
;
3263 Code::init_expr(&expr
);
3264 subrefs
->generate_code(&expr
, ass
);
3265 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3266 Code::free_expr(&expr
);
3269 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3273 str
= mputstr(str
, str_preamble
);
3274 str
= mputstr(str
, str_set_size
);
3277 str
= mputstrn(str
, ");\n", 3); // finally done set_size
3281 for (size_t i
= 0; i
< nof_ts
; i
++) {
3282 Template
*t
= u
.templates
->get_t_byIndex(i
);
3283 Int
ix(index_offset
+ i
);
3284 switch (t
->templatetype
) {
3286 expression_struct expr
;
3287 Code::init_expr(&expr
);
3288 switch (t
->u
.all_from
->templatetype
) {
3289 case SPECIFIC_VALUE
: {
3290 Value
*spec
= t
->u
.all_from
->u
.specific_value
;
3291 switch (spec
->get_valuetype()) {
3292 case Common::Value::V_REFD
: {
3293 Common::Reference
*ref
= spec
->get_reference();
3294 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3296 ref_pard
->generate_code_cached(&expr
);
3298 ref
->generate_code(&expr
);
3301 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3306 FATAL_ERROR("ttype %d", t
->u
.all_from
->templatetype
);
3309 str
= mputprintf(str
,
3310 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3312 str
= t
->generate_code_init_seof_element(str
, name
,
3313 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3315 str
= mputstrn(str
, "}\n", 2);
3317 skipper
+= expr
.expr
;
3318 skipper
+= ".n_elem() ";
3319 Code::free_expr(&expr
);
3320 t
->set_code_generated();
3324 printf("generate_code_init_seof allfrom default: %s\n",
3325 (Int2string(index_offset
+ index
) + skipper
).c_str());
3326 str
= t
->generate_code_init_seof_element(str
, name
,
3327 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3329 case TEMPLATE_NOTUSED
:
3339 // setting the size first
3341 str
= mputprintf(str
, "%s.set_size(%lu);\n", name
, (unsigned long) get_nof_listitems());
3342 // determining the index offset based on the governor
3345 for (size_t i
= 0; i
< nof_ts
; i
++) {
3346 Template
*t
= u
.templates
->get_t_byIndex(i
);
3347 switch (t
->templatetype
) {
3348 case PERMUTATION_MATCH
: {
3349 size_t nof_perm_ts
= t
->u
.templates
->get_nof_ts();
3350 for (size_t j
= 0; j
< nof_perm_ts
; j
++) {
3351 Int
ix(index_offset
+ index
+ j
);
3352 str
= t
->u
.templates
->get_t_byIndex(j
)
3353 ->generate_code_init_seof_element(str
, name
,
3354 Int2string(ix
).c_str(), oftype_name_str
);
3356 // do not consider index_offset in case of permutation indicators
3357 str
= mputprintf(str
, "%s.add_permutation(%lu, %lu);\n", name
,
3358 (unsigned long)index
, (unsigned long) (index
+ nof_perm_ts
- 1));
3359 t
->set_code_generated();
3360 index
+= nof_perm_ts
;
3364 str
= t
->generate_code_init_seof_element(str
, name
,
3365 Int2string(index_offset
+ index
).c_str(), oftype_name_str
);
3368 case TEMPLATE_NOTUSED
:
3373 case INDEXED_TEMPLATE_LIST
: {
3374 size_t nof_its
= u
.indexed_templates
->get_nof_its();
3376 Type
*t_last
= my_governor
->get_type_refd_last();
3377 const string
& oftype_name
=
3378 t_last
->get_ofType()->get_genname_template(my_scope
);
3379 const char *oftype_name_str
= oftype_name
.c_str();
3380 // There's no need to generate a set_size call here. To do that, we
3381 // should know the size of the base template, which is not available
3383 for (size_t i
= 0; i
< nof_its
; i
++) {
3384 IndexedTemplate
*it
= u
.indexed_templates
->get_it_byIndex(i
);
3385 const string
& tmp_id_1
= get_temporary_id();
3386 str
= mputstr(str
, "{\n");
3387 Value
*index
= (it
->get_index()).get_val();
3388 if (index
->get_valuetype() != Value::V_INT
) {
3389 const string
& tmp_id_2
= get_temporary_id();
3390 str
= mputprintf(str
, "int %s;\n", tmp_id_2
.c_str());
3391 str
= index
->generate_code_init(str
, tmp_id_2
.c_str());
3392 str
= mputprintf(str
, "%s& %s = %s[%s];\n", oftype_name_str
,
3393 tmp_id_1
.c_str(), name
, tmp_id_2
.c_str());
3395 str
= mputprintf(str
, "%s& %s = %s[%s];\n", oftype_name_str
,
3396 tmp_id_1
.c_str(), name
,
3397 Int2string(index
->get_val_Int()->get_val()).c_str());
3399 str
= it
->get_template()->generate_code_init(str
, tmp_id_1
.c_str());
3400 str
= mputstr(str
, "}\n");
3403 // It seems to be impossible in this case.
3404 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3408 FATAL_ERROR("Template::generate_code_init_seof()");
3414 char *Template::generate_code_init_seof_element(char *str
, const char *name
,
3415 const char* index
, const char *element_type_genname
)
3417 if (needs_temp_ref()) {
3418 const string
& tmp_id
= get_temporary_id();
3419 str
= mputprintf(str
, "{\n"
3420 "%s& %s = %s[%s];\n",
3421 element_type_genname
, tmp_id
.c_str(), name
, index
);
3422 str
= generate_code_init(str
, tmp_id
.c_str());
3423 str
= mputstr(str
, "}\n");
3425 char *embedded_name
= mprintf("%s[%s]", name
, index
);
3426 str
= generate_code_init(str
, embedded_name
);
3427 Free(embedded_name
);
3432 char *Template::generate_code_init_all_from(char *str
, const char *name
)
3434 // we are ALL_FROM, hence u.all_from
3435 switch (u
.all_from
->templatetype
) {
3436 case SPECIFIC_VALUE
: {
3437 Value
*spec
= u
.all_from
->u
.specific_value
;
3438 switch (spec
->get_valuetype()) {
3439 case Common::Value::V_REFD
: {
3440 Common::Reference
*ref
= spec
->get_reference();
3441 expression_struct expr
;
3442 Code::init_expr(&expr
);
3443 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3445 ref_pard
->generate_code_cached(&expr
);
3447 ref
->generate_code(&expr
);
3448 str
= mputprintf(str
, "%s = %s[i_i];\n", name
, expr
.expr
);
3449 // The caller will have to provide the for cycle with this variable
3450 Code::free_expr(&expr
);
3462 char *Template::generate_code_init_all_from_list(char *str
, const char *name
)
3464 // FIXME: this is the third instance
3465 expression_struct expr
;
3466 Code::init_expr(&expr
);
3467 switch (u
.all_from
->templatetype
) {
3468 case SPECIFIC_VALUE
: {
3469 Value
*spec
= u
.all_from
->u
.specific_value
;
3470 switch (spec
->get_valuetype()) {
3471 case Common::Value::V_REFD
: {
3472 Common::Reference
*ref
= spec
->get_reference();
3473 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3475 ref_pard
->generate_code_cached(&expr
);
3477 ref
->generate_code(&expr
);
3480 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3486 FATAL_ERROR("ttype %d", u
.all_from
->templatetype
);
3491 str
= mputstr(str
, expr
.preamble
);
3493 str
= mputprintf(str
,
3494 "%s.set_type(VALUE_LIST, %s.n_elem());\n"
3495 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3499 string
embedded_name(name
);
3500 embedded_name
+= ".list_item(i_i)";
3501 str
= generate_code_init_all_from(str
, embedded_name
.c_str());
3502 str
= mputstrn(str
, "}\n", 2);
3504 Code::free_expr(&expr
);
3508 char *Template::generate_code_init_se(char *str
, const char *name
)
3509 { // named template list
3510 size_t nof_nts
= u
.named_templates
->get_nof_nts();
3511 Type
*type
= my_governor
->get_type_refd_last();
3512 if (type
->get_nof_comps() > 0) {
3513 for (size_t i
= 0; i
< nof_nts
; i
++) {
3514 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
3515 const Identifier
& fieldname
= nt
->get_name();
3516 const char *fieldname_str
= 0;
3518 if (type
->get_typetype()==Type::T_ANYTYPE
) {
3519 at
+= fieldname
.get_name();
3520 fieldname_str
= at
.c_str();
3523 fieldname_str
= fieldname
.get_name().c_str();
3525 Template
*t
= nt
->get_template();
3526 if (t
->needs_temp_ref()) {
3528 if (type
->get_typetype() == Type::T_SIGNATURE
) {
3529 field_type
= type
->get_signature_parameters()
3530 ->get_param_byName(fieldname
)->get_type();
3532 field_type
= type
->get_comp_byName(fieldname
)->get_type();
3534 const string
& tmp_id
= get_temporary_id();
3535 const char *tmp_id_str
= tmp_id
.c_str();
3536 str
= mputprintf(str
, "{\n"
3537 "%s& %s = %s.%s();\n",
3538 field_type
->get_genname_template(my_scope
).c_str(), tmp_id_str
,
3539 name
, fieldname_str
);
3540 str
= t
->generate_code_init(str
, tmp_id_str
);
3541 str
= mputstr(str
, "}\n");
3543 char *embedded_name
= mprintf("%s.%s()", name
, fieldname_str
);
3544 str
= t
->generate_code_init(str
, embedded_name
);
3545 Free(embedded_name
);
3549 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3554 char *Template::generate_code_init_list(char *str
, const char *name
,
3555 bool is_complemented
) // VALUE_LIST or COMPLEMENTED_LIST
3557 size_t nof_ts
= u
.templates
->get_nof_ts();
3558 const string
& type_name
= my_governor
->get_genname_template(my_scope
);
3559 const char *type_name_str
= type_name
.c_str();
3561 dynamic_array
<int> variables
;
3562 size_t fixed_part
= 0;
3563 for (size_t i
= 0; i
< nof_ts
; ++i
) {
3564 Template
*t
= u
.templates
->get_t_byIndex(i
);
3565 if (t
->templatetype
== ALL_FROM
) {
3571 if (variables
.size() > 0) {
3572 char* str_preamble
= 0;
3573 char* str_set_type
= mputprintf(0, "%s.set_type(%s, %lu", name
,
3574 (is_complemented
? "COMPLEMENTED_LIST" : "VALUE_LIST"),
3575 (unsigned long)fixed_part
);
3576 // The code to compute the number of elements at run time (the variable part).
3577 // This is the sum of sizes of "all from"s.
3578 for (size_t v
= 0, vs
= variables
.size(); v
< vs
; ++v
) {
3579 Template
*vt
= u
.templates
->get_t_byIndex(variables
[v
]);
3580 if (vt
->templatetype
!= ALL_FROM
) FATAL_ERROR("must be ALL_FROM");
3581 if (vt
->u
.all_from
->templatetype
!= SPECIFIC_VALUE
) FATAL_ERROR("not value");
3582 Value
*val
= vt
->u
.all_from
->u
.specific_value
;
3583 if (val
->get_valuetype() != Value::V_REFD
) FATAL_ERROR("ref expected from val");
3584 Common::Reference
*ref
= val
->get_reference();
3585 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3586 Common::Assignment
*ass
= ref
->get_refd_assignment();
3587 if (!ass
) FATAL_ERROR("Could not grab ass!");
3589 str_set_type
= mputstrn(str_set_type
, " + ", 3);
3591 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3593 // in case of parametrised references:
3594 // - temporary parameters need to be declared (stored in str_preamble)
3595 // - the same temporary needs to be used at each call (generate_code_cached call)
3596 expression_struct expr
;
3597 Code::init_expr(&expr
);
3599 ref_pard
->generate_code_cached(&expr
);
3600 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
3602 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3604 Code::free_expr(&expr
);
3607 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
3609 expression_struct expr
;
3610 Code::init_expr(&expr
);
3612 subrefs
->generate_code(&expr
, ass
);
3613 str_set_type
= mputprintf(str
, "%s", expr
.expr
);
3615 Code::free_expr(&expr
);
3618 str_set_type
= mputstr(str_set_type
, ".n_elem()");
3621 str
= mputstr(str
, str_preamble
);
3622 str
= mputstr(str
, str_set_type
);
3627 str
= mputstrn(str
, ");\n", 3);
3629 string shifty
; // contains the expression used to calculate
3630 // the size increase due to the runtime expansion of "all from".
3631 // In nof_ts, each "all from" appears as 1, but actually contributes
3632 // more. So the increase (by which all elements after the "all from"
3633 // are shifted) is:Â target_of_all_from.n_elem()-1
3634 // This needs to be accumulated for each "all from".
3635 for (size_t vi
= 0; vi
< nof_ts
; ++vi
) {
3636 Template
*t
= u
.templates
->get_t_byIndex(vi
);
3637 switch (t
->templatetype
) {
3638 case VALUE_LIST_ALL_FROM
:
3639 FATAL_ERROR("VALUE_LIST_ALL_FROM not handled");
3641 expression_struct expr
;
3642 Code::init_expr(&expr
);
3644 switch (t
->u
.all_from
->templatetype
) {
3645 case SPECIFIC_VALUE
: {
3646 Value
*sv
= t
->u
.all_from
->u
.specific_value
;
3647 switch (sv
->get_valuetype()) {
3648 case Value::V_REFD
: {
3649 Common::Reference
*ref
= sv
->get_reference();
3650 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3652 ref_pard
->generate_code_cached(&expr
);
3654 ref
->generate_code(&expr
);
3658 FATAL_ERROR("VT NOT HANDLED");
3659 } // switch valuetype
3663 FATAL_ERROR("ttype not handled");
3667 // All local variables should contain a single underscore,
3668 // to avoid potential clashes with field names.
3669 str
= mputprintf(str
, "for (int i_i= 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3672 if (t
->needs_temp_ref()) {
3673 // Not possible, because t->templatetype is ALL_FROM
3674 FATAL_ERROR("temp ref not handled");
3676 char *embedded_name
= mprintf("%s.list_item(%lu + i_i%s)", name
,
3677 (unsigned long) vi
, shifty
.c_str());
3678 str
= t
->generate_code_init(str
, embedded_name
);
3679 Free(embedded_name
);
3681 str
= mputstrn(str
, "}\n", 2);
3684 shifty
+= expr
.expr
;
3685 shifty
+= ".n_elem() /* 3303 */ ";
3687 Code::free_expr(&expr
);
3690 default: // "fixed one"
3691 if (t
->needs_temp_ref()) { // FIXME: this is copypasta from below / but may need to be changed
3692 const string
& tmp_id
= get_temporary_id();
3693 const char *tmp_id_str
= tmp_id
.c_str();
3694 str
= mputprintf(str
, "{\n"
3695 "%s& %s = %s.list_item(%lu);\n",
3696 type_name_str
, tmp_id_str
, name
, (unsigned long) vi
);
3697 str
= t
->generate_code_init(str
, tmp_id_str
);
3698 str
= mputstr(str
, "}\n");
3700 char *embedded_name
= mprintf("%s.list_item(%lu%s)", name
,
3701 (unsigned long) vi
, shifty
.c_str());
3702 str
= t
->generate_code_init(str
, embedded_name
);
3703 Free(embedded_name
);
3706 } // switch t->templatetype
3710 str
= mputprintf(str
, "%s.set_type(%s, %lu);\n", name
,
3711 is_complemented
? "COMPLEMENTED_LIST" : "VALUE_LIST",
3712 (unsigned long) nof_ts
);
3713 for (size_t i
= 0; i
< nof_ts
; i
++) {
3714 Template
*t
= u
.templates
->get_t_byIndex(i
);
3715 if (t
->needs_temp_ref()) {
3716 const string
& tmp_id
= get_temporary_id();
3717 const char *tmp_id_str
= tmp_id
.c_str();
3718 str
= mputprintf(str
, "{\n"
3719 "%s& %s = %s.list_item(%lu);\n",
3720 type_name_str
, tmp_id_str
, name
, (unsigned long) i
);
3721 str
= t
->generate_code_init(str
, tmp_id_str
);
3722 str
= mputstr(str
, "}\n");
3724 char *embedded_name
= mprintf("%s.list_item(%lu)", name
,
3726 str
= t
->generate_code_init(str
, embedded_name
);
3727 Free(embedded_name
);
3734 char *Template::generate_code_init_set(char *str
, const char *name
,
3735 bool is_superset
) // SUPERSET_MATCH and SUBSET_MATCH
3737 size_t nof_ts
= u
.templates
->get_nof_ts();
3738 const string
& oftype_name
=
3739 my_governor
->get_ofType()->get_genname_template(my_scope
);
3740 const char *oftype_name_str
= oftype_name
.c_str();
3742 dynamic_array
<int> variables
;
3743 size_t fixed_part
= 0;
3744 for (size_t i
= 0; i
< nof_ts
; ++i
) {
3745 Template
*t
= u
.templates
->get_t_byIndex(i
);
3746 if (t
->templatetype
== ALL_FROM
) {
3752 //warning("There are %lu set elements", nof_ts);
3753 if (variables
.size() > 0) {
3754 char* str_preamble
= 0;
3755 char* str_set_type
= mputprintf(0, "%s.set_type(%s, %lu", name
,
3756 is_superset
? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) fixed_part
);
3758 for (size_t v
= 0, vs
= variables
.size(); v
< vs
; ++v
) {
3759 Template
*vt
= u
.templates
->get_t_byIndex(variables
[v
]);
3760 if (vt
->templatetype
!= ALL_FROM
) FATAL_ERROR("must be ALL_FROM");
3761 if (vt
->u
.all_from
->templatetype
!= SPECIFIC_VALUE
) FATAL_ERROR("not value");
3762 Value
*val
= vt
->u
.all_from
->u
.specific_value
;
3763 if (val
->get_valuetype() != Value::V_REFD
) FATAL_ERROR("ref expected from val");
3764 Common::Reference
*ref
= val
->get_reference();
3765 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
3766 Common::Assignment
*ass
= ref
->get_refd_assignment();
3767 if (!ass
) FATAL_ERROR("Could not grab ass!");
3769 str_set_type
= mputstrn(str_set_type
, " + ", 3);
3771 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3773 // in case of parametrised references:
3774 // - temporary parameters need to be declared (stored in str_preamble)
3775 // - the same temporary needs to be used at each call (generate_code_cached call)
3776 expression_struct expr
;
3777 Code::init_expr(&expr
);
3779 ref_pard
->generate_code_cached(&expr
);
3780 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
3782 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3784 Code::free_expr(&expr
);
3787 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
3789 expression_struct expr
;
3790 Code::init_expr(&expr
);
3792 subrefs
->generate_code(&expr
, ass
);
3793 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
3795 Code::free_expr(&expr
);
3798 str_set_type
= mputstr(str_set_type
, ".n_elem()");
3801 str
= mputstr(str
, str_preamble
);
3802 str
= mputstr(str
, str_set_type
);
3807 str
= mputstrn(str
, ");\n", 3);
3810 for (size_t i
= 0; i
< nof_ts
; i
++) {
3811 Template
*t
= u
.templates
->get_t_byIndex(i
);
3812 switch (t
->templatetype
) {
3814 expression_struct expr
; // FIXME copypasta from init_list above !
3815 Code::init_expr(&expr
);
3817 switch (t
->u
.all_from
->templatetype
) {
3818 case SPECIFIC_VALUE
: {
3819 Value
*sv
= t
->u
.all_from
->u
.specific_value
;
3820 switch (sv
->get_valuetype()) {
3821 case Value::V_REFD
: {
3822 Common::Reference
*ref
= sv
->get_reference();
3823 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3825 ref_pard
->generate_code_cached(&expr
);
3827 ref
->generate_code(&expr
);
3831 FATAL_ERROR("VT NOT HANDLED");
3832 } // switch valuetype
3836 FATAL_ERROR("ttype not handled");
3840 str
= mputprintf(str
,
3841 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3845 char *embedded_name
= mprintf("%s.set_item(%lu%s + i_i)", name
,
3846 (unsigned long) i
, shifty
.c_str());
3847 str
= t
->generate_code_init_all_from(str
, embedded_name
);
3848 Free(embedded_name
);
3850 str
= mputstrn(str
, "}\n", 2);
3853 shifty
+= expr
.expr
;
3854 shifty
+= ".n_elem() /* 3442 */";
3855 Code::free_expr(&expr
);
3857 case VALUE_LIST_ALL_FROM
:
3858 FATAL_ERROR("Not possible");
3859 break; // not reached
3862 if (t
->needs_temp_ref()) {
3863 const string
& tmp_id
= get_temporary_id();
3864 const char *tmp_id_str
= tmp_id
.c_str();
3865 str
= mputprintf(str
, "{\n"
3866 "%s& %s = %s.set_item(%lu%s);\n",
3867 oftype_name_str
, tmp_id_str
, name
, (unsigned long) i
, shifty
.c_str());
3868 str
= t
->generate_code_init(str
, tmp_id_str
);
3869 str
= mputstr(str
, "}\n");
3871 char *embedded_name
= mprintf("%s.set_item(%lu%s)", name
,
3872 (unsigned long) i
, shifty
.c_str());
3873 str
= t
->generate_code_init(str
, embedded_name
);
3874 Free(embedded_name
);
3877 } // switch t->templatetype
3882 str
= mputprintf(str
, "%s.set_type(%s, %lu);\n", name
,
3883 is_superset
? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) nof_ts
);
3884 for (size_t i
= 0; i
< nof_ts
; i
++) {
3885 Template
*t
= u
.templates
->get_t_byIndex(i
);
3886 if (t
->needs_temp_ref()) {
3887 const string
& tmp_id
= get_temporary_id();
3888 const char *tmp_id_str
= tmp_id
.c_str();
3889 str
= mputprintf(str
, "{\n"
3890 "%s& %s = %s.set_item(%lu);\n",
3891 oftype_name_str
, tmp_id_str
, name
, (unsigned long) i
);
3892 str
= t
->generate_code_init(str
, tmp_id_str
);
3893 str
= mputstr(str
, "}\n");
3895 char *embedded_name
= mprintf("%s.set_item(%lu)", name
,
3897 str
= t
->generate_code_init(str
, embedded_name
);
3898 Free(embedded_name
);
3905 void Template::generate_code_expr_invoke(expression_struct
*expr
)
3907 Value
*last_v
= u
.invoke
.v
->get_value_refd_last();
3908 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
3909 Common::Assignment
*function
= last_v
->get_refd_fat();
3910 expr
->expr
= mputprintf(expr
->expr
, "%s(",
3911 function
->get_genname_from_scope(my_scope
).c_str());
3912 u
.invoke
.ap_list
->generate_code_alias(expr
,
3913 function
->get_FormalParList(), function
->get_RunsOnType(), false);
3915 u
.invoke
.v
->generate_code_expr_mandatory(expr
);
3916 expr
->expr
= mputstr(expr
->expr
, ".invoke(");
3917 Type
* gov_last
= u
.invoke
.v
->get_expr_governor_last();
3918 u
.invoke
.ap_list
->generate_code_alias(expr
, 0,
3919 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
3921 expr
->expr
= mputc(expr
->expr
, ')');
3924 char *Template::rearrange_init_code_refd(char *str
)
3926 if (templatetype
!= TEMPLATE_REFD
)
3927 FATAL_ERROR("Template::rearrange_init_code_refd()");
3928 ActualParList
*parlist
= u
.ref
.ref
->get_parlist();
3929 // generate code for the templates that are used in the actual parameter
3930 // list of the reference
3931 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
3932 bool rearrange
= (ass
->get_my_scope()->get_scope_mod_gen() ==
3933 my_scope
->get_scope_mod_gen());
3934 if (parlist
) str
= parlist
->rearrange_init_code(str
, rearrange
);
3935 // do nothing if the reference does not point to a template definition
3936 if (ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) return str
;
3937 // do nothing if the referenced template is in another module
3938 if (ass
->get_my_scope()->get_scope_mod_gen() !=
3939 my_scope
->get_scope_mod_gen()) return str
;
3940 Template
*t
= ass
->get_Template();
3942 // the reference points to a parameterized template
3943 // we must perform the rearrangement for all non-parameterized templates
3944 // that are referred by the parameterized template regardless the
3945 // sub-references of u.ref.ref
3946 str
= t
->rearrange_init_code(str
);
3948 // the reference points to a non-parameterized template
3949 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
3951 // we should follow the sub-references as much as we can
3952 // and perform the rearrangement for the referred field only
3953 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); i
++) {
3954 FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
3955 if (ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
3956 // stop if the body does not have fields
3957 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
3958 // get the sub-template of the referred field
3959 t
= t
->u
.named_templates
->get_nt_byName(*ref
->get_id())
3962 // stop if the body is not a list
3963 if (t
->templatetype
!= TEMPLATE_LIST
) break;
3964 Value
*array_index
= ref
->get_val()->get_value_refd_last();
3965 // stop if the index cannot be evaluated at compile time
3966 if (array_index
->get_valuetype() != Value::V_INT
) break;
3967 Int index
= array_index
->get_val_Int()->get_val();
3968 // index transformation in case of arrays
3969 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
3970 index
-= t
->my_governor
->get_dimension()->get_offset();
3971 // get the template with the given index
3972 t
= t
->get_listitem_byIndex(index
);
3976 // otherwise if the reference points to a top-level template
3977 // we should initialize its entire body
3978 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
3983 char *Template::rearrange_init_code_invoke(char *str
)
3985 str
= u
.invoke
.v
->rearrange_init_code(str
);
3986 bool type_is_local
= u
.invoke
.v
->get_expr_governor_last()->get_my_scope()
3987 ->get_scope_mod_gen() == my_scope
->get_scope_mod_gen();
3988 str
= u
.invoke
.ap_list
->rearrange_init_code(str
, type_is_local
);
3992 bool Template::needs_temp_ref()
3994 if (length_restriction
|| is_ifpresent
) return true;
3995 switch (templatetype
) {
3999 case SPECIFIC_VALUE
:
4001 case TEMPLATE_INVOKE
:
4009 // temporary reference is needed if the template has at least one
4010 // element (excluding not used symbols)
4011 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
4012 if (u
.templates
->get_t_byIndex(i
)->templatetype
!= TEMPLATE_NOTUSED
)
4016 case INDEXED_TEMPLATE_LIST
:
4017 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
4018 if (u
.indexed_templates
->get_it_byIndex(i
)->get_template()
4019 ->templatetype
!= TEMPLATE_NOTUSED
)
4023 case NAMED_TEMPLATE_LIST
:
4024 return u
.named_templates
->get_nof_nts() > 1;
4026 case VALUE_LIST_ALL_FROM
:
4029 case COMPLEMENTED_LIST
:
4031 case SUPERSET_MATCH
:
4034 case TEMPLATE_ERROR
:
4035 case TEMPLATE_NOTUSED
:
4036 FATAL_ERROR("Template::needs_temp_ref()");
4037 case PERMUTATION_MATCH
:
4044 bool Template::has_single_expr()
4046 if (length_restriction
|| is_ifpresent
|| get_needs_conversion())
4048 switch (templatetype
) {
4058 case SPECIFIC_VALUE
:
4059 return u
.specific_value
->has_single_expr();
4060 case TEMPLATE_REFD
: {
4061 Template
*t_last
= get_template_refd_last();
4062 if (t_last
!= this && t_last
->has_single_expr()) {
4063 for (Scope
*t_scope
= my_scope
; t_scope
;
4064 t_scope
= t_scope
->get_parent_scope()) {
4065 // return true if t_last is visible from my scope
4066 if (t_scope
== t_last
->my_scope
) return true;
4069 // otherwise consider the reference itself
4070 return u
.ref
.ref
->has_single_expr(); }
4071 case TEMPLATE_INVOKE
:
4072 if (!u
.invoke
.v
->has_single_expr()) return false;
4073 for (size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++)
4074 if (!u
.invoke
.ap_list
->get_par(i
)->has_single_expr()) return false;
4077 return u
.templates
->get_nof_ts() == 0;
4078 case NAMED_TEMPLATE_LIST
: {
4079 if (!my_governor
) FATAL_ERROR("Template::has_single_expr()");
4080 Type
*type
= my_governor
->get_type_refd_last();
4081 return type
->get_nof_comps() == 0; }
4082 case INDEXED_TEMPLATE_LIST
:
4083 return u
.indexed_templates
->get_nof_its() == 0;
4085 case COMPLEMENTED_LIST
:
4087 case SUPERSET_MATCH
:
4089 case PERMUTATION_MATCH
:
4092 case VALUE_LIST_ALL_FROM
:
4095 FATAL_ERROR("Template::has_single_expr()");
4100 string
Template::get_single_expr(bool cast_needed
)
4102 if (cast_needed
&& (length_restriction
|| is_ifpresent
))
4103 FATAL_ERROR("Template::get_single_expr()");
4105 switch (templatetype
) {
4107 ret_val
= "OMIT_VALUE";
4110 ret_val
= "ANY_VALUE";
4113 ret_val
= "ANY_OR_OMIT";
4115 case SPECIFIC_VALUE
:
4116 ret_val
= u
.specific_value
->get_single_expr();
4118 case TEMPLATE_REFD
: {
4119 // convert the reference to a single expression
4120 expression_struct expr
;
4121 Code::init_expr(&expr
);
4122 u
.ref
.ref
->generate_code(&expr
);
4123 if (expr
.preamble
|| expr
.postamble
)
4124 FATAL_ERROR("Template::get_single_expr()");
4125 ret_val
= expr
.expr
;
4126 Code::free_expr(&expr
);
4129 case TEMPLATE_INVOKE
: {
4130 expression_struct expr
;
4131 Code::init_expr(&expr
);
4132 generate_code_expr_invoke(&expr
);
4133 if (expr
.preamble
|| expr
.postamble
)
4134 FATAL_ERROR("Template::get_single_expr()");
4135 ret_val
= expr
.expr
;
4136 Code::free_expr(&expr
);
4139 if (u
.templates
->get_nof_ts() != 0)
4140 FATAL_ERROR("Template::get_single_expr()");
4141 ret_val
= "NULL_VALUE";
4143 case NAMED_TEMPLATE_LIST
:
4144 if (u
.named_templates
->get_nof_nts() != 0)
4145 FATAL_ERROR("Template::get_single_expr()");
4146 ret_val
= "NULL_VALUE";
4148 case INDEXED_TEMPLATE_LIST
:
4149 if (u
.indexed_templates
->get_nof_its() != 0)
4150 FATAL_ERROR("Template::get_single_expr()");
4151 ret_val
= "NULL_VALUE";
4154 return get_my_scope()->get_scope_mod_gen()
4155 ->add_bitstring_pattern(*u
.pattern
);
4157 return get_my_scope()->get_scope_mod_gen()
4158 ->add_hexstring_pattern(*u
.pattern
);
4160 return get_my_scope()->get_scope_mod_gen()
4161 ->add_octetstring_pattern(*u
.pattern
);
4165 ->create_charstring_literals(get_my_scope()->get_scope_mod_gen());
4167 FATAL_ERROR("Template::get_single_expr()");
4169 if (cast_needed
) ret_val
= my_governor
->get_genname_template(my_scope
) +
4170 "(" + ret_val
+ ")";
4174 void Template::dump(unsigned level
) const
4176 DEBUG(level
, "%s", get_templatetype_str());
4177 switch (templatetype
) {
4178 case TEMPLATE_ERROR
:
4183 case SPECIFIC_VALUE
:
4184 u
.specific_value
->dump(level
+1);
4187 u
.ref
.ref
->dump(level
+1);
4189 case TEMPLATE_INVOKE
:
4190 u
.invoke
.v
->dump(level
+1);
4191 if (u
.invoke
.ap_list
) u
.invoke
.ap_list
->dump(level
+ 1);
4192 else if (u
.invoke
.t_list
) u
.invoke
.t_list
->dump(level
+ 1);
4196 case COMPLEMENTED_LIST
:
4197 case SUPERSET_MATCH
:
4199 case PERMUTATION_MATCH
:
4200 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
4201 u
.templates
->get_t_byIndex(i
)->dump(level
+1);
4203 case NAMED_TEMPLATE_LIST
:
4204 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
4205 u
.named_templates
->get_nt_byIndex(i
)->dump(level
+1);
4207 case INDEXED_TEMPLATE_LIST
:
4208 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
4209 u
.indexed_templates
->get_it_byIndex(i
)->dump(level
+1);
4212 u
.value_range
->dump(level
);
4217 DEBUG(level
+1, "%s", u
.pattern
->c_str());
4221 u
.pstring
->dump(level
+1);
4224 case VALUE_LIST_ALL_FROM
:
4225 u
.all_from
->dump(level
+1);
4230 if (length_restriction
) length_restriction
->dump(level
+ 1);
4233 bool Template::has_allfrom() const
4234 { // the code generation of all from is not fully implemented. This helps avoid of using it.
4235 if (templatetype
!= TEMPLATE_LIST
) FATAL_ERROR("has_allfrom(): Templatetype shall be TEMPLATE_LIST");
4236 size_t nof_ts
= u
.templates
->get_nof_ts();
4237 for (size_t i
= 0; i
< nof_ts
; i
++) {
4238 if (u
.templates
->get_t_byIndex(i
)->templatetype
== ALL_FROM
) {
4245 // =================================
4246 // ===== TemplateInstance
4247 // =================================
4249 TemplateInstance::TemplateInstance(const TemplateInstance
& p
)
4250 : Node(p
), Location(p
)
4252 type
= p
.type
? p
.type
->clone() : 0;
4253 derived_reference
= p
.derived_reference
? p
.derived_reference
->clone() : 0;
4254 template_body
= p
.template_body
->clone();
4257 TemplateInstance::TemplateInstance(Type
*p_type
, Ref_base
*p_ref
,
4258 Template
*p_body
) : Node(), Location(), type(p_type
),
4259 derived_reference(p_ref
), template_body(p_body
)
4261 if (!p_body
) FATAL_ERROR("TemplateInstance::TemplateInstance()");
4262 if (type
) type
->set_ownertype(Type::OT_TEMPLATE_INST
, this);
4265 TemplateInstance::~TemplateInstance()
4268 delete derived_reference
;
4269 delete template_body
;
4272 void TemplateInstance::release()
4275 derived_reference
= 0;
4279 TemplateInstance
*TemplateInstance::clone() const
4281 return new TemplateInstance(*this);
4284 void TemplateInstance::set_fullname(const string
& p_fullname
)
4286 Node::set_fullname(p_fullname
);
4287 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
4288 if (derived_reference
)
4289 derived_reference
->set_fullname(p_fullname
+ ".<derived_reference>");
4290 template_body
->set_fullname(p_fullname
);
4293 void TemplateInstance::set_my_scope(Scope
*p_scope
)
4295 if (type
) type
->set_my_scope(p_scope
);
4296 if (derived_reference
) derived_reference
->set_my_scope(p_scope
);
4297 template_body
->set_my_scope(p_scope
);
4300 Type::typetype_t
TemplateInstance::get_expr_returntype
4301 (Type::expected_value_t exp_val
)
4303 Type
*t
= get_expr_governor(exp_val
);
4304 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
4305 else return template_body
->get_expr_returntype(exp_val
);
4308 Type
*TemplateInstance::get_expr_governor(Type::expected_value_t exp_val
)
4310 if (type
) return type
;
4311 if (derived_reference
) {
4312 Type
*ret_val
= chk_DerivedRef(0);
4313 if (ret_val
) return ret_val
;
4315 return template_body
->get_expr_governor(exp_val
);
4318 void TemplateInstance::chk(Type
*governor
)
4320 if (!governor
) FATAL_ERROR("TemplateInstance::chk()");
4321 governor
= chk_Type(governor
);
4322 governor
= chk_DerivedRef(governor
);
4323 template_body
->set_my_governor(governor
);
4324 governor
->chk_this_template_ref(template_body
);
4325 governor
->chk_this_template_generic(template_body
,
4326 (derived_reference
!= 0 ? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
4327 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
4330 Type
*TemplateInstance::chk_Type(Type
*governor
)
4332 if (!type
) return governor
;
4334 Error_Context
cntxt(type
, "In explicit type specification");
4337 TypeCompatInfo
info(template_body
->get_template_refd_last()
4338 ->get_my_scope()->get_scope_mod(), governor
, type
,
4342 if (!governor
) return type
;
4343 else if (governor
->is_compatible(type
, &info
, &l_chain
, &r_chain
)) {
4346 if (info
.is_subtype_error()) {
4347 type
->error("%s", info
.get_subtype_error().c_str());
4349 if (!info
.is_erroneous()) {
4350 type
->error("Incompatible explicit type specification: `%s' was "
4351 "expected instead of `%s'",
4352 governor
->get_typename().c_str(),
4353 type
->get_typename().c_str());
4355 type
->error("%s", info
.get_error_str_str().c_str());
4361 Type
*TemplateInstance::chk_DerivedRef(Type
*governor
)
4363 if (!derived_reference
) return governor
;
4364 Error_Context
cntxt(derived_reference
, "In derived reference");
4365 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4366 // the base template reference must not have sub-references
4367 if (derived_reference
->get_subrefs())
4368 FATAL_ERROR("TemplateInstance::chk_DerivedRef()");
4369 bool set_bt
= false;
4370 if (!ass
) goto error
;
4371 switch (ass
->get_asstype()) {
4372 case Common::Assignment::A_TEMPLATE
:
4375 case Common::Assignment::A_MODULEPAR_TEMP
:
4376 case Common::Assignment::A_VAR_TEMPLATE
:
4377 case Common::Assignment::A_PAR_TEMPL_IN
:
4378 case Common::Assignment::A_PAR_TEMPL_OUT
:
4379 case Common::Assignment::A_PAR_TEMPL_INOUT
:
4380 case Common::Assignment::A_FUNCTION_RTEMP
:
4381 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: {
4382 if (!governor
) governor
= type
;
4383 Type
*base_template_type
= ass
->get_Type();
4385 TypeCompatInfo
info(template_body
->get_template_refd_last()
4386 ->get_my_scope()->get_scope_mod(), governor
, type
,
4390 if (!governor
->is_compatible(base_template_type
, &info
, &l_chain
,
4392 if (info
.is_subtype_error()) {
4393 derived_reference
->error("%s", info
.get_subtype_error().c_str());
4395 if (!info
.is_erroneous()) {
4396 derived_reference
->error("Base template `%s' has incompatible "
4397 "type: `%s' was expected instead of `%s'",
4398 ass
->get_fullname().c_str(),
4399 governor
->get_typename().c_str(),
4400 base_template_type
->get_typename().c_str());
4402 derived_reference
->error("%s", info
.get_error_str_str().c_str());
4404 // if explicit type specification is omitted
4405 // check the template body against the type of the base template
4406 if (!type
) governor
= base_template_type
;
4409 if (info
.needs_conversion())
4410 template_body
->set_needs_conversion();
4412 } else governor
= base_template_type
;
4415 derived_reference
->error("Reference to a template was expected instead "
4416 "of %s", ass
->get_description().c_str());
4419 if (set_bt
) template_body
->set_base_template(ass
->get_Template());
4422 // drop the erroneous derived_reference to avoid further errors
4423 delete derived_reference
;
4424 derived_reference
= 0;
4428 void TemplateInstance::chk_recursions(ReferenceChain
& refch
)
4430 template_body
->chk_recursions(refch
);
4433 bool TemplateInstance::is_string_type(Type::expected_value_t exp_val
)
4435 switch (get_expr_returntype(exp_val
)) {
4447 bool TemplateInstance::chk_restriction(const char* definition_name
,
4448 template_restriction_t template_restriction
)
4450 bool needs_runtime_check
= false;
4451 if (derived_reference
) // if modified
4453 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4454 switch (ass
->get_asstype()) {
4455 case Common::Assignment::A_TEMPLATE
:
4456 // already added to template_body as base template by chk_DerivedRef()
4457 needs_runtime_check
= template_body
->chk_restriction(
4458 definition_name
, template_restriction
);
4460 case Common::Assignment::A_MODULEPAR_TEMP
:
4461 case Common::Assignment::A_VAR_TEMPLATE
:
4462 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
4463 case Common::Assignment::A_FUNCTION_RTEMP
:
4464 case Common::Assignment::A_PAR_TEMPL_IN
:
4465 case Common::Assignment::A_PAR_TEMPL_OUT
:
4466 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
4467 // create a temporary Template to be added as the base template and
4468 // check, remove and delete after checked
4469 if (template_body
->get_base_template())
4470 FATAL_ERROR("TemplateInstance::chk_restriction()");
4471 template_body
->set_base_template(new Template(derived_reference
));
4472 needs_runtime_check
= template_body
->chk_restriction(
4473 definition_name
, template_restriction
);
4474 delete template_body
->get_base_template();
4475 template_body
->set_base_template(0);
4481 needs_runtime_check
= template_body
->chk_restriction(definition_name
,
4482 template_restriction
);
4484 return needs_runtime_check
;
4487 bool TemplateInstance::has_single_expr()
4489 if (derived_reference
) return false;
4490 else if (type
) return false;
4491 else return template_body
->has_single_expr();
4494 void TemplateInstance::set_code_section(
4495 GovernedSimple::code_section_t p_code_section
)
4497 if (derived_reference
) derived_reference
->set_code_section(p_code_section
);
4498 template_body
->set_code_section(p_code_section
);
4501 bool TemplateInstance::needs_temp_ref()
4503 if (template_body
->get_templatetype() != Template::SPECIFIC_VALUE
)
4505 Value
*val
= template_body
->get_specific_value();
4506 if (val
->get_valuetype() == Value::V_REFD
) {
4507 FieldOrArrayRefs
*refs
= val
->get_reference()->get_subrefs();
4508 if (!refs
) return false;
4509 // We need at least a 2-long reference chain. E.g. "a[0].b". 3.0.4
4510 // can't handle a normal reference following an indexed reference. The
4511 // indexed reference must be on the first place. Code like: "a.b[0].c"
4513 if (refs
->get_nof_refs() < 2
4514 || refs
->get_ref(0)->get_type() != FieldOrArrayRef::ARRAY_REF
)
4522 void TemplateInstance::generate_code(expression_struct
*expr
,
4523 template_restriction_t template_restriction
)
4525 if (derived_reference
) {
4526 // preserve the target expression
4527 char *expr_backup
= expr
->expr
;
4528 // reset the space for the target expression
4530 derived_reference
->generate_code(expr
);
4531 // now the C++ equivalent of the base template reference is in expr->expr
4532 const string
& tmp_id
= template_body
->get_temporary_id();
4533 const char *tmp_id_str
= tmp_id
.c_str();
4534 // create a temporary variable and copy the contents of base template
4536 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s(%s);\n",
4537 template_body
->get_my_governor()->get_genname_template(
4538 template_body
->get_my_scope()).c_str(), tmp_id_str
, expr
->expr
);
4539 // perform the modifications on the temporary variable
4540 expr
->preamble
= template_body
->generate_code_init(expr
->preamble
,
4542 // runtime template restriction check
4543 if (template_restriction
!=TR_NONE
)
4544 expr
->preamble
= Template::generate_restriction_check_code(
4545 expr
->preamble
, tmp_id_str
, template_restriction
);
4546 // the base template reference is no longer needed
4548 // restore the target expression append the name of the temporary
4550 expr
->expr
= mputstr(expr_backup
, tmp_id_str
);
4551 } else template_body
->generate_code_expr(expr
, template_restriction
);
4554 char *TemplateInstance::rearrange_init_code(char *str
)
4556 if (derived_reference
) {
4557 ActualParList
*parlist
= derived_reference
->get_parlist();
4558 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
4559 if (!ass
) FATAL_ERROR("TemplateInstance::rearrange_init_code()");
4560 bool is_local
= (ass
->get_my_scope()->get_scope_mod_gen() ==
4561 derived_reference
->get_my_scope()->get_scope_mod_gen());
4562 if (parlist
) str
= parlist
->rearrange_init_code(str
, is_local
);
4563 if (is_local
&& ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
4564 // the base template reference refers to a template within the local
4566 Template
*t
= ass
->get_Template();
4568 // the referred template is parameterized
4569 // the embedded referenced templates shall be visited
4570 str
= t
->rearrange_init_code(str
);
4572 // the referred template is not parameterized
4573 // its entire body has to be initialized now
4574 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
4578 str
= template_body
->rearrange_init_code(str
);
4582 void TemplateInstance::append_stringRepr(string
& str
) const
4585 str
+= type
->get_typename();
4588 if (derived_reference
) {
4590 str
+= derived_reference
->get_dispname();
4593 str
+= template_body
->get_stringRepr();
4596 void TemplateInstance::dump(unsigned level
) const
4599 DEBUG(level
, "type:");
4600 type
->dump(level
+ 1);
4602 if (derived_reference
) {
4603 DEBUG(level
, "modifies:");
4604 derived_reference
->dump(level
+ 1);
4606 template_body
->dump(level
);
4609 Value
* TemplateInstance::get_specific_value() const
4611 if (type
) return NULL
;
4612 if (derived_reference
) return NULL
;
4613 if (template_body
->is_length_restricted() || template_body
->get_ifpresent())
4615 if (template_body
->get_templatetype()!=Template::SPECIFIC_VALUE
) return NULL
;
4616 return template_body
->get_specific_value();
4619 Def_Template
* TemplateInstance::get_Referenced_Base_Template()
4620 { // it may return 0
4621 if (!get_Template()) return NULL
;
4622 Ttcn::Template::templatetype_t tpt
= get_Template()->get_templatetype();
4623 if (Ttcn::Template::TEMPLATE_REFD
!= tpt
) return NULL
;
4624 Ttcn::Ref_base
* refbase
= get_Template()->get_reference();
4625 Ttcn::Reference
* ref
= dynamic_cast<Ttcn::Reference
*>(refbase
);
4626 if (!ref
) return NULL
;
4627 Common::Assignment
* ass
= ref
->get_refd_assignment();
4628 Ttcn::Definition
* def
= dynamic_cast<Ttcn::Definition
*>(ass
);
4629 if (!def
) return NULL
;
4630 Ttcn::Def_Template
* deftemp
= dynamic_cast<Ttcn::Def_Template
*>(def
);
4631 if (!deftemp
) return NULL
;