Переменные могут быть 32, 16, 8 бит.
Поэтому вам нужно знать:
- адреса переменных
- переменныхтипы и
- операция
И вам нужно передать эту информацию.
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
enum type_e {
TYPE_u8,
TYPE_u16,
TYPE_u32,
// TODO: add more, ex. TYPE_INT, TYPE_DOUBLE, etc.
};
enum oper_e {
OP_PLUS,
OP_MINUS,
// TODO: add mode, ex. OP_POW or OP_DIV etc.
};
void SCRIPT_Process(void *res, const void *l, const void *r, enum type_e type, enum oper_e oper)
{
switch (oper) {
case OP_PLUS:
switch (type) {
case TYPE_u8:
*(uint8_t*)res = *(uint8_t*)l + *(uint8_t*)r;
break;
case TYPE_u16:
*(uint16_t*)res = *(uint16_t*)l + *(uint16_t*)r;
break;
case TYPE_u32:
*(uint32_t*)res = *(uint32_t*)l + *(uint32_t*)r;
break;
default:
assert(0);
}
break;
case OP_MINUS:
// TODO:
assert(0);
}
}
int main() {
uint32_t l = 5, r = 2, res;
SCRIPT_Process(&res, &r, &l, TYPE_u32, OP_PLUS);
printf("%d + %d = %d\n", (int)l, (int)r, (int)res);
}
Было бы неплохо предоставить макрос, чтобы сделать код более подробным ис меньшим количеством набрав:
#define SCRIPT_PROCESS_MACRO(type, res, l, op, r) \
*(type*)res = *(type*)l op *(type*)r;
void SCRIPT_Process(void *res, void *l, void *r, enum type_e type, enum oper_e oper)
{
switch (oper) {
case OP_PLUS:
switch (type) {
case TYPE_u8:
SCRIPT_PROCESS_MACRO(uint8_t, res, l, +, r);
break;
case TYPE_u16:
SCRIPT_PROCESS_MACRO(uint16_t, res, l, +, r);
break;
case TYPE_u32:
SCRIPT_PROCESS_MACRO(uint32_t, res, l, +, r);
break;
default:
assert(0);
}
break;
case OP_MINUS:
// TODO:
assert(0);
}
}
Или еще более простым с большим количеством макросов, что делает добавление новых операций и типов тривиальным:
#define SCRIPT_PROCESS_MACRO(type, res, l, op, r) \
*(type*)res = *(type*)l op *(type*)r;
#define SCRIPT_PROCESS_TYPE_CASES(type, res, l, op, r) \
switch (type) { \
case TYPE_u8: SCRIPT_PROCESS_MACRO(uint8_t, res, l, op, r); break; \
case TYPE_u16: SCRIPT_PROCESS_MACRO(uint16_t, res, l, op, r); break; \
case TYPE_u32: SCRIPT_PROCESS_MACRO(uint32_t, res, l, op, r); break; \
default: assert(0); break; \
}
void SCRIPT_Process(void *res, void *l, void *r, enum type_e type, enum oper_e oper)
{
switch (oper) {
case OP_PLUS:
SCRIPT_PROCESS_TYPE_CASES(type, res, l, +, r);
break;
case OP_MINUS:
SCRIPT_PROCESS_TYPE_CASES(type, res, l, -, r);
break;
}
}
Или вы можете даже пойти с еще более универсальным решением,имеющие отдельные типы для результата, левый и правый операнды:
void SCRIPT_Process(
void *res, enum type_e restype,
const void *l, enum type_e ltype,
const void *r, enum type_e rtype,
enum oper_e oper) {
if (restype == TYPE_u8 && ltype == TYPE_u32 && rtype == TYPE_u16 && oper == OP_ADD) {
*(uint8_t*)res = *(uint32_t*)ltype + *(uint16_t*)rtype;
} if ( // and so on so on so on so on ....
}