+added array manipulation functions
This commit is contained in:
parent
1dca057d76
commit
1a2bce265a
3
HISTORY
3
HISTORY
@ -1,3 +1,6 @@
|
||||
Jul. 12 2015
|
||||
Added array manipulation functions
|
||||
|
||||
Jun. 19 2015
|
||||
Added an mb_schedule_suspend interface to schedule to suspend the execution
|
||||
|
||||
|
266
core/my_basic.c
266
core/my_basic.c
@ -78,7 +78,7 @@ extern "C" {
|
||||
/** Macros */
|
||||
#define _VER_MAJOR 1
|
||||
#define _VER_MINOR 1
|
||||
#define _VER_REVISION 56
|
||||
#define _VER_REVISION 57
|
||||
#define _MB_VERSION ((_VER_MAJOR * 0x01000000) + (_VER_MINOR * 0x00010000) + (_VER_REVISION))
|
||||
|
||||
/* Uncomment this line to treat warnings as error */
|
||||
@ -670,6 +670,7 @@ static void _set_error_pos(mb_interpreter_t* s, int pos, unsigned short row, uns
|
||||
static int_t _get_size_of(_data_e type);
|
||||
static bool_t _try_get_value(_object_t* obj, mb_value_u* val, _data_e expected);
|
||||
|
||||
static int _get_array_pos(struct mb_interpreter_t* s, _array_t* arr, int* d, int c);
|
||||
static int _get_array_index(mb_interpreter_t* s, _ls_node_t** l, unsigned int* index);
|
||||
static bool_t _get_array_elem(mb_interpreter_t* s, _array_t* arr, unsigned int index, mb_value_u* val, _data_e* type);
|
||||
static int _set_array_elem(mb_interpreter_t* s, _ls_node_t* ast, _array_t* arr, unsigned int index, mb_value_u* val, _data_e* type);
|
||||
@ -677,6 +678,7 @@ static int _set_array_elem(mb_interpreter_t* s, _ls_node_t* ast, _array_t* arr,
|
||||
static void _init_array(_array_t* arr);
|
||||
static void _clear_array(_array_t* arr);
|
||||
static void _destroy_array(_array_t* arr);
|
||||
static bool_t _is_array(void* obj);
|
||||
static bool_t _is_string(void* obj);
|
||||
static char* _extract_string(_object_t* obj);
|
||||
static bool_t _is_internal_object(_object_t* obj);
|
||||
@ -685,6 +687,8 @@ static int _destroy_object(void* data, void* extra);
|
||||
static int _destroy_object_non_syntax(void* data, void* extra);
|
||||
static int _remove_source_object(void* data, void* extra);
|
||||
static int _compare_numbers(const _object_t* first, const _object_t* second);
|
||||
static _data_e _public_type_to_internal_type(mb_data_e t);
|
||||
static mb_data_e _internal_type_to_public_type(_data_e t);
|
||||
static int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn);
|
||||
static int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl);
|
||||
static void _try_clear_intermediate_value(void* data, void* extra, mb_interpreter_t* s);
|
||||
@ -1635,6 +1639,35 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
||||
}
|
||||
_ls_pushback(opnd, c);
|
||||
f++;
|
||||
} else if(c->type == _DT_VAR && c->data.variable->data->type == _DT_ARRAY) {
|
||||
ast = ast->prev;
|
||||
result = _get_array_index(s, &ast, &arr_idx);
|
||||
if(result != MB_FUNC_OK) {
|
||||
_handle_error_on_obj(s, SE_RN_CALCULATION_ERROR, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||
}
|
||||
ast = ast->next;
|
||||
_get_array_elem(s, c->data.variable->data->data.array, arr_idx, &arr_val, &arr_type);
|
||||
arr_elem = (_object_t*)mb_malloc(sizeof(_object_t));
|
||||
memset(arr_elem, 0, sizeof(_object_t));
|
||||
_ls_pushback(garbage, arr_elem);
|
||||
arr_elem->type = arr_type;
|
||||
arr_elem->ref = true;
|
||||
if(arr_type == _DT_INT) {
|
||||
arr_elem->data.integer = arr_val.integer;
|
||||
} else if(arr_type == _DT_REAL) {
|
||||
arr_elem->data.float_point = arr_val.float_point;
|
||||
} else if(arr_type == _DT_STRING) {
|
||||
arr_elem->data.string = arr_val.string;
|
||||
} else if(arr_type == _DT_USERTYPE) {
|
||||
arr_elem->data.usertype = arr_val.usertype;
|
||||
} else {
|
||||
mb_assert(0 && "Unsupported");
|
||||
}
|
||||
if(f) {
|
||||
_handle_error_on_obj(s, SE_RN_OPERATOR_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||
}
|
||||
_ls_pushback(opnd, arr_elem);
|
||||
f++;
|
||||
} else {
|
||||
if(c->type == _DT_VAR && ast) {
|
||||
_object_t* _err_var = (_object_t*)(ast->data);
|
||||
@ -1700,7 +1733,7 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
||||
}
|
||||
|
||||
c = (_object_t*)(_ls_popback(opnd));
|
||||
if(!c || !(c->type == _DT_INT || c->type == _DT_REAL || c->type == _DT_STRING || c->type == _DT_VAR || c->type == _DT_USERTYPE)) {
|
||||
if(!c || !(c->type == _DT_INT || c->type == _DT_REAL || c->type == _DT_STRING || c->type == _DT_VAR || c->type == _DT_USERTYPE || c->type == _DT_ARRAY)) {
|
||||
_set_current_error(s, SE_RN_INVALID_DATA_TYPE);
|
||||
result = MB_FUNC_ERR;
|
||||
|
||||
@ -1718,6 +1751,9 @@ int _calc_expression(mb_interpreter_t* s, _ls_node_t** l, _object_t** val) {
|
||||
(*val)->data.string = (char*)mb_malloc(_sl + 1);
|
||||
(*val)->data.string[_sl] = '\0';
|
||||
memcpy((*val)->data.string, c->data.string, _sl + 1);
|
||||
} else if(c->type == _DT_ARRAY) {
|
||||
(*val)->data = c->data;
|
||||
c->type = _DT_NIL;
|
||||
} else {
|
||||
(*val)->data = c->data;
|
||||
}
|
||||
@ -2343,6 +2379,7 @@ bool_t _try_get_value(_object_t* obj, mb_value_u* val, _data_e expected) {
|
||||
bool_t result = false;
|
||||
|
||||
mb_assert(obj && val);
|
||||
|
||||
if(obj->type == _DT_INT && (expected == _DT_ANY || expected == _DT_INT)) {
|
||||
val->integer = obj->data.integer;
|
||||
result = true;
|
||||
@ -2356,8 +2393,38 @@ bool_t _try_get_value(_object_t* obj, mb_value_u* val, _data_e expected) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int _get_array_pos(struct mb_interpreter_t* s, _array_t* arr, int* d, int c) {
|
||||
/* Calculate the index, used when interactive with host */
|
||||
int result = 0;
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
|
||||
mb_assert(s && arr && d);
|
||||
|
||||
if(c < 0 || c > arr->dimension_count) {
|
||||
result = -1;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
for(i = 0; i < c; i++) {
|
||||
n = d[i];
|
||||
if(n < 0 || n >= arr->dimensions[i]) {
|
||||
result = -1;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
if(result)
|
||||
result *= n;
|
||||
else
|
||||
result += n;
|
||||
}
|
||||
|
||||
_exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
int _get_array_index(mb_interpreter_t* s, _ls_node_t** l, unsigned int* index) {
|
||||
/* Calculate the index */
|
||||
/* Calculate the index, used when walking through an AST */
|
||||
int result = MB_FUNC_OK;
|
||||
_ls_node_t* ast = 0;
|
||||
_object_t* arr = 0;
|
||||
@ -2374,10 +2441,13 @@ int _get_array_index(mb_interpreter_t* s, _ls_node_t** l, unsigned int* index) {
|
||||
|
||||
/* Array name */
|
||||
ast = (_ls_node_t*)(*l);
|
||||
if(!ast || ((_object_t*)(ast->data))->type != _DT_ARRAY) {
|
||||
if(!ast || !_is_array(ast->data)) {
|
||||
_handle_error_on_obj(s, SE_RN_ARRAY_IDENTIFIER_EXPECTED, DON(ast), MB_FUNC_ERR, _exit, result);
|
||||
}
|
||||
if(((_object_t*)(ast->data))->type == _DT_ARRAY)
|
||||
arr = (_object_t*)(ast->data);
|
||||
else
|
||||
arr = ((_object_t*)(ast->data))->data.variable->data;
|
||||
/* ( */
|
||||
if(!ast->next || ((_object_t*)(ast->next->data))->type != _DT_FUNC || ((_object_t*)(ast->next->data))->data.func->pointer != _core_open_bracket) {
|
||||
_handle_error_on_obj(s, SE_RN_OPEN_BRACKET_EXPECTED,
|
||||
@ -2598,7 +2668,9 @@ void _destroy_array(_array_t* arr) {
|
||||
mb_assert(arr);
|
||||
|
||||
_clear_array(arr);
|
||||
if(arr->name) {
|
||||
safe_free(arr->name);
|
||||
}
|
||||
#ifndef MB_SIMPLE_ARRAY
|
||||
if(arr->types) {
|
||||
safe_free(arr->types);
|
||||
@ -2607,6 +2679,22 @@ void _destroy_array(_array_t* arr) {
|
||||
safe_free(arr);
|
||||
}
|
||||
|
||||
bool_t _is_array(void* obj) {
|
||||
/* Determine whether an object is an array value or an array variable */
|
||||
bool_t result = false;
|
||||
_object_t* o = 0;
|
||||
|
||||
mb_assert(obj);
|
||||
|
||||
o = (_object_t*)obj;
|
||||
if(o->type == _DT_ARRAY)
|
||||
result = true;
|
||||
else if(o->type == _DT_VAR)
|
||||
result = o->data.variable->data->type == _DT_ARRAY;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool_t _is_string(void* obj) {
|
||||
/* Determine whether an object is a string value or a string variable */
|
||||
bool_t result = false;
|
||||
@ -2799,6 +2887,38 @@ int _compare_numbers(const _object_t* first, const _object_t* second) {
|
||||
return result;
|
||||
}
|
||||
|
||||
_data_e _public_type_to_internal_type(mb_data_e t) {
|
||||
/* Convert a public mb_data_e type to an internal _data_e */
|
||||
switch(t) {
|
||||
case MB_DT_INT:
|
||||
return _DT_INT;
|
||||
case MB_DT_REAL:
|
||||
return _DT_REAL;
|
||||
case MB_DT_STRING:
|
||||
return _DT_STRING;
|
||||
case MB_DT_USERTYPE:
|
||||
return _DT_USERTYPE;
|
||||
default:
|
||||
return _DT_NIL;
|
||||
}
|
||||
}
|
||||
|
||||
mb_data_e _internal_type_to_public_type(_data_e t) {
|
||||
/* Convert an internal mb_data_e type to a public _data_e */
|
||||
switch(t) {
|
||||
case _DT_INT:
|
||||
return MB_DT_INT;
|
||||
case _DT_REAL:
|
||||
return MB_DT_REAL;
|
||||
case _DT_STRING:
|
||||
return MB_DT_STRING;
|
||||
case _DT_USERTYPE:
|
||||
return MB_DT_USERTYPE;
|
||||
default:
|
||||
return MB_DT_NIL;
|
||||
}
|
||||
}
|
||||
|
||||
int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn) {
|
||||
/* Assign a public mb_value_t to an internal _object_t */
|
||||
int result = MB_FUNC_OK;
|
||||
@ -2825,6 +2945,11 @@ int _public_value_to_internal_object(mb_value_t* pbl, _object_t* itn) {
|
||||
itn->type = _DT_USERTYPE;
|
||||
itn->data.usertype = pbl->value.usertype;
|
||||
|
||||
break;
|
||||
case MB_DT_ARRAY:
|
||||
itn->type = _DT_ARRAY;
|
||||
itn->data.array = pbl->value.array;
|
||||
|
||||
break;
|
||||
default:
|
||||
result = MB_FUNC_ERR;
|
||||
@ -2861,6 +2986,11 @@ int _internal_object_to_public_value(_object_t* itn, mb_value_t* pbl) {
|
||||
pbl->type = MB_DT_USERTYPE;
|
||||
pbl->value.usertype = itn->data.usertype;
|
||||
|
||||
break;
|
||||
case _DT_ARRAY:
|
||||
pbl->type = MB_DT_ARRAY;
|
||||
pbl->value.array = itn->data.array;
|
||||
|
||||
break;
|
||||
default:
|
||||
result = MB_FUNC_ERR;
|
||||
@ -3798,6 +3928,134 @@ int mb_push_value(struct mb_interpreter_t* s, void** l, mb_value_t val) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int mb_init_array(struct mb_interpreter_t* s, void** l, mb_data_e t, int* d, int c, void** a) {
|
||||
/* Create an array */
|
||||
int result = MB_FUNC_OK;
|
||||
_array_t* arr = 0;
|
||||
_data_e type = _DT_NIL;
|
||||
int j = 0;
|
||||
int n = 0;
|
||||
|
||||
mb_assert(s && l && d && a);
|
||||
|
||||
*a = 0;
|
||||
#ifdef MB_SIMPLE_ARRAY
|
||||
if(t == MB_DT_REAL) {
|
||||
type = _DT_REAL;
|
||||
} else if(t == MB_DT_STRING) {
|
||||
type = _DT_STRING;
|
||||
} else {
|
||||
result = MB_NEED_COMPLEX_ARRAY;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
#else /* MB_SIMPLE_ARRAY */
|
||||
type = _DT_REAL;
|
||||
#endif /* MB_SIMPLE_ARRAY */
|
||||
|
||||
arr = (_array_t*)mb_malloc(sizeof(_array_t));
|
||||
memset(arr, 0, sizeof(_array_t));
|
||||
arr->type = type;
|
||||
arr->name = 0;
|
||||
for(j = 0; j < c; j++) {
|
||||
n = d[j];
|
||||
arr->dimensions[arr->dimension_count++] = n;
|
||||
if(arr->count)
|
||||
arr->count *= n;
|
||||
else
|
||||
arr->count += n;
|
||||
}
|
||||
_init_array(arr);
|
||||
if(!arr->raw) {
|
||||
arr->dimension_count = 0;
|
||||
arr->dimensions[0] = 0;
|
||||
arr->count = 0;
|
||||
}
|
||||
*a = arr;
|
||||
|
||||
_exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
int mb_get_array_len(struct mb_interpreter_t* s, void** l, void* a, int r, int* i) {
|
||||
/* Get the length of an array */
|
||||
int result = MB_FUNC_OK;
|
||||
_array_t* arr = 0;
|
||||
|
||||
mb_assert(s && l);
|
||||
arr = (_array_t*)a;
|
||||
if(r < 0 || r >= arr->dimension_count) {
|
||||
result = MB_RANK_OUT_OF_BOUNDS;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
if(i)
|
||||
*i = arr->dimensions[r];
|
||||
|
||||
_exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
int mb_get_array_elem(struct mb_interpreter_t* s, void** l, void* a, int* d, int c, mb_value_t* val) {
|
||||
/* Get an element of an array with a given index */
|
||||
int result = MB_FUNC_OK;
|
||||
_array_t* arr = 0;
|
||||
int index = 0;
|
||||
_data_e type = _DT_NIL;
|
||||
|
||||
mb_assert(s && l);
|
||||
arr = (_array_t*)a;
|
||||
if(c < 0 || c > arr->dimension_count) {
|
||||
result = MB_RANK_OUT_OF_BOUNDS;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
if(!val)
|
||||
goto _exit;
|
||||
|
||||
index = _get_array_pos(s, arr, d, c);
|
||||
if(index < 0) {
|
||||
result = MB_INDEX_OUT_OF_BOUNDS;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
_get_array_elem(s, arr, index, &val->value, &type);
|
||||
val->type = _internal_type_to_public_type(type);
|
||||
|
||||
_exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
int mb_set_array_elem(struct mb_interpreter_t* s, void** l, void* a, int* d, int c, mb_value_t val) {
|
||||
/* Set an element of an array with a given index */
|
||||
int result = MB_FUNC_OK;
|
||||
_array_t* arr = 0;
|
||||
int index = 0;
|
||||
_data_e type = _DT_NIL;
|
||||
|
||||
mb_assert(s && l);
|
||||
arr = (_array_t*)a;
|
||||
if(c < 0 || c > arr->dimension_count) {
|
||||
result = MB_RANK_OUT_OF_BOUNDS;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
index = _get_array_pos(s, arr, d, c);
|
||||
if(index < 0) {
|
||||
result = MB_INDEX_OUT_OF_BOUNDS;
|
||||
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
type = _public_type_to_internal_type(val.type);
|
||||
_set_array_elem(s, 0, arr, (unsigned int)index, &val.value, &type);
|
||||
|
||||
_exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
int mb_dispose_value(struct mb_interpreter_t* s, mb_value_t val) {
|
||||
/* Dispose a value */
|
||||
int result = MB_FUNC_OK;
|
||||
|
@ -142,6 +142,9 @@ extern "C" {
|
||||
# define MB_LOOP_BREAK 5001
|
||||
# define MB_LOOP_CONTINUE 5002
|
||||
# define MB_SUB_RETURN 5101
|
||||
# define MB_NEED_COMPLEX_ARRAY 6001
|
||||
# define MB_RANK_OUT_OF_BOUNDS 6002
|
||||
# define MB_INDEX_OUT_OF_BOUNDS 6003
|
||||
# define MB_DEBUG_ID_NOT_FOUND 7001
|
||||
# define MB_EXTENDED_ABORT 9001
|
||||
#endif /* MB_CODES */
|
||||
@ -219,11 +222,12 @@ typedef enum mb_error_e {
|
||||
} mb_error_e;
|
||||
|
||||
typedef enum mb_data_e {
|
||||
MB_DT_NIL = -1,
|
||||
MB_DT_INT = 0,
|
||||
MB_DT_REAL,
|
||||
MB_DT_STRING,
|
||||
MB_DT_USERTYPE
|
||||
MB_DT_NIL = 0,
|
||||
MB_DT_INT = 1 << 1,
|
||||
MB_DT_REAL = 1 << 2,
|
||||
MB_DT_STRING = 1 << 3,
|
||||
MB_DT_USERTYPE = 1 << 4,
|
||||
MB_DT_ARRAY = 1 << 12
|
||||
} mb_data_e;
|
||||
|
||||
typedef union mb_value_u {
|
||||
@ -231,6 +235,7 @@ typedef union mb_value_u {
|
||||
real_t float_point;
|
||||
char* string;
|
||||
void* usertype;
|
||||
void* array;
|
||||
} mb_value_u;
|
||||
|
||||
typedef struct mb_value_t {
|
||||
@ -272,6 +277,10 @@ MBAPI int mb_push_real(struct mb_interpreter_t* s, void** l, real_t val);
|
||||
MBAPI int mb_push_string(struct mb_interpreter_t* s, void** l, char* val);
|
||||
MBAPI int mb_push_usertype(struct mb_interpreter_t* s, void** l, void* val);
|
||||
MBAPI int mb_push_value(struct mb_interpreter_t* s, void** l, mb_value_t val);
|
||||
MBAPI int mb_init_array(struct mb_interpreter_t* s, void** l, mb_data_e t, int* d, int c, void** a);
|
||||
MBAPI int mb_get_array_len(struct mb_interpreter_t* s, void** l, void* a, int r, int* i);
|
||||
MBAPI int mb_get_array_elem(struct mb_interpreter_t* s, void** l, void* a, int* d, int c, mb_value_t* val);
|
||||
MBAPI int mb_set_array_elem(struct mb_interpreter_t* s, void** l, void* a, int* d, int c, mb_value_t val);
|
||||
MBAPI int mb_dispose_value(struct mb_interpreter_t* s, mb_value_t val);
|
||||
|
||||
MBAPI int mb_load_string(struct mb_interpreter_t* s, const char* l);
|
||||
|
Binary file not shown.
Binary file not shown.
@ -36,8 +36,8 @@
|
||||
IDI_ICON_MAIN ICON "icon.ico"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,56,0
|
||||
PRODUCTVERSION 1,1,56,0
|
||||
FILEVERSION 1,1,57,0
|
||||
PRODUCTVERSION 1,1,57,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
# ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -55,13 +55,13 @@
|
||||
VALUE "Comments", "MY-BASIC"
|
||||
VALUE "CompanyName", "W. Renxin"
|
||||
VALUE "FileDescription", "MY-BASIC interpreter"
|
||||
VALUE "FileVersion", "1, 1, 56, 0"
|
||||
VALUE "FileVersion", "1, 1, 57, 0"
|
||||
VALUE "InternalName", "my_basic"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 W. Renxin"
|
||||
VALUE "LegalTrademarks", "MY-BASIC"
|
||||
VALUE "OriginalFilename", "my_basic.exe"
|
||||
VALUE "ProductName", "MY-BASIC"
|
||||
VALUE "ProductVersion", "1, 1, 56, 0"
|
||||
VALUE "ProductVersion", "1, 1, 57, 0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
Loading…
x
Reference in New Issue
Block a user