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