+added structures for class development; *updated readme doc; *updated exe icon.
This commit is contained in:
parent
bf9f5ec86c
commit
f6e9f9fbb1
4
HISTORY
4
HISTORY
@ -1,3 +1,7 @@
|
|||||||
|
Dec. 4 2015
|
||||||
|
Updated icon
|
||||||
|
Added structures for class development
|
||||||
|
|
||||||
Nov. 30 2015
|
Nov. 30 2015
|
||||||
Improved stability for sub routine
|
Improved stability for sub routine
|
||||||
Improved error handling with shell
|
Improved error handling with shell
|
||||||
|
40
README.md
40
README.md
@ -2,17 +2,21 @@
|
|||||||
|
|
||||||
**Copyright (C) 2011 - 2015 [Wang Renxin](https://cn.linkedin.com/pub/wang-renxin/43/494/20). All rights reserved.**
|
**Copyright (C) 2011 - 2015 [Wang Renxin](https://cn.linkedin.com/pub/wang-renxin/43/494/20). All rights reserved.**
|
||||||
|
|
||||||
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.
|
Why are existing script interpreters so complex? Why is it so difficult to integrate with them? Why not try MY-BASIC today! Script should be simple and enjoyable.
|
||||||
|
|
||||||
## Build status
|
## Build status
|
||||||
|
|
||||||
[](https://travis-ci.org/paladin-t/my_basic)
|
[](https://travis-ci.org/paladin-t/my_basic)
|
||||||
|
|
||||||
|
## Development status
|
||||||
|
|
||||||
|
* Class support under development
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Main features](#main-features)
|
* [Main features](#main-features)
|
||||||
* [Scripting at a glance](#scripting-at-a-glance)
|
* [Script at a glance](#script-at-a-glance)
|
||||||
* [Interpreter workflow diagram](#interpreter-workflow-diagram)
|
* [Interpreter workflow diagram](#interpreter-workflow-diagram)
|
||||||
* [Installation](#installation)
|
* [Installation](#installation)
|
||||||
* [Wiki](#wiki)
|
* [Wiki](#wiki)
|
||||||
@ -20,22 +24,22 @@ Why are existing script interpreters so complex? Why is it so difficult to integ
|
|||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter written in pure C with about 10,000 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.
|
MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter written in pure C with about 10,000 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. It's able to easily combine MY-BASIC with an existing project in C, C++, Objective-C, etc. Script driven can make your projects more powerful, elegant and neat.
|
||||||
|
|
||||||
## Main features
|
## Main features
|
||||||
|
|
||||||
* It is totally **free** to use MY-BASIC for individual or commercial purpose under the MIT license
|
* 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 is portable for a dozen of platforms
|
||||||
* With most common BASIC syntax
|
* With most common BASIC syntax
|
||||||
* **Lightweight** (within memory usage less than 128KB) and fast
|
* **Lightweight** (within memory usage less than 128KB) and fast
|
||||||
* Case-insensitive tokenization
|
* Case-insensitive tokenization
|
||||||
* Integer, float point, string, boolean, user defined data types, etc. with array support
|
* Integer, float point, string, boolean, user defined data types, etc. with array support
|
||||||
|
* Standard numeric functions, and standard string functions
|
||||||
* Referenced usertype support
|
* Referenced usertype support
|
||||||
* Collection implementation and manipulation functions for **`LIST`** and **`DICT`**
|
* Collection implementation and manipulation functions for **`LIST`** and **`DICT`**
|
||||||
* Automatic releasing of referenced objects (list, dictionary, referenced usertype, etc.) benefited from **Reference Counting** and **GC**
|
* Automatic releasing of referenced objects (list, dictionary, referenced usertype, etc.) benefited from **Reference Counting** and **Garbage Collection**
|
||||||
* Standard numeric functions, and standard string functions
|
|
||||||
* Multiple file support by `IMPORT` statement
|
* Multiple file support by `IMPORT` statement
|
||||||
* Structured user costomized **sub** routine definition by **`DEF/ENDDEF`** support, including tail recursion optimization
|
* Structured user customizable **sub** routine definition by **`DEF/ENDDEF`** support, including tail recursion optimization
|
||||||
* Structured `IF-THEN-ELSEIF-ELSE-ENDIF` support
|
* Structured `IF-THEN-ELSEIF-ELSE-ENDIF` support
|
||||||
* Structured `FOR-TO-STEP-NEXT/WHILE-WEND/DO-UNTIL` support
|
* Structured `FOR-TO-STEP-NEXT/WHILE-WEND/DO-UNTIL` support
|
||||||
* `GOTO/GOSUB-RETURN` support
|
* `GOTO/GOSUB-RETURN` support
|
||||||
@ -44,10 +48,10 @@ MY-BASIC is a lightweight cross-platform easy extendable BASIC interpreter writt
|
|||||||
* 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 projects in C, C++, Objective-C, etc.
|
* 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 with MY-BASIC
|
* It's able to learn how to build an interpreter from scratch with MY-BASIC
|
||||||
* It's able to build your own dialect based on MY-BASIC
|
* It's able to build your own dialect easily based on MY-BASIC
|
||||||
* More features/modules under developing
|
* More features/modules under developing
|
||||||
|
|
||||||
## Scripting at a glance
|
## Script at a glance
|
||||||
|
|
||||||
Come along with a traditional "hello world" script in MY-BASIC:
|
Come along with a traditional "hello world" script in MY-BASIC:
|
||||||
|
|
||||||
@ -75,20 +79,20 @@ Read the [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf) (especiall
|
|||||||
This repository contains precompiled binaries for [Windows](output/my_basic.exe) and [OS X](output/my_basic_mac), it's efficient to download it and have a first impressive playground. Or you could make a build as follow.
|
This repository contains precompiled binaries for [Windows](output/my_basic.exe) and [OS X](output/my_basic_mac), it's efficient to download it and have a first impressive playground. Or you could make a build as follow.
|
||||||
|
|
||||||
* Open the Visual Studio solution `my_basic.sln` on Windows to build an executable
|
* Open the Visual Studio solution `my_basic.sln` on Windows to build an executable
|
||||||
* Open the XCode solution `my_basic_mac.xcodeproj` on OS X to build an OS X executable
|
* Open the Xcode solution `my_basic_mac.xcodeproj` on OS X to build an OS X executable
|
||||||
* Use the `makefile` with "make" toolchain to build an interpreter binary according to your platform
|
* If you are not using VS or Xcode, use the `makefile` with a "make" toolchain to build an interpreter binary according to your own platform
|
||||||
|
|
||||||
To compile an interpreter binary for your own platform manually, please follow the steps.
|
To compile an interpreter binary for your own platform manually, please follow the steps.
|
||||||
|
|
||||||
* Retrieve at least `core` and `shell` folders for minimum build
|
1. Retrieve at least `core` and `shell` folders for minimum build
|
||||||
* Setup your compile toolchain configuration
|
2. Setup your compile toolchain configuration
|
||||||
* Use your compiler to compile `core/my_basic.c` and `shell/main.c`, including `core/my_basic.h` is required for both source files, then link up your own executable
|
3. Use your compiler to compile `core/my_basic.c` and `shell/main.c`, including `core/my_basic.h` is required for both source files, then link up your own executable
|
||||||
|
|
||||||
The standalone interpreter supports three modes.
|
The standalone interpreter supports three modes.
|
||||||
|
|
||||||
* Execute the binary directly without arguments to interactive with MY-BASIC
|
* Execute the binary directly without arguments to enter MY-BASIC interactive mode
|
||||||
* Pass a file path to the binary to load and run that script file
|
* Pass a file path to the binary to load and run that script file
|
||||||
* Pass an argument `-e` and an expression to evaluate and print it, eg. `-e "2 * (3 + 4)"`
|
* Pass an argument `-e` followed by an expression to evaluate and print it, eg. `-e "2 * (3 + 4)"`
|
||||||
|
|
||||||
### Combine with exist projects
|
### Combine with exist projects
|
||||||
|
|
||||||
@ -96,10 +100,12 @@ MY-BASIC is cleanly written in a single C source file and an associated header f
|
|||||||
|
|
||||||
You can definitely [link with MY-BASIC as a lib](https://github.com/paladin-t/my_basic/wiki/Link-with-MY_BASIC) as well.
|
You can definitely [link with MY-BASIC as a lib](https://github.com/paladin-t/my_basic/wiki/Link-with-MY_BASIC) as well.
|
||||||
|
|
||||||
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 a project, 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)
|
||||||
|
|
||||||
|
Most of the fundamental topics are mentioned in the [MY-BASIC Quick Reference](MY-BASIC%20Quick%20Reference.pdf). There are some other scattered topics besides these aspects, such as the desine principle, machinism behind MY-BASIC, effective practice, etc; they are issued in the [Wiki](https://github.com/paladin-t/my_basic/wiki).
|
||||||
|
|
||||||
* Principles
|
* Principles
|
||||||
* [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)
|
||||||
|
101
core/my_basic.c
101
core/my_basic.c
@ -81,7 +81,7 @@ extern "C" {
|
|||||||
/** Macros */
|
/** Macros */
|
||||||
#define _VER_MAJOR 1
|
#define _VER_MAJOR 1
|
||||||
#define _VER_MINOR 1
|
#define _VER_MINOR 1
|
||||||
#define _VER_REVISION 101
|
#define _VER_REVISION 102
|
||||||
#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)
|
||||||
@ -229,6 +229,7 @@ static const char* _ERR_DESC[] = {
|
|||||||
"Invalid routine",
|
"Invalid routine",
|
||||||
"Routine expected",
|
"Routine expected",
|
||||||
"Duplicate routine",
|
"Duplicate routine",
|
||||||
|
"Invalid class",
|
||||||
"Collection expected",
|
"Collection expected",
|
||||||
"Iterator expected",
|
"Iterator expected",
|
||||||
"Collection or iterator expected",
|
"Collection or iterator expected",
|
||||||
@ -261,8 +262,10 @@ typedef enum _data_e {
|
|||||||
_DT_DICT_IT,
|
_DT_DICT_IT,
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
_DT_LABEL, /* Label type, used for GOTO, GOSUB statement */
|
_DT_LABEL, /* Label type, used for GOTO, GOSUB statement */
|
||||||
_DT_ROUTINE, /* User defined sub routine in script */
|
#ifdef MB_ENABLE_CLASS
|
||||||
_DT_CLASS, /* Object instance */
|
_DT_CLASS, /* Object instance */
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
_DT_ROUTINE, /* User defined sub routine in script */
|
||||||
_DT_SEP, /* Separator */
|
_DT_SEP, /* Separator */
|
||||||
_DT_EOS /* End of statement */
|
_DT_EOS /* End of statement */
|
||||||
} _data_e;
|
} _data_e;
|
||||||
@ -357,14 +360,18 @@ typedef struct _label_t {
|
|||||||
_ls_node_t* node;
|
_ls_node_t* node;
|
||||||
} _label_t;
|
} _label_t;
|
||||||
|
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
typedef struct _class_t {
|
typedef struct _class_t {
|
||||||
char* name;
|
char* name;
|
||||||
struct _running_context_t* scope;
|
struct _running_context_t* scope;
|
||||||
} _class_t;
|
} _class_t;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
|
||||||
typedef struct _routine_t {
|
typedef struct _routine_t {
|
||||||
char* name;
|
char* name;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
_class_t* instance;
|
_class_t* instance;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
struct _running_context_t* scope;
|
struct _running_context_t* scope;
|
||||||
_ls_node_t* entry;
|
_ls_node_t* entry;
|
||||||
_ls_node_t* parameters;
|
_ls_node_t* parameters;
|
||||||
@ -396,8 +403,10 @@ typedef struct _object_t {
|
|||||||
_dict_it_t* dict_it;
|
_dict_it_t* dict_it;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
_label_t* label;
|
_label_t* label;
|
||||||
_routine_t* routine;
|
#ifdef MB_ENABLE_CLASS
|
||||||
_class_t* instance;
|
_class_t* instance;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
_routine_t* routine;
|
||||||
char separator;
|
char separator;
|
||||||
mb_val_bytes_t bytes;
|
mb_val_bytes_t bytes;
|
||||||
_raw_t raw;
|
_raw_t raw;
|
||||||
@ -440,7 +449,9 @@ MBAPI const size_t MB_SIZEOF_ARR = _MB_MEM_TAG_SIZE + sizeof(_array_t);
|
|||||||
MBAPI const size_t MB_SIZEOF_VAR = _MB_MEM_TAG_SIZE + sizeof(_var_t);
|
MBAPI const size_t MB_SIZEOF_VAR = _MB_MEM_TAG_SIZE + sizeof(_var_t);
|
||||||
MBAPI const size_t MB_SIZEOF_LBL = _MB_MEM_TAG_SIZE + sizeof(_label_t);
|
MBAPI const size_t MB_SIZEOF_LBL = _MB_MEM_TAG_SIZE + sizeof(_label_t);
|
||||||
MBAPI const size_t MB_SIZEOF_RTN = _MB_MEM_TAG_SIZE + sizeof(_routine_t);
|
MBAPI const size_t MB_SIZEOF_RTN = _MB_MEM_TAG_SIZE + sizeof(_routine_t);
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
MBAPI const size_t MB_SIZEOF_CLS = _MB_MEM_TAG_SIZE + sizeof(_class_t);
|
MBAPI const size_t MB_SIZEOF_CLS = _MB_MEM_TAG_SIZE + sizeof(_class_t);
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
#else /* MB_ENABLE_ALLOC_STAT */
|
#else /* MB_ENABLE_ALLOC_STAT */
|
||||||
MBAPI const size_t MB_SIZEOF_INT = sizeof(int);
|
MBAPI const size_t MB_SIZEOF_INT = sizeof(int);
|
||||||
MBAPI const size_t MB_SIZEOF_PTR = sizeof(intptr_t);
|
MBAPI const size_t MB_SIZEOF_PTR = sizeof(intptr_t);
|
||||||
@ -453,7 +464,9 @@ MBAPI const size_t MB_SIZEOF_ARR = sizeof(_array_t);
|
|||||||
MBAPI const size_t MB_SIZEOF_VAR = sizeof(_var_t);
|
MBAPI const size_t MB_SIZEOF_VAR = sizeof(_var_t);
|
||||||
MBAPI const size_t MB_SIZEOF_LBL = sizeof(_label_t);
|
MBAPI const size_t MB_SIZEOF_LBL = sizeof(_label_t);
|
||||||
MBAPI const size_t MB_SIZEOF_RTN = sizeof(_routine_t);
|
MBAPI const size_t MB_SIZEOF_RTN = sizeof(_routine_t);
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
MBAPI const size_t MB_SIZEOF_CLS = sizeof(_class_t);
|
MBAPI const size_t MB_SIZEOF_CLS = sizeof(_class_t);
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
#endif /* MB_ENABLE_ALLOC_STAT */
|
#endif /* MB_ENABLE_ALLOC_STAT */
|
||||||
|
|
||||||
#ifdef MB_ENABLE_SOURCE_TRACE
|
#ifdef MB_ENABLE_SOURCE_TRACE
|
||||||
@ -1150,9 +1163,11 @@ static unsigned _unref(_ref_t* ref, void* data);
|
|||||||
static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s);
|
static void _create_ref(_ref_t* ref, _unref_func_t dtor, _data_e t, mb_interpreter_t* s);
|
||||||
static void _destroy_ref(_ref_t* ref);
|
static void _destroy_ref(_ref_t* ref);
|
||||||
|
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
static void _init_class(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 _begin_class(mb_interpreter_t* s);
|
||||||
static void _end_class(mb_interpreter_t* s);
|
static bool_t _end_class(mb_interpreter_t* s);
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
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 bool_t _end_routine(mb_interpreter_t* s);
|
static bool_t _end_routine(mb_interpreter_t* s);
|
||||||
@ -1415,8 +1430,10 @@ static const _func_t _core_libs[] = {
|
|||||||
{ "CALL", _core_call },
|
{ "CALL", _core_call },
|
||||||
{ "DEF", _core_def },
|
{ "DEF", _core_def },
|
||||||
{ "ENDDEF", _core_enddef },
|
{ "ENDDEF", _core_enddef },
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
{ "CLASS", _core_class },
|
{ "CLASS", _core_class },
|
||||||
{ "ENDCLASS", _core_endclass },
|
{ "ENDCLASS", _core_endclass },
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
|
||||||
#ifdef MB_ENABLE_ALLOC_STAT
|
#ifdef MB_ENABLE_ALLOC_STAT
|
||||||
{ "MEM", _core_mem },
|
{ "MEM", _core_mem },
|
||||||
@ -3211,7 +3228,13 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
/* Create a syntax symbol */
|
/* Create a syntax symbol */
|
||||||
int result = MB_FUNC_OK;
|
int result = MB_FUNC_OK;
|
||||||
_data_e type;
|
_data_e type;
|
||||||
union { _func_t* func; _array_t* array; _class_t* instance; _routine_t* routine; _var_t* var; _label_t* label; real_t float_point; int_t integer; _raw_t any; } tmp;
|
union {
|
||||||
|
_func_t* func; _array_t* array;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
_class_t* instance;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
_routine_t* routine; _var_t* var; _label_t* label; real_t float_point; int_t integer; _raw_t any;
|
||||||
|
} tmp;
|
||||||
_raw_t value;
|
_raw_t value;
|
||||||
unsigned int ul = 0;
|
unsigned int ul = 0;
|
||||||
_parsing_context_t* context = 0;
|
_parsing_context_t* context = 0;
|
||||||
@ -3304,6 +3327,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
case _DT_CLASS:
|
case _DT_CLASS:
|
||||||
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_CLASS) {
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_CLASS) {
|
||||||
@ -3332,6 +3356,7 @@ int _create_symbol(mb_interpreter_t* s, _ls_node_t* l, char* sym, _object_t** ob
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_ROUTINE) {
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_ROUTINE) {
|
||||||
@ -3563,6 +3588,7 @@ _end_import:
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
/* _class_t */
|
/* _class_t */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
if(context->last_symbol) {
|
if(context->last_symbol) {
|
||||||
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
||||||
if(glbsyminscope && ((_object_t*)glbsyminscope->data)->type == _DT_CLASS) {
|
if(glbsyminscope && ((_object_t*)glbsyminscope->data)->type == _DT_CLASS) {
|
||||||
@ -3581,26 +3607,28 @@ _end_import:
|
|||||||
goto _exit;
|
goto _exit;
|
||||||
}
|
}
|
||||||
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
if(glbsyminscope && ((_object_t*)(glbsyminscope->data))->type == _DT_VAR) {
|
||||||
tmp.obj = (_object_t*)(glbsyminscope->data);
|
_handle_error_now(s, SE_RN_INVALID_CLASS, 0, MB_FUNC_ERR);
|
||||||
if(!tmp.obj->ref) {
|
|
||||||
_ht_remove(running->var_dict, sym, _ls_cmp_extra_string);
|
goto _exit;
|
||||||
_dispose_object(tmp.obj);
|
}
|
||||||
|
|
||||||
|
if(_IS_FUNC(context->last_symbol, _core_def)) {
|
||||||
|
if(context->routine_state > 1) {
|
||||||
|
_handle_error_now(s, SE_RN_INVALID_CLASS, 0, MB_FUNC_ERR);
|
||||||
|
|
||||||
|
goto _exit;
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _DT_CLASS;
|
result = _DT_CLASS;
|
||||||
|
|
||||||
goto _exit;
|
goto _exit;
|
||||||
} else if(_IS_FUNC(context->last_symbol, _core_endclass)) {
|
} else if(_IS_FUNC(context->last_symbol, _core_endclass)) {
|
||||||
_end_class(s);
|
if(_end_class(s))
|
||||||
_pop_scope(s);
|
_pop_scope(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
/* _routine_t */
|
/* _routine_t */
|
||||||
if(context->last_symbol) {
|
if(context->last_symbol) {
|
||||||
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
glbsyminscope = _search_identifier_in_scope_chain(s, 0, sym);
|
||||||
@ -5080,6 +5108,7 @@ void _destroy_ref(_ref_t* ref) {
|
|||||||
ref->on_unref = 0;
|
ref->on_unref = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
|
void _init_class(mb_interpreter_t* s, _class_t* instance, char* n) {
|
||||||
/* Initialize a class */
|
/* Initialize a class */
|
||||||
_running_context_t* running = 0;
|
_running_context_t* running = 0;
|
||||||
@ -5105,15 +5134,23 @@ void _begin_class(mb_interpreter_t* s) {
|
|||||||
context->class_state++;
|
context->class_state++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _end_class(mb_interpreter_t* s) {
|
bool_t _end_class(mb_interpreter_t* s) {
|
||||||
/* End parsing a class */
|
/* End parsing a class */
|
||||||
_parsing_context_t* context = 0;
|
_parsing_context_t* context = 0;
|
||||||
|
|
||||||
mb_assert(s);
|
mb_assert(s);
|
||||||
|
|
||||||
context = s->parsing_context;
|
context = s->parsing_context;
|
||||||
|
if(!context->class_state) {
|
||||||
|
_handle_error_now(s, SE_RN_INVALID_CLASS, 0, MB_FUNC_ERR);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
context->class_state--;
|
context->class_state--;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
|
||||||
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
|
void _init_routine(mb_interpreter_t* s, _routine_t* routine, char* n) {
|
||||||
/* Initialize a routine */
|
/* Initialize a routine */
|
||||||
@ -5454,10 +5491,12 @@ int _clone_object(_object_t* obj, _object_t* tgt) {
|
|||||||
tgt->data.label->node = obj->data.label->node;
|
tgt->data.label->node = obj->data.label->node;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
case _DT_CLASS:
|
case _DT_CLASS:
|
||||||
mb_assert(0 && "Not implemented");
|
mb_assert(0 && "Not implemented");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
mb_assert(0 && "Not implemented");
|
mb_assert(0 && "Not implemented");
|
||||||
|
|
||||||
@ -5545,6 +5584,7 @@ int _dispose_object(_object_t* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
case _DT_CLASS:
|
case _DT_CLASS:
|
||||||
if(!obj->ref) {
|
if(!obj->ref) {
|
||||||
safe_free(obj->data.instance->name);
|
safe_free(obj->data.instance->name);
|
||||||
@ -5555,6 +5595,7 @@ int _dispose_object(_object_t* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
if(!obj->ref) {
|
if(!obj->ref) {
|
||||||
safe_free(obj->data.routine->name);
|
safe_free(obj->data.routine->name);
|
||||||
@ -5796,6 +5837,10 @@ _data_e _public_type_to_internal_type(mb_data_e t) {
|
|||||||
case MB_DT_DICT_IT:
|
case MB_DT_DICT_IT:
|
||||||
return _DT_DICT_IT;
|
return _DT_DICT_IT;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
case MB_DT_CLASS:
|
||||||
|
return _DT_CLASS;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case MB_DT_ROUTINE:
|
case MB_DT_ROUTINE:
|
||||||
return _DT_ROUTINE;
|
return _DT_ROUTINE;
|
||||||
default:
|
default:
|
||||||
@ -5832,6 +5877,10 @@ mb_data_e _internal_type_to_public_type(_data_e t) {
|
|||||||
case _DT_DICT_IT:
|
case _DT_DICT_IT:
|
||||||
return MB_DT_DICT_IT;
|
return MB_DT_DICT_IT;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
case _DT_CLASS:
|
||||||
|
return MB_DT_CLASS;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
return MB_DT_ROUTINE;
|
return MB_DT_ROUTINE;
|
||||||
default:
|
default:
|
||||||
@ -5911,6 +5960,11 @@ int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
case MB_DT_CLASS:
|
||||||
|
itn->type = _DT_CLASS;
|
||||||
|
itn->data.instance = (_class_t*)pbl->value.instance;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case MB_DT_ROUTINE:
|
case MB_DT_ROUTINE:
|
||||||
itn->type = _DT_ROUTINE;
|
itn->type = _DT_ROUTINE;
|
||||||
itn->data.routine = (_routine_t*)pbl->value.routine;
|
itn->data.routine = (_routine_t*)pbl->value.routine;
|
||||||
@ -5993,6 +6047,13 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
case _DT_CLASS:
|
||||||
|
pbl->type = MB_DT_CLASS;
|
||||||
|
pbl->value.instance = itn->data.instance;
|
||||||
|
|
||||||
|
break;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
pbl->type = MB_DT_ROUTINE;
|
pbl->type = MB_DT_ROUTINE;
|
||||||
pbl->value.routine = itn->data.routine;
|
pbl->value.routine = itn->data.routine;
|
||||||
@ -6187,10 +6248,12 @@ int _execute_statement(mb_interpreter_t* s, _ls_node_t** l) {
|
|||||||
_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;
|
break;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
case _DT_CLASS:
|
case _DT_CLASS:
|
||||||
mb_assert(0 && "Not implemented");
|
mb_assert(0 && "Not implemented");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
case _DT_ROUTINE:
|
case _DT_ROUTINE:
|
||||||
ast = ast->prev;
|
ast = ast->prev;
|
||||||
result = _core_call(s, (void**)(&ast));
|
result = _core_call(s, (void**)(&ast));
|
||||||
@ -8175,6 +8238,12 @@ const char* mb_get_type_string(mb_data_e t) {
|
|||||||
case MB_DT_DICT_IT:
|
case MB_DT_DICT_IT:
|
||||||
return "DICT_ITERATOR";
|
return "DICT_ITERATOR";
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
case MB_DT_CLASS:
|
||||||
|
return "CLASS";
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
case MB_DT_ROUTINE:
|
||||||
|
return "ROUTINE";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,10 @@ extern "C" {
|
|||||||
# define MB_ENABLE_MODULE
|
# define MB_ENABLE_MODULE
|
||||||
#endif /* MB_ENABLE_MODULE */
|
#endif /* MB_ENABLE_MODULE */
|
||||||
|
|
||||||
|
#ifndef MB_ENABLE_CLASS
|
||||||
|
# define MB_ENABLE_CLASS
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
|
||||||
#ifndef MB_COMPACT_MODE
|
#ifndef MB_COMPACT_MODE
|
||||||
# define MB_COMPACT_MODE
|
# define MB_COMPACT_MODE
|
||||||
#endif /* MB_COMPACT_MODE */
|
#endif /* MB_COMPACT_MODE */
|
||||||
@ -309,6 +313,7 @@ typedef enum mb_error_e {
|
|||||||
SE_RN_INVALID_ROUTINE,
|
SE_RN_INVALID_ROUTINE,
|
||||||
SE_RN_ROUTINE_EXPECTED,
|
SE_RN_ROUTINE_EXPECTED,
|
||||||
SE_RN_DUPLICATE_ROUTINE,
|
SE_RN_DUPLICATE_ROUTINE,
|
||||||
|
SE_RN_INVALID_CLASS,
|
||||||
SE_RN_COLLECTION_EXPECTED,
|
SE_RN_COLLECTION_EXPECTED,
|
||||||
SE_RN_ITERATOR_EXPECTED,
|
SE_RN_ITERATOR_EXPECTED,
|
||||||
SE_RN_COLLECTION_OR_ITERATOR_EXPECTED,
|
SE_RN_COLLECTION_OR_ITERATOR_EXPECTED,
|
||||||
@ -337,7 +342,10 @@ typedef enum mb_data_e {
|
|||||||
MB_DT_DICT = 1 << 15,
|
MB_DT_DICT = 1 << 15,
|
||||||
MB_DT_DICT_IT = 1 << 16,
|
MB_DT_DICT_IT = 1 << 16,
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
MB_DT_ROUTINE = 1 << 24
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
MB_DT_CLASS = 1 << 24,
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
MB_DT_ROUTINE = 1 << 25
|
||||||
} mb_data_e;
|
} mb_data_e;
|
||||||
|
|
||||||
typedef unsigned char mb_val_bytes_t[sizeof(void*)];
|
typedef unsigned char mb_val_bytes_t[sizeof(void*)];
|
||||||
@ -356,6 +364,9 @@ typedef union mb_value_u {
|
|||||||
void* dict;
|
void* dict;
|
||||||
void* dict_it;
|
void* dict_it;
|
||||||
#endif /* MB_ENABLE_COLLECTION_LIB */
|
#endif /* MB_ENABLE_COLLECTION_LIB */
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
|
void* instance;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
void* routine;
|
void* routine;
|
||||||
mb_val_bytes_t bytes;
|
mb_val_bytes_t bytes;
|
||||||
} mb_value_u;
|
} mb_value_u;
|
||||||
|
Binary file not shown.
@ -125,7 +125,11 @@ extern MBAPI const size_t MB_SIZEOF_ARR;
|
|||||||
extern MBAPI const size_t MB_SIZEOF_VAR;
|
extern MBAPI const size_t MB_SIZEOF_VAR;
|
||||||
extern MBAPI const size_t MB_SIZEOF_LBL;
|
extern MBAPI const size_t MB_SIZEOF_LBL;
|
||||||
extern MBAPI const size_t MB_SIZEOF_RTN;
|
extern MBAPI const size_t MB_SIZEOF_RTN;
|
||||||
|
#ifdef MB_ENABLE_CLASS
|
||||||
extern MBAPI const size_t MB_SIZEOF_CLS;
|
extern MBAPI const size_t MB_SIZEOF_CLS;
|
||||||
|
#else /* MB_ENABLE_CLASS */
|
||||||
|
static const size_t MB_SIZEOF_CLS = 20;
|
||||||
|
#endif /* MB_ENABLE_CLASS */
|
||||||
|
|
||||||
typedef unsigned _pool_chunk_size_t;
|
typedef unsigned _pool_chunk_size_t;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user