Flatten values into expression grammar

This commit is contained in:
2026-04-30 19:16:51 -06:00
parent a4844b5a59
commit 2093c1d2dd
6 changed files with 2005 additions and 2122 deletions

View File

@@ -223,32 +223,44 @@ pub struct RuleBody<'db> {
/// Parse an expression from the AST.
#[salsa::tracked]
pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
use ir::ExprKind;
use ir::{ExprKind::*, Value::*};
// parse the kind depending on which field is selected
let kind = if let Some(tuple) = ast.get_field(db, "tuple") {
let els = tuple.get_fields(db, "el").map(|el| expr(db, el)).collect();
ExprKind::Extra(Arc::new(ExprExtra::Tuple(els)))
} else if let Some(val) = ast.get_field(db, "hole") {
ExprKind::Extra(Arc::new(ExprExtra::Hole))
} else if let Some(val) = ast.get_field(db, "value") {
ExprKind::Value(value(db, val))
let kind = if let Some(val) = ast.get_field(db, "hole") {
Extra(Arc::new(ExprExtra::Hole))
} else if let Some(var) = ast.get_field(db, "variable") {
let name = var.contents(db).to_string();
ExprKind::Extra(Arc::new(ExprExtra::VariableName(name)))
Extra(Arc::new(ExprExtra::VariableName(name)))
} else if let Some(ast) = ast.get_field(db, "atom") {
Extra(Arc::new(ExprExtra::Apply(apply(db, ast))))
} else if let Some(tuple) = ast.get_field(db, "tuple") {
let els = tuple.get_fields(db, "el").map(|el| expr(db, el)).collect();
Extra(Arc::new(ExprExtra::Tuple(els)))
} else if let Some(ast) = ast.get_field(db, "aggregate") {
Extra(Arc::new(ExprExtra::Aggregate(aggregate(db, ast))))
} else if ast.get_field(db, "true").is_some() {
Value(Boolean(true))
} else if ast.get_field(db, "false").is_some() {
Value(Boolean(false))
} else if let Some(sym) = ast.get_field(db, "symbol") {
todo!()
} else if let Some(int) = ast.get_field(db, "integer") {
Value(match int.contents(db).to_string().parse() {
Ok(val) => Integer(val),
Err(_) => {
diagnostic::SimpleError::new(int, "failed to parse integer literal").accumulate(db);
Integer(0)
}
})
} else if let Some(unary) = ast.get_field(db, "unary") {
let op = unary.expect_field(db, "op").expect_parse(db);
let term = Arc::new(expr(db, unary.expect_field(db, "term")));
UnaryOp { op, term }
} else if let Some(binary) = ast.get_field(db, "binary") {
let op = binary.expect_field(db, "op").expect_parse(db);
let lhs = Arc::new(expr(db, binary.expect_field(db, "lhs")));
let rhs = Arc::new(expr(db, binary.expect_field(db, "rhs")));
ExprKind::BinaryOp { op, lhs, rhs }
} else if let Some(unary) = ast.get_field(db, "unary") {
let op = unary.expect_field(db, "op").expect_parse(db);
let term = Arc::new(expr(db, unary.expect_field(db, "term")));
ExprKind::UnaryOp { op, term }
} else if let Some(ast) = ast.get_field(db, "atom") {
ExprKind::Extra(Arc::new(ExprExtra::Apply(apply(db, ast))))
} else if let Some(ast) = ast.get_field(db, "aggregate") {
ExprKind::Extra(Arc::new(ExprExtra::Aggregate(aggregate(db, ast))))
BinaryOp { op, lhs, rhs }
} else if let Some(parens) = ast.get_field(db, "parens") {
return expr(db, parens);
} else {
@@ -259,27 +271,6 @@ pub fn expr(db: &dyn Database, ast: AstNode) -> Expr {
Expr { meta: ast, kind }
}
/// Parses a value from an AST.
fn value(db: &dyn Database, ast: AstNode) -> ir::Value {
use ir::Value::*;
if ast.get_field(db, "true").is_some() {
Boolean(true)
} else if ast.get_field(db, "false").is_some() {
Boolean(false)
} else if let Some(sym) = ast.get_field(db, "symbol") {
todo!()
} else {
let int = ast.expect_field(db, "integer");
match int.contents(db).to_string().parse() {
Ok(val) => Integer(val),
Err(_) => {
diagnostic::SimpleError::new(int, "failed to parse integer literal").accumulate(db);
Integer(0)
}
}
}
}
/// Parses an aggregate operator.
pub fn aggregate(db: &dyn Database, ast: AstNode) -> Aggregate {
let kind = ast.expect_field(db, "op").with_contents(db);