Пример #1
0
// Unify all the branches of the given AST to the same type
static bool unify(ast_t* ast, pass_opt_t* options, bool report_errors)
{
  assert(ast != NULL);
  ast_t* type = ast_type(ast);

  if(is_typecheck_error(type))
    return false;

  if(!is_type_literal(type)) // Not literal, nothing to unify
    return true;

  assert(type != NULL);
  ast_t* non_literal = ast_type(type);

  if(non_literal != NULL)
  {
    // Type has a non-literal element, coerce literals to that
    lit_chain_t chain;
    chain_init_head(&chain);
    return coerce_literal_to_type(&ast, non_literal, &chain, options,
      report_errors);
    //return coerce_literals(&ast, non_literal, options);
  }

  // Still a pure literal
  return true;
}
Пример #2
0
// Coerce a literal group (tuple or array) to be the specified target type
static bool coerce_group(ast_t** astp, ast_t* target_type, lit_chain_t* chain,
  size_t cardinality, pass_opt_t* options, bool report_errors)
{
  pony_assert(astp != NULL);
  ast_t* literal_expr = *astp;
  pony_assert(literal_expr != NULL);
  pony_assert(ast_id(literal_expr) == TK_TUPLE || ast_id(literal_expr) == TK_ARRAY);
  pony_assert(chain != NULL);
  pony_assert(cardinality != CHAIN_CARD_BASE);

  size_t i = 0;
  lit_chain_t link;

  chain_add(chain, &link, cardinality);

  if(ast_id(literal_expr) == TK_ARRAY)
  {
    // The first child of an array AST is the forced type, the second child is
    // the sequence of elements.
    literal_expr = ast_childidx(literal_expr, 1);
  }

  // Process each group element separately
  for(ast_t* p = ast_child(literal_expr); p != NULL; p = ast_sibling(p))
  {
    ast_t* p_type = ast_type(p);

    if(is_typecheck_error(p_type))
      return false;

    if(is_type_literal(p_type))
    {
      // This element is a literal
      if(cardinality != CHAIN_CARD_ARRAY)
      {
        chain_clear_cache(&link);
        link.index = i;
      }

      if(!coerce_literal_to_type(&p, target_type, &link, options,
        report_errors))
        return false;
    }

    i++;
  }

  chain_remove(chain);
  return true;
}
Пример #3
0
// Coerce a literal control block to be the specified target type
static bool coerce_control_block(ast_t** astp, ast_t* target_type,
  lit_chain_t* chain, pass_opt_t* options, bool report_errors)
{
  assert(astp != NULL);
  ast_t* literal_expr = *astp;
  assert(literal_expr != NULL);

  ast_t* lit_type = ast_type(literal_expr);
  assert(lit_type != NULL);
  assert(ast_id(lit_type) == TK_LITERAL);
  ast_t* block_type = ast_type(lit_type);

  for(ast_t* p = ast_child(lit_type); p != NULL; p = ast_sibling(p))
  {
    assert(ast_id(p) == TK_LITERALBRANCH);
    ast_t* branch = (ast_t*)ast_data(p);
    assert(branch != NULL);

    if(!coerce_literal_to_type(&branch, target_type, chain, options,
      report_errors))
    {
      ast_free_unattached(block_type);
      return false;
    }

    block_type = type_union(block_type, ast_type(branch));
  }

  if(is_typecheck_error(block_type))
    return false;

  // block_type may be a sub-tree of the current type of literal_expr.
  // This means we must copy it before setting it as the type since ast_settype
  // will first free the existing type of literal_expr, which may include
  // block_type.
  if(ast_parent(block_type) != NULL)
    block_type = ast_dup(block_type);

  ast_settype(literal_expr, block_type);
  return true;
}
Пример #4
0
bool coerce_literals(ast_t** astp, ast_t* target_type, pass_opt_t* options)
{
  assert(astp != NULL);
  ast_t* literal_expr = *astp;
  assert(literal_expr != NULL);

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

  ast_t* lit_type = ast_type(literal_expr);

  if(lit_type != NULL && ast_id(lit_type) != TK_LITERAL &&
    ast_id(lit_type) != TK_OPERATORLITERAL)
    return true;

  if(target_type == NULL && !unify(literal_expr, options, true))
    return false;

  lit_chain_t chain;
  chain_init_head(&chain);
  return coerce_literal_to_type(astp, target_type, &chain, options, true);
}
Пример #5
0
// Coerce a literal expression to given tuple or non-tuple types
static bool coerce_literal_to_type(ast_t** astp, ast_t* target_type,
  lit_chain_t* chain, pass_opt_t* options, bool report_errors)
{
  assert(astp != NULL);
  ast_t* literal_expr = *astp;
  assert(literal_expr != NULL);

  ast_t* lit_type = ast_type(literal_expr);

  if(lit_type == NULL ||
    (ast_id(lit_type) != TK_LITERAL && ast_id(lit_type) != TK_OPERATORLITERAL))
  {
    // Not a literal
    return true;
  }

  if(ast_child(lit_type) != NULL)
  {
    // Control block literal
    return coerce_control_block(astp, target_type, chain, options,
      report_errors);
  }

  switch(ast_id(literal_expr))
  {
    case TK_TUPLE:  // Tuple literal
    {
      size_t cardinality = ast_childcount(literal_expr);
      if(!coerce_group(astp, target_type, chain, cardinality, options,
        report_errors))
        return false;

      break;
    }

    case TK_INT:
      return uif_type_from_chain(options, literal_expr, target_type, chain,
        false, report_errors);

    case TK_FLOAT:
      return uif_type_from_chain(options, literal_expr, target_type, chain,
        true, report_errors);

    case TK_ARRAY:
      if(!coerce_group(astp, target_type, chain, CHAIN_CARD_ARRAY, options,
        report_errors))
        return false;

      break;

    case TK_SEQ:
    {
      // Only coerce the last expression in the sequence
      ast_t* last = ast_childlast(literal_expr);

      if(!coerce_literal_to_type(&last, target_type, chain, options,
        report_errors))
        return false;

      ast_settype(literal_expr, ast_type(last));
      return true;
    }

    case TK_CALL:
    {
      AST_GET_CHILDREN(literal_expr, positional, named, receiver);
      ast_t* arg = ast_child(positional);

      if(!coerce_literal_to_type(&receiver, target_type, chain, options,
        report_errors))
        return false;

      if(arg != NULL &&
        !coerce_literal_to_type(&arg, target_type, chain, options,
        report_errors))
        return false;

      ast_settype(literal_expr, ast_type(ast_child(receiver)));
      return true;
    }

    case TK_DOT:
    {
      ast_t* receiver = ast_child(literal_expr);
      if(!coerce_literal_to_type(&receiver, target_type, chain, options,
        report_errors))
        return false;

      break;
    }

    default:
      ast_error(literal_expr, "Internal error, coerce_literal_to_type node %s",
        ast_get_print(literal_expr));
      assert(0);
      return false;
  }


  // Need to reprocess node now all the literals have types
  ast_settype(literal_expr, NULL);
  return (pass_expr(astp, options) == AST_OK);
}