diff --git a/HISTORY b/HISTORY index e7af3c9..491fda4 100755 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,6 @@ Mar. 1 2016 Added an OS statement +Fixed a class type detection bug with the IS statement Refactored platform dependent macros Feb. 29 2016 diff --git a/MY-BASIC Quick Reference.pdf b/MY-BASIC Quick Reference.pdf index f041267..cfda98e 100644 Binary files a/MY-BASIC Quick Reference.pdf and b/MY-BASIC Quick Reference.pdf differ diff --git a/README.md b/README.md index 4a039ed..1718852 100755 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Why are existing script interpreters so complex? Why is it so difficult to integ ## Introduction -MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter written in pure C with about 16,000 lines of source code. It supports structured grammar, and implements a style of OOP called [prototype-based programming](https://en.wikipedia.org/wiki/Prototype-based_programming) paradigm, furthermore it offers a functional programming ability with [lambda abstraction](https://en.wikipedia.org/wiki/Anonymous_function). Most advanced features are easily cuttable by modifying macros. It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is pretty light; all in a C source file and an associated header file; simpleness of source file layout and tightness dependency make it feels extraordinarily tough. It's able to easily combine MY-BASIC with an existing project in C, C++, Objective-C, C#, etc. Script driven can make your projects more powerful, elegant and neat. It's also able to learn how to build an interpreter from scratch with MY-BASIC, or build your own dialect easily based on it. +MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter written in pure C with less than twenty thousand lines of source code. It supports structured grammar, and implements a style of OOP called [prototype-based programming](https://en.wikipedia.org/wiki/Prototype-based_programming) paradigm, furthermore it offers a functional programming ability with [lambda abstraction](https://en.wikipedia.org/wiki/Anonymous_function). Most advanced features are easily cuttable by modifying macros. It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is pretty light; all in a C source file and an associated header file; simpleness of source file layout and tightness dependency make it feels extraordinarily tough. It's able to easily combine MY-BASIC with an existing project in C, C++, Objective-C, C#, etc. Script driven can make your projects more powerful, elegant and neat. It's also able to learn how to build an interpreter from scratch with MY-BASIC, or build your own dialect easily based on it. ## Compatibility diff --git a/core/my_basic.c b/core/my_basic.c index 24910c6..9beadd9 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -1556,7 +1556,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 int _search_class_meta_function(mb_interpreter_t* s, _class_t* instance, const char* n, _routine_t** f); -static bool_t _is_class(_class_t* instance, void* m, void* ret); +static bool_t _is_a_class(_class_t* instance, void* m, void* ret); static bool_t _add_class_meta_reachable(_class_t* meta, void* ht, void* ret); #ifdef MB_ENABLE_COLLECTION_LIB static int _reflect_class_field(void* data, void* extra, void* d); @@ -7106,14 +7106,26 @@ static int _search_class_meta_function(mb_interpreter_t* s, _class_t* instance, return 0; } -static bool_t _is_class(_class_t* instance, void* m, void* ret) { +static bool_t _is_a_class(_class_t* instance, void* m, void* ret) { /* Detect whether a class instance is inherited from another */ _class_t* meta = (_class_t*)m; bool_t* r = (bool_t*)ret; + bool_t is_a = false; mb_assert(instance && meta && ret); - *r = instance == meta; + do { + if(instance == meta) { + is_a = true; + + break; + } + if(instance == instance->created_from) + break; + instance = instance->created_from; + } while(1); + + *r = is_a; return !(*r); } @@ -12483,7 +12495,7 @@ static int _core_is(mb_interpreter_t* s, void** l) { if(!_IS_CLASS(fst) || !_IS_CLASS(scd)) { _handle_error_on_obj(s, SE_RN_CLASS_EXPECTED, s->source_file, TON(l), MB_FUNC_ERR, _exit, result); } - _traverse_class(fst->data.instance, 0, _is_class, _META_LIST_MAX_DEPTH, true, scd->data.instance, &is_a); + _traverse_class(fst->data.instance, 0, _is_a_class, _META_LIST_MAX_DEPTH, true, scd->data.instance, &is_a); val->type = _DT_INT; val->data.integer = (int_t)is_a; #else /* MB_ENABLE_CLASS */ @@ -13397,8 +13409,8 @@ _retry: bool_t is_a0 = false; bool_t is_a1 = false; if(s->last_instance && routine->instance) { - _traverse_class(s->last_instance->created_from, 0, _is_class, _META_LIST_MAX_DEPTH, true, routine->instance->created_from, &is_a0); - _traverse_class(routine->instance->created_from, 0, _is_class, _META_LIST_MAX_DEPTH, true, s->last_instance->created_from, &is_a1); + _traverse_class(s->last_instance->created_from, 0, _is_a_class, _META_LIST_MAX_DEPTH, true, routine->instance->created_from, &is_a0); + _traverse_class(routine->instance->created_from, 0, _is_a_class, _META_LIST_MAX_DEPTH, true, s->last_instance->created_from, &is_a1); } if(routine->instance && (!s->last_instance ||