![]() |
libsesstype
2.0.0
Library for Session Types programming.
|
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__