//
// 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
rpt_expr_assign::~rpt_expr_assign()
{
trace(("%s\n", __PRETTY_FUNCTION__));
}
rpt_expr_assign::rpt_expr_assign(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
trace(("%s\n", __PRETTY_FUNCTION__));
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign::create(const rpt_expr::pointer &a, const rpt_expr::pointer &b)
{
trace(("%s\n", __PRETTY_FUNCTION__));
return pointer(new rpt_expr_assign(a, b));
}
rpt_value::pointer
rpt_expr_assign::evaluate()
const
{
//
// evaluate the left hand side
//
trace(("rpt_expr_assign::evaluate()\n{\n"));
assert(get_nchildren() == 2);
rpt_value::pointer lv = nth_child(0)->evaluate(true, false);
trace(("lv is a %s\n", lv->name()));
if (lv->is_an_error())
{
trace(("}\n"));
return lv;
}
//
// if the left hand side is not a reference type,
// it is an error
//
rpt_value_reference *lv_ref = dynamic_cast(lv.get());
if (!lv_ref)
{
trace(("oops\n"));
sub_context_ty sc;
sc.var_set_charstar("Name", lv->name());
nstring s
(
sc.subst_intl
(
i18n("illegal left hand side of assignment (was given $name)")
)
);
rpt_value::pointer vp =
rpt_value_error::create(nth_child(0)->get_pos(), s);
trace(("}\n"));
return vp;
}
//
// evaluate the right hand side
//
trace(("about to evaluate rhs\n"));
rpt_value::pointer rv = nth_child(1)->evaluate(true, true);
trace(("rv is a %s\n", rv->name()));
if (rv->is_an_error())
{
trace(("}\n"));
return rv;
}
//
// set the value (will take copy)
//
trace(("set reference\n"));
lv_ref->set(rv);
//
// cleanup and go home
//
trace(("return %p;\n", rv.get()));
trace(("}\n"));
return rv;
}
static rpt_value::pointer
bin_eval(const rpt_expr::pointer &lhs,
rpt_expr::pointer (*op)(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs),
const rpt_expr::pointer &rhs)
{
//
// evaluate the left hand side
//
trace(("bin_eval()\n{\n"));
rpt_value::pointer ptr = lhs->evaluate(true, false);
if (ptr->is_an_error())
{
trace(("}\n"));
return ptr;
}
//
// if the left hand side is not a reference type,
// it is an error
//
if (!dynamic_cast(ptr.get()))
{
sub_context_ty sc;
sc.var_set_charstar("Name", ptr->name());
nstring s
(
sc.subst_intl
(
i18n("illegal left hand side of assignment (was given $name)")
)
);
assert(lhs->get_pos());
rpt_value::pointer result = rpt_value_error::create(lhs->get_pos(), s);
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
//
// construct
// lhs = lhs "op" rhs
//
// Note:
// e1 and e2 are separate because one is an lvalue, and
// the other is an rvalue. They e1 is altered by
// rpt_expr_assign, while e2 is not.
//
rpt_expr::pointer e1 = rpt_expr_constant::create(ptr);
e1->pos_from(lhs);
rpt_expr::pointer e2 = rpt_expr_constant::create(ptr);
e2->pos_from(lhs);
//
// use the constant expression to build a simple assignment expression
// "op" is the appropriate binary expression builder
//
rpt_expr::pointer e3 = op(e2, rhs);
rpt_expr::pointer e4 = rpt_expr_assign::create(e1, e3);
//
// evaluate the simple assignment
// and discard the fake expression tree
//
rpt_value::pointer result = e4->evaluate(true, true);
//
// clean up and go home
//
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_power::~rpt_expr_assign_power()
{
}
rpt_expr_assign_power::rpt_expr_assign_power(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_power::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_power(a, b));
}
rpt_value::pointer
rpt_expr_assign_power::evaluate()
const
{
trace(("power_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_power::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_mul::~rpt_expr_assign_mul()
{
}
rpt_expr_assign_mul::rpt_expr_assign_mul(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_mul::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_mul(a, b));
}
rpt_value::pointer
rpt_expr_assign_mul::evaluate()
const
{
trace(("mul_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_mul::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_div::~rpt_expr_assign_div()
{
}
rpt_expr_assign_div::rpt_expr_assign_div(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_div::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_div(a, b));
}
rpt_value::pointer
rpt_expr_assign_div::evaluate()
const
{
trace(("div_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_div::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_mod::~rpt_expr_assign_mod()
{
}
rpt_expr_assign_mod::rpt_expr_assign_mod(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_mod::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_mod(a, b));
}
rpt_value::pointer
rpt_expr_assign_mod::evaluate()
const
{
trace(("mod_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_mod::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_plus::~rpt_expr_assign_plus()
{
}
rpt_expr_assign_plus::rpt_expr_assign_plus(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_plus::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_plus(a, b));
}
rpt_value::pointer
rpt_expr_assign_plus::evaluate()
const
{
trace(("plus_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_plus::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_minus::~rpt_expr_assign_minus()
{
}
rpt_expr_assign_minus::rpt_expr_assign_minus(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_minus::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_minus(a, b));
}
rpt_value::pointer
rpt_expr_assign_minus::evaluate()
const
{
trace(("minus_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_minus::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_and_bit::~rpt_expr_assign_and_bit()
{
}
rpt_expr_assign_and_bit::rpt_expr_assign_and_bit(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_and_bit::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_and_bit(a, b));
}
rpt_value::pointer
rpt_expr_assign_and_bit::evaluate()
const
{
trace(("and_bit_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_and_bit::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_xor_bit::~rpt_expr_assign_xor_bit()
{
}
rpt_expr_assign_xor_bit::rpt_expr_assign_xor_bit(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_xor_bit::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_xor_bit(a, b));
}
rpt_value::pointer
rpt_expr_assign_xor_bit::evaluate()
const
{
trace(("xor_bit_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_xor_bit::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_or_bit::~rpt_expr_assign_or_bit()
{
}
rpt_expr_assign_or_bit::rpt_expr_assign_or_bit(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_or_bit::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_or_bit(a, b));
}
rpt_value::pointer
rpt_expr_assign_or_bit::evaluate()
const
{
trace(("or_bit_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_or_bit::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_shift_left::~rpt_expr_assign_shift_left()
{
}
rpt_expr_assign_shift_left::rpt_expr_assign_shift_left(
const rpt_expr::pointer &a, const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_shift_left::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_shift_left(a, b));
}
rpt_value::pointer
rpt_expr_assign_shift_left::evaluate()
const
{
trace(("shift_left_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_shift_left::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_shift_right::~rpt_expr_assign_shift_right()
{
}
rpt_expr_assign_shift_right::rpt_expr_assign_shift_right(
const rpt_expr::pointer &a, const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_shift_right::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_shift_right(a, b));
}
rpt_value::pointer
rpt_expr_assign_shift_right::evaluate()
const
{
trace(("shift_right_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_shift_right::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
rpt_expr_assign_join::~rpt_expr_assign_join()
{
}
rpt_expr_assign_join::rpt_expr_assign_join(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
append(a);
append(b);
if (!a->lvalue())
a->parse_error(i18n("illegal left hand side of assignment"));
}
rpt_expr::pointer
rpt_expr_assign_join::create(const rpt_expr::pointer &a,
const rpt_expr::pointer &b)
{
return pointer(new rpt_expr_assign_join(a, b));
}
rpt_value::pointer
rpt_expr_assign_join::evaluate()
const
{
trace(("join_assign::evaluate()\n{\n"));
rpt_value::pointer result =
bin_eval(nth_child(0), &rpt_expr_join::create, nth_child(1));
trace(("return %p;\n", result.get()));
trace(("}\n"));
return result;
}
// vim: set ts=8 sw=4 et :