ferment-sys 0.2.14

Syntax tree morphing of FFI-compatible stuff
Documentation
use quote::ToTokens;
use syn::{Attribute, Fields, FieldsNamed, FieldsUnnamed, ItemEnum, ItemFn, ItemImpl, ItemStruct, ItemTrait, ItemType};
use syn::punctuated::Punctuated;
use syn::token::{Brace, Paren};
use crate::ast::Void;
use crate::composer::{AttrComposable, EnumComposer, EnumComposerLink, EnumVariantComposer, EnumVariantComposerLink, FFIAspect, FFIBindingsComposer, ImplComposer, ImplComposerLink, OpaqueStructComposer, OpaqueStructComposerLink, SigComposer, SigComposerLink, StructComposer, StructComposerLink, TraitComposer, TraitComposerLink, TypeAliasComposer, TypeAliasComposerLink};
use crate::context::{ScopeChain, ScopeContextLink};
use crate::ext::PunctuateOne;
use crate::lang::Specification;
use crate::presentable::{BindingPresentableContext, ScopeContextPresentable, SeqKind, Expression};
use crate::presentation::Name;

#[allow(unused)]
pub enum ItemComposerWrapper<SPEC>
    where SPEC: Specification + 'static {
    Enum(EnumComposerLink<SPEC>),
    EnumVariantNamed(EnumVariantComposerLink<SPEC, Brace>),
    EnumVariantUnnamed(EnumVariantComposerLink<SPEC, Paren>),
    EnumVariantUnit(EnumVariantComposerLink<SPEC, Void>),
    StructNamed(StructComposerLink<SPEC, Brace>),
    StructUnnamed(StructComposerLink<SPEC, Paren>),
    OpaqueStructNamed(OpaqueStructComposerLink<SPEC, Brace>),
    OpaqueStructUnnamed(OpaqueStructComposerLink<SPEC, Paren>),
    Sig(SigComposerLink<SPEC>),
    TypeAlias(TypeAliasComposerLink<SPEC, Paren>),
    Trait(TraitComposerLink<SPEC>),
    Impl(ImplComposerLink<SPEC>),
}



impl<SPEC> ItemComposerWrapper<SPEC>
    where SPEC: Specification<Expr=Expression<SPEC>, Name=Name<SPEC>>,
          SPEC::Expr: ScopeContextPresentable,
          Name<SPEC>: ToTokens {

    pub fn r#trait(item_trait: &ItemTrait, ty_context: SPEC::TYC, scope: &ScopeChain, context: &ScopeContextLink) -> Self {
        ItemComposerWrapper::Trait(TraitComposer::from_item_trait(item_trait, ty_context, scope, context))
    }
    pub fn r#impl(item_impl: &ItemImpl, ty_context: SPEC::TYC, scope: &ScopeChain, context: &ScopeContextLink) -> Self {
        ItemComposerWrapper::Impl(ImplComposer::from_item_impl(item_impl, ty_context, scope, context))
    }
    pub fn r#fn(item_fn: &ItemFn, ty_context: SPEC::TYC, context: &ScopeContextLink) -> Self {
        ItemComposerWrapper::Sig(SigComposer::from_item_fn(item_fn, ty_context, context))
    }
    pub fn r#enum(item_enum: &ItemEnum, ty_context: SPEC::TYC, context: &ScopeContextLink) -> Self {
        ItemComposerWrapper::<SPEC>::Enum(EnumComposer::<SPEC>::new(item_enum, ty_context, context))
    }
    pub fn variant(fields: &Fields, ty_context: SPEC::TYC, attrs: &[Attribute], context: &ScopeContextLink) -> Self {
        match fields {
            Fields::Unit =>
                ItemComposerWrapper::EnumVariantUnit(EnumVariantComposer::<SPEC, Void>::new(ty_context, attrs, &Punctuated::new(), context)),
            Fields::Unnamed(fields) =>
                ItemComposerWrapper::EnumVariantUnnamed(EnumVariantComposer::<SPEC, Paren>::new(ty_context, attrs, &fields.unnamed, context)),
            Fields::Named(fields) =>
                ItemComposerWrapper::EnumVariantNamed(EnumVariantComposer::<SPEC, Brace>::new(ty_context, attrs, &fields.named, context)),
        }
    }
    pub fn r#struct(item_struct: &ItemStruct, ty_context: SPEC::TYC, context: &ScopeContextLink) -> Self {
        let ItemStruct { attrs, fields: ref f, generics, .. } = item_struct;
        match f {
            Fields::Unnamed(ref fields) =>
                ItemComposerWrapper::StructUnnamed(StructComposer::<SPEC, Paren>::new(ty_context, attrs, &[], generics, &fields.unnamed, context)),
            Fields::Named(ref fields) =>
                ItemComposerWrapper::StructNamed(StructComposer::<SPEC, Brace>::new(ty_context, attrs, &[], generics, &fields.named, context)),
            Fields::Unit =>
                ItemComposerWrapper::StructNamed(StructComposer::<SPEC, Brace>::new(ty_context, attrs, &[], generics, &Punctuated::new(), context)),
        }
    }
    pub fn opaque_struct(item_struct: &ItemStruct, ty_context: SPEC::TYC, context: &ScopeContextLink) -> Self {
        let ItemStruct { attrs, fields: ref f, generics, .. } = item_struct;
        let lifetimes = vec![];
        match f {
            Fields::Unnamed(FieldsUnnamed { ref unnamed, .. }) =>
                ItemComposerWrapper::OpaqueStructUnnamed(
                    OpaqueStructComposer::<SPEC, Paren>::new(ty_context, attrs, &lifetimes, generics, unnamed, context)),
            Fields::Named(FieldsNamed { ref named, .. }) =>
                ItemComposerWrapper::OpaqueStructNamed(
                    OpaqueStructComposer::<SPEC, Brace>::new(ty_context, attrs, &lifetimes, generics, named, context)),
            Fields::Unit =>
                ItemComposerWrapper::OpaqueStructNamed(
                    OpaqueStructComposer::<SPEC, Brace>::new(ty_context, attrs, &lifetimes, generics, &Punctuated::new(), context))
        }
    }

    pub fn callback(item_type: &ItemType, ty_context: SPEC::TYC, scope_context: &ScopeContextLink) -> Self {
        Self::Sig(SigComposer::from_type_bare_fn(ty_context, &item_type.generics, &[], &item_type.attrs, scope_context))
    }
    pub fn type_alias(item_type: &ItemType, ty_context: SPEC::TYC, scope_context: &ScopeContextLink) -> Self {
        Self::TypeAlias(TypeAliasComposer::new(ty_context, &item_type.attrs, &[], &item_type.generics, &crate::ast::pub_unnamed_field(*item_type.ty.clone()).punctuate_one(), scope_context))
    }

    pub fn compose_aspect(&self, aspect: FFIAspect) -> SeqKind<SPEC> {
        match self {
            ItemComposerWrapper::EnumVariantNamed(composer) =>
                composer.borrow().composer.borrow().compose_aspect(aspect),
            ItemComposerWrapper::EnumVariantUnnamed(composer) =>
                composer.borrow().composer.borrow().compose_aspect(aspect),
            ItemComposerWrapper::EnumVariantUnit(composer) =>
                composer.borrow().composer.borrow().compose_aspect(aspect),
            ItemComposerWrapper::StructNamed(composer) =>
                composer.borrow().composer.borrow().compose_aspect(aspect),
            ItemComposerWrapper::StructUnnamed(composer) =>
                composer.borrow().composer.borrow().compose_aspect(aspect),
            ItemComposerWrapper::TypeAlias(composer) =>
                composer.borrow().composer.borrow().compose_aspect(aspect),
            _ => SeqKind::Empty
        }
    }
    pub fn compose_ctor(&self) -> Option<BindingPresentableContext<SPEC>> {
        match self {
            ItemComposerWrapper::EnumVariantNamed(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            ItemComposerWrapper::EnumVariantUnnamed(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            ItemComposerWrapper::EnumVariantUnit(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            ItemComposerWrapper::StructNamed(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            ItemComposerWrapper::StructUnnamed(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            ItemComposerWrapper::OpaqueStructUnnamed(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            ItemComposerWrapper::OpaqueStructNamed(composer) =>
                composer.borrow().composer.borrow().bindings_composer.as_ref().map(FFIBindingsComposer::compose_ctor),
            _ => None,
        }
    }
}

impl<SPEC> AttrComposable<SPEC::Attr> for ItemComposerWrapper<SPEC>
    where SPEC: Specification<Expr=Expression<SPEC>>,
          SPEC::Expr: ScopeContextPresentable {
    fn compose_attributes(&self) -> SPEC::Attr {
        match self {
            ItemComposerWrapper::Enum(composer) =>
                composer.borrow().compose_attributes(),
            ItemComposerWrapper::EnumVariantUnit(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::EnumVariantNamed(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::StructNamed(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::EnumVariantUnnamed(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::StructUnnamed(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::OpaqueStructUnnamed(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::OpaqueStructNamed(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::Sig(composer) =>
                composer.borrow().compose_attributes(),
            ItemComposerWrapper::TypeAlias(composer) =>
                composer.borrow().composer.borrow().compose_attributes(),
            ItemComposerWrapper::Trait(composer) =>
                composer.borrow().compose_attributes(),
            ItemComposerWrapper::Impl(composer) =>
                composer.borrow().compose_attributes(),
        }
    }
}