use proc_macro2::TokenStream;
use quote::{ToTokens, quote};
use syn::{
Ident,
parse::{Parse, ParseStream},
};
use crate::{inferred_type::InferredType, keyword, scopes::ScopeId};
use super::{Expr, Visitor};
pub struct Unary {
pub op: UnaryOp,
pub operand: Box<Expr>,
}
impl Unary {
pub fn new(op: UnaryOp, operand: Expr) -> Self {
Self {
op,
operand: Box::new(operand),
}
}
pub fn accept<'a>(&'a self, visitor: &mut impl Visitor<'a>) {
self.operand.accept(visitor);
}
pub fn infer_name(&self) -> Option<&Ident> {
None
}
pub fn infer_type(&self, _scope_id: ScopeId) -> Option<InferredType<'_>> {
None
}
}
impl ToTokens for Unary {
fn to_tokens(&self, tokens: &mut TokenStream) {
let op = &self.op;
let operand = &self.operand;
quote! {
::kosame::repr::expr::Unary::new(#op, &#operand)
}
.to_tokens(tokens);
}
}
#[allow(unused)]
pub enum UnaryOp {
Not(keyword::not),
}
impl UnaryOp {
pub fn peek(input: ParseStream) -> bool {
input.fork().parse::<UnaryOp>().is_ok()
}
pub fn precedence(&self) -> u32 {
match self {
Self::Not(_) => 3,
}
}
}
impl Parse for UnaryOp {
fn parse(input: ParseStream) -> syn::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(keyword::not) {
return Ok(Self::Not(input.parse()?));
}
Err(lookahead.error())
}
}
impl ToTokens for UnaryOp {
fn to_tokens(&self, tokens: &mut TokenStream) {
macro_rules! branches {
($($variant:ident)*) => {
match self {
$(Self::$variant(..) => quote! { ::kosame::repr::expr::UnaryOp::$variant }.to_tokens(tokens)),*
}
};
}
branches!(Not);
}
}