use std::{fmt::Display, rc::Rc}; #[derive(Debug, Clone, PartialEq)] pub enum Type { Any, Number, String, Boolean, Nil, Function(FunctionType), Struct(Rc), Unresolved(String), } impl Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Type::Any => write!(f, "any"), Type::Number => write!(f, "number"), Type::String => write!(f, "string"), Type::Boolean => write!(f, "boolean"), Type::Nil => write!(f, "nil"), Type::Function(fun) => write!(f, "{}", fun), Type::Struct(struct_) => write!(f, "{}", struct_), Type::Unresolved(name) => write!(f, "{}", name), } } } #[derive(Debug, Clone, PartialEq)] pub struct FunctionType { pub params: Vec<(String, Box)>, pub return_type: Box, } impl Display for FunctionType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let rendered_params = self .params .iter() .map(|(name, ty)| format!("{}: {}", name, ty)) .collect::>() .join(", "); write!(f, "fn({}) -> {}", rendered_params, self.return_type) } } #[derive(Debug, Clone, PartialEq)] pub struct StructType { pub fields: Vec<(String, Box)>, pub methods: Vec<(String, FunctionType)>, } impl Display for StructType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let rendered_field = self .fields .iter() .map(|(name, ty)| format!("{}: {}", name, ty)) .collect::>() .join(", "); let rendered_method = self .methods .iter() .map(|(name, ty)| format!("{}: {}", name, ty)) .collect::>() .join(", "); write!(f, "struct {{ {}, {} }}", rendered_field, rendered_method) } }