1use crate::ast::*;
2use crate::runtime::{Env, eval_expr, Value};
3use crate::error::KoreResult;
4use crate::span::Span;
5
6pub fn eval_program(program: &mut Program) -> KoreResult<()> {
7 let mut env = Env::new();
8
9 for item in &mut program.items {
10 eval_item(&mut env, item)?;
11 }
12
13 Ok(())
14}
15
16fn eval_item(env: &mut Env, item: &mut Item) -> KoreResult<()> {
17 match item {
18 Item::Function(f) => eval_block(env, &mut f.body)?,
19 Item::Comptime(block) => {
20 crate::runtime::eval_block(env, &block.body)?;
21 }
22 Item::Component(c) => {
23 eval_jsx(env, &mut c.body)?;
24 for method in &mut c.methods {
25 eval_block(env, &mut method.body)?;
26 }
27 }
28 Item::Const(c) => {
29 eval_expr_in_place(env, &mut c.value)?;
30 }
31 _ => {}
32 }
33 Ok(())
34}
35
36fn eval_block(env: &mut Env, block: &mut Block) -> KoreResult<()> {
37 for stmt in &mut block.stmts {
38 eval_stmt(env, stmt)?;
39 }
40 Ok(())
41}
42
43fn eval_stmt(env: &mut Env, stmt: &mut Stmt) -> KoreResult<()> {
44 match stmt {
45 Stmt::Let { value: Some(e), .. } => eval_expr_in_place(env, e)?,
46 Stmt::Expr(e) => eval_expr_in_place(env, e)?,
47 Stmt::Return(Some(e), _) => eval_expr_in_place(env, e)?,
48 Stmt::For { iter, body, .. } => {
49 eval_expr_in_place(env, iter)?;
50 eval_block(env, body)?;
51 }
52 _ => {}
53 }
54 Ok(())
55}
56
57fn eval_expr_in_place(env: &mut Env, expr: &mut Expr) -> KoreResult<()> {
58 if let Expr::Comptime(inner, span) = expr {
60 let val = eval_expr(env, inner)?;
62
63 *expr = value_to_expr(val, *span);
65 return Ok(());
66 }
67
68 match expr {
70 Expr::Binary { left, right, .. } => {
71 eval_expr_in_place(env, left)?;
72 eval_expr_in_place(env, right)?;
73 }
74 Expr::Call { args, .. } => {
75 for arg in args {
76 eval_expr_in_place(env, &mut arg.value)?;
77 }
78 }
79 Expr::Assign { value, .. } => eval_expr_in_place(env, value)?,
80 Expr::Paren(e, _) => eval_expr_in_place(env, e)?,
81 Expr::Block(b, _) => eval_block(env, b)?,
82 Expr::JSX(node, _) => eval_jsx(env, node)?,
83 _ => {}
84 }
85 Ok(())
86}
87
88fn eval_jsx(env: &mut Env, node: &mut JSXNode) -> KoreResult<()> {
89 match node {
90 JSXNode::Element { attributes, children, .. } => {
91 for attr in attributes {
92 if let JSXAttrValue::Expr(e) = &mut attr.value {
93 eval_expr_in_place(env, e)?;
94 }
95 }
96 for child in children {
97 eval_jsx(env, child)?;
98 }
99 }
100 JSXNode::Expression(e) => eval_expr_in_place(env, e)?,
101 _ => {}
102 }
103 Ok(())
104}
105
106fn value_to_expr(val: Value, span: Span) -> Expr {
107 match val {
108 Value::Int(n) => Expr::Int(n, span),
109 Value::Float(n) => Expr::Float(n, span),
110 Value::Bool(b) => Expr::Bool(b, span),
111 Value::String(s) => Expr::String(s, span),
112 Value::Unit => Expr::Block(Block { stmts: vec![], span }, span), _ => Expr::String(format!("<unrepresentable comptime value: {}>", val), span),
114 }
115}
116