libsesstype  2.0.0
Library for Session Types programming.
project.h
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__
 All Classes Namespaces Files Functions