diff --git a/examples/crust.rs b/examples/crust.rs
index 917e7991a8ccf47f3b6e075776be46ae308b8b78..b86dcf20e6727e4a39116b98715f6c09c0ad8324 100644
--- a/examples/crust.rs
+++ b/examples/crust.rs
@@ -1,5 +1,5 @@
 use crust::{
-    ast::{Expr, Func, Op, Span, SpanExpr},
+    ast::{Block, Cmd, Expr, Func, Op, Span, SpanExpr},
     parse::{parse_block, parse_expr},
 };
 
@@ -11,7 +11,8 @@ use inkwell::{
     passes::PassManager,
     types::BasicTypeEnum,
     values::{
-        BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue,
+        BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue,
+        PointerValue,
     },
     FloatPredicate, OptimizationLevel,
 };
@@ -29,16 +30,15 @@ fn main() -> Result<(), Box<dyn Error>> {
     let execution_engine =
         module.create_jit_execution_engine(OptimizationLevel::None)?;
 
-    // match parse_block(Span::new(
-    //     "
-    //     {
-    //         return = 2 + 3;
-    //     }
-    //     ",
-    // ))
-    match parse_expr(Span::new("2 + 3")) {
-        Ok((_, expr)) => {
-            println!("{:?}", &expr);
+    match parse_block(Span::new(
+        "
+        {
+            return  2 + 3
+        }
+        ",
+    )) {
+        Ok((_, prog)) => {
+            println!("{:?}", &prog);
             let u32_type = context.i32_type();
             let fn_type = u32_type.fn_type(&[], false);
             let function = module.add_function("expr", fn_type, None);
@@ -49,10 +49,11 @@ fn main() -> Result<(), Box<dyn Error>> {
                 context: &context,
                 builder: &builder,
                 module: &module,
+                fn_value_opt: Some(function),
                 //&fpm,
             };
-            let res = compiler.compile_expr(&expr);
-            builder.build_return(Some(&res));
+            let res = compiler.compile_block(prog);
+            // builder.build_return(Some(&res));
             let fun_expr: JitFunction<ExprFunc> =
                 unsafe { execution_engine.get_function("expr").ok().unwrap() };
 
@@ -75,10 +76,22 @@ pub struct Compiler<'a> {
     // pub function: &'a Func<'a>,
 
     // variables: HashMap<String, PointerValue>,
-    // fn_value_opt: Option<FunctionValue>,
+    fn_value_opt: Option<FunctionValue>,
 }
 
 impl<'a> Compiler<'a> {
+    /// Gets a defined function given its name.
+    #[inline]
+    fn get_function(&self, name: &str) -> Option<FunctionValue> {
+        self.module.get_function(name)
+    }
+
+    /// Returns the `FunctionValue` representing the function being compiled.
+    #[inline]
+    fn fn_value(&self) -> FunctionValue {
+        self.fn_value_opt.unwrap()
+    }
+
     fn compile_expr(&self, expr: &SpanExpr) -> IntValue {
         match expr.1.clone() {
             Expr::Num(i) => self.context.i32_type().const_int(i as u64, false),
@@ -87,26 +100,87 @@ impl<'a> Compiler<'a> {
                 let lv = self.compile_expr(&l);
                 let rv = self.compile_expr(&r);
                 match op {
-                Op::Add => self.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!(),
-            }
+                    Op::Add => self.builder.build_int_add(lv, rv, "sum"),
+                    _ => unimplemented!(),
+                }
             }
-            // Expr::UnaryOp(op, e) => {
-            //     let e = eval_expr(&e);
-            //     match op {
-            //         Op::Add => e,
-            //         Op::Sub => -e,
-            //         _ => unimplemented!(),
+            _ => unimplemented!(),
+        }
+    }
+
+    /// Creates a new stack allocation instruction in the entry block of the function.
+    fn create_entry_block_alloca(&self, name: &str) -> PointerValue {
+        let builder = self.context.create_builder();
+
+        let entry = self.fn_value().get_first_basic_block().unwrap();
+
+        match entry.get_first_instruction() {
+            Some(first_instr) => builder.position_before(&first_instr),
+            None => builder.position_at_end(&entry),
+        }
+
+        builder.build_alloca(self.context.f64_type(), name)
+    }
+
+    fn compile_cmd(&self, cmd: &Cmd) -> (InstructionValue, bool) {
+        println!("{:?}", cmd);
+        match cmd {
+            //     Cmd::Assign(lexp, rexp) => {
+            //         let rval = eval_expr(rexp, mem, venv, fenv);
+            //         println!("val {:?}", rval);
+            //         let addr = eval_lvalue(lexp, mem, venv, fenv);
+            //         // println!("lval {:?}", lval);
+            //         // let addr = venv.get(&lval).unwrap();
+
+            //         mem.Menv.insert(addr, rval);
+            //         None
+            //     }
+            //     Cmd::If(exp, then_block, opt_else) => {
+            //         if get_bool(eval_expr(exp, mem, venv, fenv)) {
+            //             eval_body(then_block.to_vec(), mem, venv, fenv)
+            //         } else {
+            //             if let Some(else_block) = opt_else {
+            //                 eval_body(else_block.to_vec(), mem, venv, fenv)
+            //             } else {
+            //                 None
+            //             }
+            //         }
             //     }
+            // Cmd::Let(_, id, _, exp) => {
+            //     let val = eval_expr(exp, stack, fenv);
+            //     println!("val {:?}", val);
+
+            //     // let addr = mem.alloc(); // get new allocation slot
+            //     // mem.Menv.insert(addr, val); // write the new value
+            //     // venv.insert(id.to_owned(), addr);
+            //     // dump("after Let", mem, venv);
+            //     None
             // }
+            Cmd::Return(exp) => {
+                let expr = self.compile_expr(exp);
+                (self.builder.build_return(Some(&expr)), true)
+            }
+            //     Cmd::While(exp, body) => {
+            //         while get_bool(eval_expr(exp, mem, venv, fenv)) {
+            //             if let Some(retv) = eval_body(body.to_vec(), mem, venv, fenv) {
+            //                 return Some(retv);
+            //             }
+            //         }
+            //         None
+            //     }
             _ => unimplemented!(),
         }
     }
+
+    pub fn compile_block(&self, cmds: Vec<Cmd>) -> InstructionValue {
+        for c in &cmds {
+            let (cmd, ret) = self.compile_cmd(c);
+            if ret {
+                return cmd;
+            }
+        }
+        panic!();
+    }
 }
 
 // fn main() {