+added a duplicate sub routine error handling; +added optional argument support for INPUT statement; *fixed a variable multiple freeing bug in sub routine; *polished document.
This commit is contained in:
parent
3b7a983871
commit
c6d7dcae8f
17
HISTORY
17
HISTORY
@ -1,7 +1,14 @@
|
|||||||
|
Sep. 11 2015
|
||||||
|
Added a duplicate sub routine error handling
|
||||||
|
Added optional argument support for INPUT statement
|
||||||
|
Fixed a variable multiple freeing bug in sub routine
|
||||||
|
Polished document
|
||||||
|
|
||||||
Sep. 8 2015
|
Sep. 8 2015
|
||||||
Fixed a type parsing of sub routine bug
|
Fixed a type parsing of sub routine bug
|
||||||
Fixed a scope processing bug
|
Fixed a scope processing bug
|
||||||
Fixed a sub routine invoking bug without leading CALL statement or result receiver
|
Fixed a sub routine invoking bug without leading CALL statement or result receiver
|
||||||
|
Added a makefile
|
||||||
|
|
||||||
Sep. 6 2015
|
Sep. 6 2015
|
||||||
Improved sub routine
|
Improved sub routine
|
||||||
@ -12,7 +19,7 @@ Prompted more friendly dummy function message
|
|||||||
Polished code and document
|
Polished code and document
|
||||||
|
|
||||||
Sep. 1 2015
|
Sep. 1 2015
|
||||||
Added support for user customized routine by DEF/ENDDEF
|
Added support for user customized sub routine by DEF/ENDDEF
|
||||||
|
|
||||||
Aug. 26 2015
|
Aug. 26 2015
|
||||||
Added a memory pool to interpreter shell in main.c
|
Added a memory pool to interpreter shell in main.c
|
||||||
@ -56,7 +63,7 @@ Changed mb_dispose_value as public
|
|||||||
|
|
||||||
Apr. 23 2015 Version 1.1
|
Apr. 23 2015 Version 1.1
|
||||||
Added debug APIs
|
Added debug APIs
|
||||||
Added (nestable) multi line IF statement support
|
Added (nestable) multiple line IF statement support
|
||||||
|
|
||||||
Apr. 15 2015
|
Apr. 15 2015
|
||||||
Added mb_pop_usertype, mb_push_usertype to support user defined type
|
Added mb_pop_usertype, mb_push_usertype to support user defined type
|
||||||
@ -102,12 +109,12 @@ Added an mb_remove_reserved_func function which allows a user to disable/remove
|
|||||||
|
|
||||||
May. 22 2014
|
May. 22 2014
|
||||||
Fixed a crash bug when missing colon in a combined line, thanks to Michael P. Welch for pointing it out
|
Fixed a crash bug when missing colon in a combined line, thanks to Michael P. Welch for pointing it out
|
||||||
Fixed a missing lexical cursor stepping bug in INPUT function
|
Fixed a missing lexical cursor stepping bug in INPUT statement
|
||||||
|
|
||||||
Mar. 17 2014
|
Mar. 17 2014
|
||||||
Added an XCode project
|
Added an XCode project
|
||||||
Added a safe stdin reader function mb_gets
|
Added a safe stdin reader function mb_gets
|
||||||
Fixed a crash bug in INPUT function
|
Fixed a crash bug in INPUT statement
|
||||||
|
|
||||||
Feb. 17 2014
|
Feb. 17 2014
|
||||||
Added mod by zero processing
|
Added mod by zero processing
|
||||||
@ -119,7 +126,7 @@ Jul. 19 2013
|
|||||||
Fixed a crash bug in _execute_statement, thanks to Jon Mayo for pointing it out
|
Fixed a crash bug in _execute_statement, thanks to Jon Mayo for pointing it out
|
||||||
|
|
||||||
Feb. 25 2013
|
Feb. 25 2013
|
||||||
Fixed a cross routine multi-statement execution bug, thanks to Bruce Kendall for pointing it out
|
Fixed a cross routine multiple statement execution bug, thanks to Bruce Kendall for pointing it out
|
||||||
Fixed a memory corruption bug when loading a script file
|
Fixed a memory corruption bug when loading a script file
|
||||||
|
|
||||||
Jan. 9 2013
|
Jan. 9 2013
|
||||||
|
24
README.md
24
README.md
@ -1,18 +1,18 @@
|
|||||||

|

|
||||||
|
|
||||||
Copyright (C) 2011 - 2015 [Wang Renxin](https://twitter.com/wangrenxin)
|
Copyright (C) 2011 - 2015 [Wang Renxin](https://twitter.com/wangrenxin). All rights reserved.
|
||||||
|
|
||||||
[LinkedIn](https://cn.linkedin.com/pub/wang-renxin/43/494/20)
|
[LinkedIn](https://cn.linkedin.com/pub/wang-renxin/43/494/20)
|
||||||
|
|
||||||
Why are existing script interpreters so complex? Why is it so difficult to integrate with them? Why not try MY-BASIC today!
|
Why are existing script interpreters so complex? Why is it so difficult to integrate with them? Why not try MY-BASIC today! Scripting should be simple and enjoyable.
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 7000 lines of source code. Its grammar is similar to structured BASIC. 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. You can combine MY-BASIC with an existing C, C++, Objective-C, etc. project easily, scripting driven can make your projects more powerful, elegant and neat.
|
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 7000 lines of source code. Its grammar is similar to structured BASIC. 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. You are able to easily combine MY-BASIC with an existing project in C, C++, Objective-C, etc. Scripting driven can make your projects more powerful, elegant and neat.
|
||||||
|
|
||||||
## Main features
|
## Main features
|
||||||
|
|
||||||
* It is free
|
* It is totally free to use MY-BASIC for individual or commercial purpose under the MIT license
|
||||||
* Written in clean ANSI C, source code portable
|
* Written in clean ANSI C, source code portable
|
||||||
* With most common BASIC syntax
|
* With most common BASIC syntax
|
||||||
* Small (within memory usage less than 128KB) and fast
|
* Small (within memory usage less than 128KB) and fast
|
||||||
@ -26,11 +26,23 @@ MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in p
|
|||||||
* Standard string functions
|
* Standard string functions
|
||||||
* Debug APIs
|
* Debug APIs
|
||||||
* High expansibility, easy to use APIs, easy to write customized scripting interfaces
|
* High expansibility, easy to use APIs, easy to write customized scripting interfaces
|
||||||
* It's able to use it as a standalone interpreter, or integrate it with existing C, C++, Objective-C, etc. projects
|
* It's able to use it as a standalone interpreter, or integrate it with existing projects in C, C++, Objective-C, etc.
|
||||||
* It's able to learn how to build an interpreter from scratch from MY-BASIC
|
* It's able to learn how to build an interpreter from scratch from MY-BASIC
|
||||||
* It's able to build your own dialect based on MY-BASIC
|
* It's able to build your own dialect based on MY-BASIC
|
||||||
* More features/modules under developing
|
* More features/modules under developing
|
||||||
|
|
||||||
|
## Scripting at a glance
|
||||||
|
|
||||||
|
Come along with a traditional "hello world" script in MY-BASIC:
|
||||||
|
|
||||||
|
def foo(a, b)
|
||||||
|
print a + " " + b;
|
||||||
|
enddef
|
||||||
|
|
||||||
|
foo("Hello", "world!")
|
||||||
|
|
||||||
|
input
|
||||||
|
|
||||||
## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
||||||
|
|
||||||

|

|
||||||
@ -57,7 +69,7 @@ You can definitely [link with MY-BASIC as a lib](https://github.com/paladin-t/my
|
|||||||
|
|
||||||
For more details about using MY-BASIC when it's already integrated with exist projects, please see [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf).
|
For more details about using MY-BASIC when it's already integrated with exist projects, please see [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf).
|
||||||
|
|
||||||
## [WIKI](https://github.com/paladin-t/my_basic/wiki)
|
## [Wiki](https://github.com/paladin-t/my_basic/wiki)
|
||||||
|
|
||||||
* [Passes](https://github.com/paladin-t/my_basic/wiki/Passes)
|
* [Passes](https://github.com/paladin-t/my_basic/wiki/Passes)
|
||||||
* [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
* [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
||||||
|
160
core/my_basic.c
160
core/my_basic.c
@ -52,6 +52,7 @@ extern "C" {
|
|||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
# pragma warning(disable : 4127)
|
# pragma warning(disable : 4127)
|
||||||
# pragma warning(disable : 4305)
|
# pragma warning(disable : 4305)
|
||||||
|
# pragma warning(disable : 4996)
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@ -78,7 +79,7 @@ extern "C" {
|
|||||||
/** Macros */
|
/** Macros */
|
||||||
#define _VER_MAJOR 1
|
#define _VER_MAJOR 1
|
||||||
#define _VER_MINOR 1
|
#define _VER_MINOR 1
|
||||||
#define _VER_REVISION 68
|
#define _VER_REVISION 69
|
||||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||||
|
|
||||||
/* Uncomment the line below to treat warning as error */
|
/* Uncomment the line below to treat warning as error */
|
||||||
@ -211,6 +212,7 @@ static const char* _ERR_DESC[] = {
|
|||||||
"Don't suspend in a routine",
|
"Don't suspend in a routine",
|
||||||
"Don't mix instructional and structured sub routines",
|
"Don't mix instructional and structured sub routines",
|
||||||
"Routine expected",
|
"Routine expected",
|
||||||
|
"Duplicate routine",
|
||||||
/** Extended abort */
|
/** Extended abort */
|
||||||
"Extended abort"
|
"Extended abort"
|
||||||
};
|
};
|
||||||
@ -365,6 +367,7 @@ typedef struct _parsing_context_t {
|
|||||||
_object_t* last_symbol;
|
_object_t* last_symbol;
|
||||||
_parsing_state_e parsing_state;
|
_parsing_state_e parsing_state;
|
||||||
_symbol_state_e symbol_state;
|
_symbol_state_e symbol_state;
|
||||||
|
unsigned short class_state;
|
||||||
unsigned short routine_state;
|
unsigned short routine_state;
|
||||||
unsigned short routine_params_state;
|
unsigned short routine_params_state;
|
||||||
int parsing_pos;
|
int parsing_pos;
|
||||||
@ -776,7 +779,9 @@ static bool_t _is_array(void* obj);
|
|||||||
static bool_t _is_string(void* obj);
|
static bool_t _is_string(void* obj);
|
||||||
static char* _extract_string(_object_t* obj);
|
static char* _extract_string(_object_t* obj);
|
||||||
|
|
||||||
static void _init_instance(mb_interpreter_t* s, _class_t* instance, char* n);
|
static void _init_class(mb_interpreter_t* s, _class_t* instance, char* n);
|
||||||
|
static void _begin_class(mb_interpreter_t* s);
|
||||||
|
static void _end_class(mb_interpreter_t* s);
|
||||||
static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n);
|
static void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n);
|
||||||
static void _begin_routine(mb_interpreter_t* s);
|
static void _begin_routine(mb_interpreter_t* s);
|
||||||
static void _end_routine(mb_interpreter_t* s);
|
static void _end_routine(mb_interpreter_t* s);
|
||||||
@ -843,11 +848,21 @@ static int _close_std_lib(mb_interpreter_t* s);
|
|||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# if _MSC_VER < 1300
|
# if _MSC_VER < 1300
|
||||||
# define _do_nothing(__s, __l, __exit, __result) do { static int i = 0; ++i; printf("Unaccessable function called %d times\n", i); mb_unrefvar(__s); mb_unrefvar(__l); mb_unrefvar(__result); goto _exit; } while(0)
|
# define _do_nothing(__s, __l, __exit, __result) \
|
||||||
|
do { \
|
||||||
|
_ls_node_t* ast = 0; static int i = 0; ++i; \
|
||||||
|
printf("Unaccessable function called %d times\n", i); \
|
||||||
|
ast = (_ls_node_t*)(*(__l)); \
|
||||||
|
_handle_error_on_obj((__s), SE_RN_WRONG_FUNCTION_REACHED, 0, DON(ast), MB_FUNC_ERR, __exit, __result); \
|
||||||
|
} while(0)
|
||||||
# endif /* _MSC_VER < 1300 */
|
# endif /* _MSC_VER < 1300 */
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
#ifndef _do_nothing
|
#ifndef _do_nothing
|
||||||
# define _do_nothing(__s, __l, __exit, __result) do { _ls_node_t* ast = (_ls_node_t*)(*(__l)); _handle_error_on_obj((__s), SE_RN_WRONG_FUNCTION_REACHED, (char*)MB_FUNC, DON(ast), MB_FUNC_ERR, __exit, __result); } while(0);
|
# define _do_nothing(__s, __l, __exit, __result) \
|
||||||
|
do { \
|
||||||
|
_ls_node_t* ast = (_ls_node_t*)(*(__l)); \
|
||||||
|
_handle_error_on_obj((__s), SE_RN_WRONG_FUNCTION_REACHED, (char*)MB_FUNC, DON(ast), MB_FUNC_ERR, __exit, __result); \
|
||||||
|
} while(0);
|
||||||
#endif /* _do_nothing */
|
#endif /* _do_nothing */
|
||||||
|
|
||||||
/** Core lib */
|
/** Core lib */
|
||||||
@ -1971,6 +1986,7 @@ int _eval_routine(mb_interpreter_t* s, _ls_node_t** l, _routine_t* r) {
|
|||||||
_pop_scope(s);
|
_pop_scope(s);
|
||||||
|
|
||||||
result = _public_value_to_internal_object(&arg, var->data);
|
result = _public_value_to_internal_object(&arg, var->data);
|
||||||
|
var->data->ref = true;
|
||||||
if(result != MB_FUNC_OK)
|
if(result != MB_FUNC_OK)
|
||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
@ -2302,9 +2318,15 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
(*obj)->data.instance = ((_object_t*)(glbsyminscope->data))->data.instance;
|
(*obj)->data.instance = ((_object_t*)(glbsyminscope->data))->data.instance;
|
||||||
(*obj)->ref = true;
|
(*obj)->ref = true;
|
||||||
*delsym = true;
|
*delsym = true;
|
||||||
|
if(running != (*obj)->data.instance->scope &&
|
||||||
|
context->class_state &&
|
||||||
|
_IS_FUNC(context->last_symbol, _core_class)) {
|
||||||
|
_push_scope(s, (*obj)->data.instance->scope);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t));
|
tmp.instance = (_class_t*)mb_malloc(sizeof(_class_t));
|
||||||
_init_instance(s, tmp.instance, sym);
|
_init_class(s, tmp.instance, sym);
|
||||||
|
_push_scope(s, tmp.instance->scope);
|
||||||
(*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);
|
||||||
@ -2492,23 +2514,43 @@ _data_e _get_symbol_type(mb_interpreter_t* s, char* sym, _raw_t* value) {
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
/* _class_t */
|
/* _class_t */
|
||||||
if(context->last_symbol && _IS_FUNC(context->last_symbol, _core_class)) {
|
if(context->last_symbol) {
|
||||||
glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
|
glbsyminscope = _search_var_in_scope_chain(s, 0, sym);
|
||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
if(glbsyminscope && ((_object_t*)glbsyminscope->data)->type == _DT_CLASS) {
|
||||||
tmp.obj = (_object_t*)(glbsyminscope->data);
|
if(_IS_FUNC(context->last_symbol, _core_class))
|
||||||
if(!tmp.obj->ref) {
|
_begin_class(s);
|
||||||
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string);
|
result = _DT_CLASS;
|
||||||
_dispose_object(tmp.obj);
|
|
||||||
}
|
goto _exit;
|
||||||
tmp.obj->type = _DT_CLASS;
|
|
||||||
tmp.obj->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
|
|
||||||
_init_instance(s, tmp.obj->data.instance, sym);
|
|
||||||
_ht_set_or_insert(running->var_dict, sym, tmp.obj);
|
|
||||||
}
|
}
|
||||||
|
if(_IS_FUNC(context->last_symbol, _core_class)) {
|
||||||
|
if(_IS_FUNC(context->last_symbol, _core_class))
|
||||||
|
_begin_class(s);
|
||||||
|
if(!_is_identifier_char(sym[0])) {
|
||||||
|
result = _DT_NIL;
|
||||||
|
|
||||||
result = _DT_CLASS;
|
goto _exit;
|
||||||
|
}
|
||||||
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
||||||
|
tmp.obj = (_object_t*)(glbsyminscope->data);
|
||||||
|
if(!tmp.obj->ref) {
|
||||||
|
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string);
|
||||||
|
_dispose_object(tmp.obj);
|
||||||
|
}
|
||||||
|
tmp.obj->type = _DT_CLASS;
|
||||||
|
tmp.obj->data.instance = (_class_t*)mb_malloc(sizeof(_class_t));
|
||||||
|
_init_class(s, tmp.obj->data.instance, sym);
|
||||||
|
_init_class(s, tmp.obj->data.instance, sym);
|
||||||
|
_ht_set_or_insert(running->var_dict, sym, tmp.obj);
|
||||||
|
}
|
||||||
|
|
||||||
goto _exit;
|
result = _DT_CLASS;
|
||||||
|
|
||||||
|
goto _exit;
|
||||||
|
} else if(_IS_FUNC(context->last_symbol, _core_endclass)) {
|
||||||
|
_end_class(s);
|
||||||
|
_pop_scope(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* _routine_t */
|
/* _routine_t */
|
||||||
if(context->last_symbol) {
|
if(context->last_symbol) {
|
||||||
@ -3108,14 +3150,39 @@ char* _extract_string(_object_t* obj) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _init_instance(mb_interpreter_t* s, _class_t* instance, char* n) {
|
void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
|
||||||
/* Initialize an instance */
|
/* Initialize an instance */
|
||||||
|
_running_context_t* running = 0;
|
||||||
|
|
||||||
mb_assert(s && instance && n);
|
mb_assert(s && instance && n);
|
||||||
|
|
||||||
|
running = s->running_context;
|
||||||
|
|
||||||
memset(instance, 0, sizeof(_class_t));
|
memset(instance, 0, sizeof(_class_t));
|
||||||
instance->name = n;
|
instance->name = n;
|
||||||
instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
instance->scope = (_running_context_t*)mb_malloc(sizeof(_running_context_t));
|
||||||
memset(instance->scope, 0, sizeof(_running_context_t));
|
memset(instance->scope, 0, sizeof(_running_context_t));
|
||||||
|
instance->scope->var_dict = _ht_create(0, _ht_cmp_string, _ht_hash_string, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _begin_class(mb_interpreter_t* s) {
|
||||||
|
/* Begin parsing a class */
|
||||||
|
_parsing_context_t* context = 0;
|
||||||
|
|
||||||
|
mb_assert(s);
|
||||||
|
|
||||||
|
context = s->parsing_context;
|
||||||
|
context->class_state++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _end_class(mb_interpreter_t* s) {
|
||||||
|
/* End parsing a class */
|
||||||
|
_parsing_context_t* context = 0;
|
||||||
|
|
||||||
|
mb_assert(s);
|
||||||
|
|
||||||
|
context = s->parsing_context;
|
||||||
|
context->class_state--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
|
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
|
||||||
@ -3279,6 +3346,16 @@ int _dispose_object(_object_t* obj) {
|
|||||||
safe_free(obj->data.label);
|
safe_free(obj->data.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case _DT_CLASS:
|
||||||
|
if(!obj->ref) {
|
||||||
|
safe_free(obj->data.instance->name);
|
||||||
|
_ht_foreach(obj->data.instance->scope->var_dict, _destroy_object);
|
||||||
|
_ht_destroy(obj->data.instance->scope->var_dict);
|
||||||
|
safe_free(obj->data.instance->scope);
|
||||||
|
safe_free(obj->data.instance);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
if(!obj->ref) {
|
if(!obj->ref) {
|
||||||
@ -3291,13 +3368,6 @@ int _dispose_object(_object_t* obj) {
|
|||||||
safe_free(obj->data.routine);
|
safe_free(obj->data.routine);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
case _DT_CLASS:
|
|
||||||
if(!obj->ref) {
|
|
||||||
safe_free(obj->data.instance->scope);
|
|
||||||
safe_free(obj->data.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case _DT_NIL: /* Fall through */
|
case _DT_NIL: /* Fall through */
|
||||||
case _DT_ANY: /* Fall through */
|
case _DT_ANY: /* Fall through */
|
||||||
@ -3599,6 +3669,10 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
|||||||
case _DT_STRING:
|
case _DT_STRING:
|
||||||
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_INVALID_EXPRESSION, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case _DT_CLASS:
|
||||||
|
mb_assert(0 && "Not implemented");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
@ -6161,6 +6235,7 @@ int _core_def(mb_interpreter_t* s, void** l) {
|
|||||||
/* DEF statement */
|
/* DEF statement */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
_ls_node_t* ast = 0;
|
_ls_node_t* ast = 0;
|
||||||
|
_running_context_t* running = 0;
|
||||||
_object_t* obj = 0;
|
_object_t* obj = 0;
|
||||||
_var_t* var = 0;
|
_var_t* var = 0;
|
||||||
_ls_node_t* rnode = 0;
|
_ls_node_t* rnode = 0;
|
||||||
@ -6168,6 +6243,8 @@ int _core_def(mb_interpreter_t* s, void** l) {
|
|||||||
|
|
||||||
mb_assert(s && l);
|
mb_assert(s && l);
|
||||||
|
|
||||||
|
running = s->running_context;
|
||||||
|
|
||||||
ast = (_ls_node_t*)(*l);
|
ast = (_ls_node_t*)(*l);
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
|
|
||||||
@ -6177,6 +6254,9 @@ int _core_def(mb_interpreter_t* s, void** l) {
|
|||||||
if(!_IS_ROUTINE(obj)) {
|
if(!_IS_ROUTINE(obj)) {
|
||||||
_handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_ROUTINE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
|
if(obj->data.routine->entry) {
|
||||||
|
_handle_error_on_obj(s, SE_RN_DUPLICATE_ROUTINE, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
|
}
|
||||||
routine = (_routine_t*)(((_object_t*)(ast->data))->data.routine);
|
routine = (_routine_t*)(((_object_t*)(ast->data))->data.routine);
|
||||||
ast = ast->next;
|
ast = ast->next;
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
@ -6233,17 +6313,32 @@ _exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int _core_class(mb_interpreter_t* s, void** l) {
|
int _core_class(mb_interpreter_t* s, void** l) {
|
||||||
/* OBJ statement */
|
/* CLASS statement */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
|
_ls_node_t* ast = 0;
|
||||||
|
_running_context_t* running = 0;
|
||||||
|
|
||||||
_do_nothing(s, l, _exit, result);
|
mb_assert(s && l);
|
||||||
|
|
||||||
|
running = s->running_context;
|
||||||
|
|
||||||
|
ast = (_ls_node_t*)(*l);
|
||||||
|
ast = ast->next;
|
||||||
|
|
||||||
|
_using_jump_set_of_structured(s, ast, _exit, result);
|
||||||
|
|
||||||
|
_skip_to(s, &ast, _core_endclass, _DT_NIL);
|
||||||
|
|
||||||
|
ast = ast->next;
|
||||||
|
|
||||||
_exit:
|
_exit:
|
||||||
|
*l = ast;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _core_endclass(mb_interpreter_t* s, void** l) {
|
int _core_endclass(mb_interpreter_t* s, void** l) {
|
||||||
/* ENDOBJ statement */
|
/* ENDCLASS statement */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
|
|
||||||
_do_nothing(s, l, _exit, result);
|
_do_nothing(s, l, _exit, result);
|
||||||
@ -7132,7 +7227,12 @@ int _std_input(mb_interpreter_t* s, void** l) {
|
|||||||
ast = (_ls_node_t*)(*l);
|
ast = (_ls_node_t*)(*l);
|
||||||
obj = (_object_t*)(ast->data);
|
obj = (_object_t*)(ast->data);
|
||||||
|
|
||||||
if(!obj || obj->type != _DT_VAR) {
|
if(!obj || obj->type == _DT_EOS) {
|
||||||
|
_get_inputer(s)(line, sizeof(line));
|
||||||
|
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
if(obj->type != _DT_VAR) {
|
||||||
_handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
_handle_error_on_obj(s, SE_RN_VARIABLE_EXPECTED, 0, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||||
}
|
}
|
||||||
if(obj->data.variable->data->type == _DT_INT || obj->data.variable->data->type == _DT_REAL) {
|
if(obj->data.variable->data->type == _DT_INT || obj->data.variable->data->type == _DT_REAL) {
|
||||||
|
@ -219,6 +219,7 @@ typedef enum mb_error_e {
|
|||||||
SE_RN_DONT_SUSPEND_IN_A_ROUTINE,
|
SE_RN_DONT_SUSPEND_IN_A_ROUTINE,
|
||||||
SE_RN_DONT_MIX_INSTRUCTIONAL_AND_STRUCTURED,
|
SE_RN_DONT_MIX_INSTRUCTIONAL_AND_STRUCTURED,
|
||||||
SE_RN_ROUTINE_EXPECTED,
|
SE_RN_ROUTINE_EXPECTED,
|
||||||
|
SE_RN_DUPLICATE_ROUTINE,
|
||||||
/** Extended abort */
|
/** Extended abort */
|
||||||
SE_EA_EXTENDED_ABORT,
|
SE_EA_EXTENDED_ABORT,
|
||||||
/** Extra */
|
/** Extra */
|
||||||
|
4
makefile
Normal file → Executable file
4
makefile
Normal file → Executable file
@ -5,7 +5,7 @@ main.o : shell/main.c core/my_basic.h
|
|||||||
cc -Os -c shell/main.c
|
cc -Os -c shell/main.c
|
||||||
|
|
||||||
my_basic.o : core/my_basic.c core/my_basic.h
|
my_basic.o : core/my_basic.c core/my_basic.h
|
||||||
cc -Os -c core/my_basic.c
|
cc -Os -c core/my_basic.c -Wno-multichar -Wno-overflow
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm edit $(objects)
|
rm -f main.o my_basic.o output/my_basic_bin output/my_basic_bin.exe
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -36,8 +36,8 @@
|
|||||||
IDI_ICON_MAIN ICON "icon.ico"
|
IDI_ICON_MAIN ICON "icon.ico"
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,1,68,0
|
FILEVERSION 1,1,69,0
|
||||||
PRODUCTVERSION 1,1,68,0
|
PRODUCTVERSION 1,1,69,0
|
||||||
FILEFLAGSMASK 0x17L
|
FILEFLAGSMASK 0x17L
|
||||||
# ifdef _DEBUG
|
# ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -55,13 +55,13 @@
|
|||||||
VALUE "Comments", "MY-BASIC"
|
VALUE "Comments", "MY-BASIC"
|
||||||
VALUE "CompanyName", "Wang Renxin"
|
VALUE "CompanyName", "Wang Renxin"
|
||||||
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
||||||
VALUE "FileVersion", "1, 1, 68, 0"
|
VALUE "FileVersion", "1, 1, 69, 0"
|
||||||
VALUE "InternalName", "my_basic"
|
VALUE "InternalName", "my_basic"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
||||||
VALUE "LegalTrademarks", "MY-BASIC"
|
VALUE "LegalTrademarks", "MY-BASIC"
|
||||||
VALUE "OriginalFilename", "my_basic.exe"
|
VALUE "OriginalFilename", "my_basic.exe"
|
||||||
VALUE "ProductName", "MY-BASIC"
|
VALUE "ProductName", "MY-BASIC"
|
||||||
VALUE "ProductVersion", "1, 1, 68, 0"
|
VALUE "ProductVersion", "1, 1, 69, 0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user