Beispiel #1
0
builder_t* builder_create(const char* description)
{
  if(description == NULL)
    return NULL;

  source_t* source = source_open_string(description);
  symtab_t* symtab = symtab_new();

  ast_t* ast = build_ast(source, symtab);

  if(ast == NULL)
  {
    // Error, tidy up
    source_close(source);
    symtab_free(symtab);
    return NULL;
  }

  // Success, create builder
  builder_t* builder = POOL_ALLOC(builder_t);

  builder->sources = NULL;
  builder->defs = symtab;
  builder->dummy_root = ast_blank(TK_TEST);

  ast_add(builder->dummy_root, ast);
  add_source(builder, source);

  return builder;
}
Beispiel #2
0
ast_t* program_load(const char* path, pass_opt_t* options)
{
  ast_t* program = ast_blank(TK_PROGRAM);
  ast_scope(program);

  options->program_pass = PASS_PARSE;

  // Always load builtin package first, then the specified one.
  if(package_load(program, stringtab("builtin"), options) == NULL ||
    package_load(program, path, options) == NULL)
  {
    ast_free(program);
    return NULL;
  }

  // Reorder packages so specified package is first.
  ast_t* builtin = ast_pop(program);
  ast_append(program, builtin);

  if(!ast_passes_program(program, options))
  {
    ast_free(program);
    return NULL;
  }

  return program;
}
Beispiel #3
0
ast_t* reify_method_def(ast_t* ast, ast_t* typeparams, ast_t* typeargs,
  pass_opt_t* opt)
{
  (void)opt;
  switch(ast_id(ast))
  {
    case TK_FUN:
    case TK_BE:
    case TK_NEW:
      break;

    default:
      pony_assert(false);
  }

  // Remove the body AST to avoid duplicating it.
  ast_t* body = ast_childidx(ast, 6);
  ast_t* temp_body = ast_blank(TK_NONE);
  ast_swap(body, temp_body);

  ast_t* r_ast = reify(ast, typeparams, typeargs, opt, true);

  ast_swap(temp_body, body);
  ast_free_unattached(temp_body);

  return r_ast;
}
Beispiel #4
0
// Create a package AST, set up its state and add it to the given program
ast_t* create_package(ast_t* program, const char* name,
  const char* qualified_name, pass_opt_t* opt)
{
  ast_t* package = ast_blank(TK_PACKAGE);
  uint32_t pkg_id = program_assign_pkg_id(program);

  package_t* pkg = POOL_ALLOC(package_t);
  pkg->path = name;
  pkg->qualified_name = qualified_name;
  pkg->id = id_to_string(NULL, pkg_id);

  const char* p = strrchr(pkg->path, PATH_SLASH);

  if(p == NULL)
    p = pkg->path;
  else
    p = p + 1;

  pkg->filename = stringtab(p);

  if(pkg_id > 1)
    pkg->symbol = create_package_symbol(program, pkg->filename);
  else
    pkg->symbol = NULL;

  pkg->ast = package;
  package_set_init(&pkg->dependencies, 1);
  pkg->group = NULL;
  pkg->group_index = -1;
  pkg->next_hygienic_id = 0;
  pkg->low_index = -1;
  ast_setdata(package, pkg);

  ast_scope(package);
  ast_append(program, package);
  ast_set(program, pkg->path, package, SYM_NONE, false);
  ast_set(program, pkg->id, package, SYM_NONE, false);

  strlist_t* safe = opt->safe_packages;

  if((safe != NULL) && (strlist_find(safe, pkg->path) == NULL))
    pkg->allow_ffi = false;
  else
    pkg->allow_ffi = true;

  pkg->on_stack = false;

  return package;
}
Beispiel #5
0
ast_t* program_load(const char* path, pass_opt_t* options)
{
  ast_t* program = ast_blank(TK_PROGRAM);
  ast_scope(program);

  options->type_catchup_pass = PASS_PARSE;

  if(package_load(program, path, options) == NULL ||
    !ast_passes_program(program, options))
  {
    ast_free(program);
    return NULL;
  }

  return program;
}
Beispiel #6
0
// Add the given method to the relevant name list in the given symbol table
static bool add_method_to_list(ast_t* method, methods_t* method_info,
  const char *entity_name)
{
  assert(method != NULL);
  assert(method_info != NULL);
  assert(entity_name != NULL);

  const char* name = ast_name(ast_childidx(method, 1));
  assert(name != NULL);

  symtab_t* symtab = method_info->symtab;
  assert(symtab != NULL);

  // Entity doesn't yet have method, add it to our list for later
  ast_t* list = (ast_t*)symtab_find(symtab, name, NULL);

  if(list == NULL)
  {
    ast_t* case_clash = (ast_t*)symtab_find_case(symtab, name, NULL);

    if(case_clash != NULL)
    {
      ast_error(case_clash, "in %s method name differs only in case",
        entity_name);
      ast_error(method, "previous definition is here");
      return false;
    }

    // First instance of this name
    list = ast_blank(TK_ID);
    ast_set_name(list, name);
    symtab_add(symtab, name, (void*)list, SYM_NONE);

    if(method_info->last_list == NULL)
      ast_add(method_info->name_lists, list);
    else
      ast_add_sibling(method_info->last_list, list);

    method_info->last_list = list;
  }

  ast_add(list, method);
  return true;
}
Beispiel #7
0
ast_t* program_load(const char* path, pass_opt_t* options)
{
  ast_t* program = ast_blank(TK_PROGRAM);
  ast_scope(program);

  if(package_load(program, path, options) == NULL)
  {
    ast_free(program);
    return NULL;
  }

  if(!program_passes(program, options))
  {
    ast_free(program);
    return NULL;
  }

  return program;
}
Beispiel #8
0
// Create a package AST, set up its state and add it to the given program
static ast_t* create_package(ast_t* program, const char* name)
{
  ast_t* package = ast_blank(TK_PACKAGE);
  uint32_t pkg_id = program_assign_pkg_id(program);

  package_t* pkg = POOL_ALLOC(package_t);
  pkg->path = name;
  pkg->id = id_to_string(NULL, pkg_id);

  const char* p = strrchr(pkg->path, PATH_SLASH);

  if(p == NULL)
    p = pkg->path;
  else
    p = p + 1;

  pkg->filename = stringtab(p);

  if(pkg_id > 1)
    pkg->symbol = create_package_symbol(program, pkg->filename);
  else
    pkg->symbol = NULL;

  pkg->next_hygienic_id = 0;
  ast_setdata(package, pkg);

  ast_scope(package);
  ast_append(program, package);
  ast_set(program, pkg->path, package, SYM_NONE);
  ast_set(program, pkg->id, package, SYM_NONE);

  if((safe != NULL) && (strlist_find(safe, pkg->path) == NULL))
    pkg->allow_ffi = false;
  else
    pkg->allow_ffi = true;

  return package;
}
Beispiel #9
0
// Add methods from provided traits into the given entity
static bool build_entity_def(ast_t* entity)
{
  assert(entity != NULL);

  ast_state_t state = (ast_state_t)(uint64_t)ast_data(entity);

  // Check for recursive definitions
  switch(state)
  {
    case AST_STATE_INITIAL:
      ast_setdata(entity, (void*)AST_STATE_INPROGRESS);
      break;

    case AST_STATE_INPROGRESS:
      ast_error(entity, "traits can't be recursive");
      return false;

    case AST_STATE_DONE:
      return true;

    default:
      assert(0);
      return false;
  }

  symtab_t* symtab = symtab_new();
  ast_t* name_lists = ast_blank(TK_MEMBERS);
  methods_t method_info = { symtab, name_lists, NULL };

  bool r = process_provides(entity, &method_info);

  symtab_free(symtab);
  ast_free(name_lists);

  ast_setdata(entity, (void*)AST_STATE_DONE);
  return r;
}