Пример #1
0
// Compare the 2 given signatures to see if they are exactly the same
static bool compare_signatures(ast_t* sig_a, ast_t* sig_b)
{
  if(sig_a == NULL && sig_b == NULL)
    return true;

  if(sig_a == NULL || sig_b == NULL)
    return false;

  token_id a_id = ast_id(sig_a);

  if(a_id != ast_id(sig_b))
    return false;

  switch(a_id)
  {
    case TK_BE:
    case TK_FUN:
    case TK_NEW:
    {
      // Check everything except body and docstring, ie first 6 children
      ast_t* a_child = ast_child(sig_a);
      ast_t* b_child = ast_child(sig_b);

      for(int i = 0; i < 6; i++)
      {
        if(a_child == NULL || b_child == NULL)
          return false;

        if(!compare_signatures(a_child, b_child))
          return false;

        a_child = ast_sibling(a_child);
        b_child = ast_sibling(b_child);
      }

      return true;
    }

    case TK_STRING:
    case TK_ID:
    {
      // Can't just use strcmp, string literals may contain \0s
      size_t a_len = ast_name_len(sig_a);
      size_t b_len = ast_name_len(sig_b);

      if(a_len != b_len)
        return false;

      const char* a_text = ast_name(sig_a);
      const char* b_text = ast_name(sig_b);

      for(size_t i = 0; i < a_len; i++)
      {
        if(a_text[i] != b_text[i])
          return false;
      }

      return true;
    }

    case TK_INT:     return lexint_cmp(ast_int(sig_a), ast_int(sig_b)) == 0;
    case TK_FLOAT:   return ast_float(sig_a) == ast_float(sig_b);

    case TK_NOMINAL:
      if(ast_data(sig_a) != ast_data(sig_b))
        return false;

      break;

    default:
      break;
  }

  ast_t* a_child = ast_child(sig_a);
  ast_t* b_child = ast_child(sig_b);

  while(a_child != NULL && b_child != NULL)
  {
    if(!compare_signatures(a_child, b_child))
      return false;

    a_child = ast_sibling(a_child);
    b_child = ast_sibling(b_child);
  }

  if(a_child != NULL || b_child != NULL)
    return false;

  return true;
}
Пример #2
0
// Assign a UIF type from the given target type to the given AST
static bool uif_type_from_chain(pass_opt_t* opt, ast_t* literal,
  ast_t* target_type, lit_chain_t* chain, bool require_float,
  bool report_errors)
{
  pony_assert(literal != NULL);
  pony_assert(chain != NULL);

  lit_chain_t* chain_head = chain;
  while(chain_head->cardinality != CHAIN_CARD_BASE)
    chain_head = chain_head->next;

  if(chain_head->cached_type == NULL)
  {
    // This is the first time we've needed this type, find it
    if(!uif_type(opt, literal, target_type, chain_head, report_errors))
      return false;
  }

  if(require_float && !chain_head->valid_for_float)
  {
    if(report_errors)
      ast_error(opt->check.errors, literal, "Inferred possibly integer type %s for float literal",
        chain_head->name);

    return false;
  }

  if(ast_id(literal) == TK_INT && chain_head->cached_uif_index >= 0)
  {
    // Check for literals that are outside the range of their type.
    // Note we don't check for types bound to type parameters.
    int i = chain_head->cached_uif_index;

    if(_str_uif_types[i].limit.low != 0 || _str_uif_types[i].limit.high != 0)
    {
      // There is a limit specified for this type, the literal must be smaller
      // than that.
      bool neg_plus_one = false;

      if(_str_uif_types[i].neg_plus_one)
      {
        // If the literal is immediately negated it can be equal to the given
        // limit. This is because of how the world chooses to encode negative
        // integers.
        // For example, the maximum value in an I8 is 127. But the minimum
        // value is -128.
        // We don't actually calculate the negative value here, but we have a
        // looser test if the literal is immediately negated.
        // We do not do this if the negation is not immediate, eg "-(128)".
        ast_t* parent = ast_parent(literal);
        pony_assert(parent != NULL);
        ast_t* parent_type = ast_type(parent);

        if(parent_type != NULL && ast_id(parent_type) == TK_OPERATORLITERAL &&
          ast_child(parent) == literal &&
          ((lit_op_info_t const*)ast_data(parent_type))->neg_plus_one)
          neg_plus_one = true;
      }

      lexint_t* actual = ast_int(literal);
      int test = lexint_cmp(actual, &_str_uif_types[i].limit);

      if((test > 0) || (!neg_plus_one && (test == 0)))
      {
        // Illegal value.
        ast_error(opt->check.errors, literal, "Literal value is out of range for type (%s)",
          chain_head->name);
        return false;
      }
    }
  }

  ast_settype(literal, chain_head->cached_type);
  return true;
}