steal from jai

This commit is contained in:
2026-06-01 22:40:24 -04:00
parent d864adfd05
commit 1d568f8ce3
17 changed files with 231 additions and 84 deletions
+92 -8
View File
@@ -3,22 +3,48 @@ use crate::parser::VecDspT;
pub use super::*;
pub struct Expr {
span: Span,
ty: ExprTy,
pub span: Span,
pub ty: ExprTy,
}
pub enum ExprTy {
Block(Body),
Group(Box<Expr>),
Member {
of: Box<Expr>,
field: Ident,
},
Ident(Ident),
Lit(Lit),
Negate(Box<Expr>),
Call { target: Box<Expr>, args: Vec<Expr> },
Assign { target: Box<Expr>, val: Box<Expr> },
If { cond: Box<Expr>, body: Box<Expr> },
Loop { body: Box<Expr> },
While { cond: Box<Expr>, body: Box<Expr> },
Call {
target: Box<Expr>,
args: Vec<Expr>,
},
Assign {
target: Box<Expr>,
val: Box<Expr>,
},
Define {
target: Box<Expr>,
ty: Option<Type>,
const_: bool,
val: Box<Expr>,
},
If {
cond: Box<Expr>,
body: Box<Expr>,
},
Loop {
body: Box<Expr>,
},
While {
cond: Box<Expr>,
body: Box<Expr>,
},
Import(Ident),
Fn(Box<Func>),
Break,
}
impl Node for Expr {
@@ -32,12 +58,39 @@ impl Node for Expr {
let val = Box::new(ctx.parse_with(Self::unit)?);
ExprTy::Assign { target, val }
}
Token::Colon => {
ctx.next();
let target = Box::new(res);
let mut ty = None;
let next = ctx.expect_peek()?;
if !matches!(next, Token::Equal | Token::Colon) {
ty = Some(ctx.parse()?);
}
let const_ = match ctx.expect_next()? {
Token::Equal => false,
Token::Colon => true,
t => ctx.unexpected(t, "an equals = or colon :")?,
};
let val = Box::new(ctx.parse_with(Self::unit)?);
ExprTy::Define {
target,
ty,
val,
const_,
}
}
Token::OpenParen => {
ctx.next();
let target = Box::new(res);
let args = ctx.list(Token::Comma, Token::CloseParen)?;
ExprTy::Call { target, args }
}
Token::Dot => {
ctx.next();
let of = Box::new(res);
let field = ctx.parse()?;
ExprTy::Member { of, field }
}
_ => break,
};
res = Self {
@@ -69,6 +122,21 @@ impl ExprTy {
Self::Assign { target, val } => {
write!(f, "{} = {}", target.dsp(ctx), val.dsp(ctx))
}
Self::Define {
target,
ty,
val,
const_,
} => {
write!(f, "{} :", target.dsp(ctx))?;
if let Some(ty) = ty {
write!(f, " {} ", ty.dsp(ctx))?;
}
write!(f, "{} {}", if *const_ { ":" } else { "=" }, val.dsp(ctx))
}
Self::Member { of, field } => {
write!(f, "{}.{field}", of.dsp(ctx))
}
Self::If { cond, body } => {
write!(f, "if {} {}", cond.dsp(ctx), body.dsp(ctx))
}
@@ -88,6 +156,12 @@ impl ExprTy {
write!(f, "}}")?;
Ok(())
}
Self::Import(ident) => {
write!(f, "import {ident}")
}
Self::Break => {
write!(f, "break")
}
}
}
}
@@ -137,7 +211,12 @@ impl Expr {
ctx.expect(Token::CloseCurly)?;
ExprTy::Block(body)
}
other => return ctx.unexpected(&other, "an expression"),
Token::Break => ExprTy::Break,
Token::Import => {
let ident = ctx.parse()?;
ExprTy::Import(ident)
}
other => return ctx.unexpected(other, "an expression"),
};
Ok(Self {
ty,
@@ -179,8 +258,13 @@ impl Expr {
| ExprTy::If { body, .. }
| ExprTy::Negate(body)
| ExprTy::Assign { val: body, .. } => body.ends_with_block(),
| ExprTy::Define { val: body, .. } => body.ends_with_block(),
ExprTy::Fn(f) => f.ends_with_block(),
_ => false,
}
}
pub fn needs_semicolon(&self) -> bool {
!self.ends_with_block()
}
}