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