use std::borrow::{Borrow, Cow};
use std::fmt::{self, Debug, Display};
use crate::common::errors::*;
use crate::konst2::{FloatingConst, IntegerConst};
use crate::ty2::Type;
pub trait Const2<'t>: Debug + Display {
fn ty(&self) -> &'t Type;
fn into_owned(self) -> OwnedConst<'t>;
fn to_owned(&self) -> OwnedConst<'t>;
fn as_any<'r>(&'r self) -> AnyConst<'r, 't>;
fn cast(&self, ty: &'t Type) -> Result<Cow<Const2<'t> + 't>, ConstError>;
}
impl<'t> ToOwned for Const2<'t> + 't {
type Owned = OwnedConst<'t>;
fn to_owned(&self) -> OwnedConst<'t> {
Const2::to_owned(self)
}
}
#[derive(Debug, Clone)]
pub enum ConstError {
OutOfRange,
}
impl EmitError for ConstError {
type Output = ();
fn emit<C: DiagEmitter>(self, ctx: C) {
match self {
ConstError::OutOfRange => ctx.emit(DiagBuilder2::error("constant value out of range")),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum AnyConst<'r, 't: 'r> {
Integer(&'r IntegerConst<'t>),
Floating(&'r FloatingConst<'t>),
}
impl<'r, 't> Display for AnyConst<'r, 't> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
AnyConst::Integer(t) => Display::fmt(t, f),
AnyConst::Floating(t) => Display::fmt(t, f),
}
}
}
impl<'r, 't> Debug for AnyConst<'r, 't> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
AnyConst::Integer(t) => Debug::fmt(t, f),
AnyConst::Floating(t) => Debug::fmt(t, f),
}
}
}
impl<'r, 't, T: Const2<'t>> From<&'r T> for AnyConst<'r, 't> {
fn from(konst: &'r T) -> AnyConst<'r, 't> {
konst.as_any()
}
}
#[allow(unreachable_patterns)]
impl<'r, 't> AnyConst<'r, 't> {
pub fn as_const(self) -> &'r Const2<'t> {
match self {
AnyConst::Integer(k) => k,
AnyConst::Floating(k) => k,
}
}
pub fn as_integer(self) -> Option<&'r IntegerConst<'t>> {
match self {
AnyConst::Integer(k) => Some(k),
_ => None,
}
}
pub fn as_floating(self) -> Option<&'r FloatingConst<'t>> {
match self {
AnyConst::Floating(k) => Some(k),
_ => None,
}
}
pub fn unwrap_integer(self) -> &'r IntegerConst<'t> {
self.as_integer().expect("constant is not an integer")
}
pub fn unwrap_floating(self) -> &'r FloatingConst<'t> {
self.as_floating().expect("constant is not a float")
}
}
#[derive(Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum OwnedConst<'t> {
Integer(IntegerConst<'t>),
Floating(FloatingConst<'t>),
}
impl<'t> Borrow<Const2<'t> + 't> for OwnedConst<'t> {
fn borrow(&self) -> &(Const2<'t> + 't) {
match *self {
OwnedConst::Integer(ref k) => k,
OwnedConst::Floating(ref k) => k,
}
}
}
impl<'t> Display for OwnedConst<'t> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
OwnedConst::Integer(ref t) => Display::fmt(t, f),
OwnedConst::Floating(ref t) => Display::fmt(t, f),
}
}
}
impl<'t> Debug for OwnedConst<'t> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
OwnedConst::Integer(ref t) => Debug::fmt(t, f),
OwnedConst::Floating(ref t) => Debug::fmt(t, f),
}
}
}
impl<'t, T: Const2<'t>> From<T> for OwnedConst<'t> {
fn from(konst: T) -> OwnedConst<'t> {
konst.to_owned()
}
}