+added a sub routine invoking function; +added an mb_get_routine function; +added an mb_eval_routine function.
This commit is contained in:
parent
de3c799630
commit
9715c6da8e
131
core/my_basic.c
131
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 87
|
#define _VER_REVISION 88
|
||||||
#define _VER_SUFFIX
|
#define _VER_SUFFIX
|
||||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||||
#define _STRINGIZE(A) _MAKE_STRINGIZE(A)
|
#define _STRINGIZE(A) _MAKE_STRINGIZE(A)
|
||||||
@ -366,6 +366,9 @@ typedef struct _routine_t {
|
|||||||
_ls_node_t* parameters;
|
_ls_node_t* parameters;
|
||||||
} _routine_t;
|
} _routine_t;
|
||||||
|
|
||||||
|
typedef int (* _has_routine_arg)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, unsigned*, _routine_t*);
|
||||||
|
typedef int (* _pop_routine_arg)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, unsigned*, _routine_t*, mb_value_t*);
|
||||||
|
|
||||||
typedef union _raw_u { char c; int_t i; real_t r; void* p; } _raw_u;
|
typedef union _raw_u { char c; int_t i; real_t r; void* p; } _raw_u;
|
||||||
|
|
||||||
typedef unsigned char _raw_t[sizeof(_raw_u)];
|
typedef unsigned char _raw_t[sizeof(_raw_u)];
|
||||||
@ -910,7 +913,11 @@ static int _get_priority_index(mb_func_t op);
|
|||||||
static _object_t* _operate_operand(mb_interpreter_t* s, _object_t* optr, _object_t* opnd1, _object_t* opnd2, int* status);
|
static _object_t* _operate_operand(mb_interpreter_t* s, _object_t* optr, _object_t* opnd1, _object_t* opnd2, int* status);
|
||||||
static bool_t _is_expression_terminal(mb_interpreter_t* s, _object_t* obj);
|
static bool_t _is_expression_terminal(mb_interpreter_t* s, _object_t* obj);
|
||||||
static int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val);
|
static int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val);
|
||||||
static int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r);
|
static int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, _has_routine_arg has_arg, _pop_routine_arg pop_arg);
|
||||||
|
static int _has_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r);
|
||||||
|
static int _pop_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r, mb_value_t* val);
|
||||||
|
static int _has_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r);
|
||||||
|
static int _pop_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r, mb_value_t* val);
|
||||||
static bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj);
|
static bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj);
|
||||||
|
|
||||||
/** Handlers */
|
/** Handlers */
|
||||||
@ -2512,7 +2519,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
|||||||
f++;
|
f++;
|
||||||
} else if(c->type == _DT_ROUTINE) {
|
} else if(c->type == _DT_ROUTINE) {
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
result = _eval_routine(s, &ast, c->data.routine);
|
result = _eval_routine(s, &ast, 0, 0, c->data.routine, _has_routine_lex_arg, _pop_routine_lex_arg);
|
||||||
if(ast)
|
if(ast)
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
if(result != MB_FUNC_OK) {
|
if(result != MB_FUNC_OK) {
|
||||||
@ -2688,7 +2695,7 @@ _exit:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, _has_routine_arg has_arg, _pop_routine_arg pop_arg) {
|
||||||
/* Evaluate a routine */
|
/* Evaluate a routine */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
_ls_node_t* ast = 0;
|
_ls_node_t* ast = 0;
|
||||||
@ -2702,7 +2709,7 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
|||||||
|
|
||||||
mb_assert(s && l && r);
|
mb_assert(s && l && r);
|
||||||
|
|
||||||
if(s->last_routine && !s->last_routine->parameters && (s->last_routine->name == r->name || !strcmp(s->last_routine->name, r->name))) {
|
if(!va && s->last_routine && !s->last_routine->parameters && (s->last_routine->name == r->name || !strcmp(s->last_routine->name, r->name))) {
|
||||||
ast = (_ls_node_t*)(*l);
|
ast = (_ls_node_t*)(*l);
|
||||||
_skip_to(s, &ast, 0, _DT_EOS);
|
_skip_to(s, &ast, 0, _DT_EOS);
|
||||||
if(ast && ((_object_t*)(ast->data))->type == _DT_EOS)
|
if(ast && ((_object_t*)(ast->data))->type == _DT_EOS)
|
||||||
@ -2719,16 +2726,19 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
|||||||
lastr = s->last_routine;
|
lastr = s->last_routine;
|
||||||
s->last_routine = r;
|
s->last_routine = r;
|
||||||
|
|
||||||
|
if(!va) {
|
||||||
mb_check(mb_attempt_open_bracket(s, (void**)l));
|
mb_check(mb_attempt_open_bracket(s, (void**)l));
|
||||||
|
}
|
||||||
|
|
||||||
if(r->parameters) {
|
if(r->parameters) {
|
||||||
|
unsigned ia = 0;
|
||||||
running = _push_weak_scope(s, r->scope, r);
|
running = _push_weak_scope(s, r->scope, r);
|
||||||
if(running->meta == _SCOPE_META_REF) {
|
if(running->meta == _SCOPE_META_REF) {
|
||||||
pars = r->parameters;
|
pars = r->parameters;
|
||||||
pars = pars->next;
|
pars = pars->next;
|
||||||
while(pars && mb_has_arg(s, (void**)l)) {
|
while(pars && has_arg(s, (void**)l, va, ca, &ia, r)) {
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
mb_check(mb_pop_value(s, (void**)l, &arg));
|
mb_check(pop_arg(s, (void**)l, va, ca, &ia, r, &arg));
|
||||||
|
|
||||||
var = (_var_t*)(pars->data);
|
var = (_var_t*)(pars->data);
|
||||||
pars = pars->next;
|
pars = pars->next;
|
||||||
@ -2749,8 +2759,8 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
|||||||
} else {
|
} else {
|
||||||
pars = r->parameters;
|
pars = r->parameters;
|
||||||
pars = pars->next;
|
pars = pars->next;
|
||||||
while(pars && mb_has_arg(s, (void**)l)) {
|
while(pars && has_arg(s, (void**)l, va, ca, &ia, r)) {
|
||||||
mb_check(mb_pop_value(s, (void**)l, &arg));
|
mb_check(pop_arg(s, (void**)l, va, ca, &ia, r, &arg));
|
||||||
|
|
||||||
var = (_var_t*)(pars->data);
|
var = (_var_t*)(pars->data);
|
||||||
pars = pars->next;
|
pars = pars->next;
|
||||||
@ -2774,7 +2784,9 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
|||||||
running = _pop_weak_scope(s, running);
|
running = _pop_weak_scope(s, running);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!va) {
|
||||||
mb_check(mb_attempt_close_bracket(s, (void**)l));
|
mb_check(mb_attempt_close_bracket(s, (void**)l));
|
||||||
|
}
|
||||||
|
|
||||||
ast = (_ls_node_t*)(*l);
|
ast = (_ls_node_t*)(*l);
|
||||||
_ls_pushback(s->sub_stack, ast);
|
_ls_pushback(s->sub_stack, ast);
|
||||||
@ -2829,6 +2841,49 @@ _tail:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _has_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r) {
|
||||||
|
/* Detect if there is any more lexical argument */
|
||||||
|
mb_unrefvar(va);
|
||||||
|
mb_unrefvar(ca);
|
||||||
|
mb_unrefvar(ia);
|
||||||
|
mb_unrefvar(r);
|
||||||
|
|
||||||
|
return mb_has_arg(s, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _pop_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r, mb_value_t* val) {
|
||||||
|
/* Pop a lexical argument */
|
||||||
|
mb_unrefvar(va);
|
||||||
|
mb_unrefvar(ca);
|
||||||
|
mb_unrefvar(ia);
|
||||||
|
mb_unrefvar(r);
|
||||||
|
|
||||||
|
return mb_pop_value(s, l, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _has_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r) {
|
||||||
|
/* Detect if there is any more argument in the argument list */
|
||||||
|
mb_unrefvar(s);
|
||||||
|
mb_unrefvar(l);
|
||||||
|
mb_unrefvar(va);
|
||||||
|
mb_unrefvar(r);
|
||||||
|
|
||||||
|
return *ia < ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _pop_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r, mb_value_t* val) {
|
||||||
|
/* Pop an argument from the argument list */
|
||||||
|
mb_unrefvar(s);
|
||||||
|
mb_unrefvar(l);
|
||||||
|
mb_unrefvar(ca);
|
||||||
|
mb_unrefvar(r);
|
||||||
|
|
||||||
|
memcpy(val, &(va[*ia]), sizeof(mb_value_t));
|
||||||
|
(*ia)++;
|
||||||
|
|
||||||
|
return MB_FUNC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj) {
|
bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj) {
|
||||||
/* Determine whether an object is a PRINT termination */
|
/* Determine whether an object is a PRINT termination */
|
||||||
bool_t result = false;
|
bool_t result = false;
|
||||||
@ -5648,6 +5703,8 @@ _data_e _public_type_to_internal_type(mb_data_e t) {
|
|||||||
case MB_DT_DICT_IT:
|
case MB_DT_DICT_IT:
|
||||||
return _DT_DICT_IT;
|
return _DT_DICT_IT;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
case MB_DT_ROUTINE:
|
||||||
|
return _DT_ROUTINE;
|
||||||
default:
|
default:
|
||||||
return _DT_NIL;
|
return _DT_NIL;
|
||||||
}
|
}
|
||||||
@ -5682,6 +5739,8 @@ mb_data_e _internal_type_to_public_type(_data_e t) {
|
|||||||
case _DT_DICT_IT:
|
case _DT_DICT_IT:
|
||||||
return MB_DT_DICT_IT;
|
return MB_DT_DICT_IT;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
case _DT_ROUTINE:
|
||||||
|
return MB_DT_ROUTINE;
|
||||||
default:
|
default:
|
||||||
return MB_DT_NIL;
|
return MB_DT_NIL;
|
||||||
}
|
}
|
||||||
@ -5757,6 +5816,11 @@ int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
case MB_DT_ROUTINE:
|
||||||
|
itn->type = _DT_ROUTINE;
|
||||||
|
itn->data.routine = pbl->value.routine;
|
||||||
|
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result = MB_FUNC_ERR;
|
result = MB_FUNC_ERR;
|
||||||
|
|
||||||
@ -5835,6 +5899,11 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
case _DT_ROUTINE:
|
||||||
|
pbl->type = MB_DT_ROUTINE;
|
||||||
|
pbl->value.routine = itn->data.routine;
|
||||||
|
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result = MB_FUNC_ERR;
|
result = MB_FUNC_ERR;
|
||||||
|
|
||||||
@ -7238,6 +7307,48 @@ int mb_dispose_value(struct mb_interpreter_t* s, mb_value_t val) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mb_get_routine(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t* val) {
|
||||||
|
/* Get a sub routine with a specific name */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
_object_t* obj = 0;
|
||||||
|
_ls_node_t* scp = 0;
|
||||||
|
|
||||||
|
mb_assert(s && l && n && val);
|
||||||
|
|
||||||
|
val->type = MB_DT_NIL;
|
||||||
|
|
||||||
|
scp = _search_identifier_in_scope_chain(s, 0, (char*)n);
|
||||||
|
if(scp) {
|
||||||
|
obj = (_object_t*)(scp->data);
|
||||||
|
if(obj) {
|
||||||
|
if(obj->type == _DT_ROUTINE) {
|
||||||
|
_internal_object_to_public_value(obj, val);
|
||||||
|
} else {
|
||||||
|
_handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mb_eval_routine(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_value_t* args, unsigned argc) {
|
||||||
|
/* Evaluate a sub routine */
|
||||||
|
int result = MB_FUNC_OK;
|
||||||
|
_object_t obj;
|
||||||
|
|
||||||
|
if(val.type != MB_DT_ROUTINE) {
|
||||||
|
_handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
_public_value_to_internal_object(&val, &obj);
|
||||||
|
result = _eval_routine(s, (_ls_node_t**)l, args, argc, obj.data.routine, _has_routine_fun_arg, _pop_routine_fun_arg);
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int mb_load_string(struct mb_interpreter_t* s, const char* l) {
|
int mb_load_string(struct mb_interpreter_t* s, const char* l) {
|
||||||
/* Load and parse a script string */
|
/* Load and parse a script string */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
@ -8833,7 +8944,7 @@ int _core_call(mb_interpreter_t* s, void** l) {
|
|||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
routine = (_routine_t*)(obj->data.routine);
|
routine = (_routine_t*)(obj->data.routine);
|
||||||
|
|
||||||
_eval_routine(s, &ast, routine);
|
_eval_routine(s, &ast, 0, 0, routine, _has_routine_lex_arg, _pop_routine_lex_arg);
|
||||||
|
|
||||||
if(ast)
|
if(ast)
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user