Initial check in of support for upcasting during function invocation. No examples or tests are checked in yet. Some reorg was necessary to get things compiling in the right order. Is not currently thread safe and probably does not work properly across module boundaries

This commit is contained in:
Jason Turner
2010-08-02 01:38:25 +00:00
parent b971ee44ad
commit edee892cad
12 changed files with 873 additions and 526 deletions

View File

@@ -0,0 +1,262 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2010, Jonathan Turner (jturner@minnow-lang.org)
// and Jason Turner (lefticus@gmail.com)
// http://www.chaiscript.com
#ifndef __boxed_pod_value_hpp__
#define __boxed_pod_value_hpp__
#include "type_info.hpp"
#include "boxed_value.hpp"
#include "boxed_cast_helper.hpp"
#include <boost/any.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer_traits.hpp>
namespace chaiscript
{
/**
* Object which attempts to convert a Boxed_Value into a generic
* POD type and provide generic POD type operations
*/
struct Boxed_POD_Value
{
Boxed_POD_Value(const Boxed_Value &v)
: d(0), i(0), m_isfloat(false)
{
if (v.get_type_info().is_undef())
{
throw boost::bad_any_cast();
}
const Type_Info &inp_ = v.get_type_info();
if (inp_ == typeid(double))
{
d = boxed_cast<double>(v);
m_isfloat = true;
} else if (inp_ == typeid(float)) {
d = boxed_cast<float>(v);
m_isfloat = true;
} else if (inp_ == typeid(bool)) {
i = boxed_cast<bool>(v);
} else if (inp_ == typeid(char)) {
i = boxed_cast<char>(v);
} else if (inp_ == typeid(int)) {
i = boxed_cast<int>(v);
} else if (inp_ == typeid(unsigned int)) {
i = boxed_cast<unsigned int>(v);
} else if (inp_ == typeid(long)) {
i = boxed_cast<long>(v);
} else if (inp_ == typeid(unsigned long)) {
i = boxed_cast<unsigned long>(v);
} else if (inp_ == typeid(boost::int8_t)) {
i = boxed_cast<boost::int8_t>(v);
} else if (inp_ == typeid(boost::int16_t)) {
i = boxed_cast<boost::int16_t>(v);
} else if (inp_ == typeid(boost::int32_t)) {
i = boxed_cast<boost::int32_t>(v);
} else if (inp_ == typeid(boost::int64_t)) {
i = boxed_cast<boost::int64_t>(v);
} else if (inp_ == typeid(boost::uint8_t)) {
i = boxed_cast<boost::uint8_t>(v);
} else if (inp_ == typeid(boost::uint16_t)) {
i = boxed_cast<boost::uint16_t>(v);
} else if (inp_ == typeid(boost::uint32_t)) {
i = boxed_cast<boost::uint32_t>(v);
} else {
throw boost::bad_any_cast();
}
}
bool operator==(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i);
}
bool operator<(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) < ((r.m_isfloat)?r.d:r.i);
}
bool operator>(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) > ((r.m_isfloat)?r.d:r.i);
}
bool operator>=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) >= ((r.m_isfloat)?r.d:r.i);
}
bool operator<=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) <= ((r.m_isfloat)?r.d:r.i);
}
bool operator!=(const Boxed_POD_Value &r) const
{
return ((m_isfloat)?d:i) != ((r.m_isfloat)?r.d:r.i);
}
Boxed_Value operator+(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i + r.i);
}
return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator-(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i - r.i);
}
return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator&(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i & r.i);
}
throw bad_boxed_cast("& only valid for integer types");
}
Boxed_Value operator^(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i ^ r.i);
}
throw bad_boxed_cast("^ only valid for integer types");
}
Boxed_Value operator|(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return Boxed_Value(i | r.i);
}
throw bad_boxed_cast("| only valid for integer types");
}
Boxed_Value operator/(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i / r.i);
}
return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator<<(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i << r.i);
}
throw bad_boxed_cast("<< only valid for integer types");
}
Boxed_Value operator*(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i * r.i);
}
return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i));
}
Boxed_Value operator%(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i % r.i);
}
throw bad_boxed_cast("% only valid for integer types");
}
Boxed_Value operator>>(const Boxed_POD_Value &r) const
{
if (!m_isfloat && !r.m_isfloat)
{
return smart_size(i >> r.i);
}
throw bad_boxed_cast(">> only valid for integer types");
}
Boxed_Value smart_size(boost::int64_t i) const
{
if (i < boost::integer_traits<int>::const_min
|| i > boost::integer_traits<int>::const_max)
{
return Boxed_Value(i);
} else {
return Boxed_Value(static_cast<int>(i));
}
}
double d;
boost::int64_t i;
bool m_isfloat;
};
namespace detail
{
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<>
struct Cast_Helper<Boxed_POD_Value>
{
typedef Boxed_POD_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_POD_Value(ob);
}
};
/**
* Cast_Helper for converting from Boxed_Value to Boxed_POD_Value
*/
template<>
struct Cast_Helper<const Boxed_POD_Value &>
{
typedef Boxed_POD_Value Result_Type;
static Result_Type cast(const Boxed_Value &ob)
{
return Boxed_POD_Value(ob);
}
};
}
}
#endif