lisette-syntax 0.1.9

Little language inspired by Rust that compiles to Go
Documentation
use std::fmt;

use crate::types::{Type, TypeVariableState, unqualified_name};

impl Type {
    pub fn stringify(&self) -> String {
        match self {
            Type::Constructor {
                id, params: args, ..
            } => {
                let args_formatted = args
                    .iter()
                    .map(|a| a.stringify())
                    .collect::<Vec<_>>()
                    .join(", ");

                let name = unqualified_name(id);

                if name == "Unit" {
                    return "()".to_string();
                }

                if name == "bool" {
                    return "bool".to_string();
                }

                if name.starts_with("Tuple") {
                    return format!("({})", args_formatted);
                }

                if name == "Ref" {
                    return format!("Ref<{}>", args_formatted);
                }

                if args.is_empty() {
                    return name.to_string();
                }

                format!("{}<{}>", name, args_formatted)
            }

            Type::Variable(var) => match &*var.borrow() {
                TypeVariableState::Unbound { id, hint } => match hint {
                    Some(name) => format!("?{}", name),
                    None => format!("?{}", id),
                },
                TypeVariableState::Link(ty) => format!("{}", ty),
            },

            Type::Function {
                params: args,
                param_mutability,
                return_type,
                ..
            } => {
                let args_formatted = args
                    .iter()
                    .enumerate()
                    .map(|(i, a)| {
                        let is_mut = param_mutability.get(i).copied().unwrap_or(false);
                        if is_mut {
                            format!("mut {}", a.stringify())
                        } else {
                            a.stringify()
                        }
                    })
                    .collect::<Vec<_>>()
                    .join(", ");

                let ret_formatted = (*return_type).stringify();

                format!("fn ({}) -> {}", args_formatted, ret_formatted)
            }

            Type::Forall { .. } => {
                unreachable!("Forall types are always instantiated before display")
            }

            Type::Parameter(name) => name.to_string(),

            Type::Never => "Never".to_string(),

            Type::Tuple(elements) => {
                let formatted = elements
                    .iter()
                    .map(|e| e.stringify())
                    .collect::<Vec<_>>()
                    .join(", ");
                format!("({})", formatted)
            }

            Type::Error => "<error>".to_string(),
        }
    }
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (types, _generics) = Self::remove_vars(&[self]);
        write!(f, "{}", types[0].stringify())
    }
}