From 48cb90c23481e48bdb2f8c6e4723ee80667e79e8 Mon Sep 17 00:00:00 2001 From: paladin-t Date: Tue, 5 Jan 2016 13:47:02 +0800 Subject: [PATCH] +developing lambda, added data structure; +developing lambda, added a lambda statement; +developing lambda, added an MB_ENABLE_LAMBDA macro. --- HISTORY | 5 ++ core/my_basic.c | 201 +++++++++++++++++++++++++++++++++++++++--------- core/my_basic.h | 4 + 3 files changed, 174 insertions(+), 36 deletions(-) diff --git a/HISTORY b/HISTORY index 8696ce4..ef04b8e 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,8 @@ +Jan. 5 2016 +Developing lambda, added data structure +Developing lambda, added a LAMBDA statement +Developing lambda, added an MB_ENABLE_LAMBDA macro + Jan. 4 2016 Added stack tracing Added an mb_debug_get_stack_trace function and an MB_ENABLE_STACK_TRACE macro diff --git a/core/my_basic.c b/core/my_basic.c index 1c4aea1..85ea676 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -405,19 +405,42 @@ typedef struct _class_t { } _class_t; #endif /* MB_ENABLE_CLASS */ +typedef enum _invokable_e { + _IT_BASIC, +#ifdef MB_ENABLE_LAMBDA + _IT_LAMBDA, +#endif /* MB_ENABLE_LAMBDA */ + _IT_NATIVE +} _invokable_e; + +#ifdef MB_ENABLE_LAMBDA +typedef struct _running_context_ref_t { + _ref_t ref; + struct _running_context_t* running; +} _running_context_ref_t; +#endif /* MB_ENABLE_LAMBDA */ + typedef struct _routine_t { char* name; #ifdef MB_ENABLE_CLASS _class_t* instance; #endif /* MB_ENABLE_CLASS */ bool_t is_cloned; - bool_t is_basic; + _invokable_e type; union { struct { struct _running_context_t* scope; _ls_node_t* entry; _ls_node_t* parameters; } basic; +#ifdef MB_ENABLE_LAMBDA + struct { + _ref_t ref; + struct _running_context_ref_t* scope; + _ls_node_t* entry; + _ls_node_t* parameters; + } lambda; +#endif /* MB_ENABLE_LAMBDA */ struct { mb_routine_func_t entry; } native; @@ -1189,20 +1212,45 @@ static char* _extract_string(_object_t* obj); # define _UNREF_CLASS(__o) ((void)(__o)); # define _ADDGC_CLASS(__o, __g) ((void)(__o)); ((void)(__g)); #endif /* MB_ENABLE_CLASS */ +#ifdef MB_ENABLE_LAMBDA +# define _REF_ROUTINE(__o) \ + case _DT_ROUTINE: \ + _ref(&(__o)->data.routine->func.lambda.ref, (__o)->data.routine); \ + break; +# define _UNREF_ROUTINE(__o) \ + case _DT_ROUTINE: \ + if(!(__o)->ref && (__o)->data.routine->type == _IT_LAMBDA) \ + _unref(&(__o)->data.routine->func.lambda.ref, (__o)->data.routine); \ + else if(!(__o)->ref && (__o)->data.routine->type != _IT_LAMBDA)\ + _destroy_routine((__o)->data.routine); \ + break; +# define _ADDGC_ROUTINE(__o, __g) \ + case _DT_ROUTINE: \ + if(!(__o)->ref && (__o)->data.routine->type == _IT_LAMBDA) \ + _gc_add(&(__o)->data.routine->func.lambda.ref, (__o)->data.routine, (__g)); \ + else if(!(__o)->ref && (__o)->data.routine->type != _IT_LAMBDA)\ + _dispose_object(__o); \ + break; +#else /* MB_ENABLE_LAMBDA */ +# define _REF_ROUTINE(__o) ((void)(__o)); +# define _UNREF_ROUTINE(__o) ((void)(__o)); +# define _ADDGC_ROUTINE(__o, __g) \ + case _DT_ROUTINE: \ + ((void)(__g)); \ + _dispose_object(__o); \ + break; +#endif /* MB_ENABLE_LAMBDA */ #define _ADDGC_STRING(__o) \ case _DT_STRING: \ _dispose_object(__o); \ break; -#define _ADDGC_ROUTINE(__o) \ - case _DT_ROUTINE: \ - _dispose_object(__o); \ - break; #define _REF(__o) \ switch((__o)->type) { \ _REF_USERTYPE_REF(__o) \ _REF_ARRAY(__o) \ _REF_COLL(__o) \ _REF_CLASS(__o) \ + _REF_ROUTINE(__o) \ default: break; \ } #define _UNREF(__o) \ @@ -1211,6 +1259,7 @@ static char* _extract_string(_object_t* obj); _UNREF_ARRAY(__o) \ _UNREF_COLL(__o) \ _UNREF_CLASS(__o) \ + _UNREF_ROUTINE(__o) \ default: break; \ } #define _ADDGC(__o, __g) \ @@ -1219,8 +1268,8 @@ static char* _extract_string(_object_t* obj); _ADDGC_ARRAY(__o, __g) \ _ADDGC_COLL(__o, __g) \ _ADDGC_CLASS(__o, __g) \ + _ADDGC_ROUTINE(__o, __g) \ _ADDGC_STRING(__o) \ - _ADDGC_ROUTINE(__o) \ default: break; \ } @@ -1322,6 +1371,10 @@ static bool_t _end_routine(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 _object_t* _duplicate_parameter(void* data, void* extra, _running_context_t* running); +#ifdef MB_ENABLE_LAMBDA +static void _unref_routine(_ref_t* ref, void* data); +static void _destroy_routine(_routine_t* r); +#endif /* MB_ENABLE_LAMBDA */ #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* _push_scope_by_class(mb_interpreter_t* s, _running_context_t* p); @@ -1490,6 +1543,9 @@ 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); #endif /* MB_ENABLE_CLASS */ +#ifdef MB_ENABLE_LAMBDA +static int _core_lambda(mb_interpreter_t* s, void** l); +#endif /* MB_ENABLE_LAMBDA */ #ifdef MB_ENABLE_ALLOC_STAT static int _core_mem(mb_interpreter_t* s, void** l); #endif /* MB_ENABLE_ALLOC_STAT */ @@ -1604,6 +1660,10 @@ static const _func_t _core_libs[] = { { "VAR", _core_var }, #endif /* MB_ENABLE_CLASS */ +#ifdef MB_ENABLE_LAMBDA + { "LAMBDA", _core_lambda }, +#endif /* MB_ENABLE_LAMBDA */ + #ifdef MB_ENABLE_ALLOC_STAT { "MEM", _core_mem }, #endif /* MB_ENABLE_ALLOC_STAT */ @@ -3103,9 +3163,9 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, mb_value_t* va, unsigned _ls_pushback(s->stack_frames, r->name); #endif /* MB_ENABLE_STACK_TRACE */ - if(r->is_basic && r->func.basic.entry) { + if(r->type == _IT_BASIC && r->func.basic.entry) { result = _eval_script_routine(s, l, va, ca, r, has_arg, pop_arg); - } else if(!r->is_basic && r->func.native.entry) { + } else if(r->type == _IT_NATIVE && r->func.native.entry) { result = _eval_native_routine(s, l, va, ca, r, has_arg, pop_arg); } else { _handle_error_on_obj(s, SE_RN_INVALID_ROUTINE, 0, TON(l), MB_FUNC_ERR, _exit, result); @@ -5774,7 +5834,7 @@ int _clone_clsss_field(void* data, void* extra, void* n) { routine->name = mb_strdup(sub->name, 0); routine->instance = instance; routine->is_cloned = true; - routine->is_basic = sub->is_basic; + routine->type = sub->type; routine->func = sub->func; ret = _create_object(); ret->type = _DT_ROUTINE; @@ -5835,18 +5895,39 @@ void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n, mb_routine /* Initialize a routine */ _running_context_t* running = 0; - mb_assert(s && routine && n); + mb_assert(s && routine); running = s->running_context; memset(routine, 0, sizeof(_routine_t)); routine->name = n; - routine->is_basic = !f; - if(routine->is_basic) { + + if(n && f) + routine->type = _IT_NATIVE; + else if(n && !f) + routine->type = _IT_BASIC; +#ifdef MB_ENABLE_LAMBDA + else if(!n && !f) + routine->type = _IT_LAMBDA; +#endif /* MB_ENABLE_LAMBDA */ + + switch(routine->type) { + case _IT_BASIC: routine->func.basic.scope = _create_running_context(); routine->func.basic.scope->var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0); - } else { + + break; +#ifdef MB_ENABLE_LAMBDA + case _IT_LAMBDA: + _create_ref(&routine->func.lambda.ref, _unref_routine, _DT_ROUTINE, s); + _ref(&routine->func.lambda.ref, routine); + + break; +#endif /* MB_ENABLE_LAMBDA */ + case _IT_NATIVE: routine->func.native.entry = f; + + break; } } @@ -5918,6 +5999,44 @@ _object_t* _duplicate_parameter(void* data, void* extra, _running_context_t* run return obj; } +#ifdef MB_ENABLE_LAMBDA +void _unref_routine(_ref_t* ref, void* data) { + /* Unreference a lambda routine */ + if(!(*(ref->count))) + _destroy_routine((_routine_t*)data); +} + +void _destroy_routine(_routine_t* r) { + /* Destroy a lambda routine */ + if(r->name) { + safe_free(r->name); + } + if(!r->is_cloned) { + switch(r->type) { + case _IT_BASIC: + if(r->func.basic.scope) { + if(r->func.basic.scope->var_dict) { + _ht_foreach(r->func.basic.scope->var_dict, _destroy_object); + _ht_destroy(r->func.basic.scope->var_dict); + } + safe_free(r->func.basic.scope); + } + if(r->func.basic.parameters) + _ls_destroy(r->func.basic.parameters); + + break; + case _IT_LAMBDA: + _destroy_ref(&r->func.lambda.ref); + + break; + case _IT_NATIVE: /* Do nothing */ + break; + } + } + safe_free(r); +} +#endif /* MB_ENABLE_LAMBDA */ + #ifdef MB_ENABLE_CLASS _running_context_t* _reference_scope_by_class(mb_interpreter_t* s, _running_context_t* p, _class_t* c) { /* Create a scope reference to an exist one by a class */ @@ -6432,32 +6551,13 @@ int _dispose_object(_object_t* obj) { _UNREF_COLL(obj) _UNREF_CLASS(obj) _UNREF_COLL_IT(obj) + _UNREF_ROUTINE(obj) case _DT_LABEL: if(!obj->ref) { safe_free(obj->data.label->name); safe_free(obj->data.label); } - break; - case _DT_ROUTINE: - if(!obj->ref) { - safe_free(obj->data.routine->name); - if(!obj->data.routine->is_cloned) { - if(obj->data.routine->is_basic) { - if(obj->data.routine->func.basic.scope) { - if(obj->data.routine->func.basic.scope->var_dict) { - _ht_foreach(obj->data.routine->func.basic.scope->var_dict, _destroy_object); - _ht_destroy(obj->data.routine->func.basic.scope->var_dict); - } - safe_free(obj->data.routine->func.basic.scope); - } - if(obj->data.routine->func.basic.parameters) - _ls_destroy(obj->data.routine->func.basic.parameters); - } - } - safe_free(obj->data.routine); - } - break; case _DT_NIL: /* Fall through */ case _DT_UNKNOWN: /* Fall through */ @@ -10245,10 +10345,15 @@ int _core_let(mb_interpreter_t* s, void** l) { #else /* MB_ENABLE_COLLECTION_LIB */ var->data->data = val->data; #endif /* MB_ENABLE_COLLECTION_LIB */ - if(val->type == _DT_ROUTINE) - var->data->ref = 1; - else + if(val->type == _DT_ROUTINE) { +#ifdef MB_ENABLE_LAMBDA var->data->ref = val->ref; +#else /* MB_ENABLE_LAMBDA */ + var->data->ref = 1; +#endif /* MB_ENABLE_LAMBDA */ + } else { + var->data->ref = val->ref; + } } } else if(arr && literally) { if(val->type != _DT_UNKNOWN) { @@ -11305,6 +11410,30 @@ _exit: } #endif /* MB_ENABLE_CLASS */ +#ifdef MB_ENABLE_LAMBDA +int _core_lambda(mb_interpreter_t* s, void** l) { + /* LAMBDA statement */ + int result = MB_FUNC_OK; + mb_value_t ret; + _routine_t* routine = 0; + + mb_assert(s && l); + + routine = (_routine_t*)mb_malloc(sizeof(_routine_t)); + _init_routine(s, routine, 0, 0); + + mb_check(mb_attempt_open_bracket(s, l)); + mb_check(mb_attempt_close_bracket(s, l)); + + ret.type = MB_DT_ROUTINE; + ret.value.routine = routine; + + mb_check(mb_push_value(s, l, ret)); + + return result; +} +#endif /* MB_ENABLE_LAMBDA */ + #ifdef MB_ENABLE_ALLOC_STAT int _core_mem(mb_interpreter_t* s, void** l) { /* MEM statement */ diff --git a/core/my_basic.h b/core/my_basic.h index 7568bc3..a4a5396 100755 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -89,6 +89,10 @@ extern "C" { # define MB_ENABLE_CLASS #endif /* MB_ENABLE_CLASS */ +#ifndef MB_ENABLE_LAMBDA +# define MB_ENABLE_LAMBDA +#endif /* MB_ENABLE_LAMBDA */ + #ifndef MB_COMPACT_MODE # define MB_COMPACT_MODE #endif /* MB_COMPACT_MODE */