29 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
29 * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) |
30 * |
30 * |
31 */ |
31 */ |
32 |
32 |
33 |
33 |
|
34 |
|
35 /* TODO: |
|
36 * - Add support for comparison (= and !=) of enumeration literals! |
|
37 * We will need to add another const_value entry to the symbol_c, containing the |
|
38 * possible enumeration value of the enum constant! |
|
39 * Doing this will allow us to more easily implement a constant_propagation_c later on! |
|
40 * |
|
41 * - Add support for comparison (= and !=) of the exact same variable |
|
42 * (e.g. if (int_v = int_v) then ...) |
|
43 */ |
34 |
44 |
35 |
45 |
36 |
46 |
37 /* Do constant folding... |
47 /* Do constant folding... |
38 * |
48 * |
213 * that may be added to the standard library in the future). |
223 * that may be added to the standard library in the future). |
214 * We actually create several of each, and let the compiler choose which is the correct one, |
224 * We actually create several of each, and let the compiler choose which is the correct one, |
215 * by having it resolve the call to the overloaded function. For the C++ compiler to be able |
225 * by having it resolve the call to the overloaded function. For the C++ compiler to be able |
216 * to resolve this ambiguity, we need to add a dummy parameter to each function! |
226 * to resolve this ambiguity, we need to add a dummy parameter to each function! |
217 * |
227 * |
218 * TODO: support platforms in which int64_t is mapped onto int !! Is this really needed? |
228 * TODO: support platforms (where the compiler will run) in which int64_t is mapped onto int !! |
|
229 * Is this really needed? |
|
230 * Currently, when trying to compile matiec on sych a platform, the C++ compiler will not |
|
231 * find any apropriate matiec_strtoint64() to call, so matiec will not be able to be compiled. |
|
232 * If you need this, you are welcome to fix it yourself... |
219 */ |
233 */ |
220 static int64_t matiec_strtoint64 ( long int *dummy, const char *nptr, char **endptr, int base) {return strtol (nptr, endptr, base);} |
234 static int64_t matiec_strtoint64 ( long int *dummy, const char *nptr, char **endptr, int base) {return strtol (nptr, endptr, base);} |
221 static int64_t matiec_strtoint64 ( long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);} |
235 static int64_t matiec_strtoint64 ( long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);} |
222 |
236 |
223 static uint64_t matiec_strtouint64(unsigned long int *dummy, const char *nptr, char **endptr, int base) {return strtoul (nptr, endptr, base);} |
237 static uint64_t matiec_strtouint64(unsigned long int *dummy, const char *nptr, char **endptr, int base) {return strtoul (nptr, endptr, base);} |
542 |
556 |
543 |
557 |
544 /* unary negation (multiply by -1) */ |
558 /* unary negation (multiply by -1) */ |
545 static void *handle_neg(symbol_c *symbol, symbol_c *oper) { |
559 static void *handle_neg(symbol_c *symbol, symbol_c *oper) { |
546 DO_UNARY_OPER( int64, -, oper); CHECK_OVERFLOW_int64_NEG(symbol, oper); |
560 DO_UNARY_OPER( int64, -, oper); CHECK_OVERFLOW_int64_NEG(symbol, oper); |
|
561 /* |
|
562 * NOTE : The syntax: uint_v := -<INT_MIN> may occur inside a neg_expression_c, but would always |
|
563 * result in a data type error (in-> INT, out -> UINT). So, although we could handle it here, |
|
564 * it is not really necessary as it will later be caught by the data type checking classes. |
|
565 */ |
547 DO_UNARY_OPER(real64, -, oper); CHECK_OVERFLOW_real64(symbol); |
566 DO_UNARY_OPER(real64, -, oper); CHECK_OVERFLOW_real64(symbol); |
548 return NULL; |
567 return NULL; |
549 } |
568 } |
550 |
569 |
551 |
570 |
753 */ |
772 */ |
754 // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement |
773 // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement |
755 if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) { |
774 if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == (uint64_t)INT64_MAX+1)) { |
756 SET_CVALUE(int64, symbol, INT64_MIN); |
775 SET_CVALUE(int64, symbol, INT64_MIN); |
757 } |
776 } |
|
777 /* NOTE 3: The standard allows considers the following strange syntax correct: |
|
778 * int_v = ----------42; |
|
779 * However, it will be parsed as multiple neg_expression_c, with a single final neg_integer_c. |
|
780 * So, when parsing a neg_integer_c, we are guaranteed to always have a positive value in symbol->exp |
|
781 * --> Conclusion: |
|
782 * We do not need to handle the situation where we are negating the INT_MIN value, whose |
|
783 * result can only be stored inside an UINT (remember that INT_MIN is < 0 !!). |
|
784 * |
|
785 * NOTE 4: The syntax: uint_v := -<INT_MIN> may occur inside a neg_expression_c, but would always |
|
786 * result in a data type error. So, although we could handle it here, it is not really |
|
787 * necessary as it will later be caught by the data type checking classes. |
|
788 */ |
758 return NULL; |
789 return NULL; |
759 } |
790 } |
760 |
791 |
761 |
792 |
762 void *constant_folding_c::visit(binary_integer_c *symbol) { |
793 void *constant_folding_c::visit(binary_integer_c *symbol) { |