![]() |
libsesstype
2.0.0
Library for Session Types programming.
|
00001 #ifndef SESSTYPE__UTIL__PROJECT_H__ 00002 #define SESSTYPE__UTIL__PROJECT_H__ 00003 00004 #ifdef __cplusplus 00005 #include <stack> 00006 #endif 00007 00008 #include "sesstype/role.h" 00009 #include "sesstype/node.h" 00010 #include "sesstype/node/block.h" 00011 #include "sesstype/node/interaction.h" 00012 #include "sesstype/node/choice.h" 00013 #include "sesstype/node/recur.h" 00014 #include "sesstype/node/continue.h" 00015 #include "sesstype/node/par.h" 00016 #include "sesstype/node/nested.h" 00017 #include "sesstype/node/interruptible.h" 00018 #include "sesstype/util/node_visitor.h" 00019 00020 #ifdef __cplusplus 00021 namespace sesstype { 00022 namespace util { 00023 #endif 00024 00025 #ifdef __cplusplus 00026 00029 class ProjectionVisitor : public NodeVisitor { 00030 Role *endpoint_; 00031 std::stack<Node *> stack_; 00032 00033 public: 00034 ProjectionVisitor(Role *endpoint) : endpoint_(endpoint), stack_() 00035 { 00036 stack_.push(new BlockNode()); 00037 } 00038 00039 Node *get_root() 00040 { 00041 return stack_.top(); 00042 } 00043 00044 void visit(Node *node) override 00045 { 00046 // Nothing. 00047 } 00048 00049 void visit(BlockNode *node) override 00050 { 00057 for (auto it=node->child_begin(); it!=node->child_end(); it++) { 00058 (*it)->accept(*this); 00059 } 00060 } 00061 00062 void visit(InteractionNode *node) override 00063 { 00064 auto *parent = dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top()); 00065 InteractionNode *projected_node; 00066 00067 if (node->sndr()->matches(endpoint_)) { 00068 projected_node = node->clone(); 00069 projected_node->remove_sndr(); 00070 parent->append_child(projected_node); 00071 return; 00072 } 00073 for (auto it=node->rcvr_begin(); it!=node->rcvr_end(); it++) { 00074 if (*it && (*it)->matches(endpoint_)) { 00075 projected_node = node->clone(); 00076 projected_node->remove_rcvrs(); 00077 parent->append_child(projected_node); 00078 return; 00079 } 00080 } 00081 00082 // Remove this node because is does not match from/to 00083 } 00084 00085 void visit(ChoiceNode *node) 00086 { 00087 auto *projected_node = new ChoiceNode(node->at()); 00088 00089 stack_.push(projected_node); 00090 if (endpoint_->matches(projected_node->at())) { 00091 // Choice sender 00092 } 00093 node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this); 00094 stack_.pop(); 00095 00096 dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node); 00097 } 00098 00099 void visit(RecurNode *node) override 00100 { 00101 auto *projected_node = new RecurNode(node->label()); 00102 00103 stack_.push(projected_node); 00104 node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this); 00105 stack_.pop(); 00106 00107 dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node); 00108 } 00109 00110 void visit(ContinueNode *node) override 00111 { 00112 auto *projected_node = new ContinueNode(node->label()); 00113 dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node); 00114 } 00115 00116 void visit(ParNode *node) 00117 { 00118 auto *projected_node = new ParNode(); 00119 00120 stack_.push(projected_node); 00121 node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this); 00122 stack_.pop(); 00123 00124 dynamic_cast<BlockNode *>(stack_.top())->append_child(projected_node); 00125 } 00126 00127 void visit(NestedNode *node) 00128 { 00129 // Only include nested node if role arg matches. 00130 for (auto it=node->rolearg_begin(); it!=node->rolearg_end(); it++) { 00131 if ((*it)->matches(endpoint_)) { 00132 dynamic_cast<BlockNode *>(stack_.top())->append_child(node->clone()); 00133 break; 00134 } 00135 } 00136 } 00137 00138 void visit(InterruptibleNode *node) 00139 { 00140 auto *new_node = node->clone(); 00141 00142 // TODO only retain interrupts relevant to endpoint role? 00143 00144 stack_.push(new_node); 00145 node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this); 00146 stack_.pop(); 00147 00148 dynamic_cast<BlockNode *>(stack_.top())->append_child(new_node); 00149 } 00150 }; 00151 #endif // __cplusplus 00152 00153 #ifdef __cplusplus 00154 } // namespace util 00155 } // namespace sesstype 00156 #endif 00157 00158 #endif//SESSTYPE__UTIL__PROJECT_H__