// // aegis - project change supervisor // Copyright (C) 1997, 1999, 2002-2008 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include #include #include #include #include #include #include #include #include #include tree_and::~tree_and() { } tree_and::tree_and(const tree::pointer &a1, const tree::pointer &a2) : tree_diadic(a1, a2) { } tree::pointer tree_and::create(const tree::pointer &a1, const tree::pointer &a2) { return pointer(new tree_and(a1, a2)); } tree::pointer tree_and::create_l(const tree_list &args) { function_needs_two("&&", args); return create(args[0], args[1]); } rpt_value::pointer tree_and::evaluate(string_ty *path_unres, string_ty *path, string_ty *path_res, struct stat *st) const { rpt_value::pointer v1 = get_left()->evaluate(path_unres, path, path_res, st); if (v1->is_an_error()) return v1; rpt_value::pointer v1b = rpt_value::booleanize(v1); rpt_value_boolean *v1bp = dynamic_cast(v1b.get()); if (!v1bp) { sub_context_ty sc; sc.var_set_charstar("Name", v1->name()); nstring s ( sc.subst_intl ( i18n("boolean value required for logical and (was given $name)") ) ); return rpt_value_error::create(s); } if (!v1bp->query()) return v1b; rpt_value::pointer v2 = get_right()->evaluate(path_unres, path, path_res, st); if (v2->is_an_error()) return v2; rpt_value::pointer v2b = rpt_value::booleanize(v2); rpt_value_boolean *v2bp = dynamic_cast(v2b.get()); if (!v2bp) { sub_context_ty sc; sc.var_set_charstar("Name", v2->name()); nstring s ( sc.subst_intl ( i18n("boolean value required for logical and (was given $name)") ) ); return rpt_value_error::create(s); } return v2b; } tree::pointer tree_and::optimize() const { tree::pointer l2 = get_left()->optimize(); tree::pointer r2 = get_right()->optimize(); if (l2->constant()) { // // left is constant // rpt_value::pointer lv = l2->evaluate_constant(); rpt_value_boolean *lvbp = dynamic_cast(lv.get()); if (!lvbp) return create(l2, r2); bool flag = lvbp->query(); return (flag ? r2 : l2); } if (!r2->constant()) { // // neither left nor right are constant // return create(l2, r2); } // // right is constant, but left is not // rpt_value::pointer rv = r2->evaluate_constant(); rpt_value_boolean *rvbp = dynamic_cast(rv.get()); if (!rvbp) { return create(l2, r2); } bool flag = rvbp->query(); return (flag ? l2 : r2); } const char * tree_and::name() const { return "&&"; } tree_or::~tree_or() { } tree_or::tree_or(const tree::pointer &a1, const tree::pointer &a2) : tree_diadic(a1, a2) { } tree::pointer tree_or::create(const tree::pointer &a1, const tree::pointer &a2) { return pointer(new tree_or(a1, a2)); } tree::pointer tree_or::create_l(const tree_list &args) { function_needs_two("||", args); return create(args[0], args[1]); } rpt_value::pointer tree_or::evaluate(string_ty *path_unres, string_ty *path, string_ty *path_res, struct stat *st) const { rpt_value::pointer v1 = get_left()->evaluate(path_unres, path, path_res, st); if (v1->is_an_error()) return v1; rpt_value::pointer v1b = rpt_value::booleanize(v1); rpt_value_boolean *v1bp = dynamic_cast(v1b.get()); if (!v1bp) { sub_context_ty sc; sc.var_set_charstar("Name", v1->name()); nstring s ( sc.subst_intl ( i18n("boolean value required for logical or (was given $name)") ) ); return rpt_value_error::create(s); } if (v1bp->query()) return v1b; rpt_value::pointer v2 = get_right()->evaluate(path_unres, path, path_res, st); if (v2->is_an_error()) return v2; rpt_value::pointer v2b = rpt_value::booleanize(v2); rpt_value_boolean *v2bp = dynamic_cast(v2b.get()); if (!v2bp) { sub_context_ty sc; sc.var_set_charstar("Name", v2->name()); nstring s ( sc.subst_intl ( i18n("boolean value required for logical or (was given $name)") ) ); return rpt_value_error::create(s); } return v2b; } tree::pointer tree_or::optimize() const { tree::pointer l2 = get_left()->optimize(); tree::pointer r2 = get_right()->optimize(); if (l2->constant()) { // // left is constant // rpt_value::pointer lv = l2->evaluate_constant(); rpt_value_boolean *lvbp = dynamic_cast(lv.get()); if (!lvbp) { return create(l2, r2); } bool flag = lvbp->query(); return (flag ? l2 : r2); } if (!r2->constant()) { // // neither left nor right are constant // return create(l2, r2); } // // right is constant, but left is not // rpt_value::pointer rv = r2->evaluate_constant(); rpt_value_boolean *rvbp = dynamic_cast(rv.get()); if (!rvbp) { return create(l2, r2); } bool flag = rvbp->query(); return (flag ? r2 : l2); } const char * tree_or::name() const { return "||"; } tree_not::~tree_not() { } tree_not::tree_not(const tree::pointer &a_arg) : tree_monadic(a_arg) { } tree::pointer tree_not::create(const tree::pointer &a_arg) { return pointer(new tree_not(a_arg)); } tree::pointer tree_not::create_l(const tree_list &args) { function_needs_one("!", args); return create(args[0]); } rpt_value::pointer tree_not::evaluate(string_ty *path_unres, string_ty *path, string_ty *path_res, struct stat *st) const { rpt_value::pointer v1 = get_arg()->evaluate(path_unres, path, path_res, st); if (v1->is_an_error()) return v1; rpt_value::pointer v2 = rpt_value::booleanize(v1); rpt_value_boolean *v2bp = dynamic_cast(v2.get()); if (!v2bp) { sub_context_ty sc; sc.var_set_charstar("Name", v1->name()); nstring s(sc.subst_intl(i18n("illegal logical not ($name)"))); return rpt_value_error::create(s); } return rpt_value_boolean::create(!v2bp->query()); } tree::pointer tree_not::optimize() const { tree::pointer tp = create(get_arg()->optimize()); if (tp->constant()) tp = tp->optimize_constant(); return tp; } const char * tree_not::name() const { return "!"; } tree_comma::~tree_comma() { } tree_comma::tree_comma(const tree::pointer &a1, const tree::pointer &a2) : tree_diadic(a1, a2) { } tree::pointer tree_comma::create(const tree::pointer &a1, const tree::pointer &a2) { return pointer(new tree_comma(a1, a2)); } tree::pointer tree_comma::create_l(const tree_list &args) { function_needs_two(",", args); return create(args[0], args[1]); } rpt_value::pointer tree_comma::evaluate(string_ty *path_unres, string_ty *path, string_ty *path_res, struct stat *st) const { rpt_value::pointer vp = get_left()->evaluate(path_unres, path, path_res, st); if (vp->is_an_error()) return vp; return get_right()->evaluate(path_unres, path, path_res, st); } tree::pointer tree_comma::optimize() const { tree::pointer tp = create(get_left()->optimize(), get_right()->optimize()); if (tp->constant()) tp = tp->optimize_constant(); return tp; } const char * tree_comma::name() const { return ","; } tree_triadic::~tree_triadic() { } tree_triadic::tree_triadic(const tree::pointer &a_a1, const tree::pointer &a_a2, const tree::pointer &a_a3) : a1(a_a1), a2(a_a2), a3(a_a3) { } tree::pointer tree_triadic::create(const tree::pointer &a_a1, const tree::pointer &a_a2, const tree::pointer &a_a3) { return pointer(new tree_triadic(a_a1, a_a2, a_a3)); } void tree_triadic::print() const { printf("( ( "); a1->print(); printf(" ) ? ( "); a2->print(); printf(" ) : ( "); a3->print(); printf(" ) )"); } rpt_value::pointer tree_triadic::evaluate(string_ty *path_unres, string_ty *path, string_ty *path_res, struct stat *st) const { rpt_value::pointer v1 = a1->evaluate(path_unres, path, path_res, st); if (v1->is_an_error()) return v1; rpt_value::pointer v1b = rpt_value::booleanize(v1); rpt_value_boolean *v1bp = dynamic_cast(v1b.get()); if (!v1bp) { sub_context_ty sc; sc.var_set_charstar("Name", v1->name()); nstring s ( sc.subst_intl ( i18n("boolean value required for if (was given $name)") ) ); return rpt_value_error::create(s); } bool which = v1bp->query(); return (which ? a2 : a3)->evaluate(path_unres, path, path_res, st); } bool tree_triadic::useful() const { return (a1->useful() || a2->useful() || a3->useful()); } bool tree_triadic::constant() const { if (!a1->constant()) return false; rpt_value::pointer v1 = a1->evaluate_constant(); if (v1->is_an_error()) { return false; } rpt_value::pointer v1b = rpt_value::booleanize(v1); rpt_value_boolean *v1bp = dynamic_cast(v1b.get()); if (!v1bp) { return false; } bool which = v1bp->query(); return (which ? a2 : a3)->constant(); } tree::pointer tree_triadic::optimize() const { if (!a1->constant()) { tree::pointer arg1 = a1->optimize(); tree::pointer arg2 = a2->optimize(); tree::pointer arg3 = a3->optimize(); return tree_triadic::create(arg1, arg2, arg3); } rpt_value::pointer v1 = a1->evaluate_constant(); if (v1->is_an_error()) { tree::pointer result = tree_constant::create(v1); return result; } rpt_value::pointer v1b = rpt_value::booleanize(v1); rpt_value_boolean *v1bp = dynamic_cast(v1b.get()); if (!v1bp) { sub_context_ty sc; sc.var_set_charstar("Name", v1->name()); nstring s ( sc.subst_intl ( i18n("boolean value required for if (was given $name)") ) ); return tree_constant::create(rpt_value_error::create(s)); } bool which = v1bp->query(); return (which ? a2 : a3)->optimize(); } const char * tree_triadic::name() const { return "?:"; }