| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- #include "std.h"
- #include "nodes.h"
- static string fileLabel;
- static map<string,string> fileMap;
- void StmtNode::debug( int pos,Codegen *g ){
- if( g->debug ){
- TNode *t=fileLabel.size() ? global( fileLabel ) : iconst(0);
- g->code( call( "__bbDebugStmt",iconst( pos ),t ) );
- }
- }
- void StmtSeqNode::reset( const string &file,const string &lab ){
- fileLabel="";
- fileMap.clear();
- fileMap[file]=lab;
- }
- ////////////////////////
- // Statement Sequence //
- ////////////////////////
- void StmtSeqNode::semant( Environ *e ){
- for( int k=0;k<stmts.size();++k ){
- try{ stmts[k]->semant( e ); }
- catch( Ex &x ){
- if( x.pos<0 ) x.pos=stmts[k]->pos;
- if( !x.file.size() ) x.file=file;
- throw;
- }
- }
- }
- void StmtSeqNode::translate( Codegen *g ){
- string t=fileLabel;
- fileLabel=file.size() ? fileMap[file] : "";
- for( int k=0;k<stmts.size();++k ){
- StmtNode *stmt=stmts[k];
- stmt->debug( stmts[k]->pos,g );
- try{
- stmt->translate( g );
- }
- catch( Ex &x ){
- if( x.pos<0 ) x.pos=stmts[k]->pos;
- if( !x.file.size() ) x.file=file;
- throw;
- }
- }
- fileLabel=t;
- }
- /////////////////
- // An Include! //
- /////////////////
- void IncludeNode::semant( Environ *e ){
- label=genLabel();
- fileMap[file]=label;
-
- stmts->semant( e );
- }
- void IncludeNode::translate( Codegen *g ){
- if( g->debug ) g->s_data( file,label );
- stmts->translate( g );
- }
- ///////////////////
- // a declaration //
- ///////////////////
- void DeclStmtNode::semant( Environ *e ){
- decl->proto( e->decls,e );
- decl->semant( e );
- }
- void DeclStmtNode::translate( Codegen *g ){
- decl->translate( g );
- }
- //////////////////////////////
- // Dim AND declare an Array //
- //////////////////////////////
- void DimNode::semant( Environ *e ){
- Type *t=tagType( tag,e );
- if( Decl *d=e->findDecl( ident ) ){
- ArrayType *a=d->type->arrayType();
- if( !a || a->dims!=exprs->size() || (t && a->elementType!=t) ){
- ex( "Duplicate identifier" );
- }
- sem_type=a;sem_decl=0;
- }else{
- if( e->level>0 ) ex( "Array not found in main program" );
- if( !t ) t=Type::int_type;
- sem_type=d_new ArrayType( t,exprs->size() );
- sem_decl=e->decls->insertDecl( ident,sem_type,DECL_ARRAY );
- e->types.push_back( sem_type );
- }
- exprs->semant( e );
- exprs->castTo( Type::int_type,e );
- }
- void DimNode::translate( Codegen *g ){
- TNode *t;
- g->code( call( "__bbUndimArray",global( "_a"+ident ) ) );
- for( int k=0;k<exprs->size();++k ){
- t=add( global( "_a"+ident ),iconst( k*4+12 ) );
- t=move( exprs->exprs[k]->translate(g),mem( t ) );
- g->code( t );
- }
- g->code( call( "__bbDimArray",global( "_a"+ident ) ) );
- if( !sem_decl ) return;
- int et;
- Type *ty=sem_type->arrayType()->elementType;
- if( ty==Type::int_type ) et=1;
- else if( ty==Type::float_type ) et=2;
- else if( ty==Type::string_type ) et=3;
- else et=5;
- g->align_data( 4 );
- g->i_data( 0,"_a"+ident );
- g->i_data( et );
- g->i_data( exprs->size() );
- for( k=0;k<exprs->size();++k ) g->i_data( 0 );
- }
- ////////////////
- // Assignment //
- ////////////////
- void AssNode::semant( Environ *e ){
- var->semant( e );
- if( var->sem_type->constType() ) ex( "Constants can not be assigned to" );
- if( var->sem_type->vectorType() ) ex( "Blitz arrays can not be assigned to" );
- expr=expr->semant( e );
- expr=expr->castTo( var->sem_type,e );
- }
- void AssNode::translate( Codegen *g ){
- g->code( var->store( g,expr->translate( g ) ) );
- }
- //////////////////////////
- // Expression statement //
- //////////////////////////
- void ExprStmtNode::semant( Environ *e ){
- expr=expr->semant( e );
- }
- void ExprStmtNode::translate( Codegen *g ){
- TNode *t=expr->translate( g );
- if( expr->sem_type==Type::string_type ) t=call( "__bbStrRelease",t );
- g->code( t );
- }
- ////////////////
- // user label //
- ////////////////
- void LabelNode::semant( Environ *e ){
- if( Label *l=e->findLabel( ident ) ){
- if( l->def>=0 ) ex( "duplicate label" );
- l->def=pos;l->data_sz=data_sz;
- }else e->insertLabel( ident,pos,-1,data_sz );
- ident=e->funcLabel+ident;
- }
- void LabelNode::translate( Codegen *g ){
- g->label( "_l"+ident );
- }
- //////////////////
- // Restore data //
- //////////////////
- void RestoreNode::semant( Environ *e ){
- if( e->level>0 ) e=e->globals;
- if( ident.size()==0 ) sem_label=0;
- else{
- sem_label=e->findLabel( ident );
- if( !sem_label ) sem_label=e->insertLabel( ident,-1,pos,-1 );
- }
- }
- void RestoreNode::translate( Codegen *g ){
- TNode *t=global( "__DATA" );
- if( sem_label ) t=add( t,iconst( sem_label->data_sz*8 ) );
- g->code( call( "__bbRestore",t ) );
- }
- ////////////////////
- // Goto statement //
- ////////////////////
- void GotoNode::semant( Environ *e ){
- if( !e->findLabel( ident ) ){
- e->insertLabel( ident,-1,pos,-1 );
- }
- ident=e->funcLabel+ident;
- }
- void GotoNode::translate( Codegen *g ){
- g->code( jump( "_l"+ident ) );
- }
- /////////////////////
- // Gosub statement //
- /////////////////////
- void GosubNode::semant( Environ *e ){
- if( e->level>0 ) ex( "'Gosub' may not be used inside a function" );
- if( !e->findLabel( ident ) ) e->insertLabel( ident,-1,pos,-1 );
- ident=e->funcLabel+ident;
- }
- void GosubNode::translate( Codegen *g ){
- g->code( jsr( "_l"+ident ) );
- }
- //////////////////
- // If statement //
- //////////////////
- void IfNode::semant( Environ *e ){
- expr=expr->semant( e );
- expr=expr->castTo( Type::int_type,e );
- stmts->semant( e );
- if( elseOpt ) elseOpt->semant( e );
- }
- void IfNode::translate( Codegen *g ){
- if( ConstNode *c=expr->constNode() ){
- if( c->intValue() ) stmts->translate( g );
- else if( elseOpt ) elseOpt->translate( g );
- }else{
- string _else=genLabel();
- g->code( jumpf( expr->translate( g ),_else ) );
- stmts->translate( g );
- if( elseOpt ){
- string _else2=genLabel();
- g->code( jump( _else2 ) );
- g->label( _else );
- elseOpt->translate( g );
- _else=_else2;
- }
- g->label( _else );
- }
- }
- ///////////
- // Break //
- ///////////
- void ExitNode::semant( Environ *e ){
- sem_brk=e->breakLabel;
- if( !sem_brk.size() ) ex( "break must appear inside a loop" );
- }
- void ExitNode::translate( Codegen *g ){
- g->code( d_new TNode( IR_JUMP,0,0,sem_brk ) );
- }
- /////////////////////
- // While statement //
- /////////////////////
- void WhileNode::semant( Environ *e ){
- expr=expr->semant( e );
- expr=expr->castTo( Type::int_type,e );
- string brk=e->setBreak( sem_brk=genLabel() );
- stmts->semant( e );
- e->setBreak( brk );
- }
- void WhileNode::translate( Codegen *g ){
- string loop=genLabel();
- if( ConstNode *c=expr->constNode() ){
- if( !c->intValue() ) return;
- g->label( loop );
- stmts->translate( g );
- g->code( jump( loop ) );
- }else{
- string cond=genLabel();
- g->code( jump( cond ) );
- g->label( loop );
- stmts->translate( g );
- debug( wendPos,g );
- g->label( cond );
- g->code( jumpt( expr->translate( g ),loop ) );
- }
- g->label( sem_brk );
- }
- ///////////////////
- // For/Next loop //
- ///////////////////
- ForNode::ForNode( VarNode *var,ExprNode *from,ExprNode *to,ExprNode *step,StmtSeqNode *ss,int np )
- :var(var),fromExpr(from),toExpr(to),stepExpr(step),stmts(ss),nextPos(np){
- }
- ForNode::~ForNode(){
- delete stmts;
- delete stepExpr;
- delete toExpr;
- delete fromExpr;
- delete var;
- }
- void ForNode::semant( Environ *e ){
- var->semant( e );
- Type *ty=var->sem_type;
- if( ty->constType() ) ex( "Index variable can not be constant" );
- if( ty!=Type::int_type && ty!=Type::float_type ){
- ex( "index variable must be integer or real" );
- }
- fromExpr=fromExpr->semant( e );
- fromExpr=fromExpr->castTo( ty,e );
- toExpr=toExpr->semant( e );
- toExpr=toExpr->castTo( ty,e );
- stepExpr=stepExpr->semant( e );
- stepExpr=stepExpr->castTo( ty,e );
- if( !stepExpr->constNode() ) ex( "Step value must be constant" );
- string brk=e->setBreak( sem_brk=genLabel() );
- stmts->semant( e );
- e->setBreak( brk );
- }
- void ForNode::translate( Codegen *g ){
- TNode *t;Type *ty=var->sem_type;
- //initial assignment
- g->code( var->store( g,fromExpr->translate( g ) ) );
- string cond=genLabel();
- string loop=genLabel();
- g->code( jump( cond ) );
- g->label( loop );
- stmts->translate( g );
- //execute the step part
- debug( nextPos,g );
- int op=ty==Type::int_type ? IR_ADD : IR_FADD;
- t=d_new TNode( op,var->load( g ),stepExpr->translate( g ) );
- g->code( var->store( g,t ) );
- //test for loop cond
- g->label( cond );
- op=stepExpr->constNode()->floatValue()>0 ? '>' : '<';
- t=compare( op,var->load( g ),toExpr->translate( g ),ty );
- g->code( jumpf( t,loop ) );
- g->label( sem_brk );
- }
- ///////////////////////////////
- // For each object of a type //
- ///////////////////////////////
- void ForEachNode::semant( Environ *e ){
- var->semant( e );
- Type *ty=var->sem_type;
- if( ty->structType()==0 ) ex( "Index variable is not a NewType" );
- Type *t=e->findType( typeIdent );
- if( !t ) ex( "Type name not found" );
- if( t!=ty ) ex( "Type mismatch" );
- string brk=e->setBreak( sem_brk=genLabel() );
- stmts->semant( e );
- e->setBreak( brk );
- }
- void ForEachNode::translate( Codegen *g ){
- TNode *t,*l,*r;
- string _loop=genLabel();
- string objFirst,objNext;
- if( var->isObjParam() ){
- objFirst="__bbObjEachFirst2";
- objNext="__bbObjEachNext2";
- }else{
- objFirst="__bbObjEachFirst";
- objNext="__bbObjEachNext";
- }
- l=var->translate( g );
- r=global( "_t"+typeIdent );
- t=jumpf( call( objFirst,l,r ),sem_brk );
- g->code( t );
- g->label( _loop );
- stmts->translate( g );
- debug( nextPos,g );
- t=jumpt( call( objNext,var->translate( g ) ),_loop );
- g->code( t );
- g->label( sem_brk );
- }
- ////////////////////////////
- // Return from a function //
- ////////////////////////////
- void ReturnNode::semant( Environ *e ){
- if( e->level<=0 && expr ){
- ex( "Main program cannot return a value" );
- }
- if( e->level>0 ){
- if( !expr ){
- if( e->returnType==Type::float_type ){
- expr=d_new FloatConstNode( 0 );
- }else if( e->returnType==Type::string_type ){
- expr=d_new StringConstNode( "" );
- }else if( e->returnType->structType() ){
- expr=d_new NullNode();
- }else{
- expr=d_new IntConstNode( 0 );
- }
- }
- expr=expr->semant( e );
- expr=expr->castTo( e->returnType,e );
- returnLabel=e->funcLabel+"_leave";
- }
- }
- void ReturnNode::translate( Codegen *g ){
- if( !expr ){
- g->code( d_new TNode( IR_RET,0,0 ) );
- return;
- }
- TNode *t=expr->translate( g );
- if( expr->sem_type==Type::float_type ){
- g->code( d_new TNode( IR_FRETURN,t,0,returnLabel ) );
- }else{
- g->code( d_new TNode( IR_RETURN,t,0,returnLabel ) );
- }
- }
- //////////////////////
- // Delete statement //
- //////////////////////
- void DeleteNode::semant( Environ *e ){
- expr=expr->semant( e );
- if( expr->sem_type->structType()==0 ) ex( "Can't delete non-Newtype" );
- }
- void DeleteNode::translate( Codegen *g ){
- TNode *t=expr->translate( g );
- g->code( call( "__bbObjDelete",t ) );
- }
- ///////////////////////////
- // Delete each of a type //
- ///////////////////////////
- void DeleteEachNode::semant( Environ *e ){
- Type *t=e->findType( typeIdent );
- if( !t || t->structType()==0 ) ex( "Specified name is not a NewType name" );
- }
- void DeleteEachNode::translate( Codegen *g ){
- g->code( call( "__bbObjDeleteEach",global( "_t"+typeIdent ) ) );
- }
- ///////////////////////////
- // Insert object in list //
- ///////////////////////////
- void InsertNode::semant( Environ *e ){
- expr1=expr1->semant( e );
- expr2=expr2->semant( e );
- StructType *t1=expr1->sem_type->structType();
- StructType *t2=expr2->sem_type->structType();
- if( !t1 || !t2 ) ex( "Illegal expression type" );
- if( t1!=t2 ) ex( "Objects types are differnt" );
- }
- void InsertNode::translate( Codegen *g ){
- TNode *t1=expr1->translate( g );
- if( g->debug ) t1=jumpf( t1,"__bbNullObjEx" );
- TNode *t2=expr2->translate( g );
- if( g->debug ) t2=jumpf( t2,"__bbNullObjEx" );
- string s=before ? "__bbObjInsBefore" : "__bbObjInsAfter";
- g->code( call( s,t1,t2 ) );
- }
- ////////////////////////
- // A select statement //
- ////////////////////////
- void SelectNode::semant( Environ *e ){
- expr=expr->semant( e );
- Type *ty=expr->sem_type;
- if( ty->structType() ) ex( "Select cannot be used with objects" );
- //we need a temp var
- Decl *d=e->decls->insertDecl( genLabel(),expr->sem_type,DECL_LOCAL );
- sem_temp=d_new DeclVarNode( d );
- for( int k=0;k<cases.size();++k ){
- CaseNode *c=cases[k];
- c->exprs->semant( e );
- c->exprs->castTo( ty,e );
- c->stmts->semant( e );
- }
- if( defStmts ) defStmts->semant( e );
- }
- void SelectNode::translate( Codegen *g ){
- Type *ty=expr->sem_type;
- g->code( sem_temp->store( g,expr->translate( g ) ) );
- vector<string> labs;
- string brk=genLabel();
- for( int k=0;k<cases.size();++k ){
- CaseNode *c=cases[k];
- labs.push_back( genLabel() );
- for( int j=0;j<c->exprs->size();++j ){
- ExprNode *e=c->exprs->exprs[j];
- TNode *t=compare( '=',sem_temp->load( g ),e->translate( g ),ty );
- g->code( jumpt( t,labs.back() ) );
- }
- }
- if( defStmts ) defStmts->translate( g );
- g->code( jump( brk ) );
- for( k=0;k<cases.size();++k ){
- CaseNode *c=cases[k];
- g->label( labs[k] );
- c->stmts->translate( g );
- g->code( jump( brk ) );
- }
- g->label( brk );
- }
- ////////////////////////////
- // Repeat...Until/Forever //
- ////////////////////////////
- void RepeatNode::semant( Environ *e ){
- sem_brk=genLabel();
- string brk=e->setBreak( sem_brk );
- stmts->semant( e );
- e->setBreak( brk );
- if( expr ){
- expr=expr->semant( e );
- expr=expr->castTo( Type::int_type,e );
- }
- }
- void RepeatNode::translate( Codegen *g ){
- string loop=genLabel();
- g->label( loop );
- stmts->translate( g );
- debug( untilPos,g );
- if( ConstNode *c=expr ? expr->constNode() : 0 ){
- if( !c->intValue() ) g->code( jump( loop ) );
- }else{
- if( expr ) g->code( jumpf( expr->translate( g ),loop ) );
- else g->code( jump( loop ) );
- }
- g->label( sem_brk );
- }
- ///////////////
- // Read data //
- ///////////////
- void ReadNode::semant( Environ *e ){
- var->semant( e );
- if( var->sem_type->constType() ) ex( "Constants can not be modified" );
- if( var->sem_type->structType() ) ex( "Data can not be read into an object" );
- }
- void ReadNode::translate( Codegen *g ){
- TNode *t;
- if( var->sem_type==Type::int_type ) t=call( "__bbReadInt" );
- else if( var->sem_type==Type::float_type ) t=fcall( "__bbReadFloat" );
- else t=call( "__bbReadStr" );
- g->code( var->store( g,t ) );
- }
|