ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use std::fmt::{Display, Formatter};
use std::marker::PhantomData;
use proc_macro2::Ident;
use quote::{format_ident, ToTokens};
use syn::__private::TokenStream2;
use syn::{parse_quote, Expr, Pat, Path, Type};
use crate::composable::FieldComposer;
use crate::ext::{ToPath, ToType};
use crate::kind::FieldTypeKind;
use crate::lang::{FromDictionary, NameComposable, Specification};
use crate::presentation::{DictionaryExpr, DictionaryName};


#[derive(Clone, Debug, Default)]
pub enum Name<SPEC> where SPEC: Specification {
    #[default]
    Empty,
    Expr(Expr),
    UnnamedArg(usize),
    Index(usize),
    Constructor(Type),
    Destructor(Type),
    Read(Type),
    Write(Type),
    GetValueAtIndex(Type),
    SetValueAtIndex(Type),
    GetKeyByValue(Type),
    SetKeyForValue(Type),
    GetValueByKey(Type),
    SetValueForKey(Type),
    Dictionary(DictionaryName),
    DictionaryExpr(DictionaryExpr),
    Optional(Option<Ident>),
    UnnamedStructFieldsComp(Type, usize),
    TraitObj(Ident),
    TraitImplVtable(Ident, Ident),
    TraitImplVtableFn(Ident, Ident),
    TraitFn(Type, Type),
    TraitDestructor(Type, Type),
    Vtable(Ident),
    ModFn(Path),
    VTableInnerFn(Ident),
    Getter(Path, TokenStream2),
    Setter(Path, TokenStream2),
    Ident(Ident),
    Pat(Pat),
    Underscore,
    EnumTag(Ident),
    EnumVariantBody(Ident),
    _Phantom(PhantomData<SPEC>),
}

impl<SPEC> FromDictionary for Name<SPEC>
    where SPEC: Specification {
    fn dictionary_name(dictionary: DictionaryName) -> Self {
        Name::Dictionary(dictionary)
    }
}

impl<SPEC> ToType for Name<SPEC>
    where SPEC: Specification,
          Self: ToTokens {
    fn to_type(&self) -> Type {
        parse_quote!(#self)
    }
}
impl<SPEC> ToPath for Name<SPEC>
    where SPEC: Specification,
          Self: ToTokens {
    fn to_path(&self) -> Path {
        parse_quote!(#self)
    }
}


impl<SPEC> Display for Name<SPEC>
    where SPEC: Specification,
          Self: ToTokens {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str(format!("Name({})", self.to_token_stream()).as_str())
    }
}

impl<SPEC> Name<SPEC>
    where SPEC: Specification<Name=Self>,
          Self: ToTokens {
    
    
    pub fn o() -> Self {
        Self::Dictionary(DictionaryName::O)
    }
    pub fn obj() -> Self {
        Self::Dictionary(DictionaryName::Obj)
    }
    pub fn value() -> Self {
        Self::Dictionary(DictionaryName::Value)
    }
    pub fn ok() -> Self {
        Self::Dictionary(DictionaryName::Ok)
    }
    pub fn error() -> Self {
        Self::Dictionary(DictionaryName::Error)
    }
    pub fn self_() -> Self {
        Self::Dictionary(DictionaryName::Self_)
    }
    pub fn keys() -> Self {
        Self::Dictionary(DictionaryName::Keys)
    }
    pub fn values() -> Self {
        Self::Dictionary(DictionaryName::Values)
    }
    pub fn count() -> Self {
        Self::Dictionary(DictionaryName::Count)
    }
    pub fn caller() -> Self {
        Self::Dictionary(DictionaryName::Caller)
    }
    pub fn destructor() -> Self {
        Self::Dictionary(DictionaryName::Destructor)
    }
    pub fn ctor(ty: &Type) -> Self {
        Self::Constructor(ty.clone())
    }
    pub fn getter(path: Path, field_name: &TokenStream2) -> Self {
        Self::Getter(path, field_name.clone())
    }
    pub fn setter(path: Path, field_name: &TokenStream2) -> Self {
        Self::Setter(path, field_name.clone())
    }

    pub fn pat_tokens<T: ToTokens>(tokens: T) -> Self {
        Self::Pat(Pat::Verbatim(tokens.to_token_stream()))
    }
    pub fn self_prop<T: ToTokens>(field_name: T) -> Self {
        Self::DictionaryExpr(DictionaryExpr::self_prop(field_name))
    }

    pub fn pat(pat: &Pat) -> Self {
        Self::Pat(pat.clone())
    }

    pub fn anonymous(&self) -> Ident {
        format_ident!("o_{}", self.to_token_stream().to_string())
    }

    pub fn field_composer(&self, kind: FieldTypeKind<SPEC>) -> FieldComposer<SPEC> {
        FieldComposer::<SPEC>::named_no_attrs(self.clone(), kind)
    }
}

impl<SPEC> NameComposable<SPEC> for Name<SPEC>
    where SPEC: Specification<Name=Name<SPEC>> {
    fn ident(ident: Ident) -> Self {
        Self::Ident(ident)
    }

    fn index(ident: usize) -> Self {
        Self::Index(ident)
    }

    fn unnamed_arg(index: usize) -> Self {
        Self::UnnamedArg(index)
    }
}