📄 compiler.cpp
字号:
{
delete temporaries;
temporaries = save_temp;
}
return last_stat;
}
// do_return - handle the RETURN expression
void
compiler::do_return ()
{
if ( inConstructor )
{
compiler::PVAL pv;
findvariable ( "this", &pv );
rvalue ( &pv );
}
else
{
int tkn = scan.token ();
scan.stoken ( tkn );
if ( tkn == ';')
putcbyte ( OP_UNDEFINED );
else do_expr ();
}
frequire ( ';' );
putcbyte ( OP_RETURN );
}
// do_test - compile a test expression
void
compiler::do_test ()
{
frequire ( '(' );
do_expr ();
frequire ( ')' );
}
// do_expr - parse an expression
void
compiler::do_expr ()
{
compiler::PVAL pv;
do_expr1 ( &pv );
rvalue ( &pv );
}
// rvalue - get the rvalue of a partial expression
void
compiler::rvalue ( compiler::PVAL *pv )
{
if ( pv->fcn )
{
( *pv->fcn ) ( this, LOAD, pv->val );
pv->fcn = NULL;
}
}
// chklvalue - make sure we've got an lvalue
void
compiler::chklvalue ( compiler::PVAL *pv )
{
if ( !pv->fcn )
throw parse_error ( this, "Expecting an lvalue" );
}
// do_expr1 - handle the ',' operator
void
compiler::do_expr1 ( compiler::PVAL *pv )
{
int tkn;
do_expr2 ( pv );
while ( ( tkn = scan.token () ) == ',' )
{
rvalue ( pv );
do_expr1 ( pv );
rvalue ( pv );
}
scan.stoken ( tkn );
}
// do_vardecl - var declaration
void
compiler::do_vardecl ( void )
{
int tkn;
string id;
compiler::PVAL rhs;
for ( ; ; )
{
tkn = scan.token ();
if ( tkn != T_IDENTIFIER )
throw parse_error ( this, "Expecting an identifier" );
id = scan.t_token;
int temp_var_num = temporaries->add ( id );
if ( temp_var_num < 0 )
{
char msg [ 100 ];
sprintf ( msg, "Variable '%s' already defined", (const char *) id );
throw parse_error ( this, msg );
}
tkn = scan.token ();
if ( tkn == '=' )
{
code_temporary ( this, PUSH, 0 );
do_expr2 ( &rhs );
rvalue ( &rhs );
code_temporary ( this, STORE, temp_var_num );
tkn = scan.token ();
}
else
{
putcbyte ( OP_UNDEFINED );
code_temporary ( this, STORE, temp_var_num );
}
if ( tkn == ',' )
continue;
else if ( tkn == ';' )
{
scan.stoken ( tkn );
break;
}
else
throw parse_error ( this, "Expecting ',' | ';'" );
}
}
// do_expr2 - handle the assignment operators
void
compiler::do_expr2 ( compiler::PVAL *pv )
{
int tkn;
compiler::PVAL rhs;
do_expr3 ( pv );
while ( (tkn = scan.token () ) == '=' ||
tkn == T_ADDEQ || tkn == T_SUBEQ ||
tkn == T_MULEQ || tkn == T_DIVEQ ||
tkn == T_REMEQ || tkn == T_ANDEQ ||
tkn == T_OREQ || tkn == T_XOREQ ||
tkn == T_SHLEQ || tkn == T_SHLEQ )
{
chklvalue ( pv );
switch ( tkn )
{
case '=':
( *pv->fcn ) ( this, PUSH, 0 );
do_expr1 ( &rhs );
rvalue ( &rhs );
( *pv->fcn ) ( this, STORE, pv->val );
break;
case T_ADDEQ: do_assignment ( pv, OP_ADD ); break;
case T_SUBEQ: do_assignment ( pv, OP_SUB ); break;
case T_MULEQ: do_assignment ( pv, OP_MUL ); break;
case T_DIVEQ: do_assignment ( pv, OP_DIV ); break;
case T_REMEQ: do_assignment ( pv, OP_REM ); break;
case T_ANDEQ: do_assignment ( pv, OP_BAND ); break;
case T_OREQ: do_assignment ( pv, OP_BOR ); break;
case T_XOREQ: do_assignment ( pv, OP_XOR ); break;
case T_SHLEQ: do_assignment ( pv, OP_SHL ); break;
case T_SHREQ: do_assignment ( pv, OP_SHR ); break;
}
pv->fcn = NULL;
}
scan.stoken ( tkn );
}
// do_assignment - handle assignment operations
void
compiler::do_assignment ( compiler::PVAL *pv, int op )
{
compiler::PVAL rhs;
( *pv->fcn ) ( this, DUP, 0 );
( *pv->fcn ) ( this, LOAD, pv->val );
putcbyte ( OP_PUSH );
do_expr1 ( &rhs );
rvalue ( &rhs );
putcbyte ( op );
( *pv->fcn ) ( this, STORE, pv->val );
}
// do_expr3 - handle the '?:' operator
void
compiler::do_expr3 ( compiler::PVAL *pv )
{
int tkn, nxt, end;
do_expr4 ( pv );
while ( (tkn = scan.token () ) == '?' )
{
rvalue ( pv );
putcbyte ( OP_BRF );
nxt = putcword ( 0 );
do_expr1 ( pv );
rvalue ( pv );
frequire ( ':' );
putcbyte ( OP_BR );
end = putcword ( 0 );
fixup ( nxt, cptr );
do_expr1 ( pv );
rvalue ( pv );
fixup ( end, cptr );
}
scan.stoken ( tkn );
}
// do_expr4 - handle the '||' operator
void
compiler::do_expr4 ( compiler::PVAL *pv )
{
int tkn, end = 0;
do_expr5 ( pv );
while ( ( tkn = scan.token () ) == T_OR )
{
rvalue ( pv );
putcbyte ( OP_BRT );
end = putcword ( end );
do_expr5 ( pv );
rvalue ( pv );
}
fixup ( end, cptr );
scan.stoken ( tkn );
}
// do_expr5 - handle the '&&' operator
void
compiler::do_expr5 ( compiler::PVAL *pv )
{
int tkn, end = 0;
do_expr6 ( pv );
while ( ( tkn = scan.token () ) == T_AND )
{
rvalue ( pv );
putcbyte ( OP_BRF );
end = putcword ( end );
do_expr6 ( pv );
rvalue ( pv );
}
fixup ( end, cptr );
scan.stoken ( tkn );
}
// do_expr6 - handle the '|' operator
void
compiler::do_expr6 ( compiler::PVAL *pv )
{
int tkn;
do_expr7 ( pv );
while ( ( tkn = scan.token () ) == '|' )
{
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr7 ( pv );
rvalue ( pv );
putcbyte ( OP_BOR );
}
scan.stoken ( tkn );
}
// do_expr7 - handle the '^' operator
void
compiler::do_expr7 ( compiler::PVAL *pv )
{
int tkn;
do_expr8 ( pv );
while ( ( tkn = scan.token () ) == '^' )
{
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr8 ( pv );
rvalue ( pv );
putcbyte ( OP_XOR );
}
scan.stoken ( tkn );
}
// do_expr8 - handle the '&' operator
void
compiler::do_expr8 ( compiler::PVAL *pv )
{
int tkn;
do_expr9 ( pv );
while ( ( tkn = scan.token () ) == '&' )
{
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr9 ( pv );
rvalue ( pv );
putcbyte ( OP_BAND );
}
scan.stoken ( tkn );
}
// do_expr9 - handle the '==' and '!=' operators
void
compiler::do_expr9 ( compiler::PVAL *pv )
{
int tkn, op;
do_expr10 ( pv );
while ( ( tkn = scan.token () ) == T_EQ || tkn == T_NE )
{
switch ( tkn )
{
case T_EQ: op = OP_EQ; break;
case T_NE: op = OP_NE; break;
}
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr10 ( pv );
rvalue ( pv );
putcbyte ( op );
}
scan.stoken ( tkn );
}
// do_expr10 - handle the '<', '<=', '>=' and '>' operators
void
compiler::do_expr10 ( compiler::PVAL *pv )
{
int tkn, op;
do_expr11 ( pv );
while ( ( tkn = scan.token () ) == '<' ||
tkn == T_LE || tkn == T_GE || tkn == '>' )
{
switch ( tkn )
{
case '<': op = OP_LT; break;
case T_LE: op = OP_LE; break;
case T_GE: op = OP_GE; break;
case '>': op = OP_GT; break;
}
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr11 ( pv );
rvalue ( pv );
putcbyte ( op );
}
scan.stoken ( tkn );
}
// do_expr11 - handle the '<<' and '>>' operators
void
compiler::do_expr11 ( compiler::PVAL *pv )
{
int tkn, op;
do_expr12 ( pv );
while ( ( tkn = scan.token () ) == T_SHL || tkn == T_SHR )
{
switch ( tkn )
{
case T_SHL: op = OP_SHL; break;
case T_SHR: op = OP_SHR; break;
}
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr12 ( pv );
rvalue ( pv );
putcbyte ( op );
}
scan.stoken ( tkn );
}
// do_expr12 - handle the '+' and '-' operators
void
compiler::do_expr12 ( compiler::PVAL *pv )
{
int tkn, op;
do_expr13 ( pv );
while ( ( tkn = scan.token () ) == '+' || tkn == '-' )
{
switch ( tkn )
{
case '+': op = OP_ADD; break;
case '-': op = OP_SUB; break;
}
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr13 ( pv );
rvalue ( pv );
putcbyte ( op );
}
scan.stoken ( tkn );
}
// do_expr13 - handle the '*' and '/' operators
void
compiler::do_expr13 ( compiler::PVAL *pv )
{
int tkn, op;
do_expr14 ( pv );
while ( ( tkn = scan.token () ) == '*' || tkn == '/' ||
tkn == '%' || tkn == T_MAKEREF || tkn == T_INSTANCEOF )
{
switch ( tkn )
{
case '*': op = OP_MUL; break;
case '/': op = OP_DIV; break;
case '%': op = OP_REM; break;
case T_MAKEREF: op = OP_MAKEREF; break;
case T_INSTANCEOF: op = OP_INSTANCEOF; break;
}
rvalue ( pv );
putcbyte ( OP_PUSH );
do_expr14 ( pv );
rvalue ( pv );
putcbyte ( op );
}
scan.stoken ( tkn );
}
// do_expr14 - handle unary operators
void
compiler::do_expr14 ( compiler::PVAL *pv )
{
int tkn;
switch ( tkn = scan.token () )
{
case '-':
do_expr15 ( pv );
rvalue ( pv );
putcbyte ( OP_NEG );
break;
case '!':
do_expr15 ( pv );
rvalue ( pv );
putcbyte ( OP_NOT );
break;
case '~':
do_expr15 ( pv );
rvalue ( pv );
putcbyte ( OP_BNOT );
break;
case T_INC:
do_preincrement ( pv, OP_INC );
break;
case T_DEC:
do_preincrement ( pv, OP_DEC );
break;
case T_NEW:
do_new ( pv );
break;
default:
scan.stoken ( tkn );
do_expr15 ( pv );
return;
}
}
void
compiler::do_lit_array ( compiler::PVAL *pv )
{
compiler::PVAL pc;
CLASS *klass = get_class ( "array", VM::std );
findclassvariable ( klass, "[", &pc );
rvalue ( &pc );
// put <undefined> as this
putcbyte ( OP_PUSH );
int tkn, n = 1;
// compile each argument expression
if ( ( tkn = scan.token () ) != ']' )
{
scan.stoken ( tkn );
do
{
putcbyte ( OP_PUSH );
compiler::PVAL ai;
do_expr2 ( &ai );
rvalue ( &ai );
++n;
if ( n >= 10000 ) throw parse_error ( this, "Too many literal items" );
}
while ( ( tkn = scan.token () ) == ',' );
}
require ( tkn, ']' );
putcbyte ( OP_CALL );
putcword ( n );
// we've got an rvalue now
pv->fcn = NULL;
}
void
compiler::do_lit_map ( compiler::PVAL *pv )
{
compiler::PVAL pc;
CLASS *klass = get_class ( "map", VM::std );
findclassvariable ( klass, "{", &pc );
rvalue ( &pc );
// put <undefined> as this
putcbyte ( OP_PUSH );
int tkn, n = 1;
// compile each argument expression
if ( ( tkn = scan.token () ) != '}' )
{
scan.stoken ( tkn );
do
{
compiler::PVAL l, r;
putcbyte ( OP_PUSH );
do_expr2 ( &l );
rvalue ( &l );
tkn = scan.token ();
require ( tkn, ':' );
putcbyte ( OP_PUSH );
do_expr2 ( &r );
rvalue ( &r );
n += 2;
if ( n >= 10000 )
throw parse_error ( this, "Too many literal items" );
}
while ( ( tkn = scan.token () ) == ',' );
}
require ( tkn, '}' );
putcbyte ( OP_CALL );
putcword ( n );
// we've got an rvalue now
pv->fcn = NULL;
}
// do_preincrement - handle prefix '++' and '--'
void
compiler::do_preincrement ( compiler::PVAL *pv, int op )
{
do_expr15 ( pv );
chklvalue ( pv );
( *pv->fcn ) ( this, DUP, 0 );
( *pv->fcn ) ( this, LOAD, pv->val );
putcbyte ( op );
( *pv->fcn ) ( this, STORE, pv->val );
pv->fcn = NULL;
}
// do_postincrement - handle postfix '++' and '--'
void
compiler::do_postincrement ( compiler::PVAL *pv, int op )
{
chklvalue ( pv );
( *pv->fcn ) ( this, DUP, 0 );
( *pv->fcn ) ( this, LOAD, pv->val );
putcbyte ( OP_TSTORE );
putcbyte ( op );
( *pv->fcn ) ( this, STORE, pv->val );
putcbyte ( OP_TRESTORE );
pv->fcn = NULL;
}
// do_new - handle the 'new' operator
void
compiler::do_new ( compiler::PVAL *pv )
{
string package_name, class_name;
int tkn;
CLASS * klass = 0;
frequire ( T_IDENTIFIER );
class_name = scan.t_token;
if ( ( tkn = scan.token () ) == T_CC )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -