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]
#[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<TyKind>,
pub ty: Box<Ty>,
pub count: usize,
}
/// A [Ty]pe slice expression: `[T]`
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TySlice {
pub ty: Box<TyKind>,
pub ty: Box<Ty>,
}
/// A tuple of [Ty]pes
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TyTuple {
pub types: Vec<TyKind>,
pub types: Vec<Ty>,
}
/// A [Ty]pe-reference expression as (number of `&`, [Path])
@ -259,11 +262,17 @@ pub struct TyRef {
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
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TyFn {
pub args: Box<TyKind>,
pub rety: Option<Box<Ty>>,
pub args: Box<Ty>,
pub rety: Box<Ty>,
}
/// 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<Expr>,
pub repeat: usize,
pub repeat: Box<Expr>,
}
/// An address-of expression: `&` `mut`? [`Expr`]

View File

@ -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 {

View File

@ -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(())
}
}

View File

@ -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;

View File

@ -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<F: Fold + ?Sized>(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)),
}
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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))
}
}

View File

@ -191,6 +191,17 @@ macro path_like() {
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 {
/// Parses a Self from the provided [Parser]
fn parse(p: &mut Parser<'t>) -> PResult<Self>;
@ -343,8 +354,8 @@ impl Parse<'_> for ItemKind {
impl Parse<'_> for Generics {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
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::<FnSig>::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<TyKind>);
type FnSig = (Pattern, Vec<Ty>);
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<Self> {
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<TyTuple> {
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<TyPtr> {
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<TyFn> {
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 }),
}),
rety: match p.match_type(TokenKind::Arrow, Parsing::TyFn) {
Ok(_) => Some(Ty::parse(p)?),
Err(_) => None,
t if t.is_empty() => Ty { kind: TyKind::Empty, span, gens: Default::default() },
types => {
Ty { kind: TyKind::Tuple(TyTuple { types }), span, gens: Default::default() }
}
.map(Into::into),
}),
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![] } },
}),
})
}
}
@ -847,15 +870,12 @@ impl Parse<'_> for Stmt {
///
/// See also: [StmtKind::parse]
fn parse(p: &mut Parser) -> PResult<Stmt> {
let start = p.loc();
Ok(Stmt {
kind: StmtKind::parse(p)?,
semi: match p.match_type(TokenKind::Semi, Parsing::Stmt) {
let (kind, span) = Spanned::<StmtKind>::parse(p)?;
let semi = match p.match_type(TokenKind::Semi, Parsing::Stmt) {
Ok(_) => Semi::Terminated,
_ => Semi::Unterminated,
},
span: Span(start, p.loc()),
})
};
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();

View File

@ -204,13 +204,7 @@ fn exprkind_array_rep(p: &mut Parser) -> PResult<ExprKind> {
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(),

View File

@ -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() {

View File

@ -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<D: Yamlify>(&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<T: Yamlify> Yamlify for Vec<T> {
fn yaml(&self, y: &mut Yamler) {
for thing in self {
y.yaml(thing);
}
y.list(self);
}
}
impl Yamlify for () {

View File

@ -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"),

View File

@ -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) => {

View File

@ -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),

View File

@ -121,7 +121,7 @@ impl<'a> Table<'a> {
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()
}

View File

@ -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<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 {
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
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 {
fn evaluate(&self, table: &mut Table, node: Handle) -> Result<Handle, Error> {
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))
}

View File

@ -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(())?,
})
}

View File

@ -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"),
}
}
}