Exemplo n.º 1
0
// Write the given list of parameters to the current type file, with
// surrounding (). If the given list is empty () is still written.
static void doc_params(docgen_t* docgen, ast_t* params)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(params != NULL);

  fprintf(docgen->type_file, "(");
  ast_t* first = ast_child(params);

  for(ast_t* param = first; param != NULL; param = ast_sibling(param))
  {
    if(param != first)
      fprintf(docgen->type_file, ", ");

    AST_GET_CHILDREN(param, id, type, def_val);
    const char* name = ast_name(id);
    assert(name != NULL);

    if(ast_id(def_val) != TK_NONE)
      fprintf(docgen->type_file, "optional ");

    fprintf(docgen->type_file, "%s: ", name);
    doc_type(docgen, type);
  }

  fprintf(docgen->type_file, ")");
}
Exemplo n.º 2
0
// Write the given list of types to the current type file, with the specified
// preamble, separator and psotamble text. If the list is empty nothing is
// written.
static void doc_type_list(docgen_t* docgen, ast_t* list, const char* preamble,
  const char* separator, const char* postamble)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(list != NULL);
  assert(preamble != NULL);
  assert(separator != NULL);
  assert(postamble != NULL);

  if(ast_id(list) == TK_NONE)
    return;

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

  for(ast_t* p = ast_child(list); p != NULL; p = ast_sibling(p))
  {
    doc_type(docgen, p);

    if(ast_sibling(p) != NULL)
      fprintf(docgen->type_file, "%s", separator);
  }

  fprintf(docgen->type_file, "%s", postamble);
}
Exemplo n.º 3
0
// Write the given list of fields to the current type file.
// The given title text is used as a section header.
// If the field list is empty nothing is written.
static void doc_fields(docgen_t* docgen, ast_list_t* fields, const char* title)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(fields != NULL);
  assert(title != NULL);

  if(fields->next == NULL)  // No fields
    return;

  fprintf(docgen->type_file, "# %s\n\n", title);

  for(ast_list_t* p = fields->next; p != NULL; p = p->next)
  {
    ast_t* field = p->ast;
    assert(field != NULL);

    AST_GET_CHILDREN(field, id, type, init);
    const char* name = ast_name(id);
    assert(name != NULL);

    // Don't want ast_get_print() as that will give us flet or fvar
    fprintf(docgen->type_file, "* %s %s: ",
      (ast_id(field) == TK_VAR) ? "var" : "let", name);

    doc_type(docgen, type);
    fprintf(docgen->type_file, "\n");
  }
}
Exemplo n.º 4
0
// Write the given list of types to the current type file, with the specified
// preamble, separator and psotamble text. If the list is empty nothing is
// written.
static void doc_type_list(docgen_t* docgen, ast_t* list, const char* preamble,
  const char* separator, const char* postamble, bool generate_links, bool line_breaks)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(list != NULL);
  assert(preamble != NULL);
  assert(separator != NULL);
  assert(postamble != NULL);

  if(ast_id(list) == TK_NONE)
    return;

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

  int listItemCount = 0;
  for(ast_t* p = ast_child(list); p != NULL; p = ast_sibling(p))
  {
    doc_type(docgen, p, generate_links);

    if(ast_sibling(p) != NULL) {
      fprintf(docgen->type_file, "%s", separator);

      if (line_breaks) {
        if (listItemCount++ == 2) {
          fprintf(docgen->type_file, "\n    ");
          listItemCount = 0;
        }
      }
    }

  }

  fprintf(docgen->type_file, "%s", postamble);
}
Exemplo n.º 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);

  // 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));
}
Exemplo n.º 6
0
// Write the given list of type parameters to the current type file, with
// surrounding []. If the given list is empty nothing is written.
static void doc_type_params(docgen_t* docgen, ast_t* t_params,
  bool generate_links)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(t_params != NULL);

  if(ast_id(t_params) == TK_NONE)
    return;

  assert(ast_id(t_params) == TK_TYPEPARAMS);

  if(generate_links)
    fprintf(docgen->type_file, "\\[");
  else
    fprintf(docgen->type_file, "[");
  ast_t* first = ast_child(t_params);

  for(ast_t* t_param = first; t_param != NULL; t_param = ast_sibling(t_param))
  {
    if(t_param != first)
      fprintf(docgen->type_file, ", ");

    AST_GET_CHILDREN(t_param, id, constraint, default_type);
    const char* name = ast_name(id);
    assert(name != NULL);

    if(ast_id(default_type) != TK_NONE)
      fprintf(docgen->type_file, "optional ");

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

    if(ast_id(constraint) != TK_NONE)
      doc_type(docgen, constraint, generate_links);
    else
      fprintf(docgen->type_file, "no constraint");
  }

  if(generate_links)
    fprintf(docgen->type_file, "\\]");
  else
    fprintf(docgen->type_file, "]");
}
Exemplo n.º 7
0
static void list_doc_params(docgen_t* docgen, ast_t* params)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(params != NULL);

  ast_t* first = ast_child(params);

  for(ast_t* param = first; param != NULL; param = ast_sibling(param))
  {
    if(param == first)
      fprintf(docgen->type_file, "#### Parameters\n\n");

    fprintf(docgen->type_file, "* ");

    AST_GET_CHILDREN(param, id, type, def_val);
    const char* name = ast_name(id);
    assert(name != NULL);

    fprintf(docgen->type_file, "  %s: ", name);
    doc_type(docgen, type, true);

    // if we have a default value, add it to the documentation
    if(ast_id(def_val) != TK_NONE)
    {
      switch(ast_id(def_val))
      {
        case TK_STRING:
          fprintf(docgen->type_file, "= \"%s\"", ast_get_print(def_val));
          break;

        default:
          fprintf(docgen->type_file, " = %s", ast_get_print(def_val));
          break;
      }
    }

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

  fprintf(docgen->type_file, "\n");
}
Exemplo n.º 8
0
// Write the given list of fields to the current type file.
// The given title text is used as a section header.
// If the field list is empty nothing is written.
static void doc_fields(docgen_t* docgen, ast_list_t* fields, const char* title)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(fields != NULL);
  assert(title != NULL);

  if(fields->next == NULL)  // No fields
    return;

  fprintf(docgen->type_file, "## %s\n\n", title);

  for(ast_list_t* p = fields->next; p != NULL; p = p->next)
  {
    ast_t* field = p->ast;
    assert(field != NULL);

    AST_GET_CHILDREN(field, id, type, init);
    const char* name = ast_name(id);
    assert(name != NULL);

    // Don't want ast_get_print() as that will give us flet or fvar
    const char* ftype = NULL;

    switch(ast_id(field))
    {
      case TK_FVAR: ftype = "var"; break;
      case TK_FLET: ftype = "let"; break;
      case TK_EMBED: ftype = "embed"; break;
      default: assert(0);
    }

    fprintf(docgen->type_file, "* %s %s: ", ftype, name);
    doc_type(docgen, type, true);
    fprintf(docgen->type_file, "\n\n---\n\n");
  }
}
Exemplo n.º 9
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);
  }
}
Exemplo n.º 10
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");
}
Exemplo n.º 11
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);
  }
}