📄 runnerline.cpp
字号:
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 + -