// $Header$ #ifndef stmt_h #define stmt_h #include "Glish/List.h" #include "Func.h" #include "Event.h" class Stmt; class EventDesignator; class Agent; class Task; class Sequencer; declare(PList,Stmt); typedef PList(Stmt) stmt_list; declare(PDict,stmt_list); typedef PDict(stmt_list) stmt_list_dict; typedef enum { FLOW_NEXT, // continue on to next statement FLOW_LOOP, // go to top of loop FLOW_BREAK, // break out of loop FLOW_RETURN // return from function } stmt_flow_type; class Stmt : public GlishObject { public: Stmt() { index = 0; } // Exec() tells a statement to go ahead and execute. We use // it as a wrapper around the actual execute member function // so we can reset the current line number and perform any // other "global" statement execution (such as setting the // control flow to default to FLOW_NEXT). // // The "value_needed" argument, indicates whether any value // produced by this statement is of interest (because the // statement is possibly the last one in a function, so the // value will become the function value). Note that "value_needed" // is advisory; some statements (like "return") will always // return a value regardless of "value_needed"'s setting. // // Exec() returns a value associated with the statement or 0 // if there is none, and in "flow" returns a stmt_flow_type // indicating control flow information. virtual Value* Exec( int value_needed, stmt_flow_type& flow ); // Called when an event we've expressed interest in has arrived. // The argument specifies the Agent associated with the // event. virtual void Notify( Agent* agent ); // Returns true if we're currently active for the given event // generated by the given agent, with the given value; false // otherwise. Only actually used by "whenever" statements. virtual int IsActiveFor( Agent* agent, const char* field, Value* value ) const; // Sets the statement's activity, either to true (if "activate" is // true) or to false. virtual void SetActivity( int activate ); // Return the index of this statement. Might be 0, indicating // that the statement is not intended to be indexed (presently, // only "whenever" statements are meant to be indexed). int Index() const { return index; } protected: // DoExec() does the real work of executing the statement. virtual Value* DoExec( int value_needed, stmt_flow_type& flow ) = 0; int index; }; class SeqStmt : public Stmt { public: SeqStmt( Stmt* arg_lhs, Stmt* arg_rhs ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: Stmt* lhs; Stmt* rhs; }; class WheneverStmt : public Stmt { public: WheneverStmt( event_list* arg_trigger, Stmt* arg_stmt, Sequencer* arg_sequencer ); virtual ~WheneverStmt(); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Notify( Agent* agent ); int IsActiveFor( Agent* agent, const char* field, Value* value ) const; void SetActivity( int activate ); void Describe( ostream& s ) const; protected: event_list* trigger; Stmt* stmt; Sequencer* sequencer; int active; }; class LinkStmt : public Stmt { public: LinkStmt( event_list* source, event_list* sink, Sequencer* sequencer ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: void MakeLink( Task* src, const char* source_event, Task* snk, const char* sink_event ); virtual void LinkAction( Task* src, Value* v ); event_list* source; event_list* sink; Sequencer* sequencer; }; class UnLinkStmt : public LinkStmt { public: UnLinkStmt( event_list* source, event_list* sink, Sequencer* sequencer ); protected: void LinkAction( Task* src, Value* v ); }; class AwaitStmt : public Stmt { public: AwaitStmt( event_list* arg_await_list, int arg_only_flag, event_list* arg_except_list, Sequencer* arg_sequencer ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: event_list* await_list; int only_flag; event_list* except_list; Sequencer* sequencer; Stmt* except_stmt; }; class ActivateStmt : public Stmt { public: ActivateStmt( int activate, Expr* e, Sequencer* sequencer ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: int activate; Expr* expr; Sequencer* sequencer; }; class IfStmt : public Stmt { public: IfStmt( Expr* arg_expr, Stmt* arg_true_branch, Stmt* arg_false_branch ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: Expr* expr; Stmt* true_branch; Stmt* false_branch; }; class ForStmt : public Stmt { public: ForStmt( Expr* index_expr, Expr* range_expr, Stmt* body_stmt ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: Expr* index; Expr* range; Stmt* body; }; class WhileStmt : public Stmt { public: WhileStmt( Expr* test_expr, Stmt* body_stmt ); Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: Expr* test; Stmt* body; }; class PrintStmt : public Stmt { public: PrintStmt( parameter_list* arg_args ) { args = arg_args; description = "print"; } Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: parameter_list* args; }; class ExprStmt : public Stmt { public: ExprStmt( Expr* arg_expr ) { expr = arg_expr; description = "expression"; } Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; void DescribeSelf( ostream& s ) const; protected: Expr* expr; }; class ExitStmt : public Stmt { public: ExitStmt( Expr* arg_status, Sequencer* arg_sequencer ) { description = "exit"; status = arg_status; sequencer = arg_sequencer; } Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: Expr* status; Sequencer* sequencer; }; class LoopStmt : public Stmt { public: LoopStmt() { description = "next"; } Value* DoExec( int value_needed, stmt_flow_type& flow ); }; class BreakStmt : public Stmt { public: BreakStmt() { description = "break"; } Value* DoExec( int value_needed, stmt_flow_type& flow ); }; class ReturnStmt : public Stmt { public: ReturnStmt( Expr* arg_retval ) { description = "return"; retval = arg_retval; } Value* DoExec( int value_needed, stmt_flow_type& flow ); void Describe( ostream& s ) const; protected: Expr* retval; }; class NullStmt : public Stmt { public: NullStmt() { description = ";"; } Value* DoExec( int value_needed, stmt_flow_type& flow ); }; extern Stmt* null_stmt; extern Stmt* merge_stmts( Stmt* stmt1, Stmt* stmt2 ); #endif /* stmt_h */