91 }; |
91 }; |
92 }; |
92 }; |
93 |
93 |
94 |
94 |
95 |
95 |
96 |
96 /*** constant folding ***/ |
97 |
97 /* During stage 3 (semantic analysis/checking) we will be doing constant folding. |
98 |
98 * That algorithm will anotate the abstract syntax tree with the result of operations |
|
99 * on literals (i.e. 44 + 55 will store the result 99). |
|
100 * Since the same source code (e.g. 1 + 0) may actually be a BOOL or an ANY_INT, |
|
101 * or an ANY_BIT, we need to handle all possibilities, and determine the result of the |
|
102 * operation assuming each type. |
|
103 * For this reason, we have one entry for each possible type, with some expressions |
|
104 * having more than one entry filled in! |
|
105 */ |
|
106 class const_value_c { |
|
107 public: |
|
108 typedef enum { cs_undefined, /* not defined/not yet evaluated --> const_value is not valid! */ |
|
109 cs_non_const, /* we have determined that expression is not a const value --> const_value is not valid! */ |
|
110 cs_const_value, /* const value is valid */ |
|
111 cs_overflow /* result produced overflow or underflow --> const_value is not valid! */ |
|
112 } const_status_t; |
|
113 |
|
114 template<typename value_type> class const_value__ { |
|
115 const_status_t status; |
|
116 value_type value; |
|
117 |
|
118 public: |
|
119 const_value__(void): status(cs_undefined), value(0) {}; |
|
120 |
|
121 value_type get(void) {return value;} |
|
122 void set(value_type value_) {status = cs_const_value; value = value_;} |
|
123 void set_overflow(void) {status = cs_overflow ;} |
|
124 void set_nonconst(void) {status = cs_non_const ;} |
|
125 bool is_valid (void) {return (status == cs_const_value);} |
|
126 bool is_overflow (void) {return (status == cs_overflow );} |
|
127 bool is_nonconst (void) {return (status == cs_non_const );} |
|
128 bool is_zero (void) {return (is_valid() && (get() == 0));} |
|
129 }; |
|
130 |
|
131 const_value__< int64_t> _int64; /* status is initialised to UNDEFINED */ |
|
132 const_value__<uint64_t> _uint64; /* status is initialised to UNDEFINED */ |
|
133 const_value__<real64_t> _real64; /* status is initialised to UNDEFINED */ |
|
134 const_value__<bool > _bool; /* status is initialised to UNDEFINED */ |
|
135 |
|
136 /* default constructor and destructor */ |
|
137 const_value_c(void) {}; |
|
138 ~const_value_c(void) {}; |
|
139 }; |
99 |
140 |
100 |
141 |
101 |
142 |
102 /* The base class of all symbols */ |
143 /* The base class of all symbols */ |
103 class symbol_c { |
144 class symbol_c { |
140 * symbolic_variable_c, array_variable_c, structured_variable_c |
181 * symbolic_variable_c, array_variable_c, structured_variable_c |
141 */ |
182 */ |
142 symbol_c *scope; |
183 symbol_c *scope; |
143 |
184 |
144 /*** constant folding ***/ |
185 /*** constant folding ***/ |
145 /* During stage 3 (semantic analysis/checking) we will be doing constant folding. |
186 /* If the symbol has a constant numerical value, this will be set to that value by constant_folding_c */ |
146 * That algorithm will anotate the abstract syntax tree with the result of operations |
187 const_value_c const_value; |
147 * on literals (i.e. 44 + 55 will store the result 99). |
|
148 * Since the same source code (e.g. 1 + 0) may actually be a BOOL or an ANY_INT, |
|
149 * or an ANY_BIT, we need to handle all possibilities, and determine the result of the |
|
150 * operation assuming each type. |
|
151 * For this reason, we have one entry for each possible type, with some expressions |
|
152 * having more than one entry filled in! |
|
153 */ |
|
154 typedef enum { cs_undefined, /* not defined/not yet evaluated --> const_value is not valid! */ |
|
155 cs_non_const, /* we have determined that expression is not a const value --> const_value is not valid! */ |
|
156 cs_const_value, /* const value is valid */ |
|
157 cs_overflow /* result produced overflow or underflow --> const_value is not valid! */ |
|
158 } const_status_t; |
|
159 |
|
160 typedef struct const_value_real64_s {const_status_t status; real64_t value; const_value_real64_s (): status(cs_undefined), value(0.0) {} } const_value_real64_t; |
|
161 typedef struct const_value_int64_s {const_status_t status; int64_t value; const_value_int64_s (): status(cs_undefined), value(0) {} } const_value_int64_t; |
|
162 typedef struct const_value_uint64_s {const_status_t status; uint64_t value; const_value_uint64_s (): status(cs_undefined), value(0) {} } const_value_uint64_t; |
|
163 typedef struct const_value_bool_s {const_status_t status; bool value; const_value_bool_s (): status(cs_undefined), value(false) {} } const_value_bool_t; |
|
164 |
|
165 typedef struct { |
|
166 const_value_real64_t _real64; /* status is initialised to UNDEFINED */ |
|
167 const_value_int64_t _int64; /* status is initialised to UNDEFINED */ |
|
168 const_value_uint64_t _uint64; /* status is initialised to UNDEFINED */ |
|
169 const_value_bool_t _bool; /* status is initialised to UNDEFINED */ |
|
170 } const_value_t; |
|
171 const_value_t const_value; |
|
172 |
188 |
173 /*** Enumeration datatype checking ***/ |
189 /*** Enumeration datatype checking ***/ |
174 /* Not all symbols will contain the following anotations, which is why they are not declared here in symbol_c |
190 /* Not all symbols will contain the following anotations, which is why they are not declared here in symbol_c |
175 * They will be declared only inside the symbols that require them (have a look at absyntax.def) |
191 * They will be declared only inside the symbols that require them (have a look at absyntax.def) |
176 */ |
192 */ |