use std::fmt::{Display, Write};
use crate::parser::lexing::TokenKind;
use super::unchecked::{self, DeriveValue};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Variant {
Structure {
namespace: Vec<Identifier>,
},
Enumeration {
namespace: Vec<Identifier>,
},
Result {
namespace: Vec<Identifier>,
},
Option {
namespace: Vec<Identifier>,
},
Vec {
namespace: Vec<Identifier>,
},
Namespace,
RootNamespace,
Function,
Primitive,
NamedType,
DocNamedType,
Void,
}
impl Default for Variant {
fn default() -> Self {
Self::Void
}
}
impl Variant {
pub fn new() -> Self {
Self::default()
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Namespace {
pub name: Identifier,
pub functions: Vec<Function>,
pub structures: Vec<Structure>,
pub enumerations: Vec<Enumeration>,
pub namespaces: Vec<Namespace>,
pub attributes: Vec<Attribute>,
}
impl From<&CommandSpec> for Namespace {
fn from(value: &CommandSpec) -> Self {
Self {
name: Identifier {
name: "<root>".to_owned(),
variant: Variant::RootNamespace,
},
functions: value.functions.clone(),
structures: value.structures.clone(),
enumerations: value.enumerations.clone(),
namespaces: value.namespaces.clone(),
attributes: vec![],
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct CommandSpec {
pub structures: Vec<Structure>,
pub enumerations: Vec<Enumeration>,
pub functions: Vec<Function>,
pub namespaces: Vec<Namespace>,
}
impl From<Namespace> for CommandSpec {
fn from(value: Namespace) -> Self {
Self {
structures: value.structures,
enumerations: value.enumerations,
functions: value.functions,
namespaces: value.namespaces,
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Structure {
pub identifier: Identifier,
pub contents: Vec<DocNamedType>,
pub attributes: Vec<Attribute>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Enumeration {
pub identifier: Identifier,
pub states: Vec<DocIdentifier>,
pub attributes: Vec<Attribute>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Function {
pub identifier: Identifier,
pub inputs: Vec<NamedType>,
pub output: Option<Type>,
pub attributes: Vec<Attribute>,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Type {
Typical {
identifier: Identifier,
generic_args: Vec<Type>,
},
Function {
inputs: Vec<NamedType>,
output: Option<Box<Type>>,
},
}
impl Type {
pub fn print_generics(&self) -> String {
let mut output = String::new();
self.display_generics(&mut output)
.expect("This should fail");
output
}
pub fn display_generics<T: Write>(&self, f: &mut T) -> std::fmt::Result {
match self {
Type::Typical {
identifier: _,
generic_args,
} => {
if !generic_args.is_empty() {
f.write_char('<')?;
let mut first_run = true;
for arg in generic_args {
if !first_run {
f.write_str(", ")?;
} else {
first_run = false;
}
write!(f, "{}", arg)?;
}
f.write_char('>')
} else {
f.write_str("")
}
}
Type::Function { .. } => {
unimplemented!("This function should only be called for the 'Typical' enum variant")
}
}
}
}
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Type::Typical {
identifier,
generic_args: _,
} => {
f.write_str(&identifier.name)?;
self.display_generics(f)
}
Type::Function { inputs, output } => {
f.write_str("fn(")?;
if !inputs.is_empty() {
f.write_str(
&inputs
.iter()
.map(|ty| ty.to_string())
.collect::<Vec<_>>()
.join(", "),
)?;
}
f.write_str(")")?;
if let Some(output) = output {
f.write_str("-> ")?;
f.write_str(output.to_string().as_str())?;
}
Ok(())
}
}
}
}
impl Display for NamedType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.name.name)?;
f.write_str(": ")?;
f.write_str(self.r#type.to_string().as_str())
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct NamedType {
pub name: Identifier,
pub r#type: Type,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct DocNamedType {
pub name: Identifier,
pub r#type: Type,
pub attributes: Vec<Attribute>,
}
impl From<&DocNamedType> for NamedType {
fn from(value: &DocNamedType) -> Self {
Self {
name: value.name.to_owned(),
r#type: value.r#type.to_owned(),
}
}
}
impl TokenKind {
pub fn to_identifier(self: TokenKind, variant: Variant) -> Identifier {
match self {
TokenKind::Identifier(ident) => Identifier {
name: ident,
variant,
},
_ => {
panic!(
"
Tried to convert a non Identifier TokenKind to a
Identifier. This is a bug. The token was: '{}'
",
self
)
}
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Attribute {
#[allow(non_camel_case_types)]
doc(String),
#[allow(non_camel_case_types)]
derive(DeriveValue),
#[allow(non_camel_case_types)]
error(String),
}
impl From<unchecked::Attribute> for Attribute {
fn from(value: unchecked::Attribute) -> Self {
match value {
unchecked::Attribute::doc { content: name, .. } => Self::doc(name.content),
unchecked::Attribute::derive { value, .. } => Self::derive(value),
unchecked::Attribute::error { content, .. } => Self::error(content.content),
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Identifier {
pub name: String,
pub variant: Variant,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct DocIdentifier {
pub name: String,
pub variant: Variant,
pub attributes: Vec<Attribute>,
}
impl From<&DocIdentifier> for Identifier {
fn from(value: &DocIdentifier) -> Self {
Self {
name: value.name.to_owned(),
variant: value.variant.clone(),
}
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.name)
}
}