Exemple #1
0
static bool special_case_call(compile_t* c, ast_t* ast, LLVMValueRef* value)
{
  AST_GET_CHILDREN(ast, positional, named, postfix);

  if((ast_id(postfix) != TK_FUNREF) || (ast_id(named) != TK_NONE))
    return false;

  AST_GET_CHILDREN(postfix, receiver, method);
  ast_t* receiver_type = ast_type(receiver);

  if(ast_id(receiver_type) != TK_NOMINAL)
    return false;

  AST_GET_CHILDREN(receiver_type, package, id);

  if(ast_name(package) != c->str_builtin)
    return false;

  const char* name = ast_name(id);

  if(name == c->str_Bool)
    return special_case_operator(c, ast, value, true, true);

  if((name == c->str_I8) ||
    (name == c->str_I16) ||
    (name == c->str_I32) ||
    (name == c->str_I64) ||
    (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_ULong) ||
    (name == c->str_USize) ||
    (name == c->str_F32) ||
    (name == c->str_F64)
    )
  {
    return special_case_operator(c, ast, value, false, true);
  }

  if((name == c->str_I128) || (name == c->str_U128))
  {
    bool native128;
    os_is_target(OS_NATIVE128_NAME, c->opt->release, &native128);
    return special_case_operator(c, ast, value, false, native128);
  }

  if(name == c->str_Platform)
  {
    *value = special_case_platform(c, ast);
    return true;
  }

  return false;
}
Exemple #2
0
// Evaluate the given ifdef condition for the given config, or our target build
// if no config is given.
static bool cond_eval(ast_t* ast, buildflagset_t* config, bool release,
  pass_opt_t* opt)
{
  pony_assert(ast != NULL);

  switch(ast_id(ast))
  {
    case TK_NONE:
      // No condition to evaluate
      return true;

    case TK_IFDEFAND:
    {
      AST_GET_CHILDREN(ast, left, right);
      return cond_eval(left, config, release, opt) &&
        cond_eval(right, config, release, opt);
    }

    case TK_IFDEFOR:
    {
      AST_GET_CHILDREN(ast, left, right);
      return cond_eval(left, config, release, opt) ||
        cond_eval(right, config, release, opt);
    }

    case TK_IFDEFNOT:
      return !cond_eval(ast_child(ast), config, release, opt);

    case TK_IFDEFFLAG:
    {
      const char* name = ast_name(ast_child(ast));

      if(config != NULL)
        // Lookup flag in given config.
        return buildflagset_get(config, name);

      // No config given, lookup platform flag for current build.
      bool val;
      if(os_is_target(name, release, &val, opt))
      {
        return val;
      }

      // Not a platform flag, must be a user flag.
      return is_build_flag_defined(name);
    }

    default:
      pony_assert(0);
      return false;
  }
}
Exemple #3
0
static LLVMValueRef special_case_platform(compile_t* c, ast_t* ast)
{
  AST_GET_CHILDREN(ast, positional, named, postfix);
  AST_GET_CHILDREN(postfix, receiver, method);

  const char* method_name = ast_name(method);
  bool is_target;

  if(os_is_target(method_name, c->opt->release, &is_target, c->opt))
    return LLVMConstInt(c->ibool, is_target ? 1 : 0, false);

  ast_error(c->opt->check.errors, ast, "unknown Platform setting");
  return NULL;
}
Exemple #4
0
// Check the given ast is a valid ifdef condition.
// The context parameter is for error messages and should be a literal string
// such as "ifdef condition" or "use guard".
static bool syntax_ifdef_cond(pass_opt_t* opt, ast_t* ast, const char* context)
{
  assert(ast != NULL);
  assert(context != NULL);

  switch(ast_id(ast))
  {
    case TK_AND:
    case TK_OR:
    case TK_NOT:
      // Valid node.
      break;

    case TK_STRING:
    {
      // Check user flag is not also a platform, or outlawed, flags
      const char* name = ast_name(ast);

      // Create an all lower case version of the name for comparisons.
      size_t len = strlen(name) + 1;
      char* lower_case = (char*)ponyint_pool_alloc_size(len);

      for(size_t i = 0; i < len; i++)
        lower_case[i] = (char)tolower(name[i]);

      bool r = true;
      bool result;
      if(os_is_target(lower_case, true, &result, opt))
        r = false;

      for(int i = 0; _illegal_flags[i] != NULL; i++)
        if(strcmp(lower_case, _illegal_flags[i]) == 0)
          r = false;

      ponyint_pool_free_size(len, lower_case);

      if(!r)
      {
        ast_error(opt->check.errors, ast,
          "\"%s\" is not a valid user build flag\n", name);
        return false;
      }

      // TODO: restrict case?
      break;
    }

    case TK_REFERENCE:
    {
      const char* name = ast_name(ast_child(ast));
      bool result;
      if(!os_is_target(name, true, &result, opt))
      {
        ast_error(opt->check.errors, ast,
          "\"%s\" is not a valid platform flag\n", name);
        return false;
      }

      // Don't recurse into children, that'll hit the ID node
      return true;
    }

    case TK_SEQ:
      if(ast_childcount(ast) != 1)
      {
        ast_error(opt->check.errors, ast,
          "Sequence not allowed in %s", context);
        return false;
      }

      break;

    default:
      ast_error(opt->check.errors, ast, "Invalid %s", context);
      return false;
  }

  for(ast_t* p = ast_child(ast); p != NULL; p = ast_sibling(p))
  {
    if(!syntax_ifdef_cond(opt, p, context))
      return false;
  }

  return true;
}