rue_compiler/compile/expr/
list.rs1use log::debug;
2use rue_ast::AstListExpr;
3use rue_diagnostic::DiagnosticKind;
4use rue_hir::{Hir, Value};
5use rue_types::{Pair, Type, TypeId, Union};
6
7use crate::{Compiler, compile_expr};
8
9pub fn compile_list_expr(
10 ctx: &mut Compiler,
11 list: &AstListExpr,
12 mut expected_type: Option<TypeId>,
13) -> Value {
14 let mut values = Vec::new();
15 let mut nil_terminated = true;
16
17 let len = list.items().count();
18
19 for (i, item) in list.items().enumerate() {
20 let is_spread = if let Some(spread) = item.spread() {
21 if i == len - 1 {
22 true
23 } else {
24 ctx.diagnostic(&spread, DiagnosticKind::NonFinalSpread);
25 false
26 }
27 } else {
28 false
29 };
30
31 let item_type = if is_spread {
32 nil_terminated = false;
33 expected_type
34 } else if let Some(ty) = expected_type
35 && let pairs = rue_types::extract_pairs(ctx.types_mut(), ty, false)
36 && !pairs.is_empty()
37 {
38 let first = if pairs.len() == 1 {
39 pairs[0].first
40 } else {
41 ctx.alloc_type(Type::Union(Union::new(
42 pairs.iter().map(|pair| pair.first).collect(),
43 )))
44 };
45
46 let rest = if pairs.len() == 1 {
47 pairs[0].rest
48 } else {
49 ctx.alloc_type(Type::Union(Union::new(
50 pairs.iter().map(|pair| pair.rest).collect(),
51 )))
52 };
53
54 expected_type = Some(rest);
55
56 Some(first)
57 } else {
58 None
59 };
60
61 let value = if let Some(expr) = item.expr() {
62 compile_expr(ctx, &expr, item_type)
63 } else {
64 debug!("Unresolved list item expr");
65 ctx.builtins().unresolved.clone()
66 };
67
68 values.push(value);
69 }
70
71 let mut hir = ctx.builtins().nil.hir;
72 let mut ty = ctx.builtins().nil.ty;
73
74 for (i, value) in values.into_iter().rev().enumerate() {
75 if !nil_terminated && i == 0 {
76 hir = value.hir;
77 ty = value.ty;
78 continue;
79 }
80 hir = ctx.alloc_hir(Hir::Pair(value.hir, hir));
81 ty = ctx.alloc_type(Type::Pair(Pair::new(value.ty, ty)));
82 }
83
84 Value::new(hir, ty)
85}