628 lines
17 KiB
C++
628 lines
17 KiB
C++
|
|
|
||
|
|
#include "std.h"
|
||
|
|
#include "nodes.h"
|
||
|
|
|
||
|
|
#include <math.h>
|
||
|
|
#include <float.h>
|
||
|
|
|
||
|
|
//////////////////////////////////
|
||
|
|
// Cast an expression to a type //
|
||
|
|
//////////////////////////////////
|
||
|
|
ExprNode *ExprNode::castTo( Type *ty,Environ *e ){
|
||
|
|
if( !sem_type->canCastTo( ty ) ){
|
||
|
|
ex( "Illegal type conversion" );
|
||
|
|
}
|
||
|
|
|
||
|
|
ExprNode *cast=d_new CastNode( this,ty );
|
||
|
|
return cast->semant( e );
|
||
|
|
}
|
||
|
|
|
||
|
|
ExprNode *CastNode::semant( Environ *e ){
|
||
|
|
if( !expr->sem_type ){
|
||
|
|
expr=expr->semant( e );
|
||
|
|
}
|
||
|
|
|
||
|
|
if( ConstNode *c=expr->constNode() ){
|
||
|
|
ExprNode *e;
|
||
|
|
if( type==Type::int_type ) e=d_new IntConstNode( c->intValue() );
|
||
|
|
else if( type==Type::float_type ) e=d_new FloatConstNode( c->floatValue() );
|
||
|
|
else e=d_new StringConstNode( c->stringValue() );
|
||
|
|
delete this;
|
||
|
|
return e;
|
||
|
|
}
|
||
|
|
|
||
|
|
sem_type=type;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////
|
||
|
|
// Cast an expression to a type //
|
||
|
|
//////////////////////////////////
|
||
|
|
TNode *CastNode::translate( Codegen *g ){
|
||
|
|
TNode *t=expr->translate( g );
|
||
|
|
if( expr->sem_type==Type::float_type && sem_type==Type::int_type ){
|
||
|
|
//float->int
|
||
|
|
return d_new TNode( IR_CAST,t,0 );
|
||
|
|
}
|
||
|
|
if( expr->sem_type==Type::int_type && sem_type==Type::float_type ){
|
||
|
|
//int->float
|
||
|
|
return d_new TNode( IR_FCAST,t,0 );
|
||
|
|
}
|
||
|
|
if( expr->sem_type==Type::string_type && sem_type==Type::int_type ){
|
||
|
|
//str->int
|
||
|
|
return call( "__bbStrToInt",t );
|
||
|
|
}
|
||
|
|
if( expr->sem_type==Type::int_type && sem_type==Type::string_type ){
|
||
|
|
//int->str
|
||
|
|
return call( "__bbStrFromInt",t );
|
||
|
|
}
|
||
|
|
if( expr->sem_type==Type::string_type && sem_type==Type::float_type ){
|
||
|
|
//str->float
|
||
|
|
return fcall( "__bbStrToFloat",t );
|
||
|
|
}
|
||
|
|
if( expr->sem_type==Type::float_type && sem_type==Type::string_type ){
|
||
|
|
//float->str
|
||
|
|
return call( "__bbStrFromFloat",t );
|
||
|
|
}
|
||
|
|
if( expr->sem_type->structType() && sem_type==Type::string_type ){
|
||
|
|
//obj->str
|
||
|
|
return call( "__bbObjToStr",t );
|
||
|
|
}
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////////////
|
||
|
|
// Sequence of Expressions //
|
||
|
|
/////////////////////////////
|
||
|
|
void ExprSeqNode::semant( Environ *e ){
|
||
|
|
for( int k=0;k<exprs.size();++k ){
|
||
|
|
if( exprs[k] ) exprs[k]=exprs[k]->semant( e );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *ExprSeqNode::translate( Codegen *g,bool cfunc ){
|
||
|
|
TNode *t=0,*l=0;
|
||
|
|
for( int k=0;k<exprs.size();++k ){
|
||
|
|
|
||
|
|
TNode *q=exprs[k]->translate(g);
|
||
|
|
|
||
|
|
if( cfunc ){
|
||
|
|
Type *ty=exprs[k]->sem_type;
|
||
|
|
if( ty->stringType() ){
|
||
|
|
q=call( "__bbStrToCStr",q );
|
||
|
|
}else if( ty->structType() ){
|
||
|
|
q=d_new TNode( IR_MEM,q );
|
||
|
|
}else if( ty==Type::void_type ){
|
||
|
|
q=d_new TNode( IR_MEM,add(q,iconst(4)) );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *p;
|
||
|
|
p=d_new TNode( IR_ARG,0,0,k*4 );
|
||
|
|
p=d_new TNode( IR_MEM,p,0 );
|
||
|
|
p=d_new TNode( IR_MOVE,q,p );
|
||
|
|
p=d_new TNode( IR_SEQ,p,0 );
|
||
|
|
if( l ) l->r=p;
|
||
|
|
else t=p;
|
||
|
|
l=p;
|
||
|
|
}
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExprSeqNode::castTo( DeclSeq *decls,Environ *e,bool cfunc ){
|
||
|
|
if( exprs.size()>decls->size() ) ex( "Too many parameters" );
|
||
|
|
for( int k=0;k<decls->size();++k ){
|
||
|
|
Decl *d=decls->decls[k];
|
||
|
|
if( k<exprs.size() && exprs[k] ){
|
||
|
|
|
||
|
|
if( cfunc && d->type->structType() ){
|
||
|
|
if( exprs[k]->sem_type->structType() ){
|
||
|
|
}else if( exprs[k]->sem_type->intType() ){
|
||
|
|
exprs[k]->sem_type=Type::void_type;
|
||
|
|
}else{
|
||
|
|
ex( "Illegal type conversion" );
|
||
|
|
}
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
exprs[k]=exprs[k]->castTo( d->type,e );
|
||
|
|
|
||
|
|
}else{
|
||
|
|
if( !d->defType ) ex( "Not enough parameters" );
|
||
|
|
ExprNode *expr=constValue( d->defType );
|
||
|
|
if( k<exprs.size() ) exprs[k]=expr;
|
||
|
|
else exprs.push_back( expr );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void ExprSeqNode::castTo( Type *t,Environ *e ){
|
||
|
|
for( int k=0;k<exprs.size();++k ){
|
||
|
|
exprs[k]=exprs[k]->castTo( t,e );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
///////////////////
|
||
|
|
// Function call //
|
||
|
|
///////////////////
|
||
|
|
ExprNode *CallNode::semant( Environ *e ){
|
||
|
|
Type *t=e->findType( tag );
|
||
|
|
sem_decl=e->findFunc( ident );
|
||
|
|
if( !sem_decl || !(sem_decl->kind & DECL_FUNC) ) ex( "Function '"+ident+"' not found" );
|
||
|
|
FuncType *f=sem_decl->type->funcType();
|
||
|
|
if( t && f->returnType!=t ) ex( "incorrect function return type" );
|
||
|
|
exprs->semant( e );
|
||
|
|
exprs->castTo( f->params,e,f->cfunc );
|
||
|
|
sem_type=f->returnType;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *CallNode::translate( Codegen *g ){
|
||
|
|
|
||
|
|
FuncType *f=sem_decl->type->funcType();
|
||
|
|
|
||
|
|
TNode *t;
|
||
|
|
TNode *l=global( "_f"+ident );
|
||
|
|
TNode *r=exprs->translate( g,f->cfunc );
|
||
|
|
|
||
|
|
if( f->userlib ){
|
||
|
|
l=d_new TNode( IR_MEM,l );
|
||
|
|
usedfuncs.insert( ident );
|
||
|
|
}
|
||
|
|
|
||
|
|
if( sem_type==Type::float_type ){
|
||
|
|
t=d_new TNode( IR_FCALL,l,r,exprs->size()*4 );
|
||
|
|
}else{
|
||
|
|
t=d_new TNode( IR_CALL,l,r,exprs->size()*4 );
|
||
|
|
}
|
||
|
|
|
||
|
|
if( f->returnType->stringType() ){
|
||
|
|
if( f->cfunc ){
|
||
|
|
t=call( "__bbCStrToStr",t );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////////
|
||
|
|
// Variable expression //
|
||
|
|
/////////////////////////
|
||
|
|
ExprNode *VarExprNode::semant( Environ *e ){
|
||
|
|
var->semant( e );
|
||
|
|
sem_type=var->sem_type;
|
||
|
|
ConstType *c=sem_type->constType();
|
||
|
|
if( !c ) return this;
|
||
|
|
ExprNode *expr=constValue( c );
|
||
|
|
delete this;return expr;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *VarExprNode::translate( Codegen *g ){
|
||
|
|
return var->load( g );
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////
|
||
|
|
// Integer constant //
|
||
|
|
//////////////////////
|
||
|
|
IntConstNode::IntConstNode( int n ):value(n){
|
||
|
|
sem_type=Type::int_type;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *IntConstNode::translate( Codegen *g ){
|
||
|
|
return d_new TNode( IR_CONST,0,0,value );
|
||
|
|
}
|
||
|
|
|
||
|
|
int IntConstNode::intValue(){
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
float IntConstNode::floatValue(){
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
string IntConstNode::stringValue(){
|
||
|
|
return itoa( value );
|
||
|
|
}
|
||
|
|
|
||
|
|
////////////////////
|
||
|
|
// Float constant //
|
||
|
|
////////////////////
|
||
|
|
FloatConstNode::FloatConstNode( float f ):value(f){
|
||
|
|
sem_type=Type::float_type;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *FloatConstNode::translate( Codegen *g ){
|
||
|
|
return d_new TNode( IR_CONST,0,0,*(int*)&value );
|
||
|
|
}
|
||
|
|
|
||
|
|
int FloatConstNode::intValue(){
|
||
|
|
float flt=value;
|
||
|
|
int temp;
|
||
|
|
_control87( _RC_NEAR|_PC_24|_EM_INVALID|_EM_ZERODIVIDE|_EM_OVERFLOW|_EM_UNDERFLOW|_EM_INEXACT|_EM_DENORMAL,0xfffff );
|
||
|
|
_asm{
|
||
|
|
fld [flt];
|
||
|
|
fistp [temp];
|
||
|
|
}
|
||
|
|
_control87( _CW_DEFAULT,0xfffff );
|
||
|
|
return temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
float FloatConstNode::floatValue(){
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
string FloatConstNode::stringValue(){
|
||
|
|
return ftoa( value );
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////
|
||
|
|
// String constant //
|
||
|
|
/////////////////////
|
||
|
|
StringConstNode::StringConstNode( const string &s ):value(s){
|
||
|
|
sem_type=Type::string_type;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *StringConstNode::translate( Codegen *g ){
|
||
|
|
string lab=genLabel();
|
||
|
|
g->s_data( value,lab );
|
||
|
|
return call( "__bbStrConst",global( lab ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
int StringConstNode::intValue(){
|
||
|
|
return atoi( value );
|
||
|
|
}
|
||
|
|
|
||
|
|
float StringConstNode::floatValue(){
|
||
|
|
return (float)atof( value );
|
||
|
|
}
|
||
|
|
|
||
|
|
string StringConstNode::stringValue(){
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
////////////////////
|
||
|
|
// Unary operator //
|
||
|
|
////////////////////
|
||
|
|
ExprNode *UniExprNode::semant( Environ *e ){
|
||
|
|
expr=expr->semant( e );
|
||
|
|
sem_type=expr->sem_type;
|
||
|
|
if( sem_type!=Type::int_type && sem_type!=Type::float_type ) ex( "Illegal operator for type" );
|
||
|
|
if( ConstNode *c=expr->constNode() ){
|
||
|
|
ExprNode *e;
|
||
|
|
if( sem_type==Type::int_type ){
|
||
|
|
switch( op ){
|
||
|
|
case '+':e=d_new IntConstNode( +c->intValue() );break;
|
||
|
|
case '-':e=d_new IntConstNode( -c->intValue() );break;
|
||
|
|
case ABS:e=d_new IntConstNode( c->intValue()>=0 ? c->intValue() : -c->intValue() );break;
|
||
|
|
case SGN:e=d_new IntConstNode( c->intValue()>0 ? 1 : (c->intValue()<0 ? -1 : 0) );break;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
switch( op ){
|
||
|
|
case '+':e=d_new FloatConstNode( +c->floatValue() );break;
|
||
|
|
case '-':e=d_new FloatConstNode( -c->floatValue() );break;
|
||
|
|
case ABS:e=d_new FloatConstNode( c->floatValue()>=0 ? c->floatValue() : -c->floatValue() );break;
|
||
|
|
case SGN:e=d_new FloatConstNode( c->floatValue()>0 ? 1 : (c->floatValue()<0 ? -1 : 0) );break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
delete this;
|
||
|
|
return e;
|
||
|
|
}
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *UniExprNode::translate( Codegen *g ){
|
||
|
|
int n=0;
|
||
|
|
TNode *l=expr->translate( g );
|
||
|
|
if( sem_type==Type::int_type ){
|
||
|
|
switch( op ){
|
||
|
|
case '+':return l;
|
||
|
|
case '-':n=IR_NEG;break;
|
||
|
|
case ABS:return call( "__bbAbs",l );
|
||
|
|
case SGN:return call( "__bbSgn",l );
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
switch( op ){
|
||
|
|
case '+':return l;
|
||
|
|
case '-':n=IR_FNEG;break;
|
||
|
|
case ABS:return fcall( "__bbFAbs",l );
|
||
|
|
case SGN:return fcall( "__bbFSgn",l );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return d_new TNode( n,l,0 );
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////////////////////////////////////
|
||
|
|
// boolean expression - accepts ints, returns ints //
|
||
|
|
/////////////////////////////////////////////////////
|
||
|
|
ExprNode *BinExprNode::semant( Environ *e ){
|
||
|
|
lhs=lhs->semant(e);lhs=lhs->castTo( Type::int_type,e );
|
||
|
|
rhs=rhs->semant(e);rhs=rhs->castTo( Type::int_type,e );
|
||
|
|
ConstNode *lc=lhs->constNode(),*rc=rhs->constNode();
|
||
|
|
if( lc && rc ){
|
||
|
|
ExprNode *expr;
|
||
|
|
switch( op ){
|
||
|
|
case AND:expr=d_new IntConstNode( lc->intValue() & rc->intValue() );break;
|
||
|
|
case OR: expr=d_new IntConstNode( lc->intValue() | rc->intValue() );break;
|
||
|
|
case XOR:expr=d_new IntConstNode( lc->intValue() ^ rc->intValue() );break;
|
||
|
|
case SHL:expr=d_new IntConstNode( lc->intValue()<< rc->intValue() );break;
|
||
|
|
case SHR:expr=d_new IntConstNode( (unsigned)lc->intValue()>>rc->intValue() );break;
|
||
|
|
case SAR:expr=d_new IntConstNode( lc->intValue()>> rc->intValue() );break;
|
||
|
|
}
|
||
|
|
delete this;
|
||
|
|
return expr;
|
||
|
|
}
|
||
|
|
sem_type=Type::int_type;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *BinExprNode::translate( Codegen *g ){
|
||
|
|
TNode *l=lhs->translate( g );
|
||
|
|
TNode *r=rhs->translate( g );
|
||
|
|
int n=0;
|
||
|
|
switch( op ){
|
||
|
|
case AND:n=IR_AND;break;case OR:n=IR_OR;break;case XOR:n=IR_XOR;break;
|
||
|
|
case SHL:n=IR_SHL;break;case SHR:n=IR_SHR;break;case SAR:n=IR_SAR;break;
|
||
|
|
}
|
||
|
|
return d_new TNode( n,l,r );
|
||
|
|
}
|
||
|
|
|
||
|
|
///////////////////////////
|
||
|
|
// arithmetic expression //
|
||
|
|
///////////////////////////
|
||
|
|
ExprNode *ArithExprNode::semant( Environ *e ){
|
||
|
|
lhs=lhs->semant(e);
|
||
|
|
rhs=rhs->semant(e);
|
||
|
|
if( lhs->sem_type->structType() || rhs->sem_type->structType() ){
|
||
|
|
ex( "Arithmetic operator cannot be applied to custom type objects" );
|
||
|
|
}
|
||
|
|
if( lhs->sem_type==Type::string_type || rhs->sem_type==Type::string_type ){
|
||
|
|
//one side is a string - only + operator...
|
||
|
|
if( op!='+' ) ex( "Operator cannot be applied to strings" );
|
||
|
|
sem_type=Type::string_type;
|
||
|
|
}else if( op=='^' || lhs->sem_type==Type::float_type || rhs->sem_type==Type::float_type ){
|
||
|
|
//It's ^, or one side is a float
|
||
|
|
sem_type=Type::float_type;
|
||
|
|
}else{
|
||
|
|
//must be 2 ints
|
||
|
|
sem_type=Type::int_type;
|
||
|
|
}
|
||
|
|
lhs=lhs->castTo( sem_type,e );
|
||
|
|
rhs=rhs->castTo( sem_type,e );
|
||
|
|
ConstNode *lc=lhs->constNode(),*rc=rhs->constNode();
|
||
|
|
if( rc && (op=='/' || op==MOD) ){
|
||
|
|
if( (sem_type==Type::int_type && !rc->intValue()) || (sem_type==Type::float_type && !rc->floatValue()) ){
|
||
|
|
ex( "Division by zero" );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if( lc && rc ){
|
||
|
|
ExprNode *expr;
|
||
|
|
if( sem_type==Type::string_type ){
|
||
|
|
expr=d_new StringConstNode( lc->stringValue()+rc->stringValue() );
|
||
|
|
}else if( sem_type==Type::int_type ){
|
||
|
|
switch( op ){
|
||
|
|
case '+':expr=d_new IntConstNode( lc->intValue()+rc->intValue() );break;
|
||
|
|
case '-':expr=d_new IntConstNode( lc->intValue()-rc->intValue() );break;
|
||
|
|
case '*':expr=d_new IntConstNode( lc->intValue()*rc->intValue() );break;
|
||
|
|
case '/':expr=d_new IntConstNode( lc->intValue()/rc->intValue() );break;
|
||
|
|
case MOD:expr=d_new IntConstNode( lc->intValue()%rc->intValue() );break;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
switch( op ){
|
||
|
|
case '+':expr=d_new FloatConstNode( lc->floatValue()+rc->floatValue() );break;
|
||
|
|
case '-':expr=d_new FloatConstNode( lc->floatValue()-rc->floatValue() );break;
|
||
|
|
case '*':expr=d_new FloatConstNode( lc->floatValue()*rc->floatValue() );break;
|
||
|
|
case '/':expr=d_new FloatConstNode( lc->floatValue()/rc->floatValue() );break;
|
||
|
|
case MOD:expr=d_new FloatConstNode( fmod( lc->floatValue(),rc->floatValue() ) );break;
|
||
|
|
case '^':expr=d_new FloatConstNode( pow( lc->floatValue(),rc->floatValue() ) );break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
delete this;
|
||
|
|
return expr;
|
||
|
|
}
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *ArithExprNode::translate( Codegen *g ){
|
||
|
|
TNode *l=lhs->translate( g );
|
||
|
|
TNode *r=rhs->translate( g );
|
||
|
|
if( sem_type==Type::string_type ){
|
||
|
|
return call( "__bbStrConcat",l,r );
|
||
|
|
}
|
||
|
|
int n=0;
|
||
|
|
if( sem_type==Type::int_type ){
|
||
|
|
switch( op ){
|
||
|
|
case '+':n=IR_ADD;break;case '-':n=IR_SUB;break;
|
||
|
|
case '*':n=IR_MUL;break;case '/':n=IR_DIV;break;
|
||
|
|
case MOD:return call( "__bbMod",l,r );
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
switch( op ){
|
||
|
|
case '+':n=IR_FADD;break;case '-':n=IR_FSUB;break;
|
||
|
|
case '*':n=IR_FMUL;break;case '/':n=IR_FDIV;break;
|
||
|
|
case MOD:return fcall( "__bbFMod",l,r );
|
||
|
|
case '^':return fcall( "__bbFPow",l,r );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return d_new TNode( n,l,r );
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////////////
|
||
|
|
// relation expression //
|
||
|
|
/////////////////////////
|
||
|
|
ExprNode *RelExprNode::semant( Environ *e ){
|
||
|
|
lhs=lhs->semant(e);
|
||
|
|
rhs=rhs->semant(e);
|
||
|
|
if( lhs->sem_type->structType() || rhs->sem_type->structType() ){
|
||
|
|
if( op!='=' && op!=NE ) ex( "Illegal operator for custom type objects" );
|
||
|
|
opType=lhs->sem_type!=Type::null_type ? lhs->sem_type : rhs->sem_type;
|
||
|
|
}else if( lhs->sem_type==Type::string_type || rhs->sem_type==Type::string_type ){
|
||
|
|
opType=Type::string_type;
|
||
|
|
}else if( lhs->sem_type==Type::float_type || rhs->sem_type==Type::float_type ){
|
||
|
|
opType=Type::float_type;
|
||
|
|
}else{
|
||
|
|
opType=Type::int_type;
|
||
|
|
}
|
||
|
|
sem_type=Type::int_type;
|
||
|
|
lhs=lhs->castTo( opType,e );
|
||
|
|
rhs=rhs->castTo( opType,e );
|
||
|
|
ConstNode *lc=lhs->constNode(),*rc=rhs->constNode();
|
||
|
|
if( lc && rc ){
|
||
|
|
ExprNode *expr;
|
||
|
|
if( opType==Type::string_type ){
|
||
|
|
switch( op ){
|
||
|
|
case '<':expr=d_new IntConstNode( lc->stringValue()< rc->stringValue() );break;
|
||
|
|
case '=':expr=d_new IntConstNode( lc->stringValue()==rc->stringValue() );break;
|
||
|
|
case '>':expr=d_new IntConstNode( lc->stringValue()> rc->stringValue() );break;
|
||
|
|
case LE: expr=d_new IntConstNode( lc->stringValue()<=rc->stringValue() );break;
|
||
|
|
case NE: expr=d_new IntConstNode( lc->stringValue()!=rc->stringValue() );break;
|
||
|
|
case GE: expr=d_new IntConstNode( lc->stringValue()>=rc->stringValue() );break;
|
||
|
|
}
|
||
|
|
}else if( opType==Type::float_type ){
|
||
|
|
switch( op ){
|
||
|
|
case '<':expr=d_new IntConstNode( lc->floatValue()< rc->floatValue() );break;
|
||
|
|
case '=':expr=d_new IntConstNode( lc->floatValue()==rc->floatValue() );break;
|
||
|
|
case '>':expr=d_new IntConstNode( lc->floatValue()> rc->floatValue() );break;
|
||
|
|
case LE: expr=d_new IntConstNode( lc->floatValue()<=rc->floatValue() );break;
|
||
|
|
case NE: expr=d_new IntConstNode( lc->floatValue()!=rc->floatValue() );break;
|
||
|
|
case GE: expr=d_new IntConstNode( lc->floatValue()>=rc->floatValue() );break;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
switch( op ){
|
||
|
|
case '<':expr=d_new IntConstNode( lc->intValue()< rc->intValue() );break;
|
||
|
|
case '=':expr=d_new IntConstNode( lc->intValue()==rc->intValue() );break;
|
||
|
|
case '>':expr=d_new IntConstNode( lc->intValue()> rc->intValue() );break;
|
||
|
|
case LE: expr=d_new IntConstNode( lc->intValue()<=rc->intValue() );break;
|
||
|
|
case NE: expr=d_new IntConstNode( lc->intValue()!=rc->intValue() );break;
|
||
|
|
case GE: expr=d_new IntConstNode( lc->intValue()>=rc->intValue() );break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
delete this;
|
||
|
|
return expr;
|
||
|
|
}
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *RelExprNode::translate( Codegen *g ){
|
||
|
|
TNode *l=lhs->translate( g );
|
||
|
|
TNode *r=rhs->translate( g );
|
||
|
|
return compare( op,l,r,opType );
|
||
|
|
}
|
||
|
|
|
||
|
|
////////////////////
|
||
|
|
// New expression //
|
||
|
|
////////////////////
|
||
|
|
ExprNode *NewNode::semant( Environ *e ){
|
||
|
|
sem_type=e->findType( ident );
|
||
|
|
if( !sem_type ) ex( "custom type name not found" );
|
||
|
|
if( sem_type->structType()==0 ) ex( "type is not a custom type" );
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *NewNode::translate( Codegen *g ){
|
||
|
|
return call( "__bbObjNew",global( "_t"+ident ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
////////////////////
|
||
|
|
// First of class //
|
||
|
|
////////////////////
|
||
|
|
ExprNode *FirstNode::semant( Environ *e ){
|
||
|
|
sem_type=e->findType( ident );
|
||
|
|
if( !sem_type ) ex( "custom type name name not found" );
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *FirstNode::translate( Codegen *g ){
|
||
|
|
return call( "__bbObjFirst",global( "_t"+ident ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
///////////////////
|
||
|
|
// Last of class //
|
||
|
|
///////////////////
|
||
|
|
ExprNode *LastNode::semant( Environ *e ){
|
||
|
|
sem_type=e->findType( ident );
|
||
|
|
if( !sem_type ) ex( "custom type name not found" );
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *LastNode::translate( Codegen *g ){
|
||
|
|
return call( "__bbObjLast",global( "_t"+ident ) );
|
||
|
|
}
|
||
|
|
|
||
|
|
////////////////////
|
||
|
|
// Next of object //
|
||
|
|
////////////////////
|
||
|
|
ExprNode *AfterNode::semant( Environ *e ){
|
||
|
|
expr=expr->semant( e );
|
||
|
|
if( expr->sem_type==Type::null_type ) ex( "'After' cannot be used on 'Null'" );
|
||
|
|
if( expr->sem_type->structType()==0 ) ex( "'After' must be used with a custom type object" );
|
||
|
|
sem_type=expr->sem_type;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *AfterNode::translate( Codegen *g ){
|
||
|
|
TNode *t=expr->translate( g );
|
||
|
|
if( g->debug ) t=jumpf( t,"__bbNullObjEx" );
|
||
|
|
return call( "__bbObjNext",t );
|
||
|
|
}
|
||
|
|
|
||
|
|
////////////////////
|
||
|
|
// Prev of object //
|
||
|
|
////////////////////
|
||
|
|
ExprNode *BeforeNode::semant( Environ *e ){
|
||
|
|
expr=expr->semant( e );
|
||
|
|
if( expr->sem_type==Type::null_type ) ex( "'Before' cannot be used with 'Null'" );
|
||
|
|
if( expr->sem_type->structType()==0 ) ex( "'Before' must be used with a custom type object" );
|
||
|
|
sem_type=expr->sem_type;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *BeforeNode::translate( Codegen *g ){
|
||
|
|
TNode *t=expr->translate( g );
|
||
|
|
if( g->debug ) t=jumpf( t,"__bbNullObjEx" );
|
||
|
|
return call( "__bbObjPrev",t );
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////
|
||
|
|
// Null object //
|
||
|
|
/////////////////
|
||
|
|
ExprNode *NullNode::semant( Environ *e ){
|
||
|
|
sem_type=Type::null_type;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *NullNode::translate( Codegen *g ){
|
||
|
|
return d_new TNode( IR_CONST,0,0,0 );
|
||
|
|
}
|
||
|
|
|
||
|
|
/////////////////
|
||
|
|
// Object cast //
|
||
|
|
/////////////////
|
||
|
|
ExprNode *ObjectCastNode::semant( Environ *e ){
|
||
|
|
expr=expr->semant( e );
|
||
|
|
expr=expr->castTo( Type::int_type,e );
|
||
|
|
sem_type=e->findType( type_ident );
|
||
|
|
if( !sem_type ) ex( "custom type name not found" );
|
||
|
|
if( !sem_type->structType() ) ex( "type is not a custom type" );
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *ObjectCastNode::translate( Codegen *g ){
|
||
|
|
TNode *t=expr->translate( g );
|
||
|
|
t=call( "__bbObjFromHandle",t,global( "_t"+sem_type->structType()->ident ) );
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
///////////////////
|
||
|
|
// Object Handle //
|
||
|
|
///////////////////
|
||
|
|
ExprNode *ObjectHandleNode::semant( Environ *e ){
|
||
|
|
expr=expr->semant( e );
|
||
|
|
if( !expr->sem_type->structType() ) ex( "'ObjectHandle' must be used with an object" );
|
||
|
|
sem_type=Type::int_type;
|
||
|
|
return this;
|
||
|
|
}
|
||
|
|
|
||
|
|
TNode *ObjectHandleNode::translate( Codegen *g ){
|
||
|
|
TNode *t=expr->translate( g );
|
||
|
|
return call( "__bbObjToHandle",t );
|
||
|
|
}
|