*polished sample script; *fixed a memory leak with gc caused by reference cycle; *finished internal class development.
This commit is contained in:
parent
a426e150ae
commit
ef79101296
2
HISTORY
2
HISTORY
@ -1,6 +1,8 @@
|
|||||||
Dec. 11 2015
|
Dec. 11 2015
|
||||||
Added an IS statement to detect type equality of a value
|
Added an IS statement to detect type equality of a value
|
||||||
Added support to store a routine in a variable by CALL statement
|
Added support to store a routine in a variable by CALL statement
|
||||||
|
Fixed a memory leak with GC caused by reference cycle
|
||||||
|
Finished internal class development
|
||||||
|
|
||||||
Dec. 10 2015
|
Dec. 10 2015
|
||||||
Developing class, added a NEW statement to duplicate a class instance
|
Developing class, added a NEW statement to duplicate a class instance
|
||||||
|
193
core/my_basic.c
193
core/my_basic.c
@ -82,7 +82,7 @@ extern "C" {
|
|||||||
/** Macros */
|
/** Macros */
|
||||||
#define _VER_MAJOR 1
|
#define _VER_MAJOR 1
|
||||||
#define _VER_MINOR 1
|
#define _VER_MINOR 1
|
||||||
#define _VER_REVISION 105
|
#define _VER_REVISION 106
|
||||||
#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)
|
||||||
@ -312,6 +312,8 @@ typedef short _lock_t;
|
|||||||
#ifdef MB_ENABLE_GC
|
#ifdef MB_ENABLE_GC
|
||||||
typedef struct _gc_t {
|
typedef struct _gc_t {
|
||||||
_ht_node_t* table;
|
_ht_node_t* table;
|
||||||
|
_ht_node_t* recursive_table;
|
||||||
|
_ht_node_t* collected_table;
|
||||||
int_t collecting;
|
int_t collecting;
|
||||||
} _gc_t;
|
} _gc_t;
|
||||||
#endif /* MB_ENABLE_GC */
|
#endif /* MB_ENABLE_GC */
|
||||||
@ -1072,6 +1074,10 @@ static char* _extract_string(_object_t* obj);
|
|||||||
case _DT_USERTYPE_REF: \
|
case _DT_USERTYPE_REF: \
|
||||||
_unref(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref); \
|
_unref(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref); \
|
||||||
break;
|
break;
|
||||||
|
#define _ADDGC_USERTYPE_REF(__o, __g) \
|
||||||
|
case _DT_USERTYPE_REF: \
|
||||||
|
_gc_add(&(__o)->data.usertype_ref->ref, (__o)->data.usertype_ref, (__g)); \
|
||||||
|
break;
|
||||||
#define _REF_ARRAY(__o) \
|
#define _REF_ARRAY(__o) \
|
||||||
case _DT_ARRAY: \
|
case _DT_ARRAY: \
|
||||||
if(!(__o)->ref) \
|
if(!(__o)->ref) \
|
||||||
@ -1082,6 +1088,11 @@ static char* _extract_string(_object_t* obj);
|
|||||||
if(!(__o)->ref) \
|
if(!(__o)->ref) \
|
||||||
_unref(&(__o)->data.array->ref, (__o)->data.array); \
|
_unref(&(__o)->data.array->ref, (__o)->data.array); \
|
||||||
break;
|
break;
|
||||||
|
#define _ADDGC_ARRAY(__o, __g) \
|
||||||
|
case _DT_ARRAY: \
|
||||||
|
if(!(__o)->ref) \
|
||||||
|
_gc_add(&(__o)->data.array->ref, (__o)->data.array, (__g)); \
|
||||||
|
break;
|
||||||
#ifdef MB_ENABLE_COLLECTION_LIB
|
#ifdef MB_ENABLE_COLLECTION_LIB
|
||||||
# define _REF_COLL(__o) \
|
# define _REF_COLL(__o) \
|
||||||
case _DT_LIST: \
|
case _DT_LIST: \
|
||||||
@ -1097,6 +1108,13 @@ static char* _extract_string(_object_t* obj);
|
|||||||
case _DT_DICT: \
|
case _DT_DICT: \
|
||||||
_unref(&(__o)->data.dict->ref, (__o)->data.dict); \
|
_unref(&(__o)->data.dict->ref, (__o)->data.dict); \
|
||||||
break;
|
break;
|
||||||
|
# define _ADDGC_COLL(__o, __g) \
|
||||||
|
case _DT_LIST: \
|
||||||
|
_gc_add(&(__o)->data.list->ref, (__o)->data.list, (__g)); \
|
||||||
|
break; \
|
||||||
|
case _DT_DICT: \
|
||||||
|
_gc_add(&(__o)->data.dict->ref, (__o)->data.dict, (__g)); \
|
||||||
|
break;
|
||||||
#else /* MB_ENABLE_COLLECTION_LIB */
|
#else /* MB_ENABLE_COLLECTION_LIB */
|
||||||
# define _REF_COLL(__o) ((void)(__o));
|
# define _REF_COLL(__o) ((void)(__o));
|
||||||
# define _UNREF_COLL(__o) ((void)(__o));
|
# define _UNREF_COLL(__o) ((void)(__o));
|
||||||
@ -1111,9 +1129,15 @@ static char* _extract_string(_object_t* obj);
|
|||||||
if(!(__o)->ref) \
|
if(!(__o)->ref) \
|
||||||
_unref(&(__o)->data.instance->ref, (__o)->data.instance); \
|
_unref(&(__o)->data.instance->ref, (__o)->data.instance); \
|
||||||
break;
|
break;
|
||||||
|
# define _ADDGC_CLASS(__o, __g) \
|
||||||
|
case _DT_CLASS: \
|
||||||
|
if(!(__o)->ref) \
|
||||||
|
_gc_add(&(__o)->data.instance->ref, (__o)->data.instance, (__g)); \
|
||||||
|
break;
|
||||||
#else /* MB_ENABLE_CLASS */
|
#else /* MB_ENABLE_CLASS */
|
||||||
# define _REF_CLASS(__o) ((void)(__o));
|
# define _REF_CLASS(__o) ((void)(__o));
|
||||||
# define _UNREF_CLASS(__o) ((void)(__o));
|
# define _UNREF_CLASS(__o) ((void)(__o));
|
||||||
|
# define _ADDGC_CLASS(__o, __g) ((void)(__o)); ((void)(__g));
|
||||||
#endif /* MB_ENABLE_CLASS */
|
#endif /* MB_ENABLE_CLASS */
|
||||||
#define _REF(__o) \
|
#define _REF(__o) \
|
||||||
switch((__o)->type) { \
|
switch((__o)->type) { \
|
||||||
@ -1131,6 +1155,14 @@ static char* _extract_string(_object_t* obj);
|
|||||||
_UNREF_CLASS(__o) \
|
_UNREF_CLASS(__o) \
|
||||||
default: break; \
|
default: break; \
|
||||||
}
|
}
|
||||||
|
#define _ADDGC(__o, __g) \
|
||||||
|
switch((__o)->type) { \
|
||||||
|
_ADDGC_USERTYPE_REF(__o, __g) \
|
||||||
|
_ADDGC_ARRAY(__o, __g) \
|
||||||
|
_ADDGC_COLL(__o, __g) \
|
||||||
|
_ADDGC_CLASS(__o, __g) \
|
||||||
|
default: break; \
|
||||||
|
}
|
||||||
|
|
||||||
static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
|
static bool_t _lock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
|
||||||
static bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
|
static bool_t _unlock_ref_object(_lock_t* lk, _ref_t* ref, void* obj);
|
||||||
@ -1142,10 +1174,12 @@ static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpret
|
|||||||
static void _destroy_ref(_ref_t* ref);
|
static void _destroy_ref(_ref_t* ref);
|
||||||
|
|
||||||
#ifdef MB_ENABLE_GC
|
#ifdef MB_ENABLE_GC
|
||||||
static void _gc_add(_ref_t* ref, void* data);
|
static void _gc_add(_ref_t* ref, void* data, _gc_t* gc);
|
||||||
static void _gc_remove(_ref_t* ref, void* data);
|
static void _gc_remove(_ref_t* ref, void* data);
|
||||||
static int _gc_add_reachable(void* data, void* extra, void* ht);
|
static int _gc_add_reachable(void* data, void* extra, void* ht);
|
||||||
static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht);
|
static void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht);
|
||||||
|
static int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc);
|
||||||
|
static int _gc_destroy_garbage_in_dict(void* data, void* extra, _gc_t* gc);
|
||||||
static int _gc_destroy_garbage(void* data, void* extra);
|
static int _gc_destroy_garbage(void* data, void* extra);
|
||||||
static void _gc_try_trigger(mb_interpreter_t* s);
|
static void _gc_try_trigger(mb_interpreter_t* s);
|
||||||
static void _gc_collect_garbage(mb_interpreter_t* s);
|
static void _gc_collect_garbage(mb_interpreter_t* s);
|
||||||
@ -1265,6 +1299,7 @@ static void _swap_public_value(mb_value_t* tgt, mb_value_t* src);
|
|||||||
static int _clear_scope_chain(mb_interpreter_t* s);
|
static int _clear_scope_chain(mb_interpreter_t* s);
|
||||||
static int _dispose_scope_chain(mb_interpreter_t* s);
|
static int _dispose_scope_chain(mb_interpreter_t* s);
|
||||||
static void _tidy_scope_chain(mb_interpreter_t* s);
|
static void _tidy_scope_chain(mb_interpreter_t* s);
|
||||||
|
static void _tidy_intermediate_value(_ref_t* ref, void* data);
|
||||||
|
|
||||||
static void _stepped(mb_interpreter_t* s, _ls_node_t* ast);
|
static void _stepped(mb_interpreter_t* s, _ls_node_t* ast);
|
||||||
static int _execute_statement(mb_interpreter_t* s, _ls_node_t** l);
|
static int _execute_statement(mb_interpreter_t* s, _ls_node_t** l);
|
||||||
@ -4115,7 +4150,9 @@ unsigned _unref(_ref_t* ref, void* data) {
|
|||||||
|
|
||||||
result = --(*(ref->count));
|
result = --(*(ref->count));
|
||||||
#ifdef MB_ENABLE_GC
|
#ifdef MB_ENABLE_GC
|
||||||
_gc_add(ref, data);
|
_gc_add(ref, data, 0);
|
||||||
|
if(ref->count && !(*ref->count))
|
||||||
|
_tidy_intermediate_value(ref, data);
|
||||||
ref->on_unref(ref, data);
|
ref->on_unref(ref, data);
|
||||||
if(!ref->count)
|
if(!ref->count)
|
||||||
_gc_remove(ref, data);
|
_gc_remove(ref, data);
|
||||||
@ -4148,23 +4185,33 @@ void _destroy_ref(_ref_t* ref) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MB_ENABLE_GC
|
#ifdef MB_ENABLE_GC
|
||||||
void _gc_add(_ref_t* ref, void* data) {
|
void _gc_add(_ref_t* ref, void* data, _gc_t* gc) {
|
||||||
/* Add a referenced object to GC */
|
/* Add a referenced object to GC */
|
||||||
|
_ht_node_t* table = 0;
|
||||||
|
|
||||||
mb_assert(ref && data);
|
mb_assert(ref && data);
|
||||||
|
|
||||||
|
if(gc && _ht_find(gc->collected_table, ref))
|
||||||
|
return;
|
||||||
|
|
||||||
if(ref->type == _DT_ARRAY)
|
if(ref->type == _DT_ARRAY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!ref->s->gc.table)
|
if(!ref->s->gc.table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(ref->s->gc.collecting)
|
if(ref->s->gc.collecting > 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(ref->count && *ref->count)
|
if(ref->s->gc.collecting)
|
||||||
_ht_set_or_insert(ref->s->gc.table, ref, data);
|
table = ref->s->gc.recursive_table;
|
||||||
else
|
else
|
||||||
_ht_remove(ref->s->gc.table, ref, 0);
|
table = ref->s->gc.table;
|
||||||
|
|
||||||
|
if(ref->count && *ref->count)
|
||||||
|
_ht_set_or_insert(table, ref, data);
|
||||||
|
else
|
||||||
|
_ht_remove(table, ref, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gc_remove(_ref_t* ref, void* data) {
|
void _gc_remove(_ref_t* ref, void* data) {
|
||||||
@ -4251,27 +4298,9 @@ void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht) {
|
|||||||
/* Get all reachable referenced objects */
|
/* Get all reachable referenced objects */
|
||||||
_running_context_t* running = 0;
|
_running_context_t* running = 0;
|
||||||
_ht_node_t* global_scope = 0;
|
_ht_node_t* global_scope = 0;
|
||||||
_object_t tmp;
|
|
||||||
|
|
||||||
mb_assert(s && ht);
|
mb_assert(s && ht);
|
||||||
|
|
||||||
_MAKE_NIL(&tmp);
|
|
||||||
_public_value_to_internal_object(&s->running_context->intermediate_value, &tmp);
|
|
||||||
switch(tmp.type) {
|
|
||||||
case _DT_ARRAY: /* Fall through */
|
|
||||||
#ifdef MB_ENABLE_COLLECTION_LIB
|
|
||||||
case _DT_LIST: /* Fall through */
|
|
||||||
case _DT_DICT: /* Fall through */
|
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
|
||||||
#ifdef MB_ENABLE_CLASS
|
|
||||||
case _DT_CLASS: /* Fall through */
|
|
||||||
#endif /* MB_ENABLE_CLASS */
|
|
||||||
case _DT_USERTYPE_REF:
|
|
||||||
_gc_add_reachable(&tmp, 0, ht);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
running = s->running_context;
|
running = s->running_context;
|
||||||
while(running) {
|
while(running) {
|
||||||
global_scope = running->var_dict;
|
global_scope = running->var_dict;
|
||||||
@ -4283,10 +4312,50 @@ void _gc_get_reachable(mb_interpreter_t* s, _ht_node_t* ht) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _gc_destroy_garbage_in_list(void* data, void* extra, _gc_t* gc) {
|
||||||
|
/* Destroy only the capsule (wrapper) of an object, leave the data behind, and add it to GC if possible */
|
||||||
|
int result = _OP_RESULT_NORMAL;
|
||||||
|
_object_t* obj = 0;
|
||||||
|
mb_unrefvar(extra);
|
||||||
|
|
||||||
|
mb_assert(data);
|
||||||
|
|
||||||
|
obj = (_object_t*)data;
|
||||||
|
_ADDGC(obj, gc);
|
||||||
|
safe_free(obj);
|
||||||
|
|
||||||
|
result = _OP_RESULT_DEL_NODE;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _gc_destroy_garbage_in_dict(void* data, void* extra, _gc_t* gc) {
|
||||||
|
/* Destroy only the capsule (wrapper) of an object, leave the data behind, deal with extra as well, and add it to GC if possible */
|
||||||
|
int result = _OP_RESULT_NORMAL;
|
||||||
|
_object_t* obj = 0;
|
||||||
|
mb_unrefvar(extra);
|
||||||
|
|
||||||
|
mb_assert(data);
|
||||||
|
|
||||||
|
obj = (_object_t*)data;
|
||||||
|
_ADDGC(obj, gc);
|
||||||
|
safe_free(obj);
|
||||||
|
|
||||||
|
obj = (_object_t*)extra;
|
||||||
|
_ADDGC(obj, gc);
|
||||||
|
safe_free(obj);
|
||||||
|
|
||||||
|
result = _OP_RESULT_DEL_NODE;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int _gc_destroy_garbage(void* data, void* extra) {
|
int _gc_destroy_garbage(void* data, void* extra) {
|
||||||
/* Destroy a garbage */
|
/* Destroy a garbage */
|
||||||
int result = _OP_RESULT_NORMAL;
|
int result = _OP_RESULT_NORMAL;
|
||||||
|
_gc_t* gc = 0;
|
||||||
_ref_t* ref = 0;
|
_ref_t* ref = 0;
|
||||||
|
bool_t cld = false;
|
||||||
#ifdef MB_ENABLE_COLLECTION_LIB
|
#ifdef MB_ENABLE_COLLECTION_LIB
|
||||||
_list_t* lst = 0;
|
_list_t* lst = 0;
|
||||||
_dict_t* dct = 0;
|
_dict_t* dct = 0;
|
||||||
@ -4295,18 +4364,27 @@ int _gc_destroy_garbage(void* data, void* extra) {
|
|||||||
mb_assert(data && extra);
|
mb_assert(data && extra);
|
||||||
|
|
||||||
ref = (_ref_t*)extra;
|
ref = (_ref_t*)extra;
|
||||||
|
gc = &ref->s->gc;
|
||||||
switch(ref->type) {
|
switch(ref->type) {
|
||||||
#ifdef MB_ENABLE_COLLECTION_LIB
|
#ifdef MB_ENABLE_COLLECTION_LIB
|
||||||
case _DT_LIST:
|
case _DT_LIST:
|
||||||
lst = (_list_t*)data;
|
lst = (_list_t*)data;
|
||||||
_ls_foreach(lst->list, _destroy_object_capsule_only);
|
if(gc->collecting <= 1 && !_ht_find(gc->recursive_table, ref)) {
|
||||||
|
_LS_FOREACH(lst->list, _do_nothing_on_object, _gc_destroy_garbage_in_list, gc);
|
||||||
|
} else {
|
||||||
|
_ls_foreach(lst->list, _destroy_object_capsule_only);
|
||||||
|
}
|
||||||
_ls_clear(lst->list);
|
_ls_clear(lst->list);
|
||||||
lst->count = 0;
|
lst->count = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case _DT_DICT:
|
case _DT_DICT:
|
||||||
dct = (_dict_t*)data;
|
dct = (_dict_t*)data;
|
||||||
_ht_foreach(dct->dict, _destroy_object_capsule_only_with_extra);
|
if(gc->collecting <= 1 && !_ht_find(gc->recursive_table, ref)) {
|
||||||
|
_HT_FOREACH(dct->dict, _do_nothing_on_object, _gc_destroy_garbage_in_dict, gc);
|
||||||
|
} else {
|
||||||
|
_ht_foreach(dct->dict, _destroy_object_capsule_only_with_extra);
|
||||||
|
}
|
||||||
_ht_clear(dct->dict);
|
_ht_clear(dct->dict);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -4314,7 +4392,12 @@ int _gc_destroy_garbage(void* data, void* extra) {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_unref(ref, data);
|
if(ref->count) {
|
||||||
|
cld = (*(ref->count)) == 1;
|
||||||
|
_unref(ref, data);
|
||||||
|
if(cld)
|
||||||
|
_ht_set_or_insert(gc->collected_table, ref, data);
|
||||||
|
}
|
||||||
|
|
||||||
result = _OP_RESULT_DEL_NODE;
|
result = _OP_RESULT_DEL_NODE;
|
||||||
|
|
||||||
@ -4345,8 +4428,14 @@ void _gc_collect_garbage(mb_interpreter_t* s) {
|
|||||||
_HT_FOREACH(valid, _do_nothing_on_object, _ht_remove_exist, s->gc.table);
|
_HT_FOREACH(valid, _do_nothing_on_object, _ht_remove_exist, s->gc.table);
|
||||||
/* Collect garbage */
|
/* Collect garbage */
|
||||||
_ht_foreach(s->gc.table, _gc_destroy_garbage);
|
_ht_foreach(s->gc.table, _gc_destroy_garbage);
|
||||||
/* Tidy */
|
|
||||||
_ht_clear(s->gc.table);
|
_ht_clear(s->gc.table);
|
||||||
|
if(s->gc.recursive_table->count) {
|
||||||
|
s->gc.collecting++;
|
||||||
|
_ht_foreach(s->gc.recursive_table, _gc_destroy_garbage);
|
||||||
|
_ht_clear(s->gc.recursive_table);
|
||||||
|
s->gc.collecting--;
|
||||||
|
}
|
||||||
|
/* Tidy */
|
||||||
_ht_clear(valid);
|
_ht_clear(valid);
|
||||||
_ht_destroy(valid);
|
_ht_destroy(valid);
|
||||||
s->gc.collecting--;
|
s->gc.collecting--;
|
||||||
@ -6629,6 +6718,7 @@ int _dispose_scope_chain(mb_interpreter_t* s) {
|
|||||||
result++;
|
result++;
|
||||||
running = prev;
|
running = prev;
|
||||||
}
|
}
|
||||||
|
s->running_context = 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -6654,6 +6744,35 @@ void _tidy_scope_chain(mb_interpreter_t* s) {
|
|||||||
#endif /* MB_ENABLE_CLASS */
|
#endif /* MB_ENABLE_CLASS */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _tidy_intermediate_value(_ref_t* ref, void* data) {
|
||||||
|
/* Tidy the intermediate value */
|
||||||
|
_object_t tmp;
|
||||||
|
|
||||||
|
mb_assert(ref && data);
|
||||||
|
|
||||||
|
if(!ref->s->running_context)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_MAKE_NIL(&tmp);
|
||||||
|
_public_value_to_internal_object(&ref->s->running_context->intermediate_value, &tmp);
|
||||||
|
if(tmp.data.usertype == data) {
|
||||||
|
switch(tmp.type) {
|
||||||
|
case _DT_ARRAY: /* Fall through */
|
||||||
|
#ifdef MB_ENABLE_COLLECTION_LIB
|
||||||
|
case _DT_LIST: /* Fall through */
|
||||||
|
case _DT_DICT: /* Fall through */
|
||||||
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
case _DT_CLASS: /* Fall through */
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
case _DT_USERTYPE_REF:
|
||||||
|
mb_make_nil(ref->s->running_context->intermediate_value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _stepped(mb_interpreter_t* s, _ls_node_t* ast) {
|
void _stepped(mb_interpreter_t* s, _ls_node_t* ast) {
|
||||||
/* Called each step */
|
/* Called each step */
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
@ -7405,6 +7524,8 @@ int mb_open(struct mb_interpreter_t** s) {
|
|||||||
|
|
||||||
#ifdef MB_ENABLE_GC
|
#ifdef MB_ENABLE_GC
|
||||||
(*s)->gc.table = _ht_create(0, _ht_cmp_ref, _ht_hash_ref, _do_nothing_on_object);
|
(*s)->gc.table = _ht_create(0, _ht_cmp_ref, _ht_hash_ref, _do_nothing_on_object);
|
||||||
|
(*s)->gc.recursive_table = _ht_create(0, _ht_cmp_ref, _ht_hash_ref, _do_nothing_on_object);
|
||||||
|
(*s)->gc.collected_table = _ht_create(0, _ht_cmp_ref, _ht_hash_ref, _do_nothing_on_object);
|
||||||
#endif /* MB_ENABLE_GC */
|
#endif /* MB_ENABLE_GC */
|
||||||
|
|
||||||
(*s)->sub_stack = _ls_create();
|
(*s)->sub_stack = _ls_create();
|
||||||
@ -7446,13 +7567,21 @@ int mb_close(struct mb_interpreter_t** s) {
|
|||||||
|
|
||||||
#ifdef MB_ENABLE_GC
|
#ifdef MB_ENABLE_GC
|
||||||
_gc_collect_garbage(*s);
|
_gc_collect_garbage(*s);
|
||||||
_ht_destroy((*s)->gc.table);
|
|
||||||
(*s)->gc.table = 0;
|
|
||||||
#endif /* MB_ENABLE_GC */
|
#endif /* MB_ENABLE_GC */
|
||||||
|
|
||||||
_tidy_scope_chain(*s);
|
_tidy_scope_chain(*s);
|
||||||
_dispose_scope_chain(*s);
|
_dispose_scope_chain(*s);
|
||||||
|
|
||||||
|
#ifdef MB_ENABLE_GC
|
||||||
|
_gc_collect_garbage(*s);
|
||||||
|
_ht_destroy((*s)->gc.table);
|
||||||
|
_ht_destroy((*s)->gc.recursive_table);
|
||||||
|
_ht_destroy((*s)->gc.collected_table);
|
||||||
|
(*s)->gc.table = 0;
|
||||||
|
(*s)->gc.recursive_table = 0;
|
||||||
|
(*s)->gc.collected_table = 0;
|
||||||
|
#endif /* MB_ENABLE_GC */
|
||||||
|
|
||||||
_ls_foreach((*s)->temp_values, _destroy_object);
|
_ls_foreach((*s)->temp_values, _destroy_object);
|
||||||
_ls_destroy((*s)->temp_values);
|
_ls_destroy((*s)->temp_values);
|
||||||
_ls_foreach((*s)->lazy_destroy_objects, _destroy_object);
|
_ls_foreach((*s)->lazy_destroy_objects, _destroy_object);
|
||||||
|
@ -4,4 +4,4 @@
|
|||||||
|
|
||||||
s$ = "hello "
|
s$ = "hello "
|
||||||
s$ = s$ + "world"
|
s$ = s$ + "world"
|
||||||
PRINT s$ + "!"
|
print s$ + "!"
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
e = 50
|
e = 50
|
||||||
|
|
||||||
PRINT "Primes in ", e, ": ", 2, ", "
|
print "Primes in ", e, ": ", 2, ", "
|
||||||
|
|
||||||
FOR n = 3 TO e
|
for n = 3 to e
|
||||||
m = 2
|
m = 2
|
||||||
is = 1
|
isp = 1
|
||||||
WHILE m < n
|
while m < n
|
||||||
IF n MOD m = 0 THEN is = 0 ELSE m = m + 1
|
if n mod m = 0 then isp = 0 else m = m + 1
|
||||||
IF is = 0 THEN EXIT
|
if isp = 0 then exit
|
||||||
WEND
|
wend
|
||||||
IF is = 1 THEN PRINT n, ", "
|
if isp = 1 then print n, ", "
|
||||||
NEXT n
|
next n
|
@ -2,21 +2,21 @@
|
|||||||
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
PRINT "Input: "
|
print "Input: "
|
||||||
INPUT ns$
|
input ns$
|
||||||
n = VAL(ns$)
|
n = val(ns$)
|
||||||
|
|
||||||
x = n * 2 - 1
|
x = n * 2 - 1
|
||||||
a = 1 - 1 / 3
|
a = 1 - 1 / 3
|
||||||
w = (x - 5) / 2 + 1
|
w = (x - 5) / 2 + 1
|
||||||
v = 100 / w
|
v = 100 / w
|
||||||
|
|
||||||
FOR y = 5 TO x STEP 2
|
for y = 5 to x step 2
|
||||||
iy = (y - 1) / 4
|
iy = (y - 1) / 4
|
||||||
iy = FLOOR(iy)
|
iy = floor(iy)
|
||||||
IF iy = (y - 1) / 4 THEN a = a + 1 / y ELSE a = a - 1 / y
|
if iy = (y - 1) / 4 then a = a + 1 / y else a = a - 1 / y
|
||||||
u = u + v
|
u = u + v
|
||||||
NEXT
|
next
|
||||||
a = a * 4
|
a = a * 4
|
||||||
|
|
||||||
PRINT "PI = ", a
|
print "Pi = ", a
|
@ -2,22 +2,22 @@
|
|||||||
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
BEGIN:
|
begin:
|
||||||
n = 10
|
n = 10
|
||||||
DIM arr(n)
|
dim arr(n)
|
||||||
GOSUB CALC
|
gosub calc
|
||||||
GOSUB SHOW
|
gosub show
|
||||||
END
|
end
|
||||||
|
|
||||||
CALC:
|
calc:
|
||||||
arr(0) = 1
|
arr(0) = 1
|
||||||
FOR i = 1 TO n - 1
|
for i = 1 to n - 1
|
||||||
IF i = 1 THEN arr(i) = 1 ELSE arr(i) = arr(i - 1) + arr(i - 2)
|
if i = 1 then arr(i) = 1 else arr(i) = arr(i - 1) + arr(i - 2)
|
||||||
NEXT
|
next
|
||||||
RETURN
|
return
|
||||||
|
|
||||||
SHOW:
|
show:
|
||||||
FOR i = 0 TO n - 1
|
for i = 0 to n - 1
|
||||||
PRINT arr(i), ", "
|
print arr(i), ", "
|
||||||
NEXT
|
next
|
||||||
RETURN
|
return
|
@ -2,14 +2,14 @@
|
|||||||
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
' Copyright (c) 2011 - 2015 Wang Renxin. All rights reserved.
|
||||||
' For more information, see https://github.com/paladin-t/my_basic/
|
' For more information, see https://github.com/paladin-t/my_basic/
|
||||||
|
|
||||||
DEF AREA(a, b)
|
def area(a, b)
|
||||||
RETURN CALL MUL(a, b)
|
return call mul(a, b)
|
||||||
ENDDEF
|
enddef
|
||||||
|
|
||||||
DEF MUL(a, b)
|
def mul(a, b)
|
||||||
return a * b
|
return a * b
|
||||||
ENDDEF
|
enddef
|
||||||
|
|
||||||
a = 3
|
a = 3
|
||||||
b = 4
|
b = 4
|
||||||
PRINT a; b; AREA(a, b);
|
print a; b; area(a, b);
|
Loading…
x
Reference in New Issue
Block a user