//
// 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
#define PAIR(a, b) ((a) * rpt_value_type_MAX + (b))
rpt_expr_mul::~rpt_expr_mul()
{
}
rpt_expr_mul::rpt_expr_mul(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
append(lhs);
append(rhs);
}
rpt_expr::pointer
rpt_expr_mul::create(const rpt_expr::pointer &lhs, const rpt_expr::pointer &rhs)
{
return pointer(new rpt_expr_mul(lhs, rhs));
}
rpt_value::pointer
rpt_expr_mul::evaluate()
const
{
//
// evaluate the left hand side
//
trace(("mul::evaluate()\n"));
assert(get_nchildren() == 2);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
return v1;
//
// coerce the left hand side to an arithmetic type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v1a = rpt_value::arithmetic(v1);
//
// evaluate the right hand side
//
rpt_value::pointer v2 = nth_child(1)->evaluate(true, true);
if (v2->is_an_error())
return v2;
//
// coerce the right hand side to an arithmetic type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v2a = rpt_value::arithmetic(v2);
//
// the type of the result depends on
// the types of the operands
//
{
rpt_value_integer *v1aip = dynamic_cast(v1a.get());
if (v1aip)
{
long v1n = v1aip->query();
{
rpt_value_integer *v2aip =
dynamic_cast(v2a.get());
if (v2aip)
{
return rpt_value_integer::create(v1n * v2aip->query());
}
}
{
rpt_value_real *v2arp =
dynamic_cast(v2a.get());
if (v2arp)
{
return rpt_value_real::create(v1n * v2arp->query());
}
}
}
}
{
rpt_value_real *v1arp = dynamic_cast(v1a.get());
if (v1arp)
{
double v1n = v1arp->query();
{
rpt_value_integer *v2aip =
dynamic_cast(v2a.get());
if (v2aip)
{
return rpt_value_real::create(v1n * v2aip->query());
}
}
{
rpt_value_real *v2arp =
dynamic_cast(v2a.get());
if (v2arp)
{
return rpt_value_real::create(v1n * v2arp->query());
}
}
}
}
sub_context_ty sc;
sc.var_set_charstar("Name1", v1a->name());
sc.var_set_charstar("Name2", v2a->name());
nstring s(sc.subst_intl(i18n("illegal multiplication ($name1 * $name2)")));
return rpt_value_error::create(get_pos(), s);
}
rpt_expr_div::~rpt_expr_div()
{
}
rpt_expr_div::rpt_expr_div(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
append(lhs);
append(rhs);
}
rpt_expr::pointer
rpt_expr_div::create(const rpt_expr::pointer &lhs, const rpt_expr::pointer &rhs)
{
return pointer(new rpt_expr_div(lhs, rhs));
}
static rpt_value::pointer
div_by_zero_error(const rpt_expr::pointer &ep)
{
sub_context_ty sc;
nstring s(sc.subst_intl(i18n("division by zero")));
return rpt_value_error::create(ep->get_pos(), s);
}
rpt_value::pointer
rpt_expr_div::evaluate()
const
{
//
// evaluate the left hand side
//
trace(("div::evaluate()\n"));
assert(get_nchildren() == 2);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
return v1;
//
// coerce the left hand side to an arithmetic type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v1a = rpt_value::arithmetic(v1);
//
// evaluate the right hand side
//
rpt_value::pointer v2 = nth_child(1)->evaluate(true, true);
if (v2->is_an_error())
return v2;
//
// coerce the right hand side to an arithmetic type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v2a = rpt_value::arithmetic(v2);
//
// the type of the result depends on
// the types of the operands
//
{
rpt_value_integer *v1aip = dynamic_cast(v1a.get());
if (v1aip)
{
long v1n = v1aip->query();
{
rpt_value_integer *v2aip =
dynamic_cast(v2a.get());
if (v2aip)
{
long den = v2aip->query();
if (den == 0)
return div_by_zero_error(nth_child(1));
return rpt_value_integer::create(v1n / den);
}
}
{
rpt_value_real *v2arp =
dynamic_cast(v2a.get());
if (v2arp)
{
double den = v2arp->query();
if (den == 0)
return div_by_zero_error(nth_child(1));
return rpt_value_real::create(v1n / den);
}
}
}
}
{
rpt_value_real *v1arp = dynamic_cast(v1a.get());
if (v1arp)
{
double v1n = v1arp->query();
{
rpt_value_integer *v2aip =
dynamic_cast(v2a.get());
if (v2aip)
{
long den = v2aip->query();
if (den == 0)
return div_by_zero_error(nth_child(1));
return rpt_value_real::create(v1n / den);
}
}
{
rpt_value_real *v2arp =
dynamic_cast(v2a.get());
if (v2arp)
{
double den = v2arp->query();
if (den == 0)
return div_by_zero_error(nth_child(1));
return rpt_value_real::create(v1n / den);
}
}
}
}
sub_context_ty sc;
sc.var_set_charstar("Name1", v1a->name());
sc.var_set_charstar("Name2", v2a->name());
nstring s(sc.subst_intl(i18n("illegal division ($name1 / $name2)")));
return rpt_value_error::create(get_pos(), s);
}
rpt_expr_mod::~rpt_expr_mod()
{
}
rpt_expr_mod::rpt_expr_mod(const rpt_expr::pointer &lhs,
const rpt_expr::pointer &rhs)
{
append(lhs);
append(rhs);
}
rpt_expr::pointer
rpt_expr_mod::create(const rpt_expr::pointer &lhs, const rpt_expr::pointer &rhs)
{
return pointer(new rpt_expr_mod(lhs, rhs));
}
static rpt_value::pointer
mod_by_zero_error(const rpt_expr::pointer &ep)
{
sub_context_ty sc;
nstring s(sc.subst_intl(i18n("modulo by zero")));
return rpt_value_error::create(ep->get_pos(), s);
}
rpt_value::pointer
rpt_expr_mod::evaluate()
const
{
//
// evaluate the left hand side
//
trace(("mod::evaluate()\n"));
assert(get_nchildren() == 2);
rpt_value::pointer v1 = nth_child(0)->evaluate(true, true);
if (v1->is_an_error())
return v1;
//
// coerce the left hand side to an arithmetic type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v1a = rpt_value::arithmetic(v1);
//
// evaluate the right hand side
//
rpt_value::pointer v2 = nth_child(1)->evaluate(true, true);
if (v2->is_an_error())
return v2;
//
// coerce the right hand side to an arithmetic type
// (will not give error if can't, will copy instead)
//
rpt_value::pointer v2a = rpt_value::arithmetic(v2);
//
// the type of the result depends on
// the types of the operands
//
{
rpt_value_integer *v1aip = dynamic_cast(v1a.get());
if (v1aip)
{
long num = v1aip->query();
{
rpt_value_integer *v2aip =
dynamic_cast(v2a.get());
if (v2aip)
{
long den = v2aip->query();
if (den == 0)
return mod_by_zero_error(nth_child(1));
return rpt_value_integer::create(num % den);
}
}
{
rpt_value_real *v2arp =
dynamic_cast(v2a.get());
if (v2arp)
{
double den = v2arp->query();
if (den == 0)
return mod_by_zero_error(nth_child(1));
return rpt_value_real::create(fmod(num, den));
}
}
}
}
{
rpt_value_real *v1arp = dynamic_cast(v1a.get());
if (v1arp)
{
double num = v1arp->query();
{
rpt_value_integer *v2aip =
dynamic_cast(v2a.get());
if (v2aip)
{
long den = v2aip->query();
if (den == 0)
return mod_by_zero_error(nth_child(1));
return rpt_value_real::create(fmod(num, den));
}
}
{
rpt_value_real *v2arp =
dynamic_cast(v2a.get());
if (v2arp)
{
double den = v2arp->query();
if (den == 0)
return mod_by_zero_error(nth_child(1));
return rpt_value_real::create(fmod(num, den));
}
}
}
}
sub_context_ty sc;
sc.var_set_charstar("Name1", v1a->name());
sc.var_set_charstar("Name2", v2a->name());
// xgettext:no-c-format
nstring s(sc.subst_intl(i18n("illegal modulo ($name1 % $name2)")));
return rpt_value_error::create(get_pos(), s);
}
// vim: set ts=8 sw=4 et :