+developing class, added a NEW statement to duplicate a class instance.
This commit is contained in:
parent
fd85f4fd44
commit
072f32197c
3
HISTORY
3
HISTORY
@ -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
|
||||||
|
161
core/my_basic.c
161
core/my_basic.c
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user