⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 smallbasic for linux
💻 C
字号:
/**	expressions (byte-code)**	Nicholas Christopoulos**	This program is distributed under the terms of the GPL v2.0 or later*	Download the GNU Public License (GPL) from www.gnu.org*/#include "sys.h"#include "str.h"#include "kw.h"#include "panic.h"#include "var.h"#include "blib.h"#include "device.h"#include "pproc.h"extern int prog_error;extern byte *prog_source;extern word prog_ip;extern word prog_line;extern var_t **tvar;extern lab_t *tlab;#define	IP					prog_ip#define	CODE(x)				prog_source[(x)]#define	CODE_PEEK()			CODE(IP)#define	CHECKOP1(s)			if (CODE(IP) == kwTYPE_OPR && CODE(IP+1) == (s)) { IP += 2; return (s); }#define	CHECKOP2(s,o)		if (CODE(IP) == kwTYPE_OPR && CODE(IP+1) == (s)[0] && CODE(IP+2) == kwTYPE_OPR && CODE(IP+3) == (s)[1]) { IP += 4; return (o); }#define	CHECKOP3(s,o)		if ( code_checkop_s((s)) ) { IP += 6; return (o); }#define V_FREE(v)			if ( (v) ) { if ( (v)->type == V_STR ) { if ((v)->ptr) tmp_free((v)->ptr); (v)->ptr=NULL; (v)->size=0; } }void	eval(var_t *result)				;void	eval_rte_syntax_error(void)	SEC(TRASH);void	eval_rte_syntax_error(void)		{ rt_raise("(EXPR): SYNTAX ERROR"); }void	eval_rte_out_of_range(void)	SEC(TRASH);void	eval_rte_out_of_range(void)		{ rt_raise("(EXPR): OUT OF RANGE"); }void	eval_rte_type_mismatch(void) SEC(TRASH);void	eval_rte_type_mismatch(void)	{ rt_raise("(EXPR): TYPE MISMATCH"); }void	eval_rte_missing_lp(void)	SEC(TRASH);void	eval_rte_missing_lp(void)		{ rt_raise("(EXPR): MISSING '('"); }void	eval_rte_missing_rp(void)	SEC(TRASH);void	eval_rte_missing_rp(void)		{ rt_raise("(EXPR): MISSING ')'"); }void	eval_rte_missing_sep(void)	SEC(TRASH);void	eval_rte_missing_sep(void)		{ rt_raise("(EXPR): MISSING SEPARATOR OR PARENTHESIS"); }void	eval_rte_division_by_zero(void)	SEC(TRASH);void	eval_rte_division_by_zero(void)	{ rt_raise("(EXPR): DIVISION BY ZERO"); }/**	Convertion multi-dim index to one-dim index*/word	getarrayidx(var_t *array){	byte	code;	var_t	var;	word	idx = 0, lev = 0, m = 0;	word	idim, i;	do	{		v_init(&var);		eval(&var);		if	( prog_error )	return 0;		idim = v_getint(&var);		v_free(&var);		if	( prog_error )				return 0;		idim = idim - array->lbound[lev];		m = idim;		for ( i = lev+1; i < array->maxdim; i ++ )				m = m * (ABS(array->ubound[i] - array->lbound[i]) + 1);		idx += m;		// skip separator		code = CODE_PEEK();		if	( code == kwTYPE_SEP )	{			IP ++;			if	( code_getnext() != ',' )				eval_rte_syntax_error();			}		// next		lev ++;		} while ( CODE_PEEK() != kwTYPE_LEVEL_END );	if	( !prog_error )		{		if	( array->maxdim != lev )				eval_rte_missing_sep();		}	return idx;}/**	main*/void	eval(var_t *r){	byte	code, op;	byte	level = 0;	word	len;	var_t	*var_p;	word	array_index;	var_t	*left = NULL, vtmp;	// stack	var_t	stk[24];		//	word	sp = 0;			// stack pointer	stknode_t	udf_rv;	r->type = V_INT;	r->i = 0L;	do	{		code = CODE(IP);	IP ++;				switch ( code )	{		case	kwTYPE_INT:			V_FREE(r);			r->type = V_INT;			r->i    = code_getnext32();	// 32-bit value			break;		case	kwTYPE_NUM:			V_FREE(r);			r->type = V_NUM;			r->n    = code_getnext64f(); // 64-bit floating-point value			break;		case	kwTYPE_STR:			V_FREE(r);			r->type = V_STR;			len = code_getnext16();	// 16-bit value (string length)			r->ptr = tmp_alloc(len+1);			memcpy(r->ptr, &prog_source[prog_ip], len);			*((char *) (r->ptr+len)) = '\0';			r->size = len;			IP += len;			break;		//////////////// variable ///////////////////		case	kwTYPE_VAR:			V_FREE(r);			var_p = tvar[code_getnext16()];			switch ( var_p->type )	{			case	V_INT:				r->type = V_INT;				r->i = var_p->i;				break;			case	V_NUM:				r->type = V_NUM;				r->n = var_p->n;				break;			case	V_STR:				v_set(r, var_p);				break;			case	V_ARRAY:				// copy element of array				if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )					eval_rte_missing_lp();				else	{					IP ++;		// '('					array_index = getarrayidx(var_p);					if	( !prog_error )	{						if	( array_index < var_p->size )	{							v_set(r, v_getelemptr(var_p, array_index));							if	( CODE_PEEK() == kwTYPE_SEP )									IP ++;		// ','							else if	( CODE_PEEK() == kwTYPE_LEVEL_END )									IP ++;		// ')'							else								eval_rte_missing_lp();							} // idx < v->size						else								eval_rte_out_of_range();						} // !prog_err					} // 				break; 				};	// switch(type)			break;		/////////////// STACK //////////////////		case	kwTYPE_EVPUSH:		// PUSH RESULT			switch ( r->type )	{			case	V_INT:				stk[sp].type = V_INT;				stk[sp].i = r->i;				break;			case	V_NUM:				stk[sp].type = V_NUM;				stk[sp].n = r->n;				break;			case	V_STR:				len = r->size;				stk[sp].type = V_STR;				stk[sp].ptr = tmp_alloc(len+1);				strcpy(stk[sp].ptr, r->ptr);				stk[sp].size = len;				break;				}			sp ++;			break;		case	kwTYPE_EVPOP:		// POP LEFT			sp --;			left = &stk[sp];			break;		//////////////// ADD ///////////////////		case kwTYPE_ADDOPR:			op = CODE(IP);	IP ++;			if ( r->type == V_INT && left->type == V_INT )	{				if	( op == '+' )					r->i += left->i;				else					r->i = left->i - r->i;				}			else if ( r->type == V_NUM && left->type == V_NUM )	{				r->type = V_NUM;				if	( op == '+' )					r->n += left->n;				else					r->n = left->n - r->n;				}			else if ( r->type == V_INT && left->type == V_NUM )	{				r->type = V_NUM;				if	( op == '+' )					r->n = r->i + left->n;				else					r->n = left->n - r->i;				}			else if ( r->type == V_NUM && left->type == V_INT )	{				if	( op == '+' )					r->n += left->i;				else					r->n = left->i - r->n;				}			else	{				v_init(&vtmp);				switch ( op )	{				case	'+':					v_add(&vtmp, left, r);					break;				case	'-':					if	( vtmp.type == V_NUM )	{						vtmp.type = V_NUM;						vtmp.n = v_getval(left) - v_getval(r);						}					else	{						vtmp.type = V_INT;						vtmp.i = v_igetval(left) - v_igetval(r);						}					break;					};								V_FREE(left);				v_set(r, &vtmp);				V_FREE(&vtmp);				}			break;		//////////////// MUL ///////////////////		case kwTYPE_MULOPR:			op = CODE(IP);	IP ++;			switch ( op )	{			case	'*':				r->n = v_getval(left) * v_getval(r);				break;			case	'/':				if	( v_getval(r) == 0 )					eval_rte_division_by_zero();				else						r->n = v_getval(left) / v_getval(r);				break;			case	'\\':				if	( v_igetval(r) == 0 )					eval_rte_division_by_zero();				else						r->i = v_igetval(left) / v_igetval(r);				break;			case	'%':				if	( v_igetval(r) == 0 )					eval_rte_division_by_zero();				else						r->i = v_igetval(left) % v_igetval(r);				break;				};			// cleanup			if	( r->type == V_STR )	{				if	( r->ptr )					tmp_free(r->ptr);				}			if	( op == '*' || op == '/' )				r->type = V_NUM;	// double always			else				r->type = V_INT;			V_FREE(left);			break;		//////////////// UNARY ///////////////////		case kwTYPE_UNROPR:			op = CODE(IP);	IP ++;			switch ( op )	{			case	'-':				if	( r->type == V_INT )						r->i = -r->i;				else if	( r->type == V_NUM )					r->n = -r->n;				else	{					r->n = -v_getval(r);					if	( r->ptr )						tmp_free(r->ptr);					r->type = V_NUM;					}				break;			case	'+':				break;			case	OPLOG_NOT:	// The result of ! is always integer				r->i = !v_igetval(r);				if	( r->type == V_STR )	{					if	( r->ptr )						tmp_free(r->ptr);					}				r->type = V_INT;				break;				}			// cleanup			break;		//////////////// LOGICAL ///////////////////		case kwTYPE_LOGOPR:			op = CODE(IP);	IP ++;			switch ( op )	{			case	OPLOG_AND:				r->i = v_igetval(left) && v_igetval(r);				break;			case	OPLOG_OR:				r->i = v_igetval(left) || v_igetval(r);				break;			case	OPLOG_XOR:				r->i = v_igetval(left) ^ v_igetval(r);				break;				};			// cleanup			V_FREE(left);			V_FREE(r);			//			r->type = V_INT;			break;		//////////////// COMPARE ///////////////////		case kwTYPE_CMPOPR:			op = CODE(IP);	IP ++;			switch ( op )	{			case	OPLOG_EQ:				r->i = (v_compare(left, r) == 0);				break;			case	OPLOG_GT:				r->i = (v_compare(left, r) > 0);				break;			case	OPLOG_GE:				r->i = (v_compare(left, r) >= 0);				break;			case	OPLOG_LT:				r->i = (v_compare(left, r) < 0);				break;			case	OPLOG_LE:				r->i = (v_compare(left, r) <= 0);				break;			case	OPLOG_NE:				r->i = (v_compare(left, r) != 0);				break;				}			// cleanup			V_FREE(left);			V_FREE(r);			//			r->type = V_INT;			break;		//////////////// POW ///////////////////		case kwTYPE_POWOPR:			op = CODE(IP);	IP ++;			r->n = pow(v_getval(left), v_getval(r));			V_FREE(r);			r->type = V_NUM;			// cleanup			V_FREE(left);			break;		/////////////////////////////////////////////////////////////////////////////////		case kwTYPE_LEVEL_BEGIN:			level ++;			break;		case kwTYPE_LEVEL_END:			if	( level == 0 )	{				IP --;				return;				}			level --;			break;		/////////////////////////////////////////////////////////////////////////////////		// num FUNC(STR)		case kwASC:		case kwLEN:		case kwVAL:		case kwTEXTWIDTH: case kwTEXTHEIGHT:		case kwEXIST:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				IP ++;				v_init(&vtmp);				eval(&vtmp);				if	( prog_error )	return;				cmd_ns1(code, &vtmp, r);				V_FREE(&vtmp);				if	( CODE_PEEK() != kwTYPE_LEVEL_END )					eval_rte_missing_rp();				else					IP ++;				}			break;		// str FUNC(any)		case kwCHR:		case kwSTR:		case kwOCT:		case kwHEX:		case kwLCASE:	case kwUCASE:		case kwLTRIM:	case kwRTRIM:		case kwSPACE:	case kwTAB:		case kwCAT:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				IP ++;				v_init(&vtmp);				eval(&vtmp);				if	( prog_error )	return;				r->type = V_STR;				cmd_str1(code, &vtmp, r);				V_FREE(&vtmp);				if	( CODE_PEEK() != kwTYPE_LEVEL_END )					eval_rte_missing_rp();				else					IP ++;				}			break;		// str FUNC(...)		case kwSTRING:		case kwLEFT:	case kwRIGHT:		case kwMID:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				r->type = V_STR;				IP ++;		// '('				cmd_strN(code, r);				if	( prog_error )	return;				if	( CODE_PEEK() == kwTYPE_SEP )						IP ++;		// ','				else if	( CODE_PEEK() == kwTYPE_LEVEL_END )						IP ++;		// ')'				else					eval_rte_missing_rp();				}			break;		// str FUNC(void)		case kwINKEY:		case kwTIME:		case kwDATE:			V_FREE(r);			cmd_str0(code, r);			break;		// int FUNC(...)		case kwINSTR:		case kwLBOUND:	case kwUBOUND:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				r->type = V_INT;				IP ++;		// '('				cmd_intN(code, r);				if	( prog_error )	return;				if	( CODE_PEEK() == kwTYPE_SEP )						IP ++;		// ','				else if	( CODE_PEEK() == kwTYPE_LEVEL_END )						IP ++;		// ')'				else					eval_rte_missing_sep();				}			break;		// fp FUNC(...)		case kwATAN2:	case kwPOW:		case kwROUND:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				r->type = V_NUM;				IP ++;		// '('				cmd_numN(code, r);				if	( prog_error )	return;				if	( CODE_PEEK() == kwTYPE_SEP )						IP ++;		// ','				else if	( CODE_PEEK() == kwTYPE_LEVEL_END )						IP ++;		// ')' level				else					eval_rte_missing_sep();				}			break;		// fp FUNC(fp)		case kwCOS:		case kwSIN: 	case kwTAN:		case kwCOSH:	case kwSINH: 	case kwTANH:		case kwACOS:	case kwASIN:	case kwATAN:		case kwACOSH:	case kwASINH:	case kwATANH:		case kwSQR:		case kwABS:		case kwEXP:		case kwLOG:		case kwLOG10:		case kwFIX:		case kwINT:		case kwCDBL:		case kwDEG:		case kwRAD:		case kwPEN:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				IP ++;				v_init(&vtmp);				eval(&vtmp);				if	( prog_error )	return;				r->type = V_NUM;				r->n = cmd_math1(code, &vtmp);				V_FREE(&vtmp);				if	( prog_error )	return;				if	( CODE_PEEK() != kwTYPE_LEVEL_END )					eval_rte_missing_rp();				else					IP ++;				}			break;		// int FUNC(fp)		case kwFRE:	case kwSGN:	case kwCINT:		case kwEOF:	case kwSEEK: case kwLOF:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				IP ++;				v_init(&vtmp);				eval(&vtmp);				if	( prog_error )	return;				r->type = V_INT;				r->i = cmd_imath1(code, &vtmp);//				v_free(&vtmp);				if	( CODE_PEEK() != kwTYPE_LEVEL_END )					eval_rte_missing_rp();				else					IP ++;				}			break;		// fp FUNC(void)		case kwRND:					V_FREE(r);			vtmp.type = V_NUM;			vtmp.n = 0;			r->type = V_NUM;			r->n = cmd_math1(code, &vtmp);			break;		case kwMAX:	case kwMIN:		case kwINPUTSEP:			V_FREE(r);			if	( CODE_PEEK() != kwTYPE_LEVEL_BEGIN )				eval_rte_missing_lp();			else	{				IP ++;				cmd_genfunc(code, r);				if	( prog_error )	return;				if	( CODE_PEEK() != kwTYPE_LEVEL_END )					eval_rte_missing_rp();				else					IP ++;				}			break;		// int FUNC(void)		case kwTICKS:	case kwTICKSPERSEC:	case kwTIMER:			V_FREE(r);			vtmp.type = V_INT;			vtmp.i = 0;			r->type = V_INT;			r->i = cmd_imath1(code, &vtmp);			break;		case kwFREEFILE:			V_FREE(r);			r->type = V_INT;			r->i = dev_freefilehandle();			break;		case kwTYPE_CALL_UDF:			prog_ip --;			bc_loop(1);						if	( !prog_error )	{				code_pop(&udf_rv);				if	( udf_rv.type != kwTYPE_RET )						err_stackmess();				else	{					v_set(r, udf_rv.x.vdvar.vptr);					v_free(udf_rv.x.vdvar.vptr);				// free ret-var					tmp_free(udf_rv.x.vdvar.vptr);					}				}			break;		//////////////////////////////////////		default:			IP --;			return;			};		// run-time error check		if	( prog_error )				return;				} while ( 1 );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -