+added an mb_add_var function; +added an mb_set_routine function; +added native sub routine support.

This commit is contained in:
paladin-t 2015-12-15 17:39:26 +08:00
parent 04de3f6a58
commit fd8f45a234
3 changed files with 190 additions and 43 deletions

View File

@ -1,6 +1,9 @@
Dec. 15 2015
Added a pair of mb_begin_class/mb_end_class functions
Added an mb_get_value_by_name function
Added an mb_add_var function
Added an mb_set_routine function
Added native sub routine support
Dec. 13 2015
Avoided warnings

View File

@ -225,6 +225,7 @@ static const char* _ERR_DESC[] = {
"Jump label expected",
"Variable expected",
"Invalid identifier usage",
"Duplicate identifier",
"Operator expected",
"Calculation error",
"Divide by zero",
@ -393,11 +394,9 @@ typedef struct _routine_t {
struct _running_context_t* scope;
_ls_node_t* entry;
_ls_node_t* parameters;
mb_routine_func_t functor;
} _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; mb_val_bytes_t b; } _raw_u;
typedef unsigned char _raw_t[sizeof(_raw_u)];
@ -971,12 +970,14 @@ 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 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 _proc_args(mb_interpreter_t* s, _ls_node_t** l, _running_context_t* running, mb_value_t* va, unsigned ca, _routine_t* r, _has_routine_arg has_arg, _pop_routine_arg pop_arg, bool_t proc_ref);
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 int _proc_args(mb_interpreter_t* s, _ls_node_t** l, _running_context_t* running, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg, bool_t proc_ref);
static int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg);
static int _eval_script_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg);
static int _eval_native_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg);
static int _has_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* r);
static int _pop_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* 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, void* r);
static int _pop_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* r, mb_value_t* val);
static bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj);
/** Handlers */
@ -1255,7 +1256,7 @@ static int _clone_clsss_field(void* data, void* extra, void* n);
static bool_t _clone_class_meta_link(_class_t* meta, void* n, void* ret);
static bool_t _is_class(_class_t* instance, void* m, void* ret);
#endif /* MB_ENABLE_CLASS */
static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n);
static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n, mb_routine_func_t f);
static void _begin_routine(mb_interpreter_t* s);
static bool_t _end_routine(mb_interpreter_t* s);
static void _begin_routine_parameter_list(mb_interpreter_t* s);
@ -2907,7 +2908,7 @@ _exit:
return result;
}
int _proc_args(mb_interpreter_t* s, _ls_node_t** l, _running_context_t* running, mb_value_t* va, unsigned ca, _routine_t* r, _has_routine_arg has_arg, _pop_routine_arg pop_arg, bool_t proc_ref) {
int _proc_args(mb_interpreter_t* s, _ls_node_t** l, _running_context_t* running, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg, bool_t proc_ref) {
/* Process arguments of a routine */
int result = MB_FUNC_OK;
mb_value_t arg;
@ -2953,9 +2954,25 @@ int _proc_args(mb_interpreter_t* s, _ls_node_t** l, _running_context_t* running,
return result;
}
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) {
int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg) {
/* Evaluate a routine */
int result = MB_FUNC_OK;
if(r->entry) {
result = _eval_script_routine(s, l, va, ca, r, has_arg, pop_arg);
} else if(r->functor) {
result = _eval_native_routine(s, l, va, ca, r, has_arg, pop_arg);
} else {
_handle_error_on_obj(s, SE_RN_INVALID_ROUTINE, 0, TON(l), MB_FUNC_ERR, _exit, result);
}
_exit:
return result;
}
int _eval_script_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg) {
/* Evaluate a script routine */
int result = MB_FUNC_OK;
_ls_node_t* ast = 0;
_running_context_t* running = 0;
_routine_t* lastr = 0;
@ -3054,7 +3071,31 @@ _tail:
return result;
}
int _has_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, _routine_t* r) {
int _eval_native_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned ca, _routine_t* r, mb_has_routine_arg_func_t has_arg, mb_pop_routine_arg_func_t pop_arg) {
/* Evaluate a native routine */
int result = MB_FUNC_OK;
_routine_t* lastr = 0;
mb_routine_func_t entry = 0;
mb_assert(s && l && r);
lastr = s->last_routine;
s->last_routine = r;
entry = r->functor;
if(!entry) {
_handle_error_on_obj(s, SE_RN_INVALID_ROUTINE, 0, TON(l), MB_FUNC_ERR, _exit, result);
}
result = entry(s, l, va, ca, r, has_arg, pop_arg);
_exit:
s->last_routine = lastr;
return result;
}
int _has_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* r) {
/* Detect if there is any more lexical argument */
mb_unrefvar(va);
mb_unrefvar(ca);
@ -3064,7 +3105,7 @@ int _has_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned
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) {
int _pop_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* r, mb_value_t* val) {
/* Pop a lexical argument */
mb_unrefvar(va);
mb_unrefvar(ca);
@ -3074,7 +3115,7 @@ int _pop_routine_lex_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned
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) {
int _has_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* r) {
/* Detect if there is any more argument in the argument list */
mb_unrefvar(s);
mb_unrefvar(l);
@ -3084,7 +3125,7 @@ int _has_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned
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) {
int _pop_routine_fun_arg(mb_interpreter_t* s, void** l, mb_value_t* va, unsigned ca, unsigned* ia, void* r, mb_value_t* val) {
/* Pop an argument from the argument list */
mb_unrefvar(s);
mb_unrefvar(l);
@ -3505,7 +3546,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
} else {
_running_context_t* tba = 0;
tmp.routine = (_routine_t*)mb_malloc(sizeof(_routine_t));
_init_routine(s, tmp.routine, sym);
_init_routine(s, tmp.routine, sym, 0);
_push_scope_by_routine(s, tmp.routine->scope);
(*obj)->data.routine = tmp.routine;
@ -5593,7 +5634,7 @@ bool_t _is_class(_class_t* instance, void* m, void* ret) {
}
#endif /* MB_ENABLE_CLASS */
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n, mb_routine_func_t f) {
/* Initialize a routine */
_running_context_t* running = 0;
@ -5603,9 +5644,11 @@ void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
memset(routine, 0, sizeof(_routine_t));
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);
if(!f) {
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);
}
}
void _begin_routine(mb_interpreter_t* s) {
@ -5822,7 +5865,8 @@ _running_context_t* _push_weak_scope_by_routine(mb_interpreter_t* s, _running_co
if(_find_scope(s, p))
p = _reference_scope_by_routine(s, p, r);
p->prev = s->running_context;
if(p)
p->prev = s->running_context;
return p;
}
@ -5833,8 +5877,10 @@ _running_context_t* _push_scope_by_routine(mb_interpreter_t* s, _running_context
if(_find_scope(s, p))
p = _reference_scope_by_routine(s, p, 0);
p->prev = s->running_context;
s->running_context = p;
if(p) {
p->prev = s->running_context;
s->running_context = p;
}
return s->running_context;
}
@ -5854,7 +5900,8 @@ _running_context_t* _pop_weak_scope(mb_interpreter_t* s, _running_context_t* p)
/* Pop a weak scope */
mb_assert(s);
p->prev = 0;
if(p)
p->prev = 0;
return p;
}
@ -6177,11 +6224,13 @@ int _dispose_object(_object_t* obj) {
case _DT_ROUTINE:
if(!obj->ref) {
safe_free(obj->data.routine->name);
if(obj->data.routine->scope->var_dict) {
_ht_foreach(obj->data.routine->scope->var_dict, _destroy_object);
_ht_destroy(obj->data.routine->scope->var_dict);
if(obj->data.routine->scope) {
if(obj->data.routine->scope->var_dict) {
_ht_foreach(obj->data.routine->scope->var_dict, _destroy_object);
_ht_destroy(obj->data.routine->scope->var_dict);
}
safe_free(obj->data.routine->scope);
}
safe_free(obj->data.routine->scope);
if(obj->data.routine->parameters)
_ls_destroy(obj->data.routine->parameters);
safe_free(obj->data.routine);
@ -6564,6 +6613,10 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
mb_assert(pbl && itn);
switch(itn->type) {
case _DT_VAR:
result = _internal_object_to_public_value(itn->data.variable->data, pbl);
break;
case _DT_TYPE:
pbl->type = MB_DT_TYPE;
pbl->value.type = itn->data.type;
@ -8126,6 +8179,7 @@ int mb_push_value(struct mb_interpreter_t* s, void** l, mb_value_t val) {
int mb_begin_class(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t** meta, int c, mb_value_t* out) {
/* Begin a class */
#ifdef MB_ENABLE_CLASS
int result = MB_FUNC_OK;
_class_t* instance = 0;
_object_t* obj = 0;
@ -8181,10 +8235,21 @@ int mb_begin_class(struct mb_interpreter_t* s, void** l, const char* n, mb_value
_exit:
return result;
#else /* MB_ENABLE_CLASS */
mb_unrefvar(s);
mb_unrefvar(l);
mb_unrefvar(n);
mb_unrefvar(meta);
mb_unrefvar(c);
mb_unrefvar(out);
return MB_FUNC_ERR;
#endif /* MB_ENABLE_CLASS */
}
int mb_end_class(struct mb_interpreter_t* s, void** l) {
/* End a class */
#ifdef MB_ENABLE_CLASS
int result = MB_FUNC_OK;
mb_assert(s && l);
@ -8192,6 +8257,12 @@ int mb_end_class(struct mb_interpreter_t* s, void** l) {
_pop_scope(s);
return result;
#else /* MB_ENABLE_CLASS */
mb_unrefvar(s);
mb_unrefvar(l);
return MB_FUNC_ERR;
#endif /* MB_ENABLE_CLASS */
}
int mb_get_value_by_name(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t* val) {
@ -8213,15 +8284,46 @@ int mb_get_value_by_name(struct mb_interpreter_t* s, void** l, const char* n, mb
return result;
}
int mb_add_var(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t val) {
int mb_add_var(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t val, bool_t force) {
/* Add a variable with a specific name */
int result = MB_FUNC_OK;
mb_unrefvar(s);
mb_unrefvar(l);
mb_unrefvar(n);
mb_unrefvar(val);
/* TODO */
_running_context_t* running = 0;
_object_t* obj = 0;
_var_t* var = 0;
_ls_node_t* tmp = 0;
mb_assert(s && l && n);
running = s->running_context;
tmp = _ht_find(running->var_dict, (void*)n);
if(tmp) {
if(force) {
result = mb_set_var_value(s, tmp->data, val);
goto _exit;
} else {
_handle_error_on_obj(s, SE_RN_DUPLICATE_ID, 0, TON(l), MB_FUNC_ERR, _exit, result);
}
}
var = (_var_t*)mb_malloc(sizeof(_var_t));
memset(var, 0, sizeof(_var_t));
var->name = mb_memdup(n, (unsigned)(strlen(n) + 1));
var->data = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(var->data);
_public_value_to_internal_object(&val, var->data);
obj = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(obj);
obj->type = _DT_VAR;
obj->data.variable = var;
obj->ref = false;
_ht_set_or_insert(running->var_dict, var->name, obj);
_exit:
return result;
}
@ -8762,15 +8864,53 @@ _exit:
return result;
}
int mb_set_routine(struct mb_interpreter_t* s, void** l, const char* n, mb_func_t f) {
int mb_set_routine(struct mb_interpreter_t* s, void** l, const char* n, mb_routine_func_t f, bool_t force) {
/* Set a sub routine with a specific name and functor */
int result = MB_FUNC_OK;
mb_unrefvar(s);
mb_unrefvar(l);
mb_unrefvar(n);
mb_unrefvar(f);
/* TODO */
_running_context_t* running = 0;
_object_t* obj = 0;
_routine_t* routine = 0;
_ls_node_t* tmp = 0;
_var_t* var = 0;
mb_assert(s && l);
running = s->running_context;
tmp = _ht_find(running->var_dict, (void*)n);
if(tmp) {
if(force) {
obj = (_object_t*)tmp->data;
if(obj->type == _DT_VAR)
var = obj->data.variable;
} else {
_handle_error_on_obj(s, SE_RN_DUPLICATE_ROUTINE, 0, TON(l), MB_FUNC_ERR, _exit, result);
}
}
routine = (_routine_t*)mb_malloc(sizeof(_routine_t));
_init_routine(s, routine, mb_memdup(n, (unsigned)(strlen(n) + 1)), f);
routine->functor = f;
obj = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(obj);
obj->type = _DT_ROUTINE;
obj->data.routine = routine;
obj->ref = false;
#ifdef MB_ENABLE_CLASS
routine->instance = s->last_instance;
#endif /* MB_ENABLE_CLASS */
if(var && force) {
_destroy_object(var->data, 0);
var->data = obj;
} else {
_ht_set_or_insert(running->var_dict, routine->name, obj);
}
_exit:
return result;
}

View File

@ -302,6 +302,7 @@ typedef enum mb_error_e {
SE_RN_JUMP_LABEL_EXPECTED,
SE_RN_VARIABLE_EXPECTED,
SE_RN_INVALID_ID_USAGE,
SE_RN_DUPLICATE_ID,
SE_RN_OPERATOR_EXPECTED,
SE_RN_CALCULATION_ERROR,
SE_RN_DIVIDE_BY_ZERO,
@ -385,6 +386,9 @@ typedef struct mb_value_t {
typedef unsigned short mb_mem_tag_t;
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
typedef int (* mb_has_routine_arg_func_t)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, unsigned*, void*);
typedef int (* mb_pop_routine_arg_func_t)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, unsigned*, void*, mb_value_t*);
typedef int (* mb_routine_func_t)(struct mb_interpreter_t*, void**, mb_value_t*, unsigned, void*, mb_has_routine_arg_func_t, mb_pop_routine_arg_func_t);
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*, char*, int, unsigned short, unsigned short, int);
typedef int (* mb_print_func_t)(const char*, ...);
@ -433,7 +437,7 @@ MBAPI int mb_begin_class(struct mb_interpreter_t* s, void** l, const char* n, mb
MBAPI int mb_end_class(struct mb_interpreter_t* s, void** l);
MBAPI int mb_get_value_by_name(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t* val);
MBAPI int mb_add_var(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t val);
MBAPI int mb_add_var(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t val, bool_t force);
MBAPI int mb_get_var(struct mb_interpreter_t* s, void** l, void** v);
MBAPI int mb_get_var_value(struct mb_interpreter_t* s, void* v, mb_value_t* val);
MBAPI int mb_set_var_value(struct mb_interpreter_t* s, void* v, mb_value_t val);
@ -453,7 +457,7 @@ MBAPI int mb_unref_value(struct mb_interpreter_t* s, void** l, mb_value_t val);
MBAPI int mb_dispose_value(struct mb_interpreter_t* s, mb_value_t val);
MBAPI int mb_get_routine(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t* val);
MBAPI int mb_set_routine(struct mb_interpreter_t* s, void** l, const char* n, mb_func_t f);
MBAPI int mb_set_routine(struct mb_interpreter_t* s, void** l, const char* n, mb_routine_func_t f, bool_t force);
MBAPI int mb_eval_routine(struct mb_interpreter_t* s, void** l, mb_value_t val, mb_value_t* args, unsigned argc);
MBAPI int mb_load_string(struct mb_interpreter_t* s, const char* l);