Add operators, math, time, string, collection, and HOF builtins to El

This commit is contained in:
Will Anderson
2026-04-29 03:58:16 -05:00
parent a42429012e
commit 8d4d9ed786
15 changed files with 972 additions and 19 deletions
+16
View File
@@ -84,6 +84,21 @@ pub enum BinOp {
Add, Sub, Mul, Div,
Eq, NotEq, Lt, Gt, LtEq, GtEq,
And, Or,
Mod, // %
BitAnd, // &
BitOr, // | (single pipe)
BitXor, // ^
Shl, // <<
Shr, // >>
}
// ── Unary operators ───────────────────────────────────────────────────────────
#[derive(Debug, Clone, PartialEq)]
pub enum UnaryOp {
Neg, // - (unary minus)
Not, // ! (logical not)
BitNot, // ~
}
// ── Expressions ───────────────────────────────────────────────────────────────
@@ -94,6 +109,7 @@ pub enum Expr {
Ident(String),
BinOp { op: BinOp, left: Box<Expr>, right: Box<Expr> },
UnaryNot(Box<Expr>),
UnaryBitNot(Box<Expr>),
Call { func: Box<Expr>, args: Vec<Expr> },
Block(Vec<Stmt>),
Match { subject: Box<Expr>, arms: Vec<MatchArm> },
+1 -1
View File
@@ -11,7 +11,7 @@ mod error;
mod parser;
pub use ast::{
BinOp, Decorator, Expr, Field, Literal, MatchArm, Param, Pattern, Program, ProtocolMethod,
BinOp, UnaryOp, Decorator, Expr, Field, Literal, MatchArm, Param, Pattern, Program, ProtocolMethod,
SeedStmt, Stmt, TestTarget, TypeExpr, Variant,
};
pub use error::{ParseError, ParseErrorKind};
+48 -1
View File
@@ -717,6 +717,48 @@ impl Parser {
self.parse_pipe_expr()
}
fn parse_bitwise_or_expr(&mut self) -> Result<Expr, ParseError> {
let mut left = self.parse_bitwise_xor_expr()?;
while self.eat(&Token::Pipe) {
let right = self.parse_bitwise_xor_expr()?;
left = Expr::BinOp { op: BinOp::BitOr, left: Box::new(left), right: Box::new(right) };
}
Ok(left)
}
fn parse_bitwise_xor_expr(&mut self) -> Result<Expr, ParseError> {
let mut left = self.parse_bitwise_and_expr()?;
while self.eat(&Token::Caret) {
let right = self.parse_bitwise_and_expr()?;
left = Expr::BinOp { op: BinOp::BitXor, left: Box::new(left), right: Box::new(right) };
}
Ok(left)
}
fn parse_bitwise_and_expr(&mut self) -> Result<Expr, ParseError> {
let mut left = self.parse_shift_expr()?;
while self.eat(&Token::Ampersand) {
let right = self.parse_shift_expr()?;
left = Expr::BinOp { op: BinOp::BitAnd, left: Box::new(left), right: Box::new(right) };
}
Ok(left)
}
fn parse_shift_expr(&mut self) -> Result<Expr, ParseError> {
let mut left = self.parse_additive()?;
loop {
let op = match self.peek() {
Token::Shl => BinOp::Shl,
Token::Shr => BinOp::Shr,
_ => break,
};
self.advance();
let right = self.parse_additive()?;
left = Expr::BinOp { op, left: Box::new(left), right: Box::new(right) };
}
Ok(left)
}
/// pipe_expr = or_expr (|> ident)*
/// `a |> f` desugars to `Call(f, [a])`
fn parse_pipe_expr(&mut self) -> Result<Expr, ParseError> {
@@ -766,7 +808,7 @@ impl Parser {
}
fn parse_comparison(&mut self) -> Result<Expr, ParseError> {
let mut left = self.parse_additive()?;
let mut left = self.parse_bitwise_or_expr()?;
loop {
let op = match self.peek() {
Token::Lt => BinOp::Lt,
@@ -803,6 +845,7 @@ impl Parser {
let op = match self.peek() {
Token::Star => BinOp::Mul,
Token::Slash => BinOp::Div,
Token::Percent => BinOp::Mod,
_ => break,
};
self.advance();
@@ -817,6 +860,10 @@ impl Parser {
let inner = self.parse_unary()?;
return Ok(Expr::UnaryNot(Box::new(inner)));
}
if self.eat(&Token::Tilde) {
let inner = self.parse_unary()?;
return Ok(Expr::UnaryBitNot(Box::new(inner)));
}
self.parse_postfix()
}