use crate::proc_macro::TokenStream;
use crate::{
kparser::{DummyTracer, KParserError},
kproc_macros::KTokenStream,
proc_macro::TokenTree,
};
use std::collections::HashMap;
use std::fmt::Display;
use super::{
fmt::{fmt_generics, fmt_ty},
kimpl::parse_impl,
kstruct::parse_struct,
ktrait::parse_trait,
};
pub trait TopLevelAST {
fn span(&self) -> TokenTree;
fn is_trait(&self) -> bool {
false
}
fn is_struct(&self) -> bool {
false
}
fn is_impl(&self) -> bool {
false
}
fn is_fn(&self) -> bool {
false
}
}
pub enum TopLevelNode {
Struct(StructToken),
Trait(TraitToken),
Impl(ImplToken),
Fn(MethodDeclToken),
}
impl Display for TopLevelNode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Impl(node) => write!(f, "{node}"),
Self::Struct(node) => write!(f, "{node}"),
Self::Trait(node) => write!(f, "{node}"),
Self::Fn(node) => write!(f, "{node}"),
}
}
}
impl From<StructToken> for TopLevelNode {
fn from(value: StructToken) -> Self {
TopLevelNode::Struct(value)
}
}
impl From<ImplToken> for TopLevelNode {
fn from(value: ImplToken) -> Self {
TopLevelNode::Impl(value)
}
}
impl From<TraitToken> for TopLevelNode {
fn from(value: TraitToken) -> Self {
TopLevelNode::Trait(value)
}
}
impl From<MethodDeclToken> for TopLevelNode {
fn from(value: MethodDeclToken) -> Self {
TopLevelNode::Fn(value)
}
}
#[derive(Debug)]
pub struct StructToken {
pub attrs: HashMap<String, AttrToken>,
pub visibility: Option<TokenTree>,
pub name: TokenTree,
pub fields: Vec<FieldToken>,
pub generics: Option<GenericParams>,
}
impl TopLevelAST for StructToken {
fn span(&self) -> TokenTree {
self.name.clone()
}
fn is_struct(&self) -> bool {
true
}
}
impl Default for StructToken {
fn default() -> Self {
panic!()
}
}
impl TryFrom<&TokenStream> for StructToken {
type Error = KParserError;
fn try_from(value: &TokenStream) -> Result<Self, Self::Error> {
let mut stream = KTokenStream::new(value);
parse_struct(&mut stream, &DummyTracer {})
}
}
impl Display for StructToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "")
}
}
#[derive(Debug, Clone)]
pub struct GenericParams {
pub params: Vec<GenericParam>,
}
#[derive(Debug, Clone)]
pub enum GenericParam {
LifetimeParam(LifetimeParam),
TypeParam(TyToken),
Bounds(Bound), }
impl GenericParam {
pub fn add_bound(&mut self, bound: Bound) {
match self {
Self::TypeParam(param) => param.bounds.push(bound),
Self::LifetimeParam(param) => param.bounds.push(bound),
Self::Bounds(params) => params.add_bound(bound),
}
}
}
impl Display for GenericParam {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::LifetimeParam(param) => write!(f, "{param}"),
Self::TypeParam(param) => write!(f, "{param}"),
Self::Bounds(bounds) => write!(f, "{bounds}"),
}
}
}
#[derive(Clone, Debug)]
pub enum Bound {
Lifetime(LifetimeParam),
Trait(TypeParam),
}
impl Bound {
pub fn add_bound(&mut self, bound: Bound) {
match self {
Self::Trait(param) => param.bounds.push(bound),
Self::Lifetime(param) => param.bounds.push(bound),
}
}
}
impl std::fmt::Display for Bound {
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
unimplemented!()
}
}
#[derive(Debug, Clone)]
pub struct LifetimeParam {
pub lifetime_or_label: TokenTree,
pub bounds: Vec<Bound>,
}
impl std::fmt::Display for LifetimeParam {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut code = format!("'{}", self.lifetime_or_label);
if !self.bounds.is_empty() {
code += &format!(
" {}",
self.bounds
.iter()
.map(|bound| format!("{bound} +"))
.collect::<String>()
);
code = code.strip_suffix('+').unwrap_or(&code).to_owned();
}
write!(f, "{code}")
}
}
#[derive(Debug, Clone)]
pub struct TypeParam {
pub identifier: TokenTree,
pub bounds: Vec<Bound>,
}
impl Display for GenericParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let gen = fmt_generics(self);
write!(f, "{gen}")
}
}
#[derive(Debug)]
pub struct FieldToken {
pub attrs: HashMap<String, AttrToken>,
pub visibility: Option<TokenTree>,
pub identifier: TokenTree,
pub ty: TyToken,
}
impl Display for FieldToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut vis = String::new();
if let Some(viss) = &self.visibility {
vis = viss.to_string()
}
write!(f, "{} {}: {}", vis, self.identifier, self.ty)
}
}
#[derive(Debug, Clone)]
pub enum TyKind {
ImplTrait,
Parenthesized,
TraitObject,
TypePath,
TupleType,
NeverType,
RawPointerType,
ReferenceType,
ArrayType,
SliceType,
InferredType,
QualifiedPathInType,
BareFunctionType,
MacroInvocation,
}
#[derive(Debug, Clone)]
pub struct TyToken {
pub kind: TyKind,
pub ref_tok: Option<TokenTree>,
pub mut_tok: Option<TokenTree>,
pub identifier: TokenTree,
pub dyn_tok: Option<TokenTree>,
pub lifetime: Option<LifetimeParam>,
pub generics: Option<Vec<TyToken>>,
pub bounds: Vec<Bound>,
}
impl Display for TyToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let code = fmt_ty(self);
write!(f, "{code}")
}
}
#[derive(Debug, Clone)]
pub struct CondAttributeToken {
pub name: TokenTree,
pub value: AttributeToken,
}
#[derive(Debug, Clone)]
pub struct AttributeToken {
pub name: TokenTree,
pub value: Option<TokenTree>,
}
#[derive(Debug, Clone)]
pub enum AttrToken {
Attr(AttributeToken),
CondAttr(CondAttributeToken),
}
impl AttrToken {
pub fn name(&self) -> String {
match self {
Self::Attr(tok) => tok.name.to_string(),
Self::CondAttr(tok) => tok.name.to_string(),
}
}
pub fn attribute(&self) -> AttributeToken {
match self {
Self::Attr(attr) => attr.to_owned(),
Self::CondAttr(attr) => attr.value.clone(),
}
}
pub fn is_conditional(&self) -> bool {
match self {
Self::Attr(_) => false,
Self::CondAttr(_) => true,
}
}
}
#[derive(Debug)]
pub struct ImplToken {
pub attributes: HashMap<String, AttrToken>,
pub generics: Option<GenericParams>,
pub name: TokenTree,
pub for_ty: Option<TyToken>,
pub raw_block: TokenStream,
pub functions: Vec<MethodDeclToken>,
}
impl TopLevelAST for ImplToken {
fn span(&self) -> TokenTree {
self.name.clone()
}
fn is_impl(&self) -> bool {
true
}
}
impl TryFrom<&TokenStream> for ImplToken {
type Error = KParserError;
fn try_from(value: &TokenStream) -> Result<Self, Self::Error> {
let mut stream = KTokenStream::new(value);
parse_impl(&mut stream, &DummyTracer {})
}
}
impl Default for ImplToken {
fn default() -> Self {
panic!()
}
}
impl Display for ImplToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "impl {} {{ {} }}", self.name, self.raw_block)
}
}
#[derive(Debug)]
pub struct TraitToken {
pub attrs: HashMap<String, AttrToken>,
pub visibility: Option<TokenTree>,
pub ident: TokenTree,
pub generics: Option<GenericParams>,
pub inn_attrs: Option<AttrToken>,
pub associated_items: Vec<AssociatedItem>,
pub raw_block: TokenStream,
pub functions: Vec<MethodDeclToken>,
}
impl TopLevelAST for TraitToken {
fn span(&self) -> TokenTree {
self.ident.clone()
}
fn is_trait(&self) -> bool {
true
}
}
impl TryFrom<&TokenStream> for TraitToken {
type Error = KParserError;
fn try_from(value: &TokenStream) -> Result<Self, Self::Error> {
let mut stream = KTokenStream::new(value);
parse_trait(&mut stream, &DummyTracer {})
}
}
impl Default for TraitToken {
fn default() -> Self {
panic!()
}
}
impl Display for TraitToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "")
}
}
#[derive(Debug)]
pub enum AssociatedItem {
AssociatedFn(FnDeclTok),
AssociatedMethod(MethodDeclToken),
}
#[derive(Debug)]
pub struct MethodDeclToken {
pub attrs: HashMap<String, AttrToken>,
pub visibility: Option<TokenTree>,
pub qualifier: Option<TokenTree>,
pub ident: TokenTree,
pub generics: Option<GenericParams>,
pub raw_params: TokenStream,
pub params: Vec<(TokenTree, TyToken)>,
pub return_ty: Option<TyToken>,
pub raw_body: Option<TokenStream>,
}
impl Default for MethodDeclToken {
fn default() -> Self {
unimplemented!()
}
}
impl Display for MethodDeclToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "")
}
}
impl TopLevelAST for MethodDeclToken {
fn span(&self) -> TokenTree {
self.ident.clone()
}
fn is_fn(&self) -> bool {
true
}
}
pub type FnDeclTok = MethodDeclToken;