blitz3d/compiler/declnode.cpp

281 lines
7.2 KiB
C++

#include "std.h"
#include "nodes.h"
//////////////////////////////
// Sequence of declarations //
//////////////////////////////
void DeclSeqNode::proto( DeclSeq *d,Environ *e ){
for( int k=0;k<decls.size();++k ){
try{ decls[k]->proto( d,e ); }
catch( Ex &x ){
if( x.pos<0 ) x.pos=decls[k]->pos;
if(!x.file.size() ) x.file=decls[k]->file;
throw;
}
}
}
void DeclSeqNode::semant( Environ *e ){
for( int k=0;k<decls.size();++k ){
try{ decls[k]->semant( e ); }
catch( Ex &x ){
if( x.pos<0 ) x.pos=decls[k]->pos;
if(!x.file.size() ) x.file=decls[k]->file;
throw;
}
}
}
void DeclSeqNode::translate( Codegen *g ){
for( int k=0;k<decls.size();++k ){
try{ decls[k]->translate( g ); }
catch( Ex &x ){
if( x.pos<0 ) x.pos=decls[k]->pos;
if(!x.file.size() ) x.file=decls[k]->file;
throw;
}
}
}
void DeclSeqNode::transdata( Codegen *g ){
for( int k=0;k<decls.size();++k ){
try{ decls[k]->transdata( g ); }
catch( Ex &x ){
if( x.pos<0 ) x.pos=decls[k]->pos;
if(!x.file.size() ) x.file=decls[k]->file;
throw;
}
}
}
////////////////////////////
// Simple var declaration //
////////////////////////////
void VarDeclNode::proto( DeclSeq *d,Environ *e ){
Type *ty=tagType( tag,e );
if( !ty ) ty=Type::int_type;
ConstType *defType=0;
if( expr ){
expr=expr->semant( e );
expr=expr->castTo( ty,e );
if( constant || (kind&DECL_PARAM) ){
ConstNode *c=expr->constNode();
if( !c ) ex( "Expression must be constant" );
if( ty==Type::int_type ) ty=d_new ConstType( c->intValue() );
else if( ty==Type::float_type ) ty=d_new ConstType( c->floatValue() );
else ty=d_new ConstType( c->stringValue() );
e->types.push_back( ty );
delete expr;expr=0;
}
if( kind&DECL_PARAM ){
defType=ty->constType();ty=defType->valueType;
}
}else if( constant ) ex( "Constants must be initialized" );
Decl *decl=d->insertDecl( ident,ty,kind,defType );
if( !decl ) ex( "Duplicate variable name" );
if( expr ) sem_var=d_new DeclVarNode( decl );
}
void VarDeclNode::semant( Environ *e ){
}
void VarDeclNode::translate( Codegen *g ){
if( kind & DECL_GLOBAL ){
g->align_data( 4 );
g->i_data( 0,"_v"+ident );
}
if( expr ) g->code( sem_var->store( g,expr->translate( g ) ) );
}
//////////////////////////
// Function Declaration //
//////////////////////////
void FuncDeclNode::proto( DeclSeq *d,Environ *e ){
Type *t=tagType( tag,e );if( !t ) t=Type::int_type;
a_ptr<DeclSeq> decls( d_new DeclSeq() );
params->proto( decls,e );
sem_type=d_new FuncType( t,decls.release(),false,false );
if( !d->insertDecl( ident,sem_type,DECL_FUNC ) ){
delete sem_type;ex( "duplicate identifier" );
}
e->types.push_back( sem_type );
}
void FuncDeclNode::semant( Environ *e ){
sem_env=d_new Environ( genLabel(),sem_type->returnType,1,e );
DeclSeq *decls=sem_env->decls;
int k;
for( k=0;k<sem_type->params->size();++k ){
Decl *d=sem_type->params->decls[k];
if( !decls->insertDecl( d->name,d->type,d->kind ) ) ex( "duplicate identifier" );
}
stmts->semant( sem_env );
}
void FuncDeclNode::translate( Codegen *g ){
//var offsets
int size=enumVars( sem_env );
//enter function
g->enter( "_f"+ident,size );
//initialize locals
TNode *t=createVars( sem_env );
if( t ) g->code( t );
if( g->debug ){
string t=genLabel();
g->s_data( ident,t );
g->code( call( "__bbDebugEnter",local(0),iconst((int)sem_env),global(t) ) );
}
//translate statements
stmts->translate( g );
for( int k=0;k<sem_env->labels.size();++k ){
if( sem_env->labels[k]->def<0 ) ex( "Undefined label",sem_env->labels[k]->ref );
}
//leave the function
g->label( sem_env->funcLabel+"_leave" );
t=deleteVars( sem_env );
if( g->debug ) t=d_new TNode( IR_SEQ,call( "__bbDebugLeave" ),t );
g->leave( t,sem_type->params->size()*4 );
}
//////////////////////
// Type Declaration //
//////////////////////
void StructDeclNode::proto( DeclSeq *d,Environ *e ){
sem_type=d_new StructType( ident,d_new DeclSeq() );
if( !d->insertDecl( ident,sem_type,DECL_STRUCT ) ){
delete sem_type;ex( "Duplicate identifier" );
}
e->types.push_back( sem_type );
}
void StructDeclNode::semant( Environ *e ){
fields->proto( sem_type->fields,e );
for( int k=0;k<sem_type->fields->size();++k ) sem_type->fields->decls[k]->offset=k*4;
}
void StructDeclNode::translate( Codegen *g ){
//translate fields
fields->translate( g );
//type ID
g->align_data( 4 );
g->i_data( 5,"_t"+ident );
//used and free lists for type
int k;
for( k=0;k<2;++k ){
string lab=genLabel();
g->i_data( 0,lab ); //fields
g->p_data( lab ); //next
g->p_data( lab ); //prev
g->i_data( 0 ); //type
g->i_data( -1 ); //ref_cnt
}
//number of fields
g->i_data( sem_type->fields->size() );
//type of each field
for( k=0;k<sem_type->fields->size();++k ){
Decl *field=sem_type->fields->decls[k];
Type *type=field->type;
string t;
if( type==Type::int_type ) t="__bbIntType";
else if( type==Type::float_type ) t="__bbFltType";
else if( type==Type::string_type ) t="__bbStrType";
else if( StructType *s=type->structType() ) t="_t"+s->ident;
else if( VectorType *v=type->vectorType() ) t=v->label;
g->p_data( t );
}
}
//////////////////////
// Data declaration //
//////////////////////
void DataDeclNode::proto( DeclSeq *d,Environ *e ){
expr=expr->semant( e );
ConstNode *c=expr->constNode();
if( !c ) ex( "Data expression must be constant" );
if( expr->sem_type==Type::string_type ) str_label=genLabel();
}
void DataDeclNode::semant( Environ *e ){
}
void DataDeclNode::translate( Codegen *g ){
if( expr->sem_type!=Type::string_type ) return;
ConstNode *c=expr->constNode();
g->s_data( c->stringValue(),str_label );
}
void DataDeclNode::transdata( Codegen *g ){
ConstNode *c=expr->constNode();
if( expr->sem_type==Type::int_type ){
g->i_data( 1 );g->i_data( c->intValue() );
}else if( expr->sem_type==Type::float_type ){
float n=c->floatValue();
g->i_data( 2 );g->i_data( *(int*)&n );
}else{
g->i_data( 4 );g->p_data( str_label );
}
}
////////////////////////
// Vector declaration //
////////////////////////
void VectorDeclNode::proto( DeclSeq *d,Environ *env ){
Type *ty=tagType( tag,env );if( !ty ) ty=Type::int_type;
vector<int> sizes;
for( int k=0;k<exprs->size();++k ){
ExprNode *e=exprs->exprs[k]=exprs->exprs[k]->semant( env );
ConstNode *c=e->constNode();
if( !c ) ex( "Blitz array sizes must be constant" );
int n=c->intValue();
if( n<0 ) ex( "Blitz array sizes must not be negative" );
sizes.push_back( n+1 );
}
string label=genLabel();
sem_type=d_new VectorType( label,ty,sizes );
if( !d->insertDecl( ident,sem_type,kind ) ){
delete sem_type;ex( "Duplicate identifier" );
}
env->types.push_back( sem_type );
}
void VectorDeclNode::translate( Codegen *g ){
//type tag!
g->align_data( 4 );
VectorType *v=sem_type->vectorType();
g->i_data( 6,v->label );
int sz=1;
for( int k=0;k<v->sizes.size();++k ) sz*=v->sizes[k];
g->i_data( sz );
string t;
Type *type=v->elementType;
if( type==Type::int_type ) t="__bbIntType";
else if( type==Type::float_type ) t="__bbFltType";
else if( type==Type::string_type ) t="__bbStrType";
else if( StructType *s=type->structType() ) t="_t"+s->ident;
else if( VectorType *v=type->vectorType() ) t=v->label;
g->p_data( t );
if( kind==DECL_GLOBAL ) g->i_data( 0,"_v"+ident );
}