Example #1
0
ast_t* type_builtin(pass_opt_t* opt, ast_t* from, const char* name)
{
  ast_t* ast = type_base(from, NULL, name);

  if(!names_nominal(opt, from, &ast, false))
  {
    ast_error(from, "unable to validate '%s'", name);
    ast_free(ast);
    return NULL;
  }

  return ast;
}
Example #2
0
ast_result_t pass_names(ast_t** astp, pass_opt_t* options)
{
  (void)options;
  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_NOMINAL:
      if(!names_nominal(options, ast, astp))
        return AST_ERROR;
      break;

    case TK_ARROW:
      if(!names_arrow(ast))
        return AST_ERROR;
      break;

    default: {}
  }

  return AST_OK;
}
Example #3
0
ast_t* type_pointer_to(pass_opt_t* opt, ast_t* to)
{
  BUILD(pointer, to,
    NODE(TK_NOMINAL,
      NONE // Package
      ID("Pointer")
      NODE(TK_TYPEARGS,
        TREE(to)
        )
      NONE // Capability
      NONE // Ephemeral
      ));

  if(!names_nominal(opt, to, &pointer, false))
  {
    ast_error(to, "unable to create Pointer[%s]", ast_print_type(to));
    ast_free(pointer);
    return NULL;
  }

  return pointer;
}
Example #4
0
bool expr_nominal(pass_opt_t* opt, ast_t** astp)
{
  // Resolve typealiases and typeparam references.
  if(!names_nominal(opt, *astp, astp))
    return false;

  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_TYPEPARAMREF:
      return flatten_typeparamref(ast) == AST_OK;

    case TK_NOMINAL:
      break;

    default:
      return true;
  }

  // If still nominal, check constraints.
  ast_t* def = (ast_t*)ast_data(ast);

  // Special case: don't check the constraint of a Pointer. This allows a
  // Pointer[Pointer[A]], which is normally not allowed, as a Pointer[A] is
  // not a subtype of Any.
  ast_t* id = ast_child(def);
  const char* name = ast_name(id);

  if(!strcmp(name, "Pointer"))
    return true;

  ast_t* typeparams = ast_childidx(def, 1);
  ast_t* typeargs = ast_childidx(ast, 2);

  return check_constraints(typeargs, typeparams, typeargs, true);
}
Example #5
0
bool expr_nominal(pass_opt_t* opt, ast_t** astp)
{
  // Resolve type aliases and typeparam references.
  if(!names_nominal(opt, *astp, astp, true))
    return false;

  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_TYPEPARAMREF:
      return flatten_typeparamref(ast) == AST_OK;

    case TK_NOMINAL:
      break;

    default:
      return true;
  }

  // If still nominal, check constraints.
  ast_t* def = (ast_t*)ast_data(ast);

  // Special case: don't check the constraint of a Pointer. This allows a
  // Pointer[Pointer[A]], which is normally not allowed, as a Pointer[A] is
  // not a subtype of Any.
  ast_t* id = ast_child(def);
  const char* name = ast_name(id);

  if(!strcmp(name, "Pointer"))
    return true;

  ast_t* typeparams = ast_childidx(def, 1);
  ast_t* typeargs = ast_childidx(ast, 2);

  if(!reify_defaults(typeparams, typeargs, true))
    return false;

  if(!strcmp(name, "MaybePointer"))
  {
    // MaybePointer[A] must be bound to a struct.
    assert(ast_childcount(typeargs) == 1);
    ast_t* typeparam = ast_child(typeparams);
    ast_t* typearg = ast_child(typeargs);
    bool ok = false;

    switch(ast_id(typearg))
    {
      case TK_NOMINAL:
      {
        ast_t* def = (ast_t*)ast_data(typearg);
        ok = ast_id(def) == TK_STRUCT;
        break;
      }

      case TK_TYPEPARAMREF:
      {
        ast_t* def = (ast_t*)ast_data(typearg);
        ok = def == typeparam;
        break;
      }

      default: {}
    }

    if(!ok)
    {
      ast_error(ast,
        "%s is not allowed: the type argument to MaybePointer must be a struct",
        ast_print_type(ast));

      return false;
    }
  }

  return check_constraints(typeargs, typeparams, typeargs, true);
}
Example #6
0
bool expr_nominal(pass_opt_t* opt, ast_t** astp)
{
  // Resolve type aliases and typeparam references.
  if(!names_nominal(opt, *astp, astp, true))
    return false;

  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_TYPEPARAMREF:
      return flatten_typeparamref(opt, ast) == AST_OK;

    case TK_NOMINAL:
      break;

    default:
      return true;
  }

  // If still nominal, check constraints.
  ast_t* def = (ast_t*)ast_data(ast);

  // Special case: don't check the constraint of a Pointer or an Array. These
  // builtin types have no contraint on their type parameter, and it is safe
  // to bind a struct as a type argument (which is not safe on any user defined
  // type, as that type might then be used for pattern matching).
  if(is_pointer(ast) || is_literal(ast, "Array"))
    return true;

  ast_t* typeparams = ast_childidx(def, 1);
  ast_t* typeargs = ast_childidx(ast, 2);

  if(!reify_defaults(typeparams, typeargs, true, opt))
    return false;

  if(is_maybe(ast))
  {
    // MaybePointer[A] must be bound to a struct.
    assert(ast_childcount(typeargs) == 1);
    ast_t* typeparam = ast_child(typeparams);
    ast_t* typearg = ast_child(typeargs);
    bool ok = false;

    switch(ast_id(typearg))
    {
      case TK_NOMINAL:
      {
        ast_t* def = (ast_t*)ast_data(typearg);
        ok = ast_id(def) == TK_STRUCT;
        break;
      }

      case TK_TYPEPARAMREF:
      {
        ast_t* def = (ast_t*)ast_data(typearg);
        ok = def == typeparam;
        break;
      }

      default: {}
    }

    if(!ok)
    {
      ast_error(opt->check.errors, ast,
        "%s is not allowed: "
        "the type argument to MaybePointer must be a struct",
        ast_print_type(ast));

      return false;
    }

    return true;
  }

  return check_constraints(typeargs, typeparams, typeargs, true, opt);
}