conlang: RIP THE EXPRKIND BANDAGE OFF

cl-ast: No more bare ExprKind: every Expr has a Span
cl-interpret: Give errors a span
cl-repl: Print eval errors in load_file, instead of returning them. These changes are relevant.
This commit is contained in:
2025-03-11 00:36:42 -05:00
parent c0ad544486
commit 7e311cb0ef
14 changed files with 213 additions and 163 deletions

View File

@@ -1,6 +1,6 @@
use super::*;
use cl_ast::ExprKind;
use cl_ast::Expr;
use cl_lexer::error::{Error as LexError, Reason};
use std::fmt::Display;
pub type PResult<T> = Result<T, Error>;
@@ -30,7 +30,7 @@ pub enum ErrorKind {
ExpectedParsing {
want: Parsing,
},
InvalidPattern(Box<ExprKind>),
InvalidPattern(Box<Expr>),
/// Indicates unfinished code
Todo(&'static str),
}
@@ -135,7 +135,7 @@ impl Display for Error {
ErrorKind::Todo(_) => write!(f, "{loc} {reason} {while_parsing:?}"),
// lexical errors print their own higher-resolution loc info
ErrorKind::Lexical(e) => write!(f, "{e} (while parsing {while_parsing})"),
_ => write!(f, "{loc} {reason} while parsing {while_parsing}"),
_ => write!(f, "{loc}: {reason} while parsing {while_parsing}"),
}
}
}

View File

@@ -888,26 +888,15 @@ impl Parse<'_> for StmtKind {
impl Parse<'_> for Expr {
/// Parses an [Expr]
///
/// See also: [ExprKind::parse]
fn parse(p: &mut Parser) -> PResult<Expr> {
let start = p.loc();
Ok(Expr { kind: ExprKind::parse(p)?, extents: Span(start, p.loc()) })
}
}
impl Parse<'_> for ExprKind {
/// Parses an [ExprKind] at the lowest precedence level
// Implementer's note: Do not call this from within [prec::exprkind]
fn parse(p: &mut Parser<'_>) -> PResult<ExprKind> {
prec::exprkind(p, 0)
prec::expr(p, 0)
}
}
impl Parse<'_> for Quote {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let quote = delim(
ExprKind::parse,
Expr::parse,
(TokenKind::Grave, TokenKind::Grave),
Parsing::ExprKind,
)(p)?
@@ -981,16 +970,20 @@ impl Parse<'_> for AddrOf {
match p.peek_kind(P)? {
TokenKind::Amp => {
p.consume_peeked();
Ok(AddrOf { mutable: Mutability::parse(p)?, expr: ExprKind::parse(p)?.into() })
Ok(AddrOf { mutable: Mutability::parse(p)?, expr: Expr::parse(p)?.into() })
}
TokenKind::AmpAmp => {
let start = p.loc();
p.consume_peeked();
Ok(AddrOf {
mutable: Mutability::Not,
expr: ExprKind::AddrOf(AddrOf {
mutable: Mutability::parse(p)?,
expr: ExprKind::parse(p)?.into(),
})
expr: Expr {
kind: ExprKind::AddrOf(AddrOf {
mutable: Mutability::parse(p)?,
expr: Expr::parse(p)?.into(),
}),
extents: Span(start, p.loc()),
}
.into(),
})
}
@@ -1009,9 +1002,7 @@ impl Parse<'_> for Block {
/// Conditions (which precede curly-braced blocks) get special treatment
fn condition(p: &mut Parser) -> PResult<Expr> {
let start = p.loc();
let kind = prec::exprkind(p, prec::Precedence::Condition.level())?;
Ok(Expr { kind, extents: Span(start, p.loc()) })
prec::expr(p, prec::Precedence::Condition.level())
}
impl Parse<'_> for While {
@@ -1088,7 +1079,7 @@ impl Parse<'_> for Return {
impl Parse<'_> for Pattern {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let value = prec::exprkind(p, prec::Precedence::Pattern.level())?;
let value = prec::expr(p, prec::Precedence::Pattern.level())?;
Pattern::try_from(value).map_err(|e| p.error(InvalidPattern(e.into()), Parsing::Pattern))
}
}

View File

@@ -8,36 +8,40 @@
use super::{Parse, *};
/// Parses an [ExprKind]
pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
pub fn expr(p: &mut Parser, power: u8) -> PResult<Expr> {
let parsing = Parsing::ExprKind;
let start = p.loc();
// Prefix expressions
let mut head = match p.peek_kind(Parsing::Unary)? {
literal_like!() => Literal::parse(p)?.into(),
path_like!() => exprkind_pathlike(p)?,
TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
TokenKind::Grave => Quote::parse(p)?.into(),
TokenKind::LCurly => Block::parse(p)?.into(),
TokenKind::LBrack => exprkind_arraylike(p)?,
TokenKind::LParen => exprkind_tuplelike(p)?,
TokenKind::Let => Let::parse(p)?.into(),
TokenKind::Match => Match::parse(p)?.into(),
TokenKind::While => ExprKind::While(While::parse(p)?),
TokenKind::If => ExprKind::If(If::parse(p)?),
TokenKind::For => ExprKind::For(For::parse(p)?),
TokenKind::Break => ExprKind::Break(Break::parse(p)?),
TokenKind::Return => ExprKind::Return(Return::parse(p)?),
TokenKind::Continue => {
p.consume_peeked();
ExprKind::Continue
}
let mut head = Expr {
kind: match p.peek_kind(Parsing::Unary)? {
literal_like!() => Literal::parse(p)?.into(),
path_like!() => exprkind_pathlike(p)?,
TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
TokenKind::Grave => Quote::parse(p)?.into(),
TokenKind::LCurly => Block::parse(p)?.into(),
TokenKind::LBrack => exprkind_arraylike(p)?,
TokenKind::LParen => exprkind_tuplelike(p)?,
TokenKind::Let => Let::parse(p)?.into(),
TokenKind::Match => Match::parse(p)?.into(),
TokenKind::While => ExprKind::While(While::parse(p)?),
TokenKind::If => ExprKind::If(If::parse(p)?),
TokenKind::For => ExprKind::For(For::parse(p)?),
TokenKind::Break => ExprKind::Break(Break::parse(p)?),
TokenKind::Return => ExprKind::Return(Return::parse(p)?),
TokenKind::Continue => {
p.consume_peeked();
ExprKind::Continue
}
op => {
let (kind, prec) = from_prefix(op).ok_or_else(|| p.error(Unexpected(op), parsing))?;
let ((), after) = prec.prefix().expect("should have a precedence");
p.consume_peeked();
Unary { kind, tail: exprkind(p, after)?.into() }.into()
}
op => {
let (kind, prec) =
from_prefix(op).ok_or_else(|| p.error(Unexpected(op), parsing))?;
let ((), after) = prec.prefix().expect("should have a precedence");
p.consume_peeked();
Unary { kind, tail: expr(p, after)?.into() }.into()
}
},
extents: Span(start, p.loc()),
};
fn from_postfix(op: TokenKind) -> Option<Precedence> {
@@ -58,36 +62,50 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
break;
}
head = match op {
TokenKind::LBrack => {
p.consume_peeked();
let indices =
sep(Expr::parse, TokenKind::Comma, TokenKind::RBrack, parsing)(p)?;
p.match_type(TokenKind::RBrack, parsing)?;
ExprKind::Index(Index { head: head.into(), indices })
}
TokenKind::LParen => {
p.consume_peeked();
let exprs = sep(Expr::parse, TokenKind::Comma, TokenKind::RParen, parsing)(p)?;
p.match_type(TokenKind::RParen, parsing)?;
Binary { kind: BinaryKind::Call, parts: (head, Tuple { exprs }.into()).into() }
head = Expr {
kind: match op {
TokenKind::LBrack => {
p.consume_peeked();
let indices =
sep(Expr::parse, TokenKind::Comma, TokenKind::RBrack, parsing)(p)?;
p.match_type(TokenKind::RBrack, parsing)?;
ExprKind::Index(Index { head: head.into(), indices })
}
TokenKind::LParen => {
p.consume_peeked();
let exprs =
sep(Expr::parse, TokenKind::Comma, TokenKind::RParen, parsing)(p)?;
p.match_type(TokenKind::RParen, parsing)?;
Binary {
kind: BinaryKind::Call,
parts: (
head,
Expr {
kind: Tuple { exprs }.into(),
extents: Span(start, p.loc()),
},
)
.into(),
}
.into()
}
TokenKind::LCurly => match head {
ExprKind::Path(path) => ExprKind::Structor(structor_body(p, path)?),
_ => break,
}
TokenKind::LCurly => match head.kind {
ExprKind::Path(path) => ExprKind::Structor(structor_body(p, path)?),
_ => break,
},
TokenKind::Dot => {
p.consume_peeked();
let kind = MemberKind::parse(p)?;
Member { head: Box::new(head), kind }.into()
}
TokenKind::As => {
p.consume_peeked();
let ty = Ty::parse(p)?;
Cast { head: head.into(), ty }.into()
}
_ => Err(p.error(Unexpected(op), parsing))?,
},
TokenKind::Dot => {
p.consume_peeked();
let kind = MemberKind::parse(p)?;
Member { head: Box::new(head), kind }.into()
}
TokenKind::As => {
p.consume_peeked();
let ty = Ty::parse(p)?;
Cast { head: head.into(), ty }.into()
}
_ => Err(p.error(Unexpected(op), parsing))?,
extents: Span(start, p.loc()),
};
continue;
}
@@ -99,8 +117,11 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
}
p.consume_peeked();
let tail = exprkind(p, after)?;
head = Binary { kind, parts: (head, tail).into() }.into();
let tail = expr(p, after)?;
head = Expr {
kind: Binary { kind, parts: (head, tail).into() }.into(),
extents: Span(start, p.loc()),
};
continue;
}
@@ -111,8 +132,11 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
}
p.consume_peeked();
let tail = exprkind(p, after)?;
head = Modify { kind, parts: (head, tail).into() }.into();
let tail = expr(p, after)?;
head = Expr {
kind: Modify { kind, parts: (head, tail).into() }.into(),
extents: Span(start, p.loc()),
};
continue;
}
@@ -125,8 +149,12 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
}
p.consume_peeked();
let tail = exprkind(p, after)?;
head = Assign { parts: (head, tail).into() }.into();
let tail = expr(p, after)?;
head = Expr {
kind: Assign { parts: (head, tail).into() }.into(),
extents: Span(start, p.loc()),
};
continue;
}
@@ -138,7 +166,9 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
p.consume_peeked();
let ty = Ty::parse(p)?;
head = Cast { head: head.into(), ty }.into();
head =
Expr { kind: Cast { head: head.into(), ty }.into(), extents: Span(start, p.loc()) };
continue;
}
@@ -174,10 +204,10 @@ fn exprkind_array_rep(p: &mut Parser) -> PResult<ExprKind> {
let first = Expr::parse(p)?;
Ok(match p.peek_kind(P)? {
TokenKind::Semi => ArrayRep {
value: first.kind.into(),
value: first.into(),
repeat: {
p.consume_peeked();
Box::new(exprkind(p, 0)?)
Box::new(expr(p, 0)?)
},
}
.into(),
@@ -224,7 +254,7 @@ fn exprkind_group(p: &mut Parser) -> PResult<ExprKind> {
}
Ok(Tuple { exprs }.into())
}
_ => Ok(Group { expr: first.kind.into() }.into()),
_ => Ok(Group { expr: first.into() }.into()),
}
}