asar_math.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | #include <cstdint> | ||
| 3 | #include <memory> | ||
| 4 | #include <vector> | ||
| 5 | #include "errors.h" | ||
| 6 | #include "libstr.h" | ||
| 7 | |||
| 8 | // Public interface of the Asar mathematical subsystem // | ||
| 9 | |||
| 10 | // Asar's math is dynamically typed, this enum defines the possible types. | ||
| 11 | enum class math_val_type { | ||
| 12 | // 64-bit (double) floating point | ||
| 13 | floating, | ||
| 14 | // 64-bit signed int | ||
| 15 | integer, | ||
| 16 | // string | ||
| 17 | string, | ||
| 18 | // a resolved label with a name and value. used for datasize() and whatnot. | ||
| 19 | // auto-converts to integer when necessary. | ||
| 20 | identifier, | ||
| 21 | }; | ||
| 22 | |||
| 23 | class math_val { | ||
| 24 | public: | ||
| 25 | math_val_type m_type; | ||
| 26 | union { | ||
| 27 | double double_; | ||
| 28 | int64_t int_; | ||
| 29 | } m_numeric_val; | ||
| 30 | // this is used for both labelname in case of | ||
| 31 | // m_type=identifier, and string value in case of m_type=string | ||
| 32 | string m_string_val; | ||
| 33 | |||
| 34 | math_val() { | ||
| 35 | m_type = math_val_type::integer; | ||
| 36 | m_numeric_val.int_ = 0; | ||
| 37 | } | ||
| 38 | 158 | math_val(double v) { | |
| 39 | 158 | m_type = math_val_type::floating; | |
| 40 | 158 | m_numeric_val.double_ = v; | |
| 41 | 158 | } | |
| 42 | 23300 | math_val(int64_t v) { | |
| 43 | 23300 | m_type = math_val_type::integer; | |
| 44 | 23300 | m_numeric_val.int_ = v; | |
| 45 | 23300 | } | |
| 46 | 1312 | math_val(string v) { | |
| 47 | 1312 | m_type = math_val_type::string; | |
| 48 | 1312 | m_string_val = v; | |
| 49 | 1312 | } | |
| 50 | 941 | static math_val make_identifier(string v) { | |
| 51 | 941 | math_val res(v); | |
| 52 | 941 | res.m_type = math_val_type::identifier; | |
| 53 | 941 | return res; | |
| 54 | } | ||
| 55 | |||
| 56 | double get_double() const; | ||
| 57 | int64_t get_integer() const; | ||
| 58 | const string &get_str() const; | ||
| 59 | const string &get_identifier() const; | ||
| 60 | bool get_bool() const; | ||
| 61 | }; | ||
| 62 | |||
| 63 | class math_ast_node { | ||
| 64 | public: | ||
| 65 | // any info that's necessary during evaluation. | ||
| 66 | // external callers shouldn't need to pass in anything other than the default-constructed one. | ||
| 67 | class eval_context { | ||
| 68 | public: | ||
| 69 | // TODO would it be faster to make this a reference? does that avoid any significant copies? | ||
| 70 | std::vector<math_val> userfunc_params; | ||
| 71 | }; | ||
| 72 | |||
| 73 | virtual math_val evaluate(const eval_context& = {}) const = 0; | ||
| 74 | // 0 - no label, 1 - static label, 3 - nonstatic label, 7 - forward label | ||
| 75 | virtual int has_label() const = 0; | ||
| 76 | // how many bytes long should the result of this expression be? | ||
| 77 | virtual int get_len(bool could_be_bank_ex) const = 0; | ||
| 78 | 25818 | virtual ~math_ast_node() = default; | |
| 79 | |||
| 80 | // helper functions: | ||
| 81 | |||
| 82 | // evaluate an expression that doesn't allow non-static label references | ||
| 83 | 5967 | math_val evaluate_static() { | |
| 84 | 5967 | if(has_label() > 1) | |
| 85 | 54 | throw_err_block(0, err_no_labels_here); | |
| 86 | 8871 | return evaluate(); | |
| 87 | 5913 | } | |
| 88 | // evaluate an expression that doesn't allow forward label references | ||
| 89 | 1911 | math_val evaluate_non_forward() { | |
| 90 | 1911 | if(has_label() > 3) | |
| 91 | 4 | throw_err_block(0, err_label_forward); | |
| 92 | 2898 | return evaluate(); | |
| 93 | 1907 | } | |
| 94 | }; | ||
| 95 | |||
| 96 | void initmathcore(); | ||
| 97 | void deinitmathcore(); | ||
| 98 | void closecachedfiles(); | ||
| 99 | |||
| 100 | void createuserfunc(const char * name, const char * arguments, const char * content); | ||
| 101 | |||
| 102 | std::unique_ptr<math_ast_node> parse_math_expr(const char * str); | ||
| 103 | |||
| 104 | // old interface: to be nuked in due time | ||
| 105 | |||
| 106 | int64_t getnum(const char * str); | ||
| 107 | |||
| 108 | // still used in arch-spc700... god that one's a proper mess | ||
| 109 | int getlen(const char * str, bool optimizebankextraction=false); | ||
| 110 | extern bool foundlabel; | ||
| 111 |