From f543e7744642eb33add83e9cc064802fcd23ef41 Mon Sep 17 00:00:00 2001 From: paladin-t Date: Fri, 25 Dec 2015 16:28:44 +0800 Subject: [PATCH] +added support to put a class instance into a variable; *polished code. --- HISTORY | 2 + MY-BASIC Quick Reference.pdf | Bin 254071 -> 254083 bytes core/my_basic.c | 122 ++++++++++++++++++++++++----------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/HISTORY b/HISTORY index 510da8a..075ea14 100755 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,7 @@ Dec. 25 2015 +Added support to put a class instance into a variable Fixed a memory leak in class definition +Polished code Dec. 24 2015 Improved defining a class in C diff --git a/MY-BASIC Quick Reference.pdf b/MY-BASIC Quick Reference.pdf index 13c988e6891d7e6846a05f557ffbcf00ebe91055..1741ecd01a68062448e2300e941667aea85d553e 100644 GIT binary patch delta 3158 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 PV)%L0)J$#6_<8>g^ri~1 delta 3141 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 diff --git a/core/my_basic.c b/core/my_basic.c index bcdda0f..14b33ad 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -84,7 +84,7 @@ extern "C" { /** Macros */ #define _VER_MAJOR 1 #define _VER_MINOR 1 -#define _VER_REVISION 108 +#define _VER_REVISION 109 #define _VER_SUFFIX #define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION)) #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) #endif /* _VER_REVISION == 0 */ -/* Uncomment the line below to treat warning as error */ -/*#define _WARING_AS_ERROR*/ +/* Define as 1 to treat warning as error, 0 just leave it */ +#define _WARING_AS_ERROR 0 -/* Uncomment this line to use a comma to PRINT a new line, otherwise use a semicolon */ -/*#define _COMMA_AS_NEWLINE*/ +/* Define as 1 to create class instance without variable, 0 to put class instance into a variable */ +#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 @@ -128,10 +131,12 @@ extern "C" { #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_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 -# 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 */ -#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 */ #define _HT_ARRAY_SIZE_TINY 1 @@ -1005,7 +1010,7 @@ static bool_t _is_print_terminal(mb_interpreter_t* s, _object_t* obj); (__result)); \ } \ } while(0) -#ifdef _WARING_AS_ERROR +#if _WARING_AS_ERROR # define _handle_error(__s, __err, __func, __pos, __row, __col, __ret, __exit, __result) \ do { \ _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 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 _add_class_meta_reachable(_class_t* meta, void* ht, void* ret); #endif /* MB_ENABLE_CLASS */ 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); @@ -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 _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 _dispose_object(_object_t* obj); 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); } } else { + _var_t* var = 0; + tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t)); _init_class(s, tmp.instance, sym); _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; 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)->data.instance = tmp.instance; (*obj)->ref = true; - - s->last_instance = tmp.instance; +#endif /* _CLASS_IN_VAR */ } break; @@ -4345,7 +4372,7 @@ int _gc_add_reachable(void* data, void* extra, void* ht) { case _DT_CLASS: if(!_ht_find(htable, &obj->data.instance->ref)) { _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; @@ -5651,6 +5678,19 @@ bool_t _is_class(_class_t* instance, void* m, void* ret) { 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 */ 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); - var = (_var_t*)mb_malloc(sizeof(_var_t)); - 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; + var = _create_var(&obj, ref->name, true); _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; } +_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) { /* Clone the data of an object */ 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)); - 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); + var = _create_var(&obj, n, true); _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: @@ -10838,10 +10884,11 @@ int _core_class(mb_interpreter_t* s, void** l) { _using_jump_set_of_structured(s, ast, _exit, result); obj = (_object_t*)(ast->data); + obj = _GET_CLASS(obj); if(!_IS_CLASS(obj)) { _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; obj = (_object_t*)(ast->data); @@ -10855,6 +10902,7 @@ int _core_class(mb_interpreter_t* s, void** l) { if(tmp && tmp->data) obj = (_object_t*)tmp->data; } + obj = _GET_CLASS(obj); if(!_IS_CLASS(obj)) { _handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, 0, obj, MB_FUNC_ERR, _exit, result); } @@ -11973,7 +12021,7 @@ _print: if(!ast) break; obj = (_object_t*)(ast->data); -#ifdef _COMMA_AS_NEWLINE +#if _COMMA_AS_NEWLINE if(obj->data.separator == ',') { #else /* _COMMA_AS_NEWLINE */ if(obj->data.separator == ';') {