ast: add gens for ty and impl, raw ptr types, make fn return value non-optional
This commit is contained in:
parent
6ba62ac1c4
commit
148ef34a01
@ -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`]
|
||||
|
@ -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 {
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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(),
|
||||
|
@ -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() {
|
||||
|
@ -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 () {
|
||||
|
@ -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"),
|
||||
|
@ -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) => {
|
||||
|
@ -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),
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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(())?,
|
||||
})
|
||||
}
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user