libsesstype  2.0.0
Library for Session Types programming.
project.h
00001 #ifndef SESSTYPE__PARAMETERISED__UTIL__PROJECT_H__
00002 #define SESSTYPE__PARAMETERISED__UTIL__PROJECT_H__
00003 
00004 #ifdef __cplusplus
00005 #include <iostream>
00006 #include <stack>
00007 #endif
00008 
00009 #include "sesstype/parameterised/nodes.h"
00010 #include "sesstype/parameterised/role.h"
00011 #include "sesstype/parameterised/role_grp.h"
00012 #include "sesstype/parameterised/util/node_visitor.h"
00013 #include "sesstype/parameterised/util/expr_apply.h"
00014 #include "sesstype/parameterised/util/expr_eval.h"
00015 #include "sesstype/parameterised/util/expr_invert.h"
00016 
00017 #ifdef __cplusplus
00018 namespace sesstype {
00019 namespace parameterised {
00020 namespace util {
00021 #endif
00022 
00023 #ifdef __cplusplus
00024 
00027 class ProjectionVisitor : public NodeVisitor {
00028     Role *endpoint_;
00029     std::stack<Node *> stack_;
00030 
00031   public:
00032     ProjectionVisitor(Role *endpoint) : endpoint_(endpoint), stack_()
00033     {
00034         stack_.push(new BlockNode());
00035     }
00036 
00037     Node *get_root()
00038     {
00039         return stack_.top();
00040     }
00041 
00042     virtual void visit(Node *node) override
00043     {
00044         // Nothing.
00045     }
00046 
00047     virtual void visit(BlockNode *node) override
00048     {
00049         for (auto it=node->child_begin(); it!=node->child_end(); it++) {
00050             (*it)->accept(*this);
00051         }
00052     }
00053 
00054     virtual void visit(sesstype::parameterised::InteractionNode *node) override
00055     {
00056         auto *parent = dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top());
00057         sesstype::parameterised::InteractionNode *projected_node;
00058 
00059         if (endpoint_->num_dimens() == 0) { // Endpoint is non-parameterised
00060 
00061             for (auto it=node->rcvr_begin(); it!=node->rcvr_end(); it++) {
00062                 if (*it && (*it)->matches(endpoint_)) { // Rule 1.
00063 #ifdef __DEBUG__
00064                     std::cerr << "Rule 1 Ordinary to\n";
00065 #endif
00066                     projected_node = node->clone();
00067                     projected_node->remove_rcvrs();
00068                     parent->append_child(projected_node);
00069                     return;
00070                 }
00071             }
00072 
00073             if (node->sndr()->matches(endpoint_)) { // Rule 2.
00074 #ifdef __DEBUG__
00075                 std::cerr << "Rule 2 Ordinary from\n";
00076 #endif
00077                 projected_node = node->clone();
00078                 projected_node->remove_sndr();
00079                 parent->append_child(projected_node);
00080                 return;
00081             }
00082             return;
00083 
00084         } else { // Endpoint is parameterised
00085 
00086 
00087             // Parameterised endpoint, so multiple rule matches possible.
00088 
00089             if (node->sndr()->num_dimens() > 0) {
00090 
00091                 if (role_is_bindable(node->sndr())) { // Either Rule 8 or 9.
00092 
00093                     for (auto it=node->rcvr_begin(); it!=node->rcvr_end(); it++) {
00094                         if (*it && (*it)->matches(endpoint_)) { // Rule 9.
00095 #ifdef __DEBUG__
00096                             std::cerr << "Rule 9 Relative from\n";
00097 #endif
00098                             projected_node = node->clone();
00099 
00100                             Role *cond = new Role((*it)->name());
00101                             Role *sndr = new Role(node->sndr()->name());
00102                             for (auto param=0; param<node->sndr()->num_dimens(); param++) {
00103                                 Expr *b = (*node->sndr())[param];
00104                                 Expr *e = (**it)[param];
00105                                 std::string bindvar;
00106 
00107                                 if (auto b_rng = dynamic_cast<RngExpr *>(b)) {
00108                                     bindvar = b_rng->bindvar();
00109                                     util::ExprApply applier(b_rng);
00110                                     e->accept(applier);
00111                                     Expr *apply_b_e = applier.apply();
00112                                     util::ExprEval evaluator;
00113                                     apply_b_e->accept(evaluator);
00114                                     Expr *apply_b_e_simplified = evaluator.eval();
00115                                     delete apply_b_e;
00116 
00117                                     util::ExprInvert inv(bindvar);
00118                                     e->accept(inv);
00119                                     Expr *inv_e = inv.invert();
00120 
00121                                     cond->add_param(apply_b_e_simplified);
00122                                     sndr->add_param(inv_e);
00123                                 } else {
00124                                     cond->add_param(e);
00125                                     sndr->add_param(b);
00126                                 }
00127                             }
00128 
00129                             projected_node->remove_rcvrs();
00130                             projected_node->set_sndr(sndr);
00131                             projected_node->set_cond(cond);
00132                             parent->append_child(projected_node);
00133                             // Don't return yet.
00134                         }
00135                     }
00136 
00137                     if (node->sndr()->matches(endpoint_)) { // Rule 8.
00138 #ifdef __DEBUG__
00139                         std::cerr << "Rule 8 Relative to\n";
00140 #endif
00141                         projected_node = node->clone();
00142                         projected_node->set_cond(projected_node->sndr()->clone());
00143                         projected_node->remove_sndr();
00144                         parent->append_child(projected_node);
00145                         // Don't return yet.
00146                     }
00147 
00148                 } else { // Role not bindable and dimen > 0, Rule 3 or 4.
00149 
00150                     for (auto it=node->rcvr_begin(); it!=node->rcvr_end(); it++) {
00151                         if (*it && (*it)->matches(endpoint_)) { // Rule 3.
00152 #ifdef __DEBUG__
00153                             std::cerr << "Rule 3 Parameterised to\n";
00154 #endif
00155                             projected_node = node->clone();
00156                             projected_node->remove_rcvrs();
00157                             projected_node->set_cond((*it)->clone());
00158                             parent->append_child(projected_node);
00159                             // Don't return yet.
00160                         }
00161                     }
00162 
00163                     if (node->sndr()->matches(endpoint_)) { // Rule 4
00164 #ifdef __DEBUG__
00165                         std::cerr << "Rule 4 Parameterised from\n";
00166 #endif
00167                         projected_node = node->clone();
00168                         projected_node->set_cond(projected_node->sndr()->clone());
00169                         projected_node->remove_sndr();
00170                         parent->append_child(projected_node);
00171                     }
00172 
00173                 }
00174 
00175             } else { // sender dimension == 0, i.e. Group role
00176 
00177                 for (auto it=node->rcvr_begin(); it!=node->rcvr_end(); it++) {
00178                     if (*it && dynamic_cast<RoleGrp *>(*it)) { // Rule 6.
00179                         if (*it && (*it)->matches(endpoint_)) {
00180 #ifdef __DEBUG__
00181                             std::cerr << "Rule 6 Group from\n";
00182 #endif
00183                             projected_node = node->clone();
00184                             projected_node->remove_rcvrs();
00185                             projected_node->set_cond((*it)->clone());
00186                             parent->append_child(projected_node);
00187                             // Don't return yet.
00188                         }
00189                     }
00190                 }
00191 
00192                 if (dynamic_cast<RoleGrp *>(node->sndr())) { // Rule 7.
00193                     if (node->sndr()->matches(endpoint_)) {
00194 #ifdef __DEBUG__
00195                         std::cerr << "Rule 7 Group to\n";
00196 #endif
00197                         projected_node = node->clone();
00198                         projected_node->remove_sndr();
00199                         projected_node->set_cond(node->sndr()->clone());
00200                         parent->append_child(projected_node);
00201                         // Don't return yet.
00202                     }
00203                 }
00204             }
00205         }
00206 
00207     }
00208 
00209     bool role_is_bindable(Role *role)
00210     {
00211         for (auto i=0; i<role->num_dimens(); i++) {
00212             if (dynamic_cast<RngExpr *>((*role)[i])) {
00213                 return true;
00214             }
00215         }
00216         return false;
00217     }
00218 
00219     virtual void visit(ChoiceNode *node) override
00220     {
00221         auto *projected_node = new ChoiceNode(node->at()->clone());
00222 
00223         stack_.push(projected_node);
00224         if (endpoint_->matches(projected_node->at())) {
00225             // Choice sender
00226         }
00227         node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this);
00228         stack_.pop();
00229 
00230         dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node);
00231     }
00232 
00233     virtual void visit(RecurNode *node) override
00234     {
00235         auto *projected_node = new RecurNode(node->label());
00236 
00237         stack_.push(projected_node);
00238         node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this);
00239         stack_.pop();
00240 
00241         dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node);
00242     }
00243 
00244     virtual void visit(ContinueNode *node) override
00245     {
00246         auto *projected_node = new ContinueNode(node->label());
00247 
00248         dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node);
00249     }
00250 
00251     virtual void visit(ParNode *node) override
00252     {
00253         auto *projected_node = new ParNode();
00254 
00255         stack_.push(projected_node);
00256         node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this);
00257         stack_.pop();
00258 
00259         dynamic_cast<BlockNode *>(stack_.top())->append_child(projected_node);
00260     }
00261 
00262     virtual void visit(NestedNode *node) override
00263     {
00264         // Only include nested node if role arg matches.
00265         for (auto it=node->rolearg_begin(); it!=node->rolearg_end(); it++) {
00266             if ((*it)->matches(endpoint_)) {
00267                 dynamic_cast<BlockNode *>(stack_.top())->append_child(node->clone());
00268                 break;
00269             }
00270         }
00271     }
00272 
00273     virtual void visit(InterruptibleNode *node) override
00274     {
00275         auto *new_node = node->clone();
00276 
00277         // TODO only retain interrupts relevant to endpoint role?
00278 
00279         stack_.push(new_node);
00280         node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this);
00281         stack_.pop();
00282 
00283         dynamic_cast<BlockNode *>(stack_.top())->append_child(new_node);
00284     }
00285 
00286     virtual void visit(ForNode *node) override
00287     {
00288         auto *new_node = node->clone();
00289 
00290         stack_.push(new_node);
00291         node->BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor>::accept(*this);
00292         stack_.pop();
00293 
00294         dynamic_cast<BlockNode *>(stack_.top())->append_child(new_node);
00295     }
00296 
00297     virtual void visit(OneofNode *node) override
00298     {
00299         // TODO To be refined.
00300     }
00301 
00302     virtual void visit(IfNode *node) override
00303     {
00304         // Not part of global type syntax.
00305     }
00306 
00307     virtual void visit(AllReduceNode *node) override
00308     {
00309         auto *projected_node = new AllReduceNode(node->msg());
00310         dynamic_cast<BlockNodeTmpl<Node, Role, MsgSig, util::NodeVisitor> *>(stack_.top())->append_child(projected_node);
00311     }
00312 };
00313 #endif // __cplusplus
00314 
00315 #ifdef __cplusplus
00316 } // namespace util
00317 } // namespace parameterised
00318 } // namespace sesstype
00319 #endif
00320 
00321 #endif//SESSTYPE__PARAMETERISED__UTIL__PROJECT_H__
 All Classes Namespaces Files Functions