+added array manipulation ability to script, it's able to assign an array to a variable or use it as a scripting interface argument; +added recursive sub routine support; *fixed a wrong argument detection bug in mb_has_arg.
This commit is contained in:
parent
b4d2a05d4e
commit
faae9b4cdc
5
HISTORY
5
HISTORY
@ -1,3 +1,8 @@
|
|||||||
|
Sep. 20 2015
|
||||||
|
Added array manipulation ability to script, it's able to assign an array to a variable or use it as a scripting interface argument
|
||||||
|
Added recursive sub routine support
|
||||||
|
Fixed a wrong argument detection bug in mb_has_arg
|
||||||
|
|
||||||
Sep. 18 2015
|
Sep. 18 2015
|
||||||
Fixed a float number parsing bug, thanks to Cybermonkey342 for pointing it out
|
Fixed a float number parsing bug, thanks to Cybermonkey342 for pointing it out
|
||||||
Added directly expression evaluation shell command
|
Added directly expression evaluation shell command
|
||||||
|
133
core/my_basic.c
133
core/my_basic.c
@ -79,7 +79,7 @@ extern "C" {
|
|||||||
/** Macros */
|
/** Macros */
|
||||||
#define _VER_MAJOR 1
|
#define _VER_MAJOR 1
|
||||||
#define _VER_MINOR 1
|
#define _VER_MINOR 1
|
||||||
#define _VER_REVISION 71
|
#define _VER_REVISION 72
|
||||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||||
|
|
||||||
/* Uncomment the line below to treat warning as error */
|
/* Uncomment the line below to treat warning as error */
|
||||||
@ -375,11 +375,15 @@ typedef struct _parsing_context_t {
|
|||||||
|
|
||||||
/* Running context */
|
/* Running context */
|
||||||
#define _SCOPE_META_ROOT 'ROOT'
|
#define _SCOPE_META_ROOT 'ROOT'
|
||||||
|
#define _SCOPE_META_REF 'REFS'
|
||||||
|
|
||||||
typedef struct _running_context_t {
|
typedef struct _running_context_t {
|
||||||
struct _running_context_t* prev;
|
struct _running_context_t* prev;
|
||||||
unsigned meta;
|
unsigned meta;
|
||||||
|
union {
|
||||||
_ht_node_t* var_dict;
|
_ht_node_t* var_dict;
|
||||||
|
struct _running_context_t* ref;
|
||||||
|
} data;
|
||||||
_var_t* next_loop_var;
|
_var_t* next_loop_var;
|
||||||
mb_value_t intermediate_value;
|
mb_value_t intermediate_value;
|
||||||
} _running_context_t;
|
} _running_context_t;
|
||||||
@ -392,6 +396,7 @@ typedef struct _tuple3_t {
|
|||||||
} _tuple3_t;
|
} _tuple3_t;
|
||||||
|
|
||||||
/* Interpreter tag */
|
/* Interpreter tag */
|
||||||
|
#define _JMP_NIL 0x00
|
||||||
#define _JMP_INS 0x01
|
#define _JMP_INS 0x01
|
||||||
#define _JMP_STR 0x02
|
#define _JMP_STR 0x02
|
||||||
|
|
||||||
@ -829,6 +834,8 @@ static void _begin_routine(mb_interpreter_t* s);
|
|||||||
static void _end_routine(mb_interpreter_t* s);
|
static void _end_routine(mb_interpreter_t* s);
|
||||||
static void _begin_routine_parameter_list(mb_interpreter_t* s);
|
static void _begin_routine_parameter_list(mb_interpreter_t* s);
|
||||||
static void _end_routine_parameter_list(mb_interpreter_t* s);
|
static void _end_routine_parameter_list(mb_interpreter_t* s);
|
||||||
|
static _running_context_t* _find_scope(mb_interpreter_t* s, _running_context_t* p);
|
||||||
|
static _running_context_t* _reference_scope(mb_interpreter_t* s, _running_context_t* p);
|
||||||
static _running_context_t* _push_scope(mb_interpreter_t* s, _running_context_t* p);
|
static _running_context_t* _push_scope(mb_interpreter_t* s, _running_context_t* p);
|
||||||
static _running_context_t* _pop_scope(mb_interpreter_t* s);
|
static _running_context_t* _pop_scope(mb_interpreter_t* s);
|
||||||
static _running_context_t* _get_scope_for_add_routine(mb_interpreter_t* s);
|
static _running_context_t* _get_scope_for_add_routine(mb_interpreter_t* s);
|
||||||
@ -1789,6 +1796,10 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(c->type == _DT_ARRAY) {
|
if(c->type == _DT_ARRAY) {
|
||||||
|
if(ast && !_IS_FUNC(((_object_t*)(ast->data)), _core_open_bracket)) {
|
||||||
|
_ls_pushback(opnd, c);
|
||||||
|
f++;
|
||||||
|
} else {
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
result = _get_array_index(s, &ast, &arr_idx);
|
result = _get_array_index(s, &ast, &arr_idx);
|
||||||
if(result != MB_FUNC_OK) {
|
if(result != MB_FUNC_OK) {
|
||||||
@ -1817,6 +1828,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
}
|
}
|
||||||
_ls_pushback(opnd, arr_elem);
|
_ls_pushback(opnd, arr_elem);
|
||||||
f++;
|
f++;
|
||||||
|
}
|
||||||
} else if(c->type == _DT_FUNC) {
|
} else if(c->type == _DT_FUNC) {
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
result = (c->data.func->pointer)(s, (void**)(&ast));
|
result = (c->data.func->pointer)(s, (void**)(&ast));
|
||||||
@ -2046,6 +2058,7 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
result = _execute_statement(s, l);
|
result = _execute_statement(s, l);
|
||||||
|
ast = (_ls_node_t*)(*l);
|
||||||
if(result == MB_SUB_RETURN) {
|
if(result == MB_SUB_RETURN) {
|
||||||
result = MB_FUNC_OK;
|
result = MB_FUNC_OK;
|
||||||
|
|
||||||
@ -2349,7 +2362,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
memcpy(&tmp.array->type, value, sizeof(tmp.array->type));
|
memcpy(&tmp.array->type, value, sizeof(tmp.array->type));
|
||||||
(*obj)->data.array = tmp.array;
|
(*obj)->data.array = tmp.array;
|
||||||
|
|
||||||
ul = _ht_set_or_insert(running->var_dict, sym, *obj);
|
ul = _ht_set_or_insert(running->data.var_dict, sym, *obj);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
|
|
||||||
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
||||||
@ -2377,7 +2390,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
_push_scope(s, tmp.instance->scope);
|
_push_scope(s, tmp.instance->scope);
|
||||||
(*obj)->data.instance = tmp.instance;
|
(*obj)->data.instance = tmp.instance;
|
||||||
|
|
||||||
ul = _ht_set_or_insert(running->var_dict, sym, *obj);
|
ul = _ht_set_or_insert(running->data.var_dict, sym, *obj);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
|
|
||||||
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
||||||
@ -2407,7 +2420,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
(*obj)->data.routine = tmp.routine;
|
(*obj)->data.routine = tmp.routine;
|
||||||
|
|
||||||
tba = _get_scope_for_add_routine(s);
|
tba = _get_scope_for_add_routine(s);
|
||||||
ul = _ht_set_or_insert(tba->var_dict, sym, *obj);
|
ul = _ht_set_or_insert(tba->data.var_dict, sym, *obj);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
if(tba != _OUTTER_SCOPE(running))
|
if(tba != _OUTTER_SCOPE(running))
|
||||||
_pop_scope(s);
|
_pop_scope(s);
|
||||||
@ -2422,7 +2435,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
break;
|
break;
|
||||||
case _DT_VAR:
|
case _DT_VAR:
|
||||||
if(context->routine_params_state)
|
if(context->routine_params_state)
|
||||||
glbsyminscope = _ht_find(running->var_dict, sym);
|
glbsyminscope = _ht_find(running->data.var_dict, sym);
|
||||||
else
|
else
|
||||||
glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
|
glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
|
||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
||||||
@ -2439,7 +2452,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
tmp.var->data->data.integer = 0;
|
tmp.var->data->data.integer = 0;
|
||||||
(*obj)->data.variable = tmp.var;
|
(*obj)->data.variable = tmp.var;
|
||||||
|
|
||||||
ul = _ht_set_or_insert(running->var_dict, sym, *obj);
|
ul = _ht_set_or_insert(running->data.var_dict, sym, *obj);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
|
|
||||||
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
||||||
@ -2463,7 +2476,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
*asgn = &(tmp.label->node);
|
*asgn = &(tmp.label->node);
|
||||||
(*obj)->data.label = tmp.label;
|
(*obj)->data.label = tmp.label;
|
||||||
|
|
||||||
ul = _ht_set_or_insert(running->var_dict, sym, *obj);
|
ul = _ht_set_or_insert(running->data.var_dict, sym, *obj);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
|
|
||||||
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
|
||||||
@ -2591,14 +2604,14 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
|
|||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
||||||
tmp.obj = (_object_t*)(glbsyminscope->data);
|
tmp.obj = (_object_t*)(glbsyminscope->data);
|
||||||
if(!tmp.obj->ref) {
|
if(!tmp.obj->ref) {
|
||||||
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string);
|
_ht_remove(running->data.var_dict, sym, _ls_cmp_extra_string);
|
||||||
_dispose_object(tmp.obj);
|
_dispose_object(tmp.obj);
|
||||||
}
|
}
|
||||||
tmp.obj->type = _DT_CLASS;
|
tmp.obj->type = _DT_CLASS;
|
||||||
tmp.obj->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
|
tmp.obj->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
|
||||||
_init_class(s, tmp.obj->data.instance, sym);
|
_init_class(s, tmp.obj->data.instance, sym);
|
||||||
_init_class(s, tmp.obj->data.instance, sym);
|
_init_class(s, tmp.obj->data.instance, sym);
|
||||||
_ht_set_or_insert(running->var_dict, sym, tmp.obj);
|
_ht_set_or_insert(running->data.var_dict, sym, tmp.obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _DT_CLASS;
|
result = _DT_CLASS;
|
||||||
@ -2630,14 +2643,14 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
|
|||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
||||||
tmp.obj = (_object_t*)(glbsyminscope->data);
|
tmp.obj = (_object_t*)(glbsyminscope->data);
|
||||||
if(!tmp.obj->ref) {
|
if(!tmp.obj->ref) {
|
||||||
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string);
|
_ht_remove(running->data.var_dict, sym, _ls_cmp_extra_string);
|
||||||
_dispose_object(tmp.obj);
|
_dispose_object(tmp.obj);
|
||||||
}
|
}
|
||||||
tmp.obj->type = _DT_ROUTINE;
|
tmp.obj->type = _DT_ROUTINE;
|
||||||
tmp.obj->data.routine = (_routine_t*)mb_malloc(sizeof(_routine_t));
|
tmp.obj->data.routine = (_routine_t*)mb_malloc(sizeof(_routine_t));
|
||||||
_init_routine(s, tmp.obj->data.routine, sym);
|
_init_routine(s, tmp.obj->data.routine, sym);
|
||||||
_push_scope(s, tmp.obj->data.routine->scope);
|
_push_scope(s, tmp.obj->data.routine->scope);
|
||||||
_ht_set_or_insert(running->var_dict, sym, tmp.obj);
|
_ht_set_or_insert(running->data.var_dict, sym, tmp.obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _DT_ROUTINE;
|
result = _DT_ROUTINE;
|
||||||
@ -3219,7 +3232,7 @@ void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
|
|||||||
instance->name = n;
|
instance->name = n;
|
||||||
instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
||||||
memset(instance->scope, 0, sizeof(_running_context_t));
|
memset(instance->scope, 0, sizeof(_running_context_t));
|
||||||
instance->scope->var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
instance->scope->data.var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _begin_class(mb_interpreter_t* s) {
|
void _begin_class(mb_interpreter_t* s) {
|
||||||
@ -3254,7 +3267,7 @@ void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
|
|||||||
routine->name = n;
|
routine->name = n;
|
||||||
routine->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
routine->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
||||||
memset(routine->scope, 0, sizeof(_running_context_t));
|
memset(routine->scope, 0, sizeof(_running_context_t));
|
||||||
routine->scope->var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
routine->scope->data.var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _begin_routine(mb_interpreter_t* s) {
|
void _begin_routine(mb_interpreter_t* s) {
|
||||||
@ -3297,10 +3310,43 @@ void _end_routine_parameter_list(mb_interpreter_t* s) {
|
|||||||
context->routine_params_state--;
|
context->routine_params_state--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_running_context_t* _find_scope(mb_interpreter_t* s, _running_context_t* p) {
|
||||||
|
/* Find a scope in a scope chain */
|
||||||
|
_running_context_t* running = 0;
|
||||||
|
|
||||||
|
mb_assert(s);
|
||||||
|
|
||||||
|
running = s->running_context;
|
||||||
|
while(running) {
|
||||||
|
if(running == p)
|
||||||
|
break;
|
||||||
|
|
||||||
|
running = running->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return running;
|
||||||
|
}
|
||||||
|
|
||||||
|
_running_context_t* _reference_scope(mb_interpreter_t* s, _running_context_t* p) {
|
||||||
|
/* Create a scope reference to an exist one */
|
||||||
|
_running_context_t* result = 0;
|
||||||
|
|
||||||
|
mb_assert(s && p);
|
||||||
|
|
||||||
|
result = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
||||||
|
memset(result, 0, sizeof(_running_context_t));
|
||||||
|
result->meta = _SCOPE_META_REF;
|
||||||
|
result->data.ref = p;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
_running_context_t* _push_scope(mb_interpreter_t* s, _running_context_t* p) {
|
_running_context_t* _push_scope(mb_interpreter_t* s, _running_context_t* p) {
|
||||||
/* Push encapsule a scope */
|
/* Push encapsule a scope */
|
||||||
mb_assert(s);
|
mb_assert(s);
|
||||||
|
|
||||||
|
if(_find_scope(s, p))
|
||||||
|
p = _reference_scope(s, p);
|
||||||
p->prev = s->running_context;
|
p->prev = s->running_context;
|
||||||
s->running_context = p;
|
s->running_context = p;
|
||||||
|
|
||||||
@ -3316,6 +3362,9 @@ _running_context_t* _pop_scope(mb_interpreter_t* s) {
|
|||||||
running = s->running_context;
|
running = s->running_context;
|
||||||
s->running_context = running->prev;
|
s->running_context = running->prev;
|
||||||
running->prev = 0;
|
running->prev = 0;
|
||||||
|
if(running->meta == _SCOPE_META_REF) {
|
||||||
|
mb_free(running);
|
||||||
|
}
|
||||||
|
|
||||||
return s->running_context;
|
return s->running_context;
|
||||||
}
|
}
|
||||||
@ -3328,7 +3377,7 @@ _running_context_t* _get_scope_for_add_routine(mb_interpreter_t* s) {
|
|||||||
|
|
||||||
running = s->running_context;
|
running = s->running_context;
|
||||||
while(running) {
|
while(running) {
|
||||||
if(running->meta)
|
if(running->meta == _SCOPE_META_ROOT)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
running = running->prev;
|
running = running->prev;
|
||||||
@ -3341,6 +3390,7 @@ _ls_node_t* _search_var_in_scope_chain(mb_interpreter_t* s, _running_context_t*
|
|||||||
/* Try to search a variable in a scope chain */
|
/* Try to search a variable in a scope chain */
|
||||||
_ls_node_t* result = 0;
|
_ls_node_t* result = 0;
|
||||||
_running_context_t* running = 0;
|
_running_context_t* running = 0;
|
||||||
|
_ht_node_t* var_dict = 0;
|
||||||
|
|
||||||
mb_assert(s && n);
|
mb_assert(s && n);
|
||||||
|
|
||||||
@ -3349,7 +3399,8 @@ _ls_node_t* _search_var_in_scope_chain(mb_interpreter_t* s, _running_context_t*
|
|||||||
else
|
else
|
||||||
running = s->running_context;
|
running = s->running_context;
|
||||||
while(running && !result) {
|
while(running && !result) {
|
||||||
result = _ht_find(running->var_dict, n);
|
var_dict = running->meta == _SCOPE_META_REF ? running->data.ref->data.var_dict : running->data.var_dict;
|
||||||
|
result = _ht_find(var_dict, n);
|
||||||
if(result)
|
if(result)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3407,8 +3458,8 @@ int _dispose_object(_object_t* obj) {
|
|||||||
case _DT_CLASS:
|
case _DT_CLASS:
|
||||||
if(!obj->ref) {
|
if(!obj->ref) {
|
||||||
safe_free(obj->data.instance->name);
|
safe_free(obj->data.instance->name);
|
||||||
_ht_foreach(obj->data.instance->scope->var_dict, _destroy_object);
|
_ht_foreach(obj->data.instance->scope->data.var_dict, _destroy_object);
|
||||||
_ht_destroy(obj->data.instance->scope->var_dict);
|
_ht_destroy(obj->data.instance->scope->data.var_dict);
|
||||||
safe_free(obj->data.instance->scope);
|
safe_free(obj->data.instance->scope);
|
||||||
safe_free(obj->data.instance);
|
safe_free(obj->data.instance);
|
||||||
}
|
}
|
||||||
@ -3417,8 +3468,8 @@ int _dispose_object(_object_t* obj) {
|
|||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
if(!obj->ref) {
|
if(!obj->ref) {
|
||||||
safe_free(obj->data.routine->name);
|
safe_free(obj->data.routine->name);
|
||||||
_ht_foreach(obj->data.routine->scope->var_dict, _destroy_object);
|
_ht_foreach(obj->data.routine->scope->data.var_dict, _destroy_object);
|
||||||
_ht_destroy(obj->data.routine->scope->var_dict);
|
_ht_destroy(obj->data.routine->scope->data.var_dict);
|
||||||
safe_free(obj->data.routine->scope);
|
safe_free(obj->data.routine->scope);
|
||||||
if(obj->data.routine->parameters)
|
if(obj->data.routine->parameters)
|
||||||
_ls_destroy(obj->data.routine->parameters);
|
_ls_destroy(obj->data.routine->parameters);
|
||||||
@ -3732,11 +3783,13 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
|||||||
_ls_node_t* ast = 0;
|
_ls_node_t* ast = 0;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
_running_context_t* running = 0;
|
_running_context_t* running = 0;
|
||||||
|
_ls_node_t* sub_stack = 0;
|
||||||
bool_t skip_to_eoi = true;
|
bool_t skip_to_eoi = true;
|
||||||
|
|
||||||
mb_assert(s && l);
|
mb_assert(s && l);
|
||||||
|
|
||||||
running = s->running_context;
|
running = s->running_context;
|
||||||
|
sub_stack = s->sub_stack;
|
||||||
|
|
||||||
ast = *l;
|
ast = *l;
|
||||||
|
|
||||||
@ -3789,7 +3842,11 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
|||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
} else if(obj && obj->type == _DT_VAR) {
|
} else if(obj && obj->type == _DT_VAR) {
|
||||||
_handle_error_on_obj(s, SE_RN_COLON_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_COLON_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
} else if((obj && obj->type != _DT_FUNC) || (obj && obj->type == _DT_FUNC && (_is_operator(obj->data.func->pointer) || _is_flow(obj->data.func->pointer)))) {
|
} else if(_IS_FUNC(obj, _core_enddef)) {
|
||||||
|
ast = (_ls_node_t*)_ls_popback(sub_stack);
|
||||||
|
} else if(obj && obj->type == _DT_FUNC && (_is_operator(obj->data.func->pointer) || _is_flow(obj->data.func->pointer))) {
|
||||||
|
ast = ast->next;
|
||||||
|
} else if(obj && obj->type != _DT_FUNC) {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
} else {
|
} else {
|
||||||
_handle_error_on_obj(s, SE_RN_COLON_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_COLON_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
@ -3919,7 +3976,7 @@ int _clear_scope_chain(mb_interpreter_t* s) {
|
|||||||
while(running) {
|
while(running) {
|
||||||
prev = running->prev;
|
prev = running->prev;
|
||||||
|
|
||||||
global_scope = running->var_dict;
|
global_scope = running->data.var_dict;
|
||||||
_ht_foreach(global_scope, _destroy_object);
|
_ht_foreach(global_scope, _destroy_object);
|
||||||
_ht_clear(global_scope);
|
_ht_clear(global_scope);
|
||||||
|
|
||||||
@ -3943,7 +4000,7 @@ int _dispose_scope_chain(mb_interpreter_t* s) {
|
|||||||
while(running) {
|
while(running) {
|
||||||
prev = running->prev;
|
prev = running->prev;
|
||||||
|
|
||||||
global_scope = running->var_dict;
|
global_scope = running->data.var_dict;
|
||||||
_ht_foreach(global_scope, _destroy_object);
|
_ht_foreach(global_scope, _destroy_object);
|
||||||
_ht_clear(global_scope);
|
_ht_clear(global_scope);
|
||||||
_ht_destroy(global_scope);
|
_ht_destroy(global_scope);
|
||||||
@ -4022,9 +4079,9 @@ int _open_constant(mb_interpreter_t* s) {
|
|||||||
|
|
||||||
running = s->running_context;
|
running = s->running_context;
|
||||||
|
|
||||||
ul = _ht_set_or_insert(running->var_dict, "TRUE", _OBJ_BOOL_TRUE);
|
ul = _ht_set_or_insert(running->data.var_dict, "TRUE", _OBJ_BOOL_TRUE);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
ul = _ht_set_or_insert(running->var_dict, "FALSE", _OBJ_BOOL_FALSE);
|
ul = _ht_set_or_insert(running->data.var_dict, "FALSE", _OBJ_BOOL_FALSE);
|
||||||
mb_assert(ul);
|
mb_assert(ul);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -4222,7 +4279,7 @@ int mb_open(struct mb_interpreter_t** s) {
|
|||||||
running->meta = _SCOPE_META_ROOT;
|
running->meta = _SCOPE_META_ROOT;
|
||||||
(*s)->running_context = running;
|
(*s)->running_context = running;
|
||||||
global_scope = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
global_scope = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
||||||
running->var_dict = global_scope;
|
running->data.var_dict = global_scope;
|
||||||
|
|
||||||
(*s)->sub_stack = _ls_create();
|
(*s)->sub_stack = _ls_create();
|
||||||
|
|
||||||
@ -4295,6 +4352,7 @@ int mb_reset(struct mb_interpreter_t** s, bool_t clrf/* = false*/) {
|
|||||||
|
|
||||||
mb_assert(s);
|
mb_assert(s);
|
||||||
|
|
||||||
|
(*s)->jump_set = _JMP_NIL;
|
||||||
(*s)->no_eat_comma_mark = 0;
|
(*s)->no_eat_comma_mark = 0;
|
||||||
(*s)->last_error = SE_NO_ERR;
|
(*s)->last_error = SE_NO_ERR;
|
||||||
(*s)->last_error_func = 0;
|
(*s)->last_error_func = 0;
|
||||||
@ -4432,7 +4490,7 @@ int mb_has_arg(struct mb_interpreter_t* s, void** l) {
|
|||||||
if(ast) {
|
if(ast) {
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(!_IS_FUNC(obj, _core_close_bracket) && obj->type != _DT_EOS)
|
if(!_IS_FUNC(obj, _core_close_bracket) && obj->type != _DT_EOS)
|
||||||
result = obj->data.integer;
|
result = obj->type != _DT_NIL && obj->type != _DT_SEP && obj->type != _DT_EOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -5572,13 +5630,18 @@ int _core_let(mb_interpreter_t* s, void** l) {
|
|||||||
_handle_error_on_obj(s, SE_RN_SYNTAX, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_SYNTAX, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
if(obj->type == _DT_VAR) {
|
if(obj->type == _DT_ARRAY) {
|
||||||
var = obj->data.variable;
|
|
||||||
} else if(obj->type == _DT_ARRAY) {
|
|
||||||
arr = obj->data.array;
|
arr = obj->data.array;
|
||||||
result = _get_array_index(s, &ast, &arr_idx);
|
result = _get_array_index(s, &ast, &arr_idx);
|
||||||
if(result != MB_FUNC_OK)
|
if(result != MB_FUNC_OK)
|
||||||
goto _exit;
|
goto _exit;
|
||||||
|
} else if(obj->type == _DT_VAR && obj->data.variable->data->type == _DT_ARRAY) {
|
||||||
|
arr = obj->data.variable->data->data.array;
|
||||||
|
result = _get_array_index(s, &ast, &arr_idx);
|
||||||
|
if(result != MB_FUNC_OK)
|
||||||
|
goto _exit;
|
||||||
|
} else if(obj->type == _DT_VAR) {
|
||||||
|
var = obj->data.variable;
|
||||||
} else {
|
} else {
|
||||||
_handle_error_on_obj(s, SE_RN_VAR_OR_ARRAY_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_VAR_OR_ARRAY_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
@ -5745,10 +5808,12 @@ _elseif:
|
|||||||
|
|
||||||
if(ast && ast->next && _IS_EOS(ast->next->data))
|
if(ast && ast->next && _IS_EOS(ast->next->data))
|
||||||
multi_line = true;
|
multi_line = true;
|
||||||
|
else
|
||||||
s->skip_to_eoi = _ls_back(s->sub_stack);
|
s->skip_to_eoi = _ls_back(s->sub_stack);
|
||||||
do {
|
do {
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
|
while(ast && _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;
|
||||||
@ -5817,14 +5882,16 @@ _elseif:
|
|||||||
}
|
}
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
|
if(result != MB_SUB_RETURN) {
|
||||||
if(multi_line)
|
if(multi_line)
|
||||||
result = _skip_to(s, &ast, _core_endif, _DT_NIL);
|
result = _skip_to(s, &ast, _core_endif, _DT_NIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
*l = ast;
|
||||||
|
|
||||||
if(val->type != _DT_ANY)
|
if(val->type != _DT_ANY)
|
||||||
_destroy_object(val, 0);
|
_destroy_object(val, 0);
|
||||||
|
|
||||||
*l = ast;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6224,7 +6291,7 @@ int _core_goto(mb_interpreter_t* s, void** l) {
|
|||||||
|
|
||||||
label = (_label_t*)(obj->data.label);
|
label = (_label_t*)(obj->data.label);
|
||||||
if(!label->node) {
|
if(!label->node) {
|
||||||
glbsyminscope = _ht_find(running->var_dict, label->name);
|
glbsyminscope = _ht_find(running->data.var_dict, label->name);
|
||||||
if(!(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_LABEL)) {
|
if(!(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_LABEL)) {
|
||||||
_handle_error_on_obj(s, SE_RN_LABEL_NOT_EXISTS, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_LABEL_NOT_EXISTS, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
|
0
my_basic.sln
Normal file → Executable file
0
my_basic.sln
Normal file → Executable file
22
my_basic.vcproj
Normal file → Executable file
22
my_basic.vcproj
Normal file → Executable file
@ -66,6 +66,7 @@
|
|||||||
OutputFile="$(OutDir)\$(ProjectName)_d.exe"
|
OutputFile="$(OutDir)\$(ProjectName)_d.exe"
|
||||||
LinkIncremental="2"
|
LinkIncremental="2"
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
|
ProgramDatabaseFile="$(OutDir)\$(ProjectName)_d.pdb"
|
||||||
SubSystem="1"
|
SubSystem="1"
|
||||||
TargetMachine="1"
|
TargetMachine="1"
|
||||||
/>
|
/>
|
||||||
@ -141,6 +142,7 @@
|
|||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
|
ProgramDatabaseFile="$(OutDir)\$(ProjectName).pdb"
|
||||||
SubSystem="1"
|
SubSystem="1"
|
||||||
OptimizeReferences="2"
|
OptimizeReferences="2"
|
||||||
EnableCOMDATFolding="2"
|
EnableCOMDATFolding="2"
|
||||||
@ -287,6 +289,26 @@
|
|||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\sample\sample05.bas"
|
||||||
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="debug|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="release|Win32"
|
||||||
|
ExcludedFromBuild="true"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="res"
|
Name="res"
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -36,8 +36,8 @@
|
|||||||
IDI_ICON_MAIN ICON "icon.ico"
|
IDI_ICON_MAIN ICON "icon.ico"
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,1,71,0
|
FILEVERSION 1,1,72,0
|
||||||
PRODUCTVERSION 1,1,71,0
|
PRODUCTVERSION 1,1,72,0
|
||||||
FILEFLAGSMASK 0x17L
|
FILEFLAGSMASK 0x17L
|
||||||
# ifdef _DEBUG
|
# ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -55,13 +55,13 @@
|
|||||||
VALUE "Comments", "MY-BASIC"
|
VALUE "Comments", "MY-BASIC"
|
||||||
VALUE "CompanyName", "Wang Renxin"
|
VALUE "CompanyName", "Wang Renxin"
|
||||||
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
||||||
VALUE "FileVersion", "1, 1, 71, 0"
|
VALUE "FileVersion", "1, 1, 72, 0"
|
||||||
VALUE "InternalName", "my_basic"
|
VALUE "InternalName", "my_basic"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
||||||
VALUE "LegalTrademarks", "MY-BASIC"
|
VALUE "LegalTrademarks", "MY-BASIC"
|
||||||
VALUE "OriginalFilename", "my_basic.exe"
|
VALUE "OriginalFilename", "my_basic.exe"
|
||||||
VALUE "ProductName", "MY-BASIC"
|
VALUE "ProductName", "MY-BASIC"
|
||||||
VALUE "ProductVersion", "1, 1, 71, 0"
|
VALUE "ProductVersion", "1, 1, 72, 0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
15
sample/sample05.bas
Executable file
15
sample/sample05.bas
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
' This script is an example of MY-BASIC
|
||||||
|
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
||||||
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
|
DEF AREA(a, b)
|
||||||
|
RETURN CALL MUL(a, b)
|
||||||
|
ENDDEF
|
||||||
|
|
||||||
|
DEF MUL(a, b)
|
||||||
|
return a * b
|
||||||
|
ENDDEF
|
||||||
|
|
||||||
|
a = 3
|
||||||
|
b = 4
|
||||||
|
PRINT a; b; AREA(a, b);
|
@ -67,9 +67,9 @@
|
|||||||
# define _BIN_FILE_NAME "my_basic"
|
# define _BIN_FILE_NAME "my_basic"
|
||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
# define _BIN_FILE_NAME "my_basic_mac"
|
# define _BIN_FILE_NAME "my_basic_mac"
|
||||||
#else
|
#else /* _MSC_VER */
|
||||||
# define _BIN_FILE_NAME "my_basic_bin"
|
# define _BIN_FILE_NAME "my_basic_bin"
|
||||||
#endif
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#define _USE_MEM_POOL /* Comment this macro to disable memory pool */
|
#define _USE_MEM_POOL /* Comment this macro to disable memory pool */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user