pub use crate::hir::Dir;
use crate::score::TypeDeclRef;
use crate::ty::*;
use num::BigInt;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Const {
Null,
Int(ConstInt),
Float(ConstFloat),
Enum(ConstEnum),
IntRange(ConstIntRange),
FloatRange(ConstFloatRange),
}
impl Const {
pub fn negate(self) -> Const {
match self {
Const::Null => panic!("cannot negate null"),
Const::Int(c) => Const::Int(c.negate()),
Const::Float(c) => Const::Float(c.negate()),
Const::Enum(_) => panic!("cannot negate enumeration literal"),
Const::IntRange(_) => panic!("cannot negate integer range"),
Const::FloatRange(_) => panic!("cannot negate float range"),
}
}
pub fn kind_desc(&self) -> &'static str {
match *self {
Const::Null => "null",
Const::Int(_) => "integer",
Const::Float(_) => "float",
Const::Enum(_) => "enumeration literal",
Const::IntRange(_) => "integer range",
Const::FloatRange(_) => "float range",
}
}
}
impl From<ConstInt> for Const {
fn from(k: ConstInt) -> Const {
Const::Int(k)
}
}
impl From<ConstFloat> for Const {
fn from(k: ConstFloat) -> Const {
Const::Float(k)
}
}
impl From<ConstEnum> for Const {
fn from(k: ConstEnum) -> Const {
Const::Enum(k)
}
}
impl From<ConstIntRange> for Const {
fn from(k: ConstIntRange) -> Const {
Const::IntRange(k)
}
}
impl From<ConstFloatRange> for Const {
fn from(k: ConstFloatRange) -> Const {
Const::FloatRange(k)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstInt {
pub ty: Option<IntTy>,
pub value: BigInt,
}
impl ConstInt {
pub fn new(ty: Option<IntTy>, value: BigInt) -> ConstInt {
ConstInt {
ty: ty,
value: value,
}
}
pub fn negate(self) -> ConstInt {
ConstInt::new(self.ty, -self.value)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstFloat {}
impl ConstFloat {
pub fn negate(self) -> ConstFloat {
ConstFloat {}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstEnum {
pub decl: TypeDeclRef,
pub index: usize,
}
impl ConstEnum {
pub fn new(decl: TypeDeclRef, index: usize) -> ConstEnum {
ConstEnum {
decl: decl,
index: index,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstRange<T: fmt::Display + fmt::Debug> {
pub dir: Dir,
pub left_bound: T,
pub right_bound: T,
}
impl<T> ConstRange<T>
where
T: fmt::Display + fmt::Debug,
{
pub fn new(dir: Dir, left_bound: T, right_bound: T) -> ConstRange<T> {
ConstRange {
dir: dir,
left_bound: left_bound,
right_bound: right_bound,
}
}
}
pub type ConstIntRange = ConstRange<ConstInt>;
pub type ConstFloatRange = ConstRange<ConstFloat>;
impl fmt::Display for Const {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Const::Null => write!(f, "null"),
Const::Int(ref k) => k.fmt(f),
Const::Float(ref k) => k.fmt(f),
Const::Enum(ref k) => k.fmt(f),
Const::IntRange(ref k) => k.fmt(f),
Const::FloatRange(ref k) => k.fmt(f),
}
}
}
impl fmt::Display for ConstInt {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.value.fmt(f)
}
}
impl fmt::Display for ConstEnum {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<enum>")
}
}
impl fmt::Display for ConstFloat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<float>")
}
}
impl<T> fmt::Display for ConstRange<T>
where
T: fmt::Display + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {} {}", self.left_bound, self.dir, self.right_bound)
}
}