+debug APIs; +improved IF statment
This commit is contained in:
parent
0b42fc2961
commit
7f6417c2a2
6
HISTORY
Executable file → Normal file
6
HISTORY
Executable file → Normal file
@ -1,3 +1,7 @@
|
|||||||
|
Apr. 23 2015 Version 1.1
|
||||||
|
Added debug APIs
|
||||||
|
Added (nestable) multi line IF statement support
|
||||||
|
|
||||||
Apr. 15 2015
|
Apr. 15 2015
|
||||||
Added mb_pop_usertype, mb_push_usertype to support user defined type
|
Added mb_pop_usertype, mb_push_usertype to support user defined type
|
||||||
Polished code
|
Polished code
|
||||||
@ -169,5 +173,5 @@ Fixed a suspend / resume bug
|
|||||||
Feb. 9 2011
|
Feb. 9 2011
|
||||||
Fixed struct mb_interpreter_t declaration warnings on gcc
|
Fixed struct mb_interpreter_t declaration warnings on gcc
|
||||||
|
|
||||||
Feb. 1 2011
|
Feb. 1 2011 Version 1.0
|
||||||
First release.
|
First release.
|
||||||
|
BIN
MY-BASIC Quick Reference.pdf
Executable file → Normal file
BIN
MY-BASIC Quick Reference.pdf
Executable file → Normal file
Binary file not shown.
1
README.md
Executable file → Normal file
1
README.md
Executable file → Normal file
@ -46,6 +46,7 @@ For more details about using MY-BASIC with exist projects, please see [MY-BASIC
|
|||||||
* [Redirect PRINT and INPUT](https://github.com/paladin-t/my_basic/wiki/Redirect-PRINT-and-INPUT)
|
* [Redirect PRINT and INPUT](https://github.com/paladin-t/my_basic/wiki/Redirect-PRINT-and-INPUT)
|
||||||
* [Use usertype values](https://github.com/paladin-t/my_basic/wiki/Use-usertype-values)
|
* [Use usertype values](https://github.com/paladin-t/my_basic/wiki/Use-usertype-values)
|
||||||
* [Customizable macros](https://github.com/paladin-t/my_basic/wiki/Customizable-macros)
|
* [Customizable macros](https://github.com/paladin-t/my_basic/wiki/Customizable-macros)
|
||||||
|
* [Write a debugger](https://github.com/paladin-t/my_basic/wiki/Write-a-debugger)
|
||||||
* [More scripting API](https://github.com/paladin-t/my_basic/wiki/More-scripting-API)
|
* [More scripting API](https://github.com/paladin-t/my_basic/wiki/More-scripting-API)
|
||||||
* [File module](https://github.com/paladin-t/my_basic/wiki/File-module)
|
* [File module](https://github.com/paladin-t/my_basic/wiki/File-module)
|
||||||
* [FAQ](https://github.com/paladin-t/my_basic/wiki/FAQ)
|
* [FAQ](https://github.com/paladin-t/my_basic/wiki/FAQ)
|
||||||
|
248
core/my_basic.c
Executable file → Normal file
248
core/my_basic.c
Executable file → Normal file
@ -51,7 +51,6 @@ extern "C" {
|
|||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable : 4127)
|
# pragma warning(disable : 4127)
|
||||||
# pragma warning(disable : 4996)
|
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -77,8 +76,8 @@ extern "C" {
|
|||||||
|
|
||||||
/** Macros */
|
/** Macros */
|
||||||
#define _VER_MAJOR 1
|
#define _VER_MAJOR 1
|
||||||
#define _VER_MINOR 0
|
#define _VER_MINOR 1
|
||||||
#define _VER_REVISION 50
|
#define _VER_REVISION 51
|
||||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||||
|
|
||||||
/* Uncomment this line to treat warnings as error */
|
/* Uncomment this line to treat warnings as error */
|
||||||
@ -108,6 +107,10 @@ extern "C" {
|
|||||||
|
|
||||||
#define DON(__o) ((__o) ? ((_object_t*)((__o)->data)) : 0)
|
#define DON(__o) ((__o) ? ((_object_t*)((__o)->data)) : 0)
|
||||||
|
|
||||||
|
#define _IS_EOS(__o) (__o && ((_object_t*)(__o))->type == _DT_EOS)
|
||||||
|
#define _IS_SEP(__o, __c) (((_object_t*)(__o))->type == _DT_SEP && ((_object_t*)(__o))->data.separator == __c)
|
||||||
|
#define _IS_FUNC(__o, __f) (((_object_t*)(__o))->type == _DT_FUNC && ((_object_t*)(__o))->data.func->pointer == __f)
|
||||||
|
|
||||||
/* Hash table size */
|
/* Hash table size */
|
||||||
#define _HT_ARRAY_SIZE_SMALL 193
|
#define _HT_ARRAY_SIZE_SMALL 193
|
||||||
#define _HT_ARRAY_SIZE_MID 1543
|
#define _HT_ARRAY_SIZE_MID 1543
|
||||||
@ -342,6 +345,7 @@ typedef struct mb_interpreter_t {
|
|||||||
int last_error_pos;
|
int last_error_pos;
|
||||||
unsigned short last_error_row;
|
unsigned short last_error_row;
|
||||||
unsigned short last_error_col;
|
unsigned short last_error_col;
|
||||||
|
mb_debug_stepped_handler_t debug_stepped_handler;
|
||||||
mb_error_handler_t error_handler;
|
mb_error_handler_t error_handler;
|
||||||
mb_print_func_t printer;
|
mb_print_func_t printer;
|
||||||
mb_input_func_t inputer;
|
mb_input_func_t inputer;
|
||||||
@ -696,8 +700,10 @@ static int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn);
|
|||||||
static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl);
|
static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl);
|
||||||
static void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s);
|
static void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s);
|
||||||
|
|
||||||
|
static void _stepped(mb_interpreter_t* s, _ls_node_t* ast);
|
||||||
static int _execute_statement(mb_interpreter_t* s, _ls_node_t** l);
|
static int _execute_statement(mb_interpreter_t* s, _ls_node_t** l);
|
||||||
static int _skip_to(mb_interpreter_t* s, _ls_node_t** l, mb_func_t f, _data_e t);
|
static int _skip_to(mb_interpreter_t* s, _ls_node_t** l, mb_func_t f, _data_e t);
|
||||||
|
static int _skip_if_chunk(mb_interpreter_t* s, _ls_node_t** l);
|
||||||
static int _skip_struct(mb_interpreter_t* s, _ls_node_t** l, mb_func_t open_func, mb_func_t close_func);
|
static int _skip_struct(mb_interpreter_t* s, _ls_node_t** l, mb_func_t open_func, mb_func_t close_func);
|
||||||
|
|
||||||
static int _register_func(mb_interpreter_t* s, const char* n, mb_func_t f, bool_t local);
|
static int _register_func(mb_interpreter_t* s, const char* n, mb_func_t f, bool_t local);
|
||||||
@ -765,7 +771,9 @@ static int _core_let(mb_interpreter_t* s, void** l);
|
|||||||
static int _core_dim(mb_interpreter_t* s, void** l);
|
static int _core_dim(mb_interpreter_t* s, void** l);
|
||||||
static int _core_if(mb_interpreter_t* s, void** l);
|
static int _core_if(mb_interpreter_t* s, void** l);
|
||||||
static int _core_then(mb_interpreter_t* s, void** l);
|
static int _core_then(mb_interpreter_t* s, void** l);
|
||||||
|
static int _core_elseif(mb_interpreter_t* s, void** l);
|
||||||
static int _core_else(mb_interpreter_t* s, void** l);
|
static int _core_else(mb_interpreter_t* s, void** l);
|
||||||
|
static int _core_endif(mb_interpreter_t* s, void** l);
|
||||||
static int _core_for(mb_interpreter_t* s, void** l);
|
static int _core_for(mb_interpreter_t* s, void** l);
|
||||||
static int _core_to(mb_interpreter_t* s, void** l);
|
static int _core_to(mb_interpreter_t* s, void** l);
|
||||||
static int _core_step(mb_interpreter_t* s, void** l);
|
static int _core_step(mb_interpreter_t* s, void** l);
|
||||||
@ -840,7 +848,9 @@ static const _func_t _core_libs[] = {
|
|||||||
|
|
||||||
{ "IF", _core_if },
|
{ "IF", _core_if },
|
||||||
{ "THEN", _core_then },
|
{ "THEN", _core_then },
|
||||||
|
{ "ELSEIF", _core_elseif },
|
||||||
{ "ELSE", _core_else },
|
{ "ELSE", _core_else },
|
||||||
|
{ "ENDIF", _core_endif },
|
||||||
|
|
||||||
{ "FOR", _core_for },
|
{ "FOR", _core_for },
|
||||||
{ "TO", _core_to },
|
{ "TO", _core_to },
|
||||||
@ -1351,7 +1361,9 @@ bool_t _is_flow(mb_func_t op) {
|
|||||||
result =
|
result =
|
||||||
(op == _core_if) ||
|
(op == _core_if) ||
|
||||||
(op == _core_then) ||
|
(op == _core_then) ||
|
||||||
|
(op == _core_elseif) ||
|
||||||
(op == _core_else) ||
|
(op == _core_else) ||
|
||||||
|
(op == _core_endif) ||
|
||||||
(op == _core_for) ||
|
(op == _core_for) ||
|
||||||
(op == _core_to) ||
|
(op == _core_to) ||
|
||||||
(op == _core_step) ||
|
(op == _core_step) ||
|
||||||
@ -1488,7 +1500,9 @@ bool_t _is_expression_terminal(mb_interpreter_t* s, _object_t* obj) {
|
|||||||
(obj->type == _DT_SEP) ||
|
(obj->type == _DT_SEP) ||
|
||||||
(obj->type == _DT_FUNC &&
|
(obj->type == _DT_FUNC &&
|
||||||
(obj->data.func->pointer == _core_then ||
|
(obj->data.func->pointer == _core_then ||
|
||||||
|
obj->data.func->pointer == _core_elseif ||
|
||||||
obj->data.func->pointer == _core_else ||
|
obj->data.func->pointer == _core_else ||
|
||||||
|
obj->data.func->pointer == _core_endif ||
|
||||||
obj->data.func->pointer == _core_to ||
|
obj->data.func->pointer == _core_to ||
|
||||||
obj->data.func->pointer == _core_step));
|
obj->data.func->pointer == _core_step));
|
||||||
|
|
||||||
@ -1540,7 +1554,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
if(c->type == _DT_STRING) {
|
if(c->type == _DT_STRING) {
|
||||||
if(ast->next) {
|
if(ast->next) {
|
||||||
_object_t* _fsn = (_object_t*)ast->next->data;
|
_object_t* _fsn = (_object_t*)ast->next->data;
|
||||||
if(_fsn->type == _DT_FUNC && _fsn->data.func->pointer == _core_add)
|
if(_IS_FUNC(_fsn, _core_add))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1559,9 +1573,9 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
!(c->type == _DT_FUNC && strcmp(c->data.func->name, "#") == 0) ||
|
!(c->type == _DT_FUNC && strcmp(c->data.func->name, "#") == 0) ||
|
||||||
!(((_object_t*)(_ls_back(optr)->data))->type == _DT_FUNC && strcmp(((_object_t*)(_ls_back(optr)->data))->data.func->name, "#") == 0)) {
|
!(((_object_t*)(_ls_back(optr)->data))->type == _DT_FUNC && strcmp(((_object_t*)(_ls_back(optr)->data))->data.func->name, "#") == 0)) {
|
||||||
if(!hack) {
|
if(!hack) {
|
||||||
if(c->type == _DT_FUNC && c->data.func->pointer == _core_open_bracket) {
|
if(_IS_FUNC(c, _core_open_bracket)) {
|
||||||
++bracket_count;
|
++bracket_count;
|
||||||
} else if(c->type == _DT_FUNC && c->data.func->pointer == _core_close_bracket) {
|
} else if(_IS_FUNC(c, _core_close_bracket)) {
|
||||||
--bracket_count;
|
--bracket_count;
|
||||||
if(bracket_count < 0) {
|
if(bracket_count < 0) {
|
||||||
c = _exp_assign;
|
c = _exp_assign;
|
||||||
@ -1642,7 +1656,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
} else {
|
} else {
|
||||||
if(c->type == _DT_VAR && ast) {
|
if(c->type == _DT_VAR && ast) {
|
||||||
_object_t* _err_var = (_object_t*)(ast->data);
|
_object_t* _err_var = (_object_t*)(ast->data);
|
||||||
if(_err_var->type == _DT_FUNC && _err_var->data.func->pointer == _core_open_bracket) {
|
if(_IS_FUNC(_err_var, _core_open_bracket)) {
|
||||||
_handle_error_on_obj(s, SE_RN_INVALID_ID_USAGE, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_INVALID_ID_USAGE, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1691,7 +1705,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
}
|
}
|
||||||
_ls_pushback(opnd, r);
|
_ls_pushback(opnd, r);
|
||||||
_ls_pushback(garbage, r);
|
_ls_pushback(garbage, r);
|
||||||
if(c->type == _DT_FUNC && c->data.func->pointer == _core_close_bracket)
|
if(_IS_FUNC(c, _core_close_bracket))
|
||||||
hack = true;
|
hack = true;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1751,10 +1765,11 @@ bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj) {
|
|||||||
|
|
||||||
mb_assert(s && obj);
|
mb_assert(s && obj);
|
||||||
|
|
||||||
result =
|
result = _IS_EOS(obj) ||
|
||||||
(obj->type == _DT_EOS) ||
|
_IS_SEP(obj, ':') ||
|
||||||
(obj->type == _DT_SEP && obj->data.separator == ':') ||
|
_IS_FUNC(obj, _core_elseif) ||
|
||||||
(obj->type == _DT_FUNC && (obj->data.func->pointer == _core_else));
|
_IS_FUNC(obj, _core_else) ||
|
||||||
|
_IS_FUNC(obj, _core_endif);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1903,6 +1918,8 @@ int _append_symbol(mb_interpreter_t* s, char* sym, bool_t* delsym, int pos, unsi
|
|||||||
obj->source_row = row;
|
obj->source_row = row;
|
||||||
obj->source_col = col;
|
obj->source_col = col;
|
||||||
#else /* MB_ENABLE_SOURCE_TRACE */
|
#else /* MB_ENABLE_SOURCE_TRACE */
|
||||||
|
mb_unrefvar(row);
|
||||||
|
mb_unrefvar(col);
|
||||||
obj->source_pos = (char)pos;
|
obj->source_pos = (char)pos;
|
||||||
#endif /* MB_ENABLE_SOURCE_TRACE */
|
#endif /* MB_ENABLE_SOURCE_TRACE */
|
||||||
|
|
||||||
@ -2181,7 +2198,7 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
|
|||||||
}
|
}
|
||||||
/* _label_t */
|
/* _label_t */
|
||||||
if(context->current_char == ':') {
|
if(context->current_char == ':') {
|
||||||
if(!context->last_symbol || context->last_symbol->type == _DT_EOS) {
|
if(!context->last_symbol || _IS_EOS(context->last_symbol)) {
|
||||||
glbsyminscope = _ht_find(s->global_var_dict, sym);
|
glbsyminscope = _ht_find(s->global_var_dict, sym);
|
||||||
if(glbsyminscope) {
|
if(glbsyminscope) {
|
||||||
memcpy(*value, &glbsyminscope->data, sizeof(glbsyminscope->data));
|
memcpy(*value, &glbsyminscope->data, sizeof(glbsyminscope->data));
|
||||||
@ -2400,7 +2417,7 @@ int _get_array_index(mb_interpreter_t* s, _ls_node_t** l, unsigned int* index) {
|
|||||||
else
|
else
|
||||||
idx += (unsigned int)val.integer;
|
idx += (unsigned int)val.integer;
|
||||||
/* Comma? */
|
/* Comma? */
|
||||||
if(((_object_t*)(ast->data))->type == _DT_SEP && ((_object_t*)(ast->data))->data.separator == ',')
|
if(_IS_SEP(ast->data, ','))
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
|
|
||||||
++dcount;
|
++dcount;
|
||||||
@ -2848,6 +2865,26 @@ void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s)
|
|||||||
running->intermediate_value.type = MB_DT_NIL;
|
running->intermediate_value.type = MB_DT_NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _stepped(mb_interpreter_t* s, _ls_node_t* ast) {
|
||||||
|
/* Called each step */
|
||||||
|
_object_t* obj = 0;
|
||||||
|
|
||||||
|
mb_assert(s);
|
||||||
|
|
||||||
|
if(s->debug_stepped_handler) {
|
||||||
|
if(ast && ast->data) {
|
||||||
|
obj = (_object_t*)ast->data;
|
||||||
|
#ifdef MB_ENABLE_SOURCE_TRACE
|
||||||
|
s->debug_stepped_handler(s, obj->source_pos, obj->source_row, obj->source_col);
|
||||||
|
#else /* MB_ENABLE_SOURCE_TRACE */
|
||||||
|
s->debug_stepped_handler(s, obj->source_pos, 0, 0);
|
||||||
|
#endif /* MB_ENABLE_SOURCE_TRACE */
|
||||||
|
} else {
|
||||||
|
s->debug_stepped_handler(s, -1, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
||||||
/* Execute the ast, core execution function */
|
/* Execute the ast, core execution function */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
@ -2886,9 +2923,9 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
if(ast) {
|
if(ast) {
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(obj && obj->type == _DT_EOS) {
|
if(_IS_EOS(obj)) {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
} else if(obj && obj->type == _DT_SEP && obj->data.separator == ':') {
|
} else if(_IS_SEP(obj, ':')) {
|
||||||
skip_to_eoi = false;
|
skip_to_eoi = false;
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
} else if(obj && obj->type == _DT_VAR) {
|
} else if(obj && obj->type == _DT_VAR) {
|
||||||
@ -2912,6 +2949,8 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
|||||||
_exit:
|
_exit:
|
||||||
*l = ast;
|
*l = ast;
|
||||||
|
|
||||||
|
_stepped(s, ast);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2940,6 +2979,31 @@ _exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _skip_if_chunk(mb_interpreter_t* s, _ls_node_t** l) {
|
||||||
|
/* Skip current IF execution flow to next chunk */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
_ls_node_t* ast = 0;
|
||||||
|
_ls_node_t* tmp = 0;
|
||||||
|
_object_t* obj = 0;
|
||||||
|
|
||||||
|
mb_assert(s && l);
|
||||||
|
|
||||||
|
ast = *l;
|
||||||
|
mb_assert(ast && ast->prev);
|
||||||
|
do {
|
||||||
|
if(!ast) {
|
||||||
|
_handle_error_on_obj(s, SE_RN_SYNTAX, DON(tmp), MB_FUNC_ERR, _exit, result);
|
||||||
|
}
|
||||||
|
tmp = ast;
|
||||||
|
obj = (_object_t*)(ast->data);
|
||||||
|
*l = ast;
|
||||||
|
ast = ast->next;
|
||||||
|
} while(!_IS_FUNC(obj, _core_elseif) && !_IS_FUNC(obj, _core_if) && !_IS_FUNC(obj, _core_else));
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int _skip_struct(mb_interpreter_t* s, _ls_node_t** l, mb_func_t open_func, mb_func_t close_func) {
|
int _skip_struct(mb_interpreter_t* s, _ls_node_t** l, mb_func_t open_func, mb_func_t close_func) {
|
||||||
/* Skip current structure */
|
/* Skip current structure */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
@ -2960,10 +3024,9 @@ int _skip_struct(mb_interpreter_t* s, _ls_node_t** l, mb_func_t open_func, mb_fu
|
|||||||
obj_prev = (_object_t*)(ast->data);
|
obj_prev = (_object_t*)(ast->data);
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(obj->type == _DT_FUNC && obj->data.func->pointer == open_func) {
|
if(_IS_FUNC(obj, open_func)) {
|
||||||
++count;
|
++count;
|
||||||
} else if(obj->type == _DT_FUNC && obj->data.func->pointer == close_func &&
|
} else if(_IS_FUNC(obj, close_func) && _IS_EOS(obj_prev)) {
|
||||||
(obj_prev && obj_prev->type == _DT_EOS)) {
|
|
||||||
--count;
|
--count;
|
||||||
}
|
}
|
||||||
} while(count);
|
} while(count);
|
||||||
@ -3437,7 +3500,7 @@ int mb_attempt_open_bracket(struct mb_interpreter_t* s, void** l) {
|
|||||||
ast = (_ls_node_t*)(*l);
|
ast = (_ls_node_t*)(*l);
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_open_bracket)) {
|
if(!_IS_FUNC(obj, _core_open_bracket)) {
|
||||||
_handle_error_on_obj(s, SE_RN_OPEN_BRACKET_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_OPEN_BRACKET_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
@ -3461,7 +3524,7 @@ int mb_attempt_close_bracket(struct mb_interpreter_t* s, void** l) {
|
|||||||
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_close_bracket)) {
|
if(!_IS_FUNC(obj, _core_close_bracket)) {
|
||||||
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
@ -3483,7 +3546,7 @@ int mb_has_arg(struct mb_interpreter_t* s, void** l) {
|
|||||||
ast = (_ls_node_t*)(*l);
|
ast = (_ls_node_t*)(*l);
|
||||||
if(ast) {
|
if(ast) {
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_close_bracket) && obj->type != _DT_EOS)
|
if(!_IS_FUNC(obj, _core_close_bracket) && obj->type != _DT_EOS)
|
||||||
result = obj->data.integer;
|
result = obj->data.integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3637,7 +3700,7 @@ int mb_pop_value(struct mb_interpreter_t* s, void** l, mb_value_t* val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(running->no_eat_comma_mark < _NO_EAT_COMMA && (!inep || (inep && !(*inep)))) {
|
if(running->no_eat_comma_mark < _NO_EAT_COMMA && (!inep || (inep && !(*inep)))) {
|
||||||
if(ast && ((_object_t*)(ast->data))->type == _DT_SEP && ((_object_t*)(ast->data))->data.separator == ',')
|
if(ast && _IS_SEP(ast->data, ','))
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3884,6 +3947,58 @@ int mb_suspend(struct mb_interpreter_t* s, void** l) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mb_debug_get(struct mb_interpreter_t* s, const char* n, mb_value_t* val) {
|
||||||
|
/* Get the value of an identifier */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
_ls_node_t* v = 0;
|
||||||
|
_object_t* obj = 0;
|
||||||
|
|
||||||
|
mb_assert(s && n && val);
|
||||||
|
|
||||||
|
v = _ht_find(s->global_var_dict, (void*)n);
|
||||||
|
if(v) {
|
||||||
|
obj = (_object_t*)(v->data);
|
||||||
|
mb_assert(obj->type == _DT_VAR);
|
||||||
|
result = _internal_object_to_public_value(obj->data.variable->data, val);
|
||||||
|
} else {
|
||||||
|
val->type = MB_DT_NIL;
|
||||||
|
result = MB_DEBUG_ID_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mb_debug_set(struct mb_interpreter_t* s, const char* n, mb_value_t val) {
|
||||||
|
/* Set the value of an identifier */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
_ls_node_t* v = 0;
|
||||||
|
_object_t* obj = 0;
|
||||||
|
|
||||||
|
mb_assert(s && n);
|
||||||
|
|
||||||
|
v = _ht_find(s->global_var_dict, (void*)n);
|
||||||
|
if(v) {
|
||||||
|
obj = (_object_t*)(v->data);
|
||||||
|
mb_assert(obj->type == _DT_VAR);
|
||||||
|
result = _public_value_to_internal_object(&val, obj->data.variable->data);
|
||||||
|
} else {
|
||||||
|
result = MB_DEBUG_ID_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mb_debug_set_stepped_handler(struct mb_interpreter_t* s, mb_debug_stepped_handler_t h) {
|
||||||
|
/* Set a stepped handler to an interpreter instance */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
|
||||||
|
mb_assert(s);
|
||||||
|
|
||||||
|
s->debug_stepped_handler = h;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
mb_error_e mb_get_last_error(struct mb_interpreter_t* s) {
|
mb_error_e mb_get_last_error(struct mb_interpreter_t* s) {
|
||||||
/* Get last error information */
|
/* Get last error information */
|
||||||
mb_error_e result = SE_NO_ERR;
|
mb_error_e result = SE_NO_ERR;
|
||||||
@ -4501,7 +4616,7 @@ int _core_dim(mb_interpreter_t* s, void** l) {
|
|||||||
dummy.count += (unsigned int)val.integer;
|
dummy.count += (unsigned int)val.integer;
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
/* Comma? */
|
/* Comma? */
|
||||||
if(((_object_t*)(ast->data))->type == _DT_SEP && ((_object_t*)(ast->data))->data.separator == ',')
|
if(_IS_SEP(ast->data, ','))
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
}
|
}
|
||||||
/* Create or modify raw data */
|
/* Create or modify raw data */
|
||||||
@ -4527,6 +4642,7 @@ int _core_if(mb_interpreter_t* s, void** l) {
|
|||||||
_ls_node_t* ast = 0;
|
_ls_node_t* ast = 0;
|
||||||
_object_t* val = 0;
|
_object_t* val = 0;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
|
bool_t multi_line = false;
|
||||||
_running_context_t* running = 0;
|
_running_context_t* running = 0;
|
||||||
|
|
||||||
mb_assert(s && l);
|
mb_assert(s && l);
|
||||||
@ -4537,6 +4653,8 @@ int _core_if(mb_interpreter_t* s, void** l) {
|
|||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
|
|
||||||
val = (_object_t*)mb_malloc(sizeof(_object_t));
|
val = (_object_t*)mb_malloc(sizeof(_object_t));
|
||||||
|
|
||||||
|
_elseif:
|
||||||
memset(val, 0, sizeof(_object_t));
|
memset(val, 0, sizeof(_object_t));
|
||||||
result = _calc_expression(s, &ast, &val);
|
result = _calc_expression(s, &ast, &val);
|
||||||
if(result != MB_FUNC_OK)
|
if(result != MB_FUNC_OK)
|
||||||
@ -4545,10 +4663,13 @@ int _core_if(mb_interpreter_t* s, void** l) {
|
|||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(val->data.integer) {
|
if(val->data.integer) {
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_then)) {
|
if(!_IS_FUNC(obj, _core_then)) {
|
||||||
_handle_error_on_obj(s, SE_RN_INTEGER_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_INTEGER_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ast && ast->next && _IS_EOS(ast->next->data))
|
||||||
|
multi_line = true;
|
||||||
|
|
||||||
running->skip_to_eoi = _ls_back(running->sub_stack);
|
running->skip_to_eoi = _ls_back(running->sub_stack);
|
||||||
do {
|
do {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
@ -4557,7 +4678,16 @@ int _core_if(mb_interpreter_t* s, void** l) {
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
if(ast)
|
if(ast)
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
} while(ast && ((_object_t*)(ast->data))->type == _DT_SEP && ((_object_t*)(ast->data))->data.separator == ':');
|
} while(ast && (
|
||||||
|
(!multi_line && _IS_SEP(ast->data, ':')) || (
|
||||||
|
multi_line && ast->next && (
|
||||||
|
!_IS_FUNC(ast->next->data, _core_elseif) &&
|
||||||
|
!_IS_FUNC(ast->next->data, _core_else) &&
|
||||||
|
!_IS_FUNC(ast->next->data, _core_endif)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if(!ast)
|
if(!ast)
|
||||||
goto _exit;
|
goto _exit;
|
||||||
@ -4570,28 +4700,48 @@ int _core_if(mb_interpreter_t* s, void** l) {
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if(ast && ast->next && _IS_EOS(ast->next->data)) {
|
||||||
|
multi_line = true;
|
||||||
|
|
||||||
|
_skip_if_chunk(s, &ast);
|
||||||
|
}
|
||||||
|
if(multi_line && ast && _IS_FUNC(ast->data, _core_elseif)) {
|
||||||
|
if(ast) ast = ast->next;
|
||||||
|
|
||||||
|
goto _elseif;
|
||||||
|
}
|
||||||
|
|
||||||
result = _skip_to(s, &ast, _core_else, _DT_EOS);
|
result = _skip_to(s, &ast, _core_else, _DT_EOS);
|
||||||
if(result != MB_FUNC_OK)
|
if(result != MB_FUNC_OK)
|
||||||
goto _exit;
|
goto _exit;
|
||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(obj->type != _DT_EOS) {
|
if(obj->type != _DT_EOS) {
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_else)) {
|
if(!_IS_FUNC(obj, _core_else)) {
|
||||||
_handle_error_on_obj(s, SE_RN_ELSE_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_ELSE_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
|
while(_IS_EOS(ast->data))
|
||||||
|
ast = ast->next;
|
||||||
result = _execute_statement(s, &ast);
|
result = _execute_statement(s, &ast);
|
||||||
if(result != MB_FUNC_OK)
|
if(result != MB_FUNC_OK)
|
||||||
goto _exit;
|
goto _exit;
|
||||||
if(ast)
|
if(ast)
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
} while(ast && ((_object_t*)(ast->data))->type == _DT_SEP && ((_object_t*)(ast->data))->data.separator == ':');
|
} while(ast && (
|
||||||
|
(!multi_line && _IS_SEP(ast->data, ':')) ||
|
||||||
|
(multi_line && !_IS_FUNC(ast->next->data, _core_endif))
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
|
if(multi_line)
|
||||||
|
result = _skip_to(s, &ast, _core_endif, _DT_NIL);
|
||||||
|
|
||||||
_destroy_object(val, 0);
|
_destroy_object(val, 0);
|
||||||
|
|
||||||
*l = ast;
|
*l = ast;
|
||||||
@ -4611,6 +4761,18 @@ int _core_then(mb_interpreter_t* s, void** l) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _core_elseif(mb_interpreter_t* s, void** l) {
|
||||||
|
/* ELSEIF statement */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
mb_unrefvar(s);
|
||||||
|
mb_unrefvar(l);
|
||||||
|
|
||||||
|
mb_assert(0 && "Do nothing, impossible here");
|
||||||
|
_do_nothing;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int _core_else(mb_interpreter_t* s, void** l) {
|
int _core_else(mb_interpreter_t* s, void** l) {
|
||||||
/* ELSE statement */
|
/* ELSE statement */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
@ -4623,6 +4785,18 @@ int _core_else(mb_interpreter_t* s, void** l) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _core_endif(mb_interpreter_t* s, void** l) {
|
||||||
|
/* ENDIF statement */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
mb_unrefvar(s);
|
||||||
|
mb_unrefvar(l);
|
||||||
|
|
||||||
|
mb_assert(0 && "Do nothing, impossible here");
|
||||||
|
_do_nothing;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int _core_for(mb_interpreter_t* s, void** l) {
|
int _core_for(mb_interpreter_t* s, void** l) {
|
||||||
/* FOR statement */
|
/* FOR statement */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
@ -4660,7 +4834,7 @@ int _core_for(mb_interpreter_t* s, void** l) {
|
|||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_to)) {
|
if(!_IS_FUNC(obj, _core_to)) {
|
||||||
_handle_error_on_obj(s, SE_RN_TO_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_TO_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4678,7 +4852,7 @@ _to:
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_step)) {
|
if(!_IS_FUNC(obj, _core_step)) {
|
||||||
step_val = _OBJ_INT_UNIT;
|
step_val = _OBJ_INT_UNIT;
|
||||||
} else {
|
} else {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
@ -4702,7 +4876,7 @@ _to:
|
|||||||
} else {
|
} else {
|
||||||
/* Keep looping */
|
/* Keep looping */
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
while(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_next)) {
|
while(!_IS_FUNC(obj, _core_next)) {
|
||||||
result = _execute_statement(s, &ast);
|
result = _execute_statement(s, &ast);
|
||||||
if(result == MB_LOOP_CONTINUE) { /* NEXT */
|
if(result == MB_LOOP_CONTINUE) { /* NEXT */
|
||||||
if(!running->next_loop_var || running->next_loop_var == var_loop) { /* This loop */
|
if(!running->next_loop_var || running->next_loop_var == var_loop) { /* This loop */
|
||||||
@ -4826,7 +5000,7 @@ _loop_begin:
|
|||||||
if(loop_cond_ptr->data.integer) {
|
if(loop_cond_ptr->data.integer) {
|
||||||
/* Keep looping */
|
/* Keep looping */
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
while(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_wend)) {
|
while(!_IS_FUNC(obj, _core_wend)) {
|
||||||
result = _execute_statement(s, &ast);
|
result = _execute_statement(s, &ast);
|
||||||
if(result == MB_LOOP_BREAK) { /* EXIT */
|
if(result == MB_LOOP_BREAK) { /* EXIT */
|
||||||
if(_skip_struct(s, &ast, _core_while, _core_wend) != MB_FUNC_OK)
|
if(_skip_struct(s, &ast, _core_while, _core_wend) != MB_FUNC_OK)
|
||||||
@ -4885,7 +5059,7 @@ int _core_do(mb_interpreter_t* s, void** l) {
|
|||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_EOS)) {
|
if(!_IS_EOS(obj->type)) {
|
||||||
_handle_error_on_obj(s, SE_RN_SYNTAX, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_SYNTAX, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
@ -4898,7 +5072,7 @@ _loop_begin:
|
|||||||
ast = loop_begin_node;
|
ast = loop_begin_node;
|
||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
while(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_until)) {
|
while(!_IS_FUNC(obj, _core_until)) {
|
||||||
result = _execute_statement(s, &ast);
|
result = _execute_statement(s, &ast);
|
||||||
if(result == MB_LOOP_BREAK) { /* EXIT */
|
if(result == MB_LOOP_BREAK) { /* EXIT */
|
||||||
if(_skip_struct(s, &ast, _core_do, _core_until) != MB_FUNC_OK)
|
if(_skip_struct(s, &ast, _core_do, _core_until) != MB_FUNC_OK)
|
||||||
@ -4915,7 +5089,7 @@ _loop_begin:
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!(obj->type == _DT_FUNC && obj->data.func->pointer == _core_until)) {
|
if(!_IS_FUNC(obj, _core_until)) {
|
||||||
_handle_error_on_obj(s, SE_RN_UNTIL_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_UNTIL_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
@ -5885,13 +6059,13 @@ int _std_print(mb_interpreter_t* s, void** l) {
|
|||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(_is_print_terminal(s, obj))
|
if(_is_print_terminal(s, obj))
|
||||||
break;
|
break;
|
||||||
if(obj->type == _DT_SEP && (obj->data.separator == ',' || obj->data.separator == ';')) {
|
if(_IS_SEP(obj, ',') || _IS_SEP(obj, ';')) {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
} else {
|
} else {
|
||||||
_handle_error_on_obj(s, SE_RN_COMMA_OR_SEMICOLON_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_COMMA_OR_SEMICOLON_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
} while(ast && !(obj->type == _DT_SEP && obj->data.separator == ':') && (obj->type == _DT_SEP || !_is_expression_terminal(s, obj)));
|
} while(ast && !_IS_SEP(obj, ':') && (obj->type == _DT_SEP || !_is_expression_terminal(s, obj)));
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
--running->no_eat_comma_mark;
|
--running->no_eat_comma_mark;
|
||||||
|
8
core/my_basic.h
Executable file → Normal file
8
core/my_basic.h
Executable file → Normal file
@ -117,6 +117,7 @@ extern "C" {
|
|||||||
# define MB_LOOP_BREAK 5001
|
# define MB_LOOP_BREAK 5001
|
||||||
# define MB_LOOP_CONTINUE 5002
|
# define MB_LOOP_CONTINUE 5002
|
||||||
# define MB_SUB_RETURN 5101
|
# define MB_SUB_RETURN 5101
|
||||||
|
# define MB_DEBUG_ID_NOT_FOUND 7001
|
||||||
# define MB_EXTENDED_ABORT 9001
|
# define MB_EXTENDED_ABORT 9001
|
||||||
#endif /* MB_CODES */
|
#endif /* MB_CODES */
|
||||||
|
|
||||||
@ -212,8 +213,9 @@ typedef struct mb_value_t {
|
|||||||
mb_value_u value;
|
mb_value_u value;
|
||||||
} mb_value_t;
|
} mb_value_t;
|
||||||
|
|
||||||
typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, int, unsigned short, unsigned short, int);
|
|
||||||
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
|
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
|
||||||
|
typedef void (* mb_debug_stepped_handler_t)(struct mb_interpreter_t*, int, unsigned short, unsigned short);
|
||||||
|
typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, int, unsigned short, unsigned short, int);
|
||||||
typedef int (* mb_print_func_t)(const char*, ...);
|
typedef int (* mb_print_func_t)(const char*, ...);
|
||||||
typedef int (* mb_input_func_t)(char*, int);
|
typedef int (* mb_input_func_t)(char*, int);
|
||||||
|
|
||||||
@ -251,6 +253,10 @@ MBAPI int mb_load_file(struct mb_interpreter_t* s, const char* f);
|
|||||||
MBAPI int mb_run(struct mb_interpreter_t* s);
|
MBAPI int mb_run(struct mb_interpreter_t* s);
|
||||||
MBAPI int mb_suspend(struct mb_interpreter_t* s, void** l);
|
MBAPI int mb_suspend(struct mb_interpreter_t* s, void** l);
|
||||||
|
|
||||||
|
MBAPI int mb_debug_get(struct mb_interpreter_t* s, const char* n, mb_value_t* val);
|
||||||
|
MBAPI int mb_debug_set(struct mb_interpreter_t* s, const char* n, mb_value_t val);
|
||||||
|
MBAPI int mb_debug_set_stepped_handler(struct mb_interpreter_t* s, mb_debug_stepped_handler_t h);
|
||||||
|
|
||||||
MBAPI mb_error_e mb_get_last_error(struct mb_interpreter_t* s);
|
MBAPI mb_error_e mb_get_last_error(struct mb_interpreter_t* s);
|
||||||
MBAPI const char* mb_get_error_desc(mb_error_e err);
|
MBAPI const char* mb_get_error_desc(mb_error_e err);
|
||||||
MBAPI int mb_set_error_handler(struct mb_interpreter_t* s, mb_error_handler_t h);
|
MBAPI int mb_set_error_handler(struct mb_interpreter_t* s, mb_error_handler_t h);
|
||||||
|
BIN
output/my_basic.exe
Executable file → Normal file
BIN
output/my_basic.exe
Executable file → Normal file
Binary file not shown.
Binary file not shown.
BIN
resource/my_basic.aps
Executable file → Normal file
BIN
resource/my_basic.aps
Executable file → Normal file
Binary file not shown.
150
resource/my_basic.rc
Executable file → Normal file
150
resource/my_basic.rc
Executable file → Normal file
@ -1,113 +1,77 @@
|
|||||||
// Microsoft Visual C++ generated resource script.
|
|
||||||
//
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
#define APSTUDIO_READONLY_SYMBOLS
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
|
||||||
//
|
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
// 中文(中华人民共和国) resources
|
|
||||||
|
|
||||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
|
||||||
#ifdef _WIN32
|
# ifdef _WIN32
|
||||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||||
#pragma code_page(936)
|
# pragma code_page(936)
|
||||||
#endif //_WIN32
|
# endif //_WIN32
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
# ifdef APSTUDIO_INVOKED
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// TEXTINCLUDE
|
|
||||||
//
|
|
||||||
|
|
||||||
1 TEXTINCLUDE
|
1 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"resource.h\0"
|
"resource.h\0"
|
||||||
END
|
END
|
||||||
|
|
||||||
2 TEXTINCLUDE
|
2 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"#include ""windows.h""\r\n"
|
"#include ""windows.h""\r\n"
|
||||||
"\0"
|
"\0"
|
||||||
END
|
END
|
||||||
|
|
||||||
3 TEXTINCLUDE
|
3 TEXTINCLUDE
|
||||||
BEGIN
|
BEGIN
|
||||||
"\r\n"
|
"\r\n"
|
||||||
"\0"
|
"\0"
|
||||||
END
|
END
|
||||||
|
|
||||||
#endif // APSTUDIO_INVOKED
|
# endif
|
||||||
|
|
||||||
|
IDI_ICON_MAIN ICON "icon.ico"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
VS_VERSION_INFO VERSIONINFO
|
||||||
//
|
FILEVERSION 1,1,51,0
|
||||||
// Icon
|
PRODUCTVERSION 1,1,51,0
|
||||||
//
|
FILEFLAGSMASK 0x17L
|
||||||
|
# ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
# else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
# endif
|
||||||
|
FILEOS 0x4L
|
||||||
|
FILETYPE 0x1L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "080404b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Comments", "MY-BASIC"
|
||||||
|
VALUE "CompanyName", "W. Renxin"
|
||||||
|
VALUE "FileDescription", "MY-BASIC interpreter"
|
||||||
|
VALUE "FileVersion", "1, 1, 51, 0"
|
||||||
|
VALUE "InternalName", "my_basic"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 W. Renxin"
|
||||||
|
VALUE "LegalTrademarks", "MY-BASIC"
|
||||||
|
VALUE "OriginalFilename", "my_basic.exe"
|
||||||
|
VALUE "ProductName", "MY-BASIC"
|
||||||
|
VALUE "ProductVersion", "1, 1, 51, 0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x804, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
// Icon with lowest ID value placed first to ensure application icon
|
|
||||||
// remains consistent on all systems.
|
|
||||||
IDI_ICON_MAIN ICON "icon.ico"
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Version
|
|
||||||
//
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION 1,0,0,50
|
|
||||||
PRODUCTVERSION 1,0,0,50
|
|
||||||
FILEFLAGSMASK 0x17L
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS 0x1L
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
#endif
|
#endif
|
||||||
FILEOS 0x4L
|
|
||||||
FILETYPE 0x1L
|
|
||||||
FILESUBTYPE 0x0L
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "080404b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Comments", "MY-BASIC"
|
|
||||||
VALUE "CompanyName", "W. Renxin"
|
|
||||||
VALUE "FileDescription", "MY-BASIC interpreter"
|
|
||||||
VALUE "FileVersion", "1, 0, 0, 50"
|
|
||||||
VALUE "InternalName", "my_basic"
|
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 W. Renxin"
|
|
||||||
VALUE "LegalTrademarks", "MY-BASIC"
|
|
||||||
VALUE "OriginalFilename", "my_basic.exe"
|
|
||||||
VALUE "ProductName", "MY-BASIC"
|
|
||||||
VALUE "ProductVersion", "1, 0, 0, 50"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x804, 1200
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
#endif // 中文(中华人民共和国) resources
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef APSTUDIO_INVOKED
|
#ifndef APSTUDIO_INVOKED
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
#endif // not APSTUDIO_INVOKED
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
0
resource/resource.h
Executable file → Normal file
0
resource/resource.h
Executable file → Normal file
17
shell/main.c
Executable file → Normal file
17
shell/main.c
Executable file → Normal file
@ -197,6 +197,13 @@ static int beep(struct mb_interpreter_t* s, void** l) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _on_stepped(struct mb_interpreter_t* s, int p, unsigned short row, unsigned short col) {
|
||||||
|
mb_unrefvar(s);
|
||||||
|
mb_unrefvar(p);
|
||||||
|
mb_unrefvar(row);
|
||||||
|
mb_unrefvar(col);
|
||||||
|
}
|
||||||
|
|
||||||
static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
|
static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
|
||||||
mb_unrefvar(s);
|
mb_unrefvar(s);
|
||||||
mb_unrefvar(p);
|
mb_unrefvar(p);
|
||||||
@ -211,6 +218,7 @@ static void _on_startup(void) {
|
|||||||
mb_init();
|
mb_init();
|
||||||
|
|
||||||
mb_open(&bas);
|
mb_open(&bas);
|
||||||
|
mb_debug_set_stepped_handler(bas, _on_stepped);
|
||||||
mb_set_error_handler(bas, _on_error);
|
mb_set_error_handler(bas, _on_error);
|
||||||
|
|
||||||
mb_reg_fun(bas, beep);
|
mb_reg_fun(bas, beep);
|
||||||
@ -382,10 +390,11 @@ static int _do_line(void) {
|
|||||||
} else if(_str_eq(line, "NEW")) {
|
} else if(_str_eq(line, "NEW")) {
|
||||||
result = _new_program();
|
result = _new_program();
|
||||||
} else if(_str_eq(line, "RUN")) {
|
} else if(_str_eq(line, "RUN")) {
|
||||||
char* txt = _get_code(c);
|
int i = 0;
|
||||||
result = mb_reset(&bas, false);
|
mb_assert(c);
|
||||||
result = mb_load_string(bas, txt);
|
result = mb_reset(&bas, false);
|
||||||
free(txt);
|
for(i = 0; i < c->count; ++i)
|
||||||
|
mb_load_string(bas, c->lines[i]);
|
||||||
result = mb_run(bas);
|
result = mb_run(bas);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
} else if(_str_eq(line, "BYE")) {
|
} else if(_str_eq(line, "BYE")) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user