示例#1
0
文件: docgen.c 项目: shlomif/ponyc
// 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));
}
示例#2
0
// Print an error preamble for the given node.
static void error_preamble(ast_t* ast)
{
  assert(ast != NULL);

  printf("Internal error: AST node %d (%s), ", ast_id(ast),
    ast_get_print(ast));
}
示例#3
0
文件: docgen.c 项目: shlomif/ponyc
// Report the human readable description for the given capability node.
// The returned string is valid forever and should not be freed.
// NULL is returned for no description.
static const char* doc_get_cap(ast_t* cap)
{
  if(cap == NULL)
    return NULL;

  switch(ast_id(cap))
  {
    case TK_ISO:
    case TK_TRN:
    case TK_REF:
    case TK_VAL:
    case TK_BOX:
    case TK_TAG:
      return ast_get_print(cap);

    case TK_BOX_GENERIC:
      return "box";

    case TK_TAG_GENERIC:
      return "tag";

    default:
      return NULL;
  }
}
示例#4
0
文件: docgen.c 项目: JamesLinus/ponyc
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");
}
示例#5
0
static void type_append(printbuf_t* buf, ast_t* type, bool first)
{
  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    {
      // u3_Arg1_Arg2_Arg3
      printbuf(buf, "u%d", ast_childcount(type));
      types_append(buf, type);
      return;
    }

    case TK_ISECTTYPE:
    {
      // i3_Arg1_Arg2_Arg3
      printbuf(buf, "i%d", ast_childcount(type));
      types_append(buf, type);
      return;
    }

    case TK_TUPLETYPE:
    {
      // t3_Arg1_Arg2_Arg3
      printbuf(buf, "t%d", ast_childcount(type));
      types_append(buf, type);
      return;
    }

    case TK_NOMINAL:
    {
      // pkg_Type[_Arg1_Arg2]_cap
      AST_GET_CHILDREN(type, package, name, typeargs, cap, eph);

      ast_t* def = (ast_t*)ast_data(type);
      ast_t* pkg = ast_nearest(def, TK_PACKAGE);
      const char* pkg_name = package_symbol(pkg);

      if(pkg_name != NULL)
        printbuf(buf, "%s_", pkg_name);

      printbuf(buf, "%s", ast_name(name));
      types_append(buf, typeargs);

      if(!first)
        printbuf(buf, "_%s", ast_get_print(cap));

      return;
    }

    default: {}
  }

  assert(0);
}
示例#6
0
文件: docgen.c 项目: JamesLinus/ponyc
// Report the human readable description for the given capability node.
// The returned string is valid forever and should not be freed.
// NULL is returned for no description.
static const char* doc_get_cap(ast_t* cap)
{
  if(cap == NULL)
    return NULL;

  switch(ast_id(cap))
  {
    case TK_ISO:
    case TK_TRN:
    case TK_REF:
    case TK_VAL:
    case TK_BOX:
    case TK_TAG:
    case TK_CAP_READ:
    case TK_CAP_SEND:
    case TK_CAP_SHARE:
      return ast_get_print(cap);

    default:
      return NULL;
  }
}
示例#7
0
文件: traits.c 项目: abingham/ponyc
// Check that all the methods in the given list are compatible with the given
// method
static bool methods_compatible(ast_t* list, ast_t* method, const char* name,
  ast_t* entity)
{
  assert(list != NULL);
  assert(method != NULL);
  assert(name != NULL);
  assert(entity != NULL);

  bool r = true;

  for(ast_t* p = ast_child(list); p != NULL; p = ast_sibling(p))
  {
    if(!is_subtype(method, p))
    {
      ast_error(method,
        "Clashing type for method %s provided by trait to %s %s",
        name, ast_get_print(entity), ast_name(ast_child(entity)));
      ast_error(p, "clashing method here");
      r = false;
    }
  }

  return r;
}
示例#8
0
文件: literal.c 项目: abingham/ponyc
// 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);
}
示例#9
0
文件: docgen.c 项目: shlomif/ponyc
// 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;
}
示例#10
0
文件: docgen.c 项目: shlomif/ponyc
// 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);
  }
}
示例#11
0
文件: traits.c 项目: abingham/ponyc
// Check resulting methods are compatible with the containing entity and patch
// up symbol tables
static bool post_process_methods(ast_t* entity, pass_opt_t* options,
  bool is_concrete)
{
  assert(entity != NULL);

  bool r = true;
  ast_t* members = ast_childidx(entity, 4);

  for(ast_t* m = ast_child(members); m != NULL; m = ast_sibling(m))
  {
    token_id variety = ast_id(m);

    // Check behaviour compatability
    if(variety == TK_BE)
    {
      switch(ast_id(entity))
      {
        case TK_PRIMITIVE:
          ast_error(entity,
            "primitives can't provide traits that have behaviours");
          r = false;
          break;

        case TK_CLASS:
          ast_error(entity, "classes can't have provide that have behaviours");
          r = false;
          break;

        default:
          break;
      }
    }

    if(variety == TK_BE || variety == TK_FUN || variety == TK_NEW)
    {
      // Check concrete method bodies
      if(ast_data(m) == BODY_AMBIGUOUS)
      {
        if(is_concrete)
        {
          ast_error(m, "multiple possible method bodies from traits");
          r = false;
        }
      }
      else if(ast_data(m) == NULL)
      {
        if(is_concrete)
        {
          assert(ast_id(ast_childidx(m, 6)) == TK_NONE);
          ast_error(m, "no body found for method %d %s %s", is_concrete,
            ast_get_print(entity), ast_name(ast_child(entity)));
          r = false;
        }
      }
      else
      {
        assert(ast_id(ast_childidx(m, 6)) != TK_NONE);

        if(ast_data(m) != entity)
        {
          // Sort out copied symbol tables
          ast_visit(&m, rescope, NULL, options);
        }
      }
    }
  }

  return r;
}
示例#12
0
文件: builder.c 项目: Potpourri/ponyc
static bool compare_asts(ast_t* prev, ast_t* expected, ast_t* actual,
  bool check_siblings)
{
  assert(prev != NULL);

  if(expected == NULL && actual == NULL)
    return true;

  if(actual == NULL)
  {
    ast_error(expected, "Expected AST %s not found", ast_get_print(expected));
    return false;
  }

  if(expected == NULL)
  {
    ast_error(prev, "Unexpected AST node found, %s", ast_get_print(actual));
    return false;
  }

  token_id expected_id = ast_id(expected);
  token_id actual_id = ast_id(actual);

  if(expected_id != actual_id)
  {
    ast_error(expected, "AST ID mismatch, got %d (%s), expected %d (%s)",
      ast_id(actual), ast_get_print(actual),
      ast_id(expected), ast_get_print(expected));
    return false;
  }

  if(ast_id(expected) == TK_ID && ast_name(actual)[0] == '$' &&
    strcmp(ast_name(expected), "hygid") == 0)
  {
    // Allow expected "hygid" to match any hygenic ID
  }
  else if(strcmp(ast_get_print(expected), ast_get_print(actual)) != 0)
  {
    ast_error(expected, "AST text mismatch, got %s, expected %s",
      ast_get_print(actual), ast_get_print(expected));
    return false;
  }

  if(ast_has_scope(expected) && !ast_has_scope(actual))
  {
    ast_error(expected, "AST missing scope");
    return false;
  }

  if(!ast_has_scope(expected) && ast_has_scope(actual))
  {
    ast_error(actual, "Unexpected AST scope");
    return false;
  }

  if(!compare_asts(expected, ast_child(expected), ast_child(actual), true) ||
    !compare_asts(expected, ast_type(expected), ast_type(actual), true))
    return false;

  return !check_siblings ||
    compare_asts(expected, ast_sibling(expected), ast_sibling(actual), true);
}
示例#13
0
文件: docgen.c 项目: JamesLinus/ponyc
// 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;
}
示例#14
0
文件: docgen.c 项目: JamesLinus/ponyc
// 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");
}
示例#15
0
文件: docgen.c 项目: Sendence/ponyc
// 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);
  }
}
示例#16
0
// Check the extra information. This includes:
// * legal data pointer
// * legal scope symbol table
// * no extra children
static check_res_t check_extras(ast_t* ast, check_state_t* state,
  errors_t* errors)
{
  assert(ast != NULL);
  assert(state != NULL);


  ast_t* type_field = ast_type(ast);

  if(type_field != NULL)
  {
    if(state->type == NULL)
    {
      error_preamble(ast);
      printf("unexpected type\n");
      ast_error(state->errors, ast, "Here");
      ast_print(ast);
#ifdef IMMEDIATE_FAIL
      assert(false);
#endif
      return CHK_ERROR;
    }

    check_res_t r = state->type(type_field, errors);

    if(r == CHK_ERROR)  // Propogate error
      return CHK_ERROR;

    if(r == CHK_NOT_FOUND)
    {
      error_preamble(ast);
      printf("type field has invalid id %d\n", ast_id(type_field));
      ast_error(state->errors, ast, "Here");
      ast_print(ast);
#ifdef IMMEDIATE_FAIL
      assert(false);
#endif
      return CHK_ERROR;
    }
  }

  if(state->child != NULL)
  {
    error_preamble(ast);
    printf("child " __zu " (id %d, %s) unexpected\n", state->child_index,
      ast_id(state->child), ast_get_print(state->child));
    ast_error(state->errors, ast, "Here");
    ast_print(ast);
#ifdef IMMEDIATE_FAIL
    assert(false);
#endif
    return CHK_ERROR;
  }

  if(ast_data(ast) != NULL && !state->has_data)
  {
    error_preamble(ast);
    printf("unexpected data %p\n", ast_data(ast));
    ast_error(state->errors, ast, "Here");
    ast_print(ast);
#ifdef IMMEDIATE_FAIL
    assert(false);
#endif
    return CHK_ERROR;
  }

  if(ast_has_scope(ast) && !state->is_scope)
  {
    error_preamble(ast);
    printf("unexpected scope\n");
    ast_error(state->errors, ast, "Here");
    ast_print(ast);
#ifdef IMMEDIATE_FAIL
    assert(false);
#endif
    return CHK_ERROR;
  }

  if(!ast_has_scope(ast) && state->is_scope)
  {
    error_preamble(ast);
    printf("expected scope not found\n");
    ast_error(state->errors, ast, "Here");
    ast_print(ast);
#ifdef IMMEDIATE_FAIL
    assert(false);
#endif
    return CHK_ERROR;
  }

  return CHK_OK;
}