+added Nil type handling, including assignment, boolean operation, serialization, etc. +added an MB_CONVERT_TO_INT_LEVEL macro, would convert float to integer as much as possible if this macro was enabled; *polished document
This commit is contained in:
parent
c6d7dcae8f
commit
31ab04052a
5
HISTORY
5
HISTORY
@ -1,3 +1,8 @@
|
||||
Sep. 16 2015
|
||||
Added Nil type handling, including assignment, boolean operation, serialization, etc.
|
||||
Added an MB_CONVERT_TO_INT_LEVEL macro, would convert float to integer as much as possible if this macro was enabled
|
||||
Polished document
|
||||
|
||||
Sep. 11 2015
|
||||
Added a duplicate sub routine error handling
|
||||
Added optional argument support for INPUT statement
|
||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2011 - 2015 Wang Renxin
|
||||
Copyright (C) 2011 - 2015 Wang Renxin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
Binary file not shown.
@ -43,6 +43,8 @@ Come along with a traditional "hello world" script in MY-BASIC:
|
||||
|
||||
input
|
||||
|
||||
Read the [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf) (especially the "**Programming with BASIC**" section) to get more details about how to program in MY-BASIC.
|
||||
|
||||
## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
||||
|
||||

|
||||
|
246
core/my_basic.c
246
core/my_basic.c
@ -79,7 +79,7 @@ extern "C" {
|
||||
/** Macros */
|
||||
#define _VER_MAJOR 1
|
||||
#define _VER_MINOR 1
|
||||
#define _VER_REVISION 69
|
||||
#define _VER_REVISION 70
|
||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||
|
||||
/* Uncomment the line below to treat warning as error */
|
||||
@ -338,11 +338,9 @@ const size_t MB_SIZEOF_CLS = sizeof(_class_t);
|
||||
#ifdef MB_ENABLE_SOURCE_TRACE
|
||||
static const _object_t _OBJ_INT_UNIT = { _DT_INT, 1, false, 0, 0, 0 };
|
||||
static const _object_t _OBJ_INT_ZERO = { _DT_INT, 0, false, 0, 0, 0 };
|
||||
static const _object_t _OBJ_NIL = { _DT_NIL, 0, false, 0, 0, 0 };
|
||||
#else /* MB_ENABLE_SOURCE_TRACE */
|
||||
static const _object_t _OBJ_INT_UNIT = { _DT_INT, 1, false, 0 };
|
||||
static const _object_t _OBJ_INT_ZERO = { _DT_INT, 0, false, 0 };
|
||||
static const _object_t _OBJ_NIL = { _DT_NIL, 0, false, 0 };
|
||||
#endif /* MB_ENABLE_SOURCE_TRACE */
|
||||
|
||||
static _object_t* _OBJ_BOOL_TRUE = 0;
|
||||
@ -471,6 +469,18 @@ static _object_t* _exp_assign = 0;
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if MB_CONVERT_TO_INT_LEVEL == MB_CONVERT_TO_INT_LEVEL_NONE
|
||||
# define _convert_to_int_if_posible(__o) ((void)(__o))
|
||||
#else /* MB_CONVERT_TO_INT_LEVEL == MB_CONVERT_TO_INT_LEVEL_NONE */
|
||||
# define _convert_to_int_if_posible(__o) \
|
||||
do { \
|
||||
if((__o)->type == _DT_REAL && (real_t)(int_t)(__o)->data.float_point == (__o)->data.float_point) { \
|
||||
(__o)->type = _DT_INT; \
|
||||
(__o)->data.integer = (int_t)(__o)->data.float_point; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif /* MB_CONVERT_TO_INT_LEVEL == MB_CONVERT_TO_INT_LEVEL_NONE */
|
||||
|
||||
#define _instruct_common(__tuple) \
|
||||
_object_t opndv1; \
|
||||
_object_t opndv2; \
|
||||
@ -496,10 +506,7 @@ static _object_t* _exp_assign = 0;
|
||||
opndv1.type == _DT_INT ? opndv1.data.integer : opndv1.data.float_point, \
|
||||
opndv2.type == _DT_INT ? opndv2.data.integer : opndv2.data.float_point); \
|
||||
} \
|
||||
if(val->type == _DT_REAL && (real_t)(int_t)val->data.float_point == val->data.float_point) { \
|
||||
val->type = _DT_INT; \
|
||||
val->data.integer = (int_t)val->data.float_point; \
|
||||
} \
|
||||
_convert_to_int_if_posible(val); \
|
||||
} while(0)
|
||||
#define _instruct_num_op_num(__optr, __tuple) \
|
||||
do { \
|
||||
@ -518,10 +525,28 @@ static _object_t* _exp_assign = 0;
|
||||
((opndv1.type == _DT_INT ? opndv1.data.integer : opndv1.data.float_point) __optr \
|
||||
(opndv2.type == _DT_INT ? opndv2.data.integer : opndv2.data.float_point)); \
|
||||
} \
|
||||
if(val->type == _DT_REAL && (real_t)(int_t)val->data.float_point == val->data.float_point) { \
|
||||
_convert_to_int_if_posible(val); \
|
||||
} while(0)
|
||||
#define _instruct_num_op_num_allow_nil(__optr, __tuple) \
|
||||
do { \
|
||||
_instruct_common(__tuple) \
|
||||
if(opndv1.type == _DT_NIL) { opndv1.type = _DT_INT; opndv1.data.integer = 0; } \
|
||||
if(opndv2.type == _DT_NIL) { opndv2.type = _DT_INT; opndv2.data.integer = 0; } \
|
||||
if(opndv1.type == _DT_INT && opndv2.type == _DT_INT) { \
|
||||
if((real_t)(opndv1.data.integer __optr opndv2.data.integer) == (real_t)opndv1.data.integer __optr (real_t)opndv2.data.integer) { \
|
||||
val->type = _DT_INT; \
|
||||
val->data.integer = (int_t)val->data.float_point; \
|
||||
val->data.integer = opndv1.data.integer __optr opndv2.data.integer; \
|
||||
} else { \
|
||||
val->type = _DT_REAL; \
|
||||
val->data.float_point = (real_t)((real_t)opndv1.data.integer __optr (real_t)opndv2.data.integer); \
|
||||
} \
|
||||
} else { \
|
||||
val->type = _DT_REAL; \
|
||||
val->data.float_point = (real_t) \
|
||||
((opndv1.type == _DT_INT ? opndv1.data.integer : opndv1.data.float_point) __optr \
|
||||
(opndv2.type == _DT_INT ? opndv2.data.integer : opndv2.data.float_point)); \
|
||||
} \
|
||||
_convert_to_int_if_posible(val); \
|
||||
} while(0)
|
||||
#define _instruct_int_op_int(__optr, __tuple) \
|
||||
do { \
|
||||
@ -590,6 +615,21 @@ static _object_t* _exp_assign = 0;
|
||||
val->data.integer = __r; \
|
||||
} while(0)
|
||||
|
||||
#define _math_calculate_fun_real(__s, __l, __a, __f, __exit, __result) \
|
||||
switch((__a).type) { \
|
||||
case MB_DT_INT: \
|
||||
(__a).value.float_point = (real_t)__f((real_t)(__a).value.integer); \
|
||||
(__a).type = MB_DT_REAL; \
|
||||
break; \
|
||||
case MB_DT_REAL: \
|
||||
(__a).value.float_point = (real_t)__f((__a).value.float_point); \
|
||||
break; \
|
||||
default: \
|
||||
_handle_error_on_obj(__s, SE_RN_NUMBER_EXPECTED, 0, ((__l) && *(__l)) ? ((_object_t*)(((_tuple3_t*)(*(__l)))->e1)) : 0, MB_FUNC_WARNING, __exit, __result); \
|
||||
break; \
|
||||
} \
|
||||
mb_convert_to_int_if_posible(__a);
|
||||
|
||||
#define _using_jump_set_of_instructional(__s, __obj, __exit, __result) \
|
||||
do { \
|
||||
if((__s)->jump_set & (~_JMP_INS)) { \
|
||||
@ -1909,7 +1949,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
||||
}
|
||||
|
||||
c = (_object_t*)(_ls_popback(opnd));
|
||||
if(!c || !(c->type == _DT_INT || c->type == _DT_REAL || c->type == _DT_STRING || c->type == _DT_VAR || c->type == _DT_USERTYPE || c->type == _DT_ARRAY)) {
|
||||
if(!c || !(c->type == _DT_NIL || c->type == _DT_INT || c->type == _DT_REAL || c->type == _DT_STRING || c->type == _DT_VAR || c->type == _DT_USERTYPE || c->type == _DT_ARRAY)) {
|
||||
_set_current_error(s, SE_RN_INVALID_DATA_TYPE, 0);
|
||||
result = MB_FUNC_ERR;
|
||||
|
||||
@ -2254,8 +2294,13 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
||||
(*obj)->type = type;
|
||||
switch(type) {
|
||||
case _DT_NIL:
|
||||
memcpy(tmp.any, value, sizeof(_raw_t));
|
||||
if(tmp.integer) { /* Nil type */
|
||||
(*obj)->type = _DT_NIL;
|
||||
} else { /* End of line character */
|
||||
safe_free(*obj);
|
||||
*obj = 0;
|
||||
}
|
||||
safe_free(sym);
|
||||
|
||||
break;
|
||||
@ -2491,6 +2536,15 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
/* Nil */
|
||||
if(!strcmp(sym, "NIL")) {
|
||||
tmp.integer = ~0;
|
||||
memcpy(*value, tmp.any, sizeof(_raw_t));
|
||||
|
||||
result = _DT_NIL;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
/* _array_t */
|
||||
glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
|
||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_ARRAY) {
|
||||
@ -3490,6 +3544,8 @@ bool_t _is_internal_object(_object_t* obj) {
|
||||
_data_e _public_type_to_internal_type(mb_data_e t) {
|
||||
/* Convert a public mb_data_e type to an internal _data_e */
|
||||
switch(t) {
|
||||
case MB_DT_NIL:
|
||||
return _DT_NIL;
|
||||
case MB_DT_INT:
|
||||
return _DT_INT;
|
||||
case MB_DT_REAL:
|
||||
@ -3506,6 +3562,8 @@ _data_e _public_type_to_internal_type(mb_data_e t) {
|
||||
mb_data_e _internal_type_to_public_type(_data_e t) {
|
||||
/* Convert an internal mb_data_e type to a public _data_e */
|
||||
switch(t) {
|
||||
case _DT_NIL:
|
||||
return MB_DT_NIL;
|
||||
case _DT_INT:
|
||||
return MB_DT_INT;
|
||||
case _DT_REAL:
|
||||
@ -3526,6 +3584,11 @@ int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn) {
|
||||
mb_assert(pbl && itn);
|
||||
|
||||
switch(pbl->type) {
|
||||
case MB_DT_NIL:
|
||||
itn->type = _DT_NIL;
|
||||
itn->data.integer = false;
|
||||
|
||||
break;
|
||||
case MB_DT_INT:
|
||||
itn->type = _DT_INT;
|
||||
itn->data.integer = pbl->value.integer;
|
||||
@ -3567,6 +3630,11 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
|
||||
mb_assert(pbl && itn);
|
||||
|
||||
switch(itn->type) {
|
||||
case _DT_NIL:
|
||||
pbl->type = MB_DT_NIL;
|
||||
pbl->value.integer = false;
|
||||
|
||||
break;
|
||||
case _DT_INT:
|
||||
pbl->type = MB_DT_INT;
|
||||
pbl->value.integer = itn->data.integer;
|
||||
@ -4538,6 +4606,7 @@ int mb_push_real(struct mb_interpreter_t* s, void** l, real_t val) {
|
||||
|
||||
arg.type = MB_DT_REAL;
|
||||
arg.value.float_point = val;
|
||||
mb_convert_to_int_if_posible(arg);
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
return result;
|
||||
@ -5218,6 +5287,7 @@ int _core_neg(mb_interpreter_t* s, void** l) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -5408,7 +5478,7 @@ int _core_and(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_assert(s && l);
|
||||
|
||||
_instruct_num_op_num(&&, l);
|
||||
_instruct_num_op_num_allow_nil(&&, l);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -5419,7 +5489,7 @@ int _core_or(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_assert(s && l);
|
||||
|
||||
_instruct_num_op_num(||, l);
|
||||
_instruct_num_op_num_allow_nil(||, l);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -5438,6 +5508,11 @@ int _core_not(mb_interpreter_t* s, void** l) {
|
||||
mb_check(mb_attempt_func_end(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_NIL:
|
||||
arg.value.integer = true;
|
||||
arg.type = MB_DT_INT;
|
||||
|
||||
break;
|
||||
case MB_DT_INT:
|
||||
arg.value.integer = (int_t)(!arg.value.integer);
|
||||
|
||||
@ -5448,6 +5523,9 @@ int _core_not(mb_interpreter_t* s, void** l) {
|
||||
|
||||
break;
|
||||
default:
|
||||
arg.value.integer = false;
|
||||
arg.type = MB_DT_INT;
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_int(s, l, arg.value.integer));
|
||||
@ -5639,7 +5717,6 @@ _elseif:
|
||||
result = _calc_expression(s, &ast, &val);
|
||||
if(result != MB_FUNC_OK)
|
||||
goto _exit;
|
||||
mb_assert(val->type == _DT_INT);
|
||||
|
||||
obj = (_object_t*)(ast->data);
|
||||
if(val->data.integer) {
|
||||
@ -5966,7 +6043,6 @@ _loop_begin:
|
||||
result = _calc_expression(s, &ast, &loop_cond_ptr);
|
||||
if(result != MB_FUNC_OK)
|
||||
goto _exit;
|
||||
mb_assert(loop_cond_ptr->type == _DT_INT);
|
||||
|
||||
if(loop_cond_ptr->data.integer) {
|
||||
/* Keep looping */
|
||||
@ -6066,7 +6142,6 @@ _loop_begin:
|
||||
result = _calc_expression(s, &ast, &loop_cond_ptr);
|
||||
if(result != MB_FUNC_OK)
|
||||
goto _exit;
|
||||
mb_assert(loop_cond_ptr->type == _DT_INT);
|
||||
|
||||
if(loop_cond_ptr->data.integer) {
|
||||
/* End looping */
|
||||
@ -6402,6 +6477,7 @@ int _std_abs(mb_interpreter_t* s, void** l) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6455,21 +6531,8 @@ int _std_sqr(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)sqrt((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, sqrt, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)sqrt(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6641,21 +6704,8 @@ int _std_sin(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)sin((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, sin, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)sin(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6675,21 +6725,8 @@ int _std_cos(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)cos((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, cos, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)cos(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6709,21 +6746,8 @@ int _std_tan(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)tan((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, tan, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)tan(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6743,21 +6767,8 @@ int _std_asin(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)asin((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, asin, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)asin(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6777,21 +6788,8 @@ int _std_acos(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)acos((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, acos, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)acos(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6811,21 +6809,8 @@ int _std_atan(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)atan((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, atan, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)atan(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6845,21 +6830,8 @@ int _std_exp(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)exp((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, exp, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)exp(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -6879,21 +6851,8 @@ int _std_log(mb_interpreter_t* s, void** l) {
|
||||
|
||||
mb_check(mb_attempt_close_bracket(s, l));
|
||||
|
||||
switch(arg.type) {
|
||||
case MB_DT_INT:
|
||||
arg.value.float_point = (real_t)log((real_t)arg.value.integer);
|
||||
arg.type = MB_DT_REAL;
|
||||
_math_calculate_fun_real(s, l, arg, log, _exit, result);
|
||||
|
||||
break;
|
||||
case MB_DT_REAL:
|
||||
arg.value.float_point = (real_t)log(arg.value.float_point);
|
||||
|
||||
break;
|
||||
default:
|
||||
_handle_error_on_obj(s, SE_RN_NUMBER_EXPECTED, 0, (l && *l) ? ((_object_t*)(((_tuple3_t*)(*l))->e1)) : 0, MB_FUNC_WARNING, _exit, result);
|
||||
|
||||
break;
|
||||
}
|
||||
mb_check(mb_push_value(s, l, arg));
|
||||
|
||||
_exit:
|
||||
@ -7149,6 +7108,7 @@ int _std_print(mb_interpreter_t* s, void** l) {
|
||||
obj = (_object_t*)(ast->data);
|
||||
do {
|
||||
switch(obj->type) {
|
||||
case _DT_NIL: /* Fall through */
|
||||
case _DT_INT: /* Fall through */
|
||||
case _DT_REAL: /* Fall through */
|
||||
case _DT_STRING: /* Fall through */
|
||||
@ -7156,7 +7116,9 @@ int _std_print(mb_interpreter_t* s, void** l) {
|
||||
case _DT_ARRAY: /* Fall through */
|
||||
case _DT_FUNC:
|
||||
result = _calc_expression(s, &ast, &val_ptr);
|
||||
if(val_ptr->type == _DT_INT) {
|
||||
if(val_ptr->type == _DT_NIL) {
|
||||
_get_printer(s)(MB_NIL);
|
||||
} else if(val_ptr->type == _DT_INT) {
|
||||
_get_printer(s)(MB_INT_FMT, val_ptr->data.integer);
|
||||
} else if(val_ptr->type == _DT_REAL) {
|
||||
_get_printer(s)(MB_REAL_FMT, val_ptr->data.float_point);
|
||||
|
@ -58,50 +58,65 @@ extern "C" {
|
||||
# pragma pack(1)
|
||||
#endif /* MB_COMPACT_MODE */
|
||||
|
||||
#ifndef MB_CONVERT_TO_INT_LEVEL_NONE
|
||||
# define MB_CONVERT_TO_INT_LEVEL_NONE 0
|
||||
#endif /* MB_CONVERT_TO_INT_LEVEL_NONE */
|
||||
|
||||
#ifndef MB_CONVERT_TO_INT_LEVEL_ALL
|
||||
# define MB_CONVERT_TO_INT_LEVEL_ALL 1
|
||||
#endif /* MB_CONVERT_TO_INT_LEVEL_ALL */
|
||||
|
||||
#ifndef MB_CONVERT_TO_INT_LEVEL
|
||||
# define MB_CONVERT_TO_INT_LEVEL MB_CONVERT_TO_INT_LEVEL_ALL
|
||||
#endif /* MB_CONVERT_TO_INT_LEVEL */
|
||||
|
||||
#ifndef true
|
||||
# define true (!0)
|
||||
#endif
|
||||
#endif /* true */
|
||||
#ifndef false
|
||||
# define false (0)
|
||||
#endif
|
||||
#endif /* false */
|
||||
|
||||
#ifndef bool_t
|
||||
# define bool_t int
|
||||
#endif
|
||||
#endif /* bool_t */
|
||||
#ifndef int_t
|
||||
# define int_t int
|
||||
#endif
|
||||
#endif /* int_t */
|
||||
#ifndef real_t
|
||||
# define real_t float
|
||||
#endif
|
||||
#endif /* real_t */
|
||||
|
||||
#ifndef mb_strtol
|
||||
# define mb_strtol(__s, __e, __r) strtol((__s), (__e), (__r))
|
||||
#endif
|
||||
#endif /* mb_strtol */
|
||||
#ifndef mb_strtod
|
||||
# define mb_strtod(__s, __e) strtod((__s), (__e))
|
||||
#endif
|
||||
#endif /* mb_strtod */
|
||||
|
||||
#ifndef MB_INT_FMT
|
||||
# define MB_INT_FMT "%d"
|
||||
#endif
|
||||
#endif /* MB_INT_FMT */
|
||||
#ifndef MB_REAL_FMT
|
||||
# define MB_REAL_FMT "%g"
|
||||
#endif
|
||||
#endif /* MB_REAL_FMT */
|
||||
|
||||
#ifndef MB_FNAN
|
||||
# define MB_FNAN 0xffc00000
|
||||
#endif
|
||||
#endif /* MB_FNAN */
|
||||
#ifndef MB_FINF
|
||||
# define MB_FINF 0x7f800000
|
||||
#endif
|
||||
#endif /* MB_FINF */
|
||||
|
||||
#ifndef MB_EOS
|
||||
# define MB_EOS '\n'
|
||||
#endif
|
||||
#endif /* MB_EOS */
|
||||
#ifndef MB_NIL
|
||||
# define MB_NIL "nil"
|
||||
#endif /* MB_NIL */
|
||||
#ifndef MB_NULL_STRING
|
||||
# define MB_NULL_STRING "(empty)"
|
||||
#endif
|
||||
#endif /* MB_NULL_STRING */
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# ifndef _strcmpi
|
||||
@ -163,6 +178,20 @@ extern "C" {
|
||||
# define mb_rem_res_fun(__s, __f) mb_remove_reserved_func(__s, #__f)
|
||||
#endif /* mb_rem_res_fun */
|
||||
|
||||
#ifndef mb_convert_to_int_if_posible
|
||||
# if MB_CONVERT_TO_INT_LEVEL == MB_CONVERT_TO_INT_LEVEL_NONE
|
||||
# define mb_convert_to_int_if_posible(__v) ((void)(__v))
|
||||
# else /* MB_CONVERT_TO_INT_LEVEL == MB_CONVERT_TO_INT_LEVEL_NONE */
|
||||
# define mb_convert_to_int_if_posible(__v) \
|
||||
do { \
|
||||
if((__v).type == MB_DT_REAL && (real_t)(int_t)(__v).value.float_point == (__v).value.float_point) { \
|
||||
(__v).type = MB_DT_INT; \
|
||||
(__v).value.integer = (int_t)(__v).value.float_point; \
|
||||
} \
|
||||
} while(0)
|
||||
# endif /* MB_CONVERT_TO_INT_LEVEL == MB_CONVERT_TO_INT_LEVEL_NONE */
|
||||
#endif /* mb_convert_to_int_if_posible */
|
||||
|
||||
struct mb_interpreter_t;
|
||||
|
||||
typedef enum mb_error_e {
|
||||
|
Binary file not shown.
@ -36,8 +36,8 @@
|
||||
IDI_ICON_MAIN ICON "icon.ico"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,69,0
|
||||
PRODUCTVERSION 1,1,69,0
|
||||
FILEVERSION 1,1,70,0
|
||||
PRODUCTVERSION 1,1,70,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
# ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -55,13 +55,13 @@
|
||||
VALUE "Comments", "MY-BASIC"
|
||||
VALUE "CompanyName", "Wang Renxin"
|
||||
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
||||
VALUE "FileVersion", "1, 1, 69, 0"
|
||||
VALUE "FileVersion", "1, 1, 70, 0"
|
||||
VALUE "InternalName", "my_basic"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
||||
VALUE "LegalTrademarks", "MY-BASIC"
|
||||
VALUE "OriginalFilename", "my_basic.exe"
|
||||
VALUE "ProductName", "MY-BASIC"
|
||||
VALUE "ProductVersion", "1, 1, 69, 0"
|
||||
VALUE "ProductVersion", "1, 1, 70, 0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
Loading…
x
Reference in New Issue
Block a user