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 + -
显示快捷键?