use crate::ir::{Comptime, Shape, Type, TypeKind, ValueVariant};
use crate::value::{Value, string_to_byte_value};
use std::fmt;
use veryl_parser::resource_table::{self, StrId};
use veryl_parser::token_range::TokenRange;
use veryl_parser::veryl_grammar_trait as syntax_tree;
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Literal {
Value(Value),
Type(TypeLiteral),
Boolean(bool),
String(StrId),
}
impl Literal {
pub fn eval_comptime(&self, token: TokenRange) -> Comptime {
let (value, r#type) = match self {
Literal::Value(x) => {
let r#type = x.to_ir_type();
(ValueVariant::Numeric(x.clone()), r#type)
}
Literal::Type(x) => {
let r#type = {
let mut t = Type::new(TypeKind::Type);
t.set_concrete_width(Shape::new(vec![Some(1)]));
t
};
(ValueVariant::Type(x.into()), r#type)
}
Literal::Boolean(x) => {
let value = Value::new((*x).into(), 1, false);
let r#type = value.to_ir_type();
(ValueVariant::Numeric(value), r#type)
}
Literal::String(x) => {
let text = resource_table::get_str_value(*x).unwrap_or_default();
let value = string_to_byte_value(&text);
let width = value.width() as usize;
let r#type = {
let mut t = Type::new(TypeKind::String);
t.set_concrete_width(Shape::new(vec![Some(width)]));
t
};
(ValueVariant::Numeric(value), r#type)
}
};
Comptime {
value,
r#type,
is_const: true,
is_global: true,
token,
..Default::default()
}
}
}
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Literal::Value(x) => format!("{x:x}").fmt(f),
Literal::Type(x) => x.fmt(f),
Literal::Boolean(x) => x.fmt(f),
Literal::String(x) => x.fmt(f),
}
}
}
impl Literal {}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum TypeLiteral {
Bit,
BBool,
LBool,
Clock,
ClockPosedge,
ClockNegedge,
F32,
F64,
I8,
I16,
I32,
I64,
Logic,
Reset,
ResetAsyncHigh,
ResetAsyncLow,
ResetSyncHigh,
ResetSyncLow,
String,
U8,
U16,
U32,
U64,
}
impl TypeLiteral {
pub fn to_sv_string(&self) -> String {
let text = match self {
TypeLiteral::Bit => "bit",
TypeLiteral::BBool => "bit",
TypeLiteral::LBool => "logic",
TypeLiteral::Clock => "logic",
TypeLiteral::ClockPosedge => "logic",
TypeLiteral::ClockNegedge => "logic",
TypeLiteral::F32 => "shortreal",
TypeLiteral::F64 => "real",
TypeLiteral::I8 => "byte",
TypeLiteral::I16 => "shortint",
TypeLiteral::I32 => "int",
TypeLiteral::I64 => "longint",
TypeLiteral::Logic => "logic",
TypeLiteral::Reset => "logic",
TypeLiteral::ResetAsyncHigh => "logic",
TypeLiteral::ResetAsyncLow => "logic",
TypeLiteral::ResetSyncHigh => "logic",
TypeLiteral::ResetSyncLow => "logic",
TypeLiteral::String => "string",
TypeLiteral::U8 => "byte unsigned",
TypeLiteral::U16 => "shortint unsigned",
TypeLiteral::U32 => "int unsigned",
TypeLiteral::U64 => "longint unsigned",
};
text.to_string()
}
}
impl fmt::Display for TypeLiteral {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TypeLiteral::Bit => "bit".fmt(f),
TypeLiteral::BBool => "bbool".fmt(f),
TypeLiteral::LBool => "lbool".fmt(f),
TypeLiteral::Clock => "clock".fmt(f),
TypeLiteral::ClockPosedge => "clock_posedge".fmt(f),
TypeLiteral::ClockNegedge => "clock_negedge".fmt(f),
TypeLiteral::F32 => "f32".fmt(f),
TypeLiteral::F64 => "f64".fmt(f),
TypeLiteral::I8 => "i8".fmt(f),
TypeLiteral::I16 => "i16".fmt(f),
TypeLiteral::I32 => "i32".fmt(f),
TypeLiteral::I64 => "i64".fmt(f),
TypeLiteral::Logic => "logic".fmt(f),
TypeLiteral::Reset => "reset".fmt(f),
TypeLiteral::ResetAsyncHigh => "reset_async_high".fmt(f),
TypeLiteral::ResetAsyncLow => "reset_async_low".fmt(f),
TypeLiteral::ResetSyncHigh => "reset_sync_high".fmt(f),
TypeLiteral::ResetSyncLow => "reset_sync_low".fmt(f),
TypeLiteral::String => "string".fmt(f),
TypeLiteral::U8 => "u8".fmt(f),
TypeLiteral::U16 => "u16".fmt(f),
TypeLiteral::U32 => "u32".fmt(f),
TypeLiteral::U64 => "u64".fmt(f),
}
}
}
macro_rules! impl_to_literal {
($x:ident) => {
impl From<&syntax_tree::$x> for Literal {
fn from(_: &syntax_tree::$x) -> Self {
Self::Type(TypeLiteral::$x)
}
}
};
}
macro_rules! impl_to_type_literal {
($x:ident) => {
impl From<&syntax_tree::$x> for TypeLiteral {
fn from(_: &syntax_tree::$x) -> Self {
Self::$x
}
}
};
}
impl_to_literal!(Bit);
impl_to_literal!(BBool);
impl_to_literal!(LBool);
impl_to_literal!(Clock);
impl_to_literal!(ClockPosedge);
impl_to_literal!(ClockNegedge);
impl_to_literal!(F32);
impl_to_literal!(F64);
impl_to_literal!(I8);
impl_to_literal!(I16);
impl_to_literal!(I32);
impl_to_literal!(I64);
impl_to_literal!(Logic);
impl_to_literal!(Reset);
impl_to_literal!(ResetAsyncHigh);
impl_to_literal!(ResetAsyncLow);
impl_to_literal!(ResetSyncHigh);
impl_to_literal!(ResetSyncLow);
impl_to_literal!(U8);
impl_to_literal!(U16);
impl_to_literal!(U32);
impl_to_literal!(U64);
impl_to_type_literal!(Bit);
impl_to_type_literal!(BBool);
impl_to_type_literal!(LBool);
impl_to_type_literal!(Clock);
impl_to_type_literal!(ClockPosedge);
impl_to_type_literal!(ClockNegedge);
impl_to_type_literal!(F32);
impl_to_type_literal!(F64);
impl_to_type_literal!(I8);
impl_to_type_literal!(I16);
impl_to_type_literal!(I32);
impl_to_type_literal!(I64);
impl_to_type_literal!(Logic);
impl_to_type_literal!(Reset);
impl_to_type_literal!(ResetAsyncHigh);
impl_to_type_literal!(ResetAsyncLow);
impl_to_type_literal!(ResetSyncHigh);
impl_to_type_literal!(ResetSyncLow);
impl_to_type_literal!(U8);
impl_to_type_literal!(U16);
impl_to_type_literal!(U32);
impl_to_type_literal!(U64);
impl From<&syntax_tree::Strin> for Literal {
fn from(_: &syntax_tree::Strin) -> Self {
Self::Type(TypeLiteral::String)
}
}
impl From<&syntax_tree::Strin> for TypeLiteral {
fn from(_: &syntax_tree::Strin) -> Self {
Self::String
}
}