diff --git a/src/error.rs b/src/error.rs index 4676dd8..ef00019 100644 --- a/src/error.rs +++ b/src/error.rs @@ -20,6 +20,8 @@ pub enum AiScriptSyntaxError { Attribute, #[error(r#"Reserved word "{0}" cannot be used as variable name."#)] ReservedWord(String), + #[error("Unknown type: '{0}'")] + UnknownType(String), } #[derive(Error, Debug, PartialEq, Clone)] diff --git a/src/type.rs b/src/type.rs index ceccfdb..defe4de 100644 --- a/src/type.rs +++ b/src/type.rs @@ -1,26 +1,48 @@ -use crate::{error::AiScriptError, node as ast}; +use std::fmt::Display; -pub struct TSimple { - pub name: String, +use crate::{error::AiScriptSyntaxError, node as ast}; + +pub enum Type { + Simple(TSimple), + Generic(TGeneric), + Fn(TFn), } -pub struct TGeneric { - pub name: String, - pub inners: Vec, +impl Display for ast::NamedTypeSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let ast::NamedTypeSource { name, inner, .. } = self; + write!(f, "{name}")?; + if let Some(inner) = inner { + write!(f, "<{inner}>")?; + } + Ok(()) + } } -pub struct TFn { - pub args: Vec, - pub result: Box, +impl Display for ast::FnTypeSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let ast::FnTypeSource { args, result, .. } = self; + write!( + f, + "@({}) {{ {result} }}", + args.iter() + .map(ToString::to_string) + .collect::>() + .join(", ") + ) + } } -pub enum Type { - Simple(TSimple), - Generic(TGeneric), - Fn(TFn), +impl Display for ast::TypeSource { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ast::TypeSource::NamedTypeSource(type_source) => type_source.fmt(f), + ast::TypeSource::FnTypeSource(type_source) => type_source.fmt(f), + } + } } -pub fn get_type_by_source(type_source: ast::TypeSource) -> Result { +pub fn get_type_by_source(type_source: ast::TypeSource) -> Result { match type_source { ast::TypeSource::NamedTypeSource(type_source) => match type_source.name.as_str() { "null" | "bool" | "num" | "str" | "any" | "void" => Ok(Type::Simple(TSimple { @@ -37,14 +59,14 @@ pub fn get_type_by_source(type_source: ast::TypeSource) -> Result todo!(), + _ => Err(AiScriptSyntaxError::UnknownType(type_source.to_string())), }, ast::TypeSource::FnTypeSource(type_source) => Ok(Type::Fn(TFn { args: type_source .args .into_iter() .map(get_type_by_source) - .collect::, AiScriptError>>()?, + .collect::, AiScriptSyntaxError>>()?, result: get_type_by_source(*type_source.result)?.into(), })), }