Beispiel #1
0
bool flatten_arrows(ast_t** astp, bool errors)
{
  ast_t* ast = *astp;
  ast_t* node_type = ast_type(ast);

  if(node_type != NULL)
  {
    if(!flatten_arrows(&node_type, errors))
      return false;
  }

  if(ast_id(ast) == TK_ARROW)
  {
    AST_GET_CHILDREN(ast, left, right);
    ast_t* flat;

    if(!flatten_arrows(&right, errors))
      return false;

    if((ast_id(left) == TK_BOXTYPE) && (ast_id(right) != TK_ARROW))
      flat = viewpoint_cap(TK_BOX, TK_NONE, right);
    else
      flat = viewpoint_type(left, right);

    if(flat == NULL)
    {
      if(errors)
        ast_error(ast, "can't flatten arrow type");

      return false;
    }

    ast_replace(astp, flat);
    return true;
  }

  ast_t* child = ast_child(ast);

  while(child != NULL)
  {
    if(!flatten_arrows(&child, errors))
      return false;

    child = ast_sibling(child);
  }

  return true;
}
Beispiel #2
0
static ast_t* lookup_nominal(typecheck_t* t, ast_t* from, ast_t* orig,
  ast_t* type, const char* name, bool errors)
{
  assert(ast_id(type) == TK_NOMINAL);
  ast_t* def = (ast_t*)ast_data(type);
  ast_t* type_name = ast_child(def);
  ast_t* find = ast_get(def, name, NULL);

  if(find != NULL)
  {
    switch(ast_id(find))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_NEW:
      case TK_BE:
      case TK_FUN:
        break;

      default:
        find = NULL;
    }
  }

  if(find == NULL)
  {
    if(errors)
      ast_error(from, "couldn't find '%s' in '%s'", name, ast_name(type_name));

    return NULL;
  }

  if((name[0] == '_') && (from != NULL) && (t != NULL))
  {
    switch(ast_id(find))
    {
      case TK_FVAR:
      case TK_FLET:
        if(t->frame->type != def)
        {
          if(errors)
          {
            ast_error(from,
              "can't lookup private fields from outside the type");
          }

          return NULL;
        }
        break;

      case TK_NEW:
      case TK_BE:
      case TK_FUN:
      {
        if(ast_nearest(def, TK_PACKAGE) != t->frame->package)
        {
          if(errors)
          {
            ast_error(from,
              "can't lookup private methods from outside the package");
          }

          return NULL;
        }
        break;
      }

      default:
        assert(0);
        return NULL;
    }

    if(!strcmp(name, "_final"))
    {
      switch(ast_id(find))
      {
        case TK_NEW:
        case TK_BE:
        case TK_FUN:
          if(errors)
            ast_error(from, "can't lookup a _final function");

          return NULL;

        default: {}
      }
    }
  }

  ast_t* typeparams = ast_sibling(type_name);
  ast_t* typeargs = ast_childidx(type, 2);

  find = ast_dup(find);
  orig = ast_dup(orig);
  replace_thistype(&find, orig);
  ast_free_unattached(orig);

  ast_t* r_find = reify(from, find, typeparams, typeargs);

  if(r_find != find)
  {
    ast_free_unattached(find);
    find = r_find;
  }

  if((find != NULL) && !flatten_arrows(&find, errors))
  {
    if(errors)
      ast_error(from, "can't look this up on a tag");

    ast_free_unattached(find);
    return NULL;
  }

  return find;
}