Exemplo n.º 1
0
Arquivo: genexe.c Projeto: volth/ponyc
bool genexe(compile_t* c, ast_t* program)
{
  // The first package is the main package. It has to have a Main actor.
  const char* main_actor = stringtab("Main");
  const char* env_class = stringtab("Env");

  ast_t* package = ast_child(program);
  ast_t* main_def = ast_get(package, main_actor, NULL);

  if(main_def == NULL)
  {
    errorf(NULL, "no Main actor found in package '%s'", c->filename);
    return false;
  }

  // Generate the Main actor and the Env class.
  ast_t* main_ast = type_builtin(c->opt, main_def, main_actor);
  ast_t* env_ast = type_builtin(c->opt, main_def, env_class);

  genprim_reachable_init(c, program);
  reach(c->reachable, main_ast, stringtab("create"), NULL);
  reach(c->reachable, env_ast, stringtab("_create"), NULL);
  paint(c->reachable);

  gentype_t main_g;
  gentype_t env_g;

  bool ok = gentype(c, main_ast, &main_g) && gentype(c, env_ast, &env_g);

  if(ok)
    gen_main(c, &main_g, &env_g);

  ast_free_unattached(main_ast);
  ast_free_unattached(env_ast);

  if(!ok)
    return false;

  if(!genopt(c))
    return false;

  const char* file_o = genobj(c);

  if(file_o == NULL)
    return false;

  if(c->opt->limit < PASS_ALL)
    return true;

  if(!link_exe(c, program, file_o))
    return false;

#ifdef PLATFORM_IS_WINDOWS
  _unlink(file_o);
#else
  unlink(file_o);
#endif

  return true;
}
Exemplo n.º 2
0
static errormsg_t* make_errorfv(const char* file, const char* fmt, va_list ap)
{
  char buf[LINE_LEN];
  vsnprintf(buf, LINE_LEN, fmt, ap);

  errormsg_t* e = error_alloc();

  e->file = stringtab(file);
  e->msg = stringtab(buf);
  return e;
}
Exemplo n.º 3
0
Arquivo: error.c Projeto: mgist/ponyc
void errorfv(const char* file, const char* fmt, va_list ap)
{
  char buf[LINE_LEN];
  vsnprintf(buf, LINE_LEN, fmt, ap);

  errormsg_t* e = POOL_ALLOC(errormsg_t);
  memset(e, 0, sizeof(errormsg_t));

  e->file = stringtab(file);
  e->msg = stringtab(buf);
  add_error(e);
}
Exemplo n.º 4
0
// Replace all the strings in the _os_flags and _size_flags arrays with
// stringtab'ed versions the first time this is called.
// This method of initialisatino is obviously not at all concurrency safe, but
// in works with unit tests trivially.
static void stringtab_mutexgroups()
{
  if(_stringtabed)
    return;

  for(size_t i = 0; _os_flags[i] != NULL; i++)
    _os_flags[i] = stringtab(_os_flags[i]);

  for(size_t i = 0; _size_flags[i] != NULL; i++)
    _size_flags[i] = stringtab(_size_flags[i]);

  _stringtabed = true;
}
Exemplo n.º 5
0
Arquivo: use.c Projeto: Sendence/ponyc
// Find the index of the handler for the given URI
static int find_handler(pass_opt_t* opt, ast_t* uri, const char** out_locator)
{
  assert(uri != NULL);
  assert(out_locator != NULL);
  assert(ast_id(uri) == TK_STRING);

  const char* text = ast_name(uri);
  const char* colon = strchr(text, ':');

  if(colon == NULL)
  {
    // No scheme specified, use default
    *out_locator = stringtab(text);
    return 0;
  }

  size_t scheme_len = colon - text + 1;  // +1 for colon

  // Search for matching handler
  for(int i = 0; handlers[i].scheme != NULL; i++)
  {
    if(handlers[i].scheme_len == scheme_len &&
      strncmp(handlers[i].scheme, text, scheme_len) == 0)
    {
      if(handlers[i].handler == NULL) // No handler provided (probably test:)
        break;

      // Matching scheme found
      *out_locator = stringtab(colon + 1);
      return i;
    }
  }

  // No match found
#ifdef PLATFORM_IS_WINDOWS
  if(colon == text + 1)
  {
    // Special case error message
    ast_error(opt->check.errors, uri, "Use scheme %c: not found. "
      "If this is an absolute path use prefix \"package:\"", text[0]);
    return -1;
  }
#endif

  ast_error(opt->check.errors, uri, "Use scheme %.*s not found",
    (int)scheme_len, text);
  return -1;
}
Exemplo n.º 6
0
const char* package_alias_from_id(ast_t* module, const char* id)
{
  pony_assert(ast_id(module) == TK_MODULE);

  const char* strtab_id = stringtab(id);

  ast_t* use = ast_child(module);
  while(ast_id(use) == TK_USE)
  {
    ast_t* imported = (ast_t*)ast_data(use);
    pony_assert((imported != NULL) && (ast_id(imported) == TK_PACKAGE));

    package_t* pkg = (package_t*)ast_data(imported);
    pony_assert(pkg != NULL);

    if(pkg->id == strtab_id)
    {
      ast_t* alias = ast_child(use);
      if(ast_id(alias) == TK_NONE)
        return NULL;

      return ast_name(alias);
    }

    use = ast_sibling(use);
  }

  pony_assert(false);
  return NULL;
}
Exemplo n.º 7
0
bool has_member(ast_t* members, const char* name)
{
  name = stringtab(name);
  ast_t* member = ast_child(members);

  while(member != NULL)
  {
    ast_t* id;

    switch(ast_id(member))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
        id = ast_child(member);
        break;

      default:
        id = ast_childidx(member, 1);
        break;
    }

    if(ast_name(id) == name)
      return true;

    member = ast_sibling(member);
  }

  return false;
}
Exemplo n.º 8
0
// Make a token with the specified ID and current token text
static token_t* make_token_with_text(lexer_t* lexer, token_id id)
{
  token_t* t = make_token(lexer, id);
  append_to_token(lexer, '\0');
  token_set_string(t, stringtab(lexer->buffer));
  return t;
}
Exemplo n.º 9
0
// Check whether the directory specified by catting the given base and path
// exists
// @return The resulting directory path, which should not be deleted and is
// valid indefinitely. NULL is directory cannot be found.
static const char* try_path(const char* base, const char* path,
  bool* out_found_notdir)
{
  char composite[FILENAME_MAX];
  char file[FILENAME_MAX];

  path_cat(base, path, composite);

  if(pony_realpath(composite, file) != file)
    return NULL;

  struct stat s;
  int err = stat(file, &s);

  if(err == -1)
    return NULL;

  if(!S_ISDIR(s.st_mode))
  {
    if(out_found_notdir != NULL)
      *out_found_notdir = true;

    return NULL;
  }

  return stringtab(file);
}
Exemplo n.º 10
0
void token_set_string(token_t* token, const char* value)
{
  assert(token != NULL);
  assert(token->id == TK_STRING || token->id == TK_ID);
  assert(value != NULL);
  token->string = stringtab(value);
}
Exemplo n.º 11
0
// Check that the given path exists and add it to our package search paths
static bool add_path(const char* path)
{
#ifdef PLATFORM_IS_WINDOWS
  // The Windows implementation of stat() cannot cope with trailing a \ on a
  // directory name, so we remove it here if present. It is not safe to modify
  // the given path since it may come direct from getenv(), so we copy.
  char buf[FILENAME_MAX];
  strcpy(buf, path);
  size_t len = strlen(path);

  if(path[len - 1] == '\\')
  {
    buf[len - 1] = '\0';
    path = buf;
  }
#endif

  struct stat s;
  int err = stat(path, &s);

  if((err != -1) && S_ISDIR(s.st_mode))
  {
    path = stringtab(path);

    if(strlist_find(search, path) == NULL)
      search = strlist_append(search, path);
  }

  return true;
}
Exemplo n.º 12
0
ast_t* builder_find_sub_tree(builder_t* builder, const char* name)
{
  if(builder == NULL || name == NULL)
    return NULL;

  return (ast_t*)symtab_find(builder->defs, stringtab(name), NULL);
}
Exemplo n.º 13
0
void gendesc_init(compile_t* c, gentype_t* g)
{
  // Initialise the global descriptor.
  uint32_t size = (uint32_t)LLVMABISizeOfType(c->target_data, g->structure);

  // Generate a separate type ID for every type.
  LLVMValueRef args[DESC_LENGTH];

  args[DESC_ID] = make_type_id(c, g->type_name);
  args[DESC_SIZE] = LLVMConstInt(c->i32, size, false);
  args[DESC_TRAIT_COUNT] = make_trait_count(c, g);
  args[DESC_FIELD_COUNT] = make_field_count(c, g);
  args[DESC_TRACE] = make_function_ptr(c, genname_trace(g->type_name),
    c->trace_fn);
  args[DESC_SERIALISE] = make_function_ptr(c, genname_serialise(g->type_name),
    c->trace_fn);
  args[DESC_DESERIALISE] = make_function_ptr(c,
    genname_deserialise(g->type_name), c->trace_fn);
  args[DESC_DISPATCH] = make_function_ptr(c, genname_dispatch(g->type_name),
    c->dispatch_fn);
  args[DESC_FINALISE] = make_function_ptr(c, genname_finalise(g->type_name),
    c->final_fn);
  args[DESC_EVENT_NOTIFY] = LLVMConstInt(c->i32,
    genfun_vtable_index(c, g, stringtab("_event_notify"), NULL), false);
  args[DESC_TRAITS] = make_trait_list(c, g);
  args[DESC_FIELDS] = make_field_list(c, g);
  args[DESC_VTABLE] = make_vtable(c, g);

  LLVMValueRef desc = LLVMConstNamedStruct(g->desc_type, args, DESC_LENGTH);
  LLVMSetInitializer(g->desc, desc);
  LLVMSetGlobalConstant(g->desc, true);
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
LLVMValueRef gen_pattern_eq(compile_t* c, ast_t* pattern, LLVMValueRef r_value)
{
  // This is used for structural equality in pattern matching.
  ast_t* pattern_type = ast_type(pattern);
  AST_GET_CHILDREN(pattern_type, package, id);

  // Special case equality on primitive types.
  if(ast_name(package) == c->str_builtin)
  {
    const char* name = ast_name(id);

    if((name == c->str_Bool) ||
      (name == c->str_I8) ||
      (name == c->str_I16) ||
      (name == c->str_I32) ||
      (name == c->str_I64) ||
      (name == c->str_I128) ||
      (name == c->str_ILong) ||
      (name == c->str_ISize) ||
      (name == c->str_U8) ||
      (name == c->str_U16) ||
      (name == c->str_U32) ||
      (name == c->str_U64) ||
      (name == c->str_U128) ||
      (name == c->str_ULong) ||
      (name == c->str_USize) ||
      (name == c->str_F32) ||
      (name == c->str_F64)
      )
    {
      return gen_eq_rvalue(c, pattern, r_value);
    }
  }

  // Generate the receiver.
  LLVMValueRef l_value = gen_expr(c, pattern);

  gentype_t g;

  if(!gentype(c, pattern_type, &g))
    return NULL;

  // Static or virtual dispatch.
  LLVMValueRef func = dispatch_function(c, pattern, &g, l_value,
    stringtab("eq"), NULL);

  if(func == NULL)
    return NULL;

  // Call the function. We know it isn't partial.
  LLVMValueRef args[2];
  args[0] = l_value;
  args[1] = r_value;

  // Emit debug location for calls to test for structural equality
  dwarf_location(&c->dwarf, pattern);

  return codegen_call(c, func, args, 2);
}
Exemplo n.º 16
0
void package_add_magic(const char* path, const char* src)
{
  magic_package_t* n = POOL_ALLOC(magic_package_t);
  n->path = stringtab(path);
  n->src = src;
  n->next = magic_packages;
  magic_packages = n;
}
Exemplo n.º 17
0
Arquivo: error.c Projeto: mgist/ponyc
void errorv(source_t* source, size_t line, size_t pos, const char* fmt,
  va_list ap)
{
  char buf[LINE_LEN];
  vsnprintf(buf, LINE_LEN, fmt, ap);

  errormsg_t* e = POOL_ALLOC(errormsg_t);
  memset(e, 0, sizeof(errormsg_t));

  if(source != NULL)
    e->file = source->file;

  e->line = line;
  e->pos = pos;
  e->msg = stringtab(buf);

  if((source != NULL) && (line != 0))
  {
    size_t tline = 1;
    size_t tpos = 0;

    while((tline < e->line) && (tpos < source->len))
    {
      if(source->m[tpos] == '\n')
        tline++;

      tpos++;
    }

    size_t start = tpos;

    while((source->m[tpos] != '\n') && (tpos < source->len))
      tpos++;

    size_t len = tpos - start;

    if(len >= sizeof(buf))
      len = sizeof(buf) - 1;

    memcpy(buf, &source->m[start], len);
    buf[len] = '\0';
    e->source = stringtab(buf);
  }

  add_error(e);
}
Exemplo n.º 18
0
static const char* symbol_suffix(const char* symbol, size_t suffix)
{
  size_t len = strlen(symbol);
  VLA(char, buf, len + 32);
  snprintf(buf, len + 32, "%s" __zu, symbol, suffix);

  return stringtab(buf);
}
Exemplo n.º 19
0
bool expr_consume(pass_opt_t* opt, ast_t* ast)
{
  AST_GET_CHILDREN(ast, cap, term);
  ast_t* type = ast_type(term);

  if(is_typecheck_error(type))
    return false;

  const char* name = NULL;

  switch(ast_id(term))
  {
    case TK_VARREF:
    case TK_LETREF:
    case TK_PARAMREF:
    {
      ast_t* id = ast_child(term);
      name = ast_name(id);
      break;
    }

    case TK_THIS:
    {
      name = stringtab("this");
      break;
    }

    default:
      ast_error(opt->check.errors, ast,
        "consume must take 'this', a local, or a parameter");
      return false;
  }

  // Can't consume from an outer scope while in a loop condition.
  if((opt->check.frame->loop_cond != NULL) &&
    !ast_within_scope(opt->check.frame->loop_cond, ast, name))
  {
    ast_error(opt->check.errors, ast,
      "can't consume from an outer scope in a loop condition");
    return false;
  }

  ast_setstatus(ast, name, SYM_CONSUMED);

  token_id tcap = ast_id(cap);
  ast_t* c_type = consume_type(type, tcap);

  if(c_type == NULL)
  {
    ast_error(opt->check.errors, ast, "can't consume to this capability");
    ast_error_continue(opt->check.errors, term, "expression type is %s",
      ast_print_type(type));
    return false;
  }

  ast_settype(ast, c_type);
  return true;
}
Exemplo n.º 20
0
void package_add_magic_src(const char* path, const char* src, pass_opt_t* opt)
{
  magic_package_t* n = POOL_ALLOC(magic_package_t);
  n->path = stringtab(path);
  n->src = src;
  n->mapped_path = NULL;
  n->next = opt->magic_packages;
  opt->magic_packages = n;
}
Exemplo n.º 21
0
uint32_t reach_vtable_index(reachable_type_t* t, const char* name)
{
  reachable_method_t* m = reach_method(t, stringtab(name), NULL);

  if(m == NULL)
    return (uint32_t)-1;

  return m->vtable_index;
}
Exemplo n.º 22
0
static void genfun_dwarf(compile_t* c, gentype_t* g, const char *name,
  ast_t* typeargs, ast_t* fun)
{
  if(!codegen_hassource(c))
    return;

  // Get the function.
  const char* funname = genname_fun(g->type_name, name, typeargs);
  LLVMValueRef func = LLVMGetNamedFunction(c->module, funname);
  assert(func != NULL);

  // Count the parameters, including the receiver.
  ast_t* params = ast_childidx(fun, 3);
  size_t count = ast_childcount(params) + 1;

  size_t buf_size = (count + 1) * sizeof(const char*);
  const char** pnames = (const char**)pool_alloc_size(buf_size);
  count = 0;

  // Return value type name and receiver type name.
  pnames[count++] = genname_type(ast_childidx(fun, 4));
  pnames[count++] = g->type_name;

  // Get a type name for each parameter.
  ast_t* param = ast_child(params);

  while(param != NULL)
  {
    ast_t* ptype = ast_childidx(param, 1);
    pnames[count++] = genname_type(ptype);
    param = ast_sibling(param);
  }

  // Dwarf the method type
  dwarf_method(&c->dwarf, fun, name, funname, pnames, count, func);

  // Dwarf the receiver pointer.
  LLVMBasicBlockRef entry = LLVMGetEntryBasicBlock(codegen_fun(c));
  LLVMValueRef argument = codegen_getlocal(c, stringtab("this"));

  dwarf_this(&c->dwarf, fun, g->type_name, entry, argument);

  // Dwarf locals for parameters
  param = ast_child(params);
  size_t index = 1;

  while(param != NULL)
  {
    argument = codegen_getlocal(c, ast_name(ast_child(param)));
    dwarf_parameter(&c->dwarf, param, pnames[index + 1], entry, argument,
      index);
    param = ast_sibling(param);
    index++;
  }

  pool_free_size(buf_size, pnames);
}
Exemplo n.º 23
0
Arquivo: dwarf.c Projeto: ozra/ponyc
void dwarf_this(dwarf_t* dwarf, ast_t* fun, const char* type,
  LLVMBasicBlockRef entry, LLVMValueRef storage)
{
  dwarf_meta_t meta;
  meta_local(&meta, fun, stringtab("this"), type, entry, storage, 0, true);
  meta.flags |= DWARF_ARTIFICIAL;

  symbols_local(dwarf->symbols, &meta, true);
}
Exemplo n.º 24
0
// Check whether the given entity has illegal parts
static ast_result_t syntax_entity(ast_t* ast, int entity_def_index)
{
  assert(ast != NULL);
  assert(entity_def_index >= 0 && entity_def_index < DEF_ENTITY_COUNT);
  ast_result_t r = AST_OK;

  const permission_def_t* def = &_entity_def[entity_def_index];
  AST_GET_CHILDREN(ast, id, typeparams, defcap, provides, members, c_api);

  // Check if we're called Main
  if(def->permissions[ENTITY_MAIN] == 'N' && ast_name(id) == stringtab("Main"))
  {
    ast_error(ast, "Main must be an actor");
    r = AST_ERROR;
  }

  if(!check_id_type(id, def->desc))
    r = AST_ERROR;

  if(!check_permission(def, ENTITY_CAP, defcap, "default capability", defcap))
    r = AST_ERROR;

  if(!check_permission(def, ENTITY_C_API, c_api, "C api", c_api))
    r = AST_ERROR;

  if(ast_id(c_api) == TK_AT)
  {
    if(ast_id(typeparams) != TK_NONE)
    {
      ast_error(typeparams, "generic actor cannot specify C api");
      r = AST_ERROR;
    }
  }

  if(entity_def_index != DEF_TYPEALIAS)
  {
    // Check referenced traits
    if(ast_id(provides) != TK_NONE &&
      !check_provides_type(provides, "provides"))
      r = AST_ERROR;
  }
  else
  {
    // Check for a type alias
    if(ast_id(provides) == TK_NONE)
    {
      ast_error(provides, "a type alias must specify a type");
      r = AST_ERROR;
    }
  }

  // Check for illegal members
  if(!check_members(members, entity_def_index))
    r = AST_ERROR;

  return r;
}
Exemplo n.º 25
0
static bool add_safe(const char* path)
{
  path = stringtab(path);

  if(strlist_find(safe, path) == NULL)
    safe = strlist_append(safe, path);

  return true;
}
Exemplo n.º 26
0
static bool add_safe(const char* path, pass_opt_t* opt)
{
  path = stringtab(path);
  strlist_t* safe = opt->safe_packages;

  if(strlist_find(safe, path) == NULL)
    opt->safe_packages = strlist_append(safe, path);

  return true;
}
Exemplo n.º 27
0
static ast_t* eq_param_type(ast_t* pattern)
{
  ast_t* pattern_type = ast_type(pattern);
  ast_t* fun = lookup(NULL, pattern, pattern_type, stringtab("eq"));

  AST_GET_CHILDREN(fun, cap, id, typeparams, params, result, partial);
  ast_t* param = ast_child(params);

  return ast_childidx(param, 1);
}
Exemplo n.º 28
0
const char* ast_print_type(ast_t* type)
{
  printbuf_t* buffer = printbuf_new();
  print_type(buffer, type);

  const char* s = stringtab(buffer->m);
  printbuf_free(buffer);

  return s;
}
Exemplo n.º 29
0
Arquivo: dwarf.c Projeto: ozra/ponyc
void dwarf_init(dwarf_t* dwarf, pass_opt_t* opt, LLVMBuilderRef builder,
  LLVMTargetDataRef layout, LLVMModuleRef module)
{
  dwarf->opt = opt;
  dwarf->target_data = layout;
  dwarf->has_source = false;

  symbols_init(&dwarf->symbols, builder, module, opt->release);
  symbols_unspecified(dwarf->symbols, stringtab("$object"));
}
Exemplo n.º 30
0
static const char* make_full_name(reach_type_t* t, reach_method_t* m)
{
  // Generate the full mangled name.
  // pkg_Type[_Arg1_Arg2]_cap_name[_Arg1_Arg2]_args_result
  printbuf_t* buf = printbuf_new();
  printbuf(buf, "%s_%s", t->name, m->mangled_name);
  const char* name = stringtab(buf->m);
  printbuf_free(buf);
  return name;
}