+added structures for class development; *updated readme doc; *updated exe icon.

This commit is contained in:
paladin-t 2015-12-04 11:26:42 +08:00
parent bf9f5ec86c
commit f6e9f9fbb1
6 changed files with 129 additions and 35 deletions

View File

@ -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

View File

@ -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
[![Build Status](https://travis-ci.org/paladin-t/my_basic.svg?branch=master)](https://travis-ci.org/paladin-t/my_basic) [![Build Status](https://travis-ci.org/paladin-t/my_basic.svg?branch=master)](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)

View File

@ -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";
} }

View File

@ -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.

View File

@ -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;