Beispiel #1
0
// Process the given provided method for the given entity.
// The method passed should be reified already and will be freed by this
// function.
static bool provided_method(ast_t* entity, ast_t* reified_method,
  ast_t* raw_method, ast_t** last_method)
{
  assert(entity != NULL);
  assert(reified_method != NULL);
  assert(last_method != NULL);

  const char* entity_name = ast_name(ast_child(entity));

  if(ast_id(reified_method) == TK_BE || ast_id(reified_method) == TK_NEW)
  {
    // Modify return type to the inheritting type
    ast_t* ret_type = ast_childidx(reified_method, 4);
    assert(ast_id(ret_type) == TK_NOMINAL);

    const char* pkg_name = package_name(ast_nearest(entity, TK_PACKAGE));
    ast_set_name(ast_childidx(ret_type, 0), pkg_name);
    ast_set_name(ast_childidx(ret_type, 1), entity_name);
  }

  // Ignore docstring
  ast_t* doc = ast_childidx(reified_method, 7);

  if(ast_id(doc) == TK_STRING)
  {
    ast_set_name(doc, "");
    ast_setid(doc, TK_NONE);
  }

  // Check for existing method of the same name
  const char* name = ast_name(ast_childidx(reified_method, 1));
  assert(name != NULL);

  ast_t* existing = ast_get(entity, name, NULL);

  if(existing != NULL && is_field(existing))
  {
    ast_error(existing, "field '%s' clashes with provided method", name);
    ast_error(raw_method, "method is defined here");
    ast_free_unattached(reified_method);
    return false;
  }

  existing = add_method(entity, existing, reified_method, last_method);

  if(existing == NULL)
  {
    ast_free_unattached(reified_method);
    return false;
  }

  method_t* info = (method_t*)ast_data(existing);
  assert(info != NULL);

  if(!record_default_body(reified_method, raw_method, info))
    ast_free_unattached(reified_method);

  return true;
}
Beispiel #2
0
// Process the given provided method for the given entity.
// The method passed should be reified already and will be freed by this
// function.
static bool provided_method(pass_opt_t* opt, ast_t* entity,
  ast_t* reified_method, ast_t* raw_method, ast_t** last_method)
{
  assert(entity != NULL);
  assert(reified_method != NULL);
  assert(last_method != NULL);

  AST_GET_CHILDREN(reified_method, cap, id, typeparams, params, result,
    can_error, body, doc);

  if(ast_id(reified_method) == TK_BE || ast_id(reified_method) == TK_NEW)
  {
    // Modify return type to the inheriting type
    ast_t* this_type = type_for_this(opt, entity, ast_id(cap),
      TK_EPHEMERAL, true);

    ast_replace(&result, this_type);
  }

  // Ignore docstring
  if(ast_id(doc) == TK_STRING)
  {
    ast_set_name(doc, "");
    ast_setid(doc, TK_NONE);
  }

  // Check for existing method of the same name
  const char* name = ast_name(id);
  assert(name != NULL);

  ast_t* existing = ast_get(entity, name, NULL);

  if(existing != NULL && is_field(existing))
  {
    ast_error(existing, "field '%s' clashes with provided method", name);
    ast_error(raw_method, "method is defined here");
    ast_free_unattached(reified_method);
    return false;
  }

  existing = add_method(entity, existing, reified_method, last_method);

  if(existing == NULL)
  {
    ast_free_unattached(reified_method);
    return false;
  }

  method_t* info = (method_t*)ast_data(existing);
  assert(info != NULL);

  if(!record_default_body(reified_method, raw_method, info))
    ast_free_unattached(reified_method);

  return true;
}