diff --git a/src/Lib/Script/Ast/IrElement.hh b/src/Lib/Script/Ast/IrElement.hh
index 53dcd66333795700f2d2a958611f9dbe20f64e95..77d353c234fc09b1f875e500dd2d754f267ebcbd 100644
--- a/src/Lib/Script/Ast/IrElement.hh
+++ b/src/Lib/Script/Ast/IrElement.hh
@@ -14,6 +14,7 @@ namespace Vivy::Script
 
 /* Structural And Declarative Objects */
 class IrRoot;      // A root, with all the needed modules, etc
+class IrScope;     // A thing to store everything that is in the scope
 class IrModule;    // A module (single vvs file)
 class IrAttribute; // Attribute placed on the module, function, etc
 class IrImport;    // An import statement
@@ -107,6 +108,7 @@ concept IrElementParsable = std::is_base_of<IrElement, T>::value && requires(T i
 class IrElement {
     IrElement *parentElement       = nullptr;
     IrAttribute *elementAttributes = nullptr;
+    IrRoot *parentRoot             = nullptr;
     std::vector<IrElement *> childElements;
 
 protected:
@@ -125,6 +127,7 @@ public:
 
     virtual const IrElement *parent() const noexcept;
     virtual IrElement *parent() noexcept;
+    IrRoot *irRoot() const noexcept;
 
     void setParent(IrElement *p) noexcept;
     void setAttribute(IrAttribute *a) noexcept;
diff --git a/src/Lib/Script/Ast/IrExpression.cc b/src/Lib/Script/Ast/IrExpression.cc
index 8aa191c4d718408d07abe7bcae57aacf01ac8b00..60f991b86069f0bc3be3b8bd3929535d758c1649 100644
--- a/src/Lib/Script/Ast/IrExpression.cc
+++ b/src/Lib/Script/Ast/IrExpression.cc
@@ -1,4 +1,5 @@
 #include "IrExpression.hh"
+#include "IrScope.hh"
 #include "IrFunction.hh"
 #include "IrElement.hh"
 #include "IrVariable.hh"
diff --git a/src/Lib/Script/Ast/IrExpression.hh b/src/Lib/Script/Ast/IrExpression.hh
index c2ff6f9d72f0d69215d15645fc4f7e06d7e55bf1..4295eff6a653726f427100cae9dbb72f69f706f5 100644
--- a/src/Lib/Script/Ast/IrExpression.hh
+++ b/src/Lib/Script/Ast/IrExpression.hh
@@ -18,7 +18,8 @@ public:
 
 private:
     Type selfType;
-    IrType *selfInnerType = nullptr;
+    IrType *selfInnerType    = nullptr;
+    IrScope *selfParentScope = nullptr;
 
     /*
     ** Helper for the parser, create a binary expression, insert the last expression at
@@ -57,6 +58,7 @@ protected:
 
 public:
     std::string toString() const noexcept override;
+    IrScope *parentScope() const noexcept;
     void parse(std::vector<Token> *);
 
     Type type() const noexcept;
@@ -169,9 +171,7 @@ class IrEVariableRef : public IrExpression {
     std::vector<IrExpression *> indicies;
 
     IrEVariableRef(IrVariable *) noexcept;
-
     IrEVariableRef(IrVariable *, std::vector<IrExpression *> &&);
-
     template <typename... Args> IrEVariableRef(IrVariable *var, Args &&...indicieArgs)
         : IrEVariableRef(var, std::vector<IrExpression *>{ indicieArgs... })
     {
diff --git a/src/Lib/Script/Ast/IrRoot.cc b/src/Lib/Script/Ast/IrRoot.cc
index 9cd352ae00e194b648cc2832e742079e466cb43d..708c26902189438a32f6cf4f1d6570d3bf49d2f0 100644
--- a/src/Lib/Script/Ast/IrRoot.cc
+++ b/src/Lib/Script/Ast/IrRoot.cc
@@ -30,6 +30,11 @@ findInVector(const std::vector<T *> &vector, ::Vivy::Script::StrV itemName) noex
 
 namespace Vivy::Script
 {
+IrRoot::IrRoot() noexcept
+    : IrElement(this)
+{
+}
+
 const IrRoot *
 IrRoot::parent() const noexcept
 {
diff --git a/src/Lib/Script/Ast/IrRoot.hh b/src/Lib/Script/Ast/IrRoot.hh
index 1c4d5d87d3a313e0e219a10f34970d2d24c1e147..01209b856942620c6dc949062d59e5877fbc9440 100644
--- a/src/Lib/Script/Ast/IrRoot.hh
+++ b/src/Lib/Script/Ast/IrRoot.hh
@@ -9,12 +9,15 @@ class IrRoot final : public IrElement {
     VIVY_IR_ELEMENT(IrRoot)
     std::vector<IrModule *> modules;
     IrModule *mainVivyModule = nullptr;
-    IrRoot() noexcept        = default;
+    IrScope *globalScope     = nullptr;
+    IrRoot() noexcept;
 
 public:
     const IrRoot *parent() const noexcept override;
     IrRoot *parent() noexcept override;
 
+    IrScope *scope() noexcept;
+
     std::string toString() const noexcept override;
     void parse(std::vector<Token> *tokens);
 
diff --git a/src/Lib/Script/Ast/IrScope.cc b/src/Lib/Script/Ast/IrScope.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ef053614ecd4cadfc19e2a2d6080a92ffe32622d
--- /dev/null
+++ b/src/Lib/Script/Ast/IrScope.cc
@@ -0,0 +1,17 @@
+#include "IrScope.hh"
+#include "IrRoot.hh"
+
+namespace Vivy::Script
+{
+bool
+IrScope::isGlobal() const noexcept
+{
+    return irRoot()->scope() == this;
+}
+
+bool
+IrScope::isLocal() const noexcept
+{
+    return !isGlobal();
+}
+}
diff --git a/src/Lib/Script/Ast/IrScope.hh b/src/Lib/Script/Ast/IrScope.hh
new file mode 100644
index 0000000000000000000000000000000000000000..91ebb366f36c1ec9a5fb2521b08394ab5bb0421f
--- /dev/null
+++ b/src/Lib/Script/Ast/IrScope.hh
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "IrElement.hh"
+
+namespace Vivy::Script
+{
+class IrScope final : public IrElement {
+    VIVY_IR_ELEMENT(IrScope)
+
+    IrScope *parentScope;
+    std::vector<IrFunction *> inScopeFunctions;
+    std::vector<IrVariable *> inScopeVariables;
+
+    IrScope(IrElement *parent);
+
+public:
+    std::string toString() const noexcept override;
+
+    bool isGlobal() const noexcept;
+    bool isLocal() const noexcept;
+
+    IrFunction *getFunctionByName(StrV) const noexcept;
+    IrFunction *getFunctionByName(const char *) const noexcept;
+    IrFunction *getFunctionByName(const std::string &) const noexcept;
+
+    IrVariable *getVariableByName(StrV) const noexcept;
+    IrVariable *getVariableByName(const char *) const noexcept;
+    IrVariable *getVariableByName(const std::string &) const noexcept;
+
+    void addFunction(IrFunction *);
+    void addVariable(IrVariable *);
+};
+}