Exemple #1
0
// Determine the UIF types that the given type may be
static int uifset(pass_opt_t* opt, ast_t* type, lit_chain_t* chain)
{
  assert(chain != NULL);

  if(is_typecheck_error(type))
    return UIF_NO_TYPES;

  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
      return uifset_union(opt, type, chain);

    case TK_ISECTTYPE:
      return uifset_intersect(opt, type, chain);

    case TK_ARROW:
      // Since we don't care about capabilities we can just use the rhs
      assert(ast_id(ast_childidx(type, 1)) == TK_NOMINAL);
      return uifset(opt, ast_childidx(type, 1), chain);

    case TK_TYPEPARAMREF:
      if(chain->cardinality != CHAIN_CARD_BASE) // Incorrect cardinality
        return UIF_NO_TYPES;

      return uifset_formal_param(opt, type, chain);

    case TK_TUPLETYPE:
      if(chain->cardinality != ast_childcount(type)) // Incorrect cardinality
        return UIF_NO_TYPES;

      return uifset(opt, ast_childidx(type, chain->index), chain->next);

    case TK_NOMINAL:
      if(strcmp(ast_name(ast_childidx(type, 1)), "Array") == 0)
      {
        if(chain->cardinality != CHAIN_CARD_ARRAY) // Incorrect cardinality
          return UIF_NO_TYPES;

        ast_t* type_args = ast_childidx(type, 2);
        assert(ast_childcount(type_args) == 1);
        return uifset(opt, ast_child(type_args), chain->next);
      }

      if(chain->cardinality != CHAIN_CARD_BASE) // Incorrect cardinality
        return UIF_NO_TYPES;

      return uifset_simple_type(opt, type);

    default:
      ast_error(type, "Internal error: uif type, node %d", ast_id(type));
      assert(0);
      return UIF_ERROR;
  }
}
Exemple #2
0
// Determine the UIF types that the given non-tuple union type may be
static int uifset_union(pass_opt_t* opt, ast_t* type, lit_chain_t* chain)
{
  assert(type != NULL);
  assert(ast_id(type) == TK_UNIONTYPE);

  int uif_set = 0;

  // Process all elements of the union
  for(ast_t* p = ast_child(type); p != NULL; p = ast_sibling(p))
  {
    int r = uifset(opt, p, chain);

    if(r == UIF_ERROR)  // Propogate errors
      return UIF_ERROR;

    bool child_valid = (r != UIF_NO_TYPES);
    bool child_formal = ((r & UIF_CONSTRAINED) != 0);
    bool others_valid = ((uif_set & UIF_ALL_TYPES) != 0);
    bool others_formal = ((uif_set & UIF_CONSTRAINED) != 0);

    if(child_valid && others_valid && (child_formal != others_formal))
    {
      // We're unioning a formal parameter and a UIF type, not allowed
      ast_error(type, "Could not infer literal type, ambiguous union");
      return UIF_ERROR;
    }

    uif_set |= r;
  }

  return uif_set;
}
Exemple #3
0
// Fill the given UIF type cache
static bool uif_type(pass_opt_t* opt, ast_t* literal, ast_t* type,
  lit_chain_t* chain_head, bool report_errors)
{
  pony_assert(chain_head != NULL);
  pony_assert(chain_head->cardinality == CHAIN_CARD_BASE);

  chain_head->formal = NULL;
  int r = uifset(opt, type, chain_head->next);

  if(r == UIF_ERROR)
    return false;

  if(r == UIF_NO_TYPES)
  {
    if(report_errors)
      ast_error(opt->check.errors, literal,
        "could not infer literal type, no valid types found");

    return false;
  }

  pony_assert(type != NULL);

  if((r & UIF_CONSTRAINED) != 0)
  {
    // Type is a formal parameter
    pony_assert(chain_head->formal != NULL);
    pony_assert(chain_head->name != NULL);
    pony_assert(chain_head->cached_uif_index < 0);

    BUILD(uif_type, type,
      NODE(TK_TYPEPARAMREF, DATA(chain_head->formal)
      ID(chain_head->name) NODE(TK_VAL) NONE));

    chain_head->cached_type = uif_type;
    chain_head->valid_for_float = ((r & UIF_INT_MASK) == 0);
    return true;
  }

  // Type is one or more UIFs
  for(int i = 0; i < UIF_COUNT; i++)
  {
    if(r == (1 << i))
    {
      chain_head->valid_for_float = (((1 << i) & UIF_INT_MASK) == 0);
      chain_head->cached_type =
        type_builtin(opt, type, _str_uif_types[i].name);
      //ast_setid(ast_childidx(chain_head->cached_type, 4), TK_EPHEMERAL);
      chain_head->name = _str_uif_types[i].name;
      chain_head->cached_uif_index = i;
      return true;
    }
  }

  ast_error(opt->check.errors, literal, "Multiple possible types for literal");
  return false;
}
Exemple #4
0
// Determine the UIF types that the given non-tuple intersection type may be
static int uifset_intersect(pass_opt_t* opt, ast_t* type, lit_chain_t* chain)
{
  assert(type != NULL);
  assert(ast_id(type) == TK_ISECTTYPE);

  int uif_set = UIF_ALL_TYPES;
  int constraint = 0;

  for(ast_t* p = ast_child(type); p != NULL; p = ast_sibling(p))
  {
    int r = uifset(opt, p, chain);

    if(r == UIF_ERROR)  // Propogate errors
      return UIF_ERROR;

    if((r & UIF_CONSTRAINED) != 0)
    {
      // We have a formal parameter
      constraint = r;
    }
    else
    {
      uif_set |= r;
    }
  }

  if(constraint != 0)
  {
    // We had a formal parameter
    int constraint_set = constraint & UIF_ALL_TYPES;

    if((constraint_set & uif_set) != constraint_set)
      // UIF type limits formal parameter types, no UIF guaranteed
      return UIF_NO_TYPES;

    return constraint;
  }

  return uif_set;
}