//
// aegis - project change supervisor
// Copyright (C) 1994-1996, 1999, 2002-2008, 2012 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
rpt_expr_and_logical::~rpt_expr_and_logical()
{
}
rpt_expr_and_logical::rpt_expr_and_logical(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
append(lhs);
append(rhs);
}
rpt_expr::pointer
rpt_expr_and_logical::create(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
return pointer(new rpt_expr_and_logical(lhs, rhs));
}
rpt_value::pointer
rpt_expr_and_logical::evaluate()
const
{
//
// eveluate the left hand side
//
assert(get_nchildren() == 2);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
return v1;
rpt_value::pointer v1b = rpt_value::booleanize(v1);
rpt_value_boolean *v1p = dynamic_cast(v1b.get());
if (!v1p)
{
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(nth_child(0)->get_pos(), s);
}
//
// short circuit the evaluation if the LHS is false
//
if (!v1p->query())
return v1b;
//
// evaluate the right hand side
//
rpt_value::pointer v2 = nth_child(1)->evaluate(true, true);
if (v2->is_an_error())
return v2;
rpt_value::pointer v2b = rpt_value::booleanize(v2);
rpt_value_boolean *v2p = dynamic_cast(v2b.get());
if (!v2p)
{
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(nth_child(1)->get_pos(), s);
}
return v2b;
}
rpt_expr_or_logical::~rpt_expr_or_logical()
{
}
rpt_expr_or_logical::rpt_expr_or_logical(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
append(lhs);
append(rhs);
}
rpt_expr::pointer
rpt_expr_or_logical::create(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
return pointer(new rpt_expr_or_logical(lhs, rhs));
}
rpt_value::pointer
rpt_expr_or_logical::evaluate()
const
{
//
// evaluate the left hand side
//
assert(get_nchildren() == 2);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
return v1;
rpt_value::pointer v1b = rpt_value::booleanize(v1);
rpt_value_boolean *v1p = dynamic_cast(v1b.get());
if (!v1p)
{
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(nth_child(0)->get_pos(), s);
}
//
// short circuit the evaluation if LHS is true
//
if (v1p->query())
return v1b;
//
// evaluate the right hand side
//
rpt_value::pointer v2 = nth_child(1)->evaluate(true, true);
if (v2->is_an_error())
return v2;
rpt_value::pointer v2b = rpt_value::booleanize(v2);
rpt_value_boolean *v2p = dynamic_cast(v2b.get());
if (!v2p)
{
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(nth_child(1)->get_pos(), s);
}
return v2b;
}
rpt_expr_not_logical::~rpt_expr_not_logical()
{
}
rpt_expr_not_logical::rpt_expr_not_logical(const rpt_expr::pointer &arg)
{
append(arg);
}
rpt_expr::pointer
rpt_expr_not_logical::create(const rpt_expr::pointer &arg)
{
return pointer(new rpt_expr_not_logical(arg));
}
rpt_value::pointer
rpt_expr_not_logical::evaluate()
const
{
//
// evaluate the argument
//
trace(("not::evaluate()\n{\n"));
assert(get_nchildren() == 1);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
{
trace(("}\n"));
return v1;
}
//
// coerce the argument to boolean type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v2 = rpt_value::booleanize(v1);
//
// the type of the result depends on
// the types of the argument
//
rpt_value_boolean *v2p = dynamic_cast(v2.get());
if (!v2p)
{
sub_context_ty sc;
sc.var_set_charstar("Name", v2->name());
nstring s(sc.subst_intl(i18n("illegal logical not ($name)")));
rpt_value::pointer result =
rpt_value_error::create(nth_child(0)->get_pos(), s);
trace(("}\n"));
return result;
}
rpt_value::pointer result = rpt_value_boolean::create(!v2p->query());
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_if::~rpt_expr_if()
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
rpt_expr_if::rpt_expr_if(const rpt_expr::pointer &e1,
const rpt_expr::pointer &e2, const rpt_expr::pointer &e3)
{
trace(("%s\n", __PRETTY_FUNCTION__));
append(e1);
append(e2);
append(e3);
}
rpt_expr::pointer
rpt_expr_if::create(const rpt_expr::pointer &e1, const rpt_expr::pointer &e2,
const rpt_expr::pointer &e3)
{
trace(("%s\n", __PRETTY_FUNCTION__));
return pointer(new rpt_expr_if(e1, e2, e3));
}
rpt_value::pointer
rpt_expr_if::evaluate()
const
{
//
// evaluate the argument
//
trace(("rpt_expr_if::evaluate()\n{\n"));
assert(get_nchildren() == 3);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
{
trace(("}\n"));
return v1;
}
//
// coerce the argument to boolean type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v1b = rpt_value::booleanize(v1);
trace(("v1b->name() = \"%s\"\n", v1b->name()));
rpt_value_boolean *v1p = dynamic_cast(v1b.get());
if (!v1p)
{
trace(("mark\n"));
sub_context_ty sc;
sc.var_set_charstar("Name", v1b->name());
nstring s
(
sc.subst_intl
(
i18n("boolean value required for arithmetic if (was "
"given $name)")
)
);
rpt_value::pointer result =
rpt_value_error::create(nth_child(0)->get_pos(), s);
trace(("}\n"));
return result;
}
trace(("mark\n"));
bool cond = v1p->query();
rpt_value::pointer result = nth_child(cond ? 1 : 2)->evaluate(true, true);
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
// vim: set ts=8 sw=4 et :