Esempio n. 1
0
static bool method_chain(pass_opt_t* opt, ast_t* ast)
{
  if(!method_application(opt, ast, false))
    return false;

  // We check the receiver cap now instead of in method_application because
  // we need to know whether the receiver was recovered.
  ast_t* lhs = ast_childidx(ast, 2);
  ast_t* r_type = method_receiver_type(lhs);
  if(ast_id(lhs) == TK_FUNCHAIN)
  {
    bool recovered;
    if(!check_receiver_cap(opt, ast, &recovered))
      return false;

    if(!check_nonsendable_recover(opt, ast))
      return false;

    ast_t* f_type = ast_type(lhs);
    token_id f_cap = ast_id(ast_child(f_type));

    ast_t* c_type = chain_type(r_type, f_cap, recovered);
    ast_settype(ast, c_type);
  } else {
    ast_settype(ast, r_type);
  }

  return true;
}
Esempio n. 2
0
static bool method_application(pass_opt_t* opt, ast_t* ast, bool partial)
{
  AST_GET_CHILDREN(ast, positional, namedargs, question, lhs);

  if(!method_check_type_params(opt, &lhs))
    return false;

  ast_t* type = ast_type(lhs);

  if(is_typecheck_error(type))
    return false;

  AST_GET_CHILDREN(type, cap, typeparams, params, result);

  if(!extend_positional_args(opt, params, positional))
    return false;

  if(!apply_named_args(opt, params, positional, namedargs))
    return false;

  if(!check_arg_types(opt, params, positional, partial))
    return false;

  switch(ast_id(lhs))
  {
    case TK_FUNREF:
    case TK_FUNAPP:
      if(ast_id(ast_child(type)) != TK_AT)
      {
        if(!check_receiver_cap(opt, ast, NULL))
          return false;

        if(!check_nonsendable_recover(opt, ast))
          return false;
      } else {
        ast_t* receiver = ast_child(lhs);

        // Dig through function qualification.
        if((ast_id(receiver) == TK_FUNREF) || (ast_id(receiver) == TK_FUNAPP) ||
           (ast_id(receiver) == TK_FUNCHAIN))
          receiver = ast_child(receiver);

        ast_t* recv_type = ast_type(receiver);
        if(!is_known(recv_type) && (ast_id(receiver) == TK_TYPEREF))
        {
          ast_error(opt->check.errors, lhs, "a bare method cannot be called on "
            "an abstract type reference");
          return false;
        }
      }

      break;

    default: {}
  }

  return true;
}
Esempio n. 3
0
static bool method_application(pass_opt_t* opt, ast_t* ast, bool partial)
{
  AST_GET_CHILDREN(ast, positional, namedargs, lhs);

  if(!check_type_params(opt, &lhs))
    return false;

  ast_t* type = ast_type(lhs);

  if(is_typecheck_error(type))
    return false;

  AST_GET_CHILDREN(type, cap, typeparams, params, result);

  if(!extend_positional_args(opt, params, positional))
    return false;

  if(!apply_named_args(opt, params, positional, namedargs))
    return false;

  if(!check_arg_types(opt, params, positional, partial))
    return false;

  switch(ast_id(lhs))
  {
    case TK_FUNREF:
    case TK_FUNAPP:
      if(!check_receiver_cap(opt, ast, NULL))
        return false;

      if(!check_nonsendable_recover(opt, ast))
        return false;
      break;

    default: {}
  }

  return true;
}
Esempio n. 4
0
static bool method_application(pass_opt_t* opt, ast_t* ast, bool partial)
{
  // TODO: use args to decide unbound type parameters
  AST_GET_CHILDREN(ast, positional, namedargs, lhs);

  if(!check_type_params(&lhs))
    return false;

  ast_t* type = ast_type(lhs);

  if(is_typecheck_error(type))
    return false;

  AST_GET_CHILDREN(type, cap, typeparams, params, result);

  if(!extend_positional_args(params, positional))
    return false;

  if(!apply_named_args(params, positional, namedargs))
    return false;

  bool incomplete = is_this_incomplete(&opt->check, ast);

  if(!check_arg_types(opt, params, positional, incomplete, partial))
    return false;

  switch(ast_id(lhs))
  {
    case TK_FUNREF:
    case TK_FUNAPP:
      if(!check_receiver_cap(ast, incomplete))
        return false;
      break;

    default: {}
  }

  return true;
}
Esempio n. 5
0
static bool method_chain(pass_opt_t* opt, ast_t* ast)
{
  if(!method_application(opt, ast, false))
    return false;

  AST_GET_CHILDREN(ast, positional, namedargs, question, lhs);

  ast_t* type = ast_type(lhs);
  if(ast_id(ast_child(type)) == TK_AT)
  {
    ast_error(opt->check.errors, ast, "a bare method cannot be chained");
    return false;
  }

  // We check the receiver cap now instead of in method_application because
  // we need to know whether the receiver was recovered.
  ast_t* r_type = method_receiver_type(lhs);
  if(ast_id(lhs) == TK_FUNCHAIN)
  {
    bool recovered;
    if(!check_receiver_cap(opt, ast, &recovered))
      return false;

    if(!check_nonsendable_recover(opt, ast))
      return false;

    ast_t* f_type = ast_type(lhs);
    token_id f_cap = ast_id(ast_child(f_type));

    ast_t* c_type = chain_type(r_type, f_cap, recovered);
    ast_settype(ast, c_type);
  } else {
    ast_settype(ast, r_type);
  }

  return true;
}