use crate::ast::{BinOp, ExprKind, StmtKind};
use crate::parse;
fn first_expr_kind(code: &str) -> ExprKind {
let p = parse(code).expect("parse");
let sk = &p.statements[0].kind;
match sk {
StmtKind::Expression(e) => e.kind.clone(),
_ => panic!("expected expression stmt"),
}
}
#[test]
fn test_precedence_arithmetic() {
let k = first_expr_kind("2 + 3 * 4;");
if let ExprKind::BinOp { op, left, right } = k {
assert_eq!(op, BinOp::Add);
assert!(matches!(left.kind, ExprKind::Integer(2)));
if let ExprKind::BinOp { op, .. } = right.kind {
assert_eq!(op, BinOp::Mul);
} else {
panic!("expected Mul on right");
}
} else {
panic!("expected Add at top level");
}
}
#[test]
fn test_precedence_logical() {
let k = first_expr_kind("1 || 0 && 0;");
if let ExprKind::BinOp { op, right, .. } = k {
assert_eq!(op, BinOp::LogOr);
if let ExprKind::BinOp { op, .. } = right.kind {
assert_eq!(op, BinOp::LogAnd);
}
}
}
#[test]
fn test_nested_structures_parsing() {
let p = parse("my $x = [ { a => 1 } ];").expect("parse");
let StmtKind::My(decls) = &p.statements[0].kind else {
panic!("expected my")
};
let init = decls[0].initializer.as_ref().unwrap();
assert!(matches!(init.kind, ExprKind::ArrayRef(_)));
}
#[test]
fn test_pipe_forward_basic_desugaring() {
let k = first_expr_kind("42 |> say;");
if let ExprKind::Say { args, .. } = k {
assert_eq!(args.len(), 1);
assert!(matches!(args[0].kind, ExprKind::Integer(42)));
} else {
panic!(
"expected Say (desugared from PipeForward) at top level, got {:?}",
k
);
}
}
#[test]
fn test_ternary_precedence() {
let k = first_expr_kind("$a ? $b : $c || $d;");
if let ExprKind::Ternary { else_expr, .. } = k {
assert!(matches!(
else_expr.kind,
ExprKind::BinOp {
op: BinOp::LogOr,
..
}
));
} else {
panic!("expected Ternary");
}
}
#[test]
fn test_sub_call_no_parens() {
let k = first_expr_kind("say 42;");
if let ExprKind::Say { args, .. } = k {
assert_eq!(args.len(), 1);
} else {
panic!("expected Say");
}
}