1use crate::number::Number;
4use crate::span::Span;
5use crate::token::Token;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum UnOp {
10 Neg,
12 Fact,
14}
15
16impl From<Token<'_>> for UnOp {
17 fn from(token: Token) -> Self {
18 match token {
19 Token::Minus => UnOp::Neg,
20 Token::Bang => UnOp::Fact,
21 _ => unreachable!("Invalid token for unary operator"),
22 }
23 }
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum BinOp {
29 Add,
31 Sub,
33 Mul,
35 Div,
37 Pow,
39 Equal,
41 NotEqual,
43 Less,
45 LessEqual,
47 Greater,
49 GreaterEqual,
51}
52
53impl From<Token<'_>> for BinOp {
54 fn from(token: Token) -> Self {
55 match token {
56 Token::Plus => BinOp::Add,
57 Token::Minus => BinOp::Sub,
58 Token::Star => BinOp::Mul,
59 Token::Slash => BinOp::Div,
60 Token::Caret => BinOp::Pow,
61 Token::Equal => BinOp::Equal,
62 Token::NotEqual => BinOp::NotEqual,
63 Token::Less => BinOp::Less,
64 Token::LessEqual => BinOp::LessEqual,
65 Token::Greater => BinOp::Greater,
66 Token::GreaterEqual => BinOp::GreaterEqual,
67 _ => unreachable!("Invalid token for binary operator"),
68 }
69 }
70}
71
72#[derive(Debug, Clone)]
74pub struct Expr<'src> {
75 pub kind: ExprKind<'src>,
76 pub span: Span,
77}
78
79#[derive(Debug, Clone)]
81pub enum ExprKind<'src> {
82 Literal(Number),
84 Ident { name: &'src str },
86 Unary { op: UnOp, expr: Box<Expr<'src>> },
88 Binary {
90 op: BinOp,
91 left: Box<Expr<'src>>,
92 right: Box<Expr<'src>>,
93 },
94 Call {
96 name: &'src str,
97 args: Vec<Expr<'src>>,
98 },
99 If {
101 cond: Box<Expr<'src>>,
102 then_branch: Box<Expr<'src>>,
103 else_branch: Box<Expr<'src>>,
104 },
105 Let {
107 decls: Vec<(&'src str, Expr<'src>)>,
108 body: Box<Expr<'src>>,
109 },
110}
111
112impl<'src> Expr<'src> {
113 pub fn literal(value: Number, span: Span) -> Self {
114 Self {
115 kind: ExprKind::Literal(value),
116 span,
117 }
118 }
119
120 pub fn ident(name: &'src str, span: Span) -> Self {
121 Self {
122 kind: ExprKind::Ident { name },
123 span,
124 }
125 }
126
127 pub fn unary(op: UnOp, expr: Expr<'src>, span: Span) -> Self {
128 Self {
129 kind: ExprKind::Unary {
130 op,
131 expr: Box::new(expr),
132 },
133 span,
134 }
135 }
136
137 pub fn binary(op: BinOp, left: Expr<'src>, right: Expr<'src>, span: Span) -> Self {
138 Self {
139 kind: ExprKind::Binary {
140 op,
141 left: Box::new(left),
142 right: Box::new(right),
143 },
144 span,
145 }
146 }
147
148 pub fn call(name: &'src str, args: Vec<Expr<'src>>, span: Span) -> Self {
149 Self {
150 kind: ExprKind::Call { name, args },
151 span,
152 }
153 }
154
155 pub fn if_expr(
156 cond: Expr<'src>,
157 then_branch: Expr<'src>,
158 else_branch: Expr<'src>,
159 span: Span,
160 ) -> Self {
161 Self {
162 kind: ExprKind::If {
163 cond: Box::new(cond),
164 then_branch: Box::new(then_branch),
165 else_branch: Box::new(else_branch),
166 },
167 span,
168 }
169 }
170
171 pub fn let_expr(decls: Vec<(&'src str, Expr<'src>)>, body: Expr<'src>, span: Span) -> Self {
172 Self {
173 kind: ExprKind::Let {
174 decls,
175 body: Box::new(body),
176 },
177 span,
178 }
179 }
180}