Пример #1
0
bool expr_if(pass_opt_t* opt, ast_t* ast)
{
    ast_t* cond = ast_child(ast);
    ast_t* left = ast_sibling(cond);
    ast_t* right = ast_sibling(left);
    ast_t* cond_type = ast_type(cond);

    if(is_typecheck_error(cond_type))
        return false;

    if(!is_bool(cond_type))
    {
        ast_error(cond, "condition must be a Bool");
        return false;
    }

    ast_t* l_type = ast_type(left);
    ast_t* r_type = ast_type(right);

    ast_t* type = NULL;
    size_t branch_count = 0;

    if(!is_control_type(l_type))
    {
        type = control_type_add_branch(type, left);
        ast_inheritbranch(ast, left);
        branch_count++;
    }

    if(!is_control_type(r_type))
    {
        type = control_type_add_branch(type, right);
        ast_inheritbranch(ast, right);
        branch_count++;
    }

    if(type == NULL)
    {
        if(ast_sibling(ast) != NULL)
        {
            ast_error(ast_sibling(ast), "unreachable code");
            return false;
        }

        type = ast_from(ast, TK_IF);
    }

    ast_settype(ast, type);
    ast_inheritflags(ast);
    ast_consolidate_branches(ast, branch_count);
    literal_unify_control(ast, opt);

    // Push our symbol status to our parent scope.
    ast_inheritstatus(ast_parent(ast), ast);
    return true;
}
Пример #2
0
bool expr_repeat(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, body, cond, else_clause);

  ast_t* body_type = ast_type(body);
  ast_t* cond_type = ast_type(cond);
  ast_t* else_type = ast_type(else_clause);

  if(is_typecheck_error(cond_type))
    return false;

  if(!is_bool(cond_type))
  {
    ast_error(opt->check.errors, cond, "condition must be a Bool");
    return false;
  }

  if(is_typecheck_error(body_type) || is_typecheck_error(else_type))
    return false;

  // All consumes have to be in scope when the loop body finishes.
  errorframe_t errorf = NULL;
  if(!ast_all_consumes_in_scope(body, body, &errorf))
  {
    errorframe_report(&errorf, opt->check.errors);
    return false;
  }

  // Union with any existing type due to a break expression.
  ast_t* type = ast_type(ast);

  // No symbol status is inherited from the loop body or condition. Nothing
  // from outside can be consumed, and definitions inside may not occur.
  if(!is_control_type(body_type))
    type = control_type_add_branch(opt, type, body);

  if(!is_control_type(else_type))
  {
    type = control_type_add_branch(opt, type, else_clause);
    ast_inheritbranch(ast, else_clause);

    // Use a branch count of two instead of one. This means we will pick up any
    // consumes, but not any definitions, since definitions may not occur.
    ast_consolidate_branches(ast, 2);
  }

  if(type == NULL)
    type = ast_from(ast, TK_REPEAT);

  ast_settype(ast, type);
  literal_unify_control(ast, opt);

  // Push our symbol status to our parent scope.
  ast_inheritstatus(ast_parent(ast), ast);
  return true;
}
Пример #3
0
bool expr_cases(ast_t* ast)
{
  assert(ast_id(ast) == TK_CASES);
  ast_t* the_case = ast_child(ast);

  if(the_case == NULL)
  {
    ast_error(ast, "match must have at least one case");
    return false;
  }

  ast_t* type = NULL;
  size_t branch_count = 0;

  while(the_case != NULL)
  {
    AST_GET_CHILDREN(the_case, pattern, guard, body);
    ast_t* body_type = ast_type(body);

    if(!is_typecheck_error(body_type) && !is_control_type(body_type))
    {
      type = control_type_add_branch(type, body);
      ast_inheritbranch(ast, the_case);
      branch_count++;
    }

    the_case = ast_sibling(the_case);
  }

  if(type == NULL)
    type = ast_from(ast, TK_CASES);

  ast_settype(ast, type);
  ast_inheritflags(ast);
  ast_consolidate_branches(ast, branch_count);
  return true;
}
Пример #4
0
bool expr_seq(pass_opt_t* opt, ast_t* ast)
{
    bool ok = true;

    // Any expression other than the last that is still literal is an error
    for(ast_t* p = ast_child(ast); ast_sibling(p) != NULL; p = ast_sibling(p))
    {
        ast_t* p_type = ast_type(p);

        if(is_typecheck_error(p_type))
        {
            ok = false;
        } else if(is_type_literal(p_type)) {
            ast_error(p, "Cannot infer type of unused literal");
            ok = false;
        }
    }

    // We might already have a type due to a return expression.
    ast_t* type = ast_type(ast);
    ast_t* last = ast_childlast(ast);

    if((type != NULL) && !coerce_literals(&last, type, opt))
        return false;

    // Type is unioned with the type of the last child.
    type = control_type_add_branch(type, last);
    ast_settype(ast, type);
    ast_inheritflags(ast);

    if(!ast_has_scope(ast))
        return ok;

    ast_t* parent = ast_parent(ast);

    switch(ast_id(parent))
    {
    case TK_TRY:
    case TK_TRY_NO_CHECK:
    {
        // Propagate consumes forward in a try expression.
        AST_GET_CHILDREN(parent, body, else_clause, then_clause);

        if(body == ast)
        {
            // Push our consumes, but not defines, to the else clause.
            ast_inheritbranch(else_clause, body);
            ast_consolidate_branches(else_clause, 2);
        } else if(else_clause == ast) {
            // Push our consumes, but not defines, to the then clause. This
            // includes the consumes from the body.
            ast_inheritbranch(then_clause, else_clause);
            ast_consolidate_branches(then_clause, 2);
        }
    }

    default:
    {}
    }

    return ok;
}
Пример #5
0
bool expr_match(pass_opt_t* opt, ast_t* ast)
{
  assert(ast_id(ast) == TK_MATCH);
  AST_GET_CHILDREN(ast, expr, cases, else_clause);

  // A literal match expression should have been caught by the cases, but check
  // again to avoid an assert if we've missed a case
  ast_t* expr_type = ast_type(expr);

  if(is_typecheck_error(expr_type))
    return false;

  if(is_type_literal(expr_type))
  {
    ast_error(expr, "cannot infer type for literal match expression");
    return false;
  }

  ast_t* cases_type = ast_type(cases);
  ast_t* else_type = ast_type(else_clause);

  if(is_typecheck_error(cases_type) || is_typecheck_error(else_type))
    return false;

  ast_t* type = NULL;
  size_t branch_count = 0;

  if(!is_control_type(cases_type))
  {
    type = control_type_add_branch(type, cases);
    ast_inheritbranch(ast, cases);
    branch_count++;
  }

  if(!is_control_type(else_type))
  {
    type = control_type_add_branch(type, else_clause);
    ast_inheritbranch(ast, else_clause);
    branch_count++;
  }

  if(type == NULL)
  {
    if(ast_sibling(ast) != NULL)
    {
      ast_error(ast_sibling(ast), "unreachable code");
      return false;
    }

    type = ast_from(ast, TK_MATCH);
  }

  ast_settype(ast, type);
  ast_inheritflags(ast);
  ast_consolidate_branches(ast, branch_count);
  literal_unify_control(ast, opt);

  // Push our symbol status to our parent scope.
  ast_inheritstatus(ast_parent(ast), ast);
  return true;
}