diff --git a/HISTORY b/HISTORY index 81bcdda..4ef2716 100755 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,6 @@ +May. 20 2017 +Improved stability by preventing assigning builtin boolean + May. 18 2017 Fixed some memory potential leak when popped unexpected type of argument diff --git a/MY-BASIC Quick Reference.pdf b/MY-BASIC Quick Reference.pdf index 6b26099..2f3cb7c 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 be363ac..939a2ac 100755 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ ## Introduction -MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter written in pure C with less than twenty thousand lines of source code. MY-BASIC is a dynamic typed programming language. 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). It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is very lightweight; all in a C source file and an associated header file; simpleness of source file layout and tightness dependency make it extraordinarily tough. Anyone even C programming newbies could learn how to use it and add new scripting interfaces in five minutes. It's able to easily combine MY-BASIC with an existing project in C, C++, Java, Objective-C, Swift, C# and many other languages. 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 interpreter easily based on it. +MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter written in pure C with about twenty thousand lines of source code. MY-BASIC is a dynamic typed programming language. 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). It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is very lightweight; all in a C source file and an associated header file; simpleness of source file layout and tightness dependency make it extraordinarily tough. Anyone even C programming newbies could learn how to use it and add new scripting interfaces in five minutes. It's able to easily combine MY-BASIC with an existing project in C, C++, Java, Objective-C, Swift, C# and many other languages. Script driven can make your projects more powerful, elegant and neat. It's also possible to learn how to build an interpreter from scratch with MY-BASIC, or build your own dialect easily based on it. "MY-" in the name could be understood literally as "My" or "Make Your", it's up to you. diff --git a/core/my_basic.c b/core/my_basic.c index fd3b546..c13e0ef 100755 --- a/core/my_basic.c +++ b/core/my_basic.c @@ -233,7 +233,6 @@ typedef struct _ht_node_t { MBCONST static const char* const _ERR_DESC[] = { "No error", /** Common */ - "Open MY-BASIC failed", "A function with the same name already exists", "A function with the name does not exists", "Not supported", @@ -245,36 +244,40 @@ MBCONST static const char* const _ERR_DESC[] = { "Empty program", "Program too long", "Syntax error", + "Out of memory", "Invalid data type", "Type does not match", "Number overflow", "Invalid string", + "Number expected", + "Integer expected", + "String expected", "Index out of bound", "Cannot find with given index", "Illegal bound", "Too many dimensions", - "Operation failed", - "Invalid operation usage", "Dimension count out of bound", "Rank out of bound", "Complex array required", + "Array identifier expected", + "Array subscript expected", + "Variable expected", + "Variable or array expected", + "Invalid identifier usage", + "Duplicate identifier", "Label does not exist", "No return point", "Colon expected", "Comma expected", "Comma or semicolon expected", - "Array identifier expected", "Open bracket expected", "Close bracket expected", - "Array subscript expected", "Nested too deep", "Incomplete structure", - "Function expected", - "Variable or array identifier expected", + "Operation failed", + "Operator expected", + "Invalid operation usage", "Assign operator expected", - "String expected", - "Number expected", - "Integer expected", "ELSE statement expected", "ENDIF statement expected", "TO statement expected", @@ -282,15 +285,10 @@ MBCONST static const char* const _ERR_DESC[] = { "UNTIL statement expected", "Loop variable expected", "Jump label expected", - "Variable expected", - "Invalid identifier usage", - "Duplicate identifier", - "Operator expected", "Calculation error", + "Invalid expression", "Divide by zero", "MOD by zero", - "Invalid expression", - "Out of memory", "Module not match", "Wrong function reached", "Do not suspend in a routine", @@ -308,13 +306,12 @@ MBCONST static const char* const _ERR_DESC[] = { "HASH and COMPARE must come together", "Cannot change ME", "Invalid lambda", + "Empty collection", "List expected", "Collection expected", - "Iterator expected", - "Collection or iterator expected", "Collection or iterator or class expected", + "Iterator expected", "Invalid iterator", - "Empty collection", "Referenced usertype expected", "Referenced type expected", "Reference count overflow", @@ -12399,7 +12396,7 @@ int mb_init_array(struct mb_interpreter_t* s, void** l, mb_data_e t, int* d, int } else if(t == MB_DT_STRING) { type = _DT_STRING; } else { - _handle_error_on_obj(s, SE_RN_NEED_COMPLEX_ARRAY, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); + _handle_error_on_obj(s, SE_RN_COMPLEX_ARRAY_REQUIRED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); } #else /* MB_SIMPLE_ARRAY */ type = _DT_REAL; @@ -14341,6 +14338,9 @@ static int _core_let(mb_interpreter_t* s, void** l) { evar = obj->data.variable; var = _search_var_in_scope_chain(s, obj->data.variable); if(var == evar) evar = 0; + if(var == _OBJ_BOOL_TRUE->data.variable || var == _OBJ_BOOL_FALSE->data.variable) { + _handle_error_on_obj(s, SE_RN_INVALID_ID_USAGE, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); + } } } else { _handle_error_on_obj(s, SE_RN_VAR_OR_ARRAY_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); @@ -16960,7 +16960,7 @@ static int _std_set(mb_interpreter_t* s, void** l) { _create_internal_object_from_public_value(&nv, &nobj); fobj->data.variable->data = nobj; } else { - _handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); + _handle_error_on_obj(s, SE_RN_VAR_EXPECTED, s->source_file, DON2(l), MB_FUNC_ERR, _exit, result); } break; @@ -17188,7 +17188,7 @@ static int _std_input(mb_interpreter_t* s, void** l) { obj = (_object_t*)ast->data; } if(obj->type != _DT_VAR) { - _handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); + _handle_error_on_obj(s, SE_RN_VAR_EXPECTED, s->source_file, DON(ast), MB_FUNC_ERR, _exit, result); } if(obj->data.variable->data->type == _DT_INT || obj->data.variable->data->type == _DT_REAL) { _get_inputer(s)(line, sizeof(line)); diff --git a/core/my_basic.h b/core/my_basic.h index 076d9d4..f452a7c 100755 --- a/core/my_basic.h +++ b/core/my_basic.h @@ -384,7 +384,6 @@ struct mb_interpreter_t; typedef enum mb_error_e { SE_NO_ERR = 0, /** Common */ - SE_CM_OPEN_MB_FAILED, SE_CM_FUNC_EXISTS, SE_CM_FUNC_NOT_EXISTS, SE_CM_NOT_SUPPORTED, @@ -396,36 +395,40 @@ typedef enum mb_error_e { SE_RN_EMPTY_PROGRAM, SE_RN_PROGRAM_TOO_LONG, SE_RN_SYNTAX_ERROR, + SE_RN_OUT_OF_MEMORY, SE_RN_INVALID_DATA_TYPE, SE_RN_TYPE_NOT_MATCH, SE_RN_NUMBER_OVERFLOW, SE_RN_INVALID_STRING, + SE_RN_NUMBER_EXPECTED, + SE_RN_INTEGER_EXPECTED, + SE_RN_STRING_EXPECTED, SE_RN_INDEX_OUT_OF_BOUND, SE_RN_CANNOT_FIND_WITH_GIVEN_INDEX, SE_RN_ILLEGAL_BOUND, SE_RN_TOO_MANY_DIMENSIONS, - SE_RN_OPERATION_FAILED, - SE_RN_INVALID_OPERATION_USAGE, SE_RN_DIMENSION_COUNT_OUT_OF_BOUND, SE_RN_RANK_OUT_OF_BOUND, - SE_RN_NEED_COMPLEX_ARRAY, + SE_RN_COMPLEX_ARRAY_REQUIRED, + SE_RN_ARRAY_IDENTIFIER_EXPECTED, + SE_RN_ARRAY_SUBSCRIPT_EXPECTED, + SE_RN_VAR_EXPECTED, + SE_RN_VAR_OR_ARRAY_EXPECTED, + SE_RN_INVALID_ID_USAGE, + SE_RN_DUPLICATE_ID, SE_RN_LABEL_NOT_EXISTS, SE_RN_NO_RETURN_POINT, SE_RN_COLON_EXPECTED, SE_RN_COMMA_EXPECTED, SE_RN_COMMA_OR_SEMICOLON_EXPECTED, - SE_RN_ARRAY_IDENTIFIER_EXPECTED, SE_RN_OPEN_BRACKET_EXPECTED, SE_RN_CLOSE_BRACKET_EXPECTED, - SE_RN_ARRAY_SUBSCRIPT_EXPECTED, SE_RN_NESTED_TOO_DEEP, SE_RN_INCOMPLETE_STRUCTURE, - SE_RN_FUNCTION_EXPECTED, - SE_RN_VAR_OR_ARRAY_EXPECTED, + SE_RN_OPERATION_FAILED, + SE_RN_OPERATOR_EXPECTED, + SE_RN_INVALID_OPERATION_USAGE, SE_RN_ASSIGN_OPERATOR_EXPECTED, - SE_RN_STRING_EXPECTED, - SE_RN_NUMBER_EXPECTED, - SE_RN_INTEGER_EXPECTED, SE_RN_ELSE_EXPECTED, SE_RN_ENDIF_EXPECTED, SE_RN_TO_EXPECTED, @@ -433,15 +436,10 @@ typedef enum mb_error_e { SE_RN_UNTIL_EXPECTED, SE_RN_LOOP_VAR_EXPECTED, SE_RN_JUMP_LABEL_EXPECTED, - SE_RN_VARIABLE_EXPECTED, - SE_RN_INVALID_ID_USAGE, - SE_RN_DUPLICATE_ID, - SE_RN_OPERATOR_EXPECTED, SE_RN_CALCULATION_ERROR, + SE_RN_INVALID_EXPRESSION, SE_RN_DIVIDE_BY_ZERO, SE_RN_MOD_BY_ZERO, - SE_RN_INVALID_EXPRESSION, - SE_RN_OUT_OF_MEMORY, SE_RN_MODULE_NOT_MATCH, SE_RN_WRONG_FUNCTION_REACHED, SE_RN_DO_NOT_SUSPEND_IN_A_ROUTINE, @@ -459,13 +457,12 @@ typedef enum mb_error_e { SE_RN_HASH_AND_COMPARE_MUST_COME_TOGETHER, SE_RN_CANNOT_CHANGE_ME, SE_RN_INVALID_LAMBDA, + SE_RN_EMPTY_COLLECTION, SE_RN_LIST_EXPECTED, SE_RN_COLLECTION_EXPECTED, - SE_RN_ITERATOR_EXPECTED, - SE_RN_COLLECTION_OR_ITERATOR_EXPECTED, SE_RN_COLLECTION_OR_ITERATOR_OR_CLASS_EXPECTED, + SE_RN_ITERATOR_EXPECTED, SE_RN_INVALID_ITERATOR, - SE_RN_EMPTY_COLLECTION, SE_RN_REFERENCED_USERTYPE_EXPECTED, SE_RN_REFERENCED_TYPE_EXPECTED, SE_RN_REFERENCE_COUNT_OVERFLOW,