Inferno  0.2
render.cpp
Go to the documentation of this file.
00001 #include "tree/cpptree.hpp"
00002 #include "tree/sctree.hpp"
00003 #include "helpers/transformation.hpp"
00004 #include "tree/typeof.hpp"
00005 #include "common/trace.hpp"
00006 #include "common/read_args.hpp"
00007 #include "tree/type_db.hpp"
00008 #include "helpers/walk.hpp"
00009 #include "tree/misc.hpp"
00010 #include "tree/scope.hpp"
00011 #include "sort_decls.hpp"
00012 #include "render.hpp"
00013 #include "clang/Parse/DeclSpec.h"
00014 #include "uniquify_identifiers.hpp"
00015 
00016 using namespace CPPTree;
00017 using namespace SCTree;
00018 
00019 // Don't like the layout of rendered code?
00020 // Install "indent" on your UNIX box and pipe the output through iindent.sh
00021 
00022 // TODO maybe reduce () by using a simplified scheme, ie divide operators into "high" and "low"
00023 // categories and elide on low(high()). Note that a full scheme makes code unreadable if
00024 // user does not have them memorised. Maybe just encode those priorities that are well known.
00025 
00026 // TODO indent back to previous level at end of string
00027 #define ERROR_UNKNOWN(V) \
00028     string( "\n#error " ) + \
00029     string( V ) + \
00030     string( " not supported in " ) + \
00031     string( INFERNO_CURRENT_FUNCTION ) + \
00032     string( "\n" );
00033 
00034 #define ERROR_UNSUPPORTED(P) \
00035     ERROR_UNKNOWN( P ? typeid(*P).name() : "<NULL>" );
00036 
00037 
00038 Render::Render( string of ) :
00039     outfile( of )
00040 {
00041 }
00042 
00043 
00044 TreePtr<Node> Render::operator()( TreePtr<Node> context, TreePtr<Node> root )
00045 {
00046   // Render can only work on a whole program
00047   ASSERT( context == root );
00048   program = dynamic_pointer_cast<Program>(root);
00049   ASSERT( program );
00050   AutoPush< TreePtr<Scope> > cs( scope_stack, program );
00051   unique.clear();
00052   unique.UniquifyScope( context );
00053 
00054     string s;
00055 
00056     if( IsSystemC( root ) )
00057         s += "#include \"isystemc.h\"\n\n";
00058 
00059   s += RenderDeclarationCollection( program, ";\n", true ); // gets the .hpp stuff directly
00060 
00061   s += deferred_decls; // these could go in a .cpp file
00062 
00063   if( outfile.empty() )
00064   {
00065     puts( s.c_str() );
00066   }
00067   else
00068   {
00069     FILE *fp = fopen( outfile.c_str(), "wt" );
00070     ASSERT( fp )( "Cannot open output file \"%s\"", outfile.c_str() );
00071     fputs( s.c_str(), fp );
00072     fclose( fp );
00073   }
00074   program = TreePtr<Program>();
00075   return root; // no change
00076 }
00077 
00078 
00079 bool Render::IsSystemC( TreePtr<Node> root )
00080 { 
00081     Walk e(root);
00082     FOREACH( TreePtr<Node> n, e )
00083         if( dynamic_pointer_cast<SCConstruct>(n) )
00084             return true;
00085     return false;
00086 }
00087 
00088 
00089 string Render::RenderLiteral( TreePtr<Literal> sp )
00090 {
00091   return Sanitise( *sp );
00092 }
00093 
00094 
00095 string Render::RenderIdentifier( TreePtr<Identifier> id )
00096 {
00097   string ids;
00098   if( id )
00099   {
00100     if( TreePtr<SpecificIdentifier> ii = dynamic_pointer_cast<SpecificIdentifier>( id ) )
00101       ids = unique[ii];
00102     else
00103       ids = ERROR_UNSUPPORTED( (id) );
00104 
00105     TRACE( "%s\n", ids.c_str() );
00106   }
00107   else
00108   {
00109     TRACE();
00110   }
00111   return ids;
00112 }
00113 
00114 
00115 string Render::RenderScopePrefix( TreePtr<Identifier> id )
00116 {
00117   TreePtr<Scope> scope = GetScope( program, id );
00118   TRACE("%p %p %p\n", program.get(), scope.get(), scope_stack.top().get() );
00119   if( scope == scope_stack.top() )
00120     return string(); // local scope
00121   else if( scope == program )
00122     return " ::";
00123   else if( TreePtr<Enum> e = dynamic_pointer_cast<Enum>( scope ) ) // <- for enum
00124     return RenderScopePrefix( e->identifier );    // omit scope for the enum itself
00125   else if( TreePtr<Record> r = dynamic_pointer_cast<Record>( scope ) ) // <- for class, struct, union
00126     return RenderScopedIdentifier( r->identifier ) + "::";
00127   else if( dynamic_pointer_cast<CallableParams>( scope ) ||  // <- this is for params
00128              dynamic_pointer_cast<Compound>( scope ) ||    // <- this is for locals in body
00129              dynamic_pointer_cast<CompoundExpression>( scope ) )    // <- this is for locals in body
00130     return string();
00131   else
00132     return ERROR_UNSUPPORTED( scope );
00133 }
00134 
00135 
00136 string Render::RenderScopedIdentifier( TreePtr<Identifier> id )
00137 {
00138   string s = RenderScopePrefix( id ) + RenderIdentifier( id );
00139   TRACE("Render scoped identifier %s\n", s.c_str() );
00140   return s;
00141 }
00142 
00143 
00144 string Render::RenderIntegralType( TreePtr<Integral> type, string object )
00145 {
00146   bool ds;
00147   unsigned width;
00148   TreePtr<SpecificInteger> ic = dynamic_pointer_cast<SpecificInteger>( type->width );
00149   ASSERT(ic)("width must be integer");
00150   width = ic->getLimitedValue();
00151 
00152   TRACE("width %d\n", width);
00153 
00154   if( width == TypeDb::char_bits )
00155     ds = TypeDb::char_default_signed;
00156   else
00157     ds = TypeDb::int_default_signed;
00158 
00159   // Produce signed or unsigned if required
00160   // Note: literal strings can be converted to char * but not unsigned char * or signed char *
00161   string s;
00162   if( dynamic_pointer_cast< Signed >(type) && !ds )
00163     s = "signed ";
00164   else if( dynamic_pointer_cast< Unsigned >(type) && ds )
00165     s = "unsigned ";
00166 
00167   // Fix the width
00168   bool bitfield = false;
00169   if( width == TypeDb::char_bits )
00170     s += "char";
00171   else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_unspecified] )
00172     s += "int";
00173   else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_short] )
00174     s += "short";
00175   else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_long] )
00176     s += "long";
00177   else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_longlong] )
00178     s += "long long";
00179   else    // unmatched defaults to int for bitfields
00180   {
00181     s += "int";
00182     bitfield = true;
00183   }
00184 
00185   s += " " + object;
00186 
00187   if( bitfield )
00188   {
00189      char b[100];
00190      sprintf(b, ":%d", width);
00191      s += b;
00192   }
00193 
00194   return s;
00195 }
00196 
00197 
00198 string Render::RenderFloatingType( TreePtr<Floating> type )
00199 {
00200   string s;
00201   TreePtr<SpecificFloatSemantics> sem = dynamic_pointer_cast<SpecificFloatSemantics>(type->semantics);
00202   ASSERT(sem);
00203 
00204   if( &(const llvm::fltSemantics &)*sem == TypeDb::float_semantics )
00205     s += "float";
00206   else if( &(const llvm::fltSemantics &)*sem == TypeDb::double_semantics )
00207     s += "double";
00208   else if( &(const llvm::fltSemantics &)*sem == TypeDb::long_double_semantics )
00209     s += "long double";
00210   else
00211     ASSERT(0)("no builtin floating type has required semantics"); // TODO drop in a bit vector
00212 
00213   return s;
00214 }
00215 
00216 
00217 string Render::RenderType( TreePtr<Type> type, string object, bool constant )
00218 {
00219   string sobject;
00220   if( !object.empty() )
00221     sobject = " " + object;
00222     
00223     string const_str = constant?"const ":"";
00224 
00225   TRACE();
00226   if( TreePtr<Integral> i = dynamic_pointer_cast< Integral >(type) )
00227     return const_str + RenderIntegralType( i, object );
00228   if( TreePtr<Floating> f = dynamic_pointer_cast< Floating >(type) )
00229     return const_str + RenderFloatingType( f ) + sobject;
00230   else if( dynamic_pointer_cast< Void >(type) )
00231     return const_str + "void" + sobject;
00232   else if( dynamic_pointer_cast< Boolean >(type) )
00233     return const_str + "bool" + sobject;
00234   else if( TreePtr<Constructor> c = dynamic_pointer_cast< Constructor >(type) )
00235     return object + "(" + RenderDeclarationCollection(c, ", ", false) + ")" + const_str;
00236   else if( TreePtr<Destructor> f = dynamic_pointer_cast< Destructor >(type) )
00237     return object + "()" + const_str;
00238   else if( TreePtr<Function> f = dynamic_pointer_cast< Function >(type) )
00239     return RenderType( f->return_type, "(" + object + ")(" + RenderDeclarationCollection(f, ", ", false) + ")" + const_str );
00240   else if( TreePtr<Process> f = dynamic_pointer_cast< Process >(type) )
00241     return "void " + object + "()" + const_str;
00242   else if( TreePtr<Pointer> p = dynamic_pointer_cast< Pointer >(type) )
00243     return RenderType( p->destination, const_str + "(*" + object + ")", false ); // TODO Pointer node to indicate constancy of pointed-to object - would go into this call to RenderType
00244   else if( TreePtr<Reference> r = dynamic_pointer_cast< Reference >(type) )
00245     return RenderType( r->destination, const_str + "(&" + object + ")" );
00246   else if( TreePtr<Array> a = dynamic_pointer_cast< Array >(type) )
00247     return RenderType( a->element, object.empty() ? "[" + RenderExpression(a->size) + "]" : "(" + object + "[" + RenderExpression(a->size) + "])", constant );
00248   else if( TreePtr<Typedef> t = dynamic_pointer_cast< Typedef >(type) )
00249     return const_str + RenderIdentifier(t->identifier) + sobject;
00250   else if( TreePtr<SpecificTypeIdentifier> ti = dynamic_pointer_cast< SpecificTypeIdentifier >(type) )
00251     return const_str + RenderScopedIdentifier(ti) + sobject;
00252   else if( shared_ptr<SCNamedIdentifier> sct = dynamic_pointer_cast< SCNamedIdentifier >(type) )
00253     return const_str + sct->GetToken() + sobject;
00254     else if( dynamic_pointer_cast<Labeley>(type) )
00255         return const_str + "void *" + object;
00256   else
00257     return ERROR_UNSUPPORTED(type);
00258 }
00259 
00260 
00261 // Insert escapes into a string so it can be put in source code
00262 // TODO use \n \r etc and let printable ascii through
00263 string Render::Sanitise( string s )
00264 {
00265   string o;
00266   for( int i=0; i<s.size(); i++ )
00267   {
00268     char c[10];
00269     if( s[i] < ' ' )
00270       o += SSPrintf( c, "\\x%02x", s[i] );
00271     else
00272       o += s[i];
00273   }
00274   return o;
00275 }
00276 
00277 
00278 string Render::RenderOperator( TreePtr<Operator> op, Sequence<Expression> &operands )
00279 {
00280   ASSERT(op);
00281   if( dynamic_pointer_cast< MakeArray >(op) )
00282     return "{ " + RenderOperandSequence( operands, ", ", false ) + " }";
00283   else if( dynamic_pointer_cast< Multiplexor >(op) )
00284     return RenderExpression( operands[0], true ) + " ? " +
00285          RenderExpression( operands[1], true ) + " : " +
00286          RenderExpression( operands[2], true );
00287   else if( dynamic_pointer_cast< Subscript >(op) )
00288     return RenderExpression( operands[0], true ) + "[" +
00289          RenderExpression( operands[1], false ) + "]";
00290 #define INFIX(TOK, TEXT, NODE, BASE, CAT) \
00291   else if( dynamic_pointer_cast<NODE>(op) ) \
00292     return RenderExpression( operands[0], true ) +\
00293          TEXT +\
00294          RenderExpression( operands[1], true );
00295 #define PREFIX(TOK, TEXT, NODE, BASE, CAT) \
00296   else if( dynamic_pointer_cast<NODE>(op) ) \
00297     return TEXT +\
00298          RenderExpression( operands[0], true );
00299 #define POSTFIX(TOK, TEXT, NODE, BASE, CAT) \
00300   else if( dynamic_pointer_cast<NODE>(op) ) \
00301     return RenderExpression( operands[0], true ) +\
00302          TEXT;
00303 #include "tree/operator_db.inc"
00304   else
00305     return ERROR_UNSUPPORTED(op);
00306 }
00307 
00308 
00309 string Render::RenderCall( TreePtr<Call> call )
00310 {
00311   string s;
00312 
00313   // Render the expression that resolves to the function name unless this is
00314   // a constructor call in which case just the name of the thing being constructed.
00315   if( TreePtr<Expression> base = TypeOf::instance.IsConstructorCall( program, call ) )
00316     s += RenderExpression( base, true );
00317   else
00318     s += RenderExpression( call->callee, true );
00319 
00320   s += "(";
00321 
00322   // If CallableParams, generate some arguments, resolving the order using the original function type
00323   TreePtr<Node> ctype = TypeOf::instance( program, call->callee );
00324   ASSERT( ctype );
00325   if( TreePtr<CallableParams> cp = dynamic_pointer_cast<CallableParams>(ctype) )
00326     s += RenderMapInOrder( call, cp, ", ", false );
00327 
00328   s += ")";
00329   return s;
00330 }
00331 
00332 
00333 string Render::RenderExpression( TreePtr<Initialiser> expression, bool bracketize_operator )
00334 {
00335   TRACE("%p\n", expression.get());
00336 
00337   string before = bracketize_operator ? "(" : "";
00338   string after = bracketize_operator ? ")" : "";
00339 
00340   if( dynamic_pointer_cast< Uninitialised >(expression) )
00341     return string();
00342     else if( TreePtr<CompoundExpression> ce = dynamic_pointer_cast< CompoundExpression >(expression) )
00343     {
00344         AutoPush< TreePtr<Scope> > cs( scope_stack, ce );
00345         string s = "({ ";
00346         s += RenderDeclarationCollection( ce, "; ", true ); // Must do this first to populate backing list
00347         s += RenderSequence( ce->statements, "; ", true );
00348         return s + "})";
00349     }
00350   else if( TreePtr<SpecificLabelIdentifier> li = dynamic_pointer_cast< SpecificLabelIdentifier >(expression) )
00351     return before +
00352          "&&" + RenderIdentifier( li ) + // label-as-variable (GCC extension)
00353          after;
00354   else if( TreePtr<InstanceIdentifier> ii = dynamic_pointer_cast< InstanceIdentifier >(expression) )
00355     return RenderScopedIdentifier( ii );
00356   else if( TreePtr<SizeOf> pot = dynamic_pointer_cast< SizeOf >(expression) )
00357     return before +
00358          "sizeof(" + RenderType( pot->operand, "" ) + ")" +
00359          after;
00360   else if( TreePtr<AlignOf> pot = dynamic_pointer_cast< AlignOf >(expression) )
00361     return before +
00362          "alignof(" + RenderType( pot->operand, "" ) + ")" +
00363          after;
00364   else if( TreePtr<NonCommutativeOperator> nco = dynamic_pointer_cast< NonCommutativeOperator >(expression) )
00365     return before +
00366          RenderOperator( nco, nco->operands ) +
00367          after;
00368   else if( TreePtr<CommutativeOperator> co = dynamic_pointer_cast< CommutativeOperator >(expression) )
00369   {
00370     Sequence<Expression> seq_operands;
00371     // Operands are in collection, so move them to a container
00372     FOREACH( TreePtr<Expression> o, co->operands )
00373       seq_operands.push_back( o );
00374     return before +
00375          RenderOperator( co, seq_operands ) +
00376          after;
00377   }
00378   else if( TreePtr<Call> c = dynamic_pointer_cast< Call >(expression) )
00379     return before +
00380          RenderCall( c ) +
00381          after;
00382   else if( TreePtr<New> n = dynamic_pointer_cast< New >(expression) )
00383     return before +
00384          (dynamic_pointer_cast<Global>(n->global) ? "::" : "") +
00385          "new(" + RenderOperandSequence( n->placement_arguments, ", ", false ) + ") " +
00386          RenderType( n->type, "" ) +
00387          (n->constructor_arguments.empty() ? "" : "(" + RenderOperandSequence( n->constructor_arguments, ", ", false ) + ")" ) +
00388          after;
00389   else if( TreePtr<Delete> d = dynamic_pointer_cast< Delete >(expression) )
00390     return before +
00391          (dynamic_pointer_cast<Global>(d->global) ? "::" : "") +
00392          "delete" +
00393          (dynamic_pointer_cast<DeleteArray>(d->array) ? "[]" : "") +
00394          " " + RenderExpression( d->pointer, true ) +
00395          after;
00396   else if( TreePtr<Lookup> a = dynamic_pointer_cast< Lookup >(expression) )
00397     return before +
00398          RenderExpression( a->base, true ) + "." +
00399          RenderScopedIdentifier( a->member ) +
00400          after;
00401   else if( TreePtr<Cast> c = dynamic_pointer_cast< Cast >(expression) )
00402     return before +
00403          "(" + RenderType( c->type, "" ) + ")" +
00404          RenderExpression( c->operand, false ) +
00405          after;
00406   else if( TreePtr<MakeRecord> ro = dynamic_pointer_cast< MakeRecord >(expression) )
00407     return before +
00408          RenderMakeRecord( ro ) +
00409          after;
00410   else if( TreePtr<Literal> l = dynamic_pointer_cast< Literal >(expression) )
00411     return before +
00412          RenderLiteral( l ) +
00413          after;
00414   else if( dynamic_pointer_cast< This >(expression) )
00415     return before +
00416          "this" +
00417          after;
00418   else if( TreePtr<DeltaCount> dc = dynamic_pointer_cast<DeltaCount>(expression) ) 
00419       return before +
00420              dc->GetToken() + "()" +
00421              after;
00422   else
00423     return ERROR_UNSUPPORTED(expression);
00424 }
00425 
00426 
00427 string Render::RenderMakeRecord( TreePtr<MakeRecord> ro )
00428 {
00429   string s;
00430 
00431   // Get the record
00432   TreePtr<TypeIdentifier> id = dynamic_pointer_cast<TypeIdentifier>(ro->type);
00433   ASSERT(id);
00434   TreePtr<Record> r = GetRecordDeclaration(program, id);
00435 
00436   s += "(";
00437   s += RenderType( ro->type, "" );
00438   s += "){ ";
00439   s += RenderMapInOrder( ro, r, ", ", false );
00440   s += " }";
00441   return s;
00442 }
00443 
00444 
00445 string Render::RenderMapInOrder( TreePtr<MapOperator> ro,
00446              TreePtr<Scope> r,
00447              string separator,
00448              bool separate_last )
00449 {
00450   string s;
00451 
00452   // Get a reference to the ordered list of members for this record from a backing list
00453   if( !backing_ordering.IsExist( r ) )
00454   {
00455       TRACE("Needed to see ")(*r)(" before ")(*ro)(" so map may not match; sorting now\n");     
00456       backing_ordering[r] = SortDecls( r->members, true );
00457   }
00458   ASSERT( backing_ordering.IsExist( r ) );
00459   Sequence<Declaration> &sd = backing_ordering[r];
00460   ASSERT( sd.size() == r->members.size() );
00461   bool first = true;
00462   FOREACH( TreePtr<Declaration> d, sd )
00463   {
00464     // We only care about instances...
00465     if( TreePtr<Instance> i = dynamic_pointer_cast<Instance>( d ) )
00466     {
00467       // ...and not function instances
00468       if( !dynamic_pointer_cast<Callable>( i->type ) )
00469       {
00470         // search init for matching member (TODO could avoid O(n^2) by exploiting the map)
00471         FOREACH( TreePtr<MapOperand> mi, ro->operands )
00472         {
00473           if( i->identifier == mi->identifier )
00474           {
00475             if( !first )
00476               s += separator;
00477             s += RenderExpression( mi->value );
00478             first = false;
00479           }
00480         }
00481       }
00482     }
00483     if( separate_last )
00484       s += separator;
00485   }
00486   return s;
00487 }
00488 
00489 
00490 string Render::RenderAccess( TreePtr<AccessSpec> current_access )
00491 {
00492   if( dynamic_pointer_cast<Public>( current_access ) )
00493     return "public";
00494   else if( dynamic_pointer_cast<Private>( current_access ) )
00495     return "private";
00496   else if( dynamic_pointer_cast<Protected>( current_access ) )
00497     return "protected";
00498   else
00499     return ERROR_UNKNOWN("current_access spec");
00500 }
00501 
00502 
00503 string Render::RenderStorage( TreePtr<Instance> st )
00504 {
00505   if( dynamic_pointer_cast<Program>( scope_stack.top() ) )
00506     return ""; // at top-level scope, everything is set to static, but don't actually output the word
00507   else if( dynamic_pointer_cast<Static>( st ) )
00508     return "static ";
00509   else if( dynamic_pointer_cast<Automatic>( st ) )
00510     return "auto ";
00511   else if( dynamic_pointer_cast<Temporary>( st ) )
00512     return "/*temp*/ ";
00513   else if( TreePtr<Field> no = dynamic_pointer_cast<Field>( st ) )
00514   {
00515     TreePtr<Virtuality> v = no->virt;
00516     if( dynamic_pointer_cast<Virtual>( v ) )
00517       return "virtual ";
00518     else if( dynamic_pointer_cast<NonVirtual>( v ) )
00519       return "";
00520     else
00521       return ERROR_UNKNOWN("virtualness");
00522   }
00523   else
00524     return ERROR_UNKNOWN("storage class");
00525 }
00526 
00527 
00528 void Render::ExtractInits( Sequence<Statement> &body, Sequence<Statement> &inits, Sequence<Statement> &remainder )
00529 {
00530   FOREACH( TreePtr<Statement> s, body )
00531   {
00532     if( TreePtr<Call> o = dynamic_pointer_cast< Call >(s) )
00533     {
00534       if( TypeOf::instance.IsConstructorCall( program, o ) )
00535       {
00536         inits.push_back(s);
00537         continue;
00538       }
00539     }
00540     remainder.push_back(s);
00541   }
00542 }
00543 
00544 
00545 string Render::RenderInstance( TreePtr<Instance> o, string sep, bool showtype,
00546              bool showstorage, bool showinit, bool showscope )
00547 {
00548   string s;
00549     string name;
00550     bool constant=false;
00551 
00552   ASSERT(o->type);
00553 
00554   if( TreePtr<Static> st = dynamic_pointer_cast<Static>(o) )
00555     if( dynamic_pointer_cast<Const>(st->constancy) )
00556       constant = true;
00557   if( TreePtr<Field> f = dynamic_pointer_cast<Field>(o) )
00558     if( dynamic_pointer_cast<Const>(f->constancy) )
00559             constant = true;
00560 
00561   if( showstorage )
00562   {
00563     s += RenderStorage(o);
00564   }
00565 
00566   if( showscope )
00567     name += RenderScopePrefix(o->identifier);
00568 
00569   TreePtr<Constructor> con = dynamic_pointer_cast<Constructor>(o->type);
00570   TreePtr<Destructor> de = dynamic_pointer_cast<Destructor>(o->type);
00571   if( con || de )
00572   {
00573     TreePtr<Record> rec = dynamic_pointer_cast<Record>( GetScope( program, o->identifier ) );
00574     ASSERT( rec );        
00575     name += (de ? "~" : "");
00576     name += RenderIdentifier(rec->identifier);
00577   }
00578   else
00579   {
00580     name += RenderIdentifier(o->identifier);
00581   }
00582 
00583   if( showtype )
00584     s += RenderType( o->type, name, constant );
00585   else
00586     s = name;
00587 
00588   bool callable = dynamic_pointer_cast<Callable>(o->type);
00589 
00590     // If object is really a module, bodge in a name as a constructor parameter
00591     // But not for fields - they need an init list, done in RenderDeclarationCollection()
00592   if( !dynamic_pointer_cast<Field>(o) )
00593       if( TreePtr<TypeIdentifier> tid = dynamic_pointer_cast<TypeIdentifier>(o->type) )
00594           if( TreePtr<Record> r = GetRecordDeclaration(program, tid) )
00595               if( dynamic_pointer_cast<Module>(r) )
00596               {
00597                   s += "(\"" + RenderIdentifier(o->identifier) + "\")" + sep;
00598                   return s;
00599               }
00600   
00601   if( !showinit || dynamic_pointer_cast<Uninitialised>(o->initialiser) )
00602   {
00603     // Don't render any initialiser
00604     s += sep;
00605   }
00606   else if( callable )
00607   {
00608     // Establish the scope of the function
00609     AutoPush< TreePtr<Scope> > cs( scope_stack, GetScope( program, o->identifier ) );
00610 
00611     // Put the contents of the body into a Compound-like form even if there's only one
00612     // Statement there - this is because we will wrangle with them later
00613     Sequence<Statement> code;
00614     Collection<Declaration> members;
00615     if( TreePtr<Compound> comp = dynamic_pointer_cast<Compound>(o->initialiser) )
00616     {
00617       members = comp->members;
00618       code = comp->statements;
00619     }
00620     else if( TreePtr<Statement> st = dynamic_pointer_cast<Statement>(o->initialiser) )
00621       code.push_back( st );
00622     else
00623       s += ERROR_UNSUPPORTED(o->initialiser);
00624 
00625     // Seperate the statements into constructor initialisers and "other stuff"
00626     Sequence<Statement> inits;
00627     Sequence<Statement> remainder;
00628     ExtractInits( code, inits, remainder );
00629 
00630     // Render the constructor initialisers if there are any
00631     if( !inits.empty() )
00632     {
00633       s += " : ";
00634       s += RenderSequence( inits, ", ", false, TreePtr<Public>(), true );
00635     }
00636 
00637     // Render the other stuff as a Compound so we always get {} in all cases
00638     TreePtr<Compound> r( new Compound );
00639     r->members = members;
00640     r->statements = remainder;
00641     s += "\n" + RenderStatement(r, "");
00642     }
00643   else
00644   {
00645     if( TreePtr<Expression> ei = dynamic_pointer_cast<Expression>( o->initialiser ) )
00646     {
00647       // Render expression with an assignment
00648       AutoPush< TreePtr<Scope> > cs( scope_stack, GetScope( program, o->identifier ) );
00649       s += " = " + RenderExpression(ei) + sep;
00650     }
00651     else
00652     {
00653       s += ERROR_UNSUPPORTED(o->initialiser);
00654     }
00655   }
00656 
00657   return s;
00658 }
00659 
00660 
00661 // Non-const static objects in records and functions 
00662 // get split into a part that goes into the record (main line of rendering) and
00663 // a part that goes separately (deferred_decls gets appended at the very end).
00664 // Do all functions, since SortDecls() ignores function bodies for dep analysis
00665 bool Render::ShouldSplitInstance( TreePtr<Instance> o )
00666 {
00667   bool isfunc = !!dynamic_pointer_cast<Callable>( o->type );
00668   bool isnumber = !!dynamic_pointer_cast<Numeric>( o->type );
00669     if( TreePtr<TypeIdentifier> ti = dynamic_pointer_cast<TypeIdentifier>(o->type) )
00670         if( dynamic_pointer_cast<Enum>( GetRecordDeclaration(program, ti) ) )
00671             isnumber = 1; // enum is like a number        
00672   bool split_var = false;
00673   if( TreePtr<Static> s = dynamic_pointer_cast<Static>(o) )
00674     if( dynamic_pointer_cast<NonConst>(s->constancy) || !isnumber )
00675       split_var = true;
00676   return ( dynamic_pointer_cast<Record>( scope_stack.top() ) &&
00677          split_var ) || 
00678          isfunc;
00679 }
00680 
00681 
00682 string Render::RenderDeclaration( TreePtr<Declaration> declaration,
00683                string sep, TreePtr<AccessSpec> *current_access,
00684               bool showtype, bool force_incomplete )
00685 {
00686   TRACE();
00687   string s;
00688 
00689   TreePtr<AccessSpec> this_access;
00690 
00691   // Decide access spec for this declaration (explicit if instance, otherwise force to Public)
00692   if( TreePtr<Field> f = dynamic_pointer_cast<Field>(declaration) )
00693     this_access = f->access;
00694   else
00695     this_access = MakeTreePtr<Public>();
00696 
00697   // Now decide whether we actually need to render an access spec (ie has it changed?)
00698   if( current_access && // NULL means dont ever render access specs
00699     typeid(*this_access) != typeid(**current_access) ) // current_access spec must have changed
00700   {
00701     s += RenderAccess( this_access ) + ":\n";
00702     *current_access = this_access;
00703   }
00704 
00705   if( TreePtr<Instance> o = dynamic_pointer_cast<Instance>(declaration) )
00706   {
00707     if( ShouldSplitInstance(o) )
00708     {
00709       s += RenderInstance( o, sep, showtype, showtype, false, false );
00710       {
00711         AutoPush< TreePtr<Scope> > cs( scope_stack, program );
00712         deferred_decls += string("\n") + RenderInstance( o, sep, showtype, false, true, true );
00713       }
00714     }
00715     else
00716     {
00717       // Otherwise, render everything directly using the default settings
00718       s += RenderInstance( o, sep, showtype, showtype, true, false );
00719     }
00720   }
00721   else if( TreePtr<Typedef> t = dynamic_pointer_cast< Typedef >(declaration) )
00722   {
00723     s += "typedef " + RenderType( t->type, RenderIdentifier(t->identifier) ) + sep;
00724   }
00725   else if( TreePtr<Record> r = dynamic_pointer_cast< Record >(declaration) )
00726   {
00727     TreePtr<AccessSpec> a;
00728     bool showtype=true;
00729     string sep2=";\n";
00730     shared_ptr<SCNamedRecord> scr = dynamic_pointer_cast< SCNamedRecord >(r);
00731     if( dynamic_pointer_cast< Class >(r) || scr )
00732     {
00733       s += "class";
00734       a = TreePtr<Private>(new Private);
00735     }
00736     else if( dynamic_pointer_cast< Struct >(r) )
00737     {
00738       s += "struct";
00739       a = TreePtr<Public>(new Public);
00740     }
00741     else if( dynamic_pointer_cast< Union >(r) )
00742     {
00743       s += "union";
00744       a = TreePtr<Public>(new Public);
00745     }
00746     else if( dynamic_pointer_cast< Enum >(r) )
00747     {
00748       s += "enum";
00749       a = TreePtr<Public>(new Public);
00750       sep2 = ",\n";
00751       showtype = false;
00752     }
00753     else
00754       return ERROR_UNSUPPORTED(declaration);
00755 
00756     // Name of the record
00757     s += " " + RenderIdentifier(r->identifier);
00758 
00759     if( !force_incomplete )
00760     {
00761       // Base classes
00762       if( TreePtr<InheritanceRecord> ir = dynamic_pointer_cast< InheritanceRecord >(declaration) )
00763       {
00764         if( !ir->bases.empty() || scr )
00765         {
00766           s += " : ";
00767           bool first=true;
00768             if( scr )
00769             {
00770                 first = false;
00771                 s += "public " + scr->GetToken();
00772             }
00773           FOREACH( TreePtr<Base> b, ir->bases )
00774           {
00775             if( !first )
00776               s += ", ";
00777             first=false;
00778             ASSERT( b );
00779             s += RenderAccess(b->access) + " " /*+ RenderStorage(b->storage)*/ + RenderIdentifier(b->record);
00780           }
00781         }
00782       }
00783 
00784       // Contents
00785       AutoPush< TreePtr<Scope> > cs( scope_stack, r );
00786       s += "\n{\n" +
00787          RenderDeclarationCollection( r, sep2, true, a, showtype ) +
00788          "}";
00789     }
00790 
00791     s += ";\n";
00792   }
00793   else if( TreePtr<Label> l = dynamic_pointer_cast<Label>(declaration) )
00794     return RenderIdentifier(l->identifier) + ":;\n"; // need ; after a label in case last in compound block
00795   else
00796     s += ERROR_UNSUPPORTED(declaration);
00797 
00798     TRACE();
00799   return s;
00800 }
00801 
00802 
00803 string Render::RenderStatement( TreePtr<Statement> statement, string sep )
00804 {
00805   TRACE();
00806   if( !statement )
00807     return sep;
00808   //printf( "%s %d things\n", typeid(*statement).name(), statement->Itemise().size() );
00809   if( TreePtr<Declaration> d = dynamic_pointer_cast< Declaration >(statement) )
00810     return RenderDeclaration( d, sep );
00811   else if( TreePtr<Compound> c = dynamic_pointer_cast< Compound >(statement) )
00812   {
00813     AutoPush< TreePtr<Scope> > cs( scope_stack, c );
00814     string s = "{\n";
00815     s += RenderDeclarationCollection( c, ";\n", true ); // Must do this first to populate backing list
00816     s += RenderSequence( c->statements, ";\n", true );
00817     return s + "}\n";
00818   }
00819   else if( TreePtr<Expression> e = dynamic_pointer_cast< Expression >(statement) )
00820     return RenderExpression(e) + sep;
00821   else if( TreePtr<Return> es = dynamic_pointer_cast<Return>(statement) )
00822     return "return " + RenderExpression(es->return_value) + sep;
00823   else if( TreePtr<Goto> g = dynamic_pointer_cast<Goto>(statement) )
00824   {
00825     if( TreePtr<SpecificLabelIdentifier> li = dynamic_pointer_cast< SpecificLabelIdentifier >(g->destination) )
00826       return "goto " + RenderIdentifier(li) + sep;  // regular goto
00827     else
00828       return "goto *(" + RenderExpression(g->destination) + ")" + sep; // goto-a-variable (GCC extension)
00829   }
00830   else if( TreePtr<If> i = dynamic_pointer_cast<If>(statement) )
00831   {
00832     string s;
00833     s += "if( " + RenderExpression(i->condition) + " )\n";
00834     bool sub_if = !!dynamic_pointer_cast<If>(i->body);
00835     if( sub_if )
00836        s += "{\n"; // Note: braces there to clarify else binding eg if(a) if(b) foo; else how_do_i_bind;
00837       s += RenderStatement(i->body, ";\n");
00838     if( sub_if )
00839        s += "}\n";
00840     if( !dynamic_pointer_cast<Nop>(i->else_body) )  // Nop means no else clause
00841       s += "else\n" +
00842          RenderStatement(i->else_body, ";\n");
00843     return s;
00844   }
00845   else if( TreePtr<While> w = dynamic_pointer_cast<While>(statement) )
00846     return "while( " + RenderExpression(w->condition) + " )\n" +
00847          RenderStatement(w->body, ";\n");
00848   else if( TreePtr<Do> d = dynamic_pointer_cast<Do>(statement) )
00849     return "do\n" +
00850          RenderStatement(d->body, ";\n") +
00851          "while( " + RenderExpression(d->condition) + " )" + sep;
00852   else if( TreePtr<For> f = dynamic_pointer_cast<For>(statement) )
00853     return "for( " + RenderStatement(f->initialisation, "") + "; " + RenderExpression(f->condition) + "; "+ RenderStatement(f->increment, "") + " )\n" +
00854          RenderStatement(f->body, ";\n");
00855   else if( TreePtr<Switch> s = dynamic_pointer_cast<Switch>(statement) )
00856     return "switch( " + RenderExpression(s->condition) + " )\n" +
00857          RenderStatement(s->body, ";\n");
00858   else if( TreePtr<Case> c = dynamic_pointer_cast<Case>(statement) )
00859     return "case " + RenderExpression(c->value) + ":;\n";
00860   else if( TreePtr<RangeCase> rc = dynamic_pointer_cast<RangeCase>(statement) )
00861     return "case " + RenderExpression(rc->value_lo) + " ... " + RenderExpression(rc->value_hi) + ":\n";
00862   else if( dynamic_pointer_cast<Default>(statement) )
00863     return "default:;\n";
00864   else if( dynamic_pointer_cast<Continue>(statement) )
00865     return "continue" + sep;
00866   else if( dynamic_pointer_cast<Break>(statement) )
00867     return "break" + sep;
00868   else if( dynamic_pointer_cast<Nop>(statement) )
00869     return sep;
00870   else if( TreePtr<WaitDynamic> c = dynamic_pointer_cast<WaitDynamic>(statement) ) 
00871       return c->GetToken() + "( " + RenderExpression(c->event) + " );\n";
00872   else if( TreePtr<WaitStatic> c = dynamic_pointer_cast<WaitStatic>(statement) ) 
00873       return c->GetToken() + "();\n";
00874   else if( TreePtr<WaitDelta> c = dynamic_pointer_cast<WaitDelta>(statement) )
00875       return c->GetToken() + "(SC_ZERO_TIME);\n";
00876   else if( TreePtr<NextTriggerDynamic> c = dynamic_pointer_cast<NextTriggerDynamic>(statement) ) 
00877       return c->GetToken() + "( " + RenderExpression(c->event) + " );\n";
00878   else if( TreePtr<NextTriggerStatic> c = dynamic_pointer_cast<NextTriggerStatic>(statement) ) 
00879       return c->GetToken() + "();\n";
00880   else if( TreePtr<NextTriggerDelta> c = dynamic_pointer_cast<NextTriggerDelta>(statement) ) 
00881       return c->GetToken() + "(SC_ZERO_TIME);\n";
00882   else if( TreePtr<TerminationFunction> tf = dynamic_pointer_cast<TerminationFunction>(statement) )
00883     return tf->GetToken() + "( " + RenderExpression(tf->code) + " );\n";
00884   else if( TreePtr<NotifyImmediate> n = dynamic_pointer_cast<NotifyImmediate>(statement) )
00885     return RenderExpression( n->event, true ) + "." + n->GetToken() + "();\n";
00886   else if( TreePtr<NotifyDelta> n = dynamic_pointer_cast<NotifyDelta>(statement) )
00887     return RenderExpression( n->event, true ) + "." + n->GetToken() + "(SC_ZERO_TIME);\n";
00888     else
00889     return ERROR_UNSUPPORTED(statement);
00890 }
00891 
00892 
00893 template< class ELEMENT >
00894 string Render::RenderSequence( Sequence<ELEMENT> spe,
00895              string separator,
00896              bool separate_last,
00897              TreePtr<AccessSpec> init_access,
00898              bool showtype )
00899 {
00900   TRACE();
00901   string s;
00902   for( int i=0; i<spe.size(); i++ )
00903   {
00904     TRACE("%d %p\n", i, &i);
00905     string sep = (separate_last || i+1<spe.size()) ? separator : "";
00906     TreePtr<ELEMENT> pe = spe[i];
00907     if( TreePtr<Declaration> d = dynamic_pointer_cast< Declaration >(pe) )
00908       s += RenderDeclaration( d, sep, init_access ? &init_access : NULL, showtype );
00909     else if( TreePtr<Statement> st = dynamic_pointer_cast< Statement >(pe) )
00910       s += RenderStatement( st, sep );
00911     else
00912       s += ERROR_UNSUPPORTED(pe);
00913   }
00914   return s;
00915 }
00916 
00917 
00918 string Render::RenderOperandSequence( Sequence<Expression> spe,
00919                 string separator,
00920                 bool separate_last )
00921 {
00922   TRACE();
00923   string s;
00924   for( int i=0; i<spe.size(); i++ )
00925   {
00926     TRACE("%d %p\n", i, &i);
00927     string sep = (separate_last || i+1<spe.size()) ? separator : "";
00928     TreePtr<Expression> pe = spe[i];
00929     s += RenderExpression( pe ) + sep;
00930   }
00931   return s;
00932 }
00933 
00934 
00935 string Render::RenderModuleCtor( TreePtr<Module> m,
00936                                  TreePtr<AccessSpec> *access )
00937 {
00938     string s;
00939     
00940     // SystemC module, we must produce a constructor in SC style, do this as inline
00941     if( !dynamic_pointer_cast<Public>(*access) )
00942     {
00943         s += "public:\n";
00944         *access = MakeTreePtr<Public>();// note that we left the access as public
00945     }
00946     s += "SC_CTOR( " + RenderIdentifier( m->identifier ) + " )";
00947     int first = true;             
00948     FOREACH( TreePtr<Declaration> pd, m->members )
00949     {
00950         // Bodge an init list that names any fields we have that are modules
00951         // and initialises any fields with initialisers
00952         if( TreePtr<Field> f = dynamic_pointer_cast<Field>(pd) )
00953             if( TreePtr<TypeIdentifier> tid = dynamic_pointer_cast<TypeIdentifier>(f->type) )
00954                 if( TreePtr<Record> r = GetRecordDeclaration(program, tid) )
00955                     if( dynamic_pointer_cast<Module>(r) )
00956                     {
00957                         if( first )
00958                             s += " :";
00959                         else
00960                             s += ",";
00961                         string ids = RenderIdentifier(f->identifier);                           
00962                         s += "\n" + ids + "(\"" + ids + "\")";
00963                         first = false;
00964                     }   
00965                     
00966         // TODO figure out what this does - it seems to look for function instances and then try to 
00967         // init them as if they wew initable and their body was an expression.
00968         if( TreePtr<Field> i = dynamic_pointer_cast<Field>(pd) )
00969         {
00970             TRACE("Got ")(*i)(" init is ")(*(i->initialiser))(" %d %d\n", 
00971                     (int)(bool)dynamic_pointer_cast<Callable>(i->type),
00972                     (int)(bool)dynamic_pointer_cast<Uninitialised>(i->initialiser) );                   
00973         
00974             if( !dynamic_pointer_cast<Callable>(i->type) && !dynamic_pointer_cast<Uninitialised>(i->initialiser) )
00975             {                   
00976                 if( first )
00977                     s += " :";
00978                 else
00979                     s += ",";
00980                 string ids = RenderIdentifier(i->identifier);                           
00981                 string inits = RenderExpression(i->initialiser);
00982                 s += "\n" + ids + "(" + inits + ")";
00983                 i->initialiser = MakeTreePtr<Uninitialised>(); // TODO naughty, changing the tree
00984                 first = false;                 
00985             }
00986         }                      
00987     }    
00988     s += "\n{\n";
00989     FOREACH( TreePtr<Declaration> pd, m->members )
00990         if( TreePtr<Field> f = dynamic_pointer_cast<Field>(pd) )
00991             if( TreePtr<Process> r = dynamic_pointer_cast<Process>(f->type) )
00992                 s += r->GetToken() + "(" + RenderIdentifier( f->identifier ) + ");\n";
00993     s += "}\n";
00994     
00995     return s;
00996 }
00997 
00998 
00999 string Render::RenderDeclarationCollection( TreePtr<Scope> sd,
01000                   string separator,
01001                   bool separate_last,
01002                   TreePtr<AccessSpec> init_access,
01003                   bool showtype )
01004 {
01005   TRACE();
01006 
01007   // Uncomment one of these to stress the sorter
01008   //sd = ReverseDecls( sd );
01009   //sd = JumbleDecls( sd );
01010 
01011   Sequence<Declaration> sorted = SortDecls( sd->members, true );
01012   backing_ordering[sd] = sorted;
01013 
01014   // Emit an incomplete for each record
01015     string s;
01016   FOREACH( TreePtr<Declaration> pd, sorted ) //for( int i=0; i<sorted.size(); i++ )
01017     if( TreePtr<Record> r = dynamic_pointer_cast<Record>(pd) ) // is a record
01018       if( !dynamic_pointer_cast<Enum>(r) ) // but not an enum
01019         s += RenderDeclaration( r, separator, init_access ? &init_access : NULL, showtype, true );
01020 
01021     // For SystemC modules, we generate a constructor based on the other decls in
01022     // the module. Nothing goes in the Inferno tree for a module constructor, since
01023     // it is an elaboration mechanism, not funcitonal.
01024     if( TreePtr<Module> m = dynamic_pointer_cast<Module>(sd) )
01025         s += RenderModuleCtor( m, &init_access );
01026 
01027     // Emit the actual declarations, sorted for dependencies
01028     s += RenderSequence( sorted, separator, separate_last, init_access, showtype );
01029   TRACE();
01030   return s;
01031 }
01032