diff --git a/.clang-format b/.clang-format
index b7c58b7e74c2d42d37c66ce42fbfd3afb568a865..db13e1da7a7b72b4e811bcb0c3d11799ce3d5684 100644
--- a/.clang-format
+++ b/.clang-format
@@ -15,8 +15,8 @@ IncludeCategories:
     Priority: 2
   - Regex: '.*'
     Priority: 1
-IndentCaseLabels: false
-AllowShortCaseLabelsOnASingleLine: true
+IndentCaseLabels: true
+AllowShortCaseLabelsOnASingleLine: false
 IndentWidth: 4
 KeepEmptyLinesAtTheStartOfBlocks: false
 PenaltyReturnTypeOnItsOwnLine: 200
diff --git a/Reports/3-ir-gen/report.md b/Reports/3-ir-gen/report.md
index b557e0913894c6abcf331b0251e07775fabd7d6b..e68bd7df033e5164485185d1f1e555a296b19c60 100644
--- a/Reports/3-ir-gen/report.md
+++ b/Reports/3-ir-gen/report.md
@@ -1,10 +1,67 @@
 # lab3 瀹為獙鎶ュ憡
-瀛﹀彿 濮撳悕
+
+PB20111654 鏉庢檽濂�
 
 ## 瀹為獙瑕佹眰
+
 ## 瀹為獙闅剧偣
 
-瀹為獙涓亣鍒板摢浜涙寫鎴�
+1. syntax_tree鍜宎st鐨勫尯鍒€佷负浠€闇€瑕乤st?
+   
+   闃呰AST鐨勬瀯閫犲嚱鏁帮紝`AST(syntax_tree *)`
+   
+   瀹為檯涓婅繖閮ㄥ垎鍦ㄤ笂涓疄楠屽氨鏈夌湅calc_ast鐨勪唬鐮侊紝浣嗘槸鍗拌薄涓嶆繁鍒汇€傘€�
+
+2. 璁块棶鑰呮ā寮忕┒绔熸湁浠€涔堢敤锛�
+   
+   姣斿杩欐牱涓€绯诲垪鍑芥暟璋冪敤锛�
+   
+   ```cpp
+   ASTPrinter::visit(ASTProgram &)
+   {
+       //...
+       for (auto decl : node.declarations) {
+           decl->accept(*this);
+       }
+       //...
+   }
+   ASTVarDeclaration::accept(ASTVisitor &)
+   {
+       //...
+       auto var_decl = dynamic_cast<ASTVarDeclaration *>(this);
+       if (var_decl) {
+           var_decl->accept(visitor);
+           return;        
+       }
+       //...     
+   }
+   void ASTVarDeclaration::accept(ASTVisitor &visitor) 
+   { visitor.visit(*this); }
+   ```
+   
+   鍋囪灏辨槸vardeclaration锛岀洿鎺ヨ皟鐢�(鍦╜ASTPrinter::visit`鍐�)`visit(dynamic_cast<ASTVarDeclaration *>(this))`涓嶆槸涓€鏍风殑鍚楋紵
+   
+   鍙傝€僛鏀荤暐](https://www.jianshu.com/p/1f1049d0a0f4)锛屾帴鍙椾竴鐐癸紝鎰熻杩樻槸涓嶅お鏄庣櫧锛屼絾鏄笉褰卞搷鍐欏疄楠屻€傚洜涓虹粡杩囧弽澶嶇殑闃呰锛屾垜宸茬粡鐭ラ亾浜嗘垜浠瀹炵幇鐨刞CminusfBuilder`鏄竴涓闂€呯被锛�
+
+3. 鏃犱粠涓嬫墜锛�
+   
+   浠庡彉閲忓紑濮嬶紒
+   
+   鑷簳鍚戜笂鍋氳嚜鐒跺浜嗭紝涓嶇劧鍍忓湪鎽搁粦鎷ч瓟鏂广€�
+
+4. 濡備綍鑾峰緱杩斿洖鍊硷紵
+   
+   鍔犲叆涓€涓叏灞€鍙橀噺淇濆瓨璇彞鐨勮繑鍥炲€笺€�
+
+5. 鏁扮粍or鎸囬拡锛熻繖涓叧涔庡湴鍧€鐨勮绠椼€佺被鍨嬭浆鎹⑩€︹€�
+   
+   绛旀鍦ㄤ簬锛氫腑闂翠唬鐮佹槸濡備綍鐢熸垚鐨勶紵
+   
+   鎸夋垜鐨勭悊瑙o紝
+   
+    - 鍦ㄧ炕璇戜负涓棿浠g爜鏃讹紝鍑芥暟鍐呴儴澹版槑鐨勫彧鑳芥槸鏁扮粍锛岃绠楀湴鍧€鏃朵細寰楀埌鎸囬拡銆�
+   
+    - 鍦ㄤ紶閫掔粰鍑芥暟鏃讹紝鍙兘浼犻€掓暟缁勶紝浣嗘槸浼犻€掍负鎸囬拡銆�
 
 ## 瀹為獙璁捐
 
diff --git a/include/ast.hpp b/include/ast.hpp
index 41de619bfed598623f0a29c4d2231e84ffa446fb..ae6d12d216a9691f382613189d97d497353072b1 100644
--- a/include/ast.hpp
+++ b/include/ast.hpp
@@ -2,17 +2,13 @@
 #define _SYNTAX_TREE_HPP_
 extern "C" {
 #include "syntax_tree.h"
-    extern syntax_tree *parse(const char *input);
+extern syntax_tree *parse(const char *input);
 }
-#include <vector>
 #include <memory>
 #include <string>
+#include <vector>
 
-enum CminusType {
-    TYPE_INT,
-    TYPE_FLOAT,
-    TYPE_VOID
-};
+enum CminusType { TYPE_INT, TYPE_FLOAT, TYPE_VOID };
 
 enum RelOp {
     // <=
@@ -64,23 +60,24 @@ struct ASTVar;
 struct ASTAssignExpression;
 struct ASTSimpleExpression;
 struct ASTAdditiveExpression;
-struct ASTTerm ;
+struct ASTTerm;
 struct ASTCall;
 
 class ASTVisitor;
 
 class AST {
-public:
+  public:
     AST() = delete;
     AST(syntax_tree *);
     AST(AST &&tree) {
         root = tree.root;
         tree.root = nullptr;
     };
-    ASTProgram* get_root() { return root.get(); }
-    void run_visitor(ASTVisitor& visitor);
-private:
-    ASTNode* transform_node_iter(syntax_tree_node *);
+    ASTProgram *get_root() { return root.get(); }
+    void run_visitor(ASTVisitor &visitor);
+
+  private:
+    ASTNode *transform_node_iter(syntax_tree_node *);
     std::shared_ptr<ASTProgram> root = nullptr;
 };
 
@@ -90,21 +87,20 @@ struct ASTNode {
 
 struct ASTProgram : ASTNode {
     virtual void accept(ASTVisitor &) override final;
-    std::vector<std::shared_ptr<ASTDeclaration>>
-        declarations;
+    std::vector<std::shared_ptr<ASTDeclaration>> declarations;
 };
 
-struct ASTDeclaration: ASTNode {
+struct ASTDeclaration : ASTNode {
     virtual void accept(ASTVisitor &) override;
     CminusType type;
     std::string id;
 };
 
-struct ASTFactor: ASTNode {
+struct ASTFactor : ASTNode {
     virtual void accept(ASTVisitor &) override;
 };
 
-struct ASTNum: ASTFactor {
+struct ASTNum : ASTFactor {
     virtual void accept(ASTVisitor &) override final;
     CminusType type;
     union {
@@ -113,19 +109,19 @@ struct ASTNum: ASTFactor {
     };
 };
 
-struct ASTVarDeclaration: ASTDeclaration {
+struct ASTVarDeclaration : ASTDeclaration {
     virtual void accept(ASTVisitor &) override final;
     CminusType type;
     std::shared_ptr<ASTNum> num;
 };
 
-struct ASTFunDeclaration: ASTDeclaration {
+struct ASTFunDeclaration : ASTDeclaration {
     virtual void accept(ASTVisitor &) override final;
     std::vector<std::shared_ptr<ASTParam>> params;
     std::shared_ptr<ASTCompoundStmt> compound_stmt;
 };
 
-struct ASTParam: ASTNode {
+struct ASTParam : ASTNode {
     virtual void accept(ASTVisitor &) override final;
     CminusType type;
     std::string id;
@@ -137,62 +133,62 @@ struct ASTStatement : ASTNode {
     virtual void accept(ASTVisitor &) override;
 };
 
-struct ASTCompoundStmt: ASTStatement {
-    virtual void accept(ASTVisitor&) override final;
+struct ASTCompoundStmt : ASTStatement {
+    virtual void accept(ASTVisitor &) override final;
     std::vector<std::shared_ptr<ASTVarDeclaration>> local_declarations;
     std::vector<std::shared_ptr<ASTStatement>> statement_list;
 };
 
-struct ASTExpressionStmt: ASTStatement { 
+struct ASTExpressionStmt : ASTStatement {
     virtual void accept(ASTVisitor &) override final;
-    std::shared_ptr<ASTExpression> expression; 
+    std::shared_ptr<ASTExpression> expression;
 };
 
-struct ASTSelectionStmt: ASTStatement {
+struct ASTSelectionStmt : ASTStatement {
     virtual void accept(ASTVisitor &) override final;
-    std::shared_ptr<ASTExpression> expression; 
+    std::shared_ptr<ASTExpression> expression;
     std::shared_ptr<ASTStatement> if_statement;
     // should be nullptr if no else structure exists
     std::shared_ptr<ASTStatement> else_statement;
 };
 
-struct ASTIterationStmt: ASTStatement {
+struct ASTIterationStmt : ASTStatement {
     virtual void accept(ASTVisitor &) override final;
-    std::shared_ptr<ASTExpression> expression; 
+    std::shared_ptr<ASTExpression> expression;
     std::shared_ptr<ASTStatement> statement;
 };
 
-struct ASTReturnStmt: ASTStatement {
+struct ASTReturnStmt : ASTStatement {
     virtual void accept(ASTVisitor &) override final;
     // should be nullptr if return void
-    std::shared_ptr<ASTExpression> expression; 
+    std::shared_ptr<ASTExpression> expression;
 };
 
-struct ASTExpression: ASTFactor {
+struct ASTExpression : ASTFactor {
     virtual void accept(ASTVisitor &) override;
 };
 
-struct ASTAssignExpression: ASTExpression {
+struct ASTAssignExpression : ASTExpression {
     virtual void accept(ASTVisitor &) override final;
     std::shared_ptr<ASTVar> var;
     std::shared_ptr<ASTExpression> expression;
 };
 
-struct ASTSimpleExpression: ASTExpression {
+struct ASTSimpleExpression : ASTExpression {
     virtual void accept(ASTVisitor &) override final;
     std::shared_ptr<ASTAdditiveExpression> additive_expression_l;
     std::shared_ptr<ASTAdditiveExpression> additive_expression_r;
     RelOp op;
 };
 
-struct ASTVar: ASTFactor {
+struct ASTVar : ASTFactor {
     virtual void accept(ASTVisitor &) override final;
     std::string id;
     // nullptr if var is of int type
     std::shared_ptr<ASTExpression> expression;
 };
 
-struct ASTAdditiveExpression: ASTNode {
+struct ASTAdditiveExpression : ASTNode {
     virtual void accept(ASTVisitor &) override final;
     std::shared_ptr<ASTAdditiveExpression> additive_expression;
     AddOp op;
@@ -206,14 +202,14 @@ struct ASTTerm : ASTNode {
     std::shared_ptr<ASTFactor> factor;
 };
 
-struct ASTCall: ASTFactor {
+struct ASTCall : ASTFactor {
     virtual void accept(ASTVisitor &) override final;
     std::string id;
     std::vector<std::shared_ptr<ASTExpression>> args;
 };
 
 class ASTVisitor {
-public:
+  public:
     virtual void visit(ASTProgram &) = 0;
     virtual void visit(ASTNum &) = 0;
     virtual void visit(ASTVarDeclaration &) = 0;
@@ -233,7 +229,7 @@ public:
 };
 
 class ASTPrinter : public ASTVisitor {
-public:
+  public:
     virtual void visit(ASTProgram &) override final;
     virtual void visit(ASTNum &) override final;
     virtual void visit(ASTVarDeclaration &) override final;
@@ -252,8 +248,8 @@ public:
     virtual void visit(ASTCall &) override final;
     void add_depth() { depth += 2; }
     void remove_depth() { depth -= 2; }
-private:
+
+  private:
     int depth = 0;
 };
 #endif
-
diff --git a/include/cminusf_builder.hpp b/include/cminusf_builder.hpp
index 750dc3acdc347041bfc6eaf784c47fe192bc469f..4a20f7df027f3edbc15a7c4c23d0361ceb3844b0 100644
--- a/include/cminusf_builder.hpp
+++ b/include/cminusf_builder.hpp
@@ -96,6 +96,8 @@ class CminusfBuilder : public ASTVisitor {
     virtual void visit(ASTTerm &) override final;
     virtual void visit(ASTCall &) override final;
 
+    bool type_cast(Value *&, Value *&, std::string = "computation");
+
     std::unique_ptr<IRBuilder> builder;
     Scope scope;
     std::unique_ptr<Module> module;
diff --git a/src/cminusfc/cminusf_builder.cpp b/src/cminusfc/cminusf_builder.cpp
index e4278b2e5c54753d8ea5aa06c309e9eb6020a09a..fa4990d31055a764fb962124172d44d316ca42da 100644
--- a/src/cminusfc/cminusf_builder.cpp
+++ b/src/cminusfc/cminusf_builder.cpp
@@ -5,15 +5,18 @@
 
 #include "cminusf_builder.hpp"
 
+#include "logging.hpp"
+
 #define CONST_FP(num) ConstantFP::get((float)num, module.get())
 #define CONST_INT(num) ConstantInt::get(num, module.get())
 
-
-// TODO: Global Variable Declarations 
+// TODO: Global Variable Declarations
 // You can define global variables here
 // to store state. You can expand these
 // definitions if you need to.
 
+// the latest return value
+Value *cur_value = nullptr;
 // function that is being built
 Function *cur_fun = nullptr;
 
@@ -33,6 +36,28 @@ Type *FLOATPTR_T;
  * scope.find: find and return the value bound to the name
  */
 
+void error_exit(std::string s) {
+    LOG_ERROR << s;
+    std::abort();
+}
+
+// This function makes sure that
+// 1. 2 values have same type
+// 2. type is either int or float
+// 3. return true if there is float
+bool CminusfBuilder::type_cast(Value *&lvalue, Value *&rvalue, std::string util) {
+    if (not Type::is_eq_type(lvalue->get_type(), rvalue->get_type())) {
+        if (Type::is_eq_type(lvalue->get_type(), INT32_T) and Type::is_eq_type(rvalue->get_type(), FLOAT_T))
+            lvalue = builder->create_sitofp(lvalue, FLOAT_T);
+        else if (Type::is_eq_type(rvalue->get_type(), INT32_T) and Type::is_eq_type(lvalue->get_type(), FLOAT_T))
+            rvalue = builder->create_sitofp(rvalue, FLOAT_T);
+    }
+    // now 2 value is the same type, but we only support computing between int and float
+    if (not Type::is_eq_type(lvalue->get_type(), INT32_T) or not Type::is_eq_type(lvalue->get_type(), FLOAT_T))
+        error_exit("not supported cross-type " + util);
+    return Type::is_eq_type(lvalue->get_type(), FLOAT_T);
+}
+
 void CminusfBuilder::visit(ASTProgram &node) {
     VOID_T = Type::get_void_type(module.get());
     INT1_T = Type::get_int1_type(module.get());
@@ -46,16 +71,73 @@ void CminusfBuilder::visit(ASTProgram &node) {
     }
 }
 
+// Done
 void CminusfBuilder::visit(ASTNum &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    //
+    switch (node.type) {
+        case TYPE_INT:
+            cur_value = CONST_INT(node.i_val);
+            return;
+        case TYPE_FLOAT:
+            cur_value = CONST_FP(node.f_val);
+            return;
+        default:
+            error_exit("ASTNum is not int or float");
+    }
 }
 
+// Done
 void CminusfBuilder::visit(ASTVarDeclaration &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    if (node.num) {
+        // declares an array
+        //
+        // get array size
+        node.num->accept(*this);
+        //
+        // type cast
+        if (Type::is_eq_type(cur_value->get_type(), FLOAT_T))
+            cur_value = builder->create_fptosi(cur_value, INT32_T);
+        int size = static_cast<ConstantInt *>(cur_value)->get_value();
+        if (size <= 0)
+            error_exit("array size[" + std::to_string(size) + "] <= 0");
+
+        switch (node.type) {
+            case TYPE_INT: {
+                auto I32Array_T = Type::get_array_type(INT32_T, size);
+                cur_value = builder->create_alloca(I32Array_T);
+                break;
+            }
+
+            case TYPE_FLOAT: {
+                auto FloatArray_T = Type::get_array_type(FLOAT_T, size);
+                cur_value = builder->create_alloca(FloatArray_T);
+                break;
+            }
+            default:
+                error_exit("Variable type(not array) is not int or float");
+        }
+
+    } else {
+        switch (node.type) {
+            case TYPE_INT:
+                cur_value = builder->create_alloca(INT32_T);
+                break;
+            case TYPE_FLOAT:
+                cur_value = builder->create_alloca(FLOAT_T);
+                break;
+            default:
+                error_exit("Variable type(not array) is not int or float");
+        }
+    }
+    if (not scope.push(node.id, cur_value))
+        error_exit("variable redefined: " + node.id);
 }
 
+// Done
 void CminusfBuilder::visit(ASTFunDeclaration &node) {
     FunctionType *fun_type;
     Type *ret_type;
@@ -69,32 +151,46 @@ void CminusfBuilder::visit(ASTFunDeclaration &node) {
 
     for (auto &param : node.params) {
         //!TODO: Please accomplish param_types.
-
-
-
+        //
+        // First make function BB, which needs this param type,
+        // then set_insert_point, we can call accept to gen code,
+        switch (param->type) {
+            case TYPE_INT:
+                param_types.push_back(param->isarray ? INT32PTR_T : INT32_T);
+                break;
+            case TYPE_FLOAT:
+                param_types.push_back(param->isarray ? FLOATPTR_T : FLOAT_T);
+                break;
+            case TYPE_VOID:
+                if (not param_types.empty())
+                    error_exit("function parameters weird");
+                break;
+        }
     }
 
     fun_type = FunctionType::get(ret_type, param_types);
     auto fun = Function::create(fun_type, node.id, module.get());
-    scope.push(node.id, fun);
     cur_fun = fun;
+    scope.push(node.id, fun);
+
     auto funBB = BasicBlock::create(module.get(), "entry", fun);
     builder->set_insert_point(funBB);
     scope.enter();
+
     std::vector<Value *> args;
     for (auto arg = fun->arg_begin(); arg != fun->arg_end(); arg++) {
         args.push_back(*arg);
     }
+
     for (int i = 0; i < node.params.size(); ++i) {
         //!TODO: You need to deal with params
         // and store them in the scope.
-
-
-
+        cur_value = args[i];
+        node.params[i]->accept(*this);
     }
     node.compound_stmt->accept(*this);
-    if (builder->get_insert_block()->get_terminator() == nullptr) 
-    {
+    // default return value
+    if (builder->get_insert_block()->get_terminator() == nullptr) {
         if (cur_fun->get_return_type()->is_void_type())
             builder->create_void_ret();
         else if (cur_fun->get_return_type()->is_float_type())
@@ -105,16 +201,28 @@ void CminusfBuilder::visit(ASTFunDeclaration &node) {
     scope.exit();
 }
 
+// Done
 void CminusfBuilder::visit(ASTParam &node) {
     //!TODO: This function is empty now.
-    // Add some code here.
+    // If the parameter is int|float, copy and store them
+    switch (node.type) {
+        case TYPE_INT: {
+            scope.push(node.id, cur_value);
+            break;
+        }
+        case TYPE_FLOAT: {
+            scope.push(node.id, cur_value);
+            break;
+        }
+        case TYPE_VOID:
+            break;
+    }
 }
 
 void CminusfBuilder::visit(ASTCompoundStmt &node) {
     //!TODO: This function is not complete.
     // You may need to add some code here
-    // to deal with complex statements. 
-    
+    // to deal with complex statements.
 
     for (auto &decl : node.local_declarations) {
         decl->accept(*this);
@@ -142,43 +250,245 @@ void CminusfBuilder::visit(ASTIterationStmt &node) {
     // Add some code here.
 }
 
+// Jobs:
+// - call accept()
+// - gen return code
 void CminusfBuilder::visit(ASTReturnStmt &node) {
     if (node.expression == nullptr) {
         builder->create_void_ret();
     } else {
         //!TODO: The given code is incomplete.
         // You need to solve other return cases (e.g. return an integer).
-
-
+        //
+        node.expression->accept(*this);
+        builder->create_ret(cur_value);
     }
 }
 
 void CminusfBuilder::visit(ASTVar &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    //
+    // Goal: calculate address
+    // 1. get base
+    // 2. get bias if there is, and cast it if needed.
+
+    auto memory = scope.find(node.id);
+    Value *addr;
+    if (memory == nullptr) {
+        LOG_ERROR << node.id << " not declared!";
+        std::abort();
+    }
+    if (node.expression) { // a[1] = 1;
+        node.expression->accept(*this);
+        if (not Type::is_eq_type(cur_value->get_type(), INT32_T)) {
+            if (Type::is_eq_type(cur_value->get_type(), FLOAT_T))
+                cur_value = builder->create_fptosi(cur_value, INT32_T);
+            else {
+                LOG_ERROR << "unexpected type!";
+                std::abort();
+            }
+        }
+
+        addr = builder->create_gep(memory, {cur_value});
+
+    } else { // a = 1;
+        addr = memory;
+    }
+    cur_value = addr;
 }
 
 void CminusfBuilder::visit(ASTAssignExpression &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    //
+    // 1. For assignment, both side should have a vaule,
+    // the left side has an addr, right side have the correspond value
+    // 2. Type cast!!!
+    //
+    //
+    // This accept() should update `cur_value` to the left value
+    node.var->accept(*this);
+    auto left = cur_value;
+    // This accept() should update `cur_value` to the right value
+    node.expression->accept(*this);
+
+    // type cast
+    auto type = scope.find(node.var->id)->get_type();
+    if (not Type::is_eq_type(type, cur_value->get_type())) {
+        if (type->is_pointer_type())
+            cur_value = builder->create_fptosi(cur_value, INT32_T);
+        else if (type->is_float_type())
+            cur_value = builder->create_sitofp(cur_value, FLOAT_T);
+        else {
+            LOG(ERROR) << "Bad assignment!";
+            std::abort();
+        }
+    }
+    // gen code
+    builder->create_store(left, cur_value);
 }
 
+// Done
 void CminusfBuilder::visit(ASTSimpleExpression &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    //
+    node.additive_expression_l->accept(*this);
+    if (node.additive_expression_r) {
+        auto lvalue = cur_value;
+        node.additive_expression_r->accept(*this);
+        auto rvalue = cur_value;
+        // type cast
+        bool float_cmp = type_cast(lvalue, rvalue, "cmp");
+        switch (node.op) {
+            case OP_LE: {
+                if (float_cmp)
+                    cur_value = builder->create_fcmp_le(lvalue, rvalue);
+                else
+                    cur_value = builder->create_icmp_le(lvalue, rvalue);
+                break;
+            }
+            case OP_LT: {
+                if (float_cmp)
+                    cur_value = builder->create_fcmp_lt(lvalue, rvalue);
+                else
+                    cur_value = builder->create_icmp_lt(lvalue, rvalue);
+                break;
+            }
+            case OP_GT: {
+                if (float_cmp)
+                    cur_value = builder->create_fcmp_gt(lvalue, rvalue);
+                else
+                    cur_value = builder->create_icmp_gt(lvalue, rvalue);
+                break;
+            }
+            case OP_GE: {
+                if (float_cmp)
+                    cur_value = builder->create_fcmp_ge(lvalue, rvalue);
+                else
+                    cur_value = builder->create_icmp_ge(lvalue, rvalue);
+                break;
+            }
+            case OP_EQ: {
+                if (float_cmp)
+                    cur_value = builder->create_fcmp_eq(lvalue, rvalue);
+                else
+                    cur_value = builder->create_icmp_eq(lvalue, rvalue);
+                break;
+            }
+            case OP_NEQ: {
+                if (float_cmp)
+                    cur_value = builder->create_fcmp_ne(lvalue, rvalue);
+                else
+                    cur_value = builder->create_icmp_ne(lvalue, rvalue);
+                break;
+            }
+        }
+    }
 }
 
+// Done
 void CminusfBuilder::visit(ASTAdditiveExpression &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    //
+    node.term->accept(*this);
+    if (node.additive_expression) {
+        auto lvalue = cur_value;
+        node.additive_expression->accept(*this);
+        auto rvalue = cur_value;
+        // type cast
+        bool float_type = type_cast(lvalue, rvalue, "addop");
+        // now left and right is the same type
+        switch (node.op) {
+            case OP_PLUS: {
+                if (float_type)
+                    cur_value = builder->create_fadd(lvalue, rvalue);
+                else
+                    cur_value = builder->create_iadd(lvalue, rvalue);
+                break;
+            }
+            case OP_MINUS: {
+                if (float_type)
+                    cur_value = builder->create_fsub(lvalue, rvalue);
+                else
+                    cur_value = builder->create_isub(lvalue, rvalue);
+                break;
+            }
+        }
+    }
 }
 
+// Done
 void CminusfBuilder::visit(ASTTerm &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    node.factor->accept(*this);
+    if (node.term) {
+        auto lvalue = cur_value;
+        node.term->accept(*this);
+        auto rvalue = cur_value;
+        // type cast
+        bool float_type = type_cast(lvalue, rvalue, "mulop");
+        // now left and right is the same type
+        switch (node.op) {
+            case OP_MUL: {
+                if (float_type)
+                    cur_value = builder->create_fmul(lvalue, rvalue);
+                else
+                    cur_value = builder->create_imul(lvalue, rvalue);
+                break;
+            }
+            case OP_DIV: {
+                if (float_type)
+                    cur_value = builder->create_fdiv(lvalue, rvalue);
+                else
+                    cur_value = builder->create_isdiv(lvalue, rvalue);
+                break;
+            }
+        }
+    }
 }
 
+// Done
 void CminusfBuilder::visit(ASTCall &node) {
     //!TODO: This function is empty now.
     // Add some code here.
+    Function *func = static_cast<Function *>(scope.find(node.id));
+    std::vector<Value *> args;
+    if (func == nullptr)
+        error_exit("function " + node.id + " not declared");
+    if (node.args.size() != func->get_num_of_args())
+        error_exit("expect " + std::to_string(func->get_num_of_args()) + " params, but " +
+                   std::to_string(node.args.size()) + " is given");
+    for (int i = 0; i != node.args.size(); ++i) {
+        Type *param_type = func->get_function_type()->get_param_type(i);
+        node.args[i]->accept(*this);
+
+        // type cast
+        if (not Type::is_eq_type(param_type, cur_value->get_type())) {
+            if (param_type->is_pointer_type()) {
+                if (not Type::is_eq_type(param_type->get_pointer_element_type(),
+                                         cur_value->get_type()->get_array_element_type()))
+                    error_exit("expected right pointer type");
+                // int[] to int* or float[] to flot*
+                cur_value = builder->create_gep(cur_value, {0, 0});
+            } else if (param_type->is_integer_type() or param_type->is_float_type()) {
+                // need type cast between int and float
+                if (Type::is_eq_type(cur_value->get_type(), INT32_T))
+                    cur_value = builder->create_sitofp(cur_value, FLOAT_T);
+                else if (Type::is_eq_type(cur_value->get_type(), FLOAT_T))
+                    cur_value = builder->create_fptosi(cur_value, INT32_T);
+                else
+                    error_exit("unexpected type cast!");
+
+            } else
+                error_exit("unexpected case when casting arguments for function call" + node.id);
+        }
+
+        // now cur_value fits the param type
+        args.push_back(cur_value);
+    }
+    cur_value = builder->create_call(func, args);
 }
diff --git a/src/cminusfc/cminusfc.cpp b/src/cminusfc/cminusfc.cpp
index 09dbe05f45b3c0c23fba0ca427beed09f7b207ba..ec0d73d37bd8f05d26d66fa90cd93436e95040fa 100644
--- a/src/cminusfc/cminusfc.cpp
+++ b/src/cminusfc/cminusfc.cpp
@@ -1,4 +1,5 @@
 #include "cminusf_builder.hpp"
+
 #include <fstream>
 #include <iostream>
 #include <memory>
@@ -6,11 +7,10 @@
 using namespace std::literals::string_literals;
 
 void print_help(std::string exe_name) {
-    std::cout << "Usage: " << exe_name <<
-        " [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] <input-file>" << std::endl;
+    std::cout << "Usage: " << exe_name << " [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] <input-file>"
+              << std::endl;
 }
 
-
 int main(int argc, char **argv) {
     std::string target_path;
     std::string input_path;
diff --git a/src/common/ast.cpp b/src/common/ast.cpp
index 42439683015781ace95cf7905dc11175a6c906dc..263c4688c31502371561578af2cf9e70e499213d 100644
--- a/src/common/ast.cpp
+++ b/src/common/ast.cpp
@@ -1,31 +1,28 @@
 #include "ast.hpp"
+
 #include <cstring>
-#include <stack>
 #include <iostream>
-#define _AST_NODE_ERROR_ \
-    std::cerr << "Abort due to node cast error."\
-    "Contact with TAs to solve your problem."\
-    << std::endl;\
+#include <stack>
+#define _AST_NODE_ERROR_                                                                                               \
+    std::cerr << "Abort due to node cast error."                                                                       \
+                 "Contact with TAs to solve your problem."                                                             \
+              << std::endl;                                                                                            \
     std::abort();
 #define _STR_EQ(a, b) (strcmp((a), (b)) == 0)
 
-void AST::run_visitor(ASTVisitor &visitor) {
-    root->accept(visitor);
-}
+void AST::run_visitor(ASTVisitor &visitor) { root->accept(visitor); }
 
-AST::AST(syntax_tree* s) {
+AST::AST(syntax_tree *s) {
     if (s == nullptr) {
         std::cerr << "empty input tree!" << std::endl;
         std::abort();
     }
     auto node = transform_node_iter(s->root);
     del_syntax_tree(s);
-    root = std::shared_ptr<ASTProgram>(
-            static_cast<ASTProgram *>(node));
+    root = std::shared_ptr<ASTProgram>(static_cast<ASTProgram *>(node));
 }
 
-ASTNode *
-AST::transform_node_iter(syntax_tree_node *n) {
+ASTNode *AST::transform_node_iter(syntax_tree_node *n) {
     if (_STR_EQ(n->name, "program")) {
         auto node = new ASTProgram();
 
@@ -39,11 +36,9 @@ AST::transform_node_iter(syntax_tree_node *n) {
         s.push(list_ptr->children[0]);
 
         while (!s.empty()) {
-            auto child_node = static_cast<ASTDeclaration*>(
-                    transform_node_iter(s.top()));
+            auto child_node = static_cast<ASTDeclaration *>(transform_node_iter(s.top()));
 
-            auto child_node_shared =
-                std::shared_ptr<ASTDeclaration>(child_node);
+            auto child_node_shared = std::shared_ptr<ASTDeclaration>(child_node);
             node->declarations.push_back(child_node_shared);
             s.pop();
         }
@@ -57,7 +52,7 @@ AST::transform_node_iter(syntax_tree_node *n) {
             node->type = TYPE_INT;
         else
             node->type = TYPE_FLOAT;
- 
+
         if (n->children_num == 3) {
             node->id = n->children[1]->name;
         } else if (n->children_num == 6) {
@@ -97,19 +92,15 @@ AST::transform_node_iter(syntax_tree_node *n) {
             s.push(list_ptr->children[0]);
 
             while (!s.empty()) {
-                auto child_node = static_cast<ASTParam*>(
-                        transform_node_iter(s.top()));
+                auto child_node = static_cast<ASTParam *>(transform_node_iter(s.top()));
 
-                auto child_node_shared =
-                    std::shared_ptr<ASTParam>(child_node);
+                auto child_node_shared = std::shared_ptr<ASTParam>(child_node);
                 node->params.push_back(child_node_shared);
                 s.pop();
             }
         }
 
-        auto stmt_node =
-            static_cast<ASTCompoundStmt *>(
-                    transform_node_iter(n->children[5]));
+        auto stmt_node = static_cast<ASTCompoundStmt *>(transform_node_iter(n->children[5]));
         node->compound_stmt = std::shared_ptr<ASTCompoundStmt>(stmt_node);
         return node;
     } else if (_STR_EQ(n->name, "param")) {
@@ -134,16 +125,14 @@ AST::transform_node_iter(syntax_tree_node *n) {
             }
 
             while (!s.empty()) {
-                auto decl_node =
-                    static_cast<ASTVarDeclaration*>(
-                            transform_node_iter(s.top()));
+                auto decl_node = static_cast<ASTVarDeclaration *>(transform_node_iter(s.top()));
                 auto decl_node_ptr = std::shared_ptr<ASTVarDeclaration>(decl_node);
                 node->local_declarations.push_back(decl_node_ptr);
                 s.pop();
             }
         }
 
-        if (n->children[2]->children_num ==    2) {
+        if (n->children[2]->children_num == 2) {
             // flatten statement-list
             auto list_ptr = n->children[2];
             std::stack<syntax_tree_node *> s;
@@ -153,9 +142,7 @@ AST::transform_node_iter(syntax_tree_node *n) {
             }
 
             while (!s.empty()) {
-                auto stmt_node =
-                    static_cast<ASTStatement *>(
-                            transform_node_iter(s.top()));
+                auto stmt_node = static_cast<ASTStatement *>(transform_node_iter(s.top()));
                 auto stmt_node_ptr = std::shared_ptr<ASTStatement>(stmt_node);
                 node->statement_list.push_back(stmt_node_ptr);
                 s.pop();
@@ -167,9 +154,7 @@ AST::transform_node_iter(syntax_tree_node *n) {
     } else if (_STR_EQ(n->name, "expression-stmt")) {
         auto node = new ASTExpressionStmt();
         if (n->children_num == 2) {
-            auto expr_node =
-                static_cast<ASTExpression *>(
-                        transform_node_iter(n->children[0]));
+            auto expr_node = static_cast<ASTExpression *>(transform_node_iter(n->children[0]));
 
             auto expr_node_ptr = std::shared_ptr<ASTExpression>(expr_node);
             node->expression = expr_node_ptr;
@@ -178,24 +163,18 @@ AST::transform_node_iter(syntax_tree_node *n) {
     } else if (_STR_EQ(n->name, "selection-stmt")) {
         auto node = new ASTSelectionStmt();
 
-        auto expr_node =
-            static_cast<ASTExpression *>(
-                    transform_node_iter(n->children[2]));
+        auto expr_node = static_cast<ASTExpression *>(transform_node_iter(n->children[2]));
         auto expr_node_ptr = std::shared_ptr<ASTExpression>(expr_node);
         node->expression = expr_node_ptr;
 
-        auto if_stmt_node =
-            static_cast<ASTStatement *>(
-                    transform_node_iter(n->children[4]));
+        auto if_stmt_node = static_cast<ASTStatement *>(transform_node_iter(n->children[4]));
         auto if_stmt_node_ptr = std::shared_ptr<ASTStatement>(if_stmt_node);
         node->if_statement = if_stmt_node_ptr;
 
         // check whether this selection statement contains
         // else structure
         if (n->children_num == 7) {
-            auto else_stmt_node =
-                static_cast<ASTStatement *>(
-                        transform_node_iter(n->children[6]));
+            auto else_stmt_node = static_cast<ASTStatement *>(transform_node_iter(n->children[6]));
             auto else_stmt_node_ptr = std::shared_ptr<ASTStatement>(else_stmt_node);
             node->else_statement = else_stmt_node_ptr;
         }
@@ -204,15 +183,11 @@ AST::transform_node_iter(syntax_tree_node *n) {
     } else if (_STR_EQ(n->name, "iteration-stmt")) {
         auto node = new ASTIterationStmt();
 
-        auto expr_node =
-            static_cast<ASTExpression *>(
-                    transform_node_iter(n->children[2]));
+        auto expr_node = static_cast<ASTExpression *>(transform_node_iter(n->children[2]));
         auto expr_node_ptr = std::shared_ptr<ASTExpression>(expr_node);
         node->expression = expr_node_ptr;
 
-        auto stmt_node =
-            static_cast<ASTStatement *>(
-                    transform_node_iter(n->children[4]));
+        auto stmt_node = static_cast<ASTStatement *>(transform_node_iter(n->children[4]));
         auto stmt_node_ptr = std::shared_ptr<ASTStatement>(stmt_node);
         node->statement = stmt_node_ptr;
 
@@ -220,11 +195,8 @@ AST::transform_node_iter(syntax_tree_node *n) {
     } else if (_STR_EQ(n->name, "return-stmt")) {
         auto node = new ASTReturnStmt();
         if (n->children_num == 3) {
-            auto expr_node =
-                static_cast<ASTExpression *>(
-                        transform_node_iter(n->children[1]));
-            node->expression =
-                std::shared_ptr<ASTExpression>(expr_node);
+            auto expr_node = static_cast<ASTExpression *>(transform_node_iter(n->children[1]));
+            node->expression = std::shared_ptr<ASTExpression>(expr_node);
         }
         return node;
     } else if (_STR_EQ(n->name, "expression")) {
@@ -234,36 +206,25 @@ AST::transform_node_iter(syntax_tree_node *n) {
         }
         auto node = new ASTAssignExpression();
 
-        auto var_node =
-            static_cast<ASTVar *>(
-                    transform_node_iter(n->children[0]));
+        auto var_node = static_cast<ASTVar *>(transform_node_iter(n->children[0]));
         node->var = std::shared_ptr<ASTVar>(var_node);
 
-        auto expr_node =
-            static_cast<ASTExpression *>(
-                    transform_node_iter(n->children[2]));
-        node->expression =
-            std::shared_ptr<ASTExpression>(expr_node);
+        auto expr_node = static_cast<ASTExpression *>(transform_node_iter(n->children[2]));
+        node->expression = std::shared_ptr<ASTExpression>(expr_node);
 
         return node;
     } else if (_STR_EQ(n->name, "var")) {
         auto node = new ASTVar();
         node->id = n->children[0]->name;
         if (n->children_num == 4) {
-            auto expr_node =
-                static_cast<ASTExpression *>(
-                        transform_node_iter(n->children[2]));
-            node->expression =
-                std::shared_ptr<ASTExpression>(expr_node);
+            auto expr_node = static_cast<ASTExpression *>(transform_node_iter(n->children[2]));
+            node->expression = std::shared_ptr<ASTExpression>(expr_node);
         }
         return node;
     } else if (_STR_EQ(n->name, "simple-expression")) {
         auto node = new ASTSimpleExpression();
-        auto expr_node_1 =
-            static_cast<ASTAdditiveExpression *>(
-                    transform_node_iter(n->children[0]));
-        node->additive_expression_l =
-            std::shared_ptr<ASTAdditiveExpression>(expr_node_1);
+        auto expr_node_1 = static_cast<ASTAdditiveExpression *>(transform_node_iter(n->children[0]));
+        node->additive_expression_l = std::shared_ptr<ASTAdditiveExpression>(expr_node_1);
 
         if (n->children_num == 3) {
             auto op_name = n->children[1]->children[0]->name;
@@ -280,21 +241,15 @@ AST::transform_node_iter(syntax_tree_node *n) {
             else if (_STR_EQ(op_name, "!="))
                 node->op = OP_NEQ;
 
-            auto expr_node_2 =
-                static_cast<ASTAdditiveExpression *>(
-                        transform_node_iter(n->children[2]));
-            node->additive_expression_r =
-                std::shared_ptr<ASTAdditiveExpression>(expr_node_2);
+            auto expr_node_2 = static_cast<ASTAdditiveExpression *>(transform_node_iter(n->children[2]));
+            node->additive_expression_r = std::shared_ptr<ASTAdditiveExpression>(expr_node_2);
         }
         return node;
     } else if (_STR_EQ(n->name, "additive-expression")) {
         auto node = new ASTAdditiveExpression();
         if (n->children_num == 3) {
-            auto add_expr_node =
-                static_cast<ASTAdditiveExpression *>(
-                        transform_node_iter(n->children[0]));
-            node->additive_expression =
-                std::shared_ptr<ASTAdditiveExpression>(add_expr_node);
+            auto add_expr_node = static_cast<ASTAdditiveExpression *>(transform_node_iter(n->children[0]));
+            node->additive_expression = std::shared_ptr<ASTAdditiveExpression>(add_expr_node);
 
             auto op_name = n->children[1]->children[0]->name;
             if (_STR_EQ(op_name, "+"))
@@ -302,25 +257,18 @@ AST::transform_node_iter(syntax_tree_node *n) {
             else if (_STR_EQ(op_name, "-"))
                 node->op = OP_MINUS;
 
-            auto term_node =
-                static_cast<ASTTerm *>(
-                        transform_node_iter(n->children[2]));
+            auto term_node = static_cast<ASTTerm *>(transform_node_iter(n->children[2]));
             node->term = std::shared_ptr<ASTTerm>(term_node);
         } else {
-            auto term_node =
-                static_cast<ASTTerm *>(
-                        transform_node_iter(n->children[0]));
+            auto term_node = static_cast<ASTTerm *>(transform_node_iter(n->children[0]));
             node->term = std::shared_ptr<ASTTerm>(term_node);
         }
         return node;
     } else if (_STR_EQ(n->name, "term")) {
         auto node = new ASTTerm();
         if (n->children_num == 3) {
-            auto term_node =
-                static_cast<ASTTerm *>(
-                        transform_node_iter(n->children[0]));
-            node->term =
-                std::shared_ptr<ASTTerm>(term_node);
+            auto term_node = static_cast<ASTTerm *>(transform_node_iter(n->children[0]));
+            node->term = std::shared_ptr<ASTTerm>(term_node);
 
             auto op_name = n->children[1]->children[0]->name;
             if (_STR_EQ(op_name, "*"))
@@ -328,14 +276,10 @@ AST::transform_node_iter(syntax_tree_node *n) {
             else if (_STR_EQ(op_name, "/"))
                 node->op = OP_DIV;
 
-            auto factor_node =
-                static_cast<ASTFactor *>(
-                        transform_node_iter(n->children[2]));
+            auto factor_node = static_cast<ASTFactor *>(transform_node_iter(n->children[2]));
             node->factor = std::shared_ptr<ASTFactor>(factor_node);
         } else {
-            auto factor_node =
-                static_cast<ASTFactor *>(
-                        transform_node_iter(n->children[0]));
+            auto factor_node = static_cast<ASTFactor *>(transform_node_iter(n->children[0]));
             node->factor = std::shared_ptr<ASTFactor>(factor_node);
         }
         return node;
@@ -344,9 +288,7 @@ AST::transform_node_iter(syntax_tree_node *n) {
         if (n->children_num == 3)
             i = 1;
         auto name = n->children[i]->name;
-        if (_STR_EQ(name, "expression") ||
-                _STR_EQ(name, "var") ||
-                _STR_EQ(name, "call"))
+        if (_STR_EQ(name, "expression") || _STR_EQ(name, "var") || _STR_EQ(name, "call"))
             return transform_node_iter(n->children[i]);
         else {
             auto num_node = new ASTNum();
@@ -375,11 +317,8 @@ AST::transform_node_iter(syntax_tree_node *n) {
             s.push(list_ptr->children[0]);
 
             while (!s.empty()) {
-                auto expr_node =
-                    static_cast<ASTExpression *>(
-                            transform_node_iter(s.top()));
-                auto expr_node_ptr =
-                    std::shared_ptr<ASTExpression>(expr_node);
+                auto expr_node = static_cast<ASTExpression *>(transform_node_iter(s.top()));
+                auto expr_node_ptr = std::shared_ptr<ASTExpression>(expr_node);
                 node->args.push_back(expr_node_ptr);
                 s.pop();
             }
@@ -409,29 +348,25 @@ void ASTTerm::accept(ASTVisitor &visitor) { visitor.visit(*this); }
 void ASTCall::accept(ASTVisitor &visitor) { visitor.visit(*this); }
 
 void ASTFactor::accept(ASTVisitor &visitor) {
-    auto expr =
-        dynamic_cast<ASTExpression *>(this);
+    auto expr = dynamic_cast<ASTExpression *>(this);
     if (expr) {
         expr->accept(visitor);
         return;
     }
 
-    auto var =
-        dynamic_cast<ASTVar *>(this);
+    auto var = dynamic_cast<ASTVar *>(this);
     if (var) {
         var->accept(visitor);
         return;
     }
 
-    auto call =
-        dynamic_cast<ASTCall *>(this);
+    auto call = dynamic_cast<ASTCall *>(this);
     if (call) {
         call->accept(visitor);
         return;
     }
 
-    auto num =
-        dynamic_cast<ASTNum *>(this);
+    auto num = dynamic_cast<ASTNum *>(this);
     if (num) {
         num->accept(visitor);
         return;
@@ -441,14 +376,12 @@ void ASTFactor::accept(ASTVisitor &visitor) {
 }
 
 void ASTDeclaration::accept(ASTVisitor &visitor) {
-    auto var_decl =
-        dynamic_cast<ASTVarDeclaration *>(this);
+    auto var_decl = dynamic_cast<ASTVarDeclaration *>(this);
     if (var_decl) {
         var_decl->accept(visitor);
         return;
     }
-    auto fun_decl =
-        dynamic_cast<ASTFunDeclaration *>(this);
+    auto fun_decl = dynamic_cast<ASTFunDeclaration *>(this);
     if (fun_decl) {
         fun_decl->accept(visitor);
         return;
@@ -457,36 +390,31 @@ void ASTDeclaration::accept(ASTVisitor &visitor) {
 }
 
 void ASTStatement::accept(ASTVisitor &visitor) {
-    auto comp_stmt =
-        dynamic_cast<ASTCompoundStmt *>(this);
+    auto comp_stmt = dynamic_cast<ASTCompoundStmt *>(this);
     if (comp_stmt) {
         comp_stmt->accept(visitor);
         return;
     }
 
-    auto expr_stmt =
-        dynamic_cast<ASTExpressionStmt *>(this);
+    auto expr_stmt = dynamic_cast<ASTExpressionStmt *>(this);
     if (expr_stmt) {
         expr_stmt->accept(visitor);
         return;
     }
 
-    auto sele_stmt =
-        dynamic_cast<ASTSelectionStmt *>(this);
+    auto sele_stmt = dynamic_cast<ASTSelectionStmt *>(this);
     if (sele_stmt) {
         sele_stmt->accept(visitor);
         return;
     }
 
-    auto iter_stmt =
-        dynamic_cast<ASTIterationStmt *>(this);
+    auto iter_stmt = dynamic_cast<ASTIterationStmt *>(this);
     if (iter_stmt) {
         iter_stmt->accept(visitor);
         return;
     }
 
-    auto ret_stmt =
-        dynamic_cast<ASTReturnStmt *>(this);
+    auto ret_stmt = dynamic_cast<ASTReturnStmt *>(this);
     if (ret_stmt) {
         ret_stmt->accept(visitor);
         return;
@@ -495,15 +423,13 @@ void ASTStatement::accept(ASTVisitor &visitor) {
 }
 
 void ASTExpression::accept(ASTVisitor &visitor) {
-    auto simple_expr =
-        dynamic_cast<ASTSimpleExpression *>(this);
+    auto simple_expr = dynamic_cast<ASTSimpleExpression *>(this);
     if (simple_expr) {
         simple_expr->accept(visitor);
         return;
     }
 
-    auto assign_expr =
-        dynamic_cast<ASTAssignExpression *>(this);
+    auto assign_expr = dynamic_cast<ASTAssignExpression *>(this);
     if (assign_expr) {
         assign_expr->accept(visitor);
         return;
@@ -511,15 +437,14 @@ void ASTExpression::accept(ASTVisitor &visitor) {
     _AST_NODE_ERROR_
 }
 
-#define _DEBUG_PRINT_N_(N) {\
-    std::cout << std::string(N, '-');\
-}
+#define _DEBUG_PRINT_N_(N)                                                                                             \
+    { std::cout << std::string(N, '-'); }
 
 void ASTPrinter::visit(ASTProgram &node) {
     _DEBUG_PRINT_N_(depth);
     std::cout << "program" << std::endl;
     add_depth();
-    for (auto decl: node.declarations) {
+    for (auto decl : node.declarations) {
         decl->accept(*this);
     }
     remove_depth();
@@ -534,7 +459,6 @@ void ASTPrinter::visit(ASTNum &node) {
     } else {
         _AST_NODE_ERROR_
     }
-
 }
 
 void ASTPrinter::visit(ASTVarDeclaration &node) {
@@ -554,7 +478,7 @@ void ASTPrinter::visit(ASTFunDeclaration &node) {
     _DEBUG_PRINT_N_(depth);
     std::cout << "fun-declaration: " << node.id << std::endl;
     add_depth();
-    for (auto param: node.params) {
+    for (auto param : node.params) {
         param->accept(*this);
     }
 
@@ -574,11 +498,11 @@ void ASTPrinter::visit(ASTCompoundStmt &node) {
     _DEBUG_PRINT_N_(depth);
     std::cout << "compound-stmt" << std::endl;
     add_depth();
-    for (auto decl: node.local_declarations) {
+    for (auto decl : node.local_declarations) {
         decl->accept(*this);
     }
 
-    for (auto stmt: node.statement_list) {
+    for (auto stmt : node.statement_list) {
         stmt->accept(*this);
     }
     remove_depth();
@@ -600,7 +524,7 @@ void ASTPrinter::visit(ASTSelectionStmt &node) {
     node.expression->accept(*this);
     node.if_statement->accept(*this);
     if (node.else_statement != nullptr)
-    node.else_statement->accept(*this);
+        node.else_statement->accept(*this);
     remove_depth();
 }
 
@@ -730,7 +654,7 @@ void ASTPrinter::visit(ASTCall &node) {
     _DEBUG_PRINT_N_(depth);
     std::cout << "call: " << node.id << "()" << std::endl;
     add_depth();
-    for (auto arg: node.args) {
+    for (auto arg : node.args) {
         arg->accept(*this);
     }
     remove_depth();
diff --git a/src/common/syntax_tree.c b/src/common/syntax_tree.c
index 0ac6e6bdd1e1b2a656d64363bb80a12129bb9cfa..6a58d749648d9b56ad01dc0de169a5e387c1a768 100644
--- a/src/common/syntax_tree.c
+++ b/src/common/syntax_tree.c
@@ -1,77 +1,72 @@
+#include "syntax_tree.h"
+
 #include <stdlib.h>
 #include <string.h>
 
-#include "syntax_tree.h"
-
-syntax_tree_node * new_syntax_tree_node(const char * name)
-{
-	syntax_tree_node * new_node = (syntax_tree_node *)malloc(sizeof(syntax_tree_node));
-	if (name)
-		strncpy(new_node->name, name, SYNTAX_TREE_NODE_NAME_MAX);
-	else
-		new_node->name[0] = '\0';
-	new_node->children_num = 0;
-	return new_node;
+syntax_tree_node *new_syntax_tree_node(const char *name) {
+    syntax_tree_node *new_node = (syntax_tree_node *)malloc(sizeof(syntax_tree_node));
+    if (name)
+        strncpy(new_node->name, name, SYNTAX_TREE_NODE_NAME_MAX);
+    else
+        new_node->name[0] = '\0';
+    new_node->children_num = 0;
+    return new_node;
 }
 
-int syntax_tree_add_child(syntax_tree_node * parent, syntax_tree_node * child)
-{
-	if (!parent || !child)	return -1;
-	parent->children[parent->children_num++] = child;
-	return parent->children_num;
+int syntax_tree_add_child(syntax_tree_node *parent, syntax_tree_node *child) {
+    if (!parent || !child)
+        return -1;
+    parent->children[parent->children_num++] = child;
+    return parent->children_num;
 }
 
-void del_syntax_tree_node(syntax_tree_node * node, int recursive)
-{
-	if (!node)	return;
+void del_syntax_tree_node(syntax_tree_node *node, int recursive) {
+    if (!node)
+        return;
 
-	int i;
-	if (recursive) {
-		for (i = 0; i < node->children_num; i++) {
-			del_syntax_tree_node(node->children[i], 1);
-		}
-	}
-	free(node);
+    int i;
+    if (recursive) {
+        for (i = 0; i < node->children_num; i++) {
+            del_syntax_tree_node(node->children[i], 1);
+        }
+    }
+    free(node);
 }
 
-syntax_tree * new_syntax_tree()
-{
-	return (syntax_tree *)malloc(sizeof(syntax_tree));
-}
+syntax_tree *new_syntax_tree() { return (syntax_tree *)malloc(sizeof(syntax_tree)); }
 
-void del_syntax_tree(syntax_tree * tree)
-{
-	if (!tree)	return;
+void del_syntax_tree(syntax_tree *tree) {
+    if (!tree)
+        return;
 
-	if (tree->root) {
-		del_syntax_tree_node(tree->root, 1);
-	}
-	free(tree);
+    if (tree->root) {
+        del_syntax_tree_node(tree->root, 1);
+    }
+    free(tree);
 }
 
-void print_syntax_tree_node(FILE * fout, syntax_tree_node * node, int level)
-{
-	// assume fout valid now
-	
-	// check if "node" empty pointer
-	if (!node)	return;
-	
-	// print myself
-	int i;
-	for (i = 0; i < level; i++) {
-		fprintf(fout, "|  ");
-	}
-	fprintf(fout, ">--%s %s\n", (node->children_num ? "+" : "*"), node->name);
+void print_syntax_tree_node(FILE *fout, syntax_tree_node *node, int level) {
+    // assume fout valid now
 
-	for (i = 0; i < node->children_num; i++) {
-		print_syntax_tree_node(fout, node->children[i], level + 1);
-	}
-}
+    // check if "node" empty pointer
+    if (!node)
+        return;
+
+    // print myself
+    int i;
+    for (i = 0; i < level; i++) {
+        fprintf(fout, "|  ");
+    }
+    fprintf(fout, ">--%s %s\n", (node->children_num ? "+" : "*"), node->name);
 
-void print_syntax_tree(FILE * fout, syntax_tree * tree)
-{
-	if (!fout)	return;
-	
-	print_syntax_tree_node(fout, tree->root, 0);
+    for (i = 0; i < node->children_num; i++) {
+        print_syntax_tree_node(fout, node->children[i], level + 1);
+    }
 }
 
+void print_syntax_tree(FILE *fout, syntax_tree *tree) {
+    if (!fout)
+        return;
+
+    print_syntax_tree_node(fout, tree->root, 0);
+}
diff --git a/tests/3-ir-gen/.gitignore b/tests/3-ir-gen/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7f5e6ccf43bdbc92c0311700911d4c948826e7fc
--- /dev/null
+++ b/tests/3-ir-gen/.gitignore
@@ -0,0 +1,2 @@
+eval_result
+
diff --git a/tests/3-ir-gen/testcases/lv0_1/.gitignore b/tests/3-ir-gen/testcases/lv0_1/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..38169b59791f28c6630c0f6ca281650a1aa8008a
--- /dev/null
+++ b/tests/3-ir-gen/testcases/lv0_1/.gitignore
@@ -0,0 +1,11 @@
+*.ll
+clean.sh
+decl_float_array
+decl_float
+decl_int_array
+decl_int
+input
+output_float
+output_int
+return
+
diff --git a/tests/3-ir-gen/testcases/lv0_2/.gitignore b/tests/3-ir-gen/testcases/lv0_2/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..116c231901b7746933ac2e778077a321937c21cc
--- /dev/null
+++ b/tests/3-ir-gen/testcases/lv0_2/.gitignore
@@ -0,0 +1,35 @@
+*.ll
+clean.sh
+num_add_float
+num_add_int
+num_add_mixed
+num_comp1
+num_comp2
+num_div_float
+num_div_int
+num_div_mixed
+num_eq_float
+num_eq_int
+num_eq_mixed
+num_ge_float
+num_ge_int
+num_ge_mixed
+num_gt_float
+num_gt_int
+num_gt_mixed
+num_le_float
+num_le_int
+num_le_mixed
+num_lt_float
+num_lt_int
+num_lt_mixed
+num_mul_float
+num_mul_int
+num_mul_mixed
+num_neq_float
+num_neq_int
+num_neq_mixed
+num_sub_float
+num_sub_int
+num_sub_mixed
+