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

📄 runnerline.cpp

📁 由一个古老的BASIC解释器改进而成, 保留了ANSI C固有的艺术美感.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	switch (f.getdeftype () )
	{
	case Function::DefSingle:
		{
			CodeLine & code= f.getcode ();
			code.gotochunk (0);
			RunnerLine fnrunline (runner, code, program);
			// Prevents lock on recursive calls.
			if (fInterrupted)
			{
				if (runner.getbreakstate () !=
						Runner::BreakCont)
					throw BlBreak ();
				else
					fInterrupted= false;
			}
			fnrunline.expect (result);
			ll.freelocals ();
		}
		break;
	case Function::DefMulti:
		{
			ll.addlocal (fname);
			Runner fnrun (program);
			// We reuse the break position
			// to jump to the fn definition.
			fnrun.set_break (f.getpos () );
			fnrun.gosub_push (ll);
			CodeLine jumpline;
			jumpline.scan ("CONT");
			fnrun.runline (jumpline);
			switch (typeofvar (fname) )
			{
			case VarNumber:
				result= evaluatevarnumber (fname);
				break;
			case VarInteger:
				result= evaluatevarinteger (fname);
				break;
			case VarString:
				result= evaluatevarstring (fname);
				break;
			default:
				throw ErrBlassicInternal;
			}
			ProgramPos notused;
			fnrun.gosub_pop (notused);
		}
		break;
	}
}

void RunnerLine::valsubindex (const std::string & varname, BlResult & result)
{
        Dimension dims= expectdims ();
        switch (typeofvar (varname) )
        {
        case VarNumber:
                result= valuedimnumber (varname, dims);
                break;
        case VarInteger:
                result= valuediminteger (varname, dims);
                break;
        case VarString:
                result= valuedimstring (varname, dims);
                break;
        default:
                throw ErrBlassicInternal;
        }
}

void RunnerLine::valbase (BlResult & result)
{
	switch (token.code)
	{
	case keyIDENTIFIER:
		{
			std::string varname (token.str);
			gettoken ();
			if (token.code == '(')
				valsubindex (varname, result);
			else
				switch (typeofvar (varname) )
				{
				case VarNumber:
					result= evaluatevarnumber (varname);
					break;
				case VarInteger:
					result= evaluatevarinteger (varname);
					break;
				case VarString:
					result= evaluatevarstring (varname);
					break;
				default:
					throw ErrBlassicInternal;
				}
		}
		break;
	case keySTRING:
		result= token.str;
		gettoken ();
		break;
	case keyNUMBER:
		result= token.number ();
		gettoken ();
		break;
        case keyINTEGER:
                result= token.integer ();
                gettoken ();
                break;
	case keyMID_S:
		valmid_s (result);
		break;
	case keyLEFT_S:
		valleft_s (result);
		break;
	case keyRIGHT_S:
		valright_s (result);
		break;
	case keyCHR_S:
		valchr_s (result);
		break;
	case keyENVIRON_S:
		valenviron_s (result);
		break;
	case keySTRING_S:
		valstring_s (result);
		break;
	case keyOSFAMILY_S:
		valosfamily_s (result);
		break;
	case keyHEX_S:
		valhex_s (result);
		break;
        case keySPACE_S:
                valspace_s (result);
                break;
        case keyUPPER_S:
                valupper_s (result);
                break;
        case keyLOWER_S:
                vallower_s (result);
                break;
        case keySTR_S:
                valstr_s (result);
                break;
        case keyOCT_S:
                valoct_s (result);
                break;
        case keyBIN_S:
                valbin_s (result);
                break;
        case keyINKEY_S:
                valinkey_s (result);
                break;
	case keyPROGRAMARG_S:
		valprogramarg_s (result);
		break;
	case keyDATE_S:
		valdate_s (result);
		break;
	case keyTIME_S:
		valtime_s (result);
		break;
	case keyINPUT_S:
		valinput_s (result);
		break;
        case keyMKI_S:
                valmki_s (result);
                break;
	case keyMKS_S:
		valmks_s (result);
		break;
	case keyMKD_S:
		valmkd_s (result);
		break;
        case keyMKL_S:
                valmkl_s (result);
                break;
	case keyOSNAME_S:
		valosname_s (result);
		break;
	case keyTRIM_S:
	case keyLTRIM_S:
	case keyRTRIM_S:
		valtrim (result);
		break;
	case keyASC:
		valasc (result);
		break;
	case keyLEN:
		vallen (result);
		break;
	case keyPEEK:
		valpeek (result);
		break;
	case keyPROGRAMPTR:
		valprogramptr (result);
		break;
	case keySYSVARPTR:
		gettoken ();
		result= sysvar::address ();
		break;
	case keyRND:
		valrnd (result);
		break;
	case keyINT:
		valnumericfunc (std::floor, result);
		break;
	case keySIN:
		valnumericfunc (std::sin, result);
		break;
	case keyCOS:
		valnumericfunc (std::cos, result);
		break;
	case keyPI:
		result= M_PI;
		gettoken ();
		break;
	case keyTAN:
		valnumericfunc (std::tan, result);
		break;
	case keySQR:
		valnumericfunc (std::sqrt, result);
		break;
	case keyASIN:
		valnumericfunc (std::asin, result);
		break;
	case keyACOS:
		valnumericfunc (std::acos, result);
		break;
	case keyINSTR:
		valinstr (result);
		break;
	case keyATAN:
		valnumericfunc (std::atan, result);
		break;
	case keyABS:
		valnumericfunc (std::fabs, result);
		break;
	case keyUSR:
		valusr (result);
		break;
        case keyVAL:
                valval (result);
                break;
	case keyEOF:
		valeof (result);
		break;
	case keyVARPTR:
		valvarptr (result);
		break;
	case keySGN:
		valsgn (result);
		break;
	case keyLOG:
		valnumericfunc (std::log, result);
		break;
	case keyLOG10:
		valnumericfunc (std::log10, result);
		break;
	case keyEXP:
		valnumericfunc (std::exp, result);
		break;
	case keyTIME:
		result= BlInteger (time (NULL) );
		gettoken ();
		break;
        case keyERR:
		result= runner.geterr ();
                gettoken ();
                break;
        case keyERL:
		result= BlNumber (runner.geterrline () );
                gettoken ();
                break;
        case keyCVI:
                valcvi (result);
                break;
	case keyCVS:
		valcvs (result);
		break;
	case keyCVD:
		valcvd (result);
		break;
        case keyCVL:
                valcvl (result);
                break;
        case keyMIN:
                valmin (result);
                break;
        case keyMAX:
                valmax (result);
                break;
	case keyCINT:
                #ifdef __WIN32__
                valnumericfunc (auxCINT, result);
                #else
		valnumericfunc (rint, result);
                #endif
		break;
	case keyFIX:
		valnumericfunc (auxFIX, result);
		break;
	case keyXMOUSE:
		result= graphics::xmouse ();
		gettoken ();
		break;
	case keyYMOUSE:
		result= graphics::ymouse ();
		gettoken ();
		break;
	case keyXPOS:
		result= graphics::xpos ();
		gettoken ();
		break;
	case keyYPOS:
		result= graphics::ypos ();
		gettoken ();
		break;
	case keyPEEK16:
		valpeek16 (result);
		break;
	case keyPEEK32:
		valpeek32 (result);
		break;
        case keyFN:
                valfn (result);
                break;
	default:
		throw ErrSyntax;
	}
}

void RunnerLine::valparen (BlResult & result)
{
	if (token.code == '(')
	{
		gettoken ();
		eval (result);
		if (token.code != ')')
			throw ErrSyntax;
		gettoken ();
	}
	else
		valbase (result);
}

void RunnerLine::valexponent (BlResult & result)
{
	valparen (result);
	while (token.code == '^')
	{
		gettoken ();
		BlResult guard;
		valparen (guard);
		result= std::pow (result.number (), guard.number () );
	}
}

void RunnerLine::valmod (BlResult & result)
{
	valexponent (result);
	while (token.code == keyMOD)
	{
		gettoken ();
		BlResult guard;
		valexponent (guard);
		#if 0
		if (! guard.number () )
			throw ErrDivZero;
		result= BlNumber ( (long) result.number ()  % (long) guard.number () );
		#else
		result%= guard;
		#endif
	}
}

void RunnerLine::valunary (BlResult & result)
{
	BlCode op= 0;
	if (token.code == '+' || token.code == '-' || token.code == keyNOT)
	{
		op= token.code;
		gettoken ();
		valunary (result);
	}
	else valmod (result);

	switch (op)
	{
	case 0:
		break;
	case '+':
		if (! result.is_numeric () )
			throw ErrMismatch;
		break;
	case '-':
		result= -result;
		break;
	case keyNOT:
		//result= BlNumber (~ long (result.number () ) );
                result= ~ result.integer ();
		break;
	default:
		throw ErrBlassicInternal;
	}
}

void RunnerLine::valmuldiv (BlResult & result)
{
	valunary (result);
	BlCode op= token.code;
	while (op == '*' || op == '/')
	{
		BlResult guard;
		gettoken ();
		valunary (guard);
		switch (op)
		{
		case '*':
			result*= guard;
			break;
		case '/':
			result/= guard;
			break;
		default:
			;
		}
		op= token.code;
	}
}

void RunnerLine::valplusmin (BlResult & result)
{
	valmuldiv (result);
	BlCode op= token.code;
	while (op == '+' || op == '-')
	{
		BlResult guard;
		gettoken ();
		valmuldiv (guard);
		switch (op)
		{
		case '+':
			result+= guard;
			break;
		case '-':
			result-= guard;
			break;
		}
		op= token.code;
	}
}

void RunnerLine::valcomp (BlResult & result)
{
	valplusmin (result);
	BlCode op= token.code;
	while (iscomp (op) )
	{
		BlResult guard;
		bool r;
		gettoken ();
		valplusmin (guard);
		switch (op)
		{
		case '=':
			r= (result == guard);
			break;
		case keyDISTINCT:
			r= (result != guard);
			break;
		case '<':
			r= (result < guard);
			break;
		case keyMINOREQUAL:
			r= (result <= guard);
			break;
		case '>':
			r= (result > guard);
			break;
		case keyGREATEREQUAL:
			r= (result >= guard);
			break;
		default:
			throw ErrBlassicInternal;
		}
		result= r ? -1 : 0;
		op= token.code;
	}
}

void RunnerLine::valorand (BlResult & result)
{
	valcomp (result);
	BlCode op= token.code;
	while (op == keyOR || op == keyAND || op == keyXOR)
	{
		BlResult guard;
		gettoken ();
		valcomp (guard);
		long n1= long (result.number () );
		long n2= long (guard.number () );
		switch (op)
		{
		case keyOR:
			result= BlNumber (n1 | n2);
			break;
		case keyAND:
			result= BlNumber (n1 & n2);
			break;
		case keyXOR:
			result= BlNumber (n1 ^ n2);
			break;
		default:
			throw ErrBlassicInternal;
		}
		op= token.code;
	}
}

void RunnerLine::eval (BlResult & result)
{
	valorand (result);
}

void RunnerLine::expect (BlResult & result)
{
	gettoken ();
	eval (result);
}

BlLineNumber RunnerLine::evallinenumber ()
{
	BlLineNumber bln;
	switch (token.code)
	{
	case keyNUMBER:
		bln= BlLineNumber (token.number () );
		break;
        case keyINTEGER:
                bln= BlLineNumber (token.integer () );
                break;
	case keyIDENTIFIER:
		bln= program.getlabel (token.str);
		if (bln == 0)
			throw ErrNoLabel;
		break;
	default:
		throw ErrSyntax;
	}
	gettoken ();
	return bln;
}

void RunnerLine::evallinerange (BlLineNumber & blnBeg, BlLineNumber & blnEnd)
{
	blnBeg= 0;
	blnEnd= BlMaxLineNumber;
	if (! endsentence () && token.code != ',')
	{
		if (token.code != '-')
		{
			blnBeg= evallinenumber ();
			if (token.code == '-')
			{
				gettoken ();
				if (! endsentence () && token.code != ',')
					blnEnd= evallinenumber ();
			}
			else
				blnEnd= blnBeg;
		}
		else
		{
			gettoken ();
			blnEnd= evallinenumber ();
		}
	}
}

Dimension RunnerLine::expectdims ()
{
	Dimension dims;
	requiretoken ('(');
	for (;;)
	{
		#if 0

⌨️ 快捷键说明

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