- 
                Notifications
    
You must be signed in to change notification settings  - Fork 127
 
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