ast: add gens for ty and impl, raw ptr types, make fn return value non-optional

This commit is contained in:
John 2025-07-18 05:25:35 -04:00
parent 6ba62ac1c4
commit 148ef34a01
19 changed files with 242 additions and 147 deletions

View File

@ -183,6 +183,7 @@ pub struct Variant {
/// Sub-[items](Item) (associated functions, etc.) for a [Ty] /// Sub-[items](Item) (associated functions, etc.) for a [Ty]
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Impl { pub struct Impl {
pub gens: Generics,
pub target: ImplKind, pub target: ImplKind,
pub body: File, pub body: File,
} }
@ -216,6 +217,7 @@ pub enum UseTree {
pub struct Ty { pub struct Ty {
pub span: Span, pub span: Span,
pub kind: TyKind, pub kind: TyKind,
pub gens: Generics,
} }
/// Information about a [Ty]pe expression /// Information about a [Ty]pe expression
@ -229,26 +231,27 @@ pub enum TyKind {
Slice(TySlice), Slice(TySlice),
Tuple(TyTuple), Tuple(TyTuple),
Ref(TyRef), Ref(TyRef),
Ptr(TyPtr),
Fn(TyFn), Fn(TyFn),
} }
/// An array of [`T`](Ty) /// An array of [`T`](Ty)
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TyArray { pub struct TyArray {
pub ty: Box<TyKind>, pub ty: Box<Ty>,
pub count: usize, pub count: usize,
} }
/// A [Ty]pe slice expression: `[T]` /// A [Ty]pe slice expression: `[T]`
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TySlice { pub struct TySlice {
pub ty: Box<TyKind>, pub ty: Box<Ty>,
} }
/// A tuple of [Ty]pes /// A tuple of [Ty]pes
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TyTuple { pub struct TyTuple {
pub types: Vec<TyKind>, pub types: Vec<Ty>,
} }
/// A [Ty]pe-reference expression as (number of `&`, [Path]) /// A [Ty]pe-reference expression as (number of `&`, [Path])
@ -259,11 +262,17 @@ pub struct TyRef {
pub to: Box<Ty>, pub to: Box<Ty>,
} }
/// A [Ty]pe-reference expression as (number of `&`, [Path])
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TyPtr {
pub to: Box<Ty>,
}
/// The args and return value for a function pointer [Ty]pe /// The args and return value for a function pointer [Ty]pe
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TyFn { pub struct TyFn {
pub args: Box<TyKind>, pub args: Box<Ty>,
pub rety: Option<Box<Ty>>, pub rety: Box<Ty>,
} }
/// A path to an [Item] in the [Module] tree /// A path to an [Item] in the [Module] tree
@ -274,7 +283,7 @@ pub struct Path {
} }
/// A single component of a [Path] /// A single component of a [Path]
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PathPart { pub enum PathPart {
SuperKw, SuperKw,
SelfTy, SelfTy,
@ -411,7 +420,7 @@ pub struct Array {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ArrayRep { pub struct ArrayRep {
pub value: Box<Expr>, pub value: Box<Expr>,
pub repeat: usize, pub repeat: Box<Expr>,
} }
/// An address-of expression: `&` `mut`? [`Expr`] /// An address-of expression: `&` `mut`? [`Expr`]

View File

@ -43,6 +43,7 @@ impl_from! {
Path => TyKind::Path, Path => TyKind::Path,
TyTuple => TyKind::Tuple, TyTuple => TyKind::Tuple,
TyRef => TyKind::Ref, TyRef => TyKind::Ref,
TyPtr => TyKind::Ptr,
TyFn => TyKind::Fn, TyFn => TyKind::Fn,
} }
impl From for StmtKind { impl From for StmtKind {

View File

@ -163,7 +163,7 @@ impl Display for Module {
impl Display for Function { impl Display for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, gens, sign: sign @ TyFn { args, rety }, bind, body } = self; let Self { name, gens, sign: sign @ TyFn { args, rety }, bind, body } = self;
let types = match **args { let types = match args.kind {
TyKind::Tuple(TyTuple { ref types }) => types.as_slice(), TyKind::Tuple(TyTuple { ref types }) => types.as_slice(),
TyKind::Empty => Default::default(), TyKind::Empty => Default::default(),
_ => { _ => {
@ -191,9 +191,10 @@ impl Display for Function {
write!(f, "{arg}: {ty}")?; write!(f, "{arg}: {ty}")?;
} }
} }
if let Some(rety) = rety { if TyKind::Empty != rety.kind {
write!(f, " -> {rety}")?; write!(f, " -> {rety}")?
} }
match body { match body {
Some(body) => write!(f, " {body}"), Some(body) => write!(f, " {body}"),
None => ';'.fmt(f), None => ';'.fmt(f),
@ -246,8 +247,8 @@ impl Display for Variant {
impl Display for Impl { impl Display for Impl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { target, body } = self; let Self { gens, target, body } = self;
write!(f, "impl {target} ")?; write!(f, "impl{gens} {target} ")?;
write!(f.delimit(BRACES), "{body}") write!(f.delimit(BRACES), "{body}")
} }
} }
@ -285,7 +286,8 @@ impl Display for UseTree {
impl Display for Ty { impl Display for Ty {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.kind.fmt(f) let Self { span: _, kind, gens } = self;
write!(f, "{kind}{gens}")
} }
} }
@ -300,6 +302,7 @@ impl Display for TyKind {
TyKind::Slice(v) => v.fmt(f), TyKind::Slice(v) => v.fmt(f),
TyKind::Tuple(v) => v.fmt(f), TyKind::Tuple(v) => v.fmt(f),
TyKind::Ref(v) => v.fmt(f), TyKind::Ref(v) => v.fmt(f),
TyKind::Ptr(v) => v.fmt(f),
TyKind::Fn(v) => v.fmt(f), TyKind::Fn(v) => v.fmt(f),
} }
} }
@ -335,14 +338,21 @@ impl Display for TyRef {
} }
} }
impl Display for TyPtr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { to } = self;
write!(f, "*{to}")
}
}
impl Display for TyFn { impl Display for TyFn {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { args, rety } = self; let Self { args, rety } = self;
write!(f, "fn {args}")?; write!(f, "fn {args}")?;
match rety { if TyKind::Empty != rety.kind {
Some(v) => write!(f, " -> {v}"), write!(f, " -> {rety}")?;
None => Ok(()),
} }
Ok(())
} }
} }

View File

@ -147,8 +147,8 @@ impl WeightOf for Variant {
impl WeightOf for Impl { impl WeightOf for Impl {
fn weight_of(&self) -> usize { fn weight_of(&self) -> usize {
let Self { target, body } = self; let Self { gens, target, body } = self;
target.weight_of() + body.weight_of() gens.weight_of() + target.weight_of() + body.weight_of()
} }
} }
@ -184,8 +184,8 @@ impl WeightOf for UseTree {
impl WeightOf for Ty { impl WeightOf for Ty {
fn weight_of(&self) -> usize { fn weight_of(&self) -> usize {
let Self { span, kind } = self; let Self { span, kind, gens } = self;
span.weight_of() + kind.weight_of() span.weight_of() + kind.weight_of() + gens.weight_of()
} }
} }
@ -198,6 +198,7 @@ impl WeightOf for TyKind {
TyKind::Slice(v) => v.weight_of(), TyKind::Slice(v) => v.weight_of(),
TyKind::Tuple(v) => v.weight_of(), TyKind::Tuple(v) => v.weight_of(),
TyKind::Ref(v) => v.weight_of(), TyKind::Ref(v) => v.weight_of(),
TyKind::Ptr(v) => v.weight_of(),
TyKind::Fn(v) => v.weight_of(), TyKind::Fn(v) => v.weight_of(),
} }
} }
@ -231,6 +232,13 @@ impl WeightOf for TyRef {
} }
} }
impl WeightOf for TyPtr {
fn weight_of(&self) -> usize {
let Self { to } = self;
to.weight_of()
}
}
impl WeightOf for TyFn { impl WeightOf for TyFn {
fn weight_of(&self) -> usize { fn weight_of(&self) -> usize {
let Self { args, rety } = self; let Self { args, rety } = self;

View File

@ -156,8 +156,12 @@ pub trait Fold {
} }
} }
fn fold_impl(&mut self, i: Impl) -> Impl { fn fold_impl(&mut self, i: Impl) -> Impl {
let Impl { target, body } = i; let Impl { gens, target, body } = i;
Impl { target: self.fold_impl_kind(target), body: self.fold_file(body) } Impl {
gens: self.fold_generics(gens),
target: self.fold_impl_kind(target),
body: self.fold_file(body),
}
} }
fn fold_impl_kind(&mut self, kind: ImplKind) -> ImplKind { fn fold_impl_kind(&mut self, kind: ImplKind) -> ImplKind {
or_fold_impl_kind(self, kind) or_fold_impl_kind(self, kind)
@ -170,39 +174,39 @@ pub trait Fold {
or_fold_use_tree(self, tree) or_fold_use_tree(self, tree)
} }
fn fold_ty(&mut self, t: Ty) -> Ty { fn fold_ty(&mut self, t: Ty) -> Ty {
let Ty { span, kind } = t; let Ty { span, kind, gens } = t;
Ty { span: self.fold_span(span), kind: self.fold_ty_kind(kind) } Ty {
span: self.fold_span(span),
kind: self.fold_ty_kind(kind),
gens: self.fold_generics(gens),
}
} }
fn fold_ty_kind(&mut self, kind: TyKind) -> TyKind { fn fold_ty_kind(&mut self, kind: TyKind) -> TyKind {
or_fold_ty_kind(self, kind) or_fold_ty_kind(self, kind)
} }
fn fold_ty_array(&mut self, a: TyArray) -> TyArray { fn fold_ty_array(&mut self, a: TyArray) -> TyArray {
let TyArray { ty, count } = a; let TyArray { ty, count } = a;
TyArray { ty: Box::new(self.fold_ty_kind(*ty)), count } TyArray { ty: Box::new(self.fold_ty(*ty)), count }
} }
fn fold_ty_slice(&mut self, s: TySlice) -> TySlice { fn fold_ty_slice(&mut self, s: TySlice) -> TySlice {
let TySlice { ty } = s; let TySlice { ty } = s;
TySlice { ty: Box::new(self.fold_ty_kind(*ty)) } TySlice { ty: Box::new(self.fold_ty(*ty)) }
} }
fn fold_ty_tuple(&mut self, t: TyTuple) -> TyTuple { fn fold_ty_tuple(&mut self, t: TyTuple) -> TyTuple {
let TyTuple { types } = t; let TyTuple { types } = t;
TyTuple { TyTuple { types: types.into_iter().map(|kind| self.fold_ty(kind)).collect() }
types: types
.into_iter()
.map(|kind| self.fold_ty_kind(kind))
.collect(),
}
} }
fn fold_ty_ref(&mut self, t: TyRef) -> TyRef { fn fold_ty_ref(&mut self, t: TyRef) -> TyRef {
let TyRef { mutable, count, to } = t; let TyRef { mutable, count, to } = t;
TyRef { mutable: self.fold_mutability(mutable), count, to: Box::new(self.fold_ty(*to)) } TyRef { mutable: self.fold_mutability(mutable), count, to: Box::new(self.fold_ty(*to)) }
} }
fn fold_ty_ptr(&mut self, t: TyPtr) -> TyPtr {
let TyPtr { to } = t;
TyPtr { to: Box::new(self.fold_ty(*to)) }
}
fn fold_ty_fn(&mut self, t: TyFn) -> TyFn { fn fold_ty_fn(&mut self, t: TyFn) -> TyFn {
let TyFn { args, rety } = t; let TyFn { args, rety } = t;
TyFn { TyFn { args: Box::new(self.fold_ty(*args)), rety: Box::new(self.fold_ty(*rety)) }
args: Box::new(self.fold_ty_kind(*args)),
rety: rety.map(|t| Box::new(self.fold_ty(*t))),
}
} }
fn fold_path(&mut self, p: Path) -> Path { fn fold_path(&mut self, p: Path) -> Path {
let Path { absolute, parts } = p; let Path { absolute, parts } = p;
@ -534,6 +538,7 @@ pub fn or_fold_ty_kind<F: Fold + ?Sized>(folder: &mut F, kind: TyKind) -> TyKind
TyKind::Slice(s) => TyKind::Slice(folder.fold_ty_slice(s)), TyKind::Slice(s) => TyKind::Slice(folder.fold_ty_slice(s)),
TyKind::Tuple(t) => TyKind::Tuple(folder.fold_ty_tuple(t)), TyKind::Tuple(t) => TyKind::Tuple(folder.fold_ty_tuple(t)),
TyKind::Ref(t) => TyKind::Ref(folder.fold_ty_ref(t)), TyKind::Ref(t) => TyKind::Ref(folder.fold_ty_ref(t)),
TyKind::Ptr(t) => TyKind::Ptr(folder.fold_ty_ptr(t)),
TyKind::Fn(t) => TyKind::Fn(folder.fold_ty_fn(t)), TyKind::Fn(t) => TyKind::Fn(folder.fold_ty_fn(t)),
} }
} }

View File

@ -131,6 +131,9 @@ pub trait Visit<'a>: Sized {
fn visit_ty_ref(&mut self, value: &'a TyRef) { fn visit_ty_ref(&mut self, value: &'a TyRef) {
value.children(self) value.children(self)
} }
fn visit_ty_ptr(&mut self, value: &'a TyPtr) {
value.children(self)
}
fn visit_ty_fn(&mut self, value: &'a TyFn) { fn visit_ty_fn(&mut self, value: &'a TyFn) {
value.children(self) value.children(self)
} }

View File

@ -297,7 +297,8 @@ impl Walk for Impl {
v.visit_impl(self); v.visit_impl(self);
} }
fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) {
let Impl { target, body } = self; let Impl { gens, target, body } = self;
gens.visit_in(v);
target.visit_in(v); target.visit_in(v);
body.visit_in(v); body.visit_in(v);
} }
@ -354,9 +355,10 @@ impl Walk for Ty {
v.visit_ty(self); v.visit_ty(self);
} }
fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) {
let Ty { span, kind } = self; let Ty { span, kind, gens } = self;
span.visit_in(v); span.visit_in(v);
kind.visit_in(v); kind.visit_in(v);
gens.visit_in(v);
} }
} }
impl Walk for TyKind { impl Walk for TyKind {
@ -374,6 +376,7 @@ impl Walk for TyKind {
TyKind::Slice(value) => value.visit_in(v), TyKind::Slice(value) => value.visit_in(v),
TyKind::Tuple(value) => value.visit_in(v), TyKind::Tuple(value) => value.visit_in(v),
TyKind::Ref(value) => value.visit_in(v), TyKind::Ref(value) => value.visit_in(v),
TyKind::Ptr(value) => value.visit_in(v),
TyKind::Fn(value) => value.visit_in(v), TyKind::Fn(value) => value.visit_in(v),
} }
} }
@ -420,6 +423,16 @@ impl Walk for TyRef {
to.children(v); to.children(v);
} }
} }
impl Walk for TyPtr {
#[inline]
fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) {
v.visit_ty_ptr(self);
}
fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) {
let TyPtr { to } = self;
to.children(v);
}
}
impl Walk for TyFn { impl Walk for TyFn {
#[inline] #[inline]
fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) {
@ -852,10 +865,10 @@ impl Walk for For {
} }
fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) {
let For { bind, cond, pass, fail } = self; let For { bind, cond, pass, fail } = self;
bind.visit_in(v);
cond.visit_in(v); cond.visit_in(v);
pass.visit_in(v);
fail.visit_in(v); fail.visit_in(v);
bind.visit_in(v);
pass.visit_in(v);
} }
} }
impl Walk for Else { impl Walk for Else {

View File

@ -46,7 +46,7 @@ impl Fold for NormalizePaths {
if !absolute { if !absolute {
for segment in self.path.parts.iter().rev() { for segment in self.path.parts.iter().rev() {
tree = UseTree::Path(segment.clone(), Box::new(tree)) tree = UseTree::Path(*segment, Box::new(tree))
} }
} }

View File

@ -191,6 +191,17 @@ macro path_like() {
TokenKind::Super | TokenKind::SelfTy | TokenKind::Identifier | TokenKind::ColonColon TokenKind::Super | TokenKind::SelfTy | TokenKind::Identifier | TokenKind::ColonColon
} }
type Spanned<T> = (T, Span);
impl<'t, T: Parse<'t>> Parse<'t> for Spanned<T> {
fn parse(p: &mut Parser<'t>) -> PResult<Self> {
let head = p.loc();
let body = p.parse()?;
let tail = p.loc();
Ok((body, Span(head, tail)))
}
}
pub trait Parse<'t>: Sized { pub trait Parse<'t>: Sized {
/// Parses a Self from the provided [Parser] /// Parses a Self from the provided [Parser]
fn parse(p: &mut Parser<'t>) -> PResult<Self>; fn parse(p: &mut Parser<'t>) -> PResult<Self>;
@ -343,8 +354,8 @@ impl Parse<'_> for ItemKind {
impl Parse<'_> for Generics { impl Parse<'_> for Generics {
fn parse(p: &mut Parser<'_>) -> PResult<Self> { fn parse(p: &mut Parser<'_>) -> PResult<Self> {
const P: Parsing = Parsing::Generics; const P: Parsing = Parsing::Generics;
let vars = match p.peek_kind(P)? { let vars = match p.peek_kind(P) {
TokenKind::Lt => delim( Ok(TokenKind::Lt) => delim(
sep(Sym::parse, TokenKind::Comma, TokenKind::Gt, P), sep(Sym::parse, TokenKind::Comma, TokenKind::Gt, P),
(TokenKind::Lt, TokenKind::Gt), (TokenKind::Lt, TokenKind::Gt),
P, P,
@ -451,17 +462,16 @@ impl Parse<'_> for Function {
let name = Sym::parse(p)?; let name = Sym::parse(p)?;
let gens = Generics::parse(p)?; let gens = Generics::parse(p)?;
let (bind, types) = delim(FnSig::parse, PARENS, P)(p)?; let ((bind, types), span) = delim(Spanned::<FnSig>::parse, PARENS, P)(p)?;
let sign = TyFn { let sign = TyFn {
args: Box::new(match types.len() { args: Box::new(match types.len() {
0 => TyKind::Empty, 0 => Ty { span, kind: TyKind::Empty, gens: Default::default() },
_ => TyKind::Tuple(TyTuple { types }), _ => Ty { span, kind: TyKind::Tuple(TyTuple { types }), gens: Default::default() },
}),
rety: Box::new(match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Ty::parse(p)?,
Err(_) => Ty { span, kind: TyKind::Empty, gens: Generics { vars: vec![] } },
}), }),
rety: Ok(match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Some(Ty::parse(p)?),
Err(_) => None,
})?
.map(Box::new),
}; };
Ok(Function { Ok(Function {
name, name,
@ -479,7 +489,7 @@ impl Parse<'_> for Function {
} }
} }
type FnSig = (Pattern, Vec<TyKind>); type FnSig = (Pattern, Vec<Ty>);
impl Parse<'_> for FnSig { impl Parse<'_> for FnSig {
/// Parses the parameter list of a Function /// Parses the parameter list of a Function
@ -498,17 +508,17 @@ impl Parse<'_> for FnSig {
} }
} }
type TypedParam = (Pattern, TyKind); type TypedParam = (Pattern, Ty);
impl Parse<'_> for TypedParam { impl Parse<'_> for TypedParam {
/// Parses a single function parameter /// Parses a single function parameter
fn parse(p: &mut Parser) -> PResult<(Pattern, TyKind)> { fn parse(p: &mut Parser) -> PResult<(Pattern, Ty)> {
Ok(( Ok((
Pattern::parse(p)?, Pattern::parse(p)?,
if p.match_type(TokenKind::Colon, Parsing::Param).is_ok() { if p.match_type(TokenKind::Colon, Parsing::Param).is_ok() {
TyKind::parse(p)? Ty::parse(p)?
} else { } else {
TyKind::Infer Ty { span: Span::dummy(), kind: TyKind::Infer, gens: Default::default() }
}, },
)) ))
} }
@ -604,7 +614,11 @@ impl Parse<'_> for Impl {
const P: Parsing = Parsing::Impl; const P: Parsing = Parsing::Impl;
p.match_type(TokenKind::Impl, P)?; p.match_type(TokenKind::Impl, P)?;
Ok(Impl { target: ImplKind::parse(p)?, body: delim(File::parse, CURLIES, P)(p)? }) Ok(Impl {
gens: Generics::parse(p)?,
target: ImplKind::parse(p)?,
body: delim(File::parse, CURLIES, P)(p)?,
})
} }
} }
@ -682,8 +696,9 @@ impl Parse<'_> for Ty {
/// ///
/// See also: [TyKind::parse] /// See also: [TyKind::parse]
fn parse(p: &mut Parser<'_>) -> PResult<Self> { fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let start = p.loc(); let (kind, span) = p.parse()?;
Ok(Ty { kind: TyKind::parse(p)?, span: Span(start, p.loc()) }) let gens = p.parse()?;
Ok(Ty { span, kind, gens })
} }
} }
@ -699,9 +714,10 @@ impl Parse<'_> for TyKind {
TyKind::Never TyKind::Never
} }
TokenKind::Amp | TokenKind::AmpAmp => TyRef::parse(p)?.into(), TokenKind::Amp | TokenKind::AmpAmp => TyRef::parse(p)?.into(),
TokenKind::Star => TyPtr::parse(p)?.into(),
TokenKind::LBrack => { TokenKind::LBrack => {
p.match_type(BRACKETS.0, Parsing::TySlice)?; p.match_type(BRACKETS.0, Parsing::TySlice)?;
let ty = TyKind::parse(p)?; let ty = p.parse()?;
let (out, kind) = match p.match_type(TokenKind::Semi, Parsing::TyArray).is_ok() { let (out, kind) = match p.match_type(TokenKind::Semi, Parsing::TyArray).is_ok() {
true => { true => {
let literal = p.match_type(TokenKind::Literal, Parsing::TyArray)?; let literal = p.match_type(TokenKind::Literal, Parsing::TyArray)?;
@ -709,14 +725,11 @@ impl Parse<'_> for TyKind {
Err(p.error(Unexpected(TokenKind::Literal), Parsing::TyArray))? Err(p.error(Unexpected(TokenKind::Literal), Parsing::TyArray))?
}; };
( (
TyKind::Array(TyArray { ty: Box::new(ty), count: count as _ }), TyKind::Array(TyArray { ty, count: count as _ }),
Parsing::TyArray, Parsing::TyArray,
) )
} }
false => ( false => (TyKind::Slice(TySlice { ty }), Parsing::TySlice),
TyKind::Slice(TySlice { ty: Box::new(ty) }),
Parsing::TySlice,
),
}; };
p.match_type(BRACKETS.1, kind)?; p.match_type(BRACKETS.1, kind)?;
out out
@ -748,9 +761,7 @@ impl Parse<'_> for TyTuple {
/// [TyTuple] = `(` ([Ty] `,`)* [Ty]? `)` /// [TyTuple] = `(` ([Ty] `,`)* [Ty]? `)`
fn parse(p: &mut Parser) -> PResult<TyTuple> { fn parse(p: &mut Parser) -> PResult<TyTuple> {
const P: Parsing = Parsing::TyTuple; const P: Parsing = Parsing::TyTuple;
Ok(TyTuple { Ok(TyTuple { types: delim(sep(Ty::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)? })
types: delim(sep(TyKind::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)?,
})
} }
} }
@ -771,24 +782,36 @@ impl Parse<'_> for TyRef {
} }
} }
impl Parse<'_> for TyPtr {
/// [TyPtr] = `*` [Ty]
fn parse(p: &mut Parser) -> PResult<TyPtr> {
const P: Parsing = Parsing::TyRef;
p.match_type(TokenKind::Star, P)?;
Ok(TyPtr { to: p.parse()? })
}
}
impl Parse<'_> for TyFn { impl Parse<'_> for TyFn {
/// [TyFn] = `fn` [TyTuple] (-> [Ty])? /// [TyFn] = `fn` [TyTuple] (-> [Ty])?
fn parse(p: &mut Parser) -> PResult<TyFn> { fn parse(p: &mut Parser) -> PResult<TyFn> {
const P: Parsing = Parsing::TyFn; const P: Parsing = Parsing::TyFn;
p.match_type(TokenKind::Fn, P)?; p.match_type(TokenKind::Fn, P)?;
let args = delim(sep(TyKind::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)?; let head = p.loc();
let args = delim(sep(Ty::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)?;
let span = Span(head, p.loc());
Ok(TyFn { Ok(TyFn {
args: Box::new(match args { args: Box::new(match args {
t if t.is_empty() => TyKind::Empty, t if t.is_empty() => Ty { kind: TyKind::Empty, span, gens: Default::default() },
types => TyKind::Tuple(TyTuple { types }), types => {
Ty { kind: TyKind::Tuple(TyTuple { types }), span, gens: Default::default() }
}
}),
rety: Box::new(match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Ty::parse(p)?,
Err(_) => Ty { span, kind: TyKind::Empty, gens: Generics { vars: vec![] } },
}), }),
rety: match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Some(Ty::parse(p)?),
Err(_) => None,
}
.map(Into::into),
}) })
} }
} }
@ -847,15 +870,12 @@ impl Parse<'_> for Stmt {
/// ///
/// See also: [StmtKind::parse] /// See also: [StmtKind::parse]
fn parse(p: &mut Parser) -> PResult<Stmt> { fn parse(p: &mut Parser) -> PResult<Stmt> {
let start = p.loc(); let (kind, span) = Spanned::<StmtKind>::parse(p)?;
Ok(Stmt { let semi = match p.match_type(TokenKind::Semi, Parsing::Stmt) {
kind: StmtKind::parse(p)?, Ok(_) => Semi::Terminated,
semi: match p.match_type(TokenKind::Semi, Parsing::Stmt) { _ => Semi::Unterminated,
Ok(_) => Semi::Terminated, };
_ => Semi::Unterminated, Ok(Stmt { span, kind, semi })
},
span: Span(start, p.loc()),
})
} }
} }
@ -1132,7 +1152,7 @@ impl Parse<'_> for Pattern {
// Name, Path, Struct, TupleStruct // Name, Path, Struct, TupleStruct
TokenKind::Identifier => pathpattern(p)?, TokenKind::Identifier => pathpattern(p)?,
// Literal // Literal
TokenKind::Literal => Pattern::Literal(p.parse()?), TokenKind::True | TokenKind::False | TokenKind::Literal => Pattern::Literal(p.parse()?),
// Rest // Rest
TokenKind::DotDot => { TokenKind::DotDot => {
p.consume_peeked(); p.consume_peeked();

View File

@ -204,13 +204,7 @@ fn exprkind_array_rep(p: &mut Parser) -> PResult<ExprKind> {
value: first.into(), value: first.into(),
repeat: { repeat: {
p.consume_peeked(); p.consume_peeked();
let value = p.match_type(TokenKind::Literal, Parsing::ArrayRep)?; p.parse()?
match value.data() {
TokenData::Integer(size) => *size as usize,
_ => {
Err(p.error(ErrorKind::Unexpected(TokenKind::Literal), Parsing::ArrayRep))?
}
}
}, },
} }
.into(), .into(),

View File

@ -273,7 +273,7 @@ pub mod clangify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, gens: _, sign, bind, body } = self; let Self { name, gens: _, sign, bind, body } = self;
let TyFn { args, rety } = sign; let TyFn { args, rety } = sign;
let types = match args.as_ref() { let types = match &args.kind {
TyKind::Tuple(TyTuple { types }) => types.as_slice(), TyKind::Tuple(TyTuple { types }) => types.as_slice(),
TyKind::Empty => &[], TyKind::Empty => &[],
_ => panic!("Unsupported function args: {args}"), _ => panic!("Unsupported function args: {args}"),
@ -282,13 +282,7 @@ pub mod clangify {
Pattern::Tuple(tup) => tup.as_slice(), Pattern::Tuple(tup) => tup.as_slice(),
_ => panic!("Unsupported function binders: {args}"), _ => panic!("Unsupported function binders: {args}"),
}; };
match rety { y.p(rety).p(" ").p(name).p(" (");
Some(ty) => y.p(ty),
None => y.p("void"),
}
.p(" ")
.p(name)
.p(" (");
for (idx, (bind, ty)) in bind.iter().zip(types).enumerate() { for (idx, (bind, ty)) in bind.iter().zip(types).enumerate() {
if idx > 0 { if idx > 0 {
y.p(", "); y.p(", ");
@ -347,8 +341,8 @@ pub mod clangify {
} }
impl CLangify for Impl { impl CLangify for Impl {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { target, body } = self; let Self { gens, target, body } = self;
y.nest("/* TODO: impl ").p(target).p(" { */ "); y.nest("/* TODO: impl ").p(gens).p(target).p(" { */ ");
y.p(body); y.p(body);
y.p("/* } // impl ").p(target).p(" */ "); y.p("/* } // impl ").p(target).p(" */ ");
} }
@ -477,7 +471,7 @@ pub mod clangify {
} }
TyKind::Fn(TyFn { args, rety }) => { TyKind::Fn(TyFn { args, rety }) => {
y.nest("(").p(rety).p(" *").p(mutable).p(name).p(")("); y.nest("(").p(rety).p(" *").p(mutable).p(name).p(")(");
match args.as_ref() { match &args.kind {
TyKind::Empty => {} TyKind::Empty => {}
TyKind::Tuple(TyTuple { types }) => { TyKind::Tuple(TyTuple { types }) => {
for (idx, ty) in types.iter().enumerate() { for (idx, ty) in types.iter().enumerate() {
@ -688,14 +682,14 @@ pub mod clangify {
impl CLangify for ArrayRep { impl CLangify for ArrayRep {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { value, repeat } = self; let Self { value, repeat } = self;
let ExprKind::Literal(Literal::Int(repeat)) = &repeat.kind else {
eprintln!("Constant needs folding: {repeat}");
return;
};
{ {
let mut y = y.nest("{"); let mut y = y.nest("{");
y.endl(); for _ in 0..*repeat {
for idx in 0..*repeat { y.endl().p(value).p(",");
if idx > 0 {
y.p(", ");
}
y.p(value);
} }
} }
y.endl().p("}"); y.endl().p("}");
@ -797,7 +791,7 @@ pub mod clangify {
} }
impl CLangify for Ty { impl CLangify for Ty {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { span: _, kind } = self; let Self { span: _, kind, gens: _ } = self;
y.p(kind); y.p(kind);
} }
} }
@ -806,10 +800,11 @@ pub mod clangify {
match self { match self {
TyKind::Never => y.p("Never"), TyKind::Never => y.p("Never"),
TyKind::Empty => y.p("Empty"), TyKind::Empty => y.p("Empty"),
TyKind::Infer => y.p("Any"), TyKind::Infer => y.p("auto"),
TyKind::Path(t) => y.p(t), TyKind::Path(t) => y.p(t),
TyKind::Tuple(t) => y.p(t), TyKind::Tuple(t) => y.p(t),
TyKind::Ref(t) => y.p(t), TyKind::Ref(t) => y.p(t),
TyKind::Ptr(t) => y.p(t),
TyKind::Fn(t) => y.p(t), TyKind::Fn(t) => y.p(t),
TyKind::Slice(t) => y.p(t), TyKind::Slice(t) => y.p(t),
TyKind::Array(t) => y.p(t), TyKind::Array(t) => y.p(t),
@ -873,12 +868,18 @@ pub mod clangify {
} }
} }
} }
impl CLangify for TyPtr {
fn print(&self, y: &mut CLangifier) {
let Self { to } = self;
y.p(to).p("*");
}
}
impl CLangify for TyFn { impl CLangify for TyFn {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { args, rety } = self; let Self { args, rety } = self;
// TODO: function pointer syntax // TODO: function pointer syntax
y.nest("(").p(rety).p(" *)("); y.nest("(").p(rety).p(" *)(");
match args.as_ref() { match &args.kind {
TyKind::Empty => y, TyKind::Empty => y,
TyKind::Tuple(TyTuple { types }) => { TyKind::Tuple(TyTuple { types }) => {
for (idx, ty) in types.iter().enumerate() { for (idx, ty) in types.iter().enumerate() {

View File

@ -83,7 +83,7 @@ pub mod yamler {
pub fn key(&mut self, name: impl Yamlify) -> Section { pub fn key(&mut self, name: impl Yamlify) -> Section {
println!(); println!();
self.print_indentation(&mut std::io::stdout().lock()); self.print_indentation(&mut std::io::stdout().lock());
print!("- "); print!(" ");
name.yaml(self); name.yaml(self);
print!(":"); print!(":");
self.indent() self.indent()
@ -103,8 +103,10 @@ pub mod yamler {
} }
pub fn list<D: Yamlify>(&mut self, list: &[D]) -> &mut Self { pub fn list<D: Yamlify>(&mut self, list: &[D]) -> &mut Self {
for (idx, value) in list.iter().enumerate() { for value in list {
self.pair(idx, value); println!();
self.print_indentation(&mut std::io::stdout().lock());
self.yaml(&"- ").yaml(value);
} }
self self
} }
@ -302,8 +304,11 @@ pub mod yamlify {
} }
impl Yamlify for Impl { impl Yamlify for Impl {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { target, body } = self; let Self { gens, target, body } = self;
y.key("Impl").pair("target", target).pair("body", body); y.key("Impl")
.pair("gens", gens)
.pair("target", target)
.pair("body", body);
} }
} }
impl Yamlify for ImplKind { impl Yamlify for ImplKind {
@ -536,7 +541,10 @@ pub mod yamlify {
impl Yamlify for Index { impl Yamlify for Index {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { head, indices } = self; let Self { head, indices } = self;
y.key("Index").pair("head", head).list(indices); y.key("Index")
.pair("head", head)
.key("indices")
.list(indices);
} }
} }
impl Yamlify for Structor { impl Yamlify for Structor {
@ -589,7 +597,7 @@ pub mod yamlify {
impl Yamlify for Else { impl Yamlify for Else {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { body } = self; let Self { body } = self;
y.key("Else").yaml(body); y.key("fail").yaml(body);
} }
} }
impl Yamlify for If { impl Yamlify for If {
@ -633,8 +641,8 @@ pub mod yamlify {
} }
impl Yamlify for Ty { impl Yamlify for Ty {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { span: _, kind } = self; let Self { span: _, kind, gens } = self;
y.key("Ty").yaml(kind); y.key("Ty").yaml(kind).yaml(gens);
} }
} }
impl Yamlify for TyKind { impl Yamlify for TyKind {
@ -646,6 +654,7 @@ pub mod yamlify {
TyKind::Path(t) => y.yaml(t), TyKind::Path(t) => y.yaml(t),
TyKind::Tuple(t) => y.yaml(t), TyKind::Tuple(t) => y.yaml(t),
TyKind::Ref(t) => y.yaml(t), TyKind::Ref(t) => y.yaml(t),
TyKind::Ptr(t) => y.yaml(t),
TyKind::Fn(t) => y.yaml(t), TyKind::Fn(t) => y.yaml(t),
TyKind::Slice(t) => y.yaml(t), TyKind::Slice(t) => y.yaml(t),
TyKind::Array(t) => y.yaml(t), TyKind::Array(t) => y.yaml(t),
@ -659,9 +668,7 @@ pub mod yamlify {
if *absolute { if *absolute {
y.pair("absolute", absolute); y.pair("absolute", absolute);
} }
for part in parts { y.yaml(parts);
y.pair("part", part);
}
} }
} }
impl Yamlify for PathPart { impl Yamlify for PathPart {
@ -703,6 +710,13 @@ pub mod yamlify {
.pair("to", to); .pair("to", to);
} }
} }
impl Yamlify for TyPtr {
fn yaml(&self, y: &mut Yamler) {
let Self { to } = self;
y.key("TyPtr")
.pair("to", to);
}
}
impl Yamlify for TyFn { impl Yamlify for TyFn {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { args, rety } = self; let Self { args, rety } = self;
@ -726,9 +740,7 @@ pub mod yamlify {
} }
impl<T: Yamlify> Yamlify for Vec<T> { impl<T: Yamlify> Yamlify for Vec<T> {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
for thing in self { y.list(self);
y.yaml(thing);
}
} }
} }
impl Yamlify for () { impl Yamlify for () {

View File

@ -28,6 +28,11 @@ impl fmt::Display for Entry<'_, '_> {
let h_id = self.with_id(id); let h_id = self.with_id(id);
write_name_or(h_id, f) write_name_or(h_id, f)
} }
&TypeKind::Ptr(id) => {
f.write_str("*")?;
let h_id = self.with_id(id);
write_name_or(h_id, f)
}
TypeKind::Slice(id) => { TypeKind::Slice(id) => {
write_name_or(self.with_id(*id), &mut f.delimit_with("[", "]")) write_name_or(self.with_id(*id), &mut f.delimit_with("[", "]"))
} }
@ -66,10 +71,7 @@ fn write_adt(adt: &Adt, h: &Entry, f: &mut impl Write) -> fmt::Result {
let mut variants = variants.iter(); let mut variants = variants.iter();
separate(", ", || { separate(", ", || {
variants.next().map(|(name, def)| { variants.next().map(|(name, def)| {
move |f: &mut Delimit<_>| { move |f: &mut Delimit<_>| write!(f, "{name}: {}", h.with_id(*def))
write!(f, "{name}: ")?;
write_name_or(h.with_id(*def), f)
}
}) })
})(f.delimit_with("enum {", "}")) })(f.delimit_with("enum {", "}"))
} }
@ -77,20 +79,14 @@ fn write_adt(adt: &Adt, h: &Entry, f: &mut impl Write) -> fmt::Result {
let mut members = members.iter(); let mut members = members.iter();
separate(", ", || { separate(", ", || {
let (name, vis, id) = members.next()?; let (name, vis, id) = members.next()?;
Some(move |f: &mut Delimit<_>| { Some(move |f: &mut Delimit<_>| write!(f, "{vis}{name}: {}", h.with_id(*id)))
write!(f, "{vis}{name}: ")?;
write_name_or(h.with_id(*id), f)
})
})(f.delimit_with("struct {", "}")) })(f.delimit_with("struct {", "}"))
} }
Adt::TupleStruct(members) => { Adt::TupleStruct(members) => {
let mut members = members.iter(); let mut members = members.iter();
separate(", ", || { separate(", ", || {
let (vis, def) = members.next()?; let (vis, def) = members.next()?;
Some(move |f: &mut Delimit<_>| { Some(move |f: &mut Delimit<_>| write!(f, "{vis}{}", h.with_id(*def)))
write!(f, "{vis}")?;
write_name_or(h.with_id(*def), f)
})
})(f.delimit_with("struct (", ")")) })(f.delimit_with("struct (", ")"))
} }
Adt::UnitStruct => write!(f, "struct"), Adt::UnitStruct => write!(f, "struct"),

View File

@ -70,7 +70,7 @@ fn import_tree<'a>(
UseTree::Path(part, rest) => { UseTree::Path(part, rest) => {
let source = table let source = table
.nav(src, slice::from_ref(part)) .nav(src, slice::from_ref(part))
.ok_or_else(|| Error::NotFound(src, part.clone()))?; .ok_or(Error::NotFound(src, *part))?;
import_tree(table, source, dst, rest, seen) import_tree(table, source, dst, rest, seen)
} }
UseTree::Alias(src_name, dst_name) => { UseTree::Alias(src_name, dst_name) => {

View File

@ -496,6 +496,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> {
todo!() todo!()
} }
(TypeKind::Ref(a), TypeKind::Ref(b)) => self.unify(*a, *b), (TypeKind::Ref(a), TypeKind::Ref(b)) => self.unify(*a, *b),
(TypeKind::Ptr(a), TypeKind::Ptr(b)) => self.unify(*a, *b),
(TypeKind::Slice(a), TypeKind::Slice(b)) => self.unify(*a, *b), (TypeKind::Slice(a), TypeKind::Slice(b)) => self.unify(*a, *b),
// Slice unifies with array // Slice unifies with array
(TypeKind::Array(a, _), TypeKind::Slice(b)) => self.unify(*a, *b), (TypeKind::Array(a, _), TypeKind::Slice(b)) => self.unify(*a, *b),

View File

@ -121,7 +121,7 @@ impl<'a> Table<'a> {
self.impls.push(item); self.impls.push(item);
} }
pub fn handle_iter(&mut self) -> impl Iterator<Item = Handle> + use<> { pub fn handle_iter(&self) -> impl Iterator<Item = Handle> + use<> {
self.kinds.keys() self.kinds.keys()
} }

View File

@ -2,7 +2,7 @@
//! construct type bindings in a [Table]'s typing context. //! construct type bindings in a [Table]'s typing context.
use crate::{handle::Handle, table::Table, type_kind::TypeKind}; use crate::{handle::Handle, table::Table, type_kind::TypeKind};
use cl_ast::{PathPart, Ty, TyArray, TyFn, TyKind, TyRef, TySlice, TyTuple}; use cl_ast::{PathPart, Sym, Ty, TyArray, TyFn, TyKind, TyPtr, TyRef, TySlice, TyTuple};
#[derive(Clone, Debug, PartialEq, Eq)] // TODO: impl Display and Error #[derive(Clone, Debug, PartialEq, Eq)] // TODO: impl Display and Error
pub enum Error { pub enum Error {
@ -48,6 +48,7 @@ impl TypeExpression for TyKind {
TyKind::Slice(s) => s.evaluate(table, node), TyKind::Slice(s) => s.evaluate(table, node),
TyKind::Tuple(t) => t.evaluate(table, node), TyKind::Tuple(t) => t.evaluate(table, node),
TyKind::Ref(r) => r.evaluate(table, node), TyKind::Ref(r) => r.evaluate(table, node),
TyKind::Ptr(r) => r.evaluate(table, node),
TyKind::Fn(f) => f.evaluate(table, node), TyKind::Fn(f) => f.evaluate(table, node),
} }
} }
@ -68,6 +69,15 @@ impl TypeExpression for [PathPart] {
} }
} }
impl TypeExpression for Sym {
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
let path = [PathPart::Ident(*self)];
table
.nav(node, &path)
.ok_or_else(|| Error::BadPath { parent: node, path: path.to_vec() })
}
}
impl TypeExpression for TyArray { impl TypeExpression for TyArray {
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> { fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
let Self { ty, count } = self; let Self { ty, count } = self;
@ -107,15 +117,21 @@ impl TypeExpression for TyRef {
} }
} }
impl TypeExpression for TyPtr {
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
let Self { to } = self;
let mut t = to.evaluate(table, node)?;
t = table.anon_type(TypeKind::Ptr(t));
Ok(t)
}
}
impl TypeExpression for TyFn { impl TypeExpression for TyFn {
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> { fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
let Self { args, rety } = self; let Self { args, rety } = self;
let kind = TypeKind::FnSig { let kind = TypeKind::FnSig {
args: args.evaluate(table, node)?, args: args.evaluate(table, node)?,
rety: match rety { rety: rety.evaluate(table, node)?,
Some(ty) => ty.evaluate(table, node)?,
None => TyKind::Empty.evaluate(table, node)?,
},
}; };
Ok(table.anon_type(kind)) Ok(table.anon_type(kind))
} }

View File

@ -22,6 +22,8 @@ pub enum TypeKind {
Adt(Adt), Adt(Adt),
/// A reference to an already-defined type: &T /// A reference to an already-defined type: &T
Ref(Handle), Ref(Handle),
/// A raw pointer to an already-defined type: &T
Ptr(Handle),
/// A contiguous view of dynamically sized memory /// A contiguous view of dynamically sized memory
Slice(Handle), Slice(Handle),
/// A contiguous view of statically sized memory /// A contiguous view of statically sized memory
@ -67,6 +69,7 @@ pub enum Primitive {
Integer, Float, // Inferred int and float Integer, Float, // Inferred int and float
Bool, // boolean value Bool, // boolean value
Char, // Unicode codepoint Char, // Unicode codepoint
Str, // UTF-8 string
} }
#[rustfmt::skip] #[rustfmt::skip]
@ -117,6 +120,7 @@ impl FromStr for Primitive {
"fsize" => Primitive::Fsize, "fsize" => Primitive::Fsize,
"bool" => Primitive::Bool, "bool" => Primitive::Bool,
"char" => Primitive::Char, "char" => Primitive::Char,
"str" => Primitive::Str,
_ => Err(())?, _ => Err(())?,
}) })
} }

View File

@ -14,6 +14,7 @@ impl Display for TypeKind {
TypeKind::Primitive(i) => i.fmt(f), TypeKind::Primitive(i) => i.fmt(f),
TypeKind::Adt(a) => a.fmt(f), TypeKind::Adt(a) => a.fmt(f),
TypeKind::Ref(def) => write!(f, "&{def}"), TypeKind::Ref(def) => write!(f, "&{def}"),
TypeKind::Ptr(def) => write!(f, "*{def}"),
TypeKind::Slice(def) => write!(f, "slice [#{def}]"), TypeKind::Slice(def) => write!(f, "slice [#{def}]"),
TypeKind::Array(def, size) => write!(f, "array [#{def}; {size}]"), TypeKind::Array(def, size) => write!(f, "array [#{def}; {size}]"),
TypeKind::Tuple(defs) => { TypeKind::Tuple(defs) => {
@ -92,6 +93,7 @@ impl Display for Primitive {
Primitive::Float => f.write_str("{float}"), Primitive::Float => f.write_str("{float}"),
Primitive::Bool => f.write_str("bool"), Primitive::Bool => f.write_str("bool"),
Primitive::Char => f.write_str("char"), Primitive::Char => f.write_str("char"),
Primitive::Str => f.write_str("str"),
} }
} }
} }