Beispiel #1
0
// Write a description of the given method to the current type file
static void doc_method(docgen_t* docgen, ast_t* method)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(method != NULL);

  AST_GET_CHILDREN(method, cap, id, t_params, params, ret, error, body, doc);

  const char* name = ast_name(id);
  assert(name != NULL);

  // Sub heading
  fprintf(docgen->type_file, "## %s %s()\n", ast_get_print(method), name);

  // Reconstruct signature
  fprintf(docgen->type_file, "%s", ast_get_print(method));

  if(ast_id(method) == TK_FUN)
  {
    const char* cap_text = doc_get_cap(cap);
    if(cap_text != NULL)
      fprintf(docgen->type_file, " %s\n", cap_text);
  }

  fprintf(docgen->type_file, " %s", name);
  doc_type_params(docgen, t_params);
  doc_params(docgen, params);

  if(ast_id(method) == TK_FUN)
  {
    fprintf(docgen->type_file, ": ");
    doc_type(docgen, ret);
  }

  if(ast_id(error) == TK_QUESTION)
    fprintf(docgen->type_file, " ?");

  // Further information
  fprintf(docgen->type_file, "\n\n");
  fprintf(docgen->type_file, "%s", (name[0] == '_') ? "Private" : "Public");

  if(ast_id(error) == TK_QUESTION)
    fprintf(docgen->type_file, ", may raise an error");

  fprintf(docgen->type_file, ".\n\n");

  // Finally the docstring, if any
  if(ast_id(doc) != TK_NONE)
    fprintf(docgen->type_file, "%s\n\n", ast_name(doc));
}
Beispiel #2
0
// Write a description of the given entity to its own type file.
// The containing package is handed in to save looking it up again.
static void doc_entity(docgen_t* docgen, ast_t* ast, ast_t* package)
{
  assert(docgen != NULL);
  assert(docgen->index_file != NULL);
  assert(docgen->type_file == NULL);
  assert(ast != NULL);
  assert(package != NULL);

  // First open a file
  size_t tqfn_len;
  char* tqfn = write_tqfn(ast, NULL, &tqfn_len);

  docgen->type_file = doc_open_file(docgen, true, tqfn, ".md");

  if(docgen->type_file == NULL)
    return;

  // Add reference to new file to index file
  AST_GET_CHILDREN(ast, id, tparams, cap, provides, members, c_api, doc);

  const char* name = ast_name(id);
  assert(name != NULL);

  fprintf(docgen->index_file, "  - %s %s: \"%s.md\"\n",
    ast_get_print(ast), name, tqfn);

  pool_free_size(tqfn_len, tqfn);

  // Now we can write the actual documentation for the entity
  fprintf(docgen->type_file, "%s %s", ast_get_print(ast), name);
  doc_type_params(docgen, tparams);
  doc_type_list(docgen, provides, " is ", ", ", "");
  fprintf(docgen->type_file, "\n\nIn package \"%s\".\n\n",
    package_qualified_name(package));

  fprintf(docgen->type_file, "%s", (name[0] == '_') ? "Private" : "Public");

  const char* cap_text = doc_get_cap(cap);
  if(cap_text != NULL)
    fprintf(docgen->type_file, ", default capability %s", cap_text);

  fprintf(docgen->type_file, ".\n\n");

  if(ast_id(c_api) == TK_AT)
    fprintf(docgen->type_file, "May be called from C.\n");

  if(ast_id(doc) != TK_NONE)
    fprintf(docgen->type_file, "%s\n\n", ast_name(doc));
  else
    fprintf(docgen->type_file, "No doc string provided.\n\n");

  // Sort members into varieties
  ast_list_t pub_fields = { NULL, NULL, NULL };
  ast_list_t news = { NULL, NULL, NULL };
  ast_list_t bes = { NULL, NULL, NULL };
  ast_list_t funs = { NULL, NULL, NULL };

  for(ast_t* p = ast_child(members); p != NULL; p = ast_sibling(p))
  {
    switch(ast_id(p))
    {
      case TK_FVAR:
      case TK_FLET:
        doc_list_add_named(&pub_fields, p, 0, true, false);
        break;

      case TK_NEW:
        doc_list_add_named(&news, p, 1, true, true);
        break;

      case TK_BE:
        doc_list_add_named(&bes, p, 1, true, true);
        break;

      case TK_FUN:
        doc_list_add_named(&funs, p, 1, true, true);
        break;

      default:
        assert(0);
        break;
    }
  }

  // Handle member variety lists
  doc_fields(docgen, &pub_fields, "Public fields");
  doc_methods(docgen, &news, "Constructors");
  doc_methods(docgen, &bes, "Behaviours");
  doc_methods(docgen, &funs, "Functions");

  doc_list_free(&pub_fields);
  doc_list_free(&news);
  doc_list_free(&bes);
  doc_list_free(&funs);

  fclose(docgen->type_file);
  docgen->type_file = NULL;
}
Beispiel #3
0
// Write the given type to the current type file
static void doc_type(docgen_t* docgen, ast_t* type)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(type != NULL);

  switch(ast_id(type))
  {
    case TK_NOMINAL:
    {
      AST_GET_CHILDREN(type, package, id, tparams, cap, ephemeral);

      // Find type we reference so we can link to it
      ast_t* target = (ast_t*)ast_data(type);
      assert(target != NULL);

      size_t link_len;
      char* tqfn = write_tqfn(target, NULL, &link_len);

      // Links are of the form: [text](target)
      fprintf(docgen->type_file, "[%s](%s)", ast_name(id), tqfn);
      pool_free_size(link_len, tqfn);

      doc_type_list(docgen, tparams, "\\[", ", ", "\\]");

      const char* cap_text = doc_get_cap(cap);
      if(cap_text != NULL)
        fprintf(docgen->type_file, " %s", cap_text);

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_UNIONTYPE:
      doc_type_list(docgen, type, "(", " | ", ")");
      break;

    case TK_ISECTTYPE:
      doc_type_list(docgen, type, "(", " & ", ")");
      break;

    case TK_TUPLETYPE:
      doc_type_list(docgen, type, "(", " , ", ")");
      break;

    case TK_TYPEPARAMREF:
    {
      AST_GET_CHILDREN(type, id, cap, ephemeral);
      fprintf(docgen->type_file, "%s", ast_name(id));

      const char* cap_text = doc_get_cap(cap);
      if(cap_text != NULL)
        fprintf(docgen->type_file, " %s", cap_text);

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_ARROW:
    {
      AST_GET_CHILDREN(type, left, right);
      doc_type(docgen, left);
      fprintf(docgen->type_file, "->");
      doc_type(docgen, right);
      break;
    }

    case TK_THISTYPE:
      fprintf(docgen->type_file, "this");
      break;

    case TK_BOXTYPE:
      fprintf(docgen->type_file, "box");
      break;

    default:
      assert(0);
  }
}
Beispiel #4
0
// Write a description of the given entity to its own type file.
static void doc_entity(docgen_t* docgen, ast_t* ast)
{
  assert(docgen != NULL);
  assert(docgen->index_file != NULL);
  assert(docgen->package_file != NULL);
  assert(docgen->test_types != NULL);
  assert(docgen->public_types != NULL);
  assert(docgen->private_types != NULL);
  assert(docgen->type_file == NULL);
  assert(ast != NULL);

  // First open a file
  size_t tqfn_len;
  char* tqfn = write_tqfn(ast, NULL, &tqfn_len);

  docgen->type_file = doc_open_file(docgen, true, tqfn, ".md");

  if(docgen->type_file == NULL)
    return;

  // Add reference to new file to index file
  AST_GET_CHILDREN(ast, id, tparams, cap, provides, members, c_api, doc);

  const char* name = ast_name(id);
  assert(name != NULL);

  fprintf(docgen->index_file, "  - %s %s: \"%s.md\"\n",
    ast_get_print(ast), name, tqfn);

  // Add to appropriate package types buffer
  printbuf_t* buffer = docgen->public_types;
  if(is_for_testing(name, provides)) buffer = docgen->test_types;
  else if(name[0] == '_') buffer = docgen->private_types;
  printbuf(buffer,
           "* [%s %s](%s.md)\n",
           ast_get_print(ast), name, tqfn);

  ponyint_pool_free_size(tqfn_len, tqfn);

  // Now we can write the actual documentation for the entity
  fprintf(docgen->type_file, "# %s", name);
  doc_type_params(docgen, tparams, true);
  fprintf(docgen->type_file, "\n\n");

  if(ast_id(doc) != TK_NONE)
    fprintf(docgen->type_file, "%s\n\n", ast_name(doc));

  // code block
  fprintf(docgen->type_file, "```pony\n");
  fprintf(docgen->type_file, "%s ",ast_get_print(ast));

  const char* cap_text = doc_get_cap(cap);
  if(cap_text != NULL) fprintf(docgen->type_file, "%s ", cap_text);

  fprintf(docgen->type_file, "%s", name);

  doc_type_params(docgen, tparams, false);
  doc_type_list(docgen, provides, " is\n  ", ",\n  ", "", false);
  fprintf(docgen->type_file, "\n```\n\n");

  if (ast_id(ast) !=  TK_TYPE)
    doc_type_list(docgen, provides,
      "#### Implements\n\n* ", "\n* ", "\n\n---\n\n", true);
  else
    doc_type_list(docgen, provides,
      "#### Type Alias For\n\n* ", "\n* ", "\n\n---\n\n", true);

  // Sort members into varieties
  ast_list_t pub_fields = { NULL, NULL, NULL };
  ast_list_t news = { NULL, NULL, NULL };
  ast_list_t pub_bes = { NULL, NULL, NULL };
  ast_list_t priv_bes = { NULL, NULL, NULL };
  ast_list_t pub_funs = { NULL, NULL, NULL };
  ast_list_t priv_funs = { NULL, NULL, NULL };

  for(ast_t* p = ast_child(members); p != NULL; p = ast_sibling(p))
  {
    switch(ast_id(p))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
        doc_list_add_named(&pub_fields, p, 0, true, false);
        break;

      case TK_NEW:
        doc_list_add_named(&news, p, 1, true, true);
        break;

      case TK_BE:
        doc_list_add_named(&pub_bes, p, 1, true, false);
        doc_list_add_named(&priv_bes, p, 1, false, true);
        break;

      case TK_FUN:
        doc_list_add_named(&pub_funs, p, 1, true, false);
        doc_list_add_named(&priv_funs, p, 1, false, true);
        break;

      default:
        assert(0);
        break;
    }
  }

  // Handle member variety lists
  doc_methods(docgen, &news, "Constructors");
  doc_fields(docgen, &pub_fields, "Public fields");
  doc_methods(docgen, &pub_bes, "Public Behaviours");
  doc_methods(docgen, &pub_funs, "Public Functions");
  doc_methods(docgen, &priv_bes, "Private Behaviours");
  doc_methods(docgen, &priv_funs, "Private Functions");

  doc_list_free(&pub_fields);
  doc_list_free(&news);
  doc_list_free(&pub_bes);
  doc_list_free(&priv_bes);
  doc_list_free(&pub_funs);
  doc_list_free(&priv_funs);

  fclose(docgen->type_file);
  docgen->type_file = NULL;
}
Beispiel #5
0
// Write a description of the given method to the current type file
static void doc_method(docgen_t* docgen, ast_t* method)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(method != NULL);

  AST_GET_CHILDREN(method, cap, id, t_params, params, ret, error, body, doc);

  const char* name = ast_name(id);
  assert(name != NULL);

  // Method
  fprintf(docgen->type_file, "### %s", name);
  doc_type_params(docgen, t_params, true);
  fprintf(docgen->type_file, "\n\n");

  // The docstring, if any
  if(ast_id(doc) != TK_NONE)
    fprintf(docgen->type_file, "%s\n\n", ast_name(doc));

  // SYLVAN'S FULL CODE BLOCK HERE
  fprintf(docgen->type_file, "```pony\n");
  fprintf(docgen->type_file, "%s ", ast_get_print(method));
  if(ast_id(method) == TK_FUN || ast_id(method) == TK_NEW)
  {
    const char* cap_text = doc_get_cap(cap);
    if(cap_text != NULL) fprintf(docgen->type_file, "%s ", cap_text);
  }
  fprintf(docgen->type_file, "%s", name);
  doc_type_params(docgen, t_params, false);
  // parameters of the code block
  code_block_doc_params(docgen, params);

  // return type
  if(ast_id(method) == TK_FUN || ast_id(method) == TK_NEW)
  {
    fprintf(docgen->type_file, "\n: ");
    doc_type(docgen, ret, false);

    if(ast_id(error) == TK_QUESTION)
      fprintf(docgen->type_file, " ?");
  }

  // close the block
  fprintf(docgen->type_file, "\n```\n");

  // Parameters
  list_doc_params(docgen, params);

  // Return value
  if(ast_id(method) == TK_FUN || ast_id(method) == TK_NEW)
  {
    fprintf(docgen->type_file, "#### Returns\n\n");
    fprintf(docgen->type_file, "* ");
    doc_type(docgen, ret, true);

    if(ast_id(error) == TK_QUESTION)
      fprintf(docgen->type_file, " ?");

    fprintf(docgen->type_file, "\n\n");
  }

  // horizontal rule at the end
  // separate us from the next method visually
  fprintf(docgen->type_file, "---\n\n");
}
Beispiel #6
0
// Write the given type to the current type file
static void doc_type(docgen_t* docgen, ast_t* type, bool generate_links)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(type != NULL);

  switch(ast_id(type))
  {
    case TK_NOMINAL:
    {
      AST_GET_CHILDREN(type, package, id, tparams, cap, ephemeral);

      // Generate links only if directed to and if the type is not anonymous (as
      // indicated by a name created by package_hygienic_id).
      if(generate_links && *ast_name(id) != '$')
      {
        // Find type we reference so we can link to it
        ast_t* target = (ast_t*)ast_data(type);
        assert(target != NULL);

        size_t link_len;
        char* tqfn = write_tqfn(target, NULL, &link_len);

        // Links are of the form: [text](target)
        fprintf(docgen->type_file, "[%s](%s)", ast_nice_name(id), tqfn);
        ponyint_pool_free_size(link_len, tqfn);

        doc_type_list(docgen, tparams, "\\[", ", ", "\\]", true, false);
      }
      else
      {
        fprintf(docgen->type_file, "%s", ast_nice_name(id));
        doc_type_list(docgen, tparams, "[", ", ", "]", false, false);
      }

      const char* cap_text = doc_get_cap(cap);
      if(cap_text != NULL)
        fprintf(docgen->type_file, " %s", cap_text);

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_UNIONTYPE:
      doc_type_list(docgen, type, "(", " | ", ")", generate_links, true);
      break;

    case TK_ISECTTYPE:
      doc_type_list(docgen, type, "(", " & ", ")", generate_links, false);
      break;

    case TK_TUPLETYPE:
      doc_type_list(docgen, type, "(", " , ", ")", generate_links, false);
      break;

    case TK_TYPEPARAMREF:
    {
      AST_GET_CHILDREN(type, id, cap, ephemeral);
      fprintf(docgen->type_file, "%s", ast_nice_name(id));

      const char* cap_text = doc_get_cap(cap);
      if(cap_text != NULL)
        fprintf(docgen->type_file, " %s", cap_text);

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_ARROW:
    {
      AST_GET_CHILDREN(type, left, right);
      doc_type(docgen, left, generate_links);
      fprintf(docgen->type_file, "->");
      doc_type(docgen, right, generate_links);
      break;
    }

    case TK_THISTYPE:
      fprintf(docgen->type_file, "this");
      break;

    case TK_ISO:
    case TK_TRN:
    case TK_REF:
    case TK_VAL:
    case TK_BOX:
    case TK_TAG:
      fprintf(docgen->type_file, "%s", ast_get_print(type));
      break;

    default:
      assert(0);
  }
}