rue_compiler/compile/expr/
list.rs

1use 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}