use crate::{
inferred_type::InferredType,
keyword,
pretty::{PrettyPrint, Printer},
scopes::ScopeId,
};
use super::Visit;
use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, quote};
use syn::{
Ident,
parse::{Parse, ParseStream},
spanned::Spanned,
};
#[allow(unused)]
pub enum Lit {
Int(syn::LitInt),
Float(syn::LitFloat),
Str(syn::LitStr),
Bool(syn::LitBool),
Null(keyword::null),
}
impl Lit {
#[must_use]
pub fn infer_name(&self) -> Option<&Ident> {
None
}
#[must_use]
pub fn infer_type(&self, _scope_id: ScopeId) -> Option<InferredType<'_>> {
None
}
#[must_use]
pub fn span(&self) -> Span {
match self {
Self::Int(inner) => inner.span(),
Self::Float(inner) => inner.span(),
Self::Str(inner) => inner.span(),
Self::Bool(inner) => inner.span(),
Self::Null(inner) => inner.span(),
}
}
}
pub fn visit_lit<'a>(_visit: &mut (impl Visit<'a> + ?Sized), _lit: &'a Lit) {}
impl Parse for Lit {
fn parse(input: ParseStream) -> syn::Result<Self> {
if input.peek(keyword::null) {
return Ok(Self::Null(input.parse()?));
}
let lit = input.parse::<syn::Lit>()?;
Ok(match lit {
syn::Lit::Int(inner) => Self::Int(inner),
syn::Lit::Float(inner) => Self::Float(inner),
syn::Lit::Str(inner) => Self::Str(inner),
syn::Lit::Bool(inner) => Self::Bool(inner),
_ => {
return Err(syn::Error::new(
lit.span(),
format!("unsupported literal type `{}`", lit.to_token_stream()),
));
}
})
}
}
impl ToTokens for Lit {
fn to_tokens(&self, tokens: &mut TokenStream) {
let token_stream = match self {
Self::Int(inner) => quote! { ::kosame::repr::expr::Lit::Int(#inner as i64) },
Self::Float(inner) => quote! { ::kosame::repr::expr::Lit::Float(#inner as f64) },
Self::Str(inner) => quote! { ::kosame::repr::expr::Lit::Str(#inner) },
Self::Bool(inner) => quote! { ::kosame::repr::expr::Lit::Bool(#inner) },
Self::Null(_) => quote! { ::kosame::repr::expr::Lit::Null },
};
token_stream.to_tokens(tokens);
}
}
impl PrettyPrint for Lit {
fn pretty_print(&self, printer: &mut Printer) {
match self {
Self::Int(inner) => inner.pretty_print(printer),
Self::Float(inner) => inner.pretty_print(printer),
Self::Str(inner) => inner.pretty_print(printer),
Self::Bool(inner) => inner.pretty_print(printer),
Self::Null(inner) => inner.pretty_print(printer),
}
}
}