Skip to main content

rl_lang/resolver/
expressions.rs

1//! Expression resolution - transforms name references into indexed lookups.
2//!
3//! Each expression variant is handled in [`Resolver::resolve_expression`]:
4//!
5//! - `Identifier` -> `ResolvedIdentifier { depth, slot }` if found in scope,
6//!   left as `Identifier` if not (stdlib names, unresolved at this stage)
7//! - `Assign` -> `ResolvedAssign { depth, slot, value }`
8//! - `Lambda` -> `ResolvedLambda { capture_depth, ... }` with a fresh scope
9//!   for its parameters; `capture_depth` is the scope stack length at the
10//!   point of definition, used by the evaluator to capture the environment
11//! - `Call` with a single-segment path -> `CallExpr` with a `ResolvedIdentifier`
12//!   callee if the name is in scope; left as `Call` for stdlib paths
13//! - All other variants recurse into their sub-expressions unchanged
14//!
15//! All resolution mutates nodes in place via `ExprId` + `Arena::get_mut`.
16//! The node's `ExprId` never changes - only its `kind` does. Child `ExprId`s
17//! embedded in a parent's kind stay valid across the rewrite since resolving
18//! a child mutates the arena slot it already occupies, not its address.
19use crate::{
20    ast::{ExprId, nodes::ExpressionKind},
21    resolver::Resolver,
22};
23
24impl Resolver {
25    /// Resolves the expression at `id` in place and returns the same `id`.
26    /// The return value exists so call sites can write
27    /// `field: self.resolve_expression(field)` without changing shape.
28    pub fn resolve_expression(&mut self, id: ExprId) -> ExprId {
29        let span = self.ast_arena.exprs.get(id).span;
30        // One clone to release the immutable borrow before recursing -
31        // matches the `.kind.clone()` pattern already in evaluator.rs.
32        let kind = self.ast_arena.exprs.get(id).kind.clone();
33
34        let new_kind = match kind {
35            ExpressionKind::Identifier(name) => self
36                .resolve_name(&name)
37                .map(|(depth, slot)| ExpressionKind::ResolvedIdentifier { name, depth, slot }),
38
39            ExpressionKind::Assign { name, value } => {
40                self.resolve_expression(value);
41                self.resolve_name(&name)
42                    .map(|(depth, slot)| ExpressionKind::ResolvedAssign {
43                        name,
44                        depth,
45                        slot,
46                        value,
47                    })
48            }
49
50            ExpressionKind::Lambda {
51                params,
52                return_type,
53                body,
54            } => {
55                let capture_depth = self.scopes.len();
56
57                self.push_scope();
58                for p in &params {
59                    self.declare(p.param_name.clone());
60                }
61                let body = self.resolve_statements(body);
62                self.pop_scope();
63
64                Some(ExpressionKind::ResolvedLambda {
65                    params,
66                    return_type,
67                    body,
68                    capture_depth,
69                })
70            }
71
72            ExpressionKind::Binary { left, right, .. } => {
73                self.resolve_expression(left);
74                self.resolve_expression(right);
75                None
76            }
77            ExpressionKind::Unary { operand, .. } => {
78                self.resolve_expression(operand);
79                None
80            }
81
82            ExpressionKind::Grouping(inner) => {
83                self.resolve_expression(inner);
84                None
85            }
86            ExpressionKind::ArrayLiteral(items) => {
87                for item in &items {
88                    self.resolve_expression(*item);
89                }
90                None
91            }
92
93            ExpressionKind::Index { target, index } => {
94                self.resolve_expression(target);
95                self.resolve_expression(index);
96                None
97            }
98            ExpressionKind::IndexAssign {
99                target,
100                index,
101                value,
102            } => {
103                self.resolve_expression(target);
104                self.resolve_expression(index);
105                self.resolve_expression(value);
106                None
107            }
108
109            ExpressionKind::Call { path, args } => {
110                for arg in &args {
111                    self.resolve_expression(*arg);
112                }
113                if path.len() == 1
114                    && let Some((depth, slot)) = self.resolve_name(&path[0])
115                {
116                    let callee = self.ast_arena.alloc_expr(
117                        ExpressionKind::ResolvedIdentifier {
118                            name: path[0].clone(),
119                            depth,
120                            slot,
121                        },
122                        span,
123                    );
124                    Some(ExpressionKind::CallExpr { callee, args })
125                } else {
126                    // stdlib path - leave as Call
127                    None
128                }
129            }
130            ExpressionKind::CallExpr { callee, args } => {
131                self.resolve_expression(callee);
132                for arg in &args {
133                    self.resolve_expression(*arg);
134                }
135                None
136            }
137
138            ExpressionKind::MethodCall { caller, args, .. } => {
139                self.resolve_expression(caller);
140                for arg in &args {
141                    self.resolve_expression(*arg);
142                }
143                None
144            }
145
146            ExpressionKind::Cast { value, .. } => {
147                self.resolve_expression(value);
148                None
149            }
150
151            ExpressionKind::ErrorLiteral(inner)
152            | ExpressionKind::OkLiteral(inner)
153            | ExpressionKind::ErrLiteral(inner)
154            | ExpressionKind::Propagate(inner) => {
155                self.resolve_expression(inner);
156                None
157            }
158
159            ExpressionKind::TupleLiteral(items) => {
160                for item in &items {
161                    self.resolve_expression(*item);
162                }
163                None
164            }
165
166            ExpressionKind::StructLiteral { fields, .. } => {
167                for (_, value) in &fields {
168                    self.resolve_expression(*value);
169                }
170                None
171            }
172            ExpressionKind::FieldAccess { target, .. } => {
173                self.resolve_expression(target);
174                None
175            }
176            ExpressionKind::FieldAssign { target, value, .. } => {
177                self.resolve_expression(target);
178                self.resolve_expression(value);
179                None
180            }
181            ExpressionKind::MapLiteral(entries) => {
182                for (key, value) in &entries {
183                    self.resolve_expression(*key);
184                    self.resolve_expression(*value);
185                }
186                None
187            }
188            ExpressionKind::SetLiteral(items) => {
189                for id in &items {
190                    self.resolve_expression(*id);
191                }
192                None
193            }
194
195            _ => None,
196        };
197
198        if let Some(new_kind) = new_kind {
199            self.ast_arena.exprs.get_mut(id).kind = new_kind;
200        }
201
202        id
203    }
204}