1#![allow(dead_code)]
2
3use crate::ast::operators::Op;
4use crate::ast::program::{Program, ProgramStatement, QualifiedPath, UseTarget, Visibility};
5use crate::ast::statement::{Statement, into_then_expr, stmt_from_expr_top};
6use crate::ast::{Expr, Literal};
7use crate::compiler::parser::cst_parser::ParserError;
8use crate::compiler::parser::green::{GreenNode, GreenNodeArena, GreenNodeId, SyntaxKind};
9use crate::compiler::parser::token::{Token, TokenKind};
10use crate::interner::{ExprNodeId, Symbol, ToSymbol};
11use crate::pattern::{Pattern, TypedId, TypedPattern};
12use crate::types::Type;
13use crate::utils::metadata::{Location, Span};
14use std::ops::ControlFlow;
15use std::path::PathBuf;
16
17pub struct Lowerer<'a> {
23 source: &'a str,
24 tokens: &'a [Token],
25 arena: &'a GreenNodeArena,
26 file_path: PathBuf,
27}
28
29impl<'a> Lowerer<'a> {
30 pub fn new(
31 source: &'a str,
32 tokens: &'a [Token],
33 arena: &'a GreenNodeArena,
34 file_path: PathBuf,
35 ) -> Self {
36 Self {
37 source,
38 tokens,
39 arena,
40 file_path,
41 }
42 }
43
44 fn unwrap_paren(expr: ExprNodeId) -> ExprNodeId {
46 match expr.to_expr() {
47 Expr::Paren(inner) => Self::unwrap_paren(inner),
48 _ => expr,
49 }
50 }
51
52 pub fn lower_program(&self, root: GreenNodeId) -> Program {
54 let (mut program_statements, pending_statements, pending_span) = self
55 .arena
56 .children(root)
57 .map_or((Vec::new(), Vec::new(), 0..0), |children| {
58 children
59 .iter()
60 .copied()
61 .filter(|child| self.arena.kind(*child) == Some(SyntaxKind::Statement))
62 .filter_map(|child| self.lower_statement(child))
63 .fold(
64 (Vec::new(), Vec::new(), 0..0),
65 |(mut program_statements, mut pending_statements, mut pending_span),
66 (stmt, span)| {
67 match &stmt {
68 ProgramStatement::GlobalStatement(Statement::Single(expr)) => {
69 let stmts = stmt_from_expr_top(*expr);
71 let new_pending = stmts
72 .into_iter()
73 .map(|s| (s, self.location_from_span(span.clone())));
74 pending_statements.extend(new_pending);
75 pending_span = span;
76 }
77 _ => {
78 if !pending_statements.is_empty() {
80 if let Some(merged_expr) =
81 into_then_expr(&pending_statements)
82 {
83 program_statements.push((
84 ProgramStatement::GlobalStatement(
85 Statement::Single(merged_expr),
86 ),
87 pending_span.clone(),
88 ));
89 }
90 pending_statements.clear();
91 }
92 program_statements.push((stmt, span));
93 }
94 }
95 (program_statements, pending_statements, pending_span)
96 },
97 )
98 });
99
100 if !pending_statements.is_empty()
102 && let Some(merged_expr) = into_then_expr(&pending_statements)
103 {
104 program_statements.push((
105 ProgramStatement::GlobalStatement(Statement::Single(merged_expr)),
106 pending_span.clone(),
107 ));
108 }
109
110 Program {
111 statements: program_statements,
112 }
113 }
114
115 fn lower_statement(&self, node: GreenNodeId) -> Option<(ProgramStatement, Span)> {
117 let span = self.node_span(node)?;
118 let stmt = match self.arena.kind(node) {
119 Some(SyntaxKind::Statement) => {
120 let visibility = self.extract_visibility(node);
122
123 let (inner_kind, inner_id) = self
125 .arena
126 .children(node)
127 .and_then(|children| {
128 children.iter().copied().find_map(|child| {
129 let kind = self.arena.kind(child)?;
130 if kind == SyntaxKind::VisibilityPub {
132 None
133 } else {
134 Some((kind, child))
135 }
136 })
137 })
138 .map(|(kind, id)| (Some(kind), Some(id)))
139 .unwrap_or((None, None));
140
141 match (inner_kind, inner_id) {
142 (Some(SyntaxKind::FunctionDecl), Some(id)) => self
143 .lower_function_decl(id, visibility)
144 .unwrap_or(ProgramStatement::Error),
145 (Some(SyntaxKind::LetDecl), Some(id)) => {
146 self.lower_let_decl(id).unwrap_or(ProgramStatement::Error)
147 }
148 (Some(SyntaxKind::LetRecDecl), Some(id)) => self
149 .lower_letrec_decl(id)
150 .unwrap_or(ProgramStatement::Error),
151 (Some(SyntaxKind::IncludeStmt), Some(id)) => {
152 self.lower_include(id).unwrap_or(ProgramStatement::Error)
153 }
154 (Some(SyntaxKind::StageDecl), Some(id)) => {
155 self.lower_stage_decl(id).unwrap_or(ProgramStatement::Error)
156 }
157 (Some(SyntaxKind::ModuleDecl), Some(id)) => self
158 .lower_module_decl(id, visibility)
159 .unwrap_or(ProgramStatement::Error),
160 (Some(SyntaxKind::UseStmt), Some(id)) => self
161 .lower_use_stmt(id, visibility)
162 .unwrap_or(ProgramStatement::Error),
163 (Some(SyntaxKind::TypeDecl), Some(id)) => self
164 .lower_type_decl(id, visibility)
165 .unwrap_or(ProgramStatement::Error),
166 (Some(_), _) => {
167 let expr_nodes = self.collect_expr_nodes(node);
168 let expr = self.lower_expr_sequence(&expr_nodes);
169 ProgramStatement::GlobalStatement(Statement::Single(expr))
170 }
171 _ => ProgramStatement::Error,
172 }
173 }
174 _ => ProgramStatement::Error,
175 };
176
177 Some((stmt, span))
178 }
179
180 fn extract_visibility(&self, node: GreenNodeId) -> Visibility {
182 self.arena
183 .children(node)
184 .and_then(|children| {
185 children
186 .iter()
187 .find(|child| self.arena.kind(**child) == Some(SyntaxKind::VisibilityPub))
188 })
189 .map(|_| Visibility::Public)
190 .unwrap_or(Visibility::Private)
191 }
192
193 fn lower_module_decl(
195 &self,
196 node: GreenNodeId,
197 visibility: Visibility,
198 ) -> Option<ProgramStatement> {
199 let name_idx = self.find_token(node, |kind| matches!(kind, TokenKind::Ident))?;
200 let name = self.token_text(name_idx)?.to_symbol();
201
202 let has_block = self
204 .find_token(node, |kind| matches!(kind, TokenKind::BlockBegin))
205 .is_some();
206
207 let body = if has_block {
208 let stmts: Vec<(ProgramStatement, Span)> = self
210 .arena
211 .children(node)
212 .map(|children| {
213 children
214 .iter()
215 .copied()
216 .filter(|child| self.arena.kind(*child) == Some(SyntaxKind::Statement))
217 .filter_map(|child| self.lower_statement(child))
218 .collect()
219 })
220 .unwrap_or_default();
221 Some(stmts)
222 } else {
223 None
225 };
226
227 Some(ProgramStatement::ModuleDefinition {
228 visibility,
229 name,
230 body,
231 })
232 }
233
234 fn lower_use_stmt(
240 &self,
241 node: GreenNodeId,
242 visibility: Visibility,
243 ) -> Option<ProgramStatement> {
244 let path_node = self.find_child(node, |kind| kind == SyntaxKind::QualifiedPath)?;
245
246 let (path, target) = self.lower_use_path(path_node)?;
248
249 Some(ProgramStatement::UseStatement {
250 visibility,
251 path,
252 target,
253 })
254 }
255
256 fn lower_use_path(&self, node: GreenNodeId) -> Option<(QualifiedPath, UseTarget)> {
258 use crate::ast::program::UseTarget;
259
260 let mut segments: Vec<Symbol> = Vec::new();
261 let mut target = UseTarget::Single;
262
263 if let Some(children) = self.arena.children(node) {
264 for child in children.iter() {
265 let child_kind = self.arena.kind(*child);
266
267 match child_kind {
268 Some(SyntaxKind::UseTargetWildcard) => {
269 target = UseTarget::Wildcard;
270 }
271 Some(SyntaxKind::UseTargetMultiple) => {
272 let symbols = self.lower_use_target_multiple(*child);
274 target = UseTarget::Multiple(symbols);
275 }
276 _ => {
277 if let Some(token_idx) = self.get_token_index(*child)
279 && let Some(token) = self.tokens.get(token_idx)
280 && token.kind == TokenKind::Ident
281 && let Some(text) = self.token_text(token_idx)
282 {
283 segments.push(text.to_symbol());
284 }
285 }
286 }
287 }
288 }
289
290 if segments.is_empty() && matches!(target, UseTarget::Single) {
291 None
292 } else {
293 Some((QualifiedPath::new(segments), target))
294 }
295 }
296
297 fn lower_use_target_multiple(&self, node: GreenNodeId) -> Vec<Symbol> {
299 let mut symbols = Vec::new();
300
301 if let Some(children) = self.arena.children(node) {
302 for child in children.iter() {
303 if let Some(token_idx) = self.get_token_index(*child)
304 && let Some(token) = self.tokens.get(token_idx)
305 && token.kind == TokenKind::Ident
306 && let Some(text) = self.token_text(token_idx)
307 {
308 symbols.push(text.to_symbol());
309 }
310 }
311 }
312
313 symbols
314 }
315
316 fn lower_qualified_path(&self, node: GreenNodeId) -> Option<QualifiedPath> {
318 let segments: Vec<Symbol> = self
319 .arena
320 .children(node)
321 .map(|children| {
322 children
323 .iter()
324 .filter_map(|child| {
325 if let Some(token_idx) = self.get_token_index(*child)
326 && let Some(token) = self.tokens.get(token_idx)
327 && token.kind == TokenKind::Ident
328 {
329 self.token_text(token_idx).map(|s| s.to_symbol())
330 } else {
331 None
332 }
333 })
334 .collect()
335 })
336 .unwrap_or_default();
337
338 if segments.is_empty() {
339 None
340 } else {
341 Some(QualifiedPath::new(segments))
342 }
343 }
344
345 fn lower_type_decl(
349 &self,
350 node: GreenNodeId,
351 visibility: Visibility,
352 ) -> Option<ProgramStatement> {
353 use crate::ast::program::VariantDef;
354
355 let is_recursive = self
357 .find_token(node, |kind| matches!(kind, TokenKind::Rec))
358 .is_some();
359
360 let name_idx = self.find_token(node, |kind| matches!(kind, TokenKind::Ident))?;
362 let name = self.token_text(name_idx)?.to_symbol();
363
364 let variants: Vec<VariantDef> = self
367 .arena
368 .children(node)
369 .map(|children| {
370 children
371 .iter()
372 .copied()
373 .filter(|child| self.arena.kind(*child) == Some(SyntaxKind::VariantDef))
374 .filter_map(|child| self.lower_variant_def(child))
375 .collect()
376 })
377 .unwrap_or_default();
378
379 if variants.is_empty() {
380 let target_type = self
382 .arena
383 .children(node)
384 .and_then(|children| {
385 children
386 .iter()
387 .find(|c| {
388 self.arena
389 .kind(**c)
390 .map(Self::is_type_kind)
391 .unwrap_or(false)
392 })
393 .copied()
394 })
395 .map(|type_node| self.lower_type(type_node))?;
396
397 Some(ProgramStatement::TypeAlias {
398 visibility,
399 name,
400 target_type,
401 })
402 } else {
403 Some(ProgramStatement::TypeDeclaration {
405 visibility,
406 name,
407 variants,
408 is_recursive,
409 })
410 }
411 }
412
413 fn lower_variant_def(&self, node: GreenNodeId) -> Option<crate::ast::program::VariantDef> {
415 use crate::ast::program::VariantDef;
416
417 let name_idx = self.find_token(node, |kind| matches!(kind, TokenKind::Ident))?;
419 let name = self.token_text(name_idx)?.to_symbol();
420
421 let payload = self.arena.children(node).and_then(|children| {
423 let type_nodes: Vec<_> = children
424 .iter()
425 .filter(|c| {
426 self.arena
427 .kind(**c)
428 .map(Self::is_type_kind)
429 .unwrap_or(false)
430 })
431 .collect();
432
433 match type_nodes.len() {
434 0 => None,
435 1 => {
436 Some(self.lower_type(*type_nodes[0]))
438 }
439 _ => {
440 let elem_types: Vec<_> = type_nodes
442 .iter()
443 .map(|node| self.lower_type(**node))
444 .collect();
445
446 let loc = Location::default();
448 Some(Type::Tuple(elem_types).into_id_with_location(loc))
449 }
450 }
451 });
452
453 Some(VariantDef::new(name, payload))
454 }
455
456 fn lower_let_decl(&self, node: GreenNodeId) -> Option<ProgramStatement> {
457 let pattern_node = self.find_child(node, Self::is_pattern_kind)?;
458 let (pat, pat_span) = self.lower_pattern(pattern_node)?;
459
460 let type_annotation = if let Some(type_anno_node) =
462 self.find_child(node, |kind| kind == SyntaxKind::TypeAnnotation)
463 {
464 if let Some(type_children) = self.arena.children(type_anno_node) {
466 type_children
467 .iter()
468 .find(|c| {
469 self.arena
470 .kind(**c)
471 .map(Self::is_type_kind)
472 .unwrap_or(false)
473 })
474 .map(|type_node| self.lower_type(*type_node))
475 } else {
476 None
477 }
478 } else {
479 None
480 };
481
482 let expr_nodes = self.collect_expr_nodes_after(node, pattern_node);
483 let value = self.lower_expr_sequence(&expr_nodes);
484 let loc = self.location_from_span(pat_span.clone());
485
486 let ty =
487 type_annotation.unwrap_or_else(|| Type::Unknown.into_id_with_location(loc.clone()));
488 let typed = TypedPattern::new(pat, ty);
489
490 Some(ProgramStatement::GlobalStatement(Statement::Let(
491 typed, value,
492 )))
493 }
494
495 fn lower_function_decl(
496 &self,
497 node: GreenNodeId,
498 visibility: Visibility,
499 ) -> Option<ProgramStatement> {
500 let name_idx = self.find_token(node, |kind| {
501 matches!(kind, TokenKind::IdentFunction | TokenKind::Ident)
502 })?;
503 let name = self.token_text(name_idx)?.to_symbol();
504
505 let (params, params_span) = self
506 .find_child(node, |kind| kind == SyntaxKind::ParamList)
507 .map(|id| self.lower_param_list(id))
508 .unwrap_or_else(|| (Vec::new(), self.node_span(node).unwrap_or(0..0)));
509
510 let return_type = self.arena.children(node).and_then(|children| {
512 children
513 .iter()
514 .find_map(|child| match self.arena.kind(*child) {
515 Some(SyntaxKind::TypeAnnotation) => {
516 self.arena.children(*child).and_then(|type_children| {
517 type_children
518 .iter()
519 .find(|c| {
520 self.arena
521 .kind(**c)
522 .map(Self::is_type_kind)
523 .unwrap_or(false)
524 })
525 .map(|type_node| self.lower_type(*type_node))
526 })
527 }
528 Some(kind) if Self::is_type_kind(kind) => Some(self.lower_type(*child)),
529 _ => None,
530 })
531 });
532
533 let body_node = self
534 .find_child(node, |kind| kind == SyntaxKind::BlockExpr)
535 .or_else(|| self.find_child(node, Self::is_expr_kind))?;
536 let body = if self.arena.kind(body_node) == Some(SyntaxKind::BlockExpr) {
537 let stmts = self.lower_block_statements(body_node);
539 into_then_expr(&stmts).unwrap_or_else(|| Expr::Error.into_id_without_span())
540 } else {
541 self.lower_expr(body_node)
542 };
543
544 let arg_loc = self.location_from_span(params_span.clone());
545 Some(ProgramStatement::FnDefinition {
546 visibility,
547 name,
548 args: (params, arg_loc),
549 return_type,
550 body,
551 })
552 }
553
554 fn lower_letrec_decl(&self, node: GreenNodeId) -> Option<ProgramStatement> {
555 let ident_token = self.find_token(node, |kind| matches!(kind, TokenKind::Ident))?;
556 let expr_nodes = self.collect_expr_nodes(node);
557
558 let name = self.token_text(ident_token)?.to_symbol();
559 let span = self.node_span(node)?;
560 let loc = self.location_from_span(span.clone());
561 let ty = Type::Unknown.into_id_with_location(loc.clone());
562 let id = TypedId::new(name, ty);
563 let value = self.lower_expr_sequence(&expr_nodes);
564 Some(ProgramStatement::GlobalStatement(Statement::LetRec(
565 id, value,
566 )))
567 }
568
569 fn lower_include(&self, node: GreenNodeId) -> Option<ProgramStatement> {
570 let string_token = self.find_token(node, |kind| matches!(kind, TokenKind::Str))?;
571 let raw = self.token_text(string_token)?;
572 let content = raw.trim_matches('"').to_symbol();
574 Some(ProgramStatement::Import(content))
575 }
576
577 fn lower_stage_decl(&self, node: GreenNodeId) -> Option<ProgramStatement> {
578 use crate::ast::StageKind;
579 let stage_token = self.find_token(node, |kind| {
580 matches!(kind, TokenKind::Main | TokenKind::Macro)
581 })?;
582 let stage_kind = match self.tokens.get(stage_token)?.kind {
583 TokenKind::Main => StageKind::Main,
584 TokenKind::Macro => StageKind::Macro,
585 _ => StageKind::Main,
586 };
587 Some(ProgramStatement::StageDeclaration { stage: stage_kind })
588 }
589
590 fn lower_expr(&self, node: GreenNodeId) -> ExprNodeId {
592 let loc = self
593 .node_span(node)
594 .map(|span| self.location_from_span(span))
595 .unwrap_or_default();
596
597 match self.arena.kind(node) {
598 Some(SyntaxKind::IntLiteral) => {
599 let text = self.text_of_first_token(node).unwrap_or("0");
600 Expr::Literal(Literal::Float(text.to_symbol())).into_id(loc)
601 }
602 Some(SyntaxKind::FloatLiteral) => {
603 let text = self.text_of_first_token(node).unwrap_or("0.0");
604 Expr::Literal(Literal::Float(text.to_symbol())).into_id(loc)
605 }
606 Some(SyntaxKind::StringLiteral) => {
607 let text = self.text_of_first_token(node).unwrap_or("\"");
608 Expr::Literal(Literal::String(text.trim_matches('"').to_symbol())).into_id(loc)
609 }
610 Some(SyntaxKind::SelfLiteral) => Expr::Literal(Literal::SelfLit).into_id(loc),
611 Some(SyntaxKind::NowLiteral) => Expr::Literal(Literal::Now).into_id(loc),
612 Some(SyntaxKind::SampleRateLiteral) => Expr::Literal(Literal::SampleRate).into_id(loc),
613 Some(SyntaxKind::PlaceHolderLiteral) => {
614 Expr::Literal(Literal::PlaceHolder).into_id(loc)
615 }
616 Some(SyntaxKind::Identifier) => {
617 let text = self.text_of_first_token(node).unwrap_or("");
618 Expr::Var(text.to_symbol()).into_id(loc)
619 }
620 Some(SyntaxKind::QualifiedPath) => {
621 if let Some(path) = self.lower_qualified_path(node) {
623 if path.segments.len() == 1 {
625 Expr::Var(path.segments[0]).into_id(loc)
626 } else {
627 Expr::QualifiedVar(path).into_id(loc)
628 }
629 } else {
630 Expr::Error.into_id(loc)
631 }
632 }
633 Some(SyntaxKind::TupleExpr) => {
634 let elems = self.lower_expr_list(node);
635 Expr::Tuple(elems).into_id(loc)
636 }
637 Some(SyntaxKind::ArrayExpr) => {
638 let elems = self.lower_expr_list(node);
639 Expr::ArrayLiteral(elems).into_id(loc)
640 }
641 Some(SyntaxKind::RecordExpr) => {
642 if self
643 .find_token(node, |kind| kind == TokenKind::LeftArrow)
644 .is_some()
645 {
646 let base = self
647 .child_exprs(node)
648 .into_iter()
649 .next()
650 .map(|expr_node| self.lower_expr(expr_node))
651 .unwrap_or_else(|| Expr::Error.into_id(loc.clone()));
652 let fields = self.lower_record_fields(node);
653 Expr::RecordUpdate(base, fields).into_id(loc)
654 } else {
655 let fields = self.lower_record_fields(node);
656 if self
657 .find_token(node, |kind| kind == TokenKind::DoubleDot)
658 .is_some()
659 {
660 Expr::ImcompleteRecord(fields).into_id(loc)
661 } else {
662 Expr::RecordLiteral(fields).into_id(loc)
663 }
664 }
665 }
666 Some(SyntaxKind::IfExpr) => {
667 let expr_children = self.child_exprs(node);
668 let raw_cond = expr_children
669 .first()
670 .map(|&id| self.lower_expr(id))
671 .unwrap_or_else(|| Expr::Error.into_id(loc.clone()));
672 let cond = match raw_cond.to_expr() {
674 Expr::Paren(inner) => inner,
675 _ => raw_cond,
676 };
677 let then_expr = expr_children
678 .get(1)
679 .map(|&id| self.lower_expr(id))
680 .unwrap_or_else(|| Expr::Error.into_id(loc.clone()));
681 let else_expr = expr_children.get(2).map(|&id| self.lower_expr(id));
682 Expr::If(cond, then_expr, else_expr).into_id(loc)
683 }
684 Some(SyntaxKind::MatchExpr) => self.lower_match_expr(node, loc),
685 Some(SyntaxKind::BlockExpr) => {
686 let stmts = self.lower_block_statements(node);
687 Expr::Block(into_then_expr(&stmts)).into_id(loc)
688 }
689 Some(SyntaxKind::LambdaExpr) => {
690 let (params, body) = self.lower_lambda(node);
691 Expr::Lambda(params, None, body).into_id(loc)
692 }
693 Some(SyntaxKind::UnaryExpr) => {
694 let op = self.extract_unary_op(node).unwrap_or(Op::Minus);
695 let rhs_nodes = self.child_exprs(node);
696 let rhs = if rhs_nodes.is_empty() {
697 Expr::Error.into_id(loc.clone())
698 } else {
699 self.lower_expr_sequence(&rhs_nodes)
700 };
701 Expr::UniOp((op, loc.span.clone()), rhs).into_id(loc)
702 }
703 Some(SyntaxKind::ParenExpr) => {
704 let inner_nodes = self.child_exprs(node);
705 if inner_nodes.is_empty() {
706 Expr::Error.into_id(loc.clone())
707 } else {
708 self.lower_expr_sequence(&inner_nodes)
710 }
711 }
712 Some(SyntaxKind::MacroExpansion) => {
713 let (callee, args) = self.lower_macro_expand(node);
714 Expr::MacroExpand(callee, args).into_id(loc)
715 }
716 Some(SyntaxKind::BinaryExpr) => self.lower_binary(node),
717 Some(SyntaxKind::CallExpr) => self.lower_call(node),
718 Some(SyntaxKind::FieldAccess) => self.lower_field_access(node),
719 Some(SyntaxKind::IndexExpr) => self.lower_index(node),
720 Some(SyntaxKind::AssignExpr) => {
721 Expr::Error.into_id(loc)
723 }
724 Some(SyntaxKind::BracketExpr) => {
725 let body_nodes = self.child_exprs(node);
726 let body = if body_nodes.is_empty() {
727 Expr::Error.into_id(loc.clone())
728 } else {
729 self.lower_expr_sequence(&body_nodes)
730 };
731 Expr::Bracket(body).into_id(loc)
732 }
733 Some(SyntaxKind::EscapeExpr) => {
734 let body_nodes = self.child_exprs(node);
735 let body = if body_nodes.is_empty() {
736 Expr::Error.into_id(loc.clone())
737 } else {
738 self.lower_expr_sequence(&body_nodes)
739 };
740 Expr::Escape(body).into_id(loc)
741 }
742 _ => Expr::Error.into_id(loc),
743 }
744 }
745
746 fn lower_match_expr(&self, node: GreenNodeId, loc: Location) -> ExprNodeId {
748 use crate::ast::MatchArm;
749
750 let children: Vec<GreenNodeId> = self
751 .arena
752 .children(node)
753 .map(|c| c.to_vec())
754 .unwrap_or_default();
755
756 let scrutinee = children
758 .iter()
759 .find(|&&c| self.arena.kind(c).map(Self::is_expr_kind) == Some(true))
760 .map(|&c| self.lower_expr(c))
761 .unwrap_or_else(|| Expr::Error.into_id(loc.clone()));
762
763 let arm_list = children
765 .iter()
766 .find(|&&c| self.arena.kind(c) == Some(SyntaxKind::MatchArmList));
767
768 let arms: Vec<MatchArm> = arm_list
769 .and_then(|&list| self.arena.children(list))
770 .map(|arm_nodes| {
771 arm_nodes
772 .iter()
773 .filter(|&&c| self.arena.kind(c) == Some(SyntaxKind::MatchArm))
774 .map(|&arm| self.lower_match_arm(arm))
775 .collect()
776 })
777 .unwrap_or_default();
778
779 Expr::Match(scrutinee, arms).into_id(loc)
780 }
781
782 fn lower_match_arm(&self, node: GreenNodeId) -> crate::ast::MatchArm {
784 use crate::ast::{MatchArm, MatchPattern};
785
786 let children: Vec<GreenNodeId> = self
787 .arena
788 .children(node)
789 .map(|c| c.iter().copied().collect())
790 .unwrap_or_default();
791
792 let pattern_node = children
794 .iter()
795 .find(|&&c| self.arena.kind(c) == Some(SyntaxKind::MatchPattern));
796
797 let pattern = pattern_node
798 .map(|&pat| self.lower_match_pattern(pat))
799 .unwrap_or(MatchPattern::Wildcard);
800
801 let body = children
803 .iter()
804 .filter(|&&c| self.arena.kind(c) != Some(SyntaxKind::MatchPattern))
805 .find(|&&c| self.arena.kind(c).map(Self::is_expr_kind) == Some(true))
806 .map(|&c| self.lower_expr(c))
807 .unwrap_or_else(|| {
808 Expr::Error.into_id(self.location_from_span(self.node_span(node).unwrap_or(0..0)))
809 });
810
811 MatchArm { pattern, body }
812 }
813
814 fn lower_match_pattern(&self, node: GreenNodeId) -> crate::ast::MatchPattern {
816 use crate::ast::{Literal, MatchPattern};
817 use crate::interner::ToSymbol;
818
819 let children: Vec<GreenNodeId> = self
820 .arena
821 .children(node)
822 .map(|c| c.to_vec())
823 .unwrap_or_default();
824
825 for &child in &children {
826 match self.arena.kind(child) {
827 Some(SyntaxKind::IntLiteral) => {
828 if let Some(text) = self.text_of_first_token(child) {
829 if let Ok(n) = text.parse::<i64>() {
830 return MatchPattern::Literal(Literal::Int(n));
831 }
832 }
833 }
834 Some(SyntaxKind::FloatLiteral) => {
835 if let Some(text) = self.text_of_first_token(child) {
836 return MatchPattern::Literal(Literal::Float(text.to_symbol()));
837 }
838 }
839 Some(SyntaxKind::PlaceHolderLiteral) => {
840 return MatchPattern::Wildcard;
841 }
842 Some(SyntaxKind::ConstructorPattern) => {
843 return self.lower_constructor_pattern(child);
844 }
845 Some(SyntaxKind::TuplePattern) => {
846 return self.lower_match_tuple_pattern(child);
848 }
849 Some(SyntaxKind::Identifier) => {
850 if let Some(text) = self.text_of_first_token(child) {
852 return MatchPattern::Constructor(text.to_symbol(), None);
853 }
854 }
855 _ => {}
856 }
857 }
858
859 MatchPattern::Wildcard
860 }
861
862 fn lower_constructor_pattern(&self, node: GreenNodeId) -> crate::ast::MatchPattern {
865 use crate::ast::MatchPattern;
866 use crate::interner::ToSymbol;
867
868 let children: Vec<GreenNodeId> = self
869 .arena
870 .children(node)
871 .map(|c| c.to_vec())
872 .unwrap_or_default();
873
874 let mut constructor_name: Option<Symbol> = None;
875 let mut inner_pattern: Option<Box<MatchPattern>> = None;
876
877 for &child in &children {
878 match self.arena.kind(child) {
879 Some(SyntaxKind::Identifier) => {
880 if let Some(text) = self.text_of_first_token(child) {
881 if constructor_name.is_none() {
882 constructor_name = Some(text.to_symbol());
883 } else {
884 inner_pattern =
886 Some(Box::new(MatchPattern::Variable(text.to_symbol())));
887 }
888 }
889 }
890 Some(SyntaxKind::PlaceHolderLiteral) => {
891 inner_pattern = Some(Box::new(MatchPattern::Wildcard));
893 }
894 Some(SyntaxKind::TuplePattern) => {
895 inner_pattern = Some(Box::new(self.lower_tuple_pattern(child)));
897 }
898 _ => {}
899 }
900 }
901
902 if let Some(name) = constructor_name {
903 MatchPattern::Constructor(name, inner_pattern)
904 } else {
905 MatchPattern::Wildcard
906 }
907 }
908
909 fn lower_tuple_pattern(&self, node: GreenNodeId) -> crate::ast::MatchPattern {
913 use crate::ast::MatchPattern;
914 use crate::interner::ToSymbol;
915
916 let children: Vec<GreenNodeId> = self
917 .arena
918 .children(node)
919 .map(|c| c.to_vec())
920 .unwrap_or_default();
921
922 let mut patterns = Vec::new();
923
924 for &child in &children {
925 match self.arena.kind(child) {
926 Some(SyntaxKind::Identifier) => {
927 if let Some(text) = self.text_of_first_token(child) {
928 patterns.push(MatchPattern::Variable(text.to_symbol()));
929 }
930 }
931 Some(SyntaxKind::SinglePattern) => {
932 if let Some(text) = self.text_of_first_token(child) {
934 patterns.push(MatchPattern::Variable(text.to_symbol()));
935 }
936 }
937 Some(SyntaxKind::PlaceHolderLiteral) => {
938 patterns.push(MatchPattern::Wildcard);
939 }
940 Some(SyntaxKind::TuplePattern) => {
941 patterns.push(self.lower_tuple_pattern(child));
943 }
944 _ => {}
945 }
946 }
947
948 if patterns.len() == 1 {
952 if let MatchPattern::Tuple(_) = &patterns[0] {
953 return patterns.pop().unwrap();
954 }
955 }
956
957 MatchPattern::Tuple(patterns)
958 }
959
960 fn lower_match_tuple_pattern(&self, node: GreenNodeId) -> crate::ast::MatchPattern {
964 use crate::ast::MatchPattern;
965
966 let children: Vec<GreenNodeId> = self
967 .arena
968 .children(node)
969 .map(|c| c.to_vec())
970 .unwrap_or_default();
971
972 let mut patterns = Vec::new();
973
974 for &child in &children {
975 match self.arena.kind(child) {
976 Some(SyntaxKind::MatchPattern) => {
977 patterns.push(self.lower_match_pattern(child));
979 }
980 _ => {}
981 }
982 }
983
984 MatchPattern::Tuple(patterns)
985 }
986
987 fn lower_lambda(&self, node: GreenNodeId) -> (Vec<TypedId>, ExprNodeId) {
988 let (params, body_nodes) = self
989 .arena
990 .children(node)
991 .map(|children| {
992 (0..children.len()).fold(
993 (Vec::new(), Vec::new(), 0usize),
994 |(mut params, mut body_nodes, mut next_index), i| {
995 if i < next_index {
996 return (params, body_nodes, next_index);
997 }
998
999 let child = children[i];
1000 match self.arena.kind(child) {
1001 None => {
1002 if let Some(token_index) = self.get_token_index(child)
1003 && let Some(token) = self.tokens.get(token_index)
1004 && matches!(
1005 token.kind,
1006 TokenKind::Ident | TokenKind::IdentParameter
1007 )
1008 {
1009 let name = token.text(self.source).to_symbol();
1010 let loc = self.location_from_span(token.start..token.end());
1011 let mut ty = Type::Unknown.into_id_with_location(loc.clone());
1012 let mut next = i + 1;
1013
1014 if next < children.len()
1015 && self.arena.kind(children[next])
1016 == Some(SyntaxKind::TypeAnnotation)
1017 {
1018 ty = self
1019 .arena
1020 .children(children[next])
1021 .and_then(|type_children| {
1022 type_children
1023 .iter()
1024 .find(|c| {
1025 self.arena
1026 .kind(**c)
1027 .map(Self::is_type_kind)
1028 .unwrap_or(false)
1029 })
1030 .copied()
1031 })
1032 .map(|type_node| self.lower_type(type_node))
1033 .unwrap_or_else(|| {
1034 Type::Unknown.into_id_with_location(loc.clone())
1035 });
1036 next += 1;
1037 }
1038
1039 params.push(TypedId::new(name, ty));
1040 next_index = next;
1041 }
1042 }
1043 Some(kind) if Self::is_expr_kind(kind) => {
1044 body_nodes.push(child);
1045 }
1046 _ => {}
1047 }
1048 (params, body_nodes, next_index.max(i + 1))
1049 },
1050 )
1051 })
1052 .map(|(params, body_nodes, _)| (params, body_nodes))
1053 .unwrap_or_else(|| (Vec::new(), Vec::new()));
1054
1055 let body = self.lower_expr_sequence(&body_nodes);
1056
1057 (params, body)
1058 }
1059
1060 fn lower_record_fields(&self, node: GreenNodeId) -> Vec<crate::ast::RecordField> {
1061 let (mut fields, _) = self
1062 .arena
1063 .children(node)
1064 .map_or((Vec::new(), None), |children| {
1065 children.iter().copied().fold(
1066 (Vec::new(), None),
1067 |(mut fields, mut current), child| {
1068 if let Some(token_index) = self.get_token_index(child)
1070 && let Some(token) = self.tokens.get(token_index)
1071 && matches!(token.kind, TokenKind::Ident)
1072 {
1073 current = Some(token.text(self.source).to_symbol());
1074 return (fields, current);
1075 }
1076
1077 if self.arena.kind(child).map(Self::is_expr_kind) == Some(true)
1078 && let Some(name) = current.take()
1079 {
1080 fields.push(crate::ast::RecordField {
1081 name,
1082 expr: self.lower_expr(child),
1083 });
1084 }
1085 (fields, current)
1086 },
1087 )
1088 });
1089
1090 fields.sort_by(|a, b| a.name.as_ref().cmp(b.name.as_ref()));
1091 fields
1092 }
1093
1094 fn lower_block_statements(&self, node: GreenNodeId) -> Vec<(Statement, Location)> {
1095 self.arena
1096 .children(node)
1097 .into_iter()
1098 .flatten()
1099 .copied()
1100 .filter(|child| self.arena.kind(*child) == Some(SyntaxKind::Statement))
1101 .filter_map(|child| self.lower_statement(child))
1102 .map(|(stmt, span)| {
1103 (
1104 match stmt {
1105 ProgramStatement::GlobalStatement(s) => s,
1106 ProgramStatement::StageDeclaration { stage } => {
1107 Statement::DeclareStage(stage)
1108 }
1109 _ => Statement::Error,
1110 },
1111 self.location_from_span(span),
1112 )
1113 })
1114 .collect()
1115 }
1116
1117 fn lower_pattern(&self, node: GreenNodeId) -> Option<(Pattern, Span)> {
1118 let span = self.node_span(node)?;
1119 let pat = match self.arena.kind(node) {
1120 Some(SyntaxKind::Pattern) => {
1121 if let Some(child) = self.child_patterns(node).into_iter().next() {
1122 return self.lower_pattern(child);
1124 } else {
1125 Pattern::Error
1126 }
1127 }
1128 Some(SyntaxKind::SinglePattern) => {
1129 let name_text = self.text_of_first_token(node).unwrap_or("");
1130 if name_text == "_" {
1131 Pattern::Placeholder
1132 } else {
1133 Pattern::Single(name_text.to_symbol())
1134 }
1135 }
1136 Some(SyntaxKind::TuplePattern) => {
1137 let elems = self
1138 .child_patterns(node)
1139 .into_iter()
1140 .filter_map(|id| self.lower_pattern(id))
1141 .map(|(p, _)| p)
1142 .collect();
1143 Pattern::Tuple(elems)
1144 }
1145 Some(SyntaxKind::RecordPattern) => {
1146 let (items, _) = self
1147 .arena
1148 .children(node)
1149 .map_or((Vec::new(), None), |children| {
1150 children.iter().copied().fold(
1151 (Vec::new(), None),
1152 |(mut items, mut current), child| {
1153 if let Some(token_index) = self.get_token_index(child)
1154 && let Some(token) = self.tokens.get(token_index)
1155 && matches!(
1156 token.kind,
1157 TokenKind::Ident | TokenKind::IdentParameter
1158 )
1159 {
1160 current = Some(token.text(self.source).to_symbol());
1161 return (items, current);
1162 }
1163
1164 if self.arena.kind(child).map(Self::is_pattern_kind) == Some(true)
1165 && let Some((p, _)) = self.lower_pattern(child)
1166 && let Some(name) = current.take()
1167 {
1168 items.push((name, p));
1169 }
1170 (items, current)
1171 },
1172 )
1173 });
1174 Pattern::Record(items)
1175 }
1176 _ => Pattern::Error,
1177 };
1178
1179 Some((pat, span))
1180 }
1181
1182 fn lower_expr_sequence(&self, nodes: &[GreenNodeId]) -> ExprNodeId {
1183 let result = (0..nodes.len()).try_fold(
1184 (Option::<ExprNodeId>::None, false),
1185 |(acc, skip_next), i| {
1186 if skip_next {
1187 return ControlFlow::Continue((acc, false));
1188 }
1189
1190 let node = nodes[i];
1191 match self.arena.kind(node) {
1192 Some(SyntaxKind::BinaryExpr) => {
1193 ControlFlow::Continue((Some(self.lower_binary(node)), false))
1194 }
1195 Some(SyntaxKind::CallExpr) => {
1196 ControlFlow::Continue((Some(self.lower_call(node)), false))
1197 }
1198 Some(SyntaxKind::FieldAccess) => {
1199 ControlFlow::Continue((Some(self.lower_field_access(node)), false))
1200 }
1201 Some(SyntaxKind::IndexExpr) => {
1202 ControlFlow::Continue((Some(self.lower_index(node)), false))
1203 }
1204 Some(SyntaxKind::AssignExpr) => {
1205 if let Some(lhs) = acc {
1206 let assign = self.lower_assign(lhs, node);
1207 if i + 1 < nodes.len() {
1209 let cont = self.lower_expr_sequence(&nodes[(i + 1)..]);
1210 let loc = self.location_from_span(merge_spans(
1211 assign.to_span(),
1212 cont.to_span(),
1213 ));
1214 return ControlFlow::Break(
1215 Expr::Then(assign, Some(cont)).into_id(loc),
1216 );
1217 }
1218 ControlFlow::Continue((Some(assign), false))
1221 } else {
1222 ControlFlow::Continue((Some(self.lower_expr(node)), false))
1223 }
1224 }
1225 Some(_) => {
1226 if let Some(prev) = acc
1228 && let Expr::Then(first, None) = prev.to_expr()
1229 {
1230 let rhs = self.lower_expr_sequence(&nodes[i..]);
1231 let loc =
1232 self.location_from_span(merge_spans(prev.to_span(), rhs.to_span()));
1233 return ControlFlow::Break(Expr::Then(first, Some(rhs)).into_id(loc));
1234 }
1235 ControlFlow::Continue((Some(self.lower_expr(node)), false))
1236 }
1237 None => ControlFlow::Continue((acc, false)),
1238 }
1239 },
1240 );
1241
1242 match result {
1243 ControlFlow::Break(expr) => expr,
1244 ControlFlow::Continue((acc, _)) => {
1245 acc.unwrap_or_else(|| Expr::Error.into_id_without_span())
1246 }
1247 }
1248 }
1249
1250 fn lower_binary(&self, node: GreenNodeId) -> ExprNodeId {
1252 let (op, op_span) = self
1253 .extract_binary_op(node)
1254 .unwrap_or((Op::Unknown("".to_string()), 0..0));
1255
1256 let expr_children = self.child_exprs(node);
1257
1258 let (lhs, rhs) = if expr_children.len() >= 2 {
1265 let lhs_node = expr_children[0];
1267 let rhs_node = expr_children[expr_children.len() - 1];
1268 (self.lower_expr(lhs_node), self.lower_expr(rhs_node))
1269 } else if expr_children.len() == 1 {
1270 (
1272 Expr::Error.into_id_without_span(),
1273 self.lower_expr(expr_children[0]),
1274 )
1275 } else {
1276 (
1278 Expr::Error.into_id_without_span(),
1279 Expr::Error.into_id_without_span(),
1280 )
1281 };
1282
1283 let loc = self.location_from_span(merge_spans(lhs.to_span(), rhs.to_span()));
1284 Expr::BinOp(lhs, (op, op_span), rhs).into_id(loc)
1285 }
1286
1287 fn lower_call(&self, node: GreenNodeId) -> ExprNodeId {
1289 let expr_children = self.child_exprs(node);
1290
1291 let callee = if !expr_children.is_empty() {
1293 self.lower_expr(expr_children[0])
1294 } else {
1295 Expr::Error.into_id_without_span()
1296 };
1297
1298 let args = self
1299 .lower_arg_list(node)
1300 .into_iter()
1301 .map(Self::unwrap_paren)
1302 .collect();
1303 let call_span = self.node_span(node).unwrap_or_else(|| callee.to_span());
1304 let loc = self.location_from_span(merge_spans(callee.to_span(), call_span));
1305 Expr::Apply(callee, args).into_id(loc)
1306 }
1307
1308 fn lower_field_access(&self, node: GreenNodeId) -> ExprNodeId {
1310 let expr_children = self.child_exprs(node);
1311
1312 let lhs = if !expr_children.is_empty() {
1313 self.lower_expr(expr_children[0])
1314 } else {
1315 Expr::Error.into_id_without_span()
1316 };
1317
1318 let lhs_span = lhs.to_span();
1319
1320 let field_token = self
1322 .arena
1323 .children(node)
1324 .into_iter()
1325 .flatten()
1326 .filter_map(|&child| self.get_token_index(child))
1327 .filter_map(|idx| self.tokens.get(idx))
1328 .filter(|tok| matches!(tok.kind, TokenKind::Ident | TokenKind::Int))
1329 .next_back();
1330
1331 let expr = field_token
1332 .and_then(|tok| match tok.kind {
1333 TokenKind::Ident => Some(Expr::FieldAccess(lhs, tok.text(self.source).to_symbol())),
1334 TokenKind::Int => tok
1335 .text(self.source)
1336 .parse::<i64>()
1337 .ok()
1338 .map(|n| Expr::Proj(lhs, n)),
1339 _ => None,
1340 })
1341 .unwrap_or(Expr::Error);
1342
1343 let span = self
1344 .node_span(node)
1345 .map(|s| merge_spans(lhs_span.clone(), s))
1346 .unwrap_or(lhs_span);
1347 let loc = self.location_from_span(span);
1348 match expr {
1349 Expr::FieldAccess(_, _) | Expr::Proj(_, _) => expr.into_id(loc),
1350 _ => Expr::Error.into_id(loc),
1351 }
1352 }
1353
1354 fn lower_index(&self, node: GreenNodeId) -> ExprNodeId {
1356 let expr_children = self.child_exprs(node);
1357
1358 let (lhs, index) = if expr_children.len() >= 2 {
1360 (
1361 self.lower_expr(expr_children[0]),
1362 self.lower_expr(expr_children[1]),
1363 )
1364 } else if expr_children.len() == 1 {
1365 (
1366 self.lower_expr(expr_children[0]),
1367 Expr::Error.into_id_without_span(),
1368 )
1369 } else {
1370 (
1371 Expr::Error.into_id_without_span(),
1372 Expr::Error.into_id_without_span(),
1373 )
1374 };
1375
1376 let lhs_span = lhs.to_span();
1377 let index_span = index.to_span();
1378 let loc = self.location_from_span(merge_spans(lhs_span, index_span));
1379 Expr::ArrayAccess(lhs, index).into_id(loc)
1380 }
1381
1382 fn lower_assign(&self, lhs: ExprNodeId, node: GreenNodeId) -> ExprNodeId {
1383 let rhs_nodes = self.child_exprs(node);
1384 let rhs = self.lower_expr_sequence(&rhs_nodes);
1385 let loc = self.location_from_span(merge_spans(lhs.to_span(), rhs.to_span()));
1386 Expr::Assign(lhs, rhs).into_id(loc)
1387 }
1388
1389 fn macro_expand_span(&self, node: GreenNodeId, base_span: Span) -> Span {
1391 let bang_end = self
1392 .find_token(node, |kind| matches!(kind, TokenKind::MacroExpand))
1393 .and_then(|idx| self.tokens.get(idx).map(|t| t.end()))
1394 .unwrap_or(base_span.end);
1395 base_span.start..bang_end
1396 }
1397
1398 fn lower_macro_expand(&self, node: GreenNodeId) -> (ExprNodeId, Vec<ExprNodeId>) {
1399 let args = self.lower_arg_list(node);
1400
1401 if let Some(path_node) = self.find_child(node, |kind| kind == SyntaxKind::QualifiedPath)
1403 && let Some(path) = self.lower_qualified_path(path_node)
1404 {
1405 let path_span = self.node_span(path_node).unwrap_or(0..0);
1406 let loc = self.location_from_span(self.macro_expand_span(node, path_span));
1407 return (Expr::QualifiedVar(path).into_id(loc), args);
1408 }
1409
1410 let name_idx = self.find_token(node, |kind| matches!(kind, TokenKind::Ident));
1412 let name_text = name_idx.and_then(|idx| self.token_text(idx)).unwrap_or("");
1413 let name = name_text.to_symbol();
1414 let ident_span = name_idx
1415 .and_then(|idx| self.tokens.get(idx).map(|t| t.start..t.end()))
1416 .unwrap_or(0..0);
1417 let loc = self.location_from_span(self.macro_expand_span(node, ident_span));
1418 (Expr::Var(name).into_id(loc), args)
1419 }
1420
1421 fn lower_param_list(&self, node: GreenNodeId) -> (Vec<TypedId>, Span) {
1422 let params = if let Some(children) = self.arena.children(node) {
1423 let (new_params, _) =
1424 (0..children.len()).fold((Vec::new(), 0usize), |(mut acc, mut next_index), i| {
1425 if i < next_index {
1426 return (acc, next_index);
1427 }
1428
1429 let child = children[i];
1430 if let GreenNode::Token { token_index, .. } = self.arena.get(child)
1432 && let Some(token) = self.tokens.get(*token_index)
1433 && matches!(token.kind, TokenKind::Ident | TokenKind::IdentParameter)
1434 {
1435 let name = token.text(self.source).to_symbol();
1436 let loc = self.location_from_span(token.start..token.end());
1437 let mut next = i + 1;
1438 let mut ty = Type::Unknown.into_id_with_location(loc.clone());
1439 let mut default_value = None;
1440
1441 if next < children.len()
1443 && self.arena.kind(children[next]) == Some(SyntaxKind::TypeAnnotation)
1444 {
1445 if let Some(type_children) = self.arena.children(children[next]) {
1446 ty = type_children
1447 .iter()
1448 .find(|c| {
1449 self.arena
1450 .kind(**c)
1451 .map(Self::is_type_kind)
1452 .unwrap_or(false)
1453 })
1454 .map(|type_node| self.lower_type(*type_node))
1455 .unwrap_or_else(|| {
1456 Type::Unknown.into_id_with_location(loc.clone())
1457 });
1458 }
1459 next += 1;
1460 }
1461
1462 if next < children.len()
1464 && self.arena.kind(children[next]) == Some(SyntaxKind::ParamDefault)
1465 {
1466 let expr_nodes = self.child_exprs(children[next]);
1467 if !expr_nodes.is_empty() {
1468 default_value = Some(self.lower_expr_sequence(&expr_nodes));
1469 }
1470 next += 1;
1471 }
1472
1473 let tid = match default_value {
1474 Some(default_value) => TypedId::with_default(name, ty, default_value),
1475 None => TypedId::new(name, ty),
1476 };
1477
1478 acc.push(tid);
1479 next_index = next;
1480 }
1481
1482 (acc, next_index.max(i + 1))
1483 });
1484 new_params
1485 } else {
1486 Vec::new()
1487 };
1488
1489 let span = self.node_span(node).unwrap_or(0..0);
1490 (params, span)
1491 }
1492
1493 fn child_exprs(&self, node: GreenNodeId) -> Vec<GreenNodeId> {
1494 self.arena
1495 .children(node)
1496 .into_iter()
1497 .flatten()
1498 .copied()
1499 .filter(|child| self.arena.kind(*child).map(Self::is_expr_kind) == Some(true))
1500 .collect()
1501 }
1502
1503 fn child_patterns(&self, node: GreenNodeId) -> Vec<GreenNodeId> {
1504 self.arena
1505 .children(node)
1506 .into_iter()
1507 .flatten()
1508 .copied()
1509 .filter(|child| self.arena.kind(*child).map(Self::is_pattern_kind) == Some(true))
1510 .collect()
1511 }
1512
1513 fn find_child(
1514 &self,
1515 node: GreenNodeId,
1516 predicate: impl Fn(SyntaxKind) -> bool,
1517 ) -> Option<GreenNodeId> {
1518 self.arena
1519 .children(node)?
1520 .iter()
1521 .copied()
1522 .find(|child| match self.arena.kind(*child) {
1523 Some(kind) => predicate(kind),
1524 None => false,
1525 })
1526 }
1527
1528 fn collect_expr_nodes(&self, node: GreenNodeId) -> Vec<GreenNodeId> {
1529 self.arena
1530 .children(node)
1531 .into_iter()
1532 .flatten()
1533 .copied()
1534 .filter(|child| self.arena.kind(*child).map(Self::is_expr_kind) == Some(true))
1535 .collect()
1536 }
1537
1538 fn collect_expr_nodes_after(&self, node: GreenNodeId, after: GreenNodeId) -> Vec<GreenNodeId> {
1539 self.arena
1540 .children(node)
1541 .into_iter()
1542 .flatten()
1543 .copied()
1544 .skip_while(|child| *child != after)
1545 .skip(1)
1546 .filter(|child| self.arena.kind(*child).map(Self::is_expr_kind) == Some(true))
1547 .collect()
1548 }
1549
1550 fn find_token(
1551 &self,
1552 node: GreenNodeId,
1553 predicate: impl Fn(TokenKind) -> bool,
1554 ) -> Option<usize> {
1555 self.walk_tokens(node).into_iter().find(|&idx| {
1556 self.tokens
1557 .get(idx)
1558 .map(|t| predicate(t.kind))
1559 .unwrap_or(false)
1560 })
1561 }
1562
1563 fn walk_tokens(&self, node: GreenNodeId) -> Vec<usize> {
1564 match self.arena.get(node) {
1565 GreenNode::Token { token_index, .. } => vec![*token_index],
1566 GreenNode::Internal { children, .. } => children
1567 .iter()
1568 .flat_map(|child| self.walk_tokens(*child))
1569 .collect(),
1570 }
1571 }
1572
1573 fn text_of_first_token(&self, node: GreenNodeId) -> Option<&'a str> {
1574 self.walk_tokens(node)
1575 .into_iter()
1576 .next()
1577 .and_then(|idx| self.token_text(idx))
1578 }
1579
1580 fn text_of_token_node(&self, node: GreenNodeId) -> Option<&'a str> {
1581 match self.arena.get(node) {
1582 GreenNode::Token { token_index, .. } => self.token_text(*token_index),
1583 _ => None,
1584 }
1585 }
1586
1587 fn get_token_index(&self, node: GreenNodeId) -> Option<usize> {
1588 match self.arena.get(node) {
1589 GreenNode::Token { token_index, .. } => Some(*token_index),
1590 _ => None,
1591 }
1592 }
1593
1594 fn token_text(&self, index: usize) -> Option<&'a str> {
1595 self.tokens.get(index).map(|t| t.text(self.source))
1596 }
1597
1598 fn node_span(&self, node: GreenNodeId) -> Option<Span> {
1599 match self.arena.get(node) {
1600 GreenNode::Token { token_index, .. } => {
1601 self.tokens.get(*token_index).map(|t| t.start..t.end())
1602 }
1603 GreenNode::Internal { children, .. } => {
1604 let (start, end) = children
1605 .iter()
1606 .filter_map(|child| self.node_span(*child))
1607 .fold(
1608 (Option::<usize>::None, Option::<usize>::None),
1609 |(start, end), span| {
1610 let next_start = Some(start.map_or(span.start, |s| s.min(span.start)));
1611 let next_end = Some(end.map_or(span.end, |e| e.max(span.end)));
1612 (next_start, next_end)
1613 },
1614 );
1615
1616 start.zip(end).map(|(s, e)| s..e)
1617 }
1618 }
1619 }
1620
1621 fn location_from_span(&self, span: Span) -> Location {
1622 Location {
1623 span,
1624 path: self.file_path.clone(),
1625 }
1626 }
1627
1628 fn lower_arg_list(&self, node: GreenNodeId) -> Vec<ExprNodeId> {
1629 let collect_args = |children: &[GreenNodeId]| {
1630 let (mut args, current) = children.iter().copied().fold(
1631 (Vec::new(), Vec::new()),
1632 |(mut args, mut current), child| {
1633 match self.arena.get(child) {
1634 GreenNode::Token { token_index, .. }
1635 if self.tokens.get(*token_index).map(|t| t.kind)
1636 == Some(TokenKind::Comma) =>
1637 {
1638 if !current.is_empty() {
1639 args.push(self.lower_expr_sequence(¤t));
1640 current.clear();
1641 }
1642 }
1643 _ => {
1644 if self.arena.kind(child).map(Self::is_expr_kind) == Some(true) {
1645 current.push(child);
1646 }
1647 }
1648 }
1649 (args, current)
1650 },
1651 );
1652 if !current.is_empty() {
1653 args.push(self.lower_expr_sequence(¤t));
1654 }
1655 args
1656 };
1657
1658 if let Some(arg_node) = self.find_child(node, |kind| kind == SyntaxKind::ArgList) {
1660 if let Some(children) = self.arena.children(arg_node) {
1661 return collect_args(children);
1662 }
1663 return Vec::new();
1664 }
1665
1666 if let Some(children) = self.arena.children(node) {
1668 return collect_args(children);
1669 }
1670 Vec::new()
1671 }
1672
1673 fn lower_expr_list(&self, node: GreenNodeId) -> Vec<ExprNodeId> {
1674 let collect_elems = |children: &[GreenNodeId]| {
1675 let (mut elems, current) = children.iter().copied().fold(
1676 (Vec::new(), Vec::new()),
1677 |(mut elems, mut current), child| {
1678 match self.arena.get(child) {
1679 GreenNode::Token { token_index, .. }
1680 if self.tokens.get(*token_index).map(|t| t.kind)
1681 == Some(TokenKind::Comma) =>
1682 {
1683 if !current.is_empty() {
1684 elems.push(self.lower_expr_sequence(¤t));
1685 current.clear();
1686 }
1687 }
1688 _ => {
1689 if self.arena.kind(child).map(Self::is_expr_kind) == Some(true) {
1690 current.push(child);
1691 }
1692 }
1693 }
1694 (elems, current)
1695 },
1696 );
1697 if !current.is_empty() {
1698 elems.push(self.lower_expr_sequence(¤t));
1699 }
1700 elems
1701 };
1702
1703 self.arena
1704 .children(node)
1705 .map_or_else(Vec::new, collect_elems)
1706 }
1707
1708 fn is_expr_kind(kind: SyntaxKind) -> bool {
1709 matches!(
1710 kind,
1711 SyntaxKind::BinaryExpr
1712 | SyntaxKind::UnaryExpr
1713 | SyntaxKind::ParenExpr
1714 | SyntaxKind::CallExpr
1715 | SyntaxKind::FieldAccess
1716 | SyntaxKind::IndexExpr
1717 | SyntaxKind::AssignExpr
1718 | SyntaxKind::ArrayExpr
1719 | SyntaxKind::MacroExpansion
1720 | SyntaxKind::BracketExpr
1721 | SyntaxKind::EscapeExpr
1722 | SyntaxKind::LambdaExpr
1723 | SyntaxKind::IfExpr
1724 | SyntaxKind::MatchExpr
1725 | SyntaxKind::BlockExpr
1726 | SyntaxKind::TupleExpr
1727 | SyntaxKind::RecordExpr
1728 | SyntaxKind::IntLiteral
1729 | SyntaxKind::FloatLiteral
1730 | SyntaxKind::StringLiteral
1731 | SyntaxKind::SelfLiteral
1732 | SyntaxKind::NowLiteral
1733 | SyntaxKind::SampleRateLiteral
1734 | SyntaxKind::PlaceHolderLiteral
1735 | SyntaxKind::Identifier
1736 | SyntaxKind::QualifiedPath
1737 )
1738 }
1739
1740 fn is_pattern_kind(kind: SyntaxKind) -> bool {
1741 matches!(
1742 kind,
1743 SyntaxKind::Pattern
1744 | SyntaxKind::SinglePattern
1745 | SyntaxKind::TuplePattern
1746 | SyntaxKind::RecordPattern
1747 )
1748 }
1749
1750 fn extract_unary_op(&self, node: GreenNodeId) -> Option<Op> {
1751 self.walk_tokens(node)
1752 .into_iter()
1753 .find_map(|idx| match self.tokens.get(idx)?.kind {
1754 TokenKind::OpMinus => Some(Op::Minus),
1755 TokenKind::OpSum => Some(Op::Sum),
1756 _ => None,
1757 })
1758 }
1759
1760 fn extract_binary_op(&self, node: GreenNodeId) -> Option<(Op, Span)> {
1761 let children = self.arena.children(node)?;
1764 for &child in children {
1765 if let Some(idx) = self.get_token_index(child)
1766 && let Some(tok) = self.tokens.get(idx)
1767 {
1768 let op = match tok.kind {
1769 TokenKind::OpSum => Some(Op::Sum),
1770 TokenKind::OpMinus => Some(Op::Minus),
1771 TokenKind::OpProduct => Some(Op::Product),
1772 TokenKind::OpDivide => Some(Op::Divide),
1773 TokenKind::OpEqual => Some(Op::Equal),
1774 TokenKind::OpNotEqual => Some(Op::NotEqual),
1775 TokenKind::OpLessThan => Some(Op::LessThan),
1776 TokenKind::OpLessEqual => Some(Op::LessEqual),
1777 TokenKind::OpGreaterThan => Some(Op::GreaterThan),
1778 TokenKind::OpGreaterEqual => Some(Op::GreaterEqual),
1779 TokenKind::OpModulo => Some(Op::Modulo),
1780 TokenKind::OpExponent => Some(Op::Exponent),
1781 TokenKind::OpAnd => Some(Op::And),
1782 TokenKind::OpOr => Some(Op::Or),
1783 TokenKind::OpAt => Some(Op::At),
1784 TokenKind::OpPipe => Some(Op::Pipe),
1785 TokenKind::OpPipeMacro => Some(Op::PipeMacro),
1786 _ => None,
1787 };
1788 if let Some(op) = op {
1789 return Some((op, tok.start..tok.end()));
1790 }
1791 }
1792 }
1793 None
1794 }
1795}
1796
1797pub fn parse_program(source: &str, file_path: PathBuf) -> (Program, Vec<ParserError>) {
1799 let tokens = crate::compiler::parser::tokenize(source);
1800 let preparsed = crate::compiler::parser::preparse(&tokens);
1801 let (root, arena, tokens, errors) = crate::compiler::parser::parse_cst(tokens, &preparsed);
1802 let lowerer = Lowerer::new(source, &tokens, &arena, file_path);
1803 let program = lowerer.lower_program(root);
1804 (program, errors)
1805}
1806
1807pub fn parse_to_expr(
1810 source: &str,
1811 file_path: Option<PathBuf>,
1812) -> (
1813 ExprNodeId,
1814 crate::ast::program::ModuleInfo,
1815 Vec<Box<dyn crate::utils::error::ReportableError>>,
1816) {
1817 let path = file_path.unwrap_or_default();
1818 let (prog, parse_errs) = parse_program(source, path.clone());
1819 let errs =
1820 crate::compiler::parser::parser_errors_to_reportable(source, path.clone(), parse_errs);
1821
1822 if prog.statements.is_empty() {
1823 return (
1824 Expr::Error.into_id_without_span(),
1825 crate::ast::program::ModuleInfo::new(),
1826 errs,
1827 );
1828 }
1829
1830 let (expr, module_info, mut new_errs) = crate::ast::program::expr_from_program(prog, path);
1831 let mut all_errs = errs;
1832 all_errs.append(&mut new_errs);
1833 (expr, module_info, all_errs)
1834}
1835
1836pub fn add_global_context(ast: ExprNodeId, file_path: PathBuf) -> ExprNodeId {
1839 let span = ast.to_span();
1840 let loc = crate::utils::metadata::Location {
1841 span: span.clone(),
1842 path: file_path,
1843 };
1844 let res = Expr::Let(
1845 TypedPattern::new(
1846 Pattern::Single(crate::utils::metadata::GLOBAL_LABEL.to_symbol()),
1847 Type::Unknown.into_id_with_location(loc.clone()),
1848 ),
1849 Expr::Lambda(vec![], None, ast).into_id(loc.clone()),
1850 None,
1851 );
1852 res.into_id(loc)
1853}
1854
1855impl<'a> Lowerer<'a> {
1857 fn is_type_kind(kind: SyntaxKind) -> bool {
1858 matches!(
1859 kind,
1860 SyntaxKind::PrimitiveType
1861 | SyntaxKind::UnitType
1862 | SyntaxKind::TupleType
1863 | SyntaxKind::RecordType
1864 | SyntaxKind::FunctionType
1865 | SyntaxKind::ArrayType
1866 | SyntaxKind::CodeType
1867 | SyntaxKind::UnionType
1868 | SyntaxKind::TypeIdent
1869 )
1870 }
1871
1872 fn lower_type(&self, node: GreenNodeId) -> crate::interner::TypeNodeId {
1874 use crate::types::{PType, RecordTypeField, Type};
1875
1876 let span = self.node_span(node).unwrap_or(0..0);
1877 let loc = self.location_from_span(span);
1878
1879 match self.arena.kind(node) {
1880 Some(SyntaxKind::PrimitiveType) => {
1881 let text = self.text_of_first_token(node).unwrap_or("float");
1882 let ptype = match text {
1883 "float" => PType::Numeric,
1884 "int" => PType::Int,
1885 "string" => PType::String,
1886 _ => PType::Numeric,
1887 };
1888 Type::Primitive(ptype).into_id_with_location(loc)
1889 }
1890 Some(SyntaxKind::UnitType) => Type::Primitive(PType::Unit).into_id_with_location(loc),
1891 Some(SyntaxKind::TupleType) => {
1892 let elem_types = self
1893 .arena
1894 .children(node)
1895 .into_iter()
1896 .flatten()
1897 .filter(|child| {
1898 self.arena
1899 .kind(**child)
1900 .map(Self::is_type_kind)
1901 .unwrap_or(false)
1902 })
1903 .map(|child| self.lower_type(*child))
1904 .collect::<Vec<_>>();
1905 Type::Tuple(elem_types).into_id_with_location(loc)
1906 }
1907 Some(SyntaxKind::ArrayType) => {
1908 let elem_type = self
1909 .arena
1910 .children(node)
1911 .into_iter()
1912 .flatten()
1913 .find(|child| {
1914 self.arena
1915 .kind(**child)
1916 .map(Self::is_type_kind)
1917 .unwrap_or(false)
1918 })
1919 .map(|child| self.lower_type(*child))
1920 .unwrap_or_else(|| Type::Unknown.into_id_with_location(loc.clone()));
1921 Type::Array(elem_type).into_id_with_location(loc)
1922 }
1923 Some(SyntaxKind::FunctionType) => {
1924 let children: Vec<_> = self
1926 .arena
1927 .children(node)
1928 .into_iter()
1929 .flatten()
1930 .filter(|child| {
1931 self.arena
1932 .kind(**child)
1933 .map(Self::is_type_kind)
1934 .unwrap_or(false)
1935 })
1936 .copied()
1937 .collect();
1938
1939 if children.len() >= 2 {
1940 let lowered = children
1941 .iter()
1942 .map(|child| self.lower_type(*child))
1943 .collect::<Vec<_>>();
1944
1945 let return_type = *lowered
1946 .last()
1947 .unwrap_or(&Type::Unknown.into_id_with_location(loc.clone()));
1948 let param_type = if lowered.len() == 2 {
1949 lowered[0]
1950 } else {
1951 Type::Tuple(lowered[..lowered.len() - 1].to_vec())
1952 .into_id_with_location(loc.clone())
1953 };
1954
1955 Type::Function {
1956 arg: param_type,
1957 ret: return_type,
1958 }
1959 .into_id_with_location(loc)
1960 } else {
1961 Type::Unknown.into_id_with_location(loc)
1962 }
1963 }
1964 Some(SyntaxKind::RecordType) => {
1965 let mut fields = Vec::new();
1967 let mut current_field: Option<Symbol> = None;
1968
1969 if let Some(children) = self.arena.children(node) {
1970 for child in children {
1971 if let Some(token_index) = self.get_token_index(*child)
1973 && let Some(token) = self.tokens.get(token_index)
1974 && matches!(token.kind, TokenKind::Ident | TokenKind::IdentParameter)
1975 {
1976 current_field = Some(token.text(self.source).to_symbol());
1977 continue;
1978 }
1979
1980 if self.arena.kind(*child).map(Self::is_type_kind) == Some(true)
1981 && let Some(name) = current_field.take()
1982 {
1983 fields.push(RecordTypeField::new(name, self.lower_type(*child), false));
1984 }
1985 }
1986 }
1987 Type::Record(fields).into_id_with_location(loc)
1988 }
1989 Some(SyntaxKind::CodeType) => {
1990 let inner = self
1991 .arena
1992 .children(node)
1993 .into_iter()
1994 .flatten()
1995 .find(|child| self.arena.kind(**child).map(Self::is_type_kind) == Some(true))
1996 .map(|child| self.lower_type(*child))
1997 .unwrap_or_else(|| Type::Unknown.into_id_with_location(loc.clone()));
1998 Type::Code(inner).into_id_with_location(loc)
1999 }
2000 Some(SyntaxKind::UnionType) => {
2001 let elem_types = self
2002 .arena
2003 .children(node)
2004 .into_iter()
2005 .flatten()
2006 .filter(|child| {
2007 self.arena
2008 .kind(**child)
2009 .map(Self::is_type_kind)
2010 .unwrap_or(false)
2011 })
2012 .map(|child| self.lower_type(*child))
2013 .collect::<Vec<_>>();
2014 Type::Union(elem_types).into_id_with_location(loc)
2015 }
2016 Some(SyntaxKind::TypeIdent) => {
2017 if let Some(children) = self.arena.children(node) {
2020 let mut path_segments = Vec::new();
2021
2022 for child in children {
2023 if let Some(token_index) = self.get_token_index(*child)
2024 && let Some(token) = self.tokens.get(token_index)
2025 {
2026 if matches!(token.kind, TokenKind::Ident) {
2027 path_segments.push(token.text(self.source));
2028 }
2029 }
2031 }
2032
2033 if !path_segments.is_empty() {
2034 let type_name = path_segments.join("$").to_symbol();
2036 return Type::TypeAlias(type_name).into_id_with_location(loc);
2037 }
2038 }
2039 Type::Unknown.into_id_with_location(loc)
2040 }
2041 _ => {
2042 if let Some(token_index) = self.get_token_index(node)
2044 && let Some(token) = self.tokens.get(token_index)
2045 && matches!(token.kind, TokenKind::Ident)
2046 {
2047 let type_name = token.text(self.source).to_symbol();
2049 Type::TypeAlias(type_name).into_id_with_location(loc)
2050 } else {
2051 Type::Unknown.into_id_with_location(loc)
2052 }
2053 }
2054 }
2055 }
2056}
2057
2058fn merge_spans(a: Span, b: Span) -> Span {
2059 a.start.min(b.start)..a.end.max(b.end)
2060}
2061
2062#[cfg(test)]
2063mod tests {
2064 use super::*;
2065 use crate::compiler::parser::{parse_cst, preparse, tokenize};
2066
2067 fn parse_source(source: &str) -> Program {
2068 let tokens = tokenize(source);
2069 let preparsed = preparse(&tokens);
2070 let (green_id, arena, tokens, _errors) = parse_cst(tokens, &preparsed);
2071 let lowerer = Lowerer::new(source, &tokens, &arena, PathBuf::new());
2072 lowerer.lower_program(green_id)
2073 }
2074
2075 #[test]
2076 fn test_parse_module_declaration() {
2077 let source = "mod mymod { fn foo() { 42 } }";
2078 let prog = parse_source(source);
2079
2080 assert!(!prog.statements.is_empty());
2081
2082 let stmt = &prog.statements[0].0;
2083 match stmt {
2084 ProgramStatement::ModuleDefinition {
2085 visibility,
2086 name,
2087 body,
2088 } => {
2089 assert_eq!(*visibility, Visibility::Private);
2090 assert_eq!(name.as_str(), "mymod");
2091 assert!(body.as_ref().map(|b| !b.is_empty()).unwrap_or(false));
2092 }
2093 _ => panic!("Expected ModuleDefinition, got {:?}", stmt),
2094 }
2095 }
2096
2097 #[test]
2098 fn test_parse_pub_module_declaration() {
2099 let source = "pub mod mymod { fn bar() { 1 } }";
2100 let prog = parse_source(source);
2101
2102 assert!(!prog.statements.is_empty());
2103
2104 let stmt = &prog.statements[0].0;
2105 match stmt {
2106 ProgramStatement::ModuleDefinition {
2107 visibility,
2108 name,
2109 body,
2110 } => {
2111 assert_eq!(*visibility, Visibility::Public);
2112 assert_eq!(name.as_str(), "mymod");
2113 assert!(body.as_ref().map(|b| !b.is_empty()).unwrap_or(false));
2114 }
2115 _ => panic!("Expected ModuleDefinition, got {:?}", stmt),
2116 }
2117 }
2118
2119 #[test]
2120 fn test_parse_use_statement() {
2121 let source = "use modA::funcB";
2122 let prog = parse_source(source);
2123
2124 assert!(!prog.statements.is_empty());
2125
2126 let stmt = &prog.statements[0].0;
2127 match stmt {
2128 ProgramStatement::UseStatement {
2129 visibility,
2130 path,
2131 target,
2132 } => {
2133 assert_eq!(*visibility, Visibility::Private);
2134 assert_eq!(path.segments.len(), 2);
2135 assert_eq!(path.segments[0].as_str(), "modA");
2136 assert_eq!(path.segments[1].as_str(), "funcB");
2137 assert!(matches!(target, UseTarget::Single));
2138 }
2139 _ => panic!("Expected UseStatement, got {:?}", stmt),
2140 }
2141 }
2142
2143 #[test]
2144 fn test_parse_use_multiple() {
2145 let source = "use modA::{funcB, funcC}";
2146 let prog = parse_source(source);
2147
2148 assert!(!prog.statements.is_empty());
2149
2150 let stmt = &prog.statements[0].0;
2151 match stmt {
2152 ProgramStatement::UseStatement {
2153 visibility,
2154 path,
2155 target,
2156 } => {
2157 assert_eq!(*visibility, Visibility::Private);
2158 assert_eq!(path.segments.len(), 1);
2159 assert_eq!(path.segments[0].as_str(), "modA");
2160 match target {
2161 UseTarget::Multiple(names) => {
2162 assert_eq!(names.len(), 2);
2163 assert_eq!(names[0].as_str(), "funcB");
2164 assert_eq!(names[1].as_str(), "funcC");
2165 }
2166 _ => panic!("Expected UseTarget::Multiple"),
2167 }
2168 }
2169 _ => panic!("Expected UseStatement, got {:?}", stmt),
2170 }
2171 }
2172
2173 #[test]
2174 fn test_parse_use_wildcard() {
2175 let source = "use modA::*";
2176 let prog = parse_source(source);
2177
2178 assert!(!prog.statements.is_empty());
2179
2180 let stmt = &prog.statements[0].0;
2181 match stmt {
2182 ProgramStatement::UseStatement {
2183 visibility,
2184 path,
2185 target,
2186 } => {
2187 assert_eq!(*visibility, Visibility::Private);
2188 assert_eq!(path.segments.len(), 1);
2189 assert_eq!(path.segments[0].as_str(), "modA");
2190 assert!(matches!(target, UseTarget::Wildcard));
2191 }
2192 _ => panic!("Expected UseStatement, got {:?}", stmt),
2193 }
2194 }
2195
2196 #[test]
2197 fn test_parse_nested_module() {
2198 let source = "mod outer { mod inner { fn baz() { 0 } } }";
2199 let prog = parse_source(source);
2200
2201 assert!(!prog.statements.is_empty());
2202
2203 let stmt = &prog.statements[0].0;
2204 match stmt {
2205 ProgramStatement::ModuleDefinition {
2206 visibility,
2207 name,
2208 body,
2209 } => {
2210 assert_eq!(*visibility, Visibility::Private);
2211 assert_eq!(name.as_str(), "outer");
2212 let body = body.as_ref().expect("Expected inline module body");
2213 assert!(!body.is_empty());
2214
2215 let inner_stmt = &body[0].0;
2217 match inner_stmt {
2218 ProgramStatement::ModuleDefinition {
2219 name: inner_name, ..
2220 } => {
2221 assert_eq!(inner_name.as_str(), "inner");
2222 }
2223 _ => panic!("Expected inner ModuleDefinition"),
2224 }
2225 }
2226 _ => panic!("Expected ModuleDefinition, got {:?}", stmt),
2227 }
2228 }
2229
2230 #[test]
2231 fn test_parse_use_with_long_path() {
2232 let source = "use a::b::c::d";
2233 let prog = parse_source(source);
2234
2235 assert!(!prog.statements.is_empty());
2236
2237 let stmt = &prog.statements[0].0;
2238 match stmt {
2239 ProgramStatement::UseStatement { path, .. } => {
2240 assert_eq!(path.segments.len(), 4);
2241 assert_eq!(path.segments[0].as_str(), "a");
2242 assert_eq!(path.segments[1].as_str(), "b");
2243 assert_eq!(path.segments[2].as_str(), "c");
2244 assert_eq!(path.segments[3].as_str(), "d");
2245 }
2246 _ => panic!("Expected UseStatement, got {:?}", stmt),
2247 }
2248 }
2249
2250 #[test]
2251 fn test_module_with_multiple_items() {
2252 let source = r#"
2253mod mymod {
2254 pub fn add(x, y) { x + y }
2255 fn private_func() { 42 }
2256 use other_mod
2257}
2258"#;
2259 let prog = parse_source(source);
2260
2261 assert!(!prog.statements.is_empty());
2262
2263 let stmt = &prog.statements[0].0;
2264 match stmt {
2265 ProgramStatement::ModuleDefinition { body, .. } => {
2266 let body = body.as_ref().expect("Expected inline module body");
2268 assert!(body.len() >= 2);
2269 }
2270 _ => panic!("Expected ModuleDefinition"),
2271 }
2272 }
2273
2274 #[test]
2275 fn test_parse_external_module() {
2276 let source = "mod external_module";
2278 let prog = parse_source(source);
2279
2280 assert!(!prog.statements.is_empty());
2281
2282 let stmt = &prog.statements[0].0;
2283 match stmt {
2284 ProgramStatement::ModuleDefinition {
2285 visibility,
2286 name,
2287 body,
2288 } => {
2289 assert_eq!(*visibility, Visibility::Private);
2290 assert_eq!(name.as_str(), "external_module");
2291 assert!(body.is_none(), "External module should have None body");
2293 }
2294 _ => panic!("Expected ModuleDefinition, got {:?}", stmt),
2295 }
2296 }
2297
2298 #[test]
2299 fn test_external_module_with_use_generates_correct_ast() {
2300 use crate::ast::program::expr_from_program;
2304
2305 let inline_source = r#"
2307mod mymod {
2308 pub fn add(x, y) { x + y }
2309}
2310use mymod::add
2311fn dsp() { add(1.0, 2.0) }
2312"#;
2313 let inline_prog = parse_source(inline_source);
2314 let (expr, module_info, errs) = expr_from_program(inline_prog, PathBuf::from("test.mmm"));
2315
2316 assert!(
2318 module_info.use_alias_map.contains_key(&"add".to_symbol()),
2319 "use_alias_map should contain 'add'"
2320 );
2321 assert_eq!(
2322 module_info.use_alias_map.get(&"add".to_symbol()).copied(),
2323 Some("mymod$add".to_symbol())
2324 );
2325
2326 assert!(
2328 module_info
2329 .visibility_map
2330 .contains_key(&"mymod$add".to_symbol()),
2331 "visibility_map should contain 'mymod$add'"
2332 );
2333 assert!(
2334 *module_info
2335 .visibility_map
2336 .get(&"mymod$add".to_symbol())
2337 .unwrap(),
2338 "mymod$add should be public"
2339 );
2340
2341 let ast_string = format!("{:?}", expr.to_expr());
2343 assert!(
2344 ast_string.contains("mymod$add"),
2345 "AST should contain mymod$add, but got: {}",
2346 ast_string
2347 );
2348 }
2349
2350 #[test]
2351 fn test_parse_pub_use() {
2352 let source = "pub use modA::funcB";
2353 let prog = parse_source(source);
2354
2355 assert!(!prog.statements.is_empty());
2356
2357 let stmt = &prog.statements[0].0;
2358 match stmt {
2359 ProgramStatement::UseStatement {
2360 visibility,
2361 path,
2362 target,
2363 } => {
2364 assert_eq!(*visibility, Visibility::Public);
2365 assert_eq!(path.segments.len(), 2);
2366 assert_eq!(path.segments[0].as_str(), "modA");
2367 assert_eq!(path.segments[1].as_str(), "funcB");
2368 assert!(matches!(target, UseTarget::Single));
2369 }
2370 _ => panic!("Expected UseStatement, got {:?}", stmt),
2371 }
2372 }
2373
2374 #[test]
2375 fn test_parse_match_expr() {
2376 let source = "fn test_match(num) { match num { 0 => 100, 1 => 200, _ => 300 } }";
2377 let prog = parse_source(source);
2378
2379 assert!(!prog.statements.is_empty());
2380 let stmt = &prog.statements[0].0;
2381 match stmt {
2382 ProgramStatement::FnDefinition { body, .. } => {
2383 let body_expr = body.to_expr();
2384 match body_expr {
2385 Expr::Match(scrutinee, arms) => {
2386 match scrutinee.to_expr() {
2388 Expr::Var(name) => assert_eq!(name.as_str(), "num"),
2389 other => panic!("Expected Var, got {other:?}"),
2390 }
2391
2392 assert_eq!(arms.len(), 3);
2394
2395 match &arms[0].pattern {
2397 crate::ast::MatchPattern::Literal(crate::ast::Literal::Int(0)) => {}
2398 other => panic!("Expected pattern Literal(Int(0)), got {:?}", other),
2399 }
2400 match arms[0].body.to_expr() {
2402 Expr::Literal(crate::ast::Literal::Float(s)) => {
2403 assert_eq!(s.as_str(), "100");
2404 }
2405 other => panic!("Expected body Literal(Float(100)), got {:?}", other),
2406 }
2407
2408 match &arms[1].pattern {
2410 crate::ast::MatchPattern::Literal(crate::ast::Literal::Int(1)) => {}
2411 other => panic!("Expected pattern Literal(Int(1)), got {:?}", other),
2412 }
2413 match arms[1].body.to_expr() {
2414 Expr::Literal(crate::ast::Literal::Float(s)) => {
2415 assert_eq!(s.as_str(), "200");
2416 }
2417 other => panic!("Expected body Literal(Float(200)), got {:?}", other),
2418 }
2419
2420 match &arms[2].pattern {
2422 crate::ast::MatchPattern::Wildcard => {}
2423 other => panic!("Expected Wildcard, got {:?}", other),
2424 }
2425 match arms[2].body.to_expr() {
2426 Expr::Literal(crate::ast::Literal::Float(s)) => {
2427 assert_eq!(s.as_str(), "300");
2428 }
2429 other => panic!("Expected body Literal(Float(300)), got {:?}", other),
2430 }
2431 }
2432 other => panic!("Expected Match expr, got {:?}", other),
2433 }
2434 }
2435 _ => panic!("Expected FnDefinition, got {:?}", stmt),
2436 }
2437 }
2438
2439 #[test]
2440 fn test_parse_pipe_and_macro_pipe_share_precedence_and_associate_left() {
2441 let source = "fn test(a, b, c) { a ||> b |> c }";
2442 let prog = parse_source(source);
2443
2444 let stmt = &prog.statements[0].0;
2445 match stmt {
2446 ProgramStatement::FnDefinition { body, .. } => match body.to_expr() {
2447 Expr::BinOp(lhs, (Op::Pipe, _), rhs) => {
2448 assert!(matches!(rhs.to_expr(), Expr::Var(name) if name.as_str() == "c"));
2449 match lhs.to_expr() {
2450 Expr::BinOp(inner_lhs, (Op::PipeMacro, _), inner_rhs) => {
2451 assert!(matches!(
2452 inner_lhs.to_expr(),
2453 Expr::Var(name) if name.as_str() == "a"
2454 ));
2455 assert!(matches!(
2456 inner_rhs.to_expr(),
2457 Expr::Var(name) if name.as_str() == "b"
2458 ));
2459 }
2460 other => panic!("Expected nested PipeMacro on LHS, got {other:?}"),
2461 }
2462 }
2463 other => panic!("Expected top-level Pipe, got {other:?}"),
2464 },
2465 _ => panic!("Expected FnDefinition, got {stmt:?}"),
2466 }
2467 }
2468}