+added support to put a class instance into a variable; *polished code.

This commit is contained in:
paladin-t 2015-12-25 16:28:44 +08:00
parent a55e3e7d07
commit f543e77446
3 changed files with 87 additions and 37 deletions

View File

@ -1,5 +1,7 @@
Dec. 25 2015 Dec. 25 2015
Added support to put a class instance into a variable
Fixed a memory leak in class definition Fixed a memory leak in class definition
Polished code
Dec. 24 2015 Dec. 24 2015
Improved defining a class in C Improved defining a class in C

Binary file not shown.

View File

@ -84,7 +84,7 @@ extern "C" {
/** Macros */ /** Macros */
#define _VER_MAJOR 1 #define _VER_MAJOR 1
#define _VER_MINOR 1 #define _VER_MINOR 1
#define _VER_REVISION 108 #define _VER_REVISION 109
#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)
@ -95,11 +95,14 @@ extern "C" {
# define _MB_VERSION_STRING _STRINGIZE(_VER_MAJOR._VER_MINOR._VER_REVISION _VER_SUFFIX) # define _MB_VERSION_STRING _STRINGIZE(_VER_MAJOR._VER_MINOR._VER_REVISION _VER_SUFFIX)
#endif /* _VER_REVISION == 0 */ #endif /* _VER_REVISION == 0 */
/* Uncomment the line below to treat warning as error */ /* Define as 1 to treat warning as error, 0 just leave it */
/*#define _WARING_AS_ERROR*/ #define _WARING_AS_ERROR 0
/* Uncomment this line to use a comma to PRINT a new line, otherwise use a semicolon */ /* Define as 1 to create class instance without variable, 0 to put class instance into a variable */
/*#define _COMMA_AS_NEWLINE*/ #define _CLASS_IN_VAR 1
/* Define as 1 to use a comma to PRINT a new line, 0 to use a semicolon */
#define _COMMA_AS_NEWLINE 0
#define _NO_EAT_COMMA 2 #define _NO_EAT_COMMA 2
@ -128,10 +131,12 @@ extern "C" {
#define _IS_EOS(__o) (__o && ((_object_t*)(__o))->type == _DT_EOS) #define _IS_EOS(__o) (__o && ((_object_t*)(__o))->type == _DT_EOS)
#define _IS_SEP(__o, __c) (((_object_t*)(__o))->type == _DT_SEP && ((_object_t*)(__o))->data.separator == __c) #define _IS_SEP(__o, __c) (((_object_t*)(__o))->type == _DT_SEP && ((_object_t*)(__o))->data.separator == __c)
#define _IS_FUNC(__o, __f) (((_object_t*)(__o))->type == _DT_FUNC && ((_object_t*)(__o))->data.func->pointer == __f) #define _IS_FUNC(__o, __f) (((_object_t*)(__o))->type == _DT_FUNC && ((_object_t*)(__o))->data.func->pointer == __f)
#define _IS_VAR(__o) ((__o) && ((_object_t*)(__o))->type == _DT_VAR)
#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)))
#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)
/* Hash table size */ /* Hash table size */
#define _HT_ARRAY_SIZE_TINY 1 #define _HT_ARRAY_SIZE_TINY 1
@ -1005,7 +1010,7 @@ static bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj);
(__result)); \ (__result)); \
} \ } \
} while(0) } while(0)
#ifdef _WARING_AS_ERROR #if _WARING_AS_ERROR
# define _handle_error(__s, __err, __func, __pos, __row, __col, __ret, __exit, __result) \ # define _handle_error(__s, __err, __func, __pos, __row, __col, __ret, __exit, __result) \
do { \ do { \
_set_current_error((__s), (__err), (__func)); \ _set_current_error((__s), (__err), (__func)); \
@ -1265,6 +1270,7 @@ 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_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 _clone_class_meta_link(_class_t* meta, void* n, void* ret);
static bool_t _is_class(_class_t* instance, void* m, void* ret); static bool_t _is_class(_class_t* instance, void* m, void* ret);
static bool_t _add_class_meta_reachable(_class_t* meta, void* ht, void* ret);
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n, mb_routine_func_t f); 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 void _begin_routine(mb_interpreter_t* s);
@ -1290,6 +1296,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 _var_t* _create_var(_object_t** oobj, const char* n, bool_t dup_name);
static int _clone_object(mb_interpreter_t* s, _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);
@ -3531,9 +3538,30 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
_push_scope_by_class(s, (*obj)->data.instance->scope); _push_scope_by_class(s, (*obj)->data.instance->scope);
} }
} else { } else {
_var_t* var = 0;
tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t)); tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t));
_init_class(s, tmp.instance, sym); _init_class(s, tmp.instance, sym);
_push_scope_by_class(s, tmp.instance->scope); _push_scope_by_class(s, tmp.instance->scope);
s->last_instance = tmp.instance;
#if _CLASS_IN_VAR
var = _create_var(obj, sym, true);
ul = _ht_set_or_insert(running->var_dict, sym, *obj);
mb_assert(ul);
var->data->type = _DT_CLASS;
var->data->data.instance = tmp.instance;
*obj = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(*obj);
(*obj)->type = type;
(*obj)->data.variable = tmp.var;
(*obj)->ref = true;
#else /* _CLASS_IN_VAR */
mb_unrefvar(var);
(*obj)->data.instance = tmp.instance; (*obj)->data.instance = tmp.instance;
ul = _ht_set_or_insert(running->var_dict, sym, *obj); ul = _ht_set_or_insert(running->var_dict, sym, *obj);
@ -3544,8 +3572,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
(*obj)->type = type; (*obj)->type = type;
(*obj)->data.instance = tmp.instance; (*obj)->data.instance = tmp.instance;
(*obj)->ref = true; (*obj)->ref = true;
#endif /* _CLASS_IN_VAR */
s->last_instance = tmp.instance;
} }
break; break;
@ -4345,7 +4372,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, 0, 0, false, htable, 0); _traverse_class(obj->data.instance, _gc_add_reachable, _add_class_meta_reachable, _META_LIST_MAX_DEPTH, false, htable, 0);
} }
break; break;
@ -5651,6 +5678,19 @@ bool_t _is_class(_class_t* instance, void* m, void* ret) {
return !(*r); return !(*r);
} }
bool_t _add_class_meta_reachable(_class_t* meta, void* ht, void* ret) {
/* Add a meta class instance to a GC reachable table */
_ht_node_t* htable = (_ht_node_t*)ht;
mb_unrefvar(ret);
mb_assert(meta && ht);
if(!_ht_find(htable, &meta->ref))
_ht_set_or_insert(htable, &meta->ref, meta);
return true;
}
#endif /* MB_ENABLE_CLASS */ #endif /* MB_ENABLE_CLASS */
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n, mb_routine_func_t f) { void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n, mb_routine_func_t f) {
@ -5734,19 +5774,7 @@ _object_t* _duplicate_parameter(void* data, void* extra, _running_context_t* run
ref = (_var_t*)(data); ref = (_var_t*)(data);
var = (_var_t*)mb_malloc(sizeof(_var_t)); var = _create_var(&obj, ref->name, true);
memset(var, 0, sizeof(_var_t));
var->name = mb_memdup(ref->name, (unsigned)(strlen(ref->name) + 1));
var->data = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(var->data);
var->data->type = _DT_NIL;
var->data->data.integer = 0;
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); _ht_set_or_insert(running->var_dict, var->name, obj);
@ -6081,6 +6109,34 @@ _var_t* _search_var_in_scope_chain(mb_interpreter_t* s, _var_t* i) {
return result; return result;
} }
_var_t* _create_var(_object_t** oobj, const char* n, bool_t dup_name) {
/* Create a variable object */
_object_t* obj = 0;
_var_t* var = 0;
var = (_var_t*)mb_malloc(sizeof(_var_t));
memset(var, 0, sizeof(_var_t));
if(dup_name)
var->name = mb_memdup(n, (unsigned)(strlen(n) + 1));
else
var->name = (char*)n;
var->data = (_object_t*)mb_malloc(sizeof(_object_t));
_MAKE_NIL(var->data);
if(!oobj || !(*oobj))
obj = (_object_t*)mb_malloc(sizeof(_object_t));
else
obj = *oobj;
_MAKE_NIL(obj);
obj->type = _DT_VAR;
obj->data.variable = var;
obj->ref = false;
if(oobj) *oobj = obj;
return var;
}
int _clone_object(mb_interpreter_t* s, _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;
@ -8392,19 +8448,9 @@ int mb_add_var(struct mb_interpreter_t* s, void** l, const char* n, mb_value_t v
} }
} }
var = (_var_t*)mb_malloc(sizeof(_var_t)); var = _create_var(&obj, n, true);
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); _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); _ht_set_or_insert(running->var_dict, var->name, obj);
_exit: _exit:
@ -10838,10 +10884,11 @@ int _core_class(mb_interpreter_t* s, void** l) {
_using_jump_set_of_structured(s, ast, _exit, result); _using_jump_set_of_structured(s, ast, _exit, result);
obj = (_object_t*)(ast->data); obj = (_object_t*)(ast->data);
obj = _GET_CLASS(obj);
if(!_IS_CLASS(obj)) { if(!_IS_CLASS(obj)) {
_handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
} }
instance = (_class_t*)(((_object_t*)(ast->data))->data.instance); instance = obj->data.instance;
ast = ast->next; ast = ast->next;
obj = (_object_t*)(ast->data); obj = (_object_t*)(ast->data);
@ -10855,6 +10902,7 @@ int _core_class(mb_interpreter_t* s, void** l) {
if(tmp && tmp->data) if(tmp && tmp->data)
obj = (_object_t*)tmp->data; obj = (_object_t*)tmp->data;
} }
obj = _GET_CLASS(obj);
if(!_IS_CLASS(obj)) { if(!_IS_CLASS(obj)) {
_handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, obj, MB_FUNC_ERR, _exit, result); _handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, obj, MB_FUNC_ERR, _exit, result);
} }
@ -11973,7 +12021,7 @@ _print:
if(!ast) if(!ast)
break; break;
obj = (_object_t*)(ast->data); obj = (_object_t*)(ast->data);
#ifdef _COMMA_AS_NEWLINE #if _COMMA_AS_NEWLINE
if(obj->data.separator == ',') { if(obj->data.separator == ',') {
#else /* _COMMA_AS_NEWLINE */ #else /* _COMMA_AS_NEWLINE */
if(obj->data.separator == ';') { if(obj->data.separator == ';') {