+developing class, added a NEW statement to duplicate a class instance.

This commit is contained in:
paladin-t 2015-12-10 15:21:46 +08:00
parent fd85f4fd44
commit 072f32197c
2 changed files with 142 additions and 22 deletions

View File

@ -1,3 +1,6 @@
Dec. 10 2015
Developing class, added a NEW statement to duplicate a class instance
Dec. 9 2015 Dec. 9 2015
Developing class, added accessing by identifier Developing class, added accessing by identifier
Developing class, added a VAR statement Developing class, added a VAR statement

View File

@ -81,7 +81,7 @@ extern "C" {
/** Macros */ /** Macros */
#define _VER_MAJOR 1 #define _VER_MAJOR 1
#define _VER_MINOR 1 #define _VER_MINOR 1
#define _VER_REVISION 104 #define _VER_REVISION 105
#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)
@ -1198,23 +1198,26 @@ static int _clone_to_dict(void* data, void* extra, _dict_t* coll);
#endif /* MB_ENABLE_COLLECTION_LIB */ #endif /* MB_ENABLE_COLLECTION_LIB */
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
typedef int (* _class_walker)(void*, void*, void*); typedef int (* _class_scope_walker)(void*, void*, void*);
typedef int (* _class_meta_walker)(_class_t*, void*);
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);
static void _begin_class(mb_interpreter_t* s); static void _begin_class(mb_interpreter_t* s);
static bool_t _end_class(mb_interpreter_t* s); static bool_t _end_class(mb_interpreter_t* s);
static void _unref_class(_ref_t* ref, void* data); static void _unref_class(_ref_t* ref, void* data);
static void _destroy_class(_class_t* c); static void _destroy_class(_class_t* c);
static int _traverse_class(_class_t* c, _class_walker walker, void* extra_data); static int _traverse_class(_class_t* c, _class_scope_walker scope_walker, _class_meta_walker meta_walker, int meta_depth, void* extra_data);
static bool_t _link_meta_class(mb_interpreter_t* s, _class_t* derived, _class_t* base); static bool_t _link_meta_class(mb_interpreter_t* s, _class_t* derived, _class_t* base);
static void _unlink_meta_class(mb_interpreter_t* s, _class_t* derived); static void _unlink_meta_class(mb_interpreter_t* s, _class_t* derived);
static int _unlink_meta_instance(void* data, void* extra, _class_t* derived); static int _unlink_meta_instance(void* data, void* extra, _class_t* derived);
static int _clone_clsss_field(void* data, void* extra, void* n);
static int _clone_class_meta_link(_class_t* meta, void* n);
#endif /* MB_ENABLE_CLASS */ #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);
static void _begin_routine(mb_interpreter_t* s); static void _begin_routine(mb_interpreter_t* s);
static bool_t _end_routine(mb_interpreter_t* s); static bool_t _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 void _duplicate_parameter(void* data, void* extra, _running_context_t* running); static _object_t* _duplicate_parameter(void* data, void* extra, _running_context_t* running);
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
static _running_context_t* _reference_scope_by_class(mb_interpreter_t* s, _running_context_t* p, _class_t* c); static _running_context_t* _reference_scope_by_class(mb_interpreter_t* s, _running_context_t* p, _class_t* c);
static _running_context_t* _push_scope_by_class(mb_interpreter_t* s, _running_context_t* p); static _running_context_t* _push_scope_by_class(mb_interpreter_t* s, _running_context_t* p);
@ -1233,7 +1236,7 @@ static _ls_node_t* _search_identifier_in_scope_chain(mb_interpreter_t* s, _runni
static _array_t* _search_array_in_scope_chain(mb_interpreter_t* s, _array_t* i, _object_t** o); static _array_t* _search_array_in_scope_chain(mb_interpreter_t* s, _array_t* i, _object_t** o);
static _var_t* _search_var_in_scope_chain(mb_interpreter_t* s, _var_t* i); static _var_t* _search_var_in_scope_chain(mb_interpreter_t* s, _var_t* i);
static int _clone_object(_object_t* obj, _object_t* tgt); static int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt);
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);
@ -1374,6 +1377,7 @@ static int _core_enddef(mb_interpreter_t* s, void** l);
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
static int _core_class(mb_interpreter_t* s, void** l); static int _core_class(mb_interpreter_t* s, void** l);
static int _core_endclass(mb_interpreter_t* s, void** l); static int _core_endclass(mb_interpreter_t* s, void** l);
static int _core_new(mb_interpreter_t* s, void** l);
static int _core_var(mb_interpreter_t* s, void** l); static int _core_var(mb_interpreter_t* s, void** l);
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
#ifdef MB_ENABLE_ALLOC_STAT #ifdef MB_ENABLE_ALLOC_STAT
@ -1484,6 +1488,7 @@ static const _func_t _core_libs[] = {
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
{ "CLASS", _core_class }, { "CLASS", _core_class },
{ "ENDCLASS", _core_endclass }, { "ENDCLASS", _core_endclass },
{ "NEW", _core_new },
{ "VAR", _core_var }, { "VAR", _core_var },
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
@ -4215,7 +4220,7 @@ int _gc_add_reachable(void* data, void* extra, void* ht) {
case _DT_CLASS: case _DT_CLASS:
if(!_ht_find(htable, &obj->data.instance->ref)) { if(!_ht_find(htable, &obj->data.instance->ref)) {
_ht_set_or_insert(htable, &obj->data.instance->ref, obj->data.instance); _ht_set_or_insert(htable, &obj->data.instance->ref, obj->data.instance);
_traverse_class(obj->data.instance, _gc_add_reachable, htable); _traverse_class(obj->data.instance, _gc_add_reachable, 0, 0, htable);
} }
break; break;
@ -5189,7 +5194,7 @@ int _clone_to_list(void* data, void* extra, _list_t* coll) {
tgt = (_object_t*)mb_malloc(sizeof(_object_t)); tgt = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(tgt); _MAKE_NIL(tgt);
obj = (_object_t*)data; obj = (_object_t*)data;
_clone_object(obj, tgt); _clone_object(coll->ref.s, obj, tgt);
_push_list(coll, 0, tgt); _push_list(coll, 0, tgt);
_REF(tgt) _REF(tgt)
@ -5208,12 +5213,12 @@ int _clone_to_dict(void* data, void* extra, _dict_t* coll) {
ktgt = (_object_t*)mb_malloc(sizeof(_object_t)); ktgt = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(ktgt); _MAKE_NIL(ktgt);
kobj = (_object_t*)extra; kobj = (_object_t*)extra;
_clone_object(kobj, ktgt); _clone_object(coll->ref.s, kobj, ktgt);
vtgt = (_object_t*)mb_malloc(sizeof(_object_t)); vtgt = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(vtgt); _MAKE_NIL(vtgt);
vobj = (_object_t*)data; vobj = (_object_t*)data;
_clone_object(vobj, vtgt); _clone_object(coll->ref.s, vobj, vtgt);
_set_dict(coll, 0, 0, ktgt, vtgt); _set_dict(coll, 0, 0, ktgt, vtgt);
_REF(ktgt) _REF(ktgt)
@ -5292,20 +5297,29 @@ void _destroy_class(_class_t* c) {
safe_free(c); safe_free(c);
} }
int _traverse_class(_class_t* c, _class_walker walker, void* extra_data) { int _traverse_class(_class_t* c, _class_scope_walker scope_walker, _class_meta_walker meta_walker, int meta_depth, void* extra_data) {
/* Traverse all fields of a class instance */ /* Traverse all fields of a class instance, and its meta class instances recursively as well */
int result = 0; int result = 0;
_ls_node_t* node = 0; _ls_node_t* node = 0;
_class_t* meta = 0; _class_t* meta = 0;
mb_assert(c && walker); mb_assert(c);
result++; result++;
_HT_FOREACH(c->scope->var_dict, _do_nothing_on_object, walker, extra_data); if(scope_walker) {
_HT_FOREACH(c->scope->var_dict, _do_nothing_on_object, scope_walker, extra_data);
}
node = c->meta_list ? c->meta_list->next : 0; node = c->meta_list ? c->meta_list->next : 0;
while(node) { while(node) {
meta = (_class_t*)node->data; meta = (_class_t*)node->data;
result += _traverse_class(meta, walker, extra_data); if(meta_walker && meta_depth)
meta_walker(meta, extra_data);
result += _traverse_class(
meta,
scope_walker,
meta_walker, meta_depth ? meta_depth - 1 : 0,
extra_data
);
node = node->next; node = node->next;
} }
@ -5348,6 +5362,62 @@ int _unlink_meta_instance(void* data, void* extra, _class_t* derived) {
return 0; return 0;
} }
int _clone_clsss_field(void* data, void* extra, void* n) {
/* Clone fields of a class instance to another */
int result = _OP_RESULT_NORMAL;
_object_t* obj = 0;
_var_t* var = 0;
_routine_t* sub = 0;
_class_t* instance = (_class_t*)n;
_object_t* ret = 0;
mb_unrefvar(extra);
mb_assert(data && n);
obj = (_object_t*)data;
if(_is_internal_object(obj))
goto _exit;
switch(obj->type) {
case _DT_VAR:
var = (_var_t*)(obj->data.variable);
if(!_search_identifier_in_scope_chain(instance->ref.s, instance->scope, var->name, 0)) {
ret = _duplicate_parameter(var, 0, instance->scope);
_clone_object(instance->ref.s, obj, ret->data.variable->data);
}
break;
case _DT_ROUTINE:
sub = (_routine_t*)(obj->data.routine);
if(!_search_identifier_in_scope_chain(instance->ref.s, instance->scope, sub->name, 0)) {
ret = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(ret);
ret->type = _DT_ROUTINE;
ret->data.routine = sub;
ret->ref = true;
_ht_set_or_insert(instance->scope->var_dict, obj->data.routine->name, ret);
}
break;
default: /* Do nothing */
break;
}
_exit:
return result;
}
int _clone_class_meta_link(_class_t* meta, void* n) {
/* Link meta class to a new instance */
_class_t* instance = (_class_t*)n;
mb_assert(meta && n);
_link_meta_class(instance->ref.s, instance, meta);
return MB_FUNC_OK;
}
#endif /* MB_ENABLE_CLASS */ #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) {
@ -5412,7 +5482,7 @@ void _end_routine_parameter_list(mb_interpreter_t* s) {
context->routine_params_state--; context->routine_params_state--;
} }
void _duplicate_parameter(void* data, void* extra, _running_context_t* running) { _object_t* _duplicate_parameter(void* data, void* extra, _running_context_t* running) {
/* Duplicate a parameter from a parameter list to variable dictionary */ /* Duplicate a parameter from a parameter list to variable dictionary */
_var_t* ref = 0; _var_t* ref = 0;
_var_t* var = 0; _var_t* var = 0;
@ -5422,7 +5492,7 @@ void _duplicate_parameter(void* data, void* extra, _running_context_t* running)
mb_assert(running); mb_assert(running);
if(data == 0) if(data == 0)
return; return 0;
ref = (_var_t*)(data); ref = (_var_t*)(data);
@ -5441,6 +5511,8 @@ void _duplicate_parameter(void* data, void* extra, _running_context_t* running)
obj->ref = false; obj->ref = false;
_ht_set_or_insert(running->var_dict, var->name, obj); _ht_set_or_insert(running->var_dict, var->name, obj);
return obj;
} }
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
@ -5761,7 +5833,7 @@ _var_t* _search_var_in_scope_chain(mb_interpreter_t* s, _var_t* i) {
return result; return result;
} }
int _clone_object(_object_t* obj, _object_t* tgt) { int _clone_object(mb_interpreter_t* s, _object_t* obj, _object_t* tgt) {
/* Clone the data of an object */ /* Clone the data of an object */
int result = 0; int result = 0;
@ -5774,7 +5846,7 @@ int _clone_object(_object_t* obj, _object_t* tgt) {
tgt->type = obj->type; tgt->type = obj->type;
switch(obj->type) { switch(obj->type) {
case _DT_VAR: case _DT_VAR:
_clone_object(obj->data.variable->data, tgt); _clone_object(s, obj->data.variable->data, tgt);
break; break;
case _DT_STRING: case _DT_STRING:
@ -5827,8 +5899,11 @@ int _clone_object(_object_t* obj, _object_t* tgt) {
break; break;
#ifdef MB_ENABLE_CLASS #ifdef MB_ENABLE_CLASS
case _DT_CLASS: case _DT_CLASS:
mb_assert(0 && "Not implemented."); tgt->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
/* TODO */ _init_class(s, tgt->data.instance, mb_memdup(obj->data.instance->name, strlen(obj->data.instance->name)));
_push_scope_by_class(s, tgt->data.instance->scope);
_traverse_class(obj->data.instance, _clone_clsss_field, _clone_class_meta_link, 1, tgt->data.instance);
_pop_scope(s);
break; break;
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
@ -10167,6 +10242,48 @@ _exit:
return result; return result;
} }
int _core_new(mb_interpreter_t* s, void** l) {
/* NEW statement */
int result = MB_FUNC_OK;
mb_value_t arg;
_object_t obj;
_object_t tgt;
mb_value_t ret;
mb_assert(s && l);
mb_make_nil(ret);
mb_check(mb_attempt_func_begin(s, l));
mb_check(mb_pop_value(s, l, &arg));
mb_check(mb_attempt_func_end(s, l));
_MAKE_NIL(&obj);
switch(arg.type) {
case MB_DT_CLASS:
_public_value_to_internal_object(&arg, &obj);
_clone_object(s, &obj, &tgt);
ret.type = MB_DT_CLASS;
ret.value.instance = tgt.data.instance;
break;
default:
_handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, TON(l), MB_FUNC_ERR, _exit, result);
break;
}
mb_check(mb_push_value(s, l, ret));
_assign_public_value(&ret, 0);
_exit:
_assign_public_value(&arg, 0);
return result;
}
int _core_var(mb_interpreter_t* s, void** l) { int _core_var(mb_interpreter_t* s, void** l) {
/* VAR statement */ /* VAR statement */
int result = MB_FUNC_IGNORE; int result = MB_FUNC_IGNORE;
@ -11806,14 +11923,14 @@ 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(&ocoll, &otgt); _clone_object(s, &ocoll, &otgt);
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(&ocoll, &otgt); _clone_object(s, &ocoll, &otgt);
ret.type = MB_DT_DICT; ret.type = MB_DT_DICT;
ret.value.dict = otgt.data.dict; ret.value.dict = otgt.data.dict;