1use tenda_common::span::SourceSpan;
2use tenda_scanner::{Token, TokenKind};
3
4#[derive(Debug, PartialEq, Clone)]
5pub struct Ast {
6 pub inner: Vec<Stmt>,
7 pub span: SourceSpan,
8}
9
10impl Ast {
11 pub fn new(span: SourceSpan) -> Self {
12 Ast {
13 inner: vec![],
14 span,
15 }
16 }
17
18 pub fn from(inner: Vec<Stmt>, span: SourceSpan) -> Self {
19 Ast { inner, span }
20 }
21}
22
23impl IntoIterator for Ast {
24 type Item = Stmt;
25 type IntoIter = std::vec::IntoIter<Stmt>;
26
27 fn into_iter(self) -> Self::IntoIter {
28 self.inner.into_iter()
29 }
30}
31
32#[derive(Debug, PartialEq, Clone)]
33pub enum Stmt {
34 Expr(Expr),
35 Decl(Decl),
36 Cond(Cond),
37 While(While),
38 ForEach(ForEach),
39 Block(Block),
40 Return(Return),
41 Break(Break),
42 Continue(Continue),
43}
44
45impl Stmt {
46 pub fn get_span(&self) -> &SourceSpan {
47 match self {
48 Stmt::Expr(expr) => expr.get_span(),
49 Stmt::Decl(decl) => match decl {
50 Decl::Local(local) => &local.span,
51 Decl::Function(function) => &function.span,
52 },
53 Stmt::Cond(cond) => &cond.span,
54 Stmt::While(while_stmt) => &while_stmt.span,
55 Stmt::ForEach(for_each) => &for_each.span,
56 Stmt::Block(block) => &block.span,
57 Stmt::Return(return_stmt) => &return_stmt.span,
58 Stmt::Break(break_stmt) => &break_stmt.span,
59 Stmt::Continue(continue_stmt) => &continue_stmt.span,
60 }
61 }
62}
63
64#[derive(Debug, PartialEq, Clone)]
65pub struct Return {
66 pub value: Option<Expr>,
67 pub span: SourceSpan,
68}
69
70impl Return {
71 pub fn new(value: Option<Expr>, span: SourceSpan) -> Self {
72 Return { value, span }
73 }
74}
75
76#[derive(Debug, PartialEq, Clone)]
77pub struct Break {
78 pub span: SourceSpan,
79}
80
81impl Break {
82 pub fn new(span: SourceSpan) -> Self {
83 Break { span }
84 }
85}
86
87#[derive(Debug, PartialEq, Clone)]
88pub struct Continue {
89 pub span: SourceSpan,
90}
91
92impl Continue {
93 pub fn new(span: SourceSpan) -> Self {
94 Continue { span }
95 }
96}
97
98#[derive(Debug, PartialEq, Clone)]
99pub struct Block {
100 pub inner: Ast,
101 pub span: SourceSpan,
102}
103
104impl Block {
105 pub fn new(inner: Ast, span: SourceSpan) -> Self {
106 Block { inner, span }
107 }
108}
109
110#[derive(Debug, PartialEq, Clone)]
111pub enum Decl {
112 Local(LocalDecl),
113 Function(FunctionDecl),
114}
115
116impl Decl {
117 pub fn get_name(&self) -> &str {
118 match self {
119 Decl::Local(local) => &local.name,
120 Decl::Function(function) => &function.name,
121 }
122 }
123
124 pub fn get_uid(&self) -> usize {
125 match self {
126 Decl::Local(local) => local.uid,
127 Decl::Function(function) => function.uid,
128 }
129 }
130}
131
132#[derive(Debug, PartialEq, Clone)]
133pub struct LocalDecl {
134 pub name: String,
135 pub value: Expr,
136 pub captured: bool,
137 pub uid: usize,
138 pub span: SourceSpan,
139}
140
141impl LocalDecl {
142 pub fn new(name: String, value: Expr, uid: usize, span: SourceSpan) -> Self {
143 LocalDecl {
144 name,
145 value,
146 captured: false,
147 uid,
148 span,
149 }
150 }
151}
152
153#[derive(Debug, PartialEq, Clone)]
154pub struct FunctionParam {
155 pub name: String,
156 pub uid: usize,
157 pub captured: bool,
158 pub span: SourceSpan,
159}
160
161impl FunctionParam {
162 pub fn new(name: String, uid: usize, span: SourceSpan) -> Self {
163 FunctionParam {
164 name,
165 uid,
166 captured: false,
167 span,
168 }
169 }
170}
171
172#[derive(Debug, PartialEq, Clone)]
173pub struct FunctionDecl {
174 pub name: String,
175 pub params: Vec<FunctionParam>,
176 pub body: Box<Stmt>,
177 pub free_vars: Vec<String>,
178 pub captured: bool,
179 pub uid: usize,
180 pub span: SourceSpan,
181}
182
183impl FunctionDecl {
184 pub fn new(
185 name: String,
186 params: Vec<FunctionParam>,
187 body: Stmt,
188 uid: usize,
189 span: SourceSpan,
190 ) -> Self {
191 FunctionDecl {
192 name,
193 params,
194 body: Box::new(body),
195 free_vars: vec![],
196 captured: false,
197 uid,
198 span,
199 }
200 }
201}
202
203#[derive(Debug, PartialEq, Clone)]
204pub struct Cond {
205 pub cond: Expr,
206 pub then: Box<Stmt>,
207 pub or_else: Option<Box<Stmt>>,
208 pub span: SourceSpan,
209}
210
211impl Cond {
212 pub fn new(cond: Expr, then: Stmt, or_else: Option<Stmt>, span: SourceSpan) -> Self {
213 Cond {
214 cond,
215 then: Box::new(then),
216 or_else: or_else.map(Box::new),
217 span,
218 }
219 }
220}
221
222#[derive(Debug, PartialEq, Clone)]
223pub struct While {
224 pub cond: Expr,
225 pub body: Box<Stmt>,
226 pub span: SourceSpan,
227}
228
229impl While {
230 pub fn new(cond: Expr, body: Stmt, span: SourceSpan) -> Self {
231 While {
232 cond,
233 body: Box::new(body),
234 span,
235 }
236 }
237}
238
239#[derive(Debug, PartialEq, Clone)]
240pub struct ForEachItem {
241 pub name: String,
242 pub uid: usize,
243 pub captured: bool,
244 pub span: SourceSpan,
245}
246
247impl ForEachItem {
248 pub fn new(name: String, uid: usize, span: SourceSpan) -> Self {
249 ForEachItem {
250 name,
251 uid,
252 captured: false,
253 span,
254 }
255 }
256}
257
258#[derive(Debug, PartialEq, Clone)]
259pub struct ForEach {
260 pub item: ForEachItem,
261 pub iterable: Expr,
262 pub body: Box<Stmt>,
263 pub span: SourceSpan,
264}
265
266impl ForEach {
267 pub fn new(item: ForEachItem, iterable: Expr, body: Stmt, span: SourceSpan) -> Self {
268 ForEach {
269 item,
270 iterable,
271 body: Box::new(body),
272 span,
273 }
274 }
275}
276
277#[derive(Debug, PartialEq, Clone)]
278pub enum Expr {
279 Binary(BinaryOp),
280 Unary(UnaryOp),
281 Ternary(TernaryOp),
282 Call(Call),
283 Assign(Assign),
284 Access(Access),
285 List(List),
286 Grouping(Grouping),
287 Literal(Literal),
288 Variable(Variable),
289 AssociativeArray(AssociativeArray),
290 AnonymousFunction(AnonymousFunction),
291}
292
293impl Expr {
294 pub fn get_span(&self) -> &SourceSpan {
295 match self {
296 Expr::Binary(binary_op) => &binary_op.span,
297 Expr::Unary(unary_op) => &unary_op.span,
298 Expr::Ternary(ternary_op) => &ternary_op.span,
299 Expr::Call(call) => &call.span,
300 Expr::Assign(assign) => &assign.span,
301 Expr::Access(access) => &access.span,
302 Expr::List(list) => &list.span,
303 Expr::Grouping(grouping) => &grouping.span,
304 Expr::Literal(literal) => &literal.span,
305 Expr::Variable(variable) => &variable.span,
306 Expr::AssociativeArray(associative_array) => &associative_array.span,
307 Expr::AnonymousFunction(anonymous_function) => &anonymous_function.span,
308 }
309 }
310}
311
312#[derive(Debug, PartialEq, Clone)]
313pub struct BinaryOp {
314 pub lhs: Box<Expr>,
315 pub op: BinaryOperator,
316 pub rhs: Box<Expr>,
317 pub span: SourceSpan,
318}
319
320impl BinaryOp {
321 pub fn new(lhs: Expr, op: BinaryOperator, rhs: Expr, span: SourceSpan) -> Self {
322 BinaryOp {
323 lhs: Box::new(lhs),
324 op,
325 rhs: Box::new(rhs),
326 span,
327 }
328 }
329}
330
331#[derive(Debug, PartialEq, Clone)]
332pub struct UnaryOp {
333 pub op: UnaryOperator,
334 pub rhs: Box<Expr>,
335 pub span: SourceSpan,
336}
337
338impl UnaryOp {
339 pub fn new(op: UnaryOperator, rhs: Expr, span: SourceSpan) -> Self {
340 UnaryOp {
341 op,
342 rhs: Box::new(rhs),
343 span,
344 }
345 }
346}
347
348#[derive(Debug, PartialEq, Clone)]
349pub struct TernaryOp {
350 pub cond: Box<Expr>,
351 pub then: Box<Expr>,
352 pub or_else: Box<Expr>,
353 pub span: SourceSpan,
354}
355
356impl TernaryOp {
357 pub fn new(cond: Expr, then: Expr, or_else: Expr, span: SourceSpan) -> Self {
358 TernaryOp {
359 cond: Box::new(cond),
360 then: Box::new(then),
361 or_else: Box::new(or_else),
362 span,
363 }
364 }
365}
366
367#[derive(Debug, PartialEq, Clone)]
368pub struct Call {
369 pub callee: Box<Expr>,
370 pub args: Vec<Expr>,
371 pub span: SourceSpan,
372}
373
374impl Call {
375 pub fn new(callee: Expr, args: Vec<Expr>, span: SourceSpan) -> Self {
376 Call {
377 callee: Box::new(callee),
378 args,
379 span,
380 }
381 }
382}
383
384#[derive(Debug, PartialEq, Clone)]
385pub struct Assign {
386 pub name: Box<Expr>,
387 pub value: Box<Expr>,
388 pub span: SourceSpan,
389}
390
391impl Assign {
392 pub fn new(name: Expr, value: Expr, span: SourceSpan) -> Self {
393 Assign {
394 name: Box::new(name),
395 value: Box::new(value),
396 span,
397 }
398 }
399}
400
401#[derive(Debug, PartialEq, Clone)]
402pub struct Access {
403 pub subscripted: Box<Expr>,
404 pub index: Box<Expr>,
405 pub span: SourceSpan,
406}
407
408impl Access {
409 pub fn new(subscripted: Expr, index: Expr, span: SourceSpan) -> Self {
410 Access {
411 subscripted: Box::new(subscripted),
412 index: Box::new(index),
413 span,
414 }
415 }
416}
417
418#[derive(Debug, PartialEq, Clone)]
419pub struct List {
420 pub elements: Vec<Expr>,
421 pub span: SourceSpan,
422}
423
424impl List {
425 pub fn new(elements: Vec<Expr>, span: SourceSpan) -> Self {
426 List { elements, span }
427 }
428}
429
430#[derive(Debug, PartialEq, Clone)]
431pub struct AssociativeArray {
432 pub elements: Vec<(Literal, Expr)>,
433 pub span: SourceSpan,
434}
435
436impl AssociativeArray {
437 pub fn new(elements: Vec<(Literal, Expr)>, span: SourceSpan) -> Self {
438 AssociativeArray { elements, span }
439 }
440}
441
442#[derive(Debug, PartialEq, Clone)]
443pub struct Grouping {
444 pub expr: Box<Expr>,
445 pub span: SourceSpan,
446}
447
448impl Grouping {
449 pub fn new(expr: Expr, span: SourceSpan) -> Self {
450 Grouping {
451 expr: Box::new(expr),
452 span,
453 }
454 }
455}
456
457#[derive(Debug, PartialEq, Clone)]
458pub struct Literal {
459 pub value: tenda_scanner::Literal,
460 pub span: SourceSpan,
461}
462
463impl Literal {
464 pub fn new(value: tenda_scanner::Literal, span: SourceSpan) -> Self {
465 Literal { value, span }
466 }
467}
468
469#[derive(Debug, PartialEq, Clone)]
470pub struct Variable {
471 pub name: String,
472 pub uid: usize,
473 pub captured: bool,
474 pub span: SourceSpan,
475}
476
477impl Variable {
478 pub fn new(name: String, id: usize, span: SourceSpan) -> Self {
479 Variable {
480 name,
481 uid: id,
482 captured: false,
483 span,
484 }
485 }
486}
487
488#[derive(Debug, PartialEq, Clone)]
489pub struct AnonymousFunction {
490 pub params: Vec<FunctionParam>,
491 pub body: Box<Stmt>,
492 pub uid: usize,
493 pub free_vars: Vec<String>,
494 pub span: SourceSpan,
495}
496
497impl AnonymousFunction {
498 pub fn new(params: Vec<FunctionParam>, body: Stmt, uid: usize, span: SourceSpan) -> Self {
499 AnonymousFunction {
500 params,
501 body: Box::new(body),
502 uid,
503 free_vars: vec![],
504 span,
505 }
506 }
507}
508
509#[derive(Debug, Copy, Clone, PartialEq)]
510pub enum BinaryOperator {
511 Add,
512 Subtract,
513 Multiply,
514 Divide,
515 Exponentiation,
516 Modulo,
517 Equality,
518 Inequality,
519 Greater,
520 GreaterOrEqual,
521 Less,
522 LessOrEqual,
523 LogicalAnd,
524 LogicalOr,
525 Range,
526 Has,
527 Lacks,
528}
529
530impl From<Token> for BinaryOperator {
531 fn from(value: Token) -> Self {
532 use BinaryOperator::*;
533
534 match value.kind {
535 TokenKind::Plus => Add,
536 TokenKind::Minus => Subtract,
537 TokenKind::Star => Multiply,
538 TokenKind::Slash => Divide,
539 TokenKind::Percent => Modulo,
540 TokenKind::Caret => Exponentiation,
541 TokenKind::Equals => Equality,
542 TokenKind::Greater => Greater,
543 TokenKind::GreaterOrEqual => GreaterOrEqual,
544 TokenKind::Less => Less,
545 TokenKind::LessOrEqual => LessOrEqual,
546 TokenKind::Or => LogicalOr,
547 TokenKind::And => LogicalAnd,
548 TokenKind::Until => Range,
549 _ => panic!("invalid token for binary operation"),
550 }
551 }
552}
553
554#[derive(Debug, Copy, Clone, PartialEq)]
555pub enum UnaryOperator {
556 Negative,
557 LogicalNot,
558}
559
560impl From<Token> for UnaryOperator {
561 fn from(value: Token) -> Self {
562 use UnaryOperator::*;
563
564 match value.kind {
565 TokenKind::Minus => Negative,
566 TokenKind::Not => LogicalNot,
567 _ => panic!("invalid token for unary operation"),
568 }
569 }
570}