Inferno  0.2
state_out.cpp
Go to the documentation of this file.
00001 
00002 #include "steps/state_out.hpp"
00003 #include "tree/cpptree.hpp"
00004 #include "tree/sctree.hpp"
00005 #include "common/common.hpp"
00006 #include "sr/soft_patterns.hpp"
00007 #include "tree/typeof.hpp"
00008 #include "tree/misc.hpp"
00009 #include "inferno_patterns.hpp"
00010 
00011  
00012 using namespace CPPTree;
00013 using namespace SCTree;
00014 using namespace Steps;
00015  
00016 // TOOD go through step impls and use inline decls of leaf nodes, to reduce wordiness
00017 
00018 GotoAfterWait::GotoAfterWait()
00019 {
00020     // This step could have been tricky: we'd have needed 3 cases:
00021     // 1. { *, wait, !goto, * }
00022     // 2. { *, wait } // not covered by previous case because !goto needs to match a statement
00023     // 3. eg if() wait // not directly inside a compound block 
00024     // we use the but-not pattern, in which we principally search for anything->wait, but exclude
00025     // the only case that needs excluding which is a compound like in case 1 above but without
00026     // notting the goto. Cases 2 and 3 work because the excluded compound does not match.
00027     // Overall, a good example of but-not
00028     MakeTreePtr<Compound> sx_comp, r_comp;
00029     MakeTreePtr< Star<Declaration> > sx_decls;
00030     MakeTreePtr< Star<Statement> > sx_pre, sx_post;    
00031     MakeTreePtr<Wait> wait;
00032     MakeTreePtr< NotMatch<Statement> > notmatch;
00033     MakeTreePtr< MatchAll<Statement> > all;
00034     MakeTreePtr< AnyNode<Statement> > anynode;
00035     MakeTreePtr< Overlay<Statement> > over;
00036     MakeTreePtr<Goto> sx_goto, r_goto;
00037     MakeTreePtr<Label> r_label;
00038     MakeTreePtr<BuildLabelIdentifier> r_labelid("YIELD");
00039             
00040     all->patterns = (anynode, notmatch);
00041     anynode->terminus = over;
00042     over->through = wait;
00043     notmatch->pattern = sx_comp;
00044     sx_comp->members = sx_decls;
00045     sx_comp->statements = (sx_pre, wait, sx_goto, sx_post);    
00046     
00047     over->overlay = r_comp;
00048     //r_comp->members = ();
00049     r_comp->statements = (wait, r_goto, r_label);
00050     r_goto->destination = r_labelid;
00051     r_label->identifier = r_labelid;
00052     
00053     Configure( all );
00054 }
00055 /*
00056 GotoAfterWait::GotoAfterWait()
00057 {
00058     // TODO will miss a yield at the very end
00059     MakeTreePtr<Compound> s_comp, r_comp;
00060     MakeTreePtr< Star<Declaration> > decls;
00061     MakeTreePtr< Star<Statement> > pre, post;
00062     MakeTreePtr<Wait> wait;
00063     MakeTreePtr< NotMatch<Statement> > notmatch;
00064     MakeTreePtr<Goto> sx_goto, r_goto;
00065     MakeTreePtr<Label> r_label;
00066     MakeTreePtr<BuildLabelIdentifier> r_labelid("YIELD");
00067         
00068     s_comp->members = (decls);
00069     s_comp->statements = (pre, wait, notmatch, post);
00070     notmatch->pattern = sx_goto;
00071     
00072     r_comp->members = (decls);
00073     r_comp->statements = (pre, wait, r_goto, r_label, notmatch, post);
00074     r_goto->destination = r_labelid;
00075     r_label->identifier = r_labelid;
00076     
00077     Configure( s_comp, r_comp );
00078 }
00079 */
00080 
00081 NormaliseConditionalGotos::NormaliseConditionalGotos()
00082 {
00083     MakeTreePtr< If > iif;      
00084     MakeTreePtr< Expression > cond;      
00085     MakeTreePtr< Compound > s_comp, r_comp, sx_comp;  
00086     MakeTreePtr< Goto > then_goto, s_else_goto, r_goto, sx_goto;// TODO sx_goto could be any departure, like Return or Cease etc
00087     MakeTreePtr< Star<Declaration> > decls;
00088     MakeTreePtr< Star<Statement> > pre, post, sx_post;
00089     MakeTreePtr< Multiplexor > mult;
00090     MakeTreePtr< Label > label;    
00091     MakeTreePtr< BuildLabelIdentifier > label_id("PROCEED");
00092     MakeTreePtr< MatchAll<Statement> > s_all;
00093     MakeTreePtr< NotMatch<Statement> > sx_not;    
00094     
00095     s_all->patterns = (s_comp, sx_not);
00096     sx_not->pattern = sx_comp;    
00097     iif->condition = cond;
00098     iif->body = then_goto;
00099     iif->else_body = MakeTreePtr<Nop>(); 
00100     s_comp->members = ( decls );    
00101     s_comp->statements = ( pre, iif, post );    
00102     sx_comp->statements = ( pre, iif, sx_goto, sx_post );    
00103 
00104     label->identifier = label_id;
00105     r_goto->destination = label_id;
00106     r_comp->members = ( decls );
00107     r_comp->statements = ( pre, iif, r_goto, label, post );
00108     
00109     Configure( s_all, r_comp );
00110 }
00111 
00112 
00113 CompactGotos::CompactGotos()
00114 {
00115     MakeTreePtr< If > s_if;      
00116     MakeTreePtr< Expression > cond;      
00117     MakeTreePtr< Compound > s_comp, r_comp;  
00118     MakeTreePtr< Goto > s_then_goto, s_else_goto, r_goto;
00119     MakeTreePtr< Star<Declaration> > decls;
00120     MakeTreePtr< Star<Statement> > pre, post;
00121     MakeTreePtr< Multiplexor > mult;
00122     
00123     s_then_goto->destination = MakeTreePtr<Expression>();    
00124     s_else_goto->destination = MakeTreePtr<Expression>();
00125     s_if->condition = cond;
00126     s_if->body = s_then_goto;
00127     s_if->else_body = MakeTreePtr<Nop>(); // standed conditional branch has no else clause - our "else" is the next statement
00128     s_comp->members = ( decls );    
00129     s_comp->statements = ( pre, s_if, s_else_goto, post );    
00130 
00131     mult->operands = (cond, s_then_goto->destination, s_else_goto->destination);
00132     r_goto->destination = mult;
00133     r_comp->statements = ( pre, r_goto, post );
00134     r_comp->members = ( decls );    
00135         
00136     Configure( s_comp, r_comp );
00137 }
00138 
00139 
00140 AddGotoBeforeLabel::AddGotoBeforeLabel() // TODO really slow!!11
00141 {
00142     MakeTreePtr< If > s_if;      
00143     MakeTreePtr< Expression > cond;      
00144     MakeTreePtr< Compound > s_comp, r_comp, sx_comp;  
00145     MakeTreePtr< Goto > r_goto;
00146     MakeTreePtr< Star<Declaration> > decls;
00147     MakeTreePtr< Star<Statement> > pre, post, sx_pre, sx_post;
00148     MakeTreePtr< Multiplexor > mult;
00149     MakeTreePtr< Label > label;    
00150     MakeTreePtr< LabelIdentifier > label_id;
00151     MakeTreePtr< MatchAll<Compound> > s_all;
00152     MakeTreePtr< NotMatch<Compound> > s_not;
00153         
00154     s_all->patterns = (s_comp, s_not);
00155     s_not->pattern = sx_comp;
00156     s_comp->members = ( decls );    
00157     s_comp->statements = ( pre, label, post );    
00158     label->identifier = label_id;
00159     sx_comp->members = ( decls );    
00160     sx_comp->statements = ( sx_pre, MakeTreePtr<Goto>(), label, sx_post );
00161 
00162     r_comp->members = ( decls );    
00163     r_comp->statements = ( pre, r_goto, label, post );
00164     r_goto->destination = label_id;
00165 
00166     Configure( s_all, r_comp );
00167 }
00168 
00169 
00170 static TreePtr<Statement> MakeResetAssignmentPattern()
00171 {
00172     MakeTreePtr<Assign> ass;
00173     MakeTreePtr< TransformOf<InstanceIdentifier> > decl( &GetDeclaration::instance );
00174     decl->pattern = MakeTreePtr<LocalVariable>();
00175     ass->operands = (decl, MakeTreePtr<Literal>());    
00176     return ass;
00177 }
00178 
00179 
00180 EnsureBootstrap::EnsureBootstrap()
00181 {
00182     MakeTreePtr<Instance> fn;
00183     MakeTreePtr<Thread> thread;
00184     MakeTreePtr< Overlay<Compound> > over;
00185     MakeTreePtr< MatchAll<Compound> > s_all;
00186     MakeTreePtr< NotMatch<Compound> > s_not;    
00187     MakeTreePtr<Compound> s_body, r_body, sx_body;
00188     MakeTreePtr< Star<Declaration> > decls;
00189     MakeTreePtr< Star<Statement> > pre, sx_pre, post;
00190     MakeTreePtr<Goto> r_goto;
00191     MakeTreePtr<Label> r_label;    
00192     MakeTreePtr<BuildLabelIdentifier> r_labelid("BOOTSTRAP");
00193     MakeTreePtr< NotMatch<Statement> > stop;
00194     MakeTreePtr<Goto> sx_goto;
00195         
00196     fn->type = thread;
00197     fn->initialiser = over;
00198     over->through = s_all;
00199     s_all->patterns = (s_not, s_body);
00200     s_not->pattern = sx_body;
00201     // only exclude if there is a goto; a goto to anywhere will suffice to boot the state machine
00202     sx_body->members = (MakeTreePtr< Star<Declaration> >());
00203     sx_body->statements = (sx_pre, sx_goto, MakeTreePtr< Star<Statement> >());     
00204     sx_pre->pattern = MakeResetAssignmentPattern();
00205     sx_goto->destination = MakeTreePtr<LabelIdentifier>(); // must be a hard goto to exclude - otherwise might 
00206                                                            // have calculations in it which is no good for bootstrapping
00207     over->overlay = r_body;
00208     s_body->members = decls;
00209     s_body->statements = (pre, stop, post);
00210     pre->pattern = MakeResetAssignmentPattern();    
00211     stop->pattern = MakeResetAssignmentPattern();
00212     r_label->identifier = r_labelid;
00213     r_goto->destination = r_labelid;
00214     r_body->members = decls;
00215     r_body->statements = (pre, r_goto, r_label, stop, post);    
00216 
00217     Configure( fn );
00218 }
00219 
00220 
00221 AddStateLabelVar::AddStateLabelVar()
00222 {
00223     MakeTreePtr<Compound> s_comp, r_comp, lr_compound;
00224     MakeTreePtr< Star<Declaration> > decls;
00225     MakeTreePtr< Star<Statement> > pre, post;
00226     MakeTreePtr<Goto> ls_goto, lr_goto, sx_goto;
00227     MakeTreePtr<Assign> lr_assign;
00228     MakeTreePtr<Automatic> state_var;
00229     MakeTreePtr< NotMatch<Expression> > sx_not, lsx_not;
00230     MakeTreePtr< BuildInstanceIdentifier > state_var_id("state");
00231     
00232     ls_goto->destination = lsx_not;
00233     lsx_not->pattern = state_var_id; //  MakeTreePtr<InstanceIdentifier>();
00234     
00235     lr_compound->statements = (lr_assign, lr_goto);
00236     lr_assign->operands = (state_var_id, lsx_not);
00237     lr_goto->destination = state_var_id;
00238             
00239     MakeTreePtr< SlaveSearchReplace<Statement> > r_slave( r_comp, ls_goto, lr_compound );
00240      
00241     s_comp->members = (decls);
00242     s_comp->statements = (pre, sx_goto, post); 
00243     sx_goto->destination = sx_not;
00244     sx_not->pattern = MakeTreePtr<InstanceIdentifier>();
00245         
00246     r_comp->members = (state_var, decls);
00247     r_comp->statements = (pre, sx_goto, post); 
00248     state_var->identifier = state_var_id;
00249     state_var->type = MakeTreePtr<Labeley>();    
00250     state_var->initialiser = MakeTreePtr<Uninitialised>();
00251 
00252     Configure( s_comp, r_slave );
00253 }
00254 
00255 
00256 EnsureSuperLoop::EnsureSuperLoop()
00257 {   
00258     MakeTreePtr<Instance> fn;
00259     MakeTreePtr<Thread> thread;
00260     MakeTreePtr< Overlay<Compound> > over;
00261     MakeTreePtr< MatchAll<Compound> > s_all;
00262     MakeTreePtr< NotMatch<Statement> > sx_not, s_limit;    
00263     MakeTreePtr< Stuff<Compound> > sx_stuff;
00264     MakeTreePtr< Goto > sx_goto, first_goto;
00265     MakeTreePtr<Compound> s_body, r_body, r_loop_body;
00266     MakeTreePtr< Star<Statement> > pre, post;    
00267     MakeTreePtr< Star<Declaration> > decls;    
00268     MakeTreePtr<Do> r_loop;
00269         
00270     fn->type = thread;
00271     fn->initialiser = over;
00272     over->through = s_all;
00273     s_all->patterns = (sx_stuff, s_body);
00274     sx_stuff->terminus = sx_goto;
00275     sx_stuff->recurse_restriction = sx_not;
00276     sx_not->pattern = MakeTreePtr<Do>();
00277     s_body->members = (decls);
00278     s_body->statements = (pre, first_goto, post);
00279     pre->pattern = s_limit;
00280     s_limit->pattern = MakeTreePtr<Goto>();
00281     
00282     over->overlay = r_body;
00283     r_body->members = (decls);
00284     r_body->statements = (pre, r_loop);
00285     r_loop->body = r_loop_body;
00286     r_loop_body->statements = (first_goto, post);
00287     r_loop->condition = MakeTreePtr<True>();
00288 
00289     Configure( fn );
00290 }
00291 
00292 ShareGotos::ShareGotos()
00293 {   
00294     MakeTreePtr<Do> loop;
00295     MakeTreePtr< Overlay<Compound> > over;
00296     MakeTreePtr<Compound> s_body, r_body;
00297     MakeTreePtr< Star<Declaration> > decls;    
00298     MakeTreePtr< Star<Statement> > pre, post;    
00299     MakeTreePtr< Goto > first_goto, r_goto;
00300     MakeTreePtr<Label> r_label;    
00301     MakeTreePtr<BuildLabelIdentifier> r_labelid("ITERATE");
00302                     
00303     loop->body = over;
00304     loop->condition = MakeTreePtr<SpecificInteger>(1);
00305     over->through = s_body;
00306     s_body->members = (decls);
00307     s_body->statements = (first_goto, pre, first_goto, post);    
00308 
00309     over->overlay = r_body;
00310     r_body->members = (decls);
00311     r_body->statements = (first_goto, pre, r_goto, post, r_label);    
00312     r_label->identifier = r_labelid;
00313     r_goto->destination = r_labelid;
00314 
00315     Configure( loop );
00316 }
00317 
00318 
00319 // Something to get the size of the Collection matched by a Star as a SpecificInteger
00320 struct BuildContainerSize : SoftReplacePattern,
00321                             Special<Integer>
00322 {
00323     SPECIAL_NODE_FUNCTIONS
00324     shared_ptr< StarBase > container;
00325 private:
00326     virtual TreePtr<Node> DuplicateSubtree( const CompareReplace *sr )
00327     {
00328         ASSERT( container );
00329       TreePtr<Node> n = sr->BuildReplace( container );
00330       ASSERT( n );
00331       ContainerInterface *n_container = dynamic_cast<ContainerInterface *>(n.get());
00332       ASSERT( n_container );
00333       int size = n_container->size();
00334       TreePtr<SpecificInteger> si = MakeTreePtr<SpecificInteger>(size);
00335       return si;
00336     }                                                   
00337 }; 
00338 
00339 
00340 struct IsLabelReached : SoftSearchPattern, Special<LabelIdentifier>
00341 {
00342   SPECIAL_NODE_FUNCTIONS  
00343   virtual void FlushCache()
00344   {
00345       cache.clear();
00346   }
00347   // x is nominally the label id, at the position of this node
00348   // y is nominally the goto expression, coupled in
00349     virtual bool DecidedCompare( const CompareReplace *sr,
00350                                  const TreePtrInterface &xx,
00351                                    bool can_key,
00352                                    Conjecture &conj ) 
00353     {
00354         INDENT;
00355         ASSERT( pattern );
00356         if( can_key )
00357             return true; // Want to wait for our pattern to get keyed before we do the search, so wait for restricting pass
00358         TreePtr<Node> n = sr->coupling_keys.GetCoupled( pattern ); // TODO a templates version that returns same type as pattern, so we don't need to convert here?
00359         if( !n )
00360             n = pattern;
00361         TreePtr<Expression> y = dynamic_pointer_cast<Expression>( n );
00362         ASSERT( y )("IsLabelReached saw pattern coupled to ")(*n)(" but an Expression is needed\n"); 
00363         ASSERT( xx );
00364         TreePtr<Node> nxx = xx;
00365         TreePtr<LabelIdentifier> x = dynamic_pointer_cast<LabelIdentifier>( nxx );
00366         ASSERT( x )("IsLabelReached at ")(*xx)(" but is of type LabelIdentifier\n"); 
00367         TRACE("Can label id ")(*x)(" reach expression ")(*y)("?\n");
00368 
00369         Set< TreePtr<InstanceIdentifier> > uf;        
00370         bool r = CanReachExpr(sr, &uf, x, y);
00371         TRACE("I reakon ")(*x)(r?" does ":" does not ")("reach ")(*y)("\n"); 
00372         return r;
00373     }                 
00374     TreePtr<Expression> pattern;           
00375            
00376 private:
00377     bool CanReachExpr( const CompareReplace *sr,
00378                          Set< TreePtr<InstanceIdentifier> > *f,
00379                          TreePtr<LabelIdentifier> x, 
00380                          TreePtr<Expression> y ) // y is expression. Can it yield label x?
00381     {
00382         INDENT;
00383         bool r = false;
00384         if( TreePtr<LabelIdentifier> liy = dynamic_pointer_cast<LabelIdentifier>(y) )
00385             r = liy->IsLocalMatch( x.get() ); // y is x, so yes
00386         else if( TreePtr<InstanceIdentifier> iiy = dynamic_pointer_cast<InstanceIdentifier>( y ) )
00387             r = CanReachVar( sr, f, x, iiy );
00388         else if( TreePtr<Ternop> ty = dynamic_pointer_cast<Ternop>( y ) )
00389             r = CanReachExpr(sr, f, x, ty->operands[1]) ||
00390                 CanReachExpr(sr, f, x, ty->operands[2]); // only the choices, not the condition
00391         else if( TreePtr<Comma> cy = dynamic_pointer_cast<Comma>( y ) )
00392             r = CanReachExpr(sr, f, x, ty->operands[1]); // second operand
00393         else if( TreePtr<Subscript> sy = dynamic_pointer_cast<Subscript>( y ) ) // subscript as r-value
00394             r = CanReachExpr(sr, f, x, sy->operands[0]); // first operand
00395         else if( dynamic_pointer_cast<Dereference>( y ) )
00396             ASSERTFAIL("IsLabelReached used on expression that is read from memory, cannot figure out the answer\n");
00397             
00398         TRACE("I reakon ")(*x)(" at %p", x.get())(r?" does ":" does not ")("reach ")(*y)("\n"); 
00399         return r;        
00400     }    
00401     
00402     bool CanReachVar( const CompareReplace *sr,
00403                         Set< TreePtr<InstanceIdentifier> > *f,
00404                         TreePtr<LabelIdentifier> x, 
00405                         TreePtr<InstanceIdentifier> y ) // y is instance identifier. Can expression x be assigned to it?
00406     {
00407         INDENT;
00408         Reaching rr( x, y );
00409         if( cache.IsExist(rr) )
00410         {
00411             TRACE("cache hit yeah yeah\n");
00412             return cache[rr];
00413         }
00414         bool r = false;        
00415         Walk e( *sr->pcontext ); 
00416         
00417         if( f->IsExist(y) )
00418             return false; // already processing this identifier, so we have a loop
00419                           // so don't recurse further
00420                           
00421         f->insert(y);                          
00422 
00423         TRACE("Looking for assignment like ")(*y)(" = ")(*x)("\n");
00424 
00425         FOREACH( TreePtr<Node> n, e )
00426         {
00427             if( TreePtr<Assign> a = dynamic_pointer_cast<Assign>(n) )
00428             {
00429                 TreePtr<Expression> lhs = a->operands[0];
00430                 if( TreePtr<Subscript> slhs = dynamic_pointer_cast<Subscript>( lhs ) ) // subscript as l-value 
00431                     lhs = slhs->operands[0];
00432                 TRACE("Examining assignment: ")(*lhs)(" = ")(*a->operands[1])("\n"); 
00433                 if( lhs == y )
00434                 {
00435                     if( CanReachExpr( sr, f, x, a->operands[1] ) )
00436                     {
00437                         r = true;                        
00438                         break; // early out, since we have the info we need
00439                     }
00440                 }
00441             }
00442         }
00443         
00444         f->erase(y);
00445         return r;
00446     }
00447     
00448     struct Reaching
00449     {
00450         Reaching( TreePtr<LabelIdentifier> f, TreePtr<InstanceIdentifier> t ) : from(f), to(t) {}
00451         const TreePtr<LabelIdentifier> from;
00452         const TreePtr<InstanceIdentifier> to;
00453         bool operator<( const Reaching &other ) const 
00454         {
00455             return from==other.from ? to<other.to : from<other.from;
00456         }
00457     };
00458     Map<Reaching, bool> cache; 
00459 };
00460 
00461 
00462 InsertSwitch::InsertSwitch()
00463 {
00464     MakeTreePtr<Instance> fn;
00465     MakeTreePtr<InstanceIdentifier> fn_id;
00466     MakeTreePtr<Callable> sub;
00467     MakeTreePtr< Overlay<Compound> > func_over, over, l_over;
00468     MakeTreePtr< Compound > ls_func_comp, lr_func_comp, s_func_comp, r_func_comp, s_comp, r_comp, r_switch_comp, l_comp, ls_switch_comp, lr_switch_comp;
00469     MakeTreePtr< Star<Declaration> > func_decls, decls, l_enum_vals;
00470     MakeTreePtr< Star<Statement> > func_pre, func_post, pre, body, l_func_pre, l_func_post, l_pre, l_post;
00471     MakeTreePtr< Stuff<Statement> > stuff, l_stuff; // TODO these are parallel stuffs, which is bad. Use two first-level slaves 
00472                                                     // and modify S&R to allow couplings between them. This means running slaves 
00473                                                     // in a post-pass and doing existing passes across all same-level slaves
00474     MakeTreePtr<Goto> s_first_goto; 
00475     MakeTreePtr<Label> ls_label; 
00476     MakeTreePtr<Switch> r_switch, l_switch;     
00477     MakeTreePtr<Enum> r_enum, ls_enum, lr_enum;         
00478     MakeTreePtr< NotMatch<Statement> > s_prenot, s_postnot, xs_rr;
00479     MakeTreePtr<BuildTypeIdentifier> r_enum_id("%sStates");
00480     MakeTreePtr<Static> lr_state_decl;    
00481     MakeTreePtr<BuildInstanceIdentifier> lr_state_id("STATE_%s");
00482     MakeTreePtr<Case> lr_case;
00483     MakeTreePtr<Signed> lr_int;
00484     MakeTreePtr<BuildContainerSize> lr_count;
00485     MakeTreePtr<IsLabelReached> ls_label_id;
00486     MakeTreePtr<InstanceIdentifier> var_id;
00487     MakeTreePtr<Instance> var_decl, l_var_decl;
00488     MakeTreePtr< Overlay<Type> > var_over;  
00489     MakeTreePtr<Label> xs_pre_label;
00490     MakeTreePtr<IsLabelReached> xs_pre_reach;
00491     MakeTreePtr< MatchAll<Node> > ll_all;
00492     MakeTreePtr< NotMatch<Node> > lls_not1, lls_not2;    
00493     MakeTreePtr< AnyNode<Node> > ll_any;
00494     MakeTreePtr< Overlay<Node> > ll_over;
00495     MakeTreePtr<Goto> lls_goto;    
00496     MakeTreePtr<Label> lls_label;    
00497             
00498     fn->type = sub;
00499     fn->initialiser = func_over;
00500     fn->identifier = fn_id;
00501     func_over->through = s_func_comp;
00502     s_func_comp->members = (func_decls, var_decl);
00503     var_decl->type = var_over;
00504     var_decl->identifier = var_id;
00505     var_over->through = MakeTreePtr<Labeley>();
00506     s_func_comp->statements = (func_pre, stuff, func_post);
00507     stuff->terminus = over;
00508     stuff->recurse_restriction = xs_rr; // TODO Add support for elsewhere restriction in stuff node, restrict for no reaches
00509     xs_rr->pattern = MakeTreePtr<Switch>(); // stop it doing a second switch inside one we just created
00510     over->through = s_comp;
00511     s_comp->members = (decls);
00512     s_comp->statements = (pre, s_first_goto, body);
00513     pre->pattern = s_prenot;
00514     s_prenot->pattern = xs_pre_label;
00515     xs_pre_label->identifier = xs_pre_reach;
00516     xs_pre_reach->pattern = var_id;
00517     s_first_goto->destination = var_id;
00518 
00519     r_func_comp->members = (func_decls, r_enum, var_decl);
00520     var_over->overlay = r_enum_id;
00521     r_enum->identifier = r_enum_id;
00522     r_enum_id->sources = (fn_id);        
00523     r_func_comp->statements = (func_pre, stuff, func_post);
00524     over->overlay = r_comp;
00525     r_comp->members = (decls);
00526     r_comp->statements = (pre, r_switch);    
00527     r_switch->body = r_switch_comp;
00528     r_switch_comp->statements = (body);
00529     r_switch->condition = var_id;
00530 
00531     MakeTreePtr< SlaveSearchReplace<Compound> > lr_sub_slave( lr_func_comp, ll_all );    
00532     MakeTreePtr< SlaveCompareReplace<Compound> > r_slave( r_func_comp, ls_func_comp, lr_sub_slave );
00533     func_over->overlay = r_slave;
00534     ls_func_comp->members = (func_decls, ls_enum, l_var_decl);
00535     ls_enum->members = (l_enum_vals);
00536     ls_enum->identifier = r_enum_id; // need to match id, not enum itself, because enum's members will change during slave
00537     ls_func_comp->statements = (l_func_pre, l_stuff, l_func_post);
00538     l_stuff->terminus = l_comp;
00539     l_comp->members = (decls);
00540     l_comp->statements = (pre, l_switch);
00541     l_switch->body = l_over;
00542     l_switch->condition = s_first_goto->destination;
00543     l_over->through = ls_switch_comp;
00544     ls_switch_comp->statements = (l_pre, ls_label, l_post);
00545     ls_label->identifier = ls_label_id;
00546     ls_label_id->pattern = var_id;
00547     
00548     lr_func_comp->members = (func_decls, lr_enum, l_var_decl);
00549     lr_enum->members = (l_enum_vals, lr_state_decl);
00550     lr_enum->identifier = r_enum_id;
00551     lr_state_decl->constancy = MakeTreePtr<Const>();
00552     lr_state_decl->identifier = lr_state_id;
00553     lr_state_decl->type = lr_int;
00554     lr_state_decl->initialiser = lr_count;
00555     lr_count->container = l_enum_vals;
00556     lr_int->width = MakeTreePtr<SpecificInteger>(32); // TODO should be a common place for getting default types
00557     lr_state_id->sources = (ls_label->identifier);
00558     lr_func_comp->statements = (l_func_pre, l_stuff, l_func_post);
00559     l_over->overlay = lr_switch_comp;
00560     lr_switch_comp->statements = (l_pre, lr_case, /*ls_label,*/ l_post); 
00561     // TODO retain the label for direct gotos, BUT we are spinning at 1st slave because we think the
00562     // label is still a state, because we think it reaches state var, because the LABEL->STATE_LABEL change 
00563     // is not being seen by IsLabelReached, because this is done by 2nd slave and stays in temps until
00564     // the master's SingleCompareReplace() completes. Uh-oh!
00565     // Only fix after fixing S&R to ensure slave output goes into context
00566     lr_case->value = lr_state_id;
00567 
00568     ll_all->patterns = (ll_any, lls_not1, lls_not2);
00569     ll_any->terminus = ll_over;
00570     ll_over->through = ls_label_id;
00571     ll_over->overlay = lr_state_id;
00572     lls_not1->pattern = lls_goto;
00573     lls_goto->destination = ls_label_id; // leave gotos alone in the body
00574     lls_not2->pattern = lls_label;
00575     lls_label->identifier = ls_label_id; // leave labels alone in the body
00576 
00577     Configure( fn );    
00578 }
00579 
00580 
00581 SwitchCleanUp::SwitchCleanUp()
00582 {
00583     MakeTreePtr<Compound> r_comp, s_body, r_body;
00584     MakeTreePtr<Switch> s_switch, r_switch;
00585     MakeTreePtr< Star<Declaration> > decls;
00586     MakeTreePtr< Star<Statement> > main, tail;
00587     MakeTreePtr<Label> label;
00588     MakeTreePtr<Expression> cond;
00589     MakeTreePtr< NotMatch<Statement> > sx_not_tail, sx_not_main;
00590     MakeTreePtr< MatchAny<Statement> > sx_any_tail;
00591 
00592     s_switch->condition = cond;
00593     s_switch->body = s_body;
00594     s_body->members = decls;
00595     s_body->statements = (main, label, tail);
00596     main->pattern = sx_not_main;
00597     sx_not_main->pattern = MakeTreePtr<Break>();
00598     tail->pattern = sx_not_tail;
00599     sx_not_tail->pattern = sx_any_tail;
00600     sx_any_tail->patterns = (MakeTreePtr<Break>(), MakeTreePtr<Case>());
00601     
00602     r_comp->statements = (r_switch, label, tail);
00603     r_switch->condition = cond;
00604     r_switch->body = r_body;
00605     r_body->members = decls;
00606     r_body->statements = (main);    
00607     
00608     Configure( s_switch, r_comp );        
00609 }
00610 
00611 
00612 InferBreak::InferBreak()
00613 {
00614     MakeTreePtr<Goto> ls_goto;
00615     MakeTreePtr<Label> label;
00616     MakeTreePtr<LabelIdentifier> label_id;
00617     MakeTreePtr< Star<Declaration> > decls;
00618     MakeTreePtr< Star<Statement> > pre, post;
00619     MakeTreePtr<Breakable> breakable;
00620     MakeTreePtr<Break> lr_break;
00621     MakeTreePtr<Compound> s_comp, r_comp;
00622 
00623     ls_goto->destination = label_id;
00624 
00625     MakeTreePtr< SlaveSearchReplace<Breakable> > slave( breakable, ls_goto, lr_break ); // todo restrict to not go through more breakables
00626 
00627     s_comp->members = decls;
00628     s_comp->statements = (pre, breakable, label, post);
00629     label->identifier = label_id;
00630     
00631     r_comp->members = decls;
00632     r_comp->statements = (pre, slave, post); 
00633     
00634     Configure( s_comp, r_comp );        
00635 }
00636 
00637 
00638 FixFallthrough::FixFallthrough()
00639 {
00640     // don't actually need a switch statement here, just look in the body, pattern contains Case statements
00641     MakeTreePtr<Compound> s_comp, r_comp;
00642     MakeTreePtr< Star<Declaration> > decls;
00643     MakeTreePtr< Star<Statement> > pre, cb1, cb2, post;
00644     MakeTreePtr<Case> case1, case2;
00645     MakeTreePtr<Break> breakk;
00646     MakeTreePtr< NotMatch<Statement> > s_not1, s_not2;
00647     
00648     s_comp->members = (decls);
00649     s_comp->statements = (pre, case1, cb1,              case2, cb2, breakk, post);
00650     r_comp->members = (decls);
00651     r_comp->statements = (pre, case1, cb1, cb2, breakk, case2, cb2, breakk, post);
00652     cb1->pattern = s_not1;
00653     s_not1->pattern = MakeTreePtr<Break>();
00654     cb2->pattern = s_not2;
00655     s_not2->pattern = MakeTreePtr<Case>();
00656         
00657     Configure( s_comp, r_comp );            
00658 }
00659 
00660 #if 1
00661 MakeFallThroughMachine::MakeFallThroughMachine()
00662 {
00663     MakeTreePtr<Scope> module;
00664     MakeTreePtr< Insert<Declaration> > insert;
00665     MakeTreePtr< GreenGrass<Type> > gg;
00666     MakeTreePtr<Field> func, m_func;
00667     MakeTreePtr<InstanceIdentifier> func_id;
00668     MakeTreePtr<Thread> thread;
00669     MakeTreePtr< Overlay<Compound> > func_over;    
00670     MakeTreePtr<Compound> s_func_comp, r_func_comp;
00671     MakeTreePtr< Star<Declaration> > func_decls, module_decls;
00672     MakeTreePtr< Star<Statement> > func_stmts;
00673     MakeTreePtr< Star<Base> > bases;
00674     MakeTreePtr<Enum> r_module_enum;
00675     MakeTreePtr<BuildTypeIdentifier> r_enum_id("%sStates");
00676     MakeTreePtr< MatchAll<Scope> > m_all;
00677     MakeTreePtr< Stuff<Scope> > m_stuff_inst;
00678     MakeTreePtr< Stuff<Initialiser> > m_stuff_label;
00679     MakeTreePtr< Overlay<Type> > m_over;
00680     MakeTreePtr< Stuff<Type> > m_stuff;
00681     MakeTreePtr<Instance> m_inst;
00682     MakeTreePtr<InstanceIdentifier> m_inst_id, var_id;
00683     MakeTreePtr<TypeIdentifier> module_id;
00684     MakeTreePtr<Label> m_label;
00685     MakeTreePtr<IsLabelReached> m_ilr;
00686     MakeTreePtr< Compound > l_func_comp, lr_comp, ls_comp, lr_if_comp;
00687     MakeTreePtr< Star<Declaration> > l_func_decls, l_enum_vals, l_decls, l_module_decls;
00688     MakeTreePtr< Star<Statement> > l_func_pre, l_func_post, l_pre, l_block, l_post, l_stmts, l_dead_gotos;
00689     MakeTreePtr<Switch> l_switch;     
00690     MakeTreePtr<Enum> l_enum;     
00691     MakeTreePtr< Insert<Declaration> > l_insert;
00692     MakeTreePtr< NotMatch<Statement> > xs_rr;
00693     MakeTreePtr<Static> lr_state_decl;    
00694     MakeTreePtr<BuildInstanceIdentifier> lr_state_id("%s_STATE_%s");
00695     MakeTreePtr<Case> lr_case;
00696     MakeTreePtr<Signed> lr_int;
00697     MakeTreePtr<BuildContainerSize> lr_count;
00698     MakeTreePtr<LabelIdentifier> ls_label_id;
00699     MakeTreePtr<Instance> var_decl, l_var_decl;
00700     MakeTreePtr< MatchAll<Node> > ll_all;
00701     MakeTreePtr< NotMatch<Node> > lls_not1, lls_not2;    
00702     MakeTreePtr< AnyNode<Node> > ll_any;
00703     MakeTreePtr< Overlay<Node> > ll_over;
00704     MakeTreePtr<Goto> lls_goto;    
00705     MakeTreePtr<Label> lls_label;    
00706     MakeTreePtr<Goto> ls_goto;   
00707     MakeTreePtr<Label> ls_label; 
00708     MakeTreePtr<If> lr_if;            
00709     MakeTreePtr<Equal> lr_equal;
00710     MakeTreePtr<Loop> l_loop;
00711     MakeTreePtr< Overlay<Statement> > l_over;
00712     MakeTreePtr< NotMatch<Statement> > l_not;             
00713     MakeTreePtr< Stuff<Scope> > m_stuff_func;
00714     MakeTreePtr<Scope> l_module;
00715     MakeTreePtr<Field> l_func;
00716         
00717     ll_all->patterns = (ll_any, lls_not1, lls_not2); // TODO don't think we need the nots
00718     ll_any->terminus = ll_over;
00719     ll_over->through = ls_label_id;
00720     ll_over->overlay = lr_state_id;
00721     lls_not1->pattern = lls_goto;
00722     lls_goto->destination = ls_label_id; // leave gotos alone in the body
00723     lls_not2->pattern = lls_label;
00724     lls_label->identifier = ls_label_id; // leave labels alone in the body
00725 
00726     MakeTreePtr< SlaveSearchReplace<Scope> > slavell( l_module, ll_all );    
00727     
00728     m_all->patterns = (m_stuff_func, m_stuff_inst);
00729     m_stuff_func->terminus = m_func;
00730     m_func->identifier = func_id;
00731     m_func->initialiser = m_stuff_label;
00732     m_stuff_label->terminus = m_label;
00733     m_label->identifier = m_ilr;
00734     m_ilr->pattern = m_inst_id;
00735     m_stuff_inst->terminus = m_inst;
00736     m_inst->identifier = m_inst_id;
00737     m_inst->type = m_stuff;
00738     m_stuff->terminus = m_over;    
00739     m_over->through = MakeTreePtr<Labeley>();
00740     m_over->overlay = r_enum_id;    
00741     
00742     MakeTreePtr< SlaveCompareReplace<Scope> > slavem( module, m_all );
00743 
00744     l_func->identifier = func_id;
00745     l_func->initialiser = l_func_comp;
00746     l_func_comp->members = (func_decls);
00747     l_func_comp->statements = (l_func_pre, l_loop, l_func_post); 
00748     l_loop->body = l_over;
00749     l_over->through = ls_comp;
00750     ls_comp->members = (l_decls);
00751     ls_comp->statements = (l_pre, ls_goto, ls_label, l_block, l_post, l_dead_gotos); 
00752     ls_goto->destination = var_id;
00753     ls_label->identifier = ls_label_id;
00754     l_enum->members = (l_enum_vals, l_insert);
00755     l_enum->identifier = r_enum_id;
00756     l_block->pattern = l_not;
00757     l_not->pattern = MakeTreePtr<Goto>();
00758     l_post->pattern = MakeTreePtr<If>();    
00759     l_dead_gotos->pattern = MakeTreePtr<Goto>();
00760     l_module->members = (l_module_decls, l_enum, l_func);
00761     l_over->overlay = lr_comp;
00762     l_insert->insert = (lr_state_decl);
00763     lr_state_decl->constancy = MakeTreePtr<Const>();
00764     lr_state_decl->identifier = lr_state_id;
00765     lr_state_decl->type = lr_int;
00766     lr_state_decl->initialiser = lr_count;
00767     lr_count->container = l_enum_vals;
00768     lr_int->width = MakeTreePtr<SpecificInteger>(32); // TODO should be a common place for getting default types
00769     lr_state_id->sources = (func_id, ls_label->identifier);
00770     lr_comp->members = (l_decls);
00771     lr_comp->statements = (l_pre, lr_if, l_post); // do final block first
00772     lr_if->condition = lr_equal;
00773     lr_if->body = lr_if_comp;
00774     lr_if->else_body = MakeTreePtr<Nop>();
00775     lr_equal->operands = (ls_label_id, var_id);
00776     //lr_if_comp->members = ();
00777     lr_if_comp->statements = l_block;
00778 
00779     MakeTreePtr< SlaveCompareReplace<Scope> > slavel( slavem, l_module, slavell );
00780     
00781     //s_module->bases = (bases);
00782     //s_module->identifier = module_id;
00783     func->type = gg;
00784     gg->through = thread;
00785     func->identifier = func_id;
00786     module->members = (module_decls, func, insert);
00787     insert->insert = (r_module_enum);
00788     //r_module->bases = (bases);
00789     //r_module->identifier = module_id;
00790     r_module_enum->identifier = r_enum_id;
00791     r_enum_id->sources = (func_id);            
00792     //r_module_enum->members = ();    
00793     
00794     Configure( module, slavel );    
00795 }
00796 #else
00797 MakeFallThroughMachine::MakeFallThroughMachine()
00798 {
00799     MakeTreePtr<Instance> fn;
00800     MakeTreePtr<InstanceIdentifier> fn_id;
00801     MakeTreePtr<Callable> sub;
00802     MakeTreePtr< Overlay<Compound> > func_over, over;
00803     MakeTreePtr< Compound > ls_func_comp, lr_func_comp, s_func_comp, r_func_comp, s_comp, r_comp, r_switch_comp, lr_comp, ls_comp, lr_if_comp;
00804     MakeTreePtr< Star<Declaration> > func_decls, l_func_decls, decls, l_enum_vals, l_decls;
00805     MakeTreePtr< Star<Statement> > func_pre, func_post, stmts, body, l_func_pre, l_func_post, l_pre, l_block, l_post, l_stmts;
00806     MakeTreePtr< Stuff<Statement> > stuff;
00807     MakeTreePtr<Goto> s_first_goto; 
00808     MakeTreePtr<Switch> r_switch, l_switch;     
00809     MakeTreePtr<Enum> r_enum, ls_enum, lr_enum;         
00810     MakeTreePtr< NotMatch<Statement> > s_prenot, s_postnot, xs_rr;
00811     MakeTreePtr<BuildTypeIdentifier> r_enum_id("%sStates");
00812     MakeTreePtr<Static> lr_state_decl;    
00813     MakeTreePtr<BuildInstanceIdentifier> lr_state_id("STATE_%s");
00814     MakeTreePtr<Case> lr_case;
00815     MakeTreePtr<Signed> lr_int;
00816     MakeTreePtr<BuildContainerSize> lr_count;
00817     MakeTreePtr<LabelIdentifier> ls_label_id;
00818     MakeTreePtr<InstanceIdentifier> var_id;
00819     MakeTreePtr<Instance> var_decl, l_var_decl;
00820     MakeTreePtr< Overlay<Type> > var_over;  
00821     MakeTreePtr<Label> xs_pre_label;
00822     MakeTreePtr<IsLabelReached> xs_pre_reach;
00823     MakeTreePtr< MatchAll<Node> > ll_all;
00824     MakeTreePtr< NotMatch<Node> > lls_not1, lls_not2;    
00825     MakeTreePtr< AnyNode<Node> > ll_any;
00826     MakeTreePtr< Overlay<Node> > ll_over;
00827     MakeTreePtr<Goto> lls_goto;    
00828     MakeTreePtr<Label> lls_label;    
00829     MakeTreePtr<Goto> ls_goto;   
00830     MakeTreePtr<Label> ls_label; 
00831     MakeTreePtr<If> lr_if;            
00832     MakeTreePtr<Equal> lr_equal;
00833     MakeTreePtr<Loop> l_loop;
00834     MakeTreePtr< Overlay<Statement> > l_over;
00835     MakeTreePtr< NotMatch<Statement> > l_not;             
00836     MakeTreePtr< MatchAny<Statement> > l_any;
00837                              
00838     MakeTreePtr< SlaveSearchReplace<Compound> > lr_sub_slave( lr_func_comp, ll_all );    
00839     MakeTreePtr< SlaveCompareReplace<Compound> > r_slave( r_func_comp, ls_func_comp, lr_sub_slave );
00840 
00841     fn->type = sub;
00842     fn->initialiser = func_over;
00843     fn->identifier = fn_id;
00844     
00845     func_over->through = s_func_comp;
00846     s_func_comp->members = (func_decls, var_decl);
00847     s_func_comp->statements = (stmts);
00848     var_decl->type = var_over;
00849     var_decl->identifier = var_id;
00850     var_over->through = MakeTreePtr<Labeley>();
00851     var_over->overlay = r_enum_id;
00852 
00853     func_over->overlay = r_slave;
00854     r_func_comp->members = (func_decls, r_enum, var_decl);
00855     r_func_comp->statements = (stmts);
00856     r_enum->identifier = r_enum_id;
00857     r_enum_id->sources = (fn_id);  
00858     
00859     ls_func_comp->members = (func_decls, ls_enum, l_var_decl);
00860     ls_func_comp->statements = (l_func_pre, l_loop, l_func_post); 
00861     ls_enum->members = (l_enum_vals);
00862     ls_enum->identifier = r_enum_id; // need to match id, not enum itself, because enum's members will change during slave
00863     l_loop->body = l_over;
00864     l_over->through = ls_comp;
00865     ls_comp->members = (l_decls);
00866     ls_comp->statements = (l_pre, ls_goto, ls_label, l_block, l_post); 
00867     ls_goto->destination = var_id;
00868     ls_label->identifier = ls_label_id;
00869     l_block->pattern = l_not;
00870     l_not->pattern = l_any;
00871     l_any->patterns = (MakeTreePtr<Goto>(), MakeTreePtr<If>());
00872     l_post->pattern = MakeTreePtr<If>();
00873     
00874     lr_func_comp->members = (func_decls, lr_enum, l_var_decl);
00875     lr_func_comp->statements = (l_func_pre, l_loop, l_func_post); // do final block first
00876     l_over->overlay = lr_comp;
00877     lr_enum->members = (l_enum_vals, lr_state_decl);
00878     lr_enum->identifier = r_enum_id;
00879     lr_state_decl->constancy = MakeTreePtr<Const>();
00880     lr_state_decl->identifier = lr_state_id;
00881     lr_state_decl->type = lr_int;
00882     lr_state_decl->initialiser = lr_count;
00883     lr_count->container = l_enum_vals;
00884     lr_int->width = MakeTreePtr<SpecificInteger>(32); // TODO should be a common place for getting default types
00885     lr_state_id->sources = (ls_label->identifier);
00886     lr_comp->members = (l_decls);
00887     lr_comp->statements = (l_pre, lr_if, l_post); // do final block first
00888     lr_if->condition = lr_equal;
00889     lr_if->body = lr_if_comp;
00890     lr_if->else_body = MakeTreePtr<Nop>();
00891     lr_equal->operands = (ls_label_id, var_id);
00892     //lr_if_comp->members = ();
00893     lr_if_comp->statements = l_block;
00894 
00895     ll_all->patterns = (ll_any, lls_not1, lls_not2); // TODO don't think we need the nots
00896     ll_any->terminus = ll_over;
00897     ll_over->through = ls_label_id;
00898     ll_over->overlay = lr_state_id;
00899     lls_not1->pattern = lls_goto;
00900     lls_goto->destination = ls_label_id; // leave gotos alone in the body
00901     lls_not2->pattern = lls_label;
00902     lls_label->identifier = ls_label_id; // leave labels alone in the body
00903 
00904     Configure( fn );    
00905 }
00906 #endif
00907 
00908 
00909 
00910 AddYieldFlag::AddYieldFlag()
00911 {
00912     MakeTreePtr<Instance> fn;
00913     MakeTreePtr<InstanceIdentifier> fn_id;
00914     MakeTreePtr<Callable> sub;
00915     MakeTreePtr<Compound> s_func_comp, r_func_comp, s_comp, r_comp, ms_comp, mr_comp, msx_comp;
00916     MakeTreePtr< Star<Declaration> > enums, decls, func_decls, m_decls, msx_decls;
00917     MakeTreePtr<Instance> var_decl;
00918     MakeTreePtr<InstanceIdentifier> var_id;    
00919     MakeTreePtr<TypeIdentifier> enum_id;
00920     MakeTreePtr< Star<Statement> > func_pre, m_pre, msx_pre, m_post, msx_post, stmts;
00921     MakeTreePtr< Star<If> > l_pre, l_post;
00922     MakeTreePtr<Loop> loop;
00923     MakeTreePtr<If> ls_if, lr_if, ms_if, mr_if;
00924     MakeTreePtr<Wait> m_wait;
00925     MakeTreePtr<Enum> enum_decl;
00926     MakeTreePtr<Equal> l_equal;
00927     MakeTreePtr<LogicalAnd> lr_and;
00928     MakeTreePtr<LogicalNot> lr_not;
00929     MakeTreePtr< Overlay<Compound> > func_over, over;
00930     MakeTreePtr<Temporary> r_flag_decl;
00931     MakeTreePtr<Assign> r_flag_init, mr_assign, msx_assign;
00932     MakeTreePtr<BuildInstanceIdentifier> r_flag_id("yield_flag");
00933     MakeTreePtr< MatchAll<Compound> > ms_all;
00934     MakeTreePtr< NotMatch<Compound> > ms_not;
00935     
00936     MakeTreePtr< SlaveSearchReplace<Compound> > slavem( r_func_comp, ms_all, mr_comp );
00937     MakeTreePtr< SlaveSearchReplace<Compound> > slave( r_comp, ls_if, lr_if );  
00938       
00939     fn->type = sub;
00940     fn->initialiser = func_over;
00941     fn->identifier = fn_id;  
00942     func_over->through = s_func_comp;    
00943     s_func_comp->members = (func_decls);
00944     s_func_comp->statements = (func_pre, loop);
00945     loop->body = over;
00946     over->through = s_comp;
00947     s_comp->members = decls;
00948     s_comp->statements = (stmts);
00949     stmts->pattern = MakeTreePtr<If>(); // anti-spin
00950     func_over->overlay = slavem; 
00951     r_func_comp->members = (func_decls);
00952     r_flag_init->operands = (r_flag_id, MakeTreePtr<False>());
00953     r_func_comp->statements = (func_pre, loop);
00954     r_flag_decl->identifier = r_flag_id;
00955     r_flag_decl->type = MakeTreePtr<Boolean>();
00956     r_flag_decl->initialiser = MakeTreePtr<Uninitialised>();
00957     over->overlay = slave;
00958     r_comp->members = (decls, r_flag_decl);
00959     r_comp->statements = (r_flag_init, stmts);
00960 
00961     ls_if->condition = l_equal;
00962     l_equal->operands = (MakeTreePtr<InstanceIdentifier>(), MakeTreePtr<InstanceIdentifier>());
00963     // TODO yield_id should be of type enum_id?                         
00964     lr_if->condition = lr_and;
00965     lr_and->operands = (l_equal, lr_not);
00966     lr_not->operands = (r_flag_id);
00967 
00968     ms_all->patterns = (ms_comp, ms_not);
00969     ms_comp->members = (m_decls);
00970     ms_comp->statements = (m_pre, m_wait, m_post);
00971     ms_not->pattern = msx_comp;
00972     msx_comp->members = msx_decls;
00973     msx_comp->statements = (msx_pre, msx_assign, msx_post);
00974     msx_assign->operands = (r_flag_id, MakeTreePtr<Bool>());
00975 
00976     mr_comp->members = (m_decls);
00977     mr_comp->statements = (m_pre, m_wait, mr_assign, m_post);
00978     mr_assign->operands = (r_flag_id, MakeTreePtr<True>());
00979 
00980     Configure( fn );            
00981 }
00982 
00983 AddInferredYield::AddInferredYield()
00984 {
00985     MakeTreePtr<Instance> fn;
00986     MakeTreePtr<InstanceIdentifier> fn_id;
00987     MakeTreePtr<Thread> thread; // Must be SC_THREAD since we introduce new yield here, only makes sense in SC_THREAD
00988     MakeTreePtr<Compound> func_comp, s_comp, sx_comp, r_comp;
00989     MakeTreePtr< Star<Declaration> > func_decls;
00990     MakeTreePtr< Star<Statement> > func_pre, stmts, sx_pre;    
00991     MakeTreePtr< Overlay<Statement> > over;    
00992     MakeTreePtr<LocalVariable> flag_decl; 
00993     MakeTreePtr<InstanceIdentifier> flag_id;   
00994     MakeTreePtr<WaitDelta> r_yield;
00995     MakeTreePtr<Loop> loop;
00996     MakeTreePtr<If> r_if, sx_if;
00997     MakeTreePtr< MatchAll<Compound> > s_all;
00998     MakeTreePtr< NotMatch<Compound> > s_notmatch;
00999     MakeTreePtr< LogicalNot > r_not, sx_not;
01000     MakeTreePtr< Assign > assign;
01001           
01002     fn->type = thread;
01003     fn->initialiser = func_comp;
01004     fn->identifier = fn_id;  
01005     func_comp->members = (func_decls);
01006     flag_decl->type = MakeTreePtr<Boolean>();
01007     flag_decl->initialiser = MakeTreePtr<Uninitialised>();
01008     flag_decl->identifier = flag_id;
01009     func_comp->statements = (func_pre, loop);
01010     loop->body = over;
01011     over->through = s_all;
01012     s_all->patterns = (s_comp, s_notmatch);
01013     s_comp->members = (flag_decl);
01014     s_comp->statements = (stmts);
01015     s_notmatch->pattern = sx_comp;
01016     sx_comp->members = (flag_decl);
01017     sx_comp->statements = (sx_pre, sx_if);
01018     sx_if->condition = sx_not;
01019     sx_not->operands = (flag_id);
01020     
01021     over->overlay = r_comp;
01022     r_comp->members = (flag_decl);
01023     r_comp->statements = (stmts, r_if);
01024     r_if->condition = r_not;
01025     r_not->operands = (flag_id);
01026     r_if->body = r_yield;
01027     r_if->else_body = MakeTreePtr<Nop>();
01028     
01029     Configure( fn );            
01030 }
01031 
01032 
01033 MoveInitIntoSuperLoop::MoveInitIntoSuperLoop()
01034 {
01035     MakeTreePtr<Instance> fn;
01036     MakeTreePtr<InstanceIdentifier> fn_id;
01037     MakeTreePtr<Thread> thread; // Must be SC_THREAD since we introduce SC stuff
01038     MakeTreePtr< Star<Declaration> > func_decls;
01039     MakeTreePtr< Star<Statement> > inits, stmts;    
01040     MakeTreePtr<Loop> loop;
01041     MakeTreePtr<Compound> s_func_comp, r_func_comp, s_comp, r_comp, r_if_comp;
01042     MakeTreePtr<If> r_if;
01043     MakeTreePtr<Equal> r_equal;
01044     MakeTreePtr< Overlay<Compound> > func_over, over;    
01045     MakeTreePtr<Statement> first_init;
01046                     
01047     fn->type = thread;
01048     fn->initialiser = func_over;
01049     fn->identifier = fn_id;  
01050     func_over->through = s_func_comp;
01051     s_func_comp->members = (func_decls);
01052     s_func_comp->statements = (first_init, inits, loop);
01053     loop->body = over;
01054     over->through = s_comp;
01055 //    s_comp->members = ();
01056     s_comp->statements = (stmts);    
01057     
01058     func_over->overlay = r_func_comp;
01059     r_func_comp->members = (func_decls);
01060     r_func_comp->statements = (loop);
01061     over->overlay = r_comp;
01062 //    r_comp->members = ();
01063     r_comp->statements = (r_if, stmts);
01064     r_if->condition = r_equal;
01065     r_equal->operands = ( MakeTreePtr<DeltaCount>(), MakeTreePtr<SpecificInteger>(0) );    
01066     r_if->body = r_if_comp;
01067 //    r_if_comp->members = ();
01068     r_if_comp->statements = (first_init, inits);//, MakeTreePtr<WaitDelta>());
01069     r_if->else_body = MakeTreePtr<Nop>();
01070     
01071     Configure( fn );            
01072 }
01073 
01074 
01075 // rotate loops to avoid inferred yields when an explicit yield already exists
01076 LoopRotation::LoopRotation()
01077 {
01078     MakeTreePtr<Instance> fn, s_var_decl;
01079     MakeTreePtr<InstanceIdentifier> fn_id, s_var_id, s_cur_enum_id, s_outer_enum_id;
01080     MakeTreePtr<Thread> thread; // Must be SC_THREAD since we introduce SC stuff
01081     MakeTreePtr< Star<Declaration> > func_decls, decls, s_enums;
01082     MakeTreePtr<Static> s_cur_enum, s_outer_enum;
01083     MakeTreePtr< Star<Statement> > inits, stmts, pre, post, prepre, prepost, postpre, postpost;    
01084     MakeTreePtr<Loop> loop;
01085     MakeTreePtr<Compound> func_comp, s_comp_loop, s_comp_yield, r_comp, r_if_comp, sx_comp;
01086     MakeTreePtr<If> loop_top, loop_bottom, yield, outer_bottom, outer_top;
01087     MakeTreePtr< Star<If> > loop_body, pre_yield, post_yield;
01088     MakeTreePtr<Equal> r_equal;
01089     MakeTreePtr< Overlay<Compound> > func_over, over;    
01090     MakeTreePtr< MatchAll<Compound> > s_all;
01091     MakeTreePtr<Enum> s_enum;
01092     MakeTreePtr<TypeIdentifier> s_enum_id;
01093     MakeTreePtr< Stuff<Expression> > loop_top_stuff, outer_top_stuff;
01094     MakeTreePtr<Equal> loop_top_equal, outer_top_equal;
01095     MakeTreePtr< Stuff<Statement> > loop_bottom_stuff_enum, outer_bottom_stuff_enum, 
01096                                     loop_bottom_stuff_noyield, yield_stuff, outer_bottom_stuff_noyield;
01097     MakeTreePtr< MatchAll<Statement> > loop_bottom_matchall, outer_bottom_matchall;
01098     MakeTreePtr< NotMatch<Statement> > loop_bottom_notmatch, outer_bottom_notmatch;
01099     MakeTreePtr< NotMatch<Compound> > s_notmatch;
01100     MakeTreePtr< MatchAny<If> > inner_state;
01101     
01102     fn->type = thread;
01103     fn->initialiser = func_comp;
01104     fn->identifier = fn_id;  
01105     func_comp->members = (func_decls, /*s_enum,*/ s_var_decl); // enum removed because it is class member, not local to the function
01106     s_enum->identifier = s_enum_id;
01107     s_enum->members = (s_enums, s_cur_enum);
01108     s_cur_enum->identifier = s_cur_enum_id;
01109     s_outer_enum->identifier = s_outer_enum_id;
01110     s_var_decl->type = s_enum_id;
01111     s_var_decl->identifier = s_var_id;
01112     func_comp->statements = (inits, loop);
01113     loop->body = over;
01114     over->through = s_all;
01115     s_all->patterns = (s_comp_loop, s_comp_yield, s_notmatch);
01116     s_comp_loop->members = (decls);
01117     // Search for a loop. Assume that a state enum value in a body means "could transition to the state" and one in
01118     // the condition means "acts on the state". If we see the latter with the former blow it somewhere, we call
01119     // it a loop and assume the upward branch is normally takner as with C compilers.    
01120     s_comp_loop->statements = (pre, loop_top, loop_body, loop_bottom, post);    
01121     loop_top->condition = loop_top_stuff;
01122     loop_top_stuff->terminus = loop_top_equal;
01123     loop_top_equal->operands = (s_var_id, s_cur_enum_id);
01124     loop_bottom->body = loop_bottom_matchall;
01125     loop_bottom_matchall->patterns = (loop_bottom_stuff_enum, loop_bottom_notmatch);
01126     loop_bottom_stuff_enum->terminus = s_cur_enum_id;
01127     loop_bottom_notmatch->pattern = loop_bottom_stuff_noyield;
01128     loop_bottom_stuff_noyield->terminus = MakeTreePtr<Wait>();    
01129     s_comp_yield->members = (decls);
01130     
01131     // We need to restruct to loops that contain a yield anywhere but the bottom - these are the ones
01132     // that would benefit from loop rotation.
01133     s_comp_yield->statements = (pre, pre_yield, yield, post_yield, loop_bottom, post);    
01134     yield->body = yield_stuff;
01135     yield_stuff->terminus = MakeTreePtr<Wait>();
01136     
01137     // This part is to make sure we operate on the outermost loop first - look for another loop surrounding 
01138     // the current one, if it does not end in a yield, then do not transform. This way the outer loop will
01139     // keep getting hits until the yield is at the bottom, then inner loops can have a go.
01140     s_notmatch->pattern = sx_comp;
01141     sx_comp->members = (decls);
01142     sx_comp->statements = (prepre, outer_top, postpre, inner_state, prepost, outer_bottom, postpost);
01143     outer_top->condition = outer_top_stuff;
01144     outer_top_stuff->terminus = outer_top_equal;
01145     outer_top_equal->operands = (s_var_id, s_outer_enum_id);
01146     outer_bottom->body = outer_bottom_matchall;
01147     outer_bottom_matchall->patterns = (outer_bottom_stuff_enum, outer_bottom_notmatch);
01148     outer_bottom_stuff_enum->terminus = s_outer_enum_id;
01149     outer_bottom_notmatch->pattern = outer_bottom_stuff_noyield;
01150     outer_bottom_stuff_noyield->terminus = MakeTreePtr<Wait>();    
01151     inner_state->patterns = (loop_top, loop_bottom); // outer loop can share top or bottom state with inner loop; but not both, so at least one must be here
01152    
01153     over->overlay = r_comp;
01154     r_comp->members = (decls);
01155     r_comp->statements = (pre, loop_bottom, loop_top, loop_body, post);    // rotated version of s_comp_loop
01156         
01157     Configure( fn );            
01158 }
01159 
01160