⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 5 页
字号:
    CYG_PRECONDITION_CLASSC(expr);    CYG_PRECONDITIONC((CdlExprOp_Invalid == token) || (CdlExprOp_And == token));    int current_subexpr = expr->first_subexpression;    initialise_tokenisation(data, index);    parse_expression(expr);    if (CdlExprOp_And == token) {        CdlSubexpression subexpr;        subexpr.op        = CdlExprOp_And;        subexpr.lhs_index = current_subexpr;        subexpr.rhs_index = expr->first_subexpression;        push_subexpression(expr, subexpr);    }    token       = token_to_expr_op();    index       = token_start;    token_end   = current_index;    CYG_REPORT_RETURN();}//}}}//}}}//{{{  Expression Evaluation            // ----------------------------------------------------------------------------// Expression evaluation. This always happens in the context of a// particular toplevel. The parsed expression is held in what amounts// to a simple tree, so evaluation involves some recursion and a big// switch statement.static voidevaluate_subexpr(CdlEvalContext& context, CdlExpression expr, int subexpr_index, CdlSimpleValue& result)    throw(CdlEvalException, std::bad_alloc){    CYG_REPORT_FUNCNAME("evaluate_subexpr");    CYG_REPORT_FUNCARG2XV(expr, subexpr_index);    CYG_ASSERTC((subexpr_index >= 0) && ((unsigned int)subexpr_index < expr->sub_expressions.size()));    const CdlSubexpression& subexpr = expr->sub_expressions[subexpr_index];    switch(subexpr.op) {    case CdlExprOp_StringConstant :    case CdlExprOp_IntegerConstant :    case CdlExprOp_DoubleConstant :    {        result = subexpr.constants;        break;    }    case CdlExprOp_Reference :    {        // This expression may be happening in the context of a particular        // property. If so then the destination may or may not be resolved,        // and this is significant in the context of loading and unloading.        // Alternatively this expression may be being evaluated inside        // some Tcl code, with no particular context.        CdlNode destination = 0;        if (0 != context.property) {            // There is a property, use the bound/unbound reference.            destination = expr->references[subexpr.reference_index].get_destination();        } else {            // The destination name can be retrieved, but we still need some            // way of resolving it.            if (0 != context.toplevel) {                std::string destination_name = expr->references[subexpr.reference_index].get_destination_name();                destination = context.toplevel->lookup(destination_name);            }        }        if (0 == destination) {            // There are two ways of handling this.            //   1) throw an eval exception, which will usually result            //      in a new conflict object            //   2) substitute a value of 0.            // There should already be a conflict object for an            // unresolved reference, and having two conflicts for            // essentially the same error is not useful. Using a value            // of 0 allows things to continue for a bit longer. It is            // consistent with active vs. inactive values, gives            // basically the right result for "requires" properties,            // and so on.            //            // For now option (2) has it, but this decision may be            // reversed in future.            result = false;        } else {            CdlValuable valuable = dynamic_cast<CdlValuable>(destination);            if (0 == valuable) {                // This is a serious problem, an exception is warranted.                throw CdlEvalException("The expression references `" + destination->get_class_name() + " " +                                       destination->get_name() + "' which does not have a value.");            } else {                CdlSimpleValue::eval_valuable(context, valuable, result);            }        }        break;    }    case CdlExprOp_Negate :    {        // Unary -. Evaluate the target. If it is numeric, fine. Otherwise        // an error is warranted.        evaluate_subexpr(context, expr, subexpr.lhs_index, result);        if (result.has_integer_value()) {            result.set_integer_value(-1 * result.get_integer_value());        } else if (result.has_double_value()) {            result.set_double_value(-1.0 * result.get_double_value());        } else {            throw CdlEvalException("Attempt to negate non-numeric value `" + result.get_value() + "'.");        }        break;    }    case CdlExprOp_Plus :    {        // Unary +. Essentially this just checks that the current value is numeric.        evaluate_subexpr(context, expr, subexpr.lhs_index, result);        if ((!result.has_integer_value()) && (!result.has_double_value())) {            throw CdlEvalException("Attempt to apply unary + operator to non-numeric value `" + result.get_value() + "'.");        }        break;    }    case CdlExprOp_LogicalNot :    {        // !x        evaluate_subexpr(context, expr, subexpr.lhs_index, result);        if (result.get_bool_value()) {            result = false;;        } else {            result = true;        }        result.set_value_format(CdlValueFormat_Default);        break;    }    case CdlExprOp_BitNot :    {        // ~x. The operand must be an integer value.        evaluate_subexpr(context, expr, subexpr.lhs_index, result);        if (result.has_integer_value()) {            cdl_int tmp = result.get_integer_value();            result = ~tmp;        } else {            throw CdlEvalException("Attempt to apply unary ~ operator to non-integer value `" + result.get_value() + "'.");        }        break;    }    case CdlExprOp_Indirect :    {        // *x. The operand must evaluate to a string, and that string should be        // the name of a CdlValuable object.        CdlNode destination = 0;        evaluate_subexpr(context, expr, subexpr.lhs_index, result);        std::string name = result.get_value();                if (0 != context.toplevel) {            destination = context.toplevel->lookup(name);        } else {            CYG_FAIL("This situation should probably never happen.");        }                if (0 == destination) {            throw CdlEvalException("Attempt to apply unary indirection operator * to `" + name +                                   "', which is not the name of a known CDL entity.");        } else {            CdlValuable valuable = dynamic_cast<CdlValuable>(destination);            if (0 == valuable) {                throw CdlEvalException("Attempt to apply unary indirection operator * to `" + name +                                       "', which does not have a value.");            } else {                CdlSimpleValue::eval_valuable(context, valuable, result);            }        }        break;    }    case CdlExprOp_Active :    {        // ?x. If x is currently unresolved then default to 0.        // See the CdlExprOp_Reference code above for a similar case.        CdlNode destination = 0;        if (0 != context.property) {            destination =  expr->references[subexpr.reference_index].get_destination();        } else {            if (0 != context.toplevel) {                std::string destination_name = expr->references[subexpr.reference_index].get_destination_name();                destination = context.toplevel->lookup(destination_name);            }        }        bool active = false;        if ((0 != destination) && context.transaction->is_active(destination)) {            active = true;        }        if (active) {            result = true;        } else {            result = false;        }        break;    }    case CdlExprOp_Multiply :    {        // x * y. For now this only makes sense for numerical data,        // but it is possible to mix and match integer and double        // precision data.        //        // Strictly speaking the rhs need only be evaluated if it        // is known that the lhs is numeric.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if ((!(lhs.has_integer_value() || lhs.has_double_value())) ||            (!(rhs.has_integer_value() || rhs.has_double_value()))) {            throw CdlEvalException("Attempt to multiply non-numerical values: `" + lhs.get_value() + "' * `" +                                   rhs.get_value() + "'.");        }        if (lhs.has_integer_value() && rhs.has_integer_value()) {            result = lhs.get_integer_value() * rhs.get_integer_value();        } else {            result = lhs.get_double_value() * rhs.get_double_value();        }        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_Divide :    {        // x / y. Basically the same as multiplication, apart from a check for        // division by zero.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if ((!(lhs.has_integer_value() || lhs.has_double_value())) ||            (!(rhs.has_integer_value() || rhs.has_double_value()))) {            throw CdlEvalException("Attempt to divide non-numerical values: `" + lhs.get_value() + "' / `" +                                   rhs.get_value() + "'.");        }        if (lhs.has_integer_value() && rhs.has_integer_value()) {            cdl_int rhs_val = rhs.get_integer_value();            if (0 == rhs_val) {                throw CdlEvalException("Division by zero error: `" + lhs.get_value() + "' / `" + rhs.get_value() + "'.");            } else {                result = lhs.get_integer_value() / rhs_val;            }        } else {            double rhs_val = rhs.get_double_value();            if (0.0 == rhs_val) {                throw CdlEvalException("Division by zero error: `" + lhs.get_value() + "' / `" + rhs.get_value() + "'.");            }            result = lhs.get_double_value() / rhs_val;        }        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_Remainder :    {        // x % y. Both operands must be integral.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if (!(lhs.has_integer_value() && rhs.has_integer_value())) {            throw CdlEvalException("Attempt to use the remainder operator on non integral data: `" +                                   lhs.get_value() + "' % `" + rhs.get_value() + "'.");        }        cdl_int rhs_val = rhs.get_integer_value();        if (0 == rhs_val) {            throw CdlEvalException("Division by zero error: `" + lhs.get_value() + "' % `" + rhs.get_value() + "'.");        }        result = lhs.get_integer_value() % rhs_val;        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_Add :    {        // x + y. For now this only makes sense for numerical data,        // but it is possible to mix and match integer and double        // precision data. Arguably for string data this operator        // should mean concatenation, but it would probably be        // safer to have a separate operator for that.        //        // Strictly speaking the rhs need only be evaluated if it        // is known that the lhs is numeric.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if ((!(lhs.has_integer_value() || lhs.has_double_value())) ||            (!(rhs.has_integer_value() || rhs.has_double_value()))) {            throw CdlEvalException("Attempt to add non-numerical values: `" + lhs.get_value() + "' + `" +                                   rhs.get_value() + "'.");        }        if (lhs.has_integer_value() && rhs.has_integer_value()) {            result = lhs.get_integer_value() + rhs.get_integer_value();        } else {            result = lhs.get_double_value() + rhs.get_double_value();        }        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_Subtract :    {        // x - y. Again only numerical data is supported for now.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if ((!(lhs.has_integer_value() || lhs.has_double_value())) ||            (!(rhs.has_integer_value() || rhs.has_double_value()))) {            throw CdlEvalException("Attempt to subtract non-numerical values: `" + lhs.get_value() + "' - `" +                                   rhs.get_value() + "'.");        }        if (lhs.has_integer_value() && rhs.has_integer_value()) {            result = lhs.get_integer_value() - rhs.get_integer_value();        } else {            result = lhs.get_double_value() - rhs.get_double_value();        }        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_LeftShift :    {        // x << y. Both operands must be integral. For now there is no        // check on the value of y.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if (!(lhs.has_integer_value() && rhs.has_integer_value())) {            throw CdlEvalException("Attempt to use the left-shift operator on non integral data: `" +                                   lhs.get_value() + "' << `" + rhs.get_value() + "'.");        }        result = lhs.get_integer_value() << rhs.get_integer_value();        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_RightShift :    {        // x >> y. Both operands must be integral. For now there is no        // check on the value of y.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if (!(lhs.has_integer_value() && rhs.has_integer_value())) {            throw CdlEvalException("Attempt to use the right-shift operator on non integral data: `" +                                   lhs.get_value() + "' >> `" + rhs.get_value() + "'.");        }        result = lhs.get_integer_value() >> rhs.get_integer_value();        result.set_value_format(lhs, rhs);        break;    }    case CdlExprOp_LessThan :    case CdlExprOp_LessEqual :    case CdlExprOp_GreaterThan :    case CdlExprOp_GreaterEqual :    {        // x < y, and similar comparison operators. These share        // sufficient code to warrant a common implementation. Only        // numerical data is supported for now. These operator could        // be interpreted as e.g. substring operations, but arguably        // separate operators would be better for that.        CdlSimpleValue lhs;        CdlSimpleValue rhs;        evaluate_subexpr(context, expr, subexpr.lhs_index, lhs);        evaluate_subexpr(context, expr, subexpr.rhs_index, rhs);        if ((!(lhs.has_integer_value() || lhs.has_double_value())) ||            (!(rhs.has_integer_value() || rhs.has_double_value()))) {                        std::string op_str =                (CdlExprOp_LessThan    == subexpr.op) ? "<" :                (CdlExprOp_LessEqual   == subexpr.op) ? "<=" :                (CdlExprOp_GreaterThan == subexpr.op) ? ">" : ">=";            throw CdlEvalException("Attempt to compare non-numerical values: `" + lhs.get_value() +                                   "' " + op_str + " `" + rhs.get_value() + "'.");        }        bool val = false;        if (lhs.has_integer_value() && rhs.has_integer_value()) {            cdl_int lhs_val = lhs.get_integer_value();            cdl_int rhs_val = rhs.get_i

⌨️ 快捷键说明

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