1use super::meta_types_builder::expand_builder_expr;
2use super::quote_match::{kind_name, match_quote_pattern_expr, match_quote_pattern_type};
3use super::runtime_eval::eval_meta_expr;
4use super::*;
5
6pub(super) fn expand_builder_call_arg(
7 program: &Program,
8 arg: &CallArg,
9 env: &mut BTreeMap<String, MetaValue>,
10 function_table: &BTreeMap<String, &MetaFunctionDecl>,
11 runtime_scope: &RuntimeScope,
12 builder_env_cursor: Option<&mut BuilderEnvCursor>,
13) -> Result<CallArg, MetaEvalError> {
14 match arg {
15 CallArg::Expr(expr) => Ok(CallArg::Expr(expand_builder_expr(
16 program,
17 expr,
18 env,
19 function_table,
20 runtime_scope,
21 builder_env_cursor,
22 )?)),
23 CallArg::Spread(expr) => Ok(CallArg::Spread(expand_builder_expr(
24 program,
25 expr,
26 env,
27 function_table,
28 runtime_scope,
29 builder_env_cursor,
30 )?)),
31 CallArg::Type(ty) => Ok(CallArg::Type(ty.clone())),
32 }
33}
34
35pub(super) fn expand_quoted_expr(
36 program: &Program,
37 expr: &Expr,
38 env: &mut BTreeMap<String, MetaValue>,
39 function_table: &BTreeMap<String, &MetaFunctionDecl>,
40 runtime_scope: &RuntimeScope,
41 mut builder_env_cursor: Option<&mut BuilderEnvCursor>,
42) -> Result<Expr, MetaEvalError> {
43 match expr {
44 Expr::Ident { name, span } => Ok(Expr::Ident {
45 name: name.clone(),
46 span: *span,
47 }),
48 Expr::Int(value) => Ok(Expr::Int(*value)),
49 Expr::Number(value) => Ok(Expr::Number(value.clone())),
50 Expr::String(value) => Ok(Expr::String(value.clone())),
51 Expr::Bool(value) => Ok(Expr::Bool(*value)),
52 Expr::Array { items, span } => {
53 let mut expanded = Vec::with_capacity(items.len());
54 for item in items {
55 expanded.push(expand_quoted_expr(
56 program,
57 item,
58 env,
59 function_table,
60 runtime_scope,
61 builder_env_cursor.as_deref_mut(),
62 )?);
63 }
64 Ok(Expr::Array {
65 items: expanded,
66 span: *span,
67 })
68 }
69 Expr::Tuple { items, span } => {
70 let mut expanded = Vec::with_capacity(items.len());
71 for item in items {
72 expanded.push(expand_quoted_expr(
73 program,
74 item,
75 env,
76 function_table,
77 runtime_scope,
78 builder_env_cursor.as_deref_mut(),
79 )?);
80 }
81 Ok(Expr::Tuple {
82 items: expanded,
83 span: *span,
84 })
85 }
86 Expr::StructLit { name, fields, span } => {
87 let mut expanded_fields = Vec::with_capacity(fields.len());
88 for field in fields {
89 expanded_fields.push(crate::syntax::ast::NamedExprField {
90 name: field.name.clone(),
91 value: expand_quoted_expr(
92 program,
93 &field.value,
94 env,
95 function_table,
96 runtime_scope,
97 builder_env_cursor.as_deref_mut(),
98 )?,
99 });
100 }
101 Ok(Expr::StructLit {
102 name: name.clone(),
103 fields: expanded_fields,
104 span: *span,
105 })
106 }
107 Expr::Call { callee, args, span } => {
108 let callee = Box::new(expand_quoted_expr(
109 program,
110 callee,
111 env,
112 function_table,
113 runtime_scope,
114 builder_env_cursor.as_deref_mut(),
115 )?);
116 let mut expanded_args = Vec::with_capacity(args.len());
117 for arg in args {
118 expanded_args.push(expand_quoted_call_arg(
119 program,
120 arg,
121 env,
122 function_table,
123 runtime_scope,
124 builder_env_cursor.as_deref_mut(),
125 )?);
126 }
127 Ok(Expr::Call {
128 callee,
129 args: expanded_args,
130 span: *span,
131 })
132 }
133 Expr::IntrinsicCall { name, args, span } => {
134 let mut expanded_args = Vec::with_capacity(args.len());
135 for arg in args {
136 expanded_args.push(expand_quoted_call_arg(
137 program,
138 arg,
139 env,
140 function_table,
141 runtime_scope,
142 builder_env_cursor.as_deref_mut(),
143 )?);
144 }
145 Ok(Expr::IntrinsicCall {
146 name: name.clone(),
147 args: expanded_args,
148 span: *span,
149 })
150 }
151 Expr::Field { base, field } => {
152 let base = Box::new(expand_quoted_expr(
153 program,
154 base,
155 env,
156 function_table,
157 runtime_scope,
158 builder_env_cursor.as_deref_mut(),
159 )?);
160 Ok(Expr::Field {
161 base,
162 field: field.clone(),
163 })
164 }
165 Expr::Index { base, index } => {
166 let base = Box::new(expand_quoted_expr(
167 program,
168 base,
169 env,
170 function_table,
171 runtime_scope,
172 builder_env_cursor.as_deref_mut(),
173 )?);
174 let index = Box::new(expand_quoted_expr(
175 program,
176 index,
177 env,
178 function_table,
179 runtime_scope,
180 builder_env_cursor.as_deref_mut(),
181 )?);
182 Ok(Expr::Index { base, index })
183 }
184 Expr::SliceRange { base, start, end } => {
185 let base = Box::new(expand_quoted_expr(
186 program,
187 base,
188 env,
189 function_table,
190 runtime_scope,
191 builder_env_cursor.as_deref_mut(),
192 )?);
193 let start = start
194 .as_ref()
195 .map(|expr| {
196 expand_quoted_expr(
197 program,
198 expr,
199 env,
200 function_table,
201 runtime_scope,
202 builder_env_cursor.as_deref_mut(),
203 )
204 })
205 .transpose()?
206 .map(Box::new);
207 let end = end
208 .as_ref()
209 .map(|expr| {
210 expand_quoted_expr(
211 program,
212 expr,
213 env,
214 function_table,
215 runtime_scope,
216 builder_env_cursor.as_deref_mut(),
217 )
218 })
219 .transpose()?
220 .map(Box::new);
221 Ok(Expr::SliceRange { base, start, end })
222 }
223 Expr::Prefix { op, value } => {
224 let value = Box::new(expand_quoted_expr(
225 program,
226 value,
227 env,
228 function_table,
229 runtime_scope,
230 builder_env_cursor.as_deref_mut(),
231 )?);
232 Ok(Expr::Prefix { op: *op, value })
233 }
234 Expr::Binary { op, lhs, rhs } => {
235 let lhs = Box::new(expand_quoted_expr(
236 program,
237 lhs,
238 env,
239 function_table,
240 runtime_scope,
241 builder_env_cursor.as_deref_mut(),
242 )?);
243 let rhs = Box::new(expand_quoted_expr(
244 program,
245 rhs,
246 env,
247 function_table,
248 runtime_scope,
249 builder_env_cursor.as_deref_mut(),
250 )?);
251 Ok(Expr::Binary { op: *op, lhs, rhs })
252 }
253 Expr::Relational { op, lhs, rhs } => {
254 let lhs = Box::new(expand_quoted_expr(
255 program,
256 lhs,
257 env,
258 function_table,
259 runtime_scope,
260 builder_env_cursor.as_deref_mut(),
261 )?);
262 let rhs = Box::new(expand_quoted_expr(
263 program,
264 rhs,
265 env,
266 function_table,
267 runtime_scope,
268 builder_env_cursor.as_deref_mut(),
269 )?);
270 Ok(Expr::Relational { op: *op, lhs, rhs })
271 }
272 Expr::Block(block) => Ok(Expr::Block(expand_quoted_block(
273 program,
274 block,
275 env,
276 function_table,
277 runtime_scope,
278 builder_env_cursor.as_deref_mut(),
279 )?)),
280 Expr::Splice(meta_expr) => {
281 let splice_value = eval_meta_expr(
282 program,
283 meta_expr,
284 env,
285 function_table,
286 runtime_scope,
287 builder_env_cursor,
288 )?;
289 splice_value_to_expr(splice_value)
290 }
291 }
292}
293
294pub(super) fn splice_value_to_expr(value: MetaValue) -> Result<Expr, MetaEvalError> {
295 match value {
296 MetaValue::Expr { expr, .. } => Ok(expr),
297 MetaValue::Int(value) => Ok(Expr::Int(value)),
298 MetaValue::Bool(value) => Ok(Expr::Bool(value)),
299 MetaValue::String(value) => Ok(Expr::String(value)),
300 other => Err(MetaEvalError::SpliceExpectedCode {
301 found: kind_name(&other),
302 }),
303 }
304}
305
306pub(super) fn runtime_splice_value_to_expr(value: MetaValue) -> Result<Expr, MetaEvalError> {
307 match value {
308 MetaValue::Expr { expr, .. } => Ok(expr),
309 other => Err(MetaEvalError::SpliceExpectedCode {
310 found: kind_name(&other),
311 }),
312 }
313}
314
315pub(super) fn builder_value_to_expr(value: MetaValue) -> Result<Expr, MetaEvalError> {
316 match value {
317 MetaValue::Expr { expr, .. } => Ok(expr),
318 MetaValue::Int(value) => Ok(Expr::Int(value)),
319 MetaValue::Bool(value) => Ok(Expr::Bool(value)),
320 MetaValue::String(value) => Ok(Expr::String(value)),
321 other => Err(MetaEvalError::SpliceExpectedCode {
322 found: kind_name(&other),
323 }),
324 }
325}
326
327pub(super) fn promote_splice_value(value: MetaValue) -> Result<MetaValue, MetaEvalError> {
328 match value {
329 MetaValue::Int(value) => Ok(MetaValue::Expr {
330 expr: Expr::Int(value),
331 ty: TypeExpr::Named("i64".to_owned()),
332 }),
333 MetaValue::Bool(value) => Ok(MetaValue::Expr {
334 expr: Expr::Bool(value),
335 ty: TypeExpr::Named("Bool".to_owned()),
336 }),
337 MetaValue::String(value) => Ok(MetaValue::Expr {
338 expr: Expr::String(value),
339 ty: TypeExpr::Named("String".to_owned()),
340 }),
341 MetaValue::Expr { .. } | MetaValue::Type(_) | MetaValue::Code(_) => Ok(value),
342 }
343}
344
345pub(super) fn coerce_value_to_code_for_match(value: MetaValue) -> Option<CodeValue> {
346 match value {
347 MetaValue::Expr { expr, .. } => Some(CodeValue::Expr(expr)),
348 MetaValue::Type(ty) => Some(CodeValue::Type(ty)),
349 _ => None,
350 }
351}
352
353pub(super) fn expand_quoted_block(
354 program: &Program,
355 block: &Block,
356 env: &mut BTreeMap<String, MetaValue>,
357 function_table: &BTreeMap<String, &MetaFunctionDecl>,
358 runtime_scope: &RuntimeScope,
359 mut builder_env_cursor: Option<&mut BuilderEnvCursor>,
360) -> Result<Block, MetaEvalError> {
361 let mut statements = Vec::with_capacity(block.statements.len());
362 for stmt in &block.statements {
363 statements.push(expand_quoted_stmt(
364 program,
365 stmt,
366 env,
367 function_table,
368 runtime_scope,
369 builder_env_cursor.as_deref_mut(),
370 )?);
371 }
372 Ok(Block { statements })
373}
374
375pub(super) fn expand_quoted_stmt(
376 program: &Program,
377 stmt: &Stmt,
378 env: &mut BTreeMap<String, MetaValue>,
379 function_table: &BTreeMap<String, &MetaFunctionDecl>,
380 runtime_scope: &RuntimeScope,
381 mut builder_env_cursor: Option<&mut BuilderEnvCursor>,
382) -> Result<Stmt, MetaEvalError> {
383 match stmt {
384 Stmt::Let {
385 name,
386 name_span,
387 ownership,
388 mode,
389 value,
390 } => Ok(Stmt::Let {
391 name: name.clone(),
392 name_span: *name_span,
393 ownership: *ownership,
394 mode: *mode,
395 value: expand_quoted_expr(
396 program,
397 value,
398 env,
399 function_table,
400 runtime_scope,
401 builder_env_cursor.as_deref_mut(),
402 )?,
403 }),
404 Stmt::Assign {
405 target,
406 mode,
407 value,
408 } => Ok(Stmt::Assign {
409 target: target.clone(),
410 mode: *mode,
411 value: expand_quoted_expr(
412 program,
413 value,
414 env,
415 function_table,
416 runtime_scope,
417 builder_env_cursor.as_deref_mut(),
418 )?,
419 }),
420 Stmt::If {
421 condition,
422 then_block,
423 else_block,
424 } => Ok(Stmt::If {
425 condition: expand_quoted_expr(
426 program,
427 condition,
428 env,
429 function_table,
430 runtime_scope,
431 builder_env_cursor.as_deref_mut(),
432 )?,
433 then_block: expand_quoted_block(
434 program,
435 then_block,
436 env,
437 function_table,
438 runtime_scope,
439 builder_env_cursor.as_deref_mut(),
440 )?,
441 else_block: else_block
442 .as_ref()
443 .map(|block| {
444 expand_quoted_block(
445 program,
446 block,
447 env,
448 function_table,
449 runtime_scope,
450 builder_env_cursor.as_deref_mut(),
451 )
452 })
453 .transpose()?,
454 }),
455 Stmt::For {
456 binding,
457 iterable,
458 body,
459 } => Ok(Stmt::For {
460 binding: binding.clone(),
461 iterable: expand_quoted_expr(
462 program,
463 iterable,
464 env,
465 function_table,
466 runtime_scope,
467 builder_env_cursor.as_deref_mut(),
468 )?,
469 body: expand_quoted_block(
470 program,
471 body,
472 env,
473 function_table,
474 runtime_scope,
475 builder_env_cursor.as_deref_mut(),
476 )?,
477 }),
478 Stmt::While { condition, body } => Ok(Stmt::While {
479 condition: expand_quoted_expr(
480 program,
481 condition,
482 env,
483 function_table,
484 runtime_scope,
485 builder_env_cursor.as_deref_mut(),
486 )?,
487 body: expand_quoted_block(
488 program,
489 body,
490 env,
491 function_table,
492 runtime_scope,
493 builder_env_cursor.as_deref_mut(),
494 )?,
495 }),
496 Stmt::Match { value, arms } => Ok(Stmt::Match {
497 value: expand_quoted_expr(
498 program,
499 value,
500 env,
501 function_table,
502 runtime_scope,
503 builder_env_cursor.as_deref_mut(),
504 )?,
505 arms: arms
506 .iter()
507 .map(|arm| {
508 Ok(ruka_frontend::MatchArm {
509 pattern: arm.pattern.clone(),
510 body: expand_quoted_block(
511 program,
512 &arm.body,
513 env,
514 function_table,
515 runtime_scope,
516 builder_env_cursor.as_deref_mut(),
517 )?,
518 })
519 })
520 .collect::<Result<Vec<_>, MetaEvalError>>()?,
521 }),
522 Stmt::Meta { body } => Ok(Stmt::Meta { body: body.clone() }),
523 Stmt::Expr { expr, has_semi } => Ok(Stmt::Expr {
524 expr: expand_quoted_expr(
525 program,
526 expr,
527 env,
528 function_table,
529 runtime_scope,
530 builder_env_cursor,
531 )?,
532 has_semi: *has_semi,
533 }),
534 }
535}
536
537pub(super) fn match_quote_code(
538 pattern: &QuotedCode,
539 target: &CodeValue,
540 captures: &mut BTreeMap<String, MetaValue>,
541) -> bool {
542 match (pattern, target) {
543 (QuotedCode::Expr(pattern_expr), CodeValue::Expr(target_expr)) => {
544 match_quote_pattern_expr(pattern_expr, target_expr, captures)
545 }
546 (QuotedCode::Type(pattern_ty), CodeValue::Type(target_ty)) => {
547 match_quote_pattern_type(pattern_ty, target_ty)
548 }
549 _ => false,
550 }
551}
552
553pub(super) fn expand_quoted_call_arg(
554 program: &Program,
555 arg: &CallArg,
556 env: &mut BTreeMap<String, MetaValue>,
557 function_table: &BTreeMap<String, &MetaFunctionDecl>,
558 runtime_scope: &RuntimeScope,
559 builder_env_cursor: Option<&mut BuilderEnvCursor>,
560) -> Result<CallArg, MetaEvalError> {
561 match arg {
562 CallArg::Expr(expr) => Ok(CallArg::Expr(expand_quoted_expr(
563 program,
564 expr,
565 env,
566 function_table,
567 runtime_scope,
568 builder_env_cursor,
569 )?)),
570 CallArg::Spread(expr) => Ok(CallArg::Spread(expand_quoted_expr(
571 program,
572 expr,
573 env,
574 function_table,
575 runtime_scope,
576 builder_env_cursor,
577 )?)),
578 CallArg::Type(ty) => Ok(CallArg::Type(ty.clone())),
579 }
580}