-
Notifications
You must be signed in to change notification settings - Fork 118
Overriding operators
It's possible to override meta operators in MY-BASIC for a referenced usertype. Assuming got a referenced usertype defined as follow:
typedef struct _foo_t {
int test;
} _foo_t;
And associated functions:
static void _dtor_func(struct mb_interpreter_t* s, void* f);
static void* _clone_func(struct mb_interpreter_t* s, void* f);
static int _add(struct mb_interpreter_t* s, void** l, mb_value_t* left, mb_value_t* right, mb_value_t* ret);
static int _neg(struct mb_interpreter_t* s, void** l, mb_value_t* left, mb_value_t* right, mb_value_t* ret);
static int _new_foo(struct mb_interpreter_t* s, void** l, mb_value_t* ret, int val) {
int result = MB_FUNC_OK;
_foo_t* f = 0;
mb_assert(s && l && ret);
f = (_foo_t*)malloc(sizeof(_foo_t));
f->test = val;
mb_make_nil(*ret);
mb_check(mb_make_ref_value(s, f, ret, _dtor_func, _clone_func, 0, 0, 0)); /* Make a referenced usertype */
mb_check(mb_override_value(s, l, *ret, MB_MF_ADD, _add)); /* Override the + operator */
mb_check(mb_override_value(s, l, *ret, MB_MF_NEG, _neg)); /* Override the unary - operator */
return result;
}
static void _dtor_func(struct mb_interpreter_t* s, void* f) {
mb_assert(s && f);
free(f);
}
static void* _clone_func(struct mb_interpreter_t* s, void* f) {
_foo_t* ret = (_foo_t*)malloc(sizeof(_foo_t));
_foo_t* foo = (_foo_t*)f;
mb_assert(s && f);
ret->test = foo->test;
return ret;
}
Then define an add operator (+
) function which accepts a _foo_t
with an integer or another _foo_t
, then calculates a sum:
static int _add(struct mb_interpreter_t* s, void** l, mb_value_t* left, mb_value_t* right, mb_value_t* ret) {
int result = MB_FUNC_OK;
mb_assert(s && l && left && right && ret);
if(left->type == MB_DT_USERTYPE_REF && right->type == MB_DT_USERTYPE_REF) {
_foo_t* lf = 0;
_foo_t* rf = 0;
mb_check(mb_get_ref_value(s, l, *left, (void**)(&lf)));
mb_check(mb_get_ref_value(s, l, *right, (void**)(&rf)));
mb_check(_new_foo(s, l, ret, lf->test + rf->test));
mb_check(mb_ref_value(s, l, *ret));
} else if(left->type == MB_DT_USERTYPE_REF && right->type == MB_DT_INT) {
_foo_t* lf = 0;
int_t rf = 0;
mb_check(mb_get_ref_value(s, l, *left, (void**)(&lf)));
rf = right->value.integer;
mb_check(_new_foo(s, l, ret, lf->test + rf));
mb_check(mb_ref_value(s, l, *ret));
} else if(left->type == MB_DT_INT && right->type == MB_DT_USERTYPE_REF) {
int_t lf = 0;
_foo_t* rf = 0;
lf = left->value.integer;
mb_check(mb_get_ref_value(s, l, *right, (void**)(&rf)));
mb_check(_new_foo(s, l, ret, lf + rf->test));
mb_check(mb_ref_value(s, l, *ret));
} else {
result = MB_FUNC_ERR;
}
return result;
}
Another unary negative (-
) operator as well:
static int _neg(struct mb_interpreter_t* s, void** l, mb_value_t* left, mb_value_t* right, mb_value_t* ret) {
int result = MB_FUNC_OK;
_foo_t* lf = 0;
mb_assert(s && l && left && !right && ret);
mb_check(mb_get_ref_value(s, l, *left, (void**)(&lf)));
mb_check(_new_foo(s, l, ret, -lf->test));
mb_check(mb_ref_value(s, l, *ret));
return result;
}
We also need a BASIC function to make it possible to create a _foo_t
from BASIC:
static int foo(struct mb_interpreter_t* s, void** l) {
int result = MB_FUNC_OK;
int_t i = 0;
mb_value_t val;
mb_value_t out;
_foo_t* f = 0;
mb_assert(s && l);
mb_check(mb_attempt_open_bracket(s, l));
mb_make_nil(val);
mb_check(mb_pop_value(s, l, &val));
switch(val.type) {
case MB_DT_USERTYPE_REF:
mb_check(mb_get_ref_value(s, l, val, (void**)(&f)));
i = f->test;
mb_check(mb_unref_value(s, l, val));
break;
case MB_DT_INT:
i = val.value.integer;
break;
default:
result = MB_FUNC_ERR;
break;
}
mb_check(mb_attempt_close_bracket(s, l));
mb_check(_new_foo(s, l, &out, i));
mb_check(mb_push_value(s, l, out));
return result;
}
Don't forget to register it:
mb_reg_fun(bas, foo);
After that, it's possible to apply the +
operator to a _foo_t
and an integer in MY-BASIC:
f = foo(100)
t = -(2 + f + 1 + f)
print t;
It's supported in MY-BASIC to override with MB_MF_IS
for the IS
operator, MB_MF_ADD
for +
, MB_MF_SUB
for -
, MB_MF_MUL
for *
, MB_MF_DIV
for /
, MB_MF_NEG
for unary -
.
Read the Overriding functions page to get information about overriding meta functions.
- Principles
- Coding
- Data types
- Standalone shell
- Integration
- Customization
- More scripting API
- FAQ