+added multi-line statement support.

This commit is contained in:
Wang Renxin 2017-04-06 11:30:46 +08:00
parent 59e758c7f0
commit 4079cfd7d1
2 changed files with 109 additions and 16 deletions

View File

@ -1,3 +1,6 @@
Apr. 6 2017
Added multi-line statement support
Apr. 5 2017
Fixed an infinity loop bug with lambda
Fixed a wrong hash bug with pointer, which may cause crash on some 64bit systems

View File

@ -96,18 +96,18 @@ extern "C" {
/** Macros */
/* Version information */
#define _VER_MAJOR 1
#define _VER_MINOR 2
#define _VER_REVISION 0
#define _VER_SUFFIX
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
#define _MB_STRINGIZE(A) _MB_MAKE_STRINGIZE(A)
#define _MB_MAKE_STRINGIZE(A) #A
#if _VER_REVISION == 0
# define _MB_VERSION_STRING _MB_STRINGIZE(_VER_MAJOR._VER_MINOR _VER_SUFFIX)
#else /* _VER_REVISION == 0 */
# define _MB_VERSION_STRING _MB_STRINGIZE(_VER_MAJOR._VER_MINOR._VER_REVISION _VER_SUFFIX)
#endif /* _VER_REVISION == 0 */
#define MB_VER_MAJOR 1
#define MB_VER_MINOR 2
#define MB_VER_REVISION 0
#define MB_VER_SUFFIX
#define MB_VERSION ((MB_VER_MAJOR * 0x01000000) + (MB_VER_MINOR * 0x00010000) + (MB_VER_REVISION))
#define MB_MAKE_STRINGIZE(A) #A
#define MB_STRINGIZE(A) MB_MAKE_STRINGIZE(A)
#if MB_VER_REVISION == 0
# define MB_VERSION_STRING MB_STRINGIZE(MB_VER_MAJOR.MB_VER_MINOR MB_VER_SUFFIX)
#else /* MB_VER_REVISION == 0 */
# define MB_VERSION_STRING MB_STRINGIZE(MB_VER_MAJOR.MB_VER_MINOR.MB_VER_REVISION MB_VER_SUFFIX)
#endif /* MB_VER_REVISION == 0 */
/* Define as 1 to create hash table nodes lazily, 0 obligingly */
#define _LAZY_HASH_TABLE 1
@ -118,6 +118,9 @@ extern "C" {
/* Define as 1 to use a comma to PRINT a new line, 0 to use a semicolon */
#define _COMMA_AS_NEWLINE 0
/* Define as 1 to enable multiline statement */
#define _MULTILINE_STATEMENT 1
#define _NO_EAT_COMMA 2
/* Hash table size */
@ -846,6 +849,9 @@ typedef struct mb_interpreter_t {
#ifdef MB_ENABLE_STACK_TRACE
_ls_node_t* stack_frames;
#endif /* MB_ENABLE_STACK_TRACE */
#ifdef _MULTILINE_STATEMENT
_ls_node_t* multiline_enabled;
#endif /* _MULTILINE_STATEMENT */
/** Error handling */
bool_t handled_error;
mb_error_e last_error;
@ -1841,6 +1847,7 @@ static int _execute_ranged_for_loop(mb_interpreter_t* s, _ls_node_t** l, _var_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 bool_t _multiline_statement(mb_interpreter_t* s);
static _running_context_t* _create_running_context(bool_t create_var_dict);
static _parsing_context_t* _reset_parsing_context(_parsing_context_t* context);
@ -4068,6 +4075,16 @@ static int _pop_arg(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigne
_ls_node_t* ast = *l;
mb_make_nil(*arg);
#ifdef _MULTILINE_STATEMENT
if(_multiline_statement(s)) {
_object_t* obj = 0;
obj = (_object_t*)ast->data;
while(obj && obj->type == _DT_EOS) {
ast = ast->next;
obj = (_object_t*)ast->data;
}
}
#endif /* _MULTILINE_STATEMENT */
if(ast && ast->data && _IS_FUNC(ast->data, _core_args)) {
if(args) {
_object_t* obj = (_object_t*)_ls_popfront(args);
@ -10680,6 +10697,20 @@ _exit:
return result;
}
/* Check whether multiline statement is allowed */
static bool_t _multiline_statement(mb_interpreter_t* s) {
#ifdef _MULTILINE_STATEMENT
if(_ls_empty(s->multiline_enabled))
return false;
return (bool_t)(intptr_t)_ls_back(s->multiline_enabled)->data;
#else /* _MULTILINE_STATEMENT */
mb_unrefvar(s);
return false;
#endif /* _MULTILINE_STATEMENT */
}
/* Create a running context */
static _running_context_t* _create_running_context(bool_t create_var_dict) {
_running_context_t* result = 0;
@ -11059,12 +11090,12 @@ static int _close_coll_lib(mb_interpreter_t* s) {
/* Get the version number of this MY-BASIC system */
unsigned long mb_ver(void) {
return _MB_VERSION;
return MB_VERSION;
}
/* Get the version text of this MY-BASIC system */
const char* mb_ver_string(void) {
return _MB_VERSION_STRING;
return MB_VERSION_STRING;
}
/* Initialize the MY-BASIC system */
@ -11172,6 +11203,9 @@ int mb_open(struct mb_interpreter_t** s) {
#ifdef MB_ENABLE_STACK_TRACE
(*s)->stack_frames = _ls_create();
#endif /* MB_ENABLE_STACK_TRACE */
#ifdef _MULTILINE_STATEMENT
(*s)->multiline_enabled = _ls_create();
#endif /* _MULTILINE_STATEMENT */
(*s)->sub_stack = _ls_create();
@ -11215,6 +11249,9 @@ int mb_close(struct mb_interpreter_t** s) {
#ifdef MB_ENABLE_STACK_TRACE
_ls_destroy((*s)->stack_frames);
#endif /* MB_ENABLE_STACK_TRACE */
#ifdef _MULTILINE_STATEMENT
_ls_destroy((*s)->multiline_enabled);
#endif /* _MULTILINE_STATEMENT */
_tidy_scope_chain(*s);
_dispose_scope_chain(*s);
@ -11291,6 +11328,9 @@ int mb_reset(struct mb_interpreter_t** s, bool_t clrf) {
#ifdef MB_ENABLE_STACK_TRACE
_ls_clear((*s)->stack_frames);
#endif /* MB_ENABLE_STACK_TRACE */
#ifdef _MULTILINE_STATEMENT
_ls_clear((*s)->multiline_enabled);
#endif /* _MULTILINE_STATEMENT */
_clear_scope_chain(*s);
@ -11396,6 +11436,9 @@ int mb_attempt_func_begin(struct mb_interpreter_t* s, void** l) {
goto _exit;
}
#ifdef _MULTILINE_STATEMENT
_ls_pushback(s->multiline_enabled, (void*)(intptr_t)false);
#endif /* _MULTILINE_STATEMENT */
ast = (_ls_node_t*)*l;
obj = (_object_t*)ast->data;
if(!(obj->type == _DT_FUNC)) {
@ -11415,10 +11458,14 @@ _exit:
int mb_attempt_func_end(struct mb_interpreter_t* s, void** l) {
int result = MB_FUNC_OK;
if(!s || !l)
if(!s || !l) {
result = MB_FUNC_ERR;
else
} else {
#ifdef _MULTILINE_STATEMENT
_ls_popback(s->multiline_enabled);
#endif /* _MULTILINE_STATEMENT */
--s->no_eat_comma_mark;
}
return result;
}
@ -11436,8 +11483,16 @@ int mb_attempt_open_bracket(struct mb_interpreter_t* s, void** l) {
}
ast = (_ls_node_t*)*l;
#ifdef _MULTILINE_STATEMENT
_ls_pushback(s->multiline_enabled, (void*)(intptr_t)true);
do {
ast = ast->next;
obj = (_object_t*)ast->data;
} while(obj && obj->type == _DT_EOS);
#else /* _MULTILINE_STATEMENT */
ast = ast->next;
obj = (_object_t*)ast->data;
#endif /* _MULTILINE_STATEMENT */
if(!_IS_FUNC(obj, _core_open_bracket)) {
_handle_error_on_obj(s, SE_RN_OPEN_BRACKET_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
}
@ -11465,7 +11520,16 @@ int mb_attempt_close_bracket(struct mb_interpreter_t* s, void** l) {
if(!ast) {
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
}
#ifdef _MULTILINE_STATEMENT
_ls_popback(s->multiline_enabled);
obj = (_object_t*)ast->data;
while(obj && obj->type == _DT_EOS) {
ast = ast->next;
obj = (_object_t*)ast->data;
}
#else /* _MULTILINE_STATEMENT */
obj = (_object_t*)ast->data;
#endif /* _MULTILINE_STATEMENT */
if(!_IS_FUNC(obj, _core_close_bracket)) {
_handle_error_on_obj(s, SE_RN_CLOSE_BRACKET_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
}
@ -11488,7 +11552,19 @@ int mb_has_arg(struct mb_interpreter_t* s, void** l) {
ast = (_ls_node_t*)*l;
if(ast) {
#ifdef _MULTILINE_STATEMENT
if(_multiline_statement(s)) {
obj = (_object_t*)ast->data;
while(obj && obj->type == _DT_EOS) {
ast = ast->next;
obj = (_object_t*)ast->data;
}
} else {
obj = (_object_t*)ast->data;
}
#else /* _MULTILINE_STATEMENT */
obj = (_object_t*)ast->data;
#endif /* _MULTILINE_STATEMENT */
if(!_IS_FUNC(obj, _core_close_bracket) && obj->type != _DT_EOS)
result = obj->type != _DT_SEP && obj->type != _DT_EOS;
}
@ -11670,6 +11746,16 @@ int mb_pop_value(struct mb_interpreter_t* s, void** l, mb_value_t* val) {
}
#endif /* MB_ENABLE_USERTYPE_REF */
ast = (_ls_node_t*)*l;
#ifdef _MULTILINE_STATEMENT
if(_multiline_statement(s)) {
_object_t* obj = 0;
obj = (_object_t*)ast->data;
while(obj && obj->type == _DT_EOS) {
ast = ast->next;
obj = (_object_t*)ast->data;
}
}
#endif /* _MULTILINE_STATEMENT */
result = _calc_expression(s, &ast, &val_ptr);
if(result != MB_FUNC_OK)
goto _exit;
@ -13007,6 +13093,10 @@ int mb_run(struct mb_interpreter_t* s) {
#endif /* MB_ENABLE_CLASS */
s->last_routine = 0;
#ifdef _MULTILINE_STATEMENT
_ls_clear(s->multiline_enabled);
#endif /* _MULTILINE_STATEMENT */
mb_assert(!s->no_eat_comma_mark);
while(s->running_context->prev)
s->running_context = s->running_context->prev;