+added support to put a class instance into a variable; *polished code.
This commit is contained in:
parent
a55e3e7d07
commit
f543e77446
2
HISTORY
2
HISTORY
@ -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.
122
core/my_basic.c
122
core/my_basic.c
@ -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 == ';') {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user