Skip to content

Miscellaneous module

Wang Renxin edited this page May 31, 2022 · 11 revisions

This page shows some miscellaneous function implementatins with MY-BASIC.

Add implementation functions. An ASSERT statement which evaluates an expression, and triggers an assertion if it results false, then terminates the execution; otherwise it continue executing:

static int _assert(struct mb_interpreter_t* s, void** l) {
	int result = MB_FUNC_OK;
	int_t val = 0;
	char* msg = 0;

	mb_check(mb_attempt_open_bracket(s, l));

	mb_check(mb_pop_int(s, l, &val));

	if(mb_has_arg(s, l)) {
		mb_check(mb_pop_string(s, l, &msg));
	}

	mb_check(mb_attempt_close_bracket(s, l));

	if(!val) {
		if(msg) {
			printf("ASSERTION: %s.\n", msg);
		} else {
			printf("ASSERTION.");
		}

		result = MB_FUNC_ERR;
	}

	return result;
}

An IIF statement which evaluates the first argument and returns the second argument if it results true, otherwise returns the third one. This is similar to ?: ternary operator in some other languages, as follow:

static int _iif(struct mb_interpreter_t* s, void** l) {
	int result = MB_FUNC_OK;
	mb_value_t arg;
	mb_value_t st;
	mb_value_t sf;
	bool_t cond = false;

	mb_assert(s && l);

	mb_check(mb_attempt_open_bracket(s, l));

	mb_check(mb_pop_value(s, l, &arg));
	mb_check(mb_pop_value(s, l, &st));
	mb_check(mb_pop_value(s, l, &sf));

	mb_check(mb_attempt_close_bracket(s, l));

	switch(arg.type) {
	case MB_DT_NIL:
		break;
	case MB_DT_INT:
		cond = !!arg.value.integer;

		break;
	default:
		cond = true;

		break;
	}

	if(cond) {
		mb_check(mb_push_value(s, l, st));
	} else {
		mb_check(mb_push_value(s, l, sf));
	}

	return result;
}

A SWAP statement which swaps the value of two variables as follow:

static int _swap(struct mb_interpreter_t* s, void** l) {
	int result = MB_FUNC_OK;
	void* v0 = 0;
	void* v1 = 0;
	mb_value_t val0;
	mb_value_t val1;

	mb_assert(s && l);

	mb_check(mb_attempt_open_bracket(s, l));

	mb_check(mb_get_var(s, l, &v0, true));
	mb_check(mb_get_var(s, l, &v1, true));

	mb_check(mb_attempt_close_bracket(s, l));

	mb_get_var_value(s, v0, &val0);
	mb_get_var_value(s, v1, &val1);
	mb_set_var_value(s, v0, val1);
	mb_set_var_value(s, v1, val0);

	return result;
}

A pair of MIN and MAX functions which evaluate arguments and return the minimum or maximum value:

static int _min(struct mb_interpreter_t* s, void** l) {
	int result = MB_FUNC_OK;
	real_t ret = (real_t)INT_MAX;
	real_t tmp = (real_t)0;

	mb_assert(s && l);

	mb_check(mb_attempt_open_bracket(s, l));

	while(mb_has_arg(s, l)) {
		mb_check(mb_pop_real(s, l, &tmp));
		if(tmp < ret)
			ret = tmp;
	}

	mb_check(mb_attempt_close_bracket(s, l));

	mb_check(mb_push_real(s, l, ret));

	return result;
}
static int _max(struct mb_interpreter_t* s, void** l) {
	int result = MB_FUNC_OK;
	real_t ret = (real_t)INT_MIN;
	real_t tmp = (real_t)0;

	mb_assert(s && l);

	mb_check(mb_attempt_open_bracket(s, l));

	while(mb_has_arg(s, l)) {
		mb_check(mb_pop_real(s, l, &tmp));
		if(tmp > ret)
			ret = tmp;
	}

	mb_check(mb_attempt_close_bracket(s, l));

	mb_check(mb_push_real(s, l, ret));

	return result;
}

Register them:

mb_register_func(bas, "ASSERT", _assert);
mb_register_func(bas, "IIF", _iif);
mb_register_func(bas, "SWAP", _swap);
mb_register_func(bas, "MIN", _min);
mb_register_func(bas, "MAX", _max);

See the BASIC usage as follow.

ASSERT statement:

assert(true, "t")
assert(false, "f")

IIF statement:

print iif(true, "succeed", "fail");
print iif(false, "fail", "succeed");
print iif(nil, "fail", "succeed");
print iif(0, "fail", "succeed");
print iif(1, "succeed", "fail");
print iif(0.1, "succeed", "fail");
print iif("", "succeed", "fail");

SWAP statement:

a = "hello"
b = "world"
swap(a, b)
print b, a;

MIN and MAX statements:

print min(1, 2, 3, 4);
print max(1, 2, 3, 4);
Clone this wiki locally