"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.0/src/libponyc/type/viewpoint.c" (1 Nov 2019, 12359 Bytes) of package /linux/misc/ponyc-0.33.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "viewpoint.c" see the Fossies "Dox" file reference documentation.

    1 #include "viewpoint.h"
    2 #include "alias.h"
    3 #include "assemble.h"
    4 #include "cap.h"
    5 #include "../ast/astbuild.h"
    6 #include "ponyassert.h"
    7 
    8 enum
    9 {
   10   VIEW_UPPER_NO,
   11   VIEW_UPPER_YES,
   12   VIEW_UPPER_FORCE
   13 };
   14 
   15 ast_t* viewpoint_type(ast_t* l_type, ast_t* r_type)
   16 {
   17   int upper = VIEW_UPPER_NO;
   18 
   19   switch(ast_id(r_type))
   20   {
   21     case TK_UNIONTYPE:
   22     case TK_ISECTTYPE:
   23     case TK_TUPLETYPE:
   24     {
   25       // Adapt each element.
   26       ast_t* type = ast_from(r_type, ast_id(r_type));
   27       ast_t* child = ast_child(r_type);
   28 
   29       while(child != NULL)
   30       {
   31         ast_append(type, viewpoint_type(l_type, child));
   32         child = ast_sibling(child);
   33       }
   34 
   35       return type;
   36     }
   37 
   38     case TK_TYPEPARAMREF:
   39       upper = VIEW_UPPER_NO;
   40       break;
   41 
   42     case TK_NOMINAL:
   43     {
   44       ast_t* cap = cap_fetch(r_type);
   45 
   46       switch(ast_id(cap))
   47       {
   48         case TK_ISO:
   49         case TK_TRN:
   50         case TK_REF:
   51         case TK_BOX:
   52           // A known refcap on the right can be compacted.
   53           upper = VIEW_UPPER_YES;
   54           break;
   55 
   56         case TK_VAL:
   57         case TK_TAG:
   58         case TK_CAP_SHARE:
   59           // No refcap on the left modifies these.
   60           upper = VIEW_UPPER_FORCE;
   61           break;
   62 
   63         default: {}
   64       }
   65       break;
   66     }
   67 
   68     case TK_ARROW:
   69       break;
   70 
   71     default:
   72       pony_assert(0);
   73       return NULL;
   74   }
   75 
   76   switch(ast_id(l_type))
   77   {
   78     case TK_NOMINAL:
   79     case TK_TYPEPARAMREF:
   80     {
   81       ast_t* cap = cap_fetch(l_type);
   82 
   83       switch(ast_id(cap))
   84       {
   85         case TK_REF:
   86           // ref->T = T
   87           return ast_dup(r_type);
   88 
   89         case TK_CAP_SEND:
   90         case TK_CAP_SHARE:
   91         case TK_CAP_READ:
   92         case TK_CAP_ALIAS:
   93         case TK_CAP_ANY:
   94           // Don't compact through an unknown refcap.
   95           if(upper == VIEW_UPPER_YES)
   96             upper = VIEW_UPPER_NO;
   97           break;
   98 
   99         default: {}
  100       }
  101       break;
  102     }
  103 
  104     case TK_THISTYPE:
  105       if(upper == VIEW_UPPER_YES)
  106         upper = VIEW_UPPER_NO;
  107       break;
  108 
  109     case TK_ISO:
  110     case TK_TRN:
  111     case TK_REF:
  112     case TK_VAL:
  113     case TK_BOX:
  114     case TK_TAG:
  115       break;
  116 
  117     case TK_ARROW:
  118     {
  119       // (T1->T2)->T3 --> T1->(T2->T3)
  120       AST_GET_CHILDREN(l_type, left, right);
  121       ast_t* r_right = viewpoint_type(right, r_type);
  122       return viewpoint_type(left, r_right);
  123     }
  124 
  125     default:
  126       pony_assert(0);
  127       return NULL;
  128   }
  129 
  130   BUILD(arrow, l_type,
  131     NODE(TK_ARROW, TREE(ast_dup(l_type)) TREE(ast_dup(r_type))));
  132 
  133   if(upper != VIEW_UPPER_NO)
  134   {
  135     ast_t* arrow_upper = viewpoint_upper(arrow);
  136 
  137     if(arrow_upper == NULL)
  138       return arrow;
  139 
  140     if(arrow != arrow_upper)
  141     {
  142       ast_free_unattached(arrow);
  143       arrow = arrow_upper;
  144     }
  145   }
  146 
  147   return arrow;
  148 }
  149 
  150 ast_t* viewpoint_upper(ast_t* type)
  151 {
  152   // T = N | A
  153   // s = {k}
  154   // upper(s p'->T k p) = isect[k' in s](T (k'->k) eph(s, p', p))
  155   // eph(s, p', p) = { unalias(p) if p' = ^, forall k in s . k in {iso, trn}
  156   //                 { p          otherwise
  157   pony_assert(ast_id(type) == TK_ARROW);
  158   AST_GET_CHILDREN(type, left, right);
  159   ast_t* r_right = right;
  160 
  161   switch(ast_id(right))
  162   {
  163     case TK_NOMINAL:
  164     case TK_TYPEPARAMREF:
  165       break;
  166 
  167     case TK_ARROW:
  168       // Arrow types are right associative.
  169       r_right = viewpoint_upper(right);
  170 
  171       if(r_right == NULL)
  172         return NULL;
  173       break;
  174 
  175     default:
  176       pony_assert(0);
  177       return NULL;
  178   }
  179 
  180   token_id l_cap = TK_NONE;
  181   token_id l_eph = TK_NONE;
  182 
  183   switch(ast_id(left))
  184   {
  185     case TK_ISO:
  186     case TK_TRN:
  187     case TK_REF:
  188     case TK_VAL:
  189     case TK_BOX:
  190     case TK_TAG:
  191       l_cap = ast_id(left);
  192       break;
  193 
  194     case TK_THISTYPE:
  195       l_cap = TK_BOX;
  196       break;
  197 
  198     case TK_NOMINAL:
  199     case TK_TYPEPARAMREF:
  200     {
  201       ast_t* left_cap = cap_fetch(left);
  202       ast_t* left_eph = ast_sibling(left_cap);
  203 
  204       l_cap = ast_id(left_cap);
  205       l_eph = ast_id(left_eph);
  206       break;
  207     }
  208 
  209     default:
  210       pony_assert(0);
  211       return NULL;
  212   }
  213 
  214   ast_t* right_cap = cap_fetch(r_right);
  215   ast_t* right_eph = ast_sibling(right_cap);
  216 
  217   token_id r_cap = ast_id(right_cap);
  218   token_id r_eph = ast_id(right_eph);
  219 
  220   // No result: left side could be a tag.
  221   if(!cap_view_upper(l_cap, l_eph, &r_cap, &r_eph))
  222     return NULL;
  223 
  224   ast_t* rr_right = set_cap_and_ephemeral(r_right, r_cap, r_eph);
  225 
  226   if(r_right != right)
  227     ast_free_unattached(r_right);
  228 
  229   return rr_right;
  230 }
  231 
  232 ast_t* viewpoint_lower(ast_t* type)
  233 {
  234   // T = N | A
  235   // s = {k}
  236   // upper(s p'->T k p) = union[k' in s](T (k'->k) eph(s, p', p))
  237   // eph(s, p', p) = { unalias(p) if p' = ^, exists k in s . k in {iso, trn}
  238   //                 { p          otherwise
  239   pony_assert(ast_id(type) == TK_ARROW);
  240   AST_GET_CHILDREN(type, left, right);
  241   ast_t* r_right = right;
  242 
  243   switch(ast_id(right))
  244   {
  245     case TK_NOMINAL:
  246     case TK_TYPEPARAMREF:
  247       break;
  248 
  249     case TK_ARROW:
  250       // Arrow types are right associative.
  251       r_right = viewpoint_lower(right);
  252 
  253       if(r_right == NULL)
  254         return NULL;
  255       break;
  256 
  257     default:
  258       pony_assert(0);
  259       return NULL;
  260   }
  261 
  262   token_id l_cap = TK_NONE;
  263   token_id l_eph = TK_NONE;
  264 
  265   switch(ast_id(left))
  266   {
  267     case TK_ISO:
  268     case TK_TRN:
  269     case TK_REF:
  270     case TK_VAL:
  271     case TK_BOX:
  272     case TK_TAG:
  273       l_cap = ast_id(left);
  274       break;
  275 
  276     case TK_THISTYPE:
  277       l_cap = TK_CAP_READ;
  278       break;
  279 
  280     case TK_NOMINAL:
  281     case TK_TYPEPARAMREF:
  282     {
  283       ast_t* left_cap = cap_fetch(left);
  284       ast_t* left_eph = ast_sibling(left_cap);
  285 
  286       l_cap = ast_id(left_cap);
  287       l_eph = ast_id(left_eph);
  288       break;
  289     }
  290 
  291     default:
  292       pony_assert(0);
  293       return NULL;
  294   }
  295 
  296   ast_t* right_cap = cap_fetch(r_right);
  297   ast_t* right_eph = ast_sibling(right_cap);
  298 
  299   token_id r_cap = ast_id(right_cap);
  300   token_id r_eph = ast_id(right_eph);
  301 
  302   // No result: left side could be a tag.
  303   if(!cap_view_lower(l_cap, l_eph, &r_cap, &r_eph))
  304     return NULL;
  305 
  306   ast_t* rr_right = set_cap_and_ephemeral(r_right, r_cap, r_eph);
  307 
  308   if(r_right != right)
  309     ast_free_unattached(r_right);
  310 
  311   return rr_right;
  312 }
  313 
  314 static void replace_type(ast_t** astp, ast_t* target, ast_t* with)
  315 {
  316   ast_t* ast = *astp;
  317   ast_t* child = ast_child(ast);
  318 
  319   while(child != NULL)
  320   {
  321     replace_type(&child, target, with);
  322     child = ast_sibling(child);
  323   }
  324 
  325   ast_t* node_type = ast_type(ast);
  326 
  327   if(node_type != NULL)
  328     replace_type(&node_type, target, with);
  329 
  330   if(ast_id(ast) == ast_id(target))
  331   {
  332     switch(ast_id(target))
  333     {
  334       case TK_THISTYPE:
  335         // Replace `this`.
  336         ast_replace(astp, ast_dup(with));
  337         break;
  338 
  339       case TK_TYPEPARAMREF:
  340       {
  341         // Replace a typeparamref with a reification.
  342         ast_t* target_def = (ast_t*)ast_data(target);
  343         ast_t* left_def = (ast_t*)ast_data(ast);
  344 
  345         if(target_def == left_def)
  346         {
  347           AST_GET_CHILDREN(ast, id, cap, eph);
  348           ast_t* a_with = with;
  349 
  350           switch(ast_id(eph))
  351           {
  352             case TK_EPHEMERAL:
  353               a_with = consume_type(with, TK_NONE);
  354               break;
  355 
  356             case TK_ALIASED:
  357               a_with = alias(with);
  358               break;
  359 
  360             default: {}
  361           }
  362 
  363           if(a_with == with)
  364             a_with = ast_dup(with);
  365 
  366           ast_replace(astp, a_with);
  367         }
  368         break;
  369       }
  370 
  371       default:
  372         pony_assert(0);
  373     }
  374   } else if(ast_id(ast) == TK_ARROW) {
  375     // Recalculate all arrow types.
  376     AST_GET_CHILDREN(ast, left, right);
  377     ast_t* r_type = viewpoint_type(left, right);
  378     ast_replace(astp, r_type);
  379   }
  380 }
  381 
  382 ast_t* viewpoint_replace(ast_t* ast, ast_t* target, ast_t* with, bool duplicate)
  383 {
  384   // Target is thistype or a typeparamref. With is a type (when replacing
  385   // `this` in a reified method signature) or a single capability (when
  386   // typechecking arrow types).
  387   pony_assert(
  388     (ast_id(target) == TK_THISTYPE) ||
  389     (ast_id(target) == TK_TYPEPARAMREF));
  390 
  391   ast_t* r_ast;
  392 
  393   if(duplicate)
  394     r_ast = ast_dup(ast);
  395   else
  396     r_ast = ast;
  397 
  398   replace_type(&r_ast, target, with);
  399   return r_ast;
  400 }
  401 
  402 ast_t* viewpoint_replacethis(ast_t* ast, ast_t* with, bool duplicate)
  403 {
  404   ast_t* thistype = ast_from(ast, TK_THISTYPE);
  405   ast_t* r_ast = viewpoint_replace(ast, thistype, with, duplicate);
  406   ast_free_unattached(thistype);
  407   return r_ast;
  408 }
  409 
  410 static void replace_typeparam(ast_t* tuple, ast_t* type, ast_t* typeparamref,
  411   token_id cap, token_id eph)
  412 {
  413   ast_t* r_tp = set_cap_and_ephemeral(typeparamref, cap, eph);
  414   ast_t* r_type = viewpoint_replace(type, typeparamref, r_tp, true);
  415   ast_append(tuple, r_type);
  416 }
  417 
  418 ast_t* viewpoint_reifytypeparam(ast_t* type, ast_t* typeparamref)
  419 {
  420   pony_assert(ast_id(typeparamref) == TK_TYPEPARAMREF);
  421   AST_GET_CHILDREN(typeparamref, id, cap, eph);
  422 
  423   switch(ast_id(cap))
  424   {
  425     case TK_ISO:
  426     case TK_TRN:
  427     case TK_REF:
  428     case TK_VAL:
  429     case TK_BOX:
  430     case TK_TAG:
  431       return NULL;
  432 
  433     case TK_CAP_SEND:
  434     {
  435       ast_t* tuple = ast_from(type, TK_TUPLETYPE);
  436       replace_typeparam(tuple, type, typeparamref, TK_ISO, ast_id(eph));
  437       replace_typeparam(tuple, type, typeparamref, TK_VAL, TK_NONE);
  438       replace_typeparam(tuple, type, typeparamref, TK_TAG, TK_NONE);
  439       return tuple;
  440     }
  441 
  442     case TK_CAP_SHARE:
  443     {
  444       ast_t* tuple = ast_from(type, TK_TUPLETYPE);
  445       replace_typeparam(tuple, type, typeparamref, TK_VAL, TK_NONE);
  446       replace_typeparam(tuple, type, typeparamref, TK_TAG, TK_NONE);
  447       return tuple;
  448     }
  449 
  450     case TK_CAP_READ:
  451     {
  452       ast_t* tuple = ast_from(type, TK_TUPLETYPE);
  453       replace_typeparam(tuple, type, typeparamref, TK_REF, TK_NONE);
  454       replace_typeparam(tuple, type, typeparamref, TK_VAL, TK_NONE);
  455       replace_typeparam(tuple, type, typeparamref, TK_BOX, TK_NONE);
  456       return tuple;
  457     }
  458 
  459     case TK_CAP_ALIAS:
  460     {
  461       ast_t* tuple = ast_from(type, TK_TUPLETYPE);
  462       replace_typeparam(tuple, type, typeparamref, TK_REF, TK_NONE);
  463       replace_typeparam(tuple, type, typeparamref, TK_VAL, TK_NONE);
  464       replace_typeparam(tuple, type, typeparamref, TK_BOX, TK_NONE);
  465       replace_typeparam(tuple, type, typeparamref, TK_TAG, TK_NONE);
  466       return tuple;
  467     }
  468 
  469     case TK_CAP_ANY:
  470     {
  471       ast_t* tuple = ast_from(type, TK_TUPLETYPE);
  472       replace_typeparam(tuple, type, typeparamref, TK_ISO, ast_id(eph));
  473       replace_typeparam(tuple, type, typeparamref, TK_TRN, ast_id(eph));
  474       replace_typeparam(tuple, type, typeparamref, TK_REF, TK_NONE);
  475       replace_typeparam(tuple, type, typeparamref, TK_VAL, TK_NONE);
  476       replace_typeparam(tuple, type, typeparamref, TK_BOX, TK_NONE);
  477       replace_typeparam(tuple, type, typeparamref, TK_TAG, TK_NONE);
  478       return tuple;
  479     }
  480 
  481     default: {}
  482   }
  483 
  484   pony_assert(0);
  485   return NULL;
  486 }
  487 
  488 ast_t* viewpoint_reifythis(ast_t* type)
  489 {
  490   ast_t* tuple = ast_from(type, TK_TUPLETYPE);
  491 
  492   ast_t* this_ref = ast_from(type, TK_REF);
  493   ast_append(tuple, viewpoint_replacethis(type, this_ref, true));
  494   ast_free_unattached(this_ref);
  495 
  496   ast_t* this_val = ast_from(type, TK_VAL);
  497   ast_append(tuple, viewpoint_replacethis(type, this_val, true));
  498   ast_free_unattached(this_val);
  499 
  500   ast_t* this_box = ast_from(type, TK_BOX);
  501   ast_append(tuple, viewpoint_replacethis(type, this_box, true));
  502   ast_free_unattached(this_box);
  503 
  504   return tuple;
  505 }
  506 
  507 bool viewpoint_reifypair(ast_t* a, ast_t* b, ast_t** r_a, ast_t** r_b)
  508 {
  509   pony_assert(ast_id(a) == TK_ARROW);
  510   pony_assert(ast_id(b) == TK_ARROW);
  511 
  512   // Find the first left side that needs reification.
  513   ast_t* test = a;
  514 
  515   while(ast_id(test) == TK_ARROW)
  516   {
  517     AST_GET_CHILDREN(test, left, right);
  518 
  519     switch(ast_id(left))
  520     {
  521       case TK_THISTYPE:
  522       {
  523         // Reify on both sides.
  524         *r_a = viewpoint_reifythis(a);
  525         *r_b = viewpoint_reifythis(b);
  526         return true;
  527       }
  528 
  529       case TK_TYPEPARAMREF:
  530       {
  531         // If we can reify a, we can reify b.
  532         ast_t* r = viewpoint_reifytypeparam(a, left);
  533 
  534         if(r == NULL)
  535           break;
  536 
  537         *r_a = r;
  538         *r_b = viewpoint_reifytypeparam(b, left);
  539         return true;
  540       }
  541 
  542       default: {}
  543     }
  544 
  545     test = right;
  546   }
  547 
  548   if(ast_id(test) == TK_TYPEPARAMREF)
  549   {
  550     ast_t* r = viewpoint_reifytypeparam(a, test);
  551 
  552     if(r == NULL)
  553       return false;
  554 
  555     *r_a = r;
  556     *r_b = viewpoint_reifytypeparam(b, test);
  557     return true;
  558   }
  559 
  560   return false;
  561 }