+added a ME keyword to represent a class instance itself; +added shallow cloning support; *fixed an overrided function copying issue.

This commit is contained in:
paladin-t 2016-02-26 13:06:52 +08:00
parent ff999bf97f
commit c5df541e2b
5 changed files with 91 additions and 31 deletions

View File

@ -1,3 +1,8 @@
Feb. 26 2016
Added a ME keyword to represent a class instance itself
Added shallow cloning support
Fixed an overrided function copying issue
Feb. 25 2016 Feb. 25 2016
Improved importing directory detection Improved importing directory detection
Fixed a bug with the END and RETURN statement with FOR loop Fixed a bug with the END and RETURN statement with FOR loop
@ -13,7 +18,7 @@ Added an mb_override_value function
Added meta function overriding support for referenced usertype Added meta function overriding support for referenced usertype
Feb. 22 2016 Feb. 22 2016
Added array clone support Added array cloning support
Added array accessing support of a class instance Added array accessing support of a class instance
Added a RAISE statement to the shell Added a RAISE statement to the shell
Fixed an iterator disposing issue caused by referencing a collection weakly Fixed an iterator disposing issue caused by referencing a collection weakly

Binary file not shown.

View File

@ -148,6 +148,9 @@ extern "C" {
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
# define _IS_CLASS(__o) ((__o) && ((_object_t*)(__o))->type == _DT_CLASS) # define _IS_CLASS(__o) ((__o) && ((_object_t*)(__o))->type == _DT_CLASS)
# define _GET_CLASS(__o) ((!__o) ? 0 : (_IS_CLASS(__o) ? (__o) : (_IS_VAR(__o) && _IS_CLASS((__o)->data.variable->data) ? (__o)->data.variable->data : 0))) # define _GET_CLASS(__o) ((!__o) ? 0 : (_IS_CLASS(__o) ? (__o) : (_IS_VAR(__o) && _IS_CLASS((__o)->data.variable->data) ? (__o)->data.variable->data : 0)))
# define _IS_ME(__v) (!!(__v)->isme)
#else /* MB_ENABLE_CLASS */
# define _IS_ME(__v) false
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
#define _IS_ROUTINE(__o) ((__o) && ((_object_t*)(__o))->type == _DT_ROUTINE) #define _IS_ROUTINE(__o) ((__o) && ((_object_t*)(__o))->type == _DT_ROUTINE)
#define _GET_ROUTINE(__o) ((!__o) ? 0 : (_IS_ROUTINE(__o) ? (__o) : (_IS_VAR(__o) && _IS_ROUTINE((__o)->data.variable->data) ? (__o)->data.variable->data : 0))) #define _GET_ROUTINE(__o) ((!__o) ? 0 : (_IS_ROUTINE(__o) ? (__o) : (_IS_VAR(__o) && _IS_ROUTINE((__o)->data.variable->data) ? (__o)->data.variable->data : 0)))
@ -263,6 +266,7 @@ static const char* _ERR_DESC[] = {
"Class expected", "Class expected",
"Duplicate class", "Duplicate class",
"Wrong meta class", "Wrong meta class",
"Cannot change ME",
"Invalid lambda", "Invalid lambda",
"List expected", "List expected",
"Collection expected", "Collection expected",
@ -326,6 +330,7 @@ typedef struct _var_t {
struct _object_t* data; struct _object_t* data;
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
int pathing; int pathing;
bool_t isme;
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
} _var_t; } _var_t;
@ -439,6 +444,7 @@ typedef struct _label_t {
} _label_t; } _label_t;
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
# define _CLASS_ME "ME"
# define _CLASS_HASH_FUNC "HASH" # define _CLASS_HASH_FUNC "HASH"
# define _CLASS_COMPARE_FUNC "COMPARE" # define _CLASS_COMPARE_FUNC "COMPARE"
# define _CLASS_TO_STRING_FUNC "TOSTRING" # define _CLASS_TO_STRING_FUNC "TOSTRING"
@ -1593,7 +1599,7 @@ static _var_t* _search_var_in_scope_chain(mb_interpreter_t* s, _var_t* i);
static _var_t* _create_var(_object_t** oobj, const char* n, size_t ns, bool_t dup_name); static _var_t* _create_var(_object_t** oobj, const char* n, size_t ns, bool_t dup_name);
static _object_t* _create_object(void); static _object_t* _create_object(void);
static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bool_t toupval); static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bool_t toupval, bool_t deep);
static int _dispose_object(_object_t* obj); static int _dispose_object(_object_t* obj);
static int _destroy_object(void* data, void* extra); static int _destroy_object(void* data, void* extra);
static int _destroy_object_with_extra(void* data, void* extra); static int _destroy_object_with_extra(void* data, void* extra);
@ -4521,6 +4527,13 @@ static int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object
(*obj)->ref = true; (*obj)->ref = true;
*delsym = true; *delsym = true;
} else { } else {
if(strcmp(sym, _CLASS_ME) == 0) {
_handle_error_now(s, SE_RN_CANNOT_CHANGE_ME, s->source_file, MB_FUNC_ERR);
(*obj)->ref = true;
*delsym = true;
goto _exit;
}
tmp.var = (_var_t*)mb_malloc(sizeof(_var_t)); tmp.var = (_var_t*)mb_malloc(sizeof(_var_t));
memset(tmp.var, 0, sizeof(_var_t)); memset(tmp.var, 0, sizeof(_var_t));
tmp.var->name = sym; tmp.var->name = sym;
@ -6672,7 +6685,7 @@ static int _clone_to_list(void* data, void* extra, _list_t* coll) {
tgt = _create_object(); tgt = _create_object();
obj = (_object_t*)data; obj = (_object_t*)data;
_clone_object(coll->ref.s, obj, tgt, false); _clone_object(coll->ref.s, obj, tgt, false, false);
_push_list(coll, 0, tgt); _push_list(coll, 0, tgt);
_REF(tgt) _REF(tgt)
@ -6690,11 +6703,11 @@ static int _clone_to_dict(void* data, void* extra, _dict_t* coll) {
ktgt = _create_object(); ktgt = _create_object();
kobj = (_object_t*)extra; kobj = (_object_t*)extra;
_clone_object(coll->ref.s, kobj, ktgt, false); _clone_object(coll->ref.s, kobj, ktgt, false, false);
vtgt = _create_object(); vtgt = _create_object();
vobj = (_object_t*)data; vobj = (_object_t*)data;
_clone_object(coll->ref.s, vobj, vtgt, false); _clone_object(coll->ref.s, vobj, vtgt, false, false);
_set_dict(coll, 0, 0, ktgt, vtgt); _set_dict(coll, 0, 0, ktgt, vtgt);
_REF(ktgt) _REF(ktgt)
@ -6726,6 +6739,8 @@ static int _copy_list_to_array(void* data, void* extra, _array_helper_t* h) {
static void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) { static void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
/* Initialize a class */ /* Initialize a class */
_running_context_t* running = 0; _running_context_t* running = 0;
_object_t* meobj = 0;
_var_t* me = 0;
mb_assert(s && instance && n); mb_assert(s && instance && n);
@ -6738,6 +6753,13 @@ static void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
instance->meta_list = _ls_create(); instance->meta_list = _ls_create();
instance->scope = _create_running_context(true); instance->scope = _create_running_context(true);
instance->created_from = instance; instance->created_from = instance;
me = _create_var(&meobj, _CLASS_ME, strlen(_CLASS_ME) + 1, true);
me->data->type = _DT_CLASS;
me->data->data.instance = instance;
me->pathing = 1;
me->isme = true;
_ht_set_or_insert(instance->scope->var_dict, me->name, meobj);
} }
static void _begin_class(mb_interpreter_t* s) { static void _begin_class(mb_interpreter_t* s) {
@ -6898,8 +6920,10 @@ static int _clone_clsss_field(void* data, void* extra, void* n) {
switch(obj->type) { switch(obj->type) {
case _DT_VAR: case _DT_VAR:
var = obj->data.variable; var = obj->data.variable;
if(!_IS_ME(var)) {
ret = _duplicate_parameter(var, 0, instance->scope); ret = _duplicate_parameter(var, 0, instance->scope);
_clone_object(instance->ref.s, obj, ret->data.variable->data, false); _clone_object(instance->ref.s, obj, ret->data.variable->data, false, false);
}
break; break;
case _DT_ARRAY: case _DT_ARRAY:
@ -6908,7 +6932,7 @@ static int _clone_clsss_field(void* data, void* extra, void* n) {
ret = _create_object(); ret = _create_object();
ret->type = _DT_ARRAY; ret->type = _DT_ARRAY;
ret->ref = false; ret->ref = false;
_clone_object(instance->ref.s, obj, ret, false); _clone_object(instance->ref.s, obj, ret, false, false);
_ht_set_or_insert(instance->scope->var_dict, ret->data.array->name, ret); _ht_set_or_insert(instance->scope->var_dict, ret->data.array->name, ret);
} }
@ -7403,7 +7427,7 @@ static int _fill_with_upvalue(void* data, void* extra, void* p) {
_object_t* ovar = 0; _object_t* ovar = 0;
_var_t* var = _create_var(&ovar, n, 0, true); _var_t* var = _create_var(&ovar, n, 0, true);
obj = (_object_t*)nori->data; obj = (_object_t*)nori->data;
_clone_object(tuple->s, obj, var->data, true); _clone_object(tuple->s, obj, var->data, true, true);
_REF(var->data) _REF(var->data)
if(_IS_ROUTINE(obj) && obj->data.routine->type != _IT_LAMBDA) { if(_IS_ROUTINE(obj) && obj->data.routine->type != _IT_LAMBDA) {
ovar->ref = true; ovar->ref = true;
@ -7983,7 +8007,7 @@ static _object_t* _create_object(void) {
return result; return result;
} }
static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bool_t toupval) { static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bool_t toupval, bool_t deep) {
/* Clone the data of an object */ /* Clone the data of an object */
int result = 0; int result = 0;
@ -7996,7 +8020,7 @@ static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bo
tgt->type = obj->type; tgt->type = obj->type;
switch(obj->type) { switch(obj->type) {
case _DT_VAR: case _DT_VAR:
_clone_object(s, obj->data.variable->data, tgt, toupval); _clone_object(s, obj->data.variable->data, tgt, toupval, deep);
break; break;
case _DT_STRING: case _DT_STRING:
@ -8011,6 +8035,7 @@ static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bo
obj->data.usertype_ref->dtor, obj->data.usertype_ref->clone, obj->data.usertype_ref->dtor, obj->data.usertype_ref->clone,
obj->data.usertype_ref->hash, obj->data.usertype_ref->cmp, obj->data.usertype_ref->fmt obj->data.usertype_ref->hash, obj->data.usertype_ref->cmp, obj->data.usertype_ref->fmt
); );
memcpy(&tgt->data.usertype_ref->overrides, &obj->data.usertype_ref->overrides, sizeof(_override_func_info_t));
_ref(&tgt->data.usertype_ref->ref, tgt->data.usertype_ref); _ref(&tgt->data.usertype_ref->ref, tgt->data.usertype_ref);
break; break;
@ -8021,14 +8046,26 @@ static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bo
break; break;
case _DT_ARRAY: case _DT_ARRAY:
if(deep) {
tgt->data.array = _clone_array(s, obj->data.array); tgt->data.array = _clone_array(s, obj->data.array);
} else {
tgt->data.array = obj->data.array;
#ifdef MB_ENABLE_ARRAY_REF
_ref(&obj->data.array->ref, obj->data.array);
#endif /* MB_ENABLE_ARRAY_REF */
}
break; break;
#ifdef MB_ENABLE_COLLECTION_LIB #ifdef MB_ENABLE_COLLECTION_LIB
case _DT_LIST: case _DT_LIST:
if(deep) {
tgt->data.list = _create_list(obj->data.list->ref.s); tgt->data.list = _create_list(obj->data.list->ref.s);
_ref(&tgt->data.list->ref, tgt->data.list); _ref(&tgt->data.list->ref, tgt->data.list);
_LS_FOREACH(obj->data.list->list, _do_nothing_on_object, _clone_to_list, tgt->data.list); _LS_FOREACH(obj->data.list->list, _do_nothing_on_object, _clone_to_list, tgt->data.list);
} else {
tgt->data.list = obj->data.list;
_ref(&obj->data.list->ref, obj->data.list);
}
break; break;
case _DT_LIST_IT: case _DT_LIST_IT:
@ -8036,9 +8073,14 @@ static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bo
break; break;
case _DT_DICT: case _DT_DICT:
if(deep) {
tgt->data.dict = _create_dict(obj->data.dict->ref.s); tgt->data.dict = _create_dict(obj->data.dict->ref.s);
_ref(&tgt->data.dict->ref, tgt->data.dict); _ref(&tgt->data.dict->ref, tgt->data.dict);
_HT_FOREACH(obj->data.dict->dict, _do_nothing_on_object, _clone_to_dict, tgt->data.dict); _HT_FOREACH(obj->data.dict->dict, _do_nothing_on_object, _clone_to_dict, tgt->data.dict);
} else {
tgt->data.dict = obj->data.dict;
_ref(&obj->data.dict->ref, obj->data.dict);
}
break; break;
case _DT_DICT_IT: case _DT_DICT_IT:
@ -8053,12 +8095,17 @@ static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt, bo
break; break;
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
case _DT_CLASS: case _DT_CLASS:
if(deep) {
tgt->data.instance = (_class_t*)mb_malloc(sizeof(_class_t)); tgt->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
_init_class(s, tgt->data.instance, mb_strdup(obj->data.instance->name, 0)); _init_class(s, tgt->data.instance, mb_strdup(obj->data.instance->name, 0));
tgt->data.instance->created_from = obj->data.instance->created_from; tgt->data.instance->created_from = obj->data.instance->created_from;
_push_scope_by_class(s, tgt->data.instance->scope); _push_scope_by_class(s, tgt->data.instance->scope);
_traverse_class(obj->data.instance, _clone_clsss_field, _clone_class_meta_link, _META_LIST_MAX_DEPTH, false, tgt->data.instance, 0); _traverse_class(obj->data.instance, _clone_clsss_field, _clone_class_meta_link, _META_LIST_MAX_DEPTH, false, tgt->data.instance, 0);
_pop_scope(s, false); _pop_scope(s, false);
} else {
tgt->data.instance = obj->data.instance;
_ref(&obj->data.instance->ref, obj->data.instance);
}
break; break;
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
@ -8119,6 +8166,9 @@ static int _dispose_object(_object_t* obj) {
var = (_var_t*)obj->data.variable; var = (_var_t*)obj->data.variable;
safe_free(var->name); safe_free(var->name);
mb_assert(var->data->type != _DT_VAR); mb_assert(var->data->type != _DT_VAR);
if(_IS_ME(var))
_destroy_object_capsule_only(var->data, 0);
else
_destroy_object(var->data, 0); _destroy_object(var->data, 0);
safe_free(var); safe_free(var);
} }
@ -12374,9 +12424,13 @@ static int _core_let(mb_interpreter_t* s, void** l) {
if(result != MB_FUNC_OK) if(result != MB_FUNC_OK)
goto _exit; goto _exit;
} else if(obj->type == _DT_VAR) { } else if(obj->type == _DT_VAR) {
if(_IS_ME(obj->data.variable)) {
_handle_error_on_obj(s, SE_RN_CANNOT_CHANGE_ME, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
} else {
evar = obj->data.variable; evar = obj->data.variable;
var = _search_var_in_scope_chain(s, obj->data.variable); var = _search_var_in_scope_chain(s, obj->data.variable);
if(var == evar) evar = 0; if(var == evar) evar = 0;
}
} else { } else {
_handle_error_on_obj(s, SE_RN_VAR_OR_ARRAY_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_VAR_OR_ARRAY_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result);
} }
@ -13521,7 +13575,7 @@ static int _core_new(mb_interpreter_t* s, void** l) {
/* Fall through */ /* Fall through */
case MB_DT_CLASS: case MB_DT_CLASS:
_public_value_to_internal_object(&arg, &obj); _public_value_to_internal_object(&arg, &obj);
_clone_object(s, &obj, &tgt, false); _clone_object(s, &obj, &tgt, false, true);
ret.type = MB_DT_CLASS; ret.type = MB_DT_CLASS;
ret.value.instance = tgt.data.instance; ret.value.instance = tgt.data.instance;
@ -15546,14 +15600,14 @@ static int _coll_clone(mb_interpreter_t* s, void** l) {
switch(coll.type) { switch(coll.type) {
case MB_DT_LIST: case MB_DT_LIST:
_public_value_to_internal_object(&coll, &ocoll); _public_value_to_internal_object(&coll, &ocoll);
_clone_object(s, &ocoll, &otgt, false); _clone_object(s, &ocoll, &otgt, false, true);
ret.type = MB_DT_LIST; ret.type = MB_DT_LIST;
ret.value.list = otgt.data.list; ret.value.list = otgt.data.list;
break; break;
case MB_DT_DICT: case MB_DT_DICT:
_public_value_to_internal_object(&coll, &ocoll); _public_value_to_internal_object(&coll, &ocoll);
_clone_object(s, &ocoll, &otgt, false); _clone_object(s, &ocoll, &otgt, false, true);
ret.type = MB_DT_DICT; ret.type = MB_DT_DICT;
ret.value.dict = otgt.data.dict; ret.value.dict = otgt.data.dict;

View File

@ -338,6 +338,7 @@ typedef enum mb_error_e {
SE_RN_CLASS_EXPECTED, SE_RN_CLASS_EXPECTED,
SE_RN_DUPLICATE_CLASS, SE_RN_DUPLICATE_CLASS,
SE_RN_WRONG_META_CLASS, SE_RN_WRONG_META_CLASS,
SE_RN_CANNOT_CHANGE_ME,
SE_RN_INVALID_LAMBDA, SE_RN_INVALID_LAMBDA,
SE_RN_LIST_EXPECTED, SE_RN_LIST_EXPECTED,
SE_RN_COLLECTION_EXPECTED, SE_RN_COLLECTION_EXPECTED,

Binary file not shown.