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