From 148ef34a0194ee443f7e25b2dad6235fee85ddb4 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 18 Jul 2025 05:25:35 -0400 Subject: [PATCH] ast: add gens for ty and impl, raw ptr types, make fn return value non-optional --- compiler/cl-ast/src/ast.rs | 23 ++-- compiler/cl-ast/src/ast_impl/convert.rs | 1 + compiler/cl-ast/src/ast_impl/display.rs | 28 +++-- compiler/cl-ast/src/ast_impl/weight_of.rs | 16 ++- compiler/cl-ast/src/ast_visitor/fold.rs | 37 +++--- compiler/cl-ast/src/ast_visitor/visit.rs | 3 + compiler/cl-ast/src/ast_visitor/walk.rs | 21 +++- compiler/cl-ast/src/desugar/path_absoluter.rs | 2 +- compiler/cl-parser/src/parser.rs | 110 +++++++++++------- compiler/cl-parser/src/parser/prec.rs | 8 +- compiler/cl-repl/examples/to_c.rs | 41 +++---- compiler/cl-repl/examples/yaml.rs | 42 ++++--- compiler/cl-typeck/src/entry/display.rs | 20 ++-- compiler/cl-typeck/src/stage/import.rs | 2 +- compiler/cl-typeck/src/stage/infer/engine.rs | 1 + compiler/cl-typeck/src/table.rs | 2 +- compiler/cl-typeck/src/type_expression.rs | 26 ++++- compiler/cl-typeck/src/type_kind.rs | 4 + compiler/cl-typeck/src/type_kind/display.rs | 2 + 19 files changed, 242 insertions(+), 147 deletions(-) diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index e6ea251..99af47d 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -183,6 +183,7 @@ pub struct Variant { /// Sub-[items](Item) (associated functions, etc.) for a [Ty] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Impl { + pub gens: Generics, pub target: ImplKind, pub body: File, } @@ -216,6 +217,7 @@ pub enum UseTree { pub struct Ty { pub span: Span, pub kind: TyKind, + pub gens: Generics, } /// Information about a [Ty]pe expression @@ -229,26 +231,27 @@ pub enum TyKind { Slice(TySlice), Tuple(TyTuple), Ref(TyRef), + Ptr(TyPtr), Fn(TyFn), } /// An array of [`T`](Ty) #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TyArray { - pub ty: Box, + pub ty: Box, pub count: usize, } /// A [Ty]pe slice expression: `[T]` #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TySlice { - pub ty: Box, + pub ty: Box, } /// A tuple of [Ty]pes #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TyTuple { - pub types: Vec, + pub types: Vec, } /// A [Ty]pe-reference expression as (number of `&`, [Path]) @@ -259,11 +262,17 @@ pub struct TyRef { pub to: Box, } +/// A [Ty]pe-reference expression as (number of `&`, [Path]) +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct TyPtr { + pub to: Box, +} + /// The args and return value for a function pointer [Ty]pe #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct TyFn { - pub args: Box, - pub rety: Option>, + pub args: Box, + pub rety: Box, } /// A path to an [Item] in the [Module] tree @@ -274,7 +283,7 @@ pub struct Path { } /// A single component of a [Path] -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum PathPart { SuperKw, SelfTy, @@ -411,7 +420,7 @@ pub struct Array { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct ArrayRep { pub value: Box, - pub repeat: usize, + pub repeat: Box, } /// An address-of expression: `&` `mut`? [`Expr`] diff --git a/compiler/cl-ast/src/ast_impl/convert.rs b/compiler/cl-ast/src/ast_impl/convert.rs index a48e51a..0e016fe 100644 --- a/compiler/cl-ast/src/ast_impl/convert.rs +++ b/compiler/cl-ast/src/ast_impl/convert.rs @@ -43,6 +43,7 @@ impl_from! { Path => TyKind::Path, TyTuple => TyKind::Tuple, TyRef => TyKind::Ref, + TyPtr => TyKind::Ptr, TyFn => TyKind::Fn, } impl From for StmtKind { diff --git a/compiler/cl-ast/src/ast_impl/display.rs b/compiler/cl-ast/src/ast_impl/display.rs index f251bca..32987cc 100644 --- a/compiler/cl-ast/src/ast_impl/display.rs +++ b/compiler/cl-ast/src/ast_impl/display.rs @@ -163,7 +163,7 @@ impl Display for Module { impl Display for Function { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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::Empty => Default::default(), _ => { @@ -191,9 +191,10 @@ impl Display for Function { write!(f, "{arg}: {ty}")?; } } - if let Some(rety) = rety { - write!(f, " -> {rety}")?; + if TyKind::Empty != rety.kind { + write!(f, " -> {rety}")? } + match body { Some(body) => write!(f, " {body}"), None => ';'.fmt(f), @@ -246,8 +247,8 @@ impl Display for Variant { impl Display for Impl { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { target, body } = self; - write!(f, "impl {target} ")?; + let Self { gens, target, body } = self; + write!(f, "impl{gens} {target} ")?; write!(f.delimit(BRACES), "{body}") } } @@ -285,7 +286,8 @@ impl Display for UseTree { impl Display for Ty { 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::Tuple(v) => v.fmt(f), TyKind::Ref(v) => v.fmt(f), + TyKind::Ptr(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 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { args, rety } = self; write!(f, "fn {args}")?; - match rety { - Some(v) => write!(f, " -> {v}"), - None => Ok(()), + if TyKind::Empty != rety.kind { + write!(f, " -> {rety}")?; } + Ok(()) } } diff --git a/compiler/cl-ast/src/ast_impl/weight_of.rs b/compiler/cl-ast/src/ast_impl/weight_of.rs index 3d15a43..acd2ada 100644 --- a/compiler/cl-ast/src/ast_impl/weight_of.rs +++ b/compiler/cl-ast/src/ast_impl/weight_of.rs @@ -147,8 +147,8 @@ impl WeightOf for Variant { impl WeightOf for Impl { fn weight_of(&self) -> usize { - let Self { target, body } = self; - target.weight_of() + body.weight_of() + let Self { gens, target, body } = self; + gens.weight_of() + target.weight_of() + body.weight_of() } } @@ -184,8 +184,8 @@ impl WeightOf for UseTree { impl WeightOf for Ty { fn weight_of(&self) -> usize { - let Self { span, kind } = self; - span.weight_of() + kind.weight_of() + let Self { span, kind, gens } = self; + span.weight_of() + kind.weight_of() + gens.weight_of() } } @@ -198,6 +198,7 @@ impl WeightOf for TyKind { TyKind::Slice(v) => v.weight_of(), TyKind::Tuple(v) => v.weight_of(), TyKind::Ref(v) => v.weight_of(), + TyKind::Ptr(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 { fn weight_of(&self) -> usize { let Self { args, rety } = self; diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index 19f414e..09b03f5 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -156,8 +156,12 @@ pub trait Fold { } } fn fold_impl(&mut self, i: Impl) -> Impl { - let Impl { target, body } = i; - Impl { target: self.fold_impl_kind(target), body: self.fold_file(body) } + let Impl { gens, target, body } = i; + 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 { or_fold_impl_kind(self, kind) @@ -170,39 +174,39 @@ pub trait Fold { or_fold_use_tree(self, tree) } fn fold_ty(&mut self, t: Ty) -> Ty { - let Ty { span, kind } = t; - Ty { span: self.fold_span(span), kind: self.fold_ty_kind(kind) } + let Ty { span, kind, gens } = t; + 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 { or_fold_ty_kind(self, kind) } fn fold_ty_array(&mut self, a: TyArray) -> TyArray { 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 { 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 { let TyTuple { types } = t; - TyTuple { - types: types - .into_iter() - .map(|kind| self.fold_ty_kind(kind)) - .collect(), - } + TyTuple { types: types.into_iter().map(|kind| self.fold_ty(kind)).collect() } } fn fold_ty_ref(&mut self, t: TyRef) -> TyRef { let TyRef { mutable, count, to } = t; 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 { let TyFn { args, rety } = t; - TyFn { - args: Box::new(self.fold_ty_kind(*args)), - rety: rety.map(|t| Box::new(self.fold_ty(*t))), - } + TyFn { args: Box::new(self.fold_ty(*args)), rety: Box::new(self.fold_ty(*rety)) } } fn fold_path(&mut self, p: Path) -> Path { let Path { absolute, parts } = p; @@ -534,6 +538,7 @@ pub fn or_fold_ty_kind(folder: &mut F, kind: TyKind) -> TyKind TyKind::Slice(s) => TyKind::Slice(folder.fold_ty_slice(s)), TyKind::Tuple(t) => TyKind::Tuple(folder.fold_ty_tuple(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)), } } diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index a82af65..da5c69d 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -131,6 +131,9 @@ pub trait Visit<'a>: Sized { fn visit_ty_ref(&mut self, value: &'a TyRef) { value.children(self) } + fn visit_ty_ptr(&mut self, value: &'a TyPtr) { + value.children(self) + } fn visit_ty_fn(&mut self, value: &'a TyFn) { value.children(self) } diff --git a/compiler/cl-ast/src/ast_visitor/walk.rs b/compiler/cl-ast/src/ast_visitor/walk.rs index 0383329..25b6c1c 100644 --- a/compiler/cl-ast/src/ast_visitor/walk.rs +++ b/compiler/cl-ast/src/ast_visitor/walk.rs @@ -297,7 +297,8 @@ impl Walk for Impl { v.visit_impl(self); } 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); body.visit_in(v); } @@ -354,9 +355,10 @@ impl Walk for Ty { v.visit_ty(self); } 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); kind.visit_in(v); + gens.visit_in(v); } } impl Walk for TyKind { @@ -374,6 +376,7 @@ impl Walk for TyKind { TyKind::Slice(value) => value.visit_in(v), TyKind::Tuple(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), } } @@ -420,6 +423,16 @@ impl Walk for TyRef { 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 { #[inline] 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) { let For { bind, cond, pass, fail } = self; - bind.visit_in(v); cond.visit_in(v); - pass.visit_in(v); fail.visit_in(v); + bind.visit_in(v); + pass.visit_in(v); } } impl Walk for Else { diff --git a/compiler/cl-ast/src/desugar/path_absoluter.rs b/compiler/cl-ast/src/desugar/path_absoluter.rs index 7aeed5b..1d1134e 100644 --- a/compiler/cl-ast/src/desugar/path_absoluter.rs +++ b/compiler/cl-ast/src/desugar/path_absoluter.rs @@ -46,7 +46,7 @@ impl Fold for NormalizePaths { if !absolute { for segment in self.path.parts.iter().rev() { - tree = UseTree::Path(segment.clone(), Box::new(tree)) + tree = UseTree::Path(*segment, Box::new(tree)) } } diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index 06e47b1..fd7fa63 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -191,6 +191,17 @@ macro path_like() { TokenKind::Super | TokenKind::SelfTy | TokenKind::Identifier | TokenKind::ColonColon } +type Spanned = (T, Span); + +impl<'t, T: Parse<'t>> Parse<'t> for Spanned { + fn parse(p: &mut Parser<'t>) -> PResult { + let head = p.loc(); + let body = p.parse()?; + let tail = p.loc(); + Ok((body, Span(head, tail))) + } +} + pub trait Parse<'t>: Sized { /// Parses a Self from the provided [Parser] fn parse(p: &mut Parser<'t>) -> PResult; @@ -343,8 +354,8 @@ impl Parse<'_> for ItemKind { impl Parse<'_> for Generics { fn parse(p: &mut Parser<'_>) -> PResult { const P: Parsing = Parsing::Generics; - let vars = match p.peek_kind(P)? { - TokenKind::Lt => delim( + let vars = match p.peek_kind(P) { + Ok(TokenKind::Lt) => delim( sep(Sym::parse, TokenKind::Comma, TokenKind::Gt, P), (TokenKind::Lt, TokenKind::Gt), P, @@ -451,17 +462,16 @@ impl Parse<'_> for Function { let name = Sym::parse(p)?; let gens = Generics::parse(p)?; - let (bind, types) = delim(FnSig::parse, PARENS, P)(p)?; + let ((bind, types), span) = delim(Spanned::::parse, PARENS, P)(p)?; let sign = TyFn { args: Box::new(match types.len() { - 0 => TyKind::Empty, - _ => TyKind::Tuple(TyTuple { types }), + 0 => Ty { span, kind: TyKind::Empty, gens: Default::default() }, + _ => 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 { name, @@ -479,7 +489,7 @@ impl Parse<'_> for Function { } } -type FnSig = (Pattern, Vec); +type FnSig = (Pattern, Vec); impl Parse<'_> for FnSig { /// 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 { /// Parses a single function parameter - fn parse(p: &mut Parser) -> PResult<(Pattern, TyKind)> { + fn parse(p: &mut Parser) -> PResult<(Pattern, Ty)> { Ok(( Pattern::parse(p)?, if p.match_type(TokenKind::Colon, Parsing::Param).is_ok() { - TyKind::parse(p)? + Ty::parse(p)? } 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; 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] fn parse(p: &mut Parser<'_>) -> PResult { - let start = p.loc(); - Ok(Ty { kind: TyKind::parse(p)?, span: Span(start, p.loc()) }) + let (kind, span) = p.parse()?; + let gens = p.parse()?; + Ok(Ty { span, kind, gens }) } } @@ -699,9 +714,10 @@ impl Parse<'_> for TyKind { TyKind::Never } TokenKind::Amp | TokenKind::AmpAmp => TyRef::parse(p)?.into(), + TokenKind::Star => TyPtr::parse(p)?.into(), TokenKind::LBrack => { 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() { true => { 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))? }; ( - TyKind::Array(TyArray { ty: Box::new(ty), count: count as _ }), + TyKind::Array(TyArray { ty, count: count as _ }), Parsing::TyArray, ) } - false => ( - TyKind::Slice(TySlice { ty: Box::new(ty) }), - Parsing::TySlice, - ), + false => (TyKind::Slice(TySlice { ty }), Parsing::TySlice), }; p.match_type(BRACKETS.1, kind)?; out @@ -748,9 +761,7 @@ impl Parse<'_> for TyTuple { /// [TyTuple] = `(` ([Ty] `,`)* [Ty]? `)` fn parse(p: &mut Parser) -> PResult { const P: Parsing = Parsing::TyTuple; - Ok(TyTuple { - types: delim(sep(TyKind::parse, TokenKind::Comma, PARENS.1, P), PARENS, P)(p)?, - }) + Ok(TyTuple { types: delim(sep(Ty::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 { + const P: Parsing = Parsing::TyRef; + p.match_type(TokenKind::Star, P)?; + Ok(TyPtr { to: p.parse()? }) + } +} + impl Parse<'_> for TyFn { /// [TyFn] = `fn` [TyTuple] (-> [Ty])? fn parse(p: &mut Parser) -> PResult { const P: Parsing = Parsing::TyFn; 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 { args: Box::new(match args { - t if t.is_empty() => TyKind::Empty, - types => TyKind::Tuple(TyTuple { types }), + t if t.is_empty() => Ty { kind: TyKind::Empty, span, gens: Default::default() }, + 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] fn parse(p: &mut Parser) -> PResult { - let start = p.loc(); - Ok(Stmt { - kind: StmtKind::parse(p)?, - semi: match p.match_type(TokenKind::Semi, Parsing::Stmt) { - Ok(_) => Semi::Terminated, - _ => Semi::Unterminated, - }, - span: Span(start, p.loc()), - }) + let (kind, span) = Spanned::::parse(p)?; + let semi = match p.match_type(TokenKind::Semi, Parsing::Stmt) { + Ok(_) => Semi::Terminated, + _ => Semi::Unterminated, + }; + Ok(Stmt { span, kind, semi }) } } @@ -1132,7 +1152,7 @@ impl Parse<'_> for Pattern { // Name, Path, Struct, TupleStruct TokenKind::Identifier => pathpattern(p)?, // Literal - TokenKind::Literal => Pattern::Literal(p.parse()?), + TokenKind::True | TokenKind::False | TokenKind::Literal => Pattern::Literal(p.parse()?), // Rest TokenKind::DotDot => { p.consume_peeked(); diff --git a/compiler/cl-parser/src/parser/prec.rs b/compiler/cl-parser/src/parser/prec.rs index 4ee9e6b..0bfbc14 100644 --- a/compiler/cl-parser/src/parser/prec.rs +++ b/compiler/cl-parser/src/parser/prec.rs @@ -204,13 +204,7 @@ fn exprkind_array_rep(p: &mut Parser) -> PResult { value: first.into(), repeat: { p.consume_peeked(); - let value = p.match_type(TokenKind::Literal, Parsing::ArrayRep)?; - match value.data() { - TokenData::Integer(size) => *size as usize, - _ => { - Err(p.error(ErrorKind::Unexpected(TokenKind::Literal), Parsing::ArrayRep))? - } - } + p.parse()? }, } .into(), diff --git a/compiler/cl-repl/examples/to_c.rs b/compiler/cl-repl/examples/to_c.rs index a69923f..9af863b 100644 --- a/compiler/cl-repl/examples/to_c.rs +++ b/compiler/cl-repl/examples/to_c.rs @@ -273,7 +273,7 @@ pub mod clangify { fn print(&self, y: &mut CLangifier) { let Self { name, gens: _, sign, bind, body } = self; let TyFn { args, rety } = sign; - let types = match args.as_ref() { + let types = match &args.kind { TyKind::Tuple(TyTuple { types }) => types.as_slice(), TyKind::Empty => &[], _ => panic!("Unsupported function args: {args}"), @@ -282,13 +282,7 @@ pub mod clangify { Pattern::Tuple(tup) => tup.as_slice(), _ => panic!("Unsupported function binders: {args}"), }; - match rety { - Some(ty) => y.p(ty), - None => y.p("void"), - } - .p(" ") - .p(name) - .p(" ("); + y.p(rety).p(" ").p(name).p(" ("); for (idx, (bind, ty)) in bind.iter().zip(types).enumerate() { if idx > 0 { y.p(", "); @@ -347,8 +341,8 @@ pub mod clangify { } impl CLangify for Impl { fn print(&self, y: &mut CLangifier) { - let Self { target, body } = self; - y.nest("/* TODO: impl ").p(target).p(" { */ "); + let Self { gens, target, body } = self; + y.nest("/* TODO: impl ").p(gens).p(target).p(" { */ "); y.p(body); y.p("/* } // impl ").p(target).p(" */ "); } @@ -477,7 +471,7 @@ pub mod clangify { } TyKind::Fn(TyFn { args, rety }) => { y.nest("(").p(rety).p(" *").p(mutable).p(name).p(")("); - match args.as_ref() { + match &args.kind { TyKind::Empty => {} TyKind::Tuple(TyTuple { types }) => { for (idx, ty) in types.iter().enumerate() { @@ -688,14 +682,14 @@ pub mod clangify { impl CLangify for ArrayRep { fn print(&self, y: &mut CLangifier) { 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("{"); - y.endl(); - for idx in 0..*repeat { - if idx > 0 { - y.p(", "); - } - y.p(value); + for _ in 0..*repeat { + y.endl().p(value).p(","); } } y.endl().p("}"); @@ -797,7 +791,7 @@ pub mod clangify { } impl CLangify for Ty { fn print(&self, y: &mut CLangifier) { - let Self { span: _, kind } = self; + let Self { span: _, kind, gens: _ } = self; y.p(kind); } } @@ -806,10 +800,11 @@ pub mod clangify { match self { TyKind::Never => y.p("Never"), TyKind::Empty => y.p("Empty"), - TyKind::Infer => y.p("Any"), + TyKind::Infer => y.p("auto"), TyKind::Path(t) => y.p(t), TyKind::Tuple(t) => y.p(t), TyKind::Ref(t) => y.p(t), + TyKind::Ptr(t) => y.p(t), TyKind::Fn(t) => y.p(t), TyKind::Slice(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 { fn print(&self, y: &mut CLangifier) { let Self { args, rety } = self; // TODO: function pointer syntax y.nest("(").p(rety).p(" *)("); - match args.as_ref() { + match &args.kind { TyKind::Empty => y, TyKind::Tuple(TyTuple { types }) => { for (idx, ty) in types.iter().enumerate() { diff --git a/compiler/cl-repl/examples/yaml.rs b/compiler/cl-repl/examples/yaml.rs index 4cfefd5..c18bdce 100644 --- a/compiler/cl-repl/examples/yaml.rs +++ b/compiler/cl-repl/examples/yaml.rs @@ -83,7 +83,7 @@ pub mod yamler { pub fn key(&mut self, name: impl Yamlify) -> Section { println!(); self.print_indentation(&mut std::io::stdout().lock()); - print!("- "); + print!(" "); name.yaml(self); print!(":"); self.indent() @@ -103,8 +103,10 @@ pub mod yamler { } pub fn list(&mut self, list: &[D]) -> &mut Self { - for (idx, value) in list.iter().enumerate() { - self.pair(idx, value); + for value in list { + println!(); + self.print_indentation(&mut std::io::stdout().lock()); + self.yaml(&"- ").yaml(value); } self } @@ -302,8 +304,11 @@ pub mod yamlify { } impl Yamlify for Impl { fn yaml(&self, y: &mut Yamler) { - let Self { target, body } = self; - y.key("Impl").pair("target", target).pair("body", body); + let Self { gens, target, body } = self; + y.key("Impl") + .pair("gens", gens) + .pair("target", target) + .pair("body", body); } } impl Yamlify for ImplKind { @@ -536,7 +541,10 @@ pub mod yamlify { impl Yamlify for Index { fn yaml(&self, y: &mut Yamler) { 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 { @@ -589,7 +597,7 @@ pub mod yamlify { impl Yamlify for Else { fn yaml(&self, y: &mut Yamler) { let Self { body } = self; - y.key("Else").yaml(body); + y.key("fail").yaml(body); } } impl Yamlify for If { @@ -633,8 +641,8 @@ pub mod yamlify { } impl Yamlify for Ty { fn yaml(&self, y: &mut Yamler) { - let Self { span: _, kind } = self; - y.key("Ty").yaml(kind); + let Self { span: _, kind, gens } = self; + y.key("Ty").yaml(kind).yaml(gens); } } impl Yamlify for TyKind { @@ -646,6 +654,7 @@ pub mod yamlify { TyKind::Path(t) => y.yaml(t), TyKind::Tuple(t) => y.yaml(t), TyKind::Ref(t) => y.yaml(t), + TyKind::Ptr(t) => y.yaml(t), TyKind::Fn(t) => y.yaml(t), TyKind::Slice(t) => y.yaml(t), TyKind::Array(t) => y.yaml(t), @@ -659,9 +668,7 @@ pub mod yamlify { if *absolute { y.pair("absolute", absolute); } - for part in parts { - y.pair("part", part); - } + y.yaml(parts); } } impl Yamlify for PathPart { @@ -703,6 +710,13 @@ pub mod yamlify { .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 { fn yaml(&self, y: &mut Yamler) { let Self { args, rety } = self; @@ -726,9 +740,7 @@ pub mod yamlify { } impl Yamlify for Vec { fn yaml(&self, y: &mut Yamler) { - for thing in self { - y.yaml(thing); - } + y.list(self); } } impl Yamlify for () { diff --git a/compiler/cl-typeck/src/entry/display.rs b/compiler/cl-typeck/src/entry/display.rs index 805393d..6d89d51 100644 --- a/compiler/cl-typeck/src/entry/display.rs +++ b/compiler/cl-typeck/src/entry/display.rs @@ -28,6 +28,11 @@ impl fmt::Display for Entry<'_, '_> { let h_id = self.with_id(id); 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) => { 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(); separate(", ", || { variants.next().map(|(name, def)| { - move |f: &mut Delimit<_>| { - write!(f, "{name}: ")?; - write_name_or(h.with_id(*def), f) - } + move |f: &mut Delimit<_>| write!(f, "{name}: {}", h.with_id(*def)) }) })(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(); separate(", ", || { let (name, vis, id) = members.next()?; - Some(move |f: &mut Delimit<_>| { - write!(f, "{vis}{name}: ")?; - write_name_or(h.with_id(*id), f) - }) + Some(move |f: &mut Delimit<_>| write!(f, "{vis}{name}: {}", h.with_id(*id))) })(f.delimit_with("struct {", "}")) } Adt::TupleStruct(members) => { let mut members = members.iter(); separate(", ", || { let (vis, def) = members.next()?; - Some(move |f: &mut Delimit<_>| { - write!(f, "{vis}")?; - write_name_or(h.with_id(*def), f) - }) + Some(move |f: &mut Delimit<_>| write!(f, "{vis}{}", h.with_id(*def))) })(f.delimit_with("struct (", ")")) } Adt::UnitStruct => write!(f, "struct"), diff --git a/compiler/cl-typeck/src/stage/import.rs b/compiler/cl-typeck/src/stage/import.rs index aae9e9a..a219e9c 100644 --- a/compiler/cl-typeck/src/stage/import.rs +++ b/compiler/cl-typeck/src/stage/import.rs @@ -70,7 +70,7 @@ fn import_tree<'a>( UseTree::Path(part, rest) => { let source = table .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) } UseTree::Alias(src_name, dst_name) => { diff --git a/compiler/cl-typeck/src/stage/infer/engine.rs b/compiler/cl-typeck/src/stage/infer/engine.rs index 0fd6101..8a2194a 100644 --- a/compiler/cl-typeck/src/stage/infer/engine.rs +++ b/compiler/cl-typeck/src/stage/infer/engine.rs @@ -496,6 +496,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> { todo!() } (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), // Slice unifies with array (TypeKind::Array(a, _), TypeKind::Slice(b)) => self.unify(*a, *b), diff --git a/compiler/cl-typeck/src/table.rs b/compiler/cl-typeck/src/table.rs index 3239cff..f70ff41 100644 --- a/compiler/cl-typeck/src/table.rs +++ b/compiler/cl-typeck/src/table.rs @@ -121,7 +121,7 @@ impl<'a> Table<'a> { self.impls.push(item); } - pub fn handle_iter(&mut self) -> impl Iterator + use<> { + pub fn handle_iter(&self) -> impl Iterator + use<> { self.kinds.keys() } diff --git a/compiler/cl-typeck/src/type_expression.rs b/compiler/cl-typeck/src/type_expression.rs index c9b9b9d..fefb533 100644 --- a/compiler/cl-typeck/src/type_expression.rs +++ b/compiler/cl-typeck/src/type_expression.rs @@ -2,7 +2,7 @@ //! construct type bindings in a [Table]'s typing context. 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 pub enum Error { @@ -48,6 +48,7 @@ impl TypeExpression for TyKind { TyKind::Slice(s) => s.evaluate(table, node), TyKind::Tuple(t) => t.evaluate(table, node), TyKind::Ref(r) => r.evaluate(table, node), + TyKind::Ptr(r) => r.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 { + let path = [PathPart::Ident(*self)]; + table + .nav(node, &path) + .ok_or_else(|| Error::BadPath { parent: node, path: path.to_vec() }) + } +} + impl TypeExpression for TyArray { fn evaluate(&self, table: &mut Table, node: Handle) -> Result { 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 { + let Self { to } = self; + let mut t = to.evaluate(table, node)?; + t = table.anon_type(TypeKind::Ptr(t)); + Ok(t) + } +} + impl TypeExpression for TyFn { fn evaluate(&self, table: &mut Table, node: Handle) -> Result { let Self { args, rety } = self; let kind = TypeKind::FnSig { args: args.evaluate(table, node)?, - rety: match rety { - Some(ty) => ty.evaluate(table, node)?, - None => TyKind::Empty.evaluate(table, node)?, - }, + rety: rety.evaluate(table, node)?, }; Ok(table.anon_type(kind)) } diff --git a/compiler/cl-typeck/src/type_kind.rs b/compiler/cl-typeck/src/type_kind.rs index b71ed48..3d59dd2 100644 --- a/compiler/cl-typeck/src/type_kind.rs +++ b/compiler/cl-typeck/src/type_kind.rs @@ -22,6 +22,8 @@ pub enum TypeKind { Adt(Adt), /// A reference to an already-defined type: &T Ref(Handle), + /// A raw pointer to an already-defined type: &T + Ptr(Handle), /// A contiguous view of dynamically sized memory Slice(Handle), /// A contiguous view of statically sized memory @@ -67,6 +69,7 @@ pub enum Primitive { Integer, Float, // Inferred int and float Bool, // boolean value Char, // Unicode codepoint + Str, // UTF-8 string } #[rustfmt::skip] @@ -117,6 +120,7 @@ impl FromStr for Primitive { "fsize" => Primitive::Fsize, "bool" => Primitive::Bool, "char" => Primitive::Char, + "str" => Primitive::Str, _ => Err(())?, }) } diff --git a/compiler/cl-typeck/src/type_kind/display.rs b/compiler/cl-typeck/src/type_kind/display.rs index 104341f..dc1a6d0 100644 --- a/compiler/cl-typeck/src/type_kind/display.rs +++ b/compiler/cl-typeck/src/type_kind/display.rs @@ -14,6 +14,7 @@ impl Display for TypeKind { TypeKind::Primitive(i) => i.fmt(f), TypeKind::Adt(a) => a.fmt(f), TypeKind::Ref(def) => write!(f, "&{def}"), + TypeKind::Ptr(def) => write!(f, "*{def}"), TypeKind::Slice(def) => write!(f, "slice [#{def}]"), TypeKind::Array(def, size) => write!(f, "array [#{def}; {size}]"), TypeKind::Tuple(defs) => { @@ -92,6 +93,7 @@ impl Display for Primitive { Primitive::Float => f.write_str("{float}"), Primitive::Bool => f.write_str("bool"), Primitive::Char => f.write_str("char"), + Primitive::Str => f.write_str("str"), } } }