Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Balasko, Jeno | |
10 | * Raduly, Csaba | |
11 | * | |
12 | ******************************************************************************/ | |
970ed795 EL |
13 | #ifndef TYPECOMPAT_HH_ |
14 | #define TYPECOMPAT_HH_ | |
15 | ||
16 | #include "string.hh" | |
17 | #include "stack.hh" | |
18 | #include "vector.hh" | |
19 | ||
20 | struct expression_struct_t; | |
21 | ||
22 | namespace Ttcn { | |
23 | class TemplateInstance; | |
24 | } | |
25 | ||
26 | namespace Common { | |
27 | class Module; | |
28 | class Type; | |
29 | class GovernedSimple; | |
30 | class Reference; | |
31 | ||
32 | /** Compatibility information for error reporting during semantic checks and | |
33 | * some helpers for code generation. Used during semantic checks only. */ | |
34 | class TypeCompatInfo { | |
35 | private: | |
36 | Module *m_my_module; | |
37 | Type *m_type1; /**< Type of the LHS. Not owned. */ | |
38 | Type *m_type2; /**< Type of the RHS. Not owned. */ | |
39 | bool m_strict; /**< Type compatibility means equivalence. */ | |
40 | bool m_is_temp; /**< Compatibility between templates. */ | |
41 | bool m_needs_conversion; /**< Need for conversion code generation. */ | |
42 | bool m_erroneous; /**< Set if type conversion is not possible. */ | |
43 | string m_error_str; /**< Additional information. */ | |
44 | string m_ref_str1; /**< Reference chain for the LHS. */ | |
45 | string m_ref_str2; /**< Reference chain for the RHS. */ | |
46 | string subtype_error_str; /**< Subtype error string */ | |
47 | bool str1_elem; /**< LHS is a reference to a string element */ | |
48 | bool str2_elem; /**< RHS is a reference to a string element */ | |
49 | /// Copy constructor disabled | |
50 | TypeCompatInfo(const TypeCompatInfo&); | |
51 | /// Assignment disabled | |
52 | TypeCompatInfo& operator=(const TypeCompatInfo&); | |
53 | public: | |
54 | TypeCompatInfo(Module *p_my_module, Type *p_type1 = NULL, | |
55 | Type *p_type2 = NULL, bool p_add_ref_str = true, | |
56 | bool p_strict = true, bool p_is_temp = false); | |
57 | inline bool needs_conversion() const { return m_needs_conversion; } | |
58 | inline void set_needs_conversion(bool p_needs_conversion) | |
59 | { m_needs_conversion = p_needs_conversion; } | |
60 | void add_type_conversion(Type *p_from_type, Type *p_to_type); | |
61 | void append_ref_str(int p_ref_no, const string& p_ref); | |
62 | inline const string& get_ref_str(int p_ref_no) | |
63 | { return p_ref_no == 0 ? m_ref_str1 : m_ref_str2; } | |
64 | inline Type *get_type(int p_type_no) const | |
65 | { return p_type_no == 0 ? m_type1 : m_type2; } | |
66 | inline bool is_strict() const { return m_strict; } | |
67 | inline bool is_erroneous() const { return m_erroneous; } | |
68 | inline Module *get_my_module() const { return m_my_module; } | |
69 | void set_is_erroneous(Type *p_type1, Type *p_type2, | |
70 | const string& p_error_str); | |
71 | inline const string& get_error_str() { return m_error_str; } | |
72 | /** Assemble the error message. */ | |
73 | string get_error_str_str() const; | |
74 | void set_subtype_error(const string error_str) { subtype_error_str = error_str; } | |
75 | bool is_subtype_error() const { return !subtype_error_str.empty(); } | |
76 | string get_subtype_error() { return subtype_error_str; } | |
77 | void set_str1_elem(bool p_str1_elem) { str1_elem = p_str1_elem; } | |
78 | void set_str2_elem(bool p_str2_elem) { str2_elem = p_str2_elem; } | |
79 | bool get_str1_elem() const { return str1_elem; } | |
80 | bool get_str2_elem() const { return str2_elem; } | |
81 | }; | |
82 | ||
83 | class TypeConv { | |
84 | private: | |
85 | Type *m_from; | |
86 | Type *m_to; | |
87 | bool m_is_temp; | |
88 | public: | |
89 | TypeConv(Type *p_from, Type *p_to, bool p_is_temp) : m_from(p_from), | |
90 | m_to(p_to), m_is_temp(p_is_temp) { } | |
91 | inline Type *get_from_type() const { return m_from; } | |
92 | inline Type *get_to_type() const { return m_to; } | |
93 | inline bool is_temp() const { return m_is_temp; } | |
94 | /** Assemble the name of the generated conversion function. Take care of | |
95 | * types declared in other modules. */ | |
96 | static string get_conv_func(Type *p_from, Type *p_to, Module *p_mod); | |
97 | static bool needs_conv_refd(GovernedSimple *p_val_or_temp); | |
98 | static bool needs_conv_redir(Ttcn::TemplateInstance *p_ti, Reference *p_ref); | |
99 | /** Generate initial conversion code for a given value or template | |
100 | * reference. */ | |
101 | static char *gen_conv_code_refd(char *str, const char *name, | |
102 | GovernedSimple *p_val_or_temp); | |
103 | /** Generate conversion code for value redirect constructs. */ | |
104 | static void gen_conv_code_redir(struct expression_struct_t *expr, | |
105 | Ttcn::TemplateInstance *p_ti, | |
106 | Reference *p_ref); | |
107 | void gen_conv_func(char **p_prototypes, char **p_bodies, Module *p_mod); | |
108 | void gen_conv_func_record_set(char **p_bodies, Module *p_mod); | |
109 | void gen_conv_func_array_record(char **p_bodies, Module *p_mod); | |
110 | void gen_conv_func_array_record_of(char **p_bodies, Module *p_mod); | |
111 | void gen_conv_func_record_set_record_of_set_of(char **p_bodies, | |
112 | Module *p_mod); | |
113 | void gen_conv_func_choice_anytype(char **p_bodies, Module *p_mod); | |
114 | }; | |
115 | ||
116 | /** Class to detect recursion in the type hierarchy. It is used by | |
117 | * is_compatible*() functions to check if the two types in question | |
118 | * reference each other in a way that would cause problems (e.g. infinite | |
119 | * recursion) during the semantic analysis. */ | |
120 | class TypeChain { | |
121 | private: | |
122 | vector<Type> m_chain; | |
123 | stack<int> m_marked_states; | |
124 | int m_first_double; | |
125 | public: | |
126 | TypeChain(); | |
127 | ~TypeChain(); | |
128 | inline bool has_recursion() const { return m_first_double != -1; } | |
129 | /** Check if this is the first level of the type hierarchy. The "root" | |
130 | * types are always added at first and removed only by the | |
131 | * destructor. */ | |
132 | inline bool empty() const { return m_chain.empty(); } | |
133 | void add(Type *p_type); | |
134 | void mark_state(); | |
135 | void previous_state(); | |
136 | }; | |
137 | ||
138 | } /* namespace Common */ | |
139 | #endif /* TYPECOMPAT_HH_ */ |