diff --git a/src/Lib/Script/Ast/IrExpression.cc b/src/Lib/Script/Ast/IrExpression.cc
index 63e95cc233282a2855dc1f8812156e3c7a9deff2..7669714d229d8eb7b7a7ffe0fc74b57e45556fef 100644
--- a/src/Lib/Script/Ast/IrExpression.cc
+++ b/src/Lib/Script/Ast/IrExpression.cc
@@ -5,6 +5,10 @@
 
 #include <cassert>
 
+/*
+** IrExpression
+*/
+
 namespace Vivy::Script
 {
 IrExpression::IrExpression(IrElement *p, Type type) noexcept
@@ -63,6 +67,10 @@ IrExpression::innerType() const noexcept
 }
 }
 
+/*
+** IrEVariableRef
+*/
+
 namespace Vivy::Script
 {
 std::string
@@ -168,6 +176,10 @@ IrEConstExpr::parse(std::vector<Token> *)
 }
 }
 
+/*
+** IrECall
+*/
+
 namespace Vivy::Script
 {
 std::string
@@ -181,6 +193,16 @@ IrECall::parse(std::vector<Token> *)
 {
     throw std::logic_error("Not implemented");
 }
+
+const IrFunction *IrECall::call() const noexcept
+{
+    return callPtr;
+}
+
+const std::vector<IrExpression *>& IrECall::args() const noexcept
+{
+    return inArgs;
+}
 }
 
 namespace Vivy::Script
diff --git a/src/Lib/Script/Ast/IrExpression.hh b/src/Lib/Script/Ast/IrExpression.hh
index ff66f4338cd0d454aa60b36100c56e0ab47d50be..95688f629b1c407bf0b2f5e00d5d9d228dd30949 100644
--- a/src/Lib/Script/Ast/IrExpression.hh
+++ b/src/Lib/Script/Ast/IrExpression.hh
@@ -46,7 +46,6 @@ class IrEConstExpr : public IrExpression {
 
 public:
     std::string toString() const noexcept override;
-    void parse(std::vector<Token> *) override;
     virtual IrTPrimitive *innerType() const noexcept override;
 
     bool getInnerBoolean() const;
@@ -59,40 +58,93 @@ public:
 class IrECall : public IrExpression {
     VIVY_IR_ELEMENT(IrECall)
 
+    IrFunction *callPtr = nullptr;
+    std::vector<IrExpression *> inArgs;
+
 public:
     std::string toString() const noexcept override;
-    void parse(std::vector<Token> *) override;
+
+    const IrFunction *call() const noexcept;
+    const std::vector<IrExpression *>& args() const noexcept;
 };
 
 class IrECompOp : public IrExpression {
     VIVY_IR_ELEMENT(IrECompOp)
 
+public:
+    enum class OpType { LT, GT, LE, GE, EQ, NEQ };
+
+private:
+    const OpType selfOpType;
+    IrExpression *left;
+    IrExpression *right;
+
+    IrECompOp(OpType, IrExpression*&&left, IrExpression*&&right) noexcept;
+
 public:
     std::string toString() const noexcept override;
-    void parse(std::vector<Token> *) override;
+
+    OpType opType() const noexcept;
 };
 
 class IrEArithmeticOp : public IrExpression {
     VIVY_IR_ELEMENT(IrEArithmeticOp)
 
+public:
+    enum class OpType { Add, Sub, Mul, Div, Mod };
+
+private:
+    const OpType selfOpType;
+    IrExpression *left;
+    IrExpression *right;
+
+    IrEArithmeticOp(OpType, IrExpression*&&left, IrExpression*&&right) noexcept;
+
 public:
     std::string toString() const noexcept override;
-    void parse(std::vector<Token> *) override;
+
+    OpType opType() const noexcept;
 };
 
 class IrELogicOp : public IrExpression {
     VIVY_IR_ELEMENT(IrELogicOp)
 
+public:
+    enum class OpType { And, Or, Xor };
+
+private:
+    const OpType selfOpType;
+    IrExpression *left;
+    IrExpression *right;
+
+    IrELogicOp(OpType, IrExpression*&&left, IrExpression*&&right) noexcept;
+
 public:
     std::string toString() const noexcept override;
-    void parse(std::vector<Token> *) override;
+
+    OpType opType() const noexcept;
 };
 
 class IrEVariableRef : public IrExpression {
     VIVY_IR_ELEMENT(IrEVariableRef)
 
+    IrVariable *const referencedVariable;
+
+    IrEVariableRef(IrVariable *) noexcept;
+
+    IrEVariableRef(IrVariable *, std::vector<IrExpression*>&&);
+
+    template<typename... Args>
+    IrEVariableRef(IrVariable *var, Args...&&indicies)
+        : IrEVariableRef(var, std::vector<IrExpression*>{indicies...})
+    {
+    }
+
 public:
     std::string toString() const noexcept override;
-    void parse(std::vector<Token> *) override;
 };
+
+std::string toString(IrELogicOp::OpType) noexcept;
+std::string toString(IrEArithmeticOp::OpType) noexcept;
+std::string toString(IrECompOp::OpType) noexcept;
 }