"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.0/src/libponyc/pass/refer.c" (1 Nov 2019, 43829 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 "refer.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.32.0_vs_0.33.0.

    1 #include "refer.h"
    2 #include "../ast/id.h"
    3 #include "../pass/expr.h"
    4 #include "../../libponyrt/mem/pool.h"
    5 #include "ponyassert.h"
    6 #include <string.h>
    7 
    8 /**
    9  * Make sure the definition of something occurs before its use. This is for
   10  * both fields and local variable.
   11  */
   12 bool def_before_use(pass_opt_t* opt, ast_t* def, ast_t* use, const char* name)
   13 {
   14   if((ast_line(def) > ast_line(use)) ||
   15      ((ast_line(def) == ast_line(use)) &&
   16       (ast_pos(def) > ast_pos(use))))
   17   {
   18     ast_error(opt->check.errors, use,
   19       "declaration of '%s' appears after use", name);
   20     ast_error_continue(opt->check.errors, def,
   21       "declaration of '%s' appears here", name);
   22     return false;
   23   }
   24 
   25   return true;
   26 }
   27 
   28 static bool is_this_incomplete(pass_opt_t* opt, ast_t* ast)
   29 {
   30   // If we're in a default field initialiser, we're incomplete by definition.
   31   if(opt->check.frame->method == NULL)
   32     return true;
   33 
   34   // If we're not in a constructor, we're complete by definition.
   35   if(ast_id(opt->check.frame->method) != TK_NEW)
   36     return false;
   37 
   38   // Check if all fields have been marked as defined.
   39   ast_t* members = ast_childidx(opt->check.frame->type, 4);
   40   ast_t* member = ast_child(members);
   41 
   42   while(member != NULL)
   43   {
   44     switch(ast_id(member))
   45     {
   46       case TK_FLET:
   47       case TK_FVAR:
   48       case TK_EMBED:
   49       {
   50         sym_status_t status;
   51         ast_t* id = ast_child(member);
   52         ast_get(ast, ast_name(id), &status);
   53 
   54         if(status != SYM_DEFINED)
   55           return true;
   56 
   57         break;
   58       }
   59 
   60       default: {}
   61     }
   62 
   63     member = ast_sibling(member);
   64   }
   65 
   66   return false;
   67 }
   68 
   69 
   70 // This function generates the fully qualified string (without the `this`) for a
   71 // reference (i.e. `a.b.c.d.e`) and ensures it is part of the compiler
   72 // `stringtab`. It is used to generate this fully qualified string for the field
   73 // being consumed for tracking its `consume`d status via the ast `symtab`. It is
   74 // also used to generate the fully qualified string to ensure that same field is
   75 // being assigned to as part of the same expression as the consume. Lastly, it
   76 // is used to get the definition for the type based on the `ast_data` to ensure
   77 // at some point the field is tied to a real type even if we haven't quite fully
   78 // determined the type of each field/subfield reference yet.
   79 static const char* generate_multi_dot_name(ast_t* ast, ast_t** def_found) {
   80   pony_assert(ast_id(ast) == TK_DOT);
   81 
   82   ast_t* def = NULL;
   83   size_t len = 0;
   84   ast_t* temp_ast = ast;
   85 
   86   do {
   87     if(ast_id(temp_ast) != TK_DOT)
   88       break;
   89 
   90     AST_GET_CHILDREN(temp_ast, left, right);
   91     def = (ast_t*) ast_data(left);
   92     temp_ast = left;
   93 
   94     // the `+ 1` is for the '.' needed in the string
   95     len += strlen(ast_name(right)) + 1;
   96   } while(def == NULL);
   97 
   98   switch(ast_id(temp_ast))
   99   {
  100     case TK_DOT:
  101     {
  102       AST_GET_CHILDREN(temp_ast, left, right);
  103       if(ast_id(left) == TK_THIS)
  104       {
  105         temp_ast = right;
  106         len += strlen(ast_name(temp_ast));
  107       }
  108       else
  109         pony_assert(0);
  110       break;
  111     }
  112 
  113     case TK_LETREF:
  114     case TK_VARREF:
  115     case TK_REFERENCE:
  116     case TK_PARAMREF:
  117     {
  118       temp_ast = ast_child(temp_ast);
  119       len += strlen(ast_name(temp_ast));
  120       break;
  121     }
  122 
  123     case TK_THIS:
  124     {
  125       temp_ast = ast_sibling(temp_ast);
  126       // string len already added by loop above
  127       // subtract 1 because we don't have to add '.'
  128       // since we're ignoring the `this`
  129       len -= 1;
  130       break;
  131     }
  132 
  133     default:
  134     {
  135       pony_assert(0);
  136     }
  137   }
  138 
  139   if(def_found != NULL)
  140   {
  141     *def_found = def;
  142 
  143     if(def == NULL)
  144       return stringtab("");
  145   }
  146 
  147   // for the \0 at the end
  148   len = len + 1;
  149 
  150   char* buf = (char*)ponyint_pool_alloc_size(len);
  151   size_t offset = 0;
  152   const char* name = ast_name(temp_ast);
  153   size_t slen = strlen(name);
  154   memcpy(buf + offset, name, slen);
  155   offset += slen;
  156   temp_ast = ast_parent(temp_ast);
  157 
  158   while(temp_ast != ast)
  159   {
  160     buf[offset] = '.';
  161     offset += 1;
  162     temp_ast = ast_sibling(temp_ast);
  163     name = ast_name(temp_ast);
  164     slen = strlen(name);
  165     memcpy(buf + offset, name, slen);
  166     offset += slen;
  167     temp_ast = ast_parent(temp_ast);
  168   }
  169 
  170   pony_assert((offset + 1) == len);
  171   buf[offset] = '\0';
  172 
  173   return stringtab_consume(buf, len);
  174 }
  175 
  176 static bool is_matching_assign_lhs(ast_t* a, ast_t* b)
  177 {
  178   // Has to be the left hand side of an assignment (the first child).
  179   if(a == b)
  180     return true;
  181 
  182   // or two subfield references that match
  183   if((ast_id(a) == TK_DOT) && (ast_id(b) == TK_DOT))
  184   {
  185     // get fully qualified string identifier without `this`
  186     const char* a_name = generate_multi_dot_name(a, NULL);
  187     const char* b_name = generate_multi_dot_name(b, NULL);
  188 
  189     if(a_name == b_name)
  190       return true;
  191   }
  192 
  193   return false;
  194 }
  195 
  196 static bool is_assigned_to(ast_t* ast, bool check_result_needed)
  197 {
  198   while(true)
  199   {
  200     ast_t* parent = ast_parent(ast);
  201 
  202     switch(ast_id(parent))
  203     {
  204       case TK_ASSIGN:
  205       {
  206         if(!is_matching_assign_lhs(ast_child(parent), ast))
  207           return false;
  208 
  209         if(!check_result_needed)
  210           return true;
  211 
  212         // The result of that assignment can't be used.
  213         return !is_result_needed(parent);
  214       }
  215 
  216       case TK_SEQ:
  217       {
  218         // Might be in a tuple on the left hand side.
  219         if(ast_childcount(parent) > 1)
  220           return false;
  221 
  222         break;
  223       }
  224 
  225       case TK_TUPLE:
  226         break;
  227 
  228       default:
  229         return false;
  230     }
  231 
  232     ast = parent;
  233   }
  234 }
  235 
  236 /**
  237  * Return true if this is a reference is just being used to call a constructor
  238  * on the type, in which case we don't care if it's status is SYM_DEFINED yet.
  239  *
  240  * Example:
  241  *   let a: Array[U8] = a.create()
  242  */
  243 static bool is_constructed_from(ast_t* ast)
  244 {
  245   ast_t* parent = ast_parent(ast);
  246 
  247   if(ast_id(parent) != TK_DOT)
  248     return false;
  249 
  250   AST_GET_CHILDREN(parent, left, right);
  251   if(left != ast)
  252     return false;
  253 
  254   ast_t* def = (ast_t*)ast_data(ast);
  255 
  256   // no definition found because it's a TK_DOT
  257   if(def == NULL)
  258   {
  259     pony_assert(ast_id(ast) == TK_DOT);
  260     return false;
  261   }
  262 
  263   // TK_LET and TK_VAR have their symtable point to the TK_ID child,
  264   // so if we encounter that here, we move up to the parent node.
  265   if(ast_id(def) == TK_ID)
  266     def = ast_parent(def);
  267 
  268   switch(ast_id(def))
  269   {
  270     case TK_VAR:
  271     case TK_LET:
  272     case TK_FVAR:
  273     case TK_FLET:
  274     case TK_EMBED:
  275     {
  276       ast_t* typeref = ast_childidx(def, 1);
  277       if((typeref == NULL) || (ast_data(typeref) == NULL))
  278         return false;
  279 
  280       ast_t* typedefn = (ast_t*)ast_data(typeref);
  281       ast_t* find = ast_get(typedefn, ast_name(right), NULL);
  282 
  283       return (find != NULL) && (ast_id(find) == TK_NEW);
  284     }
  285 
  286     default: {}
  287   }
  288 
  289   return false;
  290 }
  291 
  292 static bool valid_reference(pass_opt_t* opt, ast_t* ast, sym_status_t status)
  293 {
  294   if(is_constructed_from(ast))
  295     return true;
  296 
  297   switch(status)
  298   {
  299     case SYM_DEFINED:
  300       return true;
  301 
  302     case SYM_CONSUMED:
  303     case SYM_CONSUMED_SAME_EXPR:
  304       if(is_assigned_to(ast, true))
  305         return true;
  306 
  307       ast_error(opt->check.errors, ast,
  308         "can't use a consumed local or field in an expression");
  309       return false;
  310 
  311     case SYM_UNDEFINED:
  312       if(is_assigned_to(ast, true))
  313         return true;
  314 
  315       ast_error(opt->check.errors, ast,
  316         "can't use an undefined variable in an expression");
  317       return false;
  318 
  319     case SYM_NONE:
  320       pony_assert(ast_id(ast) == TK_DOT);
  321       return true;
  322 
  323     default: {}
  324   }
  325 
  326   pony_assert(0);
  327   return false;
  328 }
  329 
  330 static const char* suggest_alt_name(ast_t* ast, const char* name)
  331 {
  332   pony_assert(ast != NULL);
  333   pony_assert(name != NULL);
  334 
  335   size_t name_len = strlen(name);
  336 
  337   if(is_name_private(name))
  338   {
  339     // Try without leading underscore
  340     const char* try_name = stringtab(name + 1);
  341 
  342     if(ast_get(ast, try_name, NULL) != NULL)
  343       return try_name;
  344   }
  345   else
  346   {
  347     // Try with a leading underscore
  348     char* buf = (char*)ponyint_pool_alloc_size(name_len + 2);
  349     buf[0] = '_';
  350     memcpy(buf + 1, name, name_len + 1);
  351     const char* try_name = stringtab_consume(buf, name_len + 2);
  352 
  353     if(ast_get(ast, try_name, NULL) != NULL)
  354       return try_name;
  355   }
  356 
  357   // Try with a different case (without crossing type/value boundary)
  358   ast_t* case_ast = ast_get_case(ast, name, NULL);
  359   if(case_ast != NULL)
  360   {
  361     ast_t* id = case_ast;
  362 
  363     int tk = ast_id(id);
  364     if(tk != TK_ID)
  365     {
  366       AST_GET_CHILDREN(case_ast, first, second);
  367 
  368       if((tk = ast_id(first)) == TK_ID)
  369       {
  370         // First is a TK_ID give it as a suggestion
  371         id = first;
  372       } else if((tk = ast_id(second)) == TK_ID) {
  373         // Second is a TK_ID give it as a suggestion
  374         id = second;
  375       } else {
  376         // Giving up on different case as tk != TK_ID
  377       }
  378     }
  379 
  380     if(tk == TK_ID)
  381     {
  382       const char* try_name = ast_name(id);
  383 
  384       if(ast_get(ast, try_name, NULL) != NULL)
  385         return try_name;
  386     }
  387   }
  388 
  389   // Give up
  390   return NULL;
  391 }
  392 
  393 static bool refer_this(pass_opt_t* opt, ast_t* ast)
  394 {
  395   pony_assert(ast_id(ast) == TK_THIS);
  396 
  397   // Can only use a this reference if it hasn't been consumed yet.
  398   sym_status_t status;
  399   ast_get(ast, stringtab("this"), &status);
  400 
  401   if((status == SYM_CONSUMED) || (status == SYM_CONSUMED_SAME_EXPR))
  402   {
  403     ast_error(opt->check.errors, ast,
  404       "can't use a consumed 'this' in an expression");
  405     return false;
  406   }
  407   pony_assert(status == SYM_NONE);
  408 
  409   // Mark the this reference as incomplete if not all fields are defined yet.
  410   if(is_this_incomplete(opt, ast))
  411     ast_setflag(ast, AST_FLAG_INCOMPLETE);
  412 
  413   return true;
  414 }
  415 
  416 bool refer_reference(pass_opt_t* opt, ast_t** astp)
  417 {
  418   ast_t* ast = *astp;
  419 
  420   const char* name = ast_name(ast_child(ast));
  421 
  422   // Handle the special case of the "don't care" reference (`_`)
  423   if(is_name_dontcare(name))
  424   {
  425     ast_setid(ast, TK_DONTCAREREF);
  426 
  427     return true;
  428   }
  429 
  430   // Everything we reference must be in scope, so we can use ast_get for lookup.
  431   sym_status_t status;
  432   ast_t* def = ast_get(ast, ast_name(ast_child(ast)), &status);
  433 
  434   // If nothing was found, we fail, but also try to suggest an alternate name.
  435   if(def == NULL)
  436   {
  437     const char* alt_name = suggest_alt_name(ast, name);
  438 
  439     if(alt_name == NULL)
  440       ast_error(opt->check.errors, ast, "can't find declaration of '%s'", name);
  441     else
  442       ast_error(opt->check.errors, ast,
  443         "can't find declaration of '%s', did you mean '%s'?", name, alt_name);
  444 
  445     return false;
  446   }
  447 
  448   // Save the found definition in the AST, so we don't need to look it up again.
  449   ast_setdata(ast, (void*)def);
  450 
  451   switch(ast_id(def))
  452   {
  453     case TK_PACKAGE:
  454     {
  455       // Only allowed if in a TK_DOT with a type.
  456       if(ast_id(ast_parent(ast)) != TK_DOT)
  457       {
  458         ast_error(opt->check.errors, ast,
  459           "a package can only appear as a prefix to a type");
  460         return false;
  461       }
  462 
  463       ast_setid(ast, TK_PACKAGEREF);
  464       return true;
  465     }
  466 
  467     case TK_INTERFACE:
  468     case TK_TRAIT:
  469     case TK_TYPE:
  470     case TK_TYPEPARAM:
  471     case TK_PRIMITIVE:
  472     case TK_STRUCT:
  473     case TK_CLASS:
  474     case TK_ACTOR:
  475     {
  476       ast_setid(ast, TK_TYPEREF);
  477 
  478       ast_add(ast, ast_from(ast, TK_NONE));    // 1st child: package reference
  479       ast_append(ast, ast_from(ast, TK_NONE)); // 3rd child: type args
  480 
  481       return true;
  482     }
  483 
  484     case TK_FVAR:
  485     case TK_FLET:
  486     case TK_EMBED:
  487     case TK_NEW:
  488     case TK_BE:
  489     case TK_FUN:
  490     {
  491       // Transform to "this.f".
  492       ast_t* dot = ast_from(ast, TK_DOT);
  493       ast_add(dot, ast_child(ast));
  494 
  495       ast_t* self = ast_from(ast, TK_THIS);
  496       ast_add(dot, self);
  497 
  498       ast_replace(astp, dot);
  499       ast = *astp;
  500       return refer_this(opt, self) && refer_dot(opt, ast);
  501     }
  502 
  503     case TK_PARAM:
  504     {
  505       if(opt->check.frame->def_arg != NULL)
  506       {
  507         ast_error(opt->check.errors, ast,
  508           "can't reference a parameter in a default argument");
  509         return false;
  510       }
  511 
  512       if(!def_before_use(opt, def, ast, name))
  513         return false;
  514 
  515       if(!valid_reference(opt, ast, status))
  516         return false;
  517 
  518       ast_setid(ast, TK_PARAMREF);
  519       return true;
  520     }
  521 
  522     case TK_VAR:
  523     case TK_LET:
  524     case TK_MATCH_CAPTURE:
  525     {
  526       if(!def_before_use(opt, def, ast, name))
  527         return false;
  528 
  529       if(!valid_reference(opt, ast, status))
  530         return false;
  531 
  532       if(ast_id(def) == TK_VAR)
  533         ast_setid(ast, TK_VARREF);
  534       else
  535         ast_setid(ast, TK_LETREF);
  536 
  537       return true;
  538     }
  539 
  540     default: {}
  541   }
  542 
  543   pony_assert(0);
  544   return false;
  545 }
  546 
  547 static bool refer_packageref_dot(pass_opt_t* opt, ast_t* ast)
  548 {
  549   pony_assert(ast_id(ast) == TK_DOT);
  550   AST_GET_CHILDREN(ast, left, right);
  551   pony_assert(ast_id(left) == TK_PACKAGEREF);
  552   pony_assert(ast_id(right) == TK_ID);
  553 
  554   // Must be a type in a package.
  555   const char* package_name = ast_name(ast_child(left));
  556   ast_t* package = ast_get(left, package_name, NULL);
  557 
  558   if(package == NULL)
  559   {
  560     ast_error(opt->check.errors, right, "can't access package '%s'",
  561       package_name);
  562     return false;
  563   }
  564 
  565   pony_assert(ast_id(package) == TK_PACKAGE);
  566   const char* type_name = ast_name(right);
  567   ast_t* def = ast_get(package, type_name, NULL);
  568 
  569   if(def == NULL)
  570   {
  571     ast_error(opt->check.errors, right, "can't find type '%s' in package '%s'",
  572       type_name, package_name);
  573     return false;
  574   }
  575 
  576   ast_setdata(ast, (void*)def);
  577   ast_setid(ast, TK_TYPEREF);
  578 
  579   ast_append(ast, ast_from(ast, TK_NONE)); // 3rd child: type args
  580 
  581   return true;
  582 }
  583 
  584 static bool refer_this_dot(pass_opt_t* opt, ast_t* ast)
  585 {
  586   pony_assert(ast_id(ast) == TK_DOT);
  587   AST_GET_CHILDREN(ast, left, right);
  588   pony_assert(ast_id(left) == TK_THIS);
  589   pony_assert(ast_id(right) == TK_ID);
  590 
  591   const char* name = ast_name(right);
  592 
  593   sym_status_t status;
  594   ast_t* def = ast_get(ast, name, &status);
  595   ast_setdata(ast, (void*)def);
  596 
  597   // If nothing was found, we fail, but also try to suggest an alternate name.
  598   if(def == NULL)
  599   {
  600     const char* alt_name = suggest_alt_name(ast, name);
  601 
  602     if(alt_name == NULL)
  603       ast_error(opt->check.errors, ast, "can't find declaration of '%s'", name);
  604     else
  605       ast_error(opt->check.errors, ast,
  606         "can't find declaration of '%s', did you mean '%s'?", name, alt_name);
  607 
  608     return false;
  609   }
  610 
  611   switch(ast_id(def))
  612   {
  613     case TK_FVAR:
  614     case TK_FLET:
  615     case TK_EMBED:
  616       if(!valid_reference(opt, ast, status))
  617         return false;
  618       break;
  619 
  620     default: {}
  621   }
  622 
  623   return true;
  624 }
  625 
  626 static bool refer_multi_dot(pass_opt_t* opt, ast_t* ast)
  627 {
  628   pony_assert(ast_id(ast) == TK_DOT);
  629   AST_GET_CHILDREN(ast, left, right);
  630 
  631   // get fully qualified string identifier without `this`
  632   const char* name = generate_multi_dot_name(ast, NULL);
  633 
  634   // use this string to check status using `valid_reference` function.
  635   sym_status_t status;
  636   ast_get(ast, name, &status);
  637 
  638 
  639   if(!valid_reference(opt, ast, status))
  640     return false;
  641 
  642   return true;
  643 }
  644 
  645 bool refer_dot(pass_opt_t* opt, ast_t* ast)
  646 {
  647   pony_assert(ast_id(ast) == TK_DOT);
  648   AST_GET_CHILDREN(ast, left, right);
  649 
  650   switch(ast_id(left))
  651   {
  652     case TK_PACKAGEREF: return refer_packageref_dot(opt, ast);
  653     case TK_THIS:       return refer_this_dot(opt, ast);
  654     case TK_PARAMREF:
  655     case TK_VARREF:
  656     case TK_LETREF:
  657     case TK_DOT:
  658     {
  659       // check multi_dot reference if it's not a function call
  660       // only if we had a field consume/reassign
  661       if(!ast_checkflag(ast, AST_FLAG_FCNSM_REASGN)
  662         && (ast_id(ast_parent(ast)) != TK_CALL)
  663         && (ast_id(ast_parent(ast)) != TK_QUALIFY))
  664         return refer_multi_dot(opt, ast);
  665     }
  666     default: {}
  667   }
  668 
  669   return true;
  670 }
  671 
  672 static bool qualify_typeref(pass_opt_t* opt, ast_t* ast)
  673 {
  674   (void)opt;
  675   ast_t* typeref = ast_child(ast);
  676 
  677   // If the typeref already has type args, it can't get any more, so we'll
  678   // leave as TK_QUALIFY, so expr pass will sugar as qualified call to apply.
  679   if(ast_id(ast_childidx(typeref, 2)) == TK_TYPEARGS)
  680     return true;
  681 
  682   ast_t* def = (ast_t*)ast_data(typeref);
  683   pony_assert(def != NULL);
  684 
  685   // If the type isn't polymorphic it can't get type args at all, so we'll
  686   // leave as TK_QUALIFY, so expr pass will sugar as qualified call to apply.
  687   ast_t* typeparams = ast_childidx(def, 1);
  688   if(ast_id(typeparams) == TK_NONE)
  689     return true;
  690 
  691   // Now, we want to get rid of the inner typeref, take its children, and
  692   // convert this TK_QUALIFY node into a TK_TYPEREF node with type args.
  693   ast_setdata(ast, (void*)def);
  694   ast_setid(ast, TK_TYPEREF);
  695 
  696   pony_assert(typeref == ast_pop(ast));
  697   ast_t* package   = ast_pop(typeref);
  698   ast_t* type_name = ast_pop(typeref);
  699   ast_free(typeref);
  700 
  701   ast_add(ast, type_name);
  702   ast_add(ast, package);
  703 
  704   return true;
  705 }
  706 
  707 bool refer_qualify(pass_opt_t* opt, ast_t* ast)
  708 {
  709   pony_assert(ast_id(ast) == TK_QUALIFY);
  710 
  711   if(ast_id(ast_child(ast)) == TK_TYPEREF)
  712     return qualify_typeref(opt, ast);
  713 
  714   return true;
  715 }
  716 
  717 static bool assign_multi_dot(pass_opt_t* opt, ast_t* ast, bool need_value)
  718 {
  719   pony_assert(ast_id(ast) == TK_DOT);
  720 
  721   // get fully qualified string identifier without `this`
  722   const char* name = generate_multi_dot_name(ast, NULL);
  723 
  724   sym_status_t status;
  725   ast_get(ast, name, &status);
  726 
  727   switch(status)
  728   {
  729     case SYM_UNDEFINED:
  730       if(need_value)
  731       {
  732         ast_error(opt->check.errors, ast,
  733           "the left side is undefined but its value is used");
  734         return false;
  735       }
  736 
  737       ast_setstatus(ast, name, SYM_DEFINED);
  738       return true;
  739 
  740     case SYM_DEFINED:
  741       return true;
  742 
  743     case SYM_CONSUMED:
  744     case SYM_CONSUMED_SAME_EXPR:
  745     {
  746       bool ok = true;
  747 
  748       if(need_value)
  749       {
  750         ast_error(opt->check.errors, ast,
  751           "the left side is consumed but its value is used");
  752         ok = false;
  753       }
  754 
  755       if(opt->check.frame->try_expr != NULL)
  756       {
  757         if(status == SYM_CONSUMED)
  758         {
  759           ast_error(opt->check.errors, ast,
  760             "can't reassign to a consumed identifier in a try expression unless"
  761             " it is reassigned in the same expression");
  762           ok = false;
  763         }
  764         // SYM_CONSUMED_SAME_EXPR is allowed to pass; verify pass will check if
  765         // there are any partial calls/errors and throw an error if necessary
  766       }
  767 
  768       if(ok)
  769         ast_setstatus(ast, name, SYM_DEFINED);
  770 
  771       return ok;
  772     }
  773 
  774     case SYM_NONE:
  775       pony_assert(ast_id(ast) == TK_DOT);
  776       return true;
  777 
  778     default: {}
  779   }
  780 
  781   pony_assert(0);
  782   return false;
  783 }
  784 
  785 static bool assign_id(pass_opt_t* opt, ast_t* ast, bool let, bool need_value)
  786 {
  787   pony_assert(ast_id(ast) == TK_ID);
  788   const char* name = ast_name(ast);
  789 
  790   sym_status_t status;
  791   ast_get(ast, name, &status);
  792 
  793   switch(status)
  794   {
  795     case SYM_UNDEFINED:
  796       if(need_value)
  797       {
  798         ast_error(opt->check.errors, ast,
  799           "the left side is undefined but its value is used");
  800         return false;
  801       }
  802 
  803       ast_setstatus(ast, name, SYM_DEFINED);
  804       return true;
  805 
  806     case SYM_DEFINED:
  807       if(let)
  808       {
  809         ast_error(opt->check.errors, ast,
  810           "can't assign to a let or embed definition more than once");
  811         return false;
  812       }
  813 
  814       return true;
  815 
  816     case SYM_CONSUMED:
  817     case SYM_CONSUMED_SAME_EXPR:
  818     {
  819       bool ok = true;
  820 
  821       if(need_value)
  822       {
  823         ast_error(opt->check.errors, ast,
  824           "the left side is consumed but its value is used");
  825         ok = false;
  826       }
  827 
  828       if(let)
  829       {
  830         ast_error(opt->check.errors, ast,
  831           "can't assign to a let or embed definition more than once");
  832         ok = false;
  833       }
  834 
  835       if(opt->check.frame->try_expr != NULL)
  836       {
  837         if(status == SYM_CONSUMED)
  838         {
  839           ast_error(opt->check.errors, ast,
  840             "can't reassign to a consumed identifier in a try expression unless"
  841             " it is reassigned in the same expression");
  842           ok = false;
  843         }
  844         // SYM_CONSUMED_SAME_EXPR is allowed to pass; verify pass will check if
  845         // there are any partial calls/errors and throw an error if necessary
  846       }
  847 
  848       if(ok)
  849         ast_setstatus(ast, name, SYM_DEFINED);
  850 
  851       return ok;
  852     }
  853 
  854     default: {}
  855   }
  856 
  857   pony_assert(0);
  858   return false;
  859 }
  860 
  861 static bool is_lvalue(pass_opt_t* opt, ast_t* ast, bool need_value)
  862 {
  863   switch(ast_id(ast))
  864   {
  865     case TK_DONTCARE:
  866       return true;
  867 
  868     case TK_DONTCAREREF:
  869       // Can only assign to it if we don't need the value.
  870       return !need_value;
  871 
  872     case TK_VAR:
  873     case TK_LET:
  874       return assign_id(opt, ast_child(ast), ast_id(ast) == TK_LET, need_value);
  875 
  876     case TK_VARREF:
  877     {
  878       ast_t* id = ast_child(ast);
  879       return assign_id(opt, id, false, need_value);
  880     }
  881 
  882     case TK_LETREF:
  883     {
  884       ast_error(opt->check.errors, ast, "can't reassign to a let local");
  885       return false;
  886     }
  887 
  888     case TK_DOT:
  889     {
  890       AST_GET_CHILDREN(ast, left, right);
  891 
  892       switch(ast_id(left))
  893       {
  894         case TK_THIS:
  895         {
  896           ast_t* def = (ast_t*)ast_data(ast);
  897 
  898           if(def == NULL)
  899             return false;
  900 
  901           switch(ast_id(def))
  902           {
  903             case TK_FVAR:  return assign_id(opt, right, false, need_value);
  904             case TK_FLET:
  905             case TK_EMBED: return assign_id(opt, right, true, need_value);
  906             default:       return false;
  907           }
  908         }
  909         case TK_VARREF:
  910         case TK_LETREF:
  911         case TK_DOT:
  912         {
  913           return assign_multi_dot(opt, ast, need_value);
  914         }
  915         default: {}
  916       }
  917 
  918       return true;
  919     }
  920 
  921     case TK_TUPLE:
  922     {
  923       // A tuple is an lvalue if every component expression is an lvalue.
  924       ast_t* child = ast_child(ast);
  925 
  926       while(child != NULL)
  927       {
  928         if(!is_lvalue(opt, child, need_value))
  929           return false;
  930 
  931         child = ast_sibling(child);
  932       }
  933 
  934       return true;
  935     }
  936 
  937     case TK_SEQ:
  938     {
  939       // A sequence is an lvalue if it has a single child that is an lvalue.
  940       // This is used because the components of a tuple are sequences.
  941       ast_t* child = ast_child(ast);
  942 
  943       if(ast_sibling(child) != NULL)
  944         return false;
  945 
  946       return is_lvalue(opt, child, need_value);
  947     }
  948 
  949     default: {}
  950   }
  951 
  952   return false;
  953 }
  954 
  955 static bool refer_pre_call(pass_opt_t* opt, ast_t* ast)
  956 {
  957   pony_assert(ast_id(ast) == TK_CALL);
  958   AST_GET_CHILDREN(ast, lhs, positional, named, question);
  959 
  960   // Run the args before the receiver, so that symbol status tracking
  961   // will see things like consumes in the args first.
  962   if(!ast_passes_subtree(&positional, opt, PASS_REFER) ||
  963     !ast_passes_subtree(&named, opt, PASS_REFER))
  964     return false;
  965 
  966   return true;
  967 }
  968 
  969 static bool refer_pre_assign(pass_opt_t* opt, ast_t* ast)
  970 {
  971   pony_assert(ast_id(ast) == TK_ASSIGN);
  972   AST_GET_CHILDREN(ast, left, right);
  973 
  974   // Run the right side before the left side, so that symbol status tracking
  975   // will see things like consumes in the right side first.
  976   if(!ast_passes_subtree(&right, opt, PASS_REFER))
  977     return false;
  978 
  979   return true;
  980 }
  981 
  982 static bool refer_assign(pass_opt_t* opt, ast_t* ast)
  983 {
  984   pony_assert(ast_id(ast) == TK_ASSIGN);
  985   AST_GET_CHILDREN(ast, left, right);
  986 
  987   if(!is_lvalue(opt, left, is_result_needed(ast)))
  988   {
  989     if(ast_id(left) == TK_DONTCAREREF)
  990     {
  991       ast_error(opt->check.errors, left,
  992         "can't read from '_'");
  993     } else {
  994       ast_error(opt->check.errors, ast,
  995         "left side must be something that can be assigned to");
  996     }
  997     return false;
  998   }
  999 
 1000   return true;
 1001 }
 1002 
 1003 static bool ast_get_child(ast_t* ast, const char* name)
 1004 {
 1005   const char* assign_name = NULL;
 1006 
 1007   switch(ast_id(ast))
 1008   {
 1009     case TK_ID:
 1010     {
 1011       assign_name = ast_name(ast);
 1012       break;
 1013     }
 1014 
 1015     case TK_DOT:
 1016     {
 1017       // get fully qualified string identifier without `this`
 1018       assign_name = generate_multi_dot_name(ast, NULL);
 1019       break;
 1020     }
 1021 
 1022     default: {}
 1023 
 1024   }
 1025 
 1026   if(assign_name == name)
 1027     return true;
 1028 
 1029   ast_t* child = ast_child(ast);
 1030 
 1031   while(child != NULL)
 1032   {
 1033     if(ast_get_child(child, name))
 1034       return true;
 1035 
 1036     child = ast_sibling(child);
 1037   }
 1038 
 1039   return false;
 1040 }
 1041 
 1042 static bool check_assigned_same_expression(ast_t* ast, const char* name,
 1043   ast_t** ret_assign_ast)
 1044 {
 1045   ast_t* assign_ast = ast;
 1046   while((assign_ast != NULL) && (ast_id(assign_ast) != TK_ASSIGN))
 1047     assign_ast = ast_parent(assign_ast);
 1048 
 1049   *ret_assign_ast = assign_ast;
 1050 
 1051   if(assign_ast == NULL)
 1052     return false;
 1053 
 1054   ast_t* assign_left = ast_child(assign_ast);
 1055   return ast_get_child(assign_left, name);
 1056 }
 1057 
 1058 static void set_flag_recursive(ast_t* outer, ast_t* inner, uint32_t flag)
 1059 {
 1060   pony_assert(outer != NULL);
 1061   pony_assert(inner != NULL);
 1062 
 1063   do
 1064   {
 1065     ast_setflag(inner, flag);
 1066 
 1067     if(inner == outer)
 1068       break;
 1069 
 1070     inner = ast_parent(inner);
 1071   } while(inner != NULL);
 1072 }
 1073 
 1074 static bool refer_consume(pass_opt_t* opt, ast_t* ast)
 1075 {
 1076   pony_assert(ast_id(ast) == TK_CONSUME);
 1077   AST_GET_CHILDREN(ast, cap, term);
 1078 
 1079   const char* name = NULL;
 1080   bool consumed_same_expr = false;
 1081 
 1082   switch(ast_id(term))
 1083   {
 1084     case TK_VARREF:
 1085     case TK_LETREF:
 1086     case TK_PARAMREF:
 1087     {
 1088       ast_t* id = ast_child(term);
 1089       name = ast_name(id);
 1090       ast_t* assign_ast = NULL;
 1091       if(check_assigned_same_expression(id, name, &assign_ast))
 1092       {
 1093         consumed_same_expr = true;
 1094         ast_setflag(assign_ast, AST_FLAG_CNSM_REASGN);
 1095       }
 1096 
 1097       break;
 1098     }
 1099 
 1100     case TK_THIS:
 1101     {
 1102       name = stringtab("this");
 1103       break;
 1104     }
 1105 
 1106     case TK_DOT:
 1107     {
 1108       AST_GET_CHILDREN(term, left, right);
 1109 
 1110       ast_t* def = NULL;
 1111 
 1112       if(ast_id(left) == TK_THIS)
 1113       {
 1114         def = (ast_t*)ast_data(term);
 1115         name = ast_name(right);
 1116 
 1117         // check it's not a let or embed if it's a this variable
 1118         if((ast_id(def) == TK_FLET) || (ast_id(def) == TK_EMBED))
 1119         {
 1120           ast_error(opt->check.errors, ast,
 1121             "can't consume a let or embed field");
 1122           return false;
 1123         }
 1124       }
 1125       else
 1126       {
 1127         // get fully qualified string identifier without `this`
 1128         // and def of the root object
 1129         name = generate_multi_dot_name(term, &def);
 1130 
 1131         // defer checking it's not a let or embed if it's not a `this` variable
 1132         // because we don't have the type info available. The expr pass will
 1133         // catch it in the `expr_consume` function.
 1134       }
 1135 
 1136       if(def == NULL)
 1137       {
 1138         ast_error(opt->check.errors, ast,
 1139           "cannot consume an unknown field type");
 1140         return false;
 1141       }
 1142 
 1143       ast_t* assign_ast = NULL;
 1144 
 1145       if(!check_assigned_same_expression(ast, name, &assign_ast))
 1146       {
 1147         ast_error(opt->check.errors, ast,
 1148           "consuming a field is only allowed if it is reassigned in the same"
 1149           " expression");
 1150         return false;
 1151       }
 1152 
 1153       consumed_same_expr = true;
 1154 
 1155       // assign flag to full tree from ast to assign_ast
 1156       set_flag_recursive(assign_ast, ast, AST_FLAG_FCNSM_REASGN);
 1157 
 1158       break;
 1159     }
 1160 
 1161     default:
 1162       ast_error(opt->check.errors, ast,
 1163         "consume must take 'this', a local, or a parameter");
 1164       return false;
 1165   }
 1166 
 1167   // Can't consume from an outer scope while in a loop condition.
 1168   if((opt->check.frame->loop_cond != NULL) &&
 1169     !ast_within_scope(opt->check.frame->loop_cond, ast, name))
 1170   {
 1171     ast_error(opt->check.errors, ast,
 1172       "can't consume from an outer scope in a loop condition");
 1173     return false;
 1174   }
 1175 
 1176   if(consumed_same_expr)
 1177     ast_setstatus(ast, name, SYM_CONSUMED_SAME_EXPR);
 1178   else
 1179     ast_setstatus(ast, name, SYM_CONSUMED);
 1180 
 1181   return true;
 1182 }
 1183 
 1184 static bool refer_pre_new(pass_opt_t* opt, ast_t* ast)
 1185 {
 1186   (void)opt;
 1187   pony_assert(ast_id(ast) == TK_NEW);
 1188 
 1189   // Set all fields to undefined at the start of this scope.
 1190   ast_t* members = ast_parent(ast);
 1191   ast_t* member = ast_child(members);
 1192   while(member != NULL)
 1193   {
 1194     switch(ast_id(member))
 1195     {
 1196       case TK_FVAR:
 1197       case TK_FLET:
 1198       case TK_EMBED:
 1199       {
 1200         // Mark this field as SYM_UNDEFINED.
 1201         AST_GET_CHILDREN(member, id, type, expr);
 1202         ast_setstatus(ast, ast_name(id), SYM_UNDEFINED);
 1203         break;
 1204       }
 1205 
 1206       default: {}
 1207     }
 1208 
 1209     member = ast_sibling(member);
 1210   }
 1211 
 1212   return true;
 1213 }
 1214 
 1215 static bool refer_new(pass_opt_t* opt, ast_t* ast)
 1216 {
 1217   pony_assert(ast_id(ast) == TK_NEW);
 1218 
 1219   ast_t* members = ast_parent(ast);
 1220   ast_t* member = ast_child(members);
 1221   bool result = true;
 1222 
 1223   while(member != NULL)
 1224   {
 1225     switch(ast_id(member))
 1226     {
 1227       case TK_FVAR:
 1228       case TK_FLET:
 1229       case TK_EMBED:
 1230       {
 1231         sym_status_t status;
 1232         ast_t* id = ast_child(member);
 1233         ast_t* def = ast_get(ast, ast_name(id), &status);
 1234 
 1235         if((def != member) || (status != SYM_DEFINED))
 1236         {
 1237           ast_error(opt->check.errors, def,
 1238             "field left undefined in constructor");
 1239           result = false;
 1240         }
 1241 
 1242         break;
 1243       }
 1244 
 1245       default: {}
 1246     }
 1247 
 1248     member = ast_sibling(member);
 1249   }
 1250 
 1251   if(!result)
 1252     ast_error(opt->check.errors, ast,
 1253       "constructor with undefined fields is here");
 1254 
 1255   return result;
 1256 }
 1257 
 1258 static bool refer_local(pass_opt_t* opt, ast_t* ast)
 1259 {
 1260   pony_assert(ast != NULL);
 1261   pony_assert(ast_type(ast) != NULL);
 1262 
 1263   AST_GET_CHILDREN(ast, id, type);
 1264   pony_assert(type != NULL);
 1265 
 1266   bool is_dontcare = is_name_dontcare(ast_name(id));
 1267 
 1268   if(ast_id(type) == TK_NONE)
 1269   {
 1270     // No type specified, infer it later
 1271     if(!is_dontcare && !is_assigned_to(ast, false))
 1272     {
 1273       ast_error(opt->check.errors, ast,
 1274         "locals must specify a type or be assigned a value");
 1275       return false;
 1276     }
 1277   }
 1278   else if(ast_id(ast) == TK_LET)
 1279   {
 1280     // Let, check we have a value assigned
 1281     if(!is_assigned_to(ast, false))
 1282     {
 1283       ast_error(opt->check.errors, ast,
 1284         "can't declare a let local without assigning to it");
 1285       return false;
 1286     }
 1287   }
 1288 
 1289   if(is_dontcare)
 1290     ast_setid(ast, TK_DONTCARE);
 1291 
 1292   return true;
 1293 }
 1294 
 1295 static bool refer_seq(pass_opt_t* opt, ast_t* ast)
 1296 {
 1297   (void)opt;
 1298   pony_assert(ast_id(ast) == TK_SEQ);
 1299 
 1300   // If the last expression jumps away with no value, then we do too.
 1301   if(ast_checkflag(ast_childlast(ast), AST_FLAG_JUMPS_AWAY))
 1302     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1303 
 1304   // Propagate symbol status forward in some cases where control flow branches
 1305   // always precede other branches of the same control flow structure.
 1306   if(ast_has_scope(ast))
 1307   {
 1308     ast_t* parent = ast_parent(ast);
 1309 
 1310     switch(ast_id(parent))
 1311     {
 1312       case TK_TRY:
 1313       case TK_TRY_NO_CHECK:
 1314       {
 1315         AST_GET_CHILDREN(parent, body, else_clause, then_clause);
 1316 
 1317         if(body == ast)
 1318         {
 1319           // Push our consumes, but not defines, to the else clause.
 1320           ast_inheritbranch(else_clause, body);
 1321           ast_consolidate_branches(else_clause, 2);
 1322         } else if(else_clause == ast) {
 1323           // Push our consumes, but not defines, to the then clause. This
 1324           // includes the consumes from the body.
 1325           ast_inheritbranch(then_clause, else_clause);
 1326           ast_consolidate_branches(then_clause, 2);
 1327         }
 1328       }
 1329       break;
 1330 
 1331       case TK_REPEAT:
 1332       {
 1333         AST_GET_CHILDREN(parent, body, cond, else_clause);
 1334 
 1335         if(body == ast)
 1336         {
 1337           // Push our consumes and our defines to the cond clause.
 1338           ast_inheritstatus(cond, body);
 1339         } else if(cond == ast) {
 1340           // Push our consumes, but not defines, to the else clause. This
 1341           // includes the consumes from the body.
 1342           ast_inheritbranch(else_clause, cond);
 1343           ast_consolidate_branches(else_clause, 2);
 1344         }
 1345       }
 1346       break;
 1347 
 1348       default: {}
 1349     }
 1350   }
 1351 
 1352   return true;
 1353 }
 1354 
 1355 static bool valid_is_comparand(pass_opt_t* opt, ast_t* ast)
 1356 {
 1357   ast_t* type;
 1358   switch(ast_id(ast))
 1359   {
 1360     case TK_TYPEREF:
 1361       type = (ast_t*) ast_data(ast);
 1362       if(ast_id(type) != TK_PRIMITIVE)
 1363       {
 1364         ast_error(opt->check.errors, ast, "identity comparison with a new object"
 1365         " will always be false");
 1366         return false;
 1367       }
 1368       return true;
 1369     case TK_SEQ:
 1370       type = ast_child(ast);
 1371       while(type != NULL)
 1372       {
 1373         if(ast_sibling(type) == NULL)
 1374           return valid_is_comparand(opt, type);
 1375         type = ast_sibling(type);
 1376       }
 1377       return true;
 1378     case TK_TUPLE:
 1379       type = ast_child(ast);
 1380       while(type != NULL)
 1381       {
 1382         if (!valid_is_comparand(opt, type))
 1383           return false;
 1384         type = ast_sibling(type);
 1385       }
 1386       return true;
 1387     default:
 1388       return true;
 1389   }
 1390 }
 1391 
 1392 static bool refer_is(pass_opt_t* opt, ast_t* ast)
 1393 {
 1394   (void)opt;
 1395   pony_assert((ast_id(ast) == TK_IS) || (ast_id(ast) == TK_ISNT));
 1396   AST_GET_CHILDREN(ast, left, right);
 1397   return valid_is_comparand(opt, right) && valid_is_comparand(opt, left);
 1398 }
 1399 
 1400 static bool refer_if(pass_opt_t* opt, ast_t* ast)
 1401 {
 1402   (void)opt;
 1403   pony_assert((ast_id(ast) == TK_IF) || (ast_id(ast) == TK_IFDEF));
 1404   AST_GET_CHILDREN(ast, cond, left, right);
 1405 
 1406   size_t branch_count = 0;
 1407 
 1408   if(!ast_checkflag(left, AST_FLAG_JUMPS_AWAY))
 1409   {
 1410     branch_count++;
 1411     ast_inheritbranch(ast, left);
 1412   }
 1413 
 1414   if(!ast_checkflag(right, AST_FLAG_JUMPS_AWAY))
 1415   {
 1416     branch_count++;
 1417     ast_inheritbranch(ast, right);
 1418   }
 1419 
 1420   ast_consolidate_branches(ast, branch_count);
 1421 
 1422   // If all branches jump away with no value, then we do too.
 1423   if(branch_count == 0)
 1424     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1425 
 1426   // Push our symbol status to our parent scope.
 1427   ast_inheritstatus(ast_parent(ast), ast);
 1428 
 1429   return true;
 1430 }
 1431 
 1432 static bool refer_iftype(pass_opt_t* opt, ast_t* ast)
 1433 {
 1434   (void)opt;
 1435   pony_assert(ast_id(ast) == TK_IFTYPE_SET);
 1436 
 1437   AST_GET_CHILDREN(ast, left_clause, right);
 1438   AST_GET_CHILDREN(left_clause, sub, super, left);
 1439 
 1440   size_t branch_count = 0;
 1441 
 1442   if(!ast_checkflag(left, AST_FLAG_JUMPS_AWAY))
 1443   {
 1444     branch_count++;
 1445     ast_inheritbranch(ast, left);
 1446   }
 1447 
 1448   if(!ast_checkflag(right, AST_FLAG_JUMPS_AWAY))
 1449   {
 1450     branch_count++;
 1451     ast_inheritbranch(ast, right);
 1452   }
 1453 
 1454   ast_consolidate_branches(ast, branch_count);
 1455 
 1456   // If all branches jump away with no value, then we do too.
 1457   if(branch_count == 0)
 1458     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1459 
 1460   // Push our symbol status to our parent scope.
 1461   ast_inheritstatus(ast_parent(ast), ast);
 1462 
 1463   return true;
 1464 }
 1465 
 1466 static bool refer_while(pass_opt_t* opt, ast_t* ast)
 1467 {
 1468   pony_assert(ast_id(ast) == TK_WHILE);
 1469   AST_GET_CHILDREN(ast, cond, body, else_clause);
 1470 
 1471   // All consumes have to be in scope when the loop body finishes.
 1472   errorframe_t errorf = NULL;
 1473   if(!ast_all_consumes_in_scope(body, body, &errorf))
 1474   {
 1475     errorframe_report(&errorf, opt->check.errors);
 1476     return false;
 1477   }
 1478 
 1479   size_t branch_count = 0;
 1480 
 1481   // No symbol status is inherited from the loop body. Nothing from outside the
 1482   // loop body can be consumed, and definitions in the body may not occur.
 1483   if(!ast_checkflag(body, AST_FLAG_JUMPS_AWAY))
 1484     branch_count++;
 1485 
 1486   if(!ast_checkflag(else_clause, AST_FLAG_JUMPS_AWAY))
 1487   {
 1488     branch_count++;
 1489     ast_inheritbranch(ast, body);
 1490 
 1491     // Use a branch count of two instead of one. This means we will pick up any
 1492     // consumes, but not any definitions, since definitions may not occur.
 1493     ast_consolidate_branches(ast, 2);
 1494   }
 1495 
 1496   // If all branches jump away with no value, then we do too.
 1497   if(branch_count == 0)
 1498     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1499 
 1500   // Push our symbol status to our parent scope.
 1501   ast_inheritstatus(ast_parent(ast), ast);
 1502 
 1503   return true;
 1504 }
 1505 
 1506 static bool refer_repeat(pass_opt_t* opt, ast_t* ast)
 1507 {
 1508   pony_assert(ast_id(ast) == TK_REPEAT);
 1509   AST_GET_CHILDREN(ast, body, cond, else_clause);
 1510 
 1511   // All consumes have to be in scope when the loop body finishes.
 1512   errorframe_t errorf = NULL;
 1513   if(!ast_all_consumes_in_scope(body, body, &errorf))
 1514   {
 1515     errorframe_report(&errorf, opt->check.errors);
 1516     return false;
 1517   }
 1518 
 1519   size_t branch_count = 0;
 1520 
 1521   // No symbol status is inherited from the loop body. Nothing from outside the
 1522   // loop body can be consumed, and definitions in the body may not occur.
 1523   if(!ast_checkflag(body, AST_FLAG_JUMPS_AWAY))
 1524   {
 1525     branch_count++;
 1526     ast_inheritbranch(ast, body);
 1527   }
 1528 
 1529   if(!ast_checkflag(else_clause, AST_FLAG_JUMPS_AWAY))
 1530   {
 1531     // Only include the else clause in the branch analysis
 1532     // if the loop has a break statement somewhere in it.
 1533     // This allows us to treat the entire loop body as being
 1534     // sure to execute in every case, at least for the purposes
 1535     // of analyzing variables being defined in its scope.
 1536     // For the case of errors and return statements that may
 1537     // exit the loop, they do not affect our analysis here
 1538     // because they will skip past more than just the loop itself.
 1539     if(ast_checkflag(body, AST_FLAG_MAY_BREAK))
 1540     {
 1541       branch_count++;
 1542       ast_inheritbranch(ast, else_clause);
 1543     }
 1544   }
 1545 
 1546   ast_consolidate_branches(ast, branch_count);
 1547 
 1548   // If all branches jump away with no value, then we do too.
 1549   if(branch_count == 0)
 1550     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1551 
 1552   // Push our symbol status to our parent scope.
 1553   ast_inheritstatus(ast_parent(ast), ast);
 1554 
 1555   return true;
 1556 }
 1557 
 1558 static bool refer_match(pass_opt_t* opt, ast_t* ast)
 1559 {
 1560   (void)opt;
 1561   pony_assert(ast_id(ast) == TK_MATCH);
 1562   AST_GET_CHILDREN(ast, expr, cases, else_clause);
 1563 
 1564   size_t branch_count = 0;
 1565 
 1566   if(!ast_checkflag(cases, AST_FLAG_JUMPS_AWAY))
 1567   {
 1568     branch_count++;
 1569     ast_inheritbranch(ast, cases);
 1570   }
 1571 
 1572   if(ast_id(else_clause) == TK_NONE)
 1573   {
 1574     branch_count++;
 1575   }
 1576   else if(!ast_checkflag(else_clause, AST_FLAG_JUMPS_AWAY))
 1577   {
 1578     branch_count++;
 1579     ast_inheritbranch(ast, else_clause);
 1580   }
 1581 
 1582   // If all branches jump away with no value, then we do too.
 1583   if(branch_count == 0)
 1584     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1585 
 1586   ast_consolidate_branches(ast, branch_count);
 1587 
 1588   // Push our symbol status to our parent scope.
 1589   ast_inheritstatus(ast_parent(ast), ast);
 1590 
 1591   return true;
 1592 }
 1593 
 1594 static bool refer_cases(pass_opt_t* opt, ast_t* ast)
 1595 {
 1596   pony_assert(ast_id(ast) == TK_CASES);
 1597   ast_t* the_case = ast_child(ast);
 1598 
 1599   if(the_case == NULL)
 1600   {
 1601     ast_error(opt->check.errors, ast, "match must have at least one case");
 1602     return false;
 1603   }
 1604 
 1605   size_t branch_count = 0;
 1606 
 1607   while(the_case != NULL)
 1608   {
 1609     AST_GET_CHILDREN(the_case, pattern, guard, body);
 1610 
 1611     if(!ast_checkflag(body, AST_FLAG_JUMPS_AWAY))
 1612     {
 1613       branch_count++;
 1614       ast_inheritbranch(ast, the_case);
 1615     }
 1616 
 1617     the_case = ast_sibling(the_case);
 1618   }
 1619 
 1620   if(branch_count == 0)
 1621     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1622 
 1623   ast_consolidate_branches(ast, branch_count);
 1624 
 1625   return true;
 1626 }
 1627 
 1628 static bool refer_try(pass_opt_t* opt, ast_t* ast)
 1629 {
 1630   pony_assert((ast_id(ast) == TK_TRY) || (ast_id(ast) == TK_TRY_NO_CHECK));
 1631   AST_GET_CHILDREN(ast, body, else_clause, then_clause);
 1632 
 1633   size_t branch_count = 0;
 1634 
 1635   if(!ast_checkflag(body, AST_FLAG_JUMPS_AWAY))
 1636     branch_count++;
 1637 
 1638   if(!ast_checkflag(else_clause, AST_FLAG_JUMPS_AWAY))
 1639     branch_count++;
 1640 
 1641   if(ast_checkflag(then_clause, AST_FLAG_JUMPS_AWAY))
 1642   {
 1643     ast_error(opt->check.errors, then_clause,
 1644       "then clause always terminates the function");
 1645     return false;
 1646   }
 1647 
 1648   // If all branches jump away with no value, then we do too.
 1649   if(branch_count == 0)
 1650     ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1651 
 1652   // Push the symbol status from the then clause to our parent scope.
 1653   ast_inheritstatus(ast_parent(ast), then_clause);
 1654 
 1655   return true;
 1656 }
 1657 
 1658 static bool refer_recover(pass_opt_t* opt, ast_t* ast)
 1659 {
 1660   (void)opt;
 1661   pony_assert(ast_id(ast) == TK_RECOVER);
 1662   AST_GET_CHILDREN(ast, cap, expr);
 1663 
 1664   // Push our symbol status to our parent scope.
 1665   ast_inheritstatus(ast_parent(ast), expr);
 1666 
 1667   return true;
 1668 }
 1669 
 1670 static bool refer_break(pass_opt_t* opt, ast_t* ast)
 1671 {
 1672   pony_assert(ast_id(ast) == TK_BREAK);
 1673 
 1674   if(opt->check.frame->loop_body == NULL)
 1675   {
 1676     ast_error(opt->check.errors, ast, "must be in a loop");
 1677     return false;
 1678   }
 1679 
 1680   ast_setflag(opt->check.frame->loop_body, AST_FLAG_MAY_BREAK);
 1681 
 1682   errorframe_t errorf = NULL;
 1683   if(!ast_all_consumes_in_scope(opt->check.frame->loop_body, ast, &errorf))
 1684   {
 1685     errorframe_report(&errorf, opt->check.errors);
 1686     return false;
 1687   }
 1688 
 1689   // break is always the last expression in a sequence
 1690   pony_assert(ast_sibling(ast) == NULL);
 1691 
 1692   ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1693 
 1694   return true;
 1695 }
 1696 
 1697 static bool refer_continue(pass_opt_t* opt, ast_t* ast)
 1698 {
 1699   pony_assert(ast_id(ast) == TK_CONTINUE);
 1700 
 1701   if(opt->check.frame->loop_body == NULL)
 1702   {
 1703     ast_error(opt->check.errors, ast, "must be in a loop");
 1704     return false;
 1705   }
 1706 
 1707   errorframe_t errorf = NULL;
 1708   if(!ast_all_consumes_in_scope(opt->check.frame->loop_body, ast, &errorf))
 1709   {
 1710     errorframe_report(&errorf, opt->check.errors);
 1711     return false;
 1712   }
 1713 
 1714   // continue is always the last expression in a sequence
 1715   pony_assert(ast_sibling(ast) == NULL);
 1716 
 1717   ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1718 
 1719   return true;
 1720 }
 1721 
 1722 static bool refer_return(pass_opt_t* opt, ast_t* ast)
 1723 {
 1724   pony_assert(ast_id(ast) == TK_RETURN);
 1725 
 1726   // return is always the last expression in a sequence
 1727   pony_assert(ast_sibling(ast) == NULL);
 1728 
 1729   ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1730 
 1731   if((ast_id(opt->check.frame->method) == TK_NEW) &&
 1732     is_this_incomplete(opt, ast))
 1733   {
 1734     ast_error(opt->check.errors, ast,
 1735       "all fields must be defined before constructor returns");
 1736     return false;
 1737   }
 1738 
 1739   return true;
 1740 }
 1741 
 1742 static bool refer_error(pass_opt_t* opt, ast_t* ast)
 1743 {
 1744   (void)opt;
 1745   // error is always the last expression in a sequence
 1746   pony_assert(ast_sibling(ast) == NULL);
 1747 
 1748   ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1749   return true;
 1750 }
 1751 
 1752 static bool refer_compile_error(pass_opt_t* opt, ast_t* ast)
 1753 {
 1754   (void)opt;
 1755   // compile_error is always the last expression in a sequence
 1756   pony_assert(ast_sibling(ast) == NULL);
 1757 
 1758   ast_setflag(ast, AST_FLAG_JUMPS_AWAY);
 1759   return true;
 1760 }
 1761 
 1762 ast_result_t pass_pre_refer(ast_t** astp, pass_opt_t* options)
 1763 {
 1764   ast_t* ast = *astp;
 1765   bool r = true;
 1766 
 1767   switch(ast_id(ast))
 1768   {
 1769     case TK_NEW:    r = refer_pre_new(options, ast); break;
 1770     case TK_CALL:   r = refer_pre_call(options, ast); break;
 1771     case TK_ASSIGN: r = refer_pre_assign(options, ast); break;
 1772 
 1773     default: {}
 1774   }
 1775 
 1776   if(!r)
 1777   {
 1778     pony_assert(errors_get_count(options->check.errors) > 0);
 1779     return AST_ERROR;
 1780   }
 1781 
 1782   return AST_OK;
 1783 }
 1784 
 1785 ast_result_t pass_refer(ast_t** astp, pass_opt_t* options)
 1786 {
 1787   ast_t* ast = *astp;
 1788   bool r = true;
 1789 
 1790   switch(ast_id(ast))
 1791   {
 1792     case TK_REFERENCE: r = refer_reference(options, astp); break;
 1793     case TK_DOT:       r = refer_dot(options, ast); break;
 1794     case TK_QUALIFY:   r = refer_qualify(options, ast); break;
 1795 
 1796     case TK_ASSIGN:    r = refer_assign(options, ast); break;
 1797     case TK_CONSUME:   r = refer_consume(options, ast); break;
 1798 
 1799     case TK_THIS:      r = refer_this(options, ast); break;
 1800     case TK_NEW:       r = refer_new(options, ast); break;
 1801     case TK_VAR:
 1802     case TK_LET:       r = refer_local(options, ast); break;
 1803 
 1804     case TK_SEQ:       r = refer_seq(options, ast); break;
 1805     case TK_IFDEF:
 1806     case TK_IF:        r = refer_if(options, ast); break;
 1807     case TK_IFTYPE_SET:
 1808                        r = refer_iftype(options, ast); break;
 1809     case TK_WHILE:     r = refer_while(options, ast); break;
 1810     case TK_REPEAT:    r = refer_repeat(options, ast); break;
 1811     case TK_MATCH:     r = refer_match(options, ast); break;
 1812     case TK_CASES:     r = refer_cases(options, ast); break;
 1813     case TK_TRY_NO_CHECK:
 1814     case TK_TRY:       r = refer_try(options, ast); break;
 1815     case TK_RECOVER:   r = refer_recover(options, ast); break;
 1816     case TK_BREAK:     r = refer_break(options, ast); break;
 1817     case TK_CONTINUE:  r = refer_continue(options, ast); break;
 1818     case TK_RETURN:    r = refer_return(options, ast); break;
 1819     case TK_ERROR:     r = refer_error(options, ast); break;
 1820     case TK_COMPILE_ERROR:
 1821                        r = refer_compile_error(options, ast); break;
 1822     case TK_IS:
 1823     case TK_ISNT:
 1824                        r = refer_is(options, ast); break;
 1825 
 1826     default: {}
 1827   }
 1828 
 1829   if(!r)
 1830   {
 1831     pony_assert(errors_get_count(options->check.errors) > 0);
 1832     return AST_ERROR;
 1833   }
 1834 
 1835   return AST_OK;
 1836 }