diff --git a/HISTORY b/HISTORY
index e31c71f..9f378a5 100755
--- a/HISTORY
+++ b/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
Fixed a float number parsing bug, thanks to Cybermonkey342 for pointing it out
Added directly expression evaluation shell command
diff --git a/core/my_basic.c b/core/my_basic.c
index 7524d7b..ee2ed4a 100755
--- a/core/my_basic.c
+++ b/core/my_basic.c
@@ -79,7 +79,7 @@ extern "C" {
/** Macros */
#define _VER_MAJOR 1
#define _VER_MINOR 1
-#define _VER_REVISION 71
+#define _VER_REVISION 72
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
/* Uncomment the line below to treat warning as error */
@@ -375,11 +375,15 @@ typedef struct _parsing_context_t {
/* Running context */
#define _SCOPE_META_ROOT 'ROOT'
+#define _SCOPE_META_REF 'REFS'
typedef struct _running_context_t {
struct _running_context_t* prev;
unsigned meta;
- _ht_node_t* var_dict;
+ union {
+ _ht_node_t* var_dict;
+ struct _running_context_t* ref;
+ } data;
_var_t* next_loop_var;
mb_value_t intermediate_value;
} _running_context_t;
@@ -392,6 +396,7 @@ typedef struct _tuple3_t {
} _tuple3_t;
/* Interpreter tag */
+#define _JMP_NIL 0x00
#define _JMP_INS 0x01
#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 _begin_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* _pop_scope(mb_interpreter_t* s);
static _running_context_t* _get_scope_for_add_routine(mb_interpreter_t* s);
@@ -1789,34 +1796,39 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
}
} else {
if(c->type == _DT_ARRAY) {
- ast = ast->prev;
- result = _get_array_index(s, &ast, &arr_idx);
- if(result != MB_FUNC_OK) {
- _handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, 0, DON(ast), MB_FUNC_ERR, _exit, result);
- }
- ast = ast->next;
- _get_array_elem(s, c->data.array, arr_idx, &arr_val, &arr_type);
- arr_elem = (_object_t*)mb_malloc(sizeof(_object_t));
- memset(arr_elem, 0, sizeof(_object_t));
- _ls_pushback(garbage, arr_elem);
- arr_elem->type = arr_type;
- arr_elem->ref = true;
- if(arr_type == _DT_INT) {
- arr_elem->data.integer = arr_val.integer;
- } else if(arr_type == _DT_REAL) {
- arr_elem->data.float_point = arr_val.float_point;
- } else if(arr_type == _DT_STRING) {
- arr_elem->data.string = arr_val.string;
- } else if(arr_type == _DT_USERTYPE) {
- arr_elem->data.usertype = arr_val.usertype;
+ if(ast && !_IS_FUNC(((_object_t*)(ast->data)), _core_open_bracket)) {
+ _ls_pushback(opnd, c);
+ f++;
} else {
- mb_assert(0 && "Unsupported");
+ ast = ast->prev;
+ result = _get_array_index(s, &ast, &arr_idx);
+ if(result != MB_FUNC_OK) {
+ _handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, 0, DON(ast), MB_FUNC_ERR, _exit, result);
+ }
+ ast = ast->next;
+ _get_array_elem(s, c->data.array, arr_idx, &arr_val, &arr_type);
+ arr_elem = (_object_t*)mb_malloc(sizeof(_object_t));
+ memset(arr_elem, 0, sizeof(_object_t));
+ _ls_pushback(garbage, arr_elem);
+ arr_elem->type = arr_type;
+ arr_elem->ref = true;
+ if(arr_type == _DT_INT) {
+ arr_elem->data.integer = arr_val.integer;
+ } else if(arr_type == _DT_REAL) {
+ arr_elem->data.float_point = arr_val.float_point;
+ } else if(arr_type == _DT_STRING) {
+ arr_elem->data.string = arr_val.string;
+ } else if(arr_type == _DT_USERTYPE) {
+ arr_elem->data.usertype = arr_val.usertype;
+ } else {
+ mb_assert(0 && "Unsupported");
+ }
+ if(f) {
+ _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
+ }
+ _ls_pushback(opnd, arr_elem);
+ f++;
}
- if(f) {
- _handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
- }
- _ls_pushback(opnd, arr_elem);
- f++;
} else if(c->type == _DT_FUNC) {
ast = ast->prev;
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 {
result = _execute_statement(s, l);
+ ast = (_ls_node_t*)(*l);
if(result == MB_SUB_RETURN) {
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));
(*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);
*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);
(*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);
*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;
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);
if(tba != _OUTTER_SCOPE(running))
_pop_scope(s);
@@ -2422,7 +2435,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
break;
case _DT_VAR:
if(context->routine_params_state)
- glbsyminscope = _ht_find(running->var_dict, sym);
+ glbsyminscope = _ht_find(running->data.var_dict, sym);
else
glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
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;
(*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);
*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);
(*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);
*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) {
tmp.obj = (_object_t*)(glbsyminscope->data);
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);
}
tmp.obj->type = _DT_CLASS;
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);
- _ht_set_or_insert(running->var_dict, sym, tmp.obj);
+ _ht_set_or_insert(running->data.var_dict, sym, tmp.obj);
}
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) {
tmp.obj = (_object_t*)(glbsyminscope->data);
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);
}
tmp.obj->type = _DT_ROUTINE;
tmp.obj->data.routine = (_routine_t*)mb_malloc(sizeof(_routine_t));
_init_routine(s, tmp.obj->data.routine, sym);
_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;
@@ -3219,7 +3232,7 @@ void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
instance->name = n;
instance->scope = (_running_context_t*)mb_malloc(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) {
@@ -3254,7 +3267,7 @@ void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
routine->name = n;
routine->scope = (_running_context_t*)mb_malloc(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) {
@@ -3297,10 +3310,43 @@ void _end_routine_parameter_list(mb_interpreter_t* s) {
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) {
/* Push encapsule a scope */
mb_assert(s);
+ if(_find_scope(s, p))
+ p = _reference_scope(s, p);
p->prev = s->running_context;
s->running_context = p;
@@ -3316,6 +3362,9 @@ _running_context_t* _pop_scope(mb_interpreter_t* s) {
running = s->running_context;
s->running_context = running->prev;
running->prev = 0;
+ if(running->meta == _SCOPE_META_REF) {
+ mb_free(running);
+ }
return s->running_context;
}
@@ -3328,7 +3377,7 @@ _running_context_t* _get_scope_for_add_routine(mb_interpreter_t* s) {
running = s->running_context;
while(running) {
- if(running->meta)
+ if(running->meta == _SCOPE_META_ROOT)
break;
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 */
_ls_node_t* result = 0;
_running_context_t* running = 0;
+ _ht_node_t* var_dict = 0;
mb_assert(s && n);
@@ -3349,7 +3399,8 @@ _ls_node_t* _search_var_in_scope_chain(mb_interpreter_t* s, _running_context_t*
else
running = s->running_context;
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)
break;
@@ -3407,8 +3458,8 @@ int _dispose_object(_object_t* obj) {
case _DT_CLASS:
if(!obj->ref) {
safe_free(obj->data.instance->name);
- _ht_foreach(obj->data.instance->scope->var_dict, _destroy_object);
- _ht_destroy(obj->data.instance->scope->var_dict);
+ _ht_foreach(obj->data.instance->scope->data.var_dict, _destroy_object);
+ _ht_destroy(obj->data.instance->scope->data.var_dict);
safe_free(obj->data.instance->scope);
safe_free(obj->data.instance);
}
@@ -3417,8 +3468,8 @@ int _dispose_object(_object_t* obj) {
case _DT_ROUTINE:
if(!obj->ref) {
safe_free(obj->data.routine->name);
- _ht_foreach(obj->data.routine->scope->var_dict, _destroy_object);
- _ht_destroy(obj->data.routine->scope->var_dict);
+ _ht_foreach(obj->data.routine->scope->data.var_dict, _destroy_object);
+ _ht_destroy(obj->data.routine->scope->data.var_dict);
safe_free(obj->data.routine->scope);
if(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;
_object_t* obj = 0;
_running_context_t* running = 0;
+ _ls_node_t* sub_stack = 0;
bool_t skip_to_eoi = true;
mb_assert(s && l);
running = s->running_context;
+ sub_stack = s->sub_stack;
ast = *l;
@@ -3789,7 +3842,11 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
ast = ast->next;
} else if(obj && obj->type == _DT_VAR) {
_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;
} else {
_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) {
prev = running->prev;
- global_scope = running->var_dict;
+ global_scope = running->data.var_dict;
_ht_foreach(global_scope, _destroy_object);
_ht_clear(global_scope);
@@ -3943,7 +4000,7 @@ int _dispose_scope_chain(mb_interpreter_t* s) {
while(running) {
prev = running->prev;
- global_scope = running->var_dict;
+ global_scope = running->data.var_dict;
_ht_foreach(global_scope, _destroy_object);
_ht_clear(global_scope);
_ht_destroy(global_scope);
@@ -4022,9 +4079,9 @@ int _open_constant(mb_interpreter_t* s) {
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);
- 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);
return result;
@@ -4222,7 +4279,7 @@ int mb_open(struct mb_interpreter_t** s) {
running->meta = _SCOPE_META_ROOT;
(*s)->running_context = running;
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();
@@ -4295,6 +4352,7 @@ int mb_reset(struct mb_interpreter_t** s, bool_t clrf/* = false*/) {
mb_assert(s);
+ (*s)->jump_set = _JMP_NIL;
(*s)->no_eat_comma_mark = 0;
(*s)->last_error = SE_NO_ERR;
(*s)->last_error_func = 0;
@@ -4432,7 +4490,7 @@ int mb_has_arg(struct mb_interpreter_t* s, void** l) {
if(ast) {
obj = (_object_t*)(ast->data);
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;
@@ -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);
}
obj = (_object_t*)(ast->data);
- if(obj->type == _DT_VAR) {
- var = obj->data.variable;
- } else if(obj->type == _DT_ARRAY) {
+ if(obj->type == _DT_ARRAY) {
arr = obj->data.array;
result = _get_array_index(s, &ast, &arr_idx);
if(result != MB_FUNC_OK)
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 {
_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))
multi_line = true;
-
- s->skip_to_eoi = _ls_back(s->sub_stack);
+ else
+ s->skip_to_eoi = _ls_back(s->sub_stack);
do {
ast = ast->next;
+ while(ast && _IS_EOS(ast->data))
+ ast = ast->next;
result = _execute_statement(s, &ast);
if(result != MB_FUNC_OK)
goto _exit;
@@ -5817,14 +5882,16 @@ _elseif:
}
_exit:
- if(multi_line)
- result = _skip_to(s, &ast, _core_endif, _DT_NIL);
+ if(result != MB_SUB_RETURN) {
+ if(multi_line)
+ result = _skip_to(s, &ast, _core_endif, _DT_NIL);
+ }
+
+ *l = ast;
if(val->type != _DT_ANY)
_destroy_object(val, 0);
- *l = ast;
-
return result;
}
@@ -6224,7 +6291,7 @@ int _core_goto(mb_interpreter_t* s, void** l) {
label = (_label_t*)(obj->data.label);
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)) {
_handle_error_on_obj(s, SE_RN_LABEL_NOT_EXISTS, 0, DON(ast), MB_FUNC_ERR, _exit, result);
}
diff --git a/my_basic.sln b/my_basic.sln
old mode 100644
new mode 100755
diff --git a/my_basic.vcproj b/my_basic.vcproj
old mode 100644
new mode 100755
index ce92e5d..a0f8232
--- a/my_basic.vcproj
+++ b/my_basic.vcproj
@@ -66,6 +66,7 @@
OutputFile="$(OutDir)\$(ProjectName)_d.exe"
LinkIncremental="2"
GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)\$(ProjectName)_d.pdb"
SubSystem="1"
TargetMachine="1"
/>
@@ -141,6 +142,7 @@
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)\$(ProjectName).pdb"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
@@ -287,6 +289,26 @@
/>
+
+
+
+
+
+
+
+