diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index b890df02db1dd0ff315ba1c81227df458faf256e..4d7ce4cb10b86364fe7ba922d5aee1125c9df65b 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -62,6 +62,18 @@
                 "kind": "build",
                 "isDefault": true
             }
+        },
+        {
+            "type": "shell",
+            "label": "cargo run --example crust",
+            "command": "cargo run --example crust",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
         }
     ]
 }
\ No newline at end of file
diff --git a/examples/crust.rs b/examples/crust.rs
index b9e80779cda32fc9a80aacfaee97cc5b714d2d13..7f92b9a98aa0b86e5d9fcf5cbd0eafe3b7526cbe 100644
--- a/examples/crust.rs
+++ b/examples/crust.rs
@@ -1,7 +1,8 @@
 use crust::{
-    ast::{Expr, Func, Sig, Span},
+    ast::{Expr, Func, Op, Span, SpanExpr},
     parse::parse_expr,
 };
+
 use inkwell::{
     builder::Builder,
     context::Context,
@@ -9,7 +10,7 @@ use inkwell::{
     module::Module,
     passes::PassManager,
     types::BasicTypeEnum,
-    values::{BasicValueEnum, FloatValue, FunctionValue, PointerValue},
+    values::{BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue},
     FloatPredicate, OptimizationLevel,
 };
 use std::collections::HashMap;
@@ -18,7 +19,42 @@ use std::error::Error;
 
 type ExprFunc = unsafe extern "C" fn() -> i32;
 
+fn compile_expr(
+    expr: &SpanExpr,
+    context: &Context,
+    module: &Module,
+    builder: &Builder,
+) -> IntValue {
+    match expr.1.clone() {
+        Expr::Num(i) => context.i32_type().const_int(i as u64, false),
+
+        Expr::BinOp(op, l, r) => {
+            let lv = compile_expr(&l, context, module, builder);
+            let rv = compile_expr(&r, context, module, builder);
+            match op {
+                Op::Add => builder.build_int_add(lv, rv, "sum")
+                ,
+                //         Op::Sub => lv - rv,
+                //         Op::Mul => lv * rv,
+                //         Op::Div => lv / rv,
+                //         Op::Pow => lv.pow(rv as u32),
+                _ => unimplemented!(),
+            }
+        }
+        // Expr::UnaryOp(op, e) => {
+        //     let e = eval_expr(&e);
+        //     match op {
+        //         Op::Add => e,
+        //         Op::Sub => -e,
+        //         _ => unimplemented!(),
+        //     }
+        // }
+        _ => unimplemented!(),
+    }
+}
+
 fn jit_compile_sum(
+    expr: &SpanExpr,
     context: &Context,
     module: &Module,
     builder: &Builder,
@@ -32,14 +68,15 @@ fn jit_compile_sum(
 
     builder.position_at_end(&basic_block);
 
-    let x = context.i32_type().const_int(1, false);
-    let y = context.i32_type().const_int(2, false);
-    let z = context.i32_type().const_int(3, false);
+    // let x = context.i32_type().const_int(1, false);
+    // let y = context.i32_type().const_int(42, false);
+    // let z = context.i32_type().const_int(3, false);
 
-    let sum = builder.build_int_add(x, y, "sum");
-    let sum = builder.build_int_add(sum, z, "sum");
-
-    builder.build_return(Some(&sum));
+    // let sum = builder.build_int_add(x, y, "sum");
+    // let sum = builder.build_int_add(sum, z, "sum");
+    // builder.build_return(Some(&sum));
+    let res = compile_expr(expr, context, module, builder);
+    builder.build_return(Some(&res));
 
     unsafe { execution_engine.get_function("expr").ok() }
 }
@@ -48,27 +85,55 @@ fn main() -> Result<(), Box<dyn Error>> {
     let context = Context::create();
     let module = context.create_module("expr");
     let builder = context.create_builder();
-    let execution_engine =
-        module.create_jit_execution_engine(OptimizationLevel::None)?;
+    let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None)?;
 
-    let p = parse_expr(Span::new(
+    match parse_expr(Span::new(
         "
-        1 + 2 + 3
+        2 + 3
         ",
-    ));
-    println!("{:?}", &p);
-
-    let fun_expr =
-        jit_compile_sum(&context, &module, &builder, &execution_engine)
-            .ok_or("Unable to JIT compile `expr`")?;
-
-    unsafe {
-        println!("{}", fun_expr.call());
+    )) {
+        Ok((_, e)) => {
+            println!("{:?}", &e);
+            let fun_expr = jit_compile_sum(&e, &context, &module, &builder, &execution_engine)
+                .ok_or("Unable to JIT compile `expr`")?;
+
+            unsafe {
+                println!("{}", fun_expr.call());
+            }
+        }
+        _ => panic!(),
     }
 
     Ok(())
 }
 
+pub fn eval_expr(e: &SpanExpr) -> i32 {
+    match e.1.clone() {
+        Expr::Num(i) => i,
+        Expr::BinOp(op, l, r) => {
+            let lv = eval_expr(&l);
+            let rv = eval_expr(&r);
+            match op {
+                Op::Add => lv + rv,
+                Op::Sub => lv - rv,
+                Op::Mul => lv * rv,
+                Op::Div => lv / rv,
+                Op::Pow => lv.pow(rv as u32),
+                _ => unimplemented!(),
+            }
+        }
+        Expr::UnaryOp(op, e) => {
+            let e = eval_expr(&e);
+            match op {
+                Op::Add => e,
+                Op::Sub => -e,
+                _ => unimplemented!(),
+            }
+        }
+        _ => unimplemented!(),
+    }
+}
+
 // fn main() {
 //     let p = parse_prog(Span::new(
 //         "