Ejemplo n.º 1
0
bool expr_fun(pass_opt_t* opt, ast_t* ast)
{
    typecheck_t* t = &opt->check;

    AST_GET_CHILDREN(ast,
                     cap, id, typeparams, params, type, can_error, body);

    if(ast_id(body) == TK_NONE)
        return true;

    if(!coerce_literals(&body, type, opt))
        return false;

    bool is_trait =
        (ast_id(t->frame->type) == TK_TRAIT) ||
        (ast_id(t->frame->type) == TK_INTERFACE) ||
        (ast_id((ast_t*)ast_data(ast)) == TK_TRAIT) ||
        (ast_id((ast_t*)ast_data(ast)) == TK_INTERFACE);

    // Check partial functions.
    if(ast_id(can_error) == TK_QUESTION)
    {
        // If a partial function, check that we might actually error.
        if(!is_trait && !ast_canerror(body))
        {
            ast_error(can_error, "function body is not partial but the function is");
            return false;
        }
    } else {
        // If not a partial function, check that we can't error.
        if(ast_canerror(body))
        {
            ast_error(can_error, "function body is partial but the function is not");
            show_partiality(body);
            return false;
        }
    }

    if(!check_primitive_init(t, ast) || !check_finaliser(ast))
        return false;

    switch(ast_id(ast))
    {
    case TK_NEW:
        return check_fields_defined(ast) && check_main_create(t, ast);

    case TK_FUN:
        return check_return_type(ast);

    default:
    {}
    }

    return true;
}
Ejemplo n.º 2
0
bool expr_fun(pass_opt_t* opt, ast_t* ast)
{
  typecheck_t* t = &opt->check;

  AST_GET_CHILDREN(ast,
    cap, id, typeparams, params, type, can_error, body);

  if(ast_id(body) == TK_NONE)
    return true;

  if(!coerce_literals(&body, type, opt))
    return false;

  bool is_trait =
    (ast_id(t->frame->type) == TK_TRAIT) ||
    (ast_id(t->frame->type) == TK_INTERFACE) ||
    (ast_id((ast_t*)ast_data(ast)) == TK_TRAIT) ||
    (ast_id((ast_t*)ast_data(ast)) == TK_INTERFACE);

  // Check partial functions.
  if(ast_id(can_error) == TK_QUESTION)
  {
    // If a partial function, check that we might actually error.
    ast_t* body_type = ast_type(body);

    if(body_type == NULL)
    {
      // An error has already occurred.
      assert(get_error_count() > 0);
      return false;
    }

    if(!is_trait &&
      !ast_canerror(body) &&
      (ast_id(body_type) != TK_COMPILE_INTRINSIC))
    {
      ast_error(can_error, "function body is not partial but the function is");
      return false;
    }
  } else {
    // If not a partial function, check that we can't error.
    if(ast_canerror(body))
    {
      ast_error(can_error, "function body is partial but the function is not");
      show_partiality(body);
      return false;
    }
  }

  if(!check_primitive_init(t, ast) || !check_finaliser(t, ast))
    return false;

  switch(ast_id(ast))
  {
    case TK_NEW:
    {
      bool ok = true;

      if(is_machine_word(type))
      {
        if(!check_return_type(ast))
         ok = false;
      }

      if(!check_fields_defined(ast))
        ok = false;

      if(!check_main_create(t, ast))
        ok = false;

      return ok;
    }

    case TK_FUN:
      return check_return_type(ast);

    default: {}
  }

  return true;
}