ast_expression.cpp

来自「这是广泛使用的通信开源项目,对于大容量,高并发的通讯要求完全能够胜任,他广泛可用」· C++ 代码 · 共 2,158 行 · 第 1/5 页

CPP
2,158
字号
// @@@ (JP) See comment below.
/*
  this->pd_v1->set_ev (this->pd_v1->eval_internal (ek));

  if (this->pd_v1->ev () == 0)
    {
      return 0;
    }
*/
  this->pd_v1->set_ev (this->pd_v1->coerce (EV_double));

  if (this->pd_v1->ev () == 0)
    {
      return 0;
    }
/*
  this->pd_v2->set_ev (this->pd_v2->eval_internal (ek));

  if (this->pd_v2->ev () == 0)
    {
      return 0;
    }
*/
  this->pd_v2->set_ev (this->pd_v2->coerce (EV_double));

  if (pd_v2->ev () == 0)
    {
      return 0;
    }

  ACE_NEW_RETURN (retval,
                  AST_ExprValue,
                  0);

  retval->et = EV_double;

  switch (this->pd_ec)
    {
    case EC_mod:
      if (this->pd_v2->ev ()->u.lval == 0)
        {
          return 0;
        }

      retval->u.lval =
        this->pd_v1->ev ()->u.lval % this->pd_v2->ev ()->u.lval;
      break;
    case EC_add:
      retval->u.dval =
        this->pd_v1->ev ()->u.dval + this->pd_v2->ev ()->u.dval;
      break;
    case EC_minus:
      retval->u.dval =
        this->pd_v1->ev ()->u.dval - this->pd_v2->ev ()->u.dval;
      break;
    case EC_mul:
      retval->u.dval =
        this->pd_v1->ev ()->u.dval * this->pd_v2->ev ()->u.dval;
      break;
    case EC_div:
      if (this->pd_v2->ev ()->u.dval == 0.0)
        {
          return 0;
        }

      retval->u.dval =
        this->pd_v1->ev ()->u.dval / this->pd_v2->ev  ()->u.dval;
      break;
    default:
      return 0;
    }

  // @@@ (JP) CORBA 2.6 and earlier say that in a constant expression,
  // each subexpression must fall within the range of the assigned type.
  // However, this may be hard for the compiler in some cases (must
  // evaluate all grouping possibilities). So there is an outstanding
  // issue, #1139, and the best guess is that it will ultimately be
  // decided that only the final value must fall within the range of
  // the assigned type. So I've commented out the checks above, and
  // added this final evaluation below. (02-06-25).
//  return eval_kind (retval, ek);
  return retval;
}

// Apply bitwise operations to an AST_Expression after evaluating
// its sub-expressions.
// Operations supported: '%', '|', '&', '^', '<<', '>>'
AST_Expression::AST_ExprValue *
AST_Expression::eval_bit_op (AST_Expression::EvalKind ek)
{
  AST_Expression::AST_ExprValue *retval = 0;

  if (this->pd_v1 == 0 || this->pd_v2 == 0)
    {
      return 0;
    }

  this->pd_v1->set_ev (this->pd_v1->eval_internal (ek));
  this->pd_v2->set_ev (this->pd_v2->eval_internal (ek));

  if (this->pd_v1->ev () == 0 || this->pd_v2->ev () == 0 )
    {
      return 0;
    }

  ACE_NEW_RETURN (retval,
                  AST_ExprValue,
                  0);

  // @@(JP) The rest will have to be expanded to handle 64-bit ints.
  if (ek == EK_ulong)
    {
      this->pd_v1->set_ev (this->pd_v1->coerce (EV_ulong));
      this->pd_v2->set_ev (this->pd_v2->coerce (EV_ulong));
      retval->et = EV_ulong;
    }
  else
    {
      this->pd_v1->set_ev (this->pd_v1->coerce (EV_long));
      this->pd_v2->set_ev (this->pd_v2->coerce (EV_long));
      retval->et = EV_long;
    }

  if (this->pd_v1->ev () == 0 || this->pd_v2->ev () == 0)
    {
      return 0;
    }

  if (ek == EK_ulong)
    {
      switch (this->pd_ec)
      {
        case EC_or:
          retval->u.ulval =
            this->pd_v1->ev ()->u.ulval | this->pd_v2->ev ()->u.ulval;
          break;
        case EC_xor:
          retval->u.ulval =
            this->pd_v1->ev ()->u.ulval ^ this->pd_v2->ev ()->u.ulval;
          break;
        case EC_and:
          retval->u.ulval =
            this->pd_v1->ev ()->u.ulval & this->pd_v2->ev ()->u.ulval;
          break;
        case EC_left:
          retval->u.ulval =
            this->pd_v1->ev ()->u.ulval << this->pd_v2->ev ()->u.ulval;
          break;
        case EC_right:
          retval->u.ulval =
            this->pd_v1->ev ()->u.ulval >> this->pd_v2->ev ()->u.ulval;
          break;
        default:
          return 0;
      }
    }
  else
    {
      switch (this->pd_ec)
      {
        case EC_or:
          retval->u.lval =
            this->pd_v1->ev ()->u.lval | this->pd_v2->ev ()->u.lval;
          break;
        case EC_xor:
          retval->u.lval =
            this->pd_v1->ev ()->u.lval ^ this->pd_v2->ev ()->u.lval;
          break;
        case EC_and:
          retval->u.lval =
            this->pd_v1->ev ()->u.lval & this->pd_v2->ev ()->u.lval;
          break;
        case EC_left:
          retval->u.lval =
            this->pd_v1->ev ()->u.lval << this->pd_v2->ev ()->u.lval;
          break;
        case EC_right:
          retval->u.lval =
            this->pd_v1->ev ()->u.lval >> this->pd_v2->ev ()->u.lval;
          break;
        default:
          return 0;
      }
    }

  return retval;
}

// Apply unary operators to an AST_Expression after evaluating its
// sub-expression.
// Operations supported: '-', '+', '~'
AST_Expression::AST_ExprValue *
AST_Expression::eval_un_op (AST_Expression::EvalKind ek)
{
  AST_ExprValue *retval = 0;

  if (this->pd_ev != 0)
    {
      return this->pd_ev;
    }

  if (this->pd_v1 == 0)
    {
      return 0;
    }

  this->pd_v1->set_ev (this->pd_v1->eval_internal (ek));

  if (this->pd_v1->ev () == 0)
    {
      return 0;
    }

  ACE_NEW_RETURN (retval,
                  AST_ExprValue,
                  0);

  retval->et = EV_double;

  switch (this->pd_ec)
    {
    case EC_u_plus:
      this->pd_v1->set_ev (this->pd_v1->coerce (EV_double));

      if (this->pd_v1->ev () == 0)
        {
          return 0;
        }

      retval->u.dval = this->pd_v1->ev ()->u.dval;
      break;
    case EC_u_minus:
      this->pd_v1->set_ev (this->pd_v1->coerce (EV_double));

      if (this->pd_v1->ev () == 0)
        {
          return 0;
        }

      retval->u.dval = -(this->pd_v1->ev ()->u.dval);
      break;
    case EC_bit_neg:
      if (this->pd_v1->ev () == 0)
        {
          return 0;
        }

      switch (this->pd_v1->ev ()->et)
      {
        case EV_short:
          retval->et = EV_short;
          retval->u.sval = ~this->pd_v1->ev ()->u.sval;
          break;
        case EV_ushort:
          retval->et = EV_ushort;
          retval->u.usval = ~this->pd_v1->ev ()->u.usval;
          break;
        case EV_long:
          retval->et = EV_long;
          retval->u.lval = ~this->pd_v1->ev ()->u.lval;
          break;
        case EV_ulong:
          retval->et = EV_ulong;
          retval->u.ulval = ~this->pd_v1->ev ()->u.ulval;
          break;
#if ! defined (ACE_LACKS_LONGLONG_T)
        case EV_longlong:
          retval->et = EV_longlong;
          retval->u.llval = ~this->pd_v1->ev ()->u.llval;
          break;
        case EV_ulonglong:
          retval->et = EV_ulonglong;
          retval->u.ullval = ~this->pd_v1->ev ()->u.ullval;
          break;
#endif /* ! defined (ACE_LACKS_LONGLONG_T) */
        case EV_octet:
          retval->et = EV_octet;
          retval->u.oval = ~this->pd_v1->ev ()->u.oval;
          break;
        default:
          return 0;
      }

      break;
    default:
      return 0;
  }

  return retval;
}

// Evaluate a symbolic AST_Expression by looking up the named
// symbol.
AST_Expression::AST_ExprValue *
AST_Expression::eval_symbol (AST_Expression::EvalKind ek)
{
  UTL_Scope     *s = 0;
  AST_Decl *d = 0;
  AST_Constant *c = 0;

  // Is there a symbol stored?
  if (this->pd_n == 0)
    {
      idl_global->err ()->eval_error  (this);
      return 0;
    }

  // Get current scope for lookup.
  if (idl_global->scopes ().depth () > 0)
    {
      s = idl_global->scopes ().top_non_null ();
    }

  if (s == 0)
    {
      idl_global->err ()->lookup_error (this->pd_n);
      return 0;
    }

  // Do lookup.
  d = s->lookup_by_name (this->pd_n,
                         I_TRUE);

  if (d == 0)
    {
      idl_global->err ()->lookup_error (this->pd_n);
      return 0;
    }

  // Is it a constant?
  if (d->node_type () != AST_Decl::NT_const
      && d->node_type () != AST_Decl::NT_enum_val)
    {
      idl_global->err ()->constant_expected (this->pd_n,
                                             d);
      return 0;
    }

  // OK, now evaluate the constant we just got, to produce its value.
  c = AST_Constant::narrow_from_decl (d);

  if (c == 0)
    {
      return 0;
    }

  return c->constant_value ()->eval_internal (ek);
}

idl_bool
AST_Expression::type_mismatch (AST_Expression::ExprType t)
{
  if (this->pd_ev != 0)
    {
      return incompatible_types (this->pd_ev->et, t);
    }

  idl_bool v1_mismatch = 0;
  idl_bool v2_mismatch = 0;

  if (this->pd_v1 != 0)
    {
      v1_mismatch = this->pd_v1->type_mismatch (t);
    }

  if (this->pd_v2 != 0)
    {
      v2_mismatch = this->pd_v2->type_mismatch (t);
    }

  return v1_mismatch | v2_mismatch;
}

// Coerce "this" to the ExprType required. Returns a copy of the
// original ExprValue with the coercion applied, if successful, or
// 0 if failed.
AST_Expression::AST_ExprValue *
AST_Expression::check_and_coerce (AST_Expression::ExprType t,
                                  AST_Decl *d)
{
  if (d != 0)
    {
      AST_Decl *enum_val =
        idl_global->scopes ().top_non_null ()->lookup_by_name (this->pd_n,
                                                               1);

      if (enum_val != 0)
        {
          AST_Decl *enum_decl = ScopeAsDecl (enum_val->defined_in ());

          if (d->node_type () == AST_Decl::NT_typedef)
            {
              AST_Typedef *td = AST_Typedef::narrow_from_decl (d);
              d = td->primitive_base_type ();
            }

          if (d != enum_decl)
            {
              idl_global->err ()->incompatible_type_error (this);
              return 0;
            }
        }
    }

  if (this->type_mismatch (t))
    {
      idl_global->err ()->incompatible_type_error (this);
      return 0;
    }

  if (d != 0 && d->node_type () == AST_Decl::NT_typedef)
    {
      this->tdef = d;
    }

  return this->coerce (t);
}

// Coerce "this" to the ExprType required. Returns a copy of the
// original ExprValue with the coercion applied, if successful, or
// 0 if failed.
AST_Expression::AST_ExprValue *
AST_Expression::coerce (AST_Expression::ExprType t)
{
  // First, evaluate it, then try to coerce result type.
  // If already evaluated, return the result.
  switch (t)
  {
    case EV_short:
      this->pd_ev = this->eval

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?