Skip to main content

kore/
comptime.rs

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    // Check if this IS a comptime expression
59    if let Expr::Comptime(inner, span) = expr {
60        // Evaluate inner expression
61        let val = eval_expr(env, inner)?;
62        
63        // Replace current expr with result value (Literal)
64        *expr = value_to_expr(val, *span);
65        return Ok(());
66    }
67    
68    // Otherwise recurse
69    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), // Unit is empty block?
113        _ => Expr::String(format!("<unrepresentable comptime value: {}>", val), span),
114    }
115}
116