예제 #1
0
파일: traits.c 프로젝트: awaidmann/ponyc
// Check that embed fields are not recursive.
static bool embed_fields(ast_t* entity, pass_opt_t* opt)
{
  assert(entity != NULL);

  int state = ast_checkflag(entity,
    AST_FLAG_RECURSE_2 | AST_FLAG_DONE_2 | AST_FLAG_ERROR_2);

  // Check for recursive embeds
  switch(state)
  {
    case 0:
      ast_setflag(entity, AST_FLAG_RECURSE_2);
      break;

    case AST_FLAG_RECURSE_2:
      ast_error(opt->check.errors, entity,
        "embedded fields can't be recursive");
      ast_clearflag(entity, AST_FLAG_RECURSE_2);
      ast_setflag(entity, AST_FLAG_ERROR_2);
      return false;

    case AST_FLAG_DONE_2:
      return true;

    case AST_FLAG_ERROR_2:
      return false;

    default:
      assert(0);
      return false;
  }

  AST_GET_CHILDREN(entity, id, typeparams, cap, provides, members);
  ast_t* member = ast_child(members);

  while(member != NULL)
  {
    if(ast_id(member) == TK_EMBED)
    {
      AST_GET_CHILDREN(member, f_id, f_type);
      ast_t* def = (ast_t*)ast_data(f_type);
      assert(def != NULL);

      if(!embed_fields(def, opt))
        return false;
    }

    member = ast_sibling(member);
  }

  ast_clearflag(entity, AST_FLAG_RECURSE_2);
  ast_setflag(entity, AST_FLAG_DONE_2);
  return true;
}
예제 #2
0
파일: traits.c 프로젝트: lzpfmh/ponyc
ast_result_t pass_traits(ast_t** astp, pass_opt_t* options)
{
  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_STRUCT:
    case TK_CLASS:
    case TK_ACTOR:
      if(!trait_entity(ast, options))
        return AST_ERROR;

      if(!embed_fields(ast, options))
        return AST_ERROR;
      break;

    case TK_PRIMITIVE:
      if(!trait_entity(ast, options))
        return AST_ERROR;

      if(!add_comparable(ast, options))
        return AST_FATAL;
      break;

    case TK_INTERFACE:
    case TK_TRAIT:
      if(!trait_entity(ast, options))
        return AST_ERROR;
      break;

    case TK_LET:
    case TK_VAR:
      local_types(ast);
      break;

    default:
      break;
  }

  return AST_OK;
}