diff --git a/include/dusk/AST/ASTNode.h b/include/dusk/AST/ASTNode.h
index 79f539289a2b0bdd467cf8ee1893eb6faf949307..b789791e836e9edd0eac714f296f60a77f817d8e 100644
--- a/include/dusk/AST/ASTNode.h
+++ b/include/dusk/AST/ASTNode.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_AST_NODE_H
 #define DUSK_AST_NODE_H
 
+#include "dusk/Basic/LLVM.h"
 #include "llvm/Support/SMLoc.h"
 
 namespace dusk {
@@ -34,13 +35,13 @@ public:
   virtual ~ASTNode() = default;
 
   /// Returns text range in source file represented by the node.
-  virtual llvm::SMRange getSourceRange() const = 0;
+  virtual SMRange getSourceRange() const = 0;
 
   /// Returns start of the text range represented by the node.
-  llvm::SMLoc getLocStart() const { return getSourceRange().Start; }
+  SMLoc getLocStart() const { return getSourceRange().Start; }
 
   /// Returns end of the text range represented by the node.
-  llvm::SMLoc getLocEnd() const { return getSourceRange().End; }
+  SMLoc getLocEnd() const { return getSourceRange().End; }
 
   /// Walks AST node.
   ///
diff --git a/include/dusk/AST/ASTPrinter.h b/include/dusk/AST/ASTPrinter.h
index 62240bf4f88abb4289e39bd65b870ba55303c244..71f2b5eca347ae25e396412e9bb6df199404bc20 100644
--- a/include/dusk/AST/ASTPrinter.h
+++ b/include/dusk/AST/ASTPrinter.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_AST_PRINTER_H
 #define DUSK_AST_PRINTER_H
 
+#include "dusk/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
@@ -60,13 +61,13 @@ public:
   unsigned getDepth() const { return Depth; }
 
   /// Returns Current indentation;
-  llvm::StringRef getIndent() const;
+  StringRef getIndent() const;
 
   /// Return indentation depth.
   operator unsigned() const { return Depth; }
 
   /// Return indentation depth.
-  operator llvm::StringRef() const { return getIndent(); }
+  operator StringRef() const { return getIndent(); }
 
   /// Increases indentation depth.
   Indentation &operator++();
@@ -76,9 +77,9 @@ public:
 
 private:
   // Util methods
-  llvm::StringRef getSpaceIndent() const;
-  llvm::StringRef getTabIndent() const;
-  llvm::StringRef getIndentBlock() const;
+  StringRef getSpaceIndent() const;
+  StringRef getTabIndent() const;
+  StringRef getIndentBlock() const;
 };
 
 /// A simple abstract class, which provides a basic interface for printing AST.
@@ -88,19 +89,19 @@ class ASTPrinter {
   Indentation Ind;
 
   /// Newline character
-  llvm::StringRef Newline = "\n";
+  StringRef Newline = "\n";
 
   /// True is cursor at start of the line.
   bool AtStartOfLine = true;
 
 public:
   ASTPrinter() = default;
-  ASTPrinter(llvm::StringRef NL);
+  ASTPrinter(StringRef NL);
 
   bool isAtStartOfLine() const { return AtStartOfLine; }
 
   /// Raw output of text without any formatting.
-  virtual void printText(llvm::StringRef Text) = 0;
+  virtual void printText(StringRef Text) = 0;
 
   /// Prints current indentation and sets \c AtStartOfLine to \c false.
   virtual void printIndent();
@@ -109,13 +110,13 @@ public:
   virtual void printNewline();
 
   /// Prints a single keyword.
-  virtual void printKeyword(llvm::StringRef KW);
+  virtual void printKeyword(StringRef KW);
 
   /// Prints given separator depending on the \c IsFirst arg, which is set
   /// to \c false, if the current element is first.
-  virtual void printSeparator(bool &IsFirst, llvm::StringRef S);
+  virtual void printSeparator(bool &IsFirst, StringRef S);
 
-  ASTPrinter &operator<<(llvm::StringRef Text);
+  ASTPrinter &operator<<(StringRef Text);
 
   ASTPrinter &operator<<(uint64_t N);
 
@@ -127,14 +128,14 @@ public:
   /// Decreates indentation.
   ASTPrinter &operator--();
 
-  //===------------------------------------------------------------------------===
+  //===----------------------------------------------------------------------===
   //
   // Callback interface.
   //
   // Callback helper methods, which are called before and after a particular
   // node is being print.
   //
-  //===------------------------------------------------------------------------===
+  //===----------------------------------------------------------------------===
 
   virtual void printDeclPre(Decl *D) {}
   virtual void printDeclPost(Decl *D) {}
@@ -144,20 +145,19 @@ public:
   virtual void printPatternPost(Pattern *P) {}
 
 private:
-  void print(llvm::StringRef Text);
+  void print(StringRef Text);
 };
 
 /// Simple implementation of ASTPrinter, which prints text into the provided
 /// \c llvm::raw_ostream.
 class StreamPrinter : public ASTPrinter {
-  llvm::raw_ostream &OS;
+  raw_ostream &OS;
 
 public:
-  StreamPrinter(llvm::raw_ostream &OS);
-  virtual void printText(llvm::StringRef Text) override;
+  StreamPrinter(raw_ostream &OS);
+  virtual void printText(StringRef Text) override;
 };
 
 } // namespace dusk
 
 #endif /* DUSK_AST_PRINTER_H */
-
diff --git a/include/dusk/AST/ASTWalker.h b/include/dusk/AST/ASTWalker.h
index 38a45d804d29aab35e1dae369290e8dbcbdaa68b..a87ffe5f1b7954369d6287cd2c46d202d4a087d0 100644
--- a/include/dusk/AST/ASTWalker.h
+++ b/include/dusk/AST/ASTWalker.h
@@ -10,6 +10,8 @@
 #ifndef DUSK_AST_WALKER_H
 #define DUSK_AST_WALKER_H
 
+#include "dusk/Basic/LLVM.h"
+
 namespace dusk {
 class Decl;
 class Expr;
diff --git a/include/dusk/AST/Decl.h b/include/dusk/AST/Decl.h
index 3baeee07eaf247e8e098c0ee1dd763b2ab13048f..91adb810bb36a5779c0d79195e22805656170bc1 100644
--- a/include/dusk/AST/Decl.h
+++ b/include/dusk/AST/Decl.h
@@ -38,13 +38,13 @@ class Decl : public ASTNode {
   DeclKind Kind;
 
   /// Declaration name
-  llvm::StringRef Name;
+  StringRef Name;
 
   /// Location of declaration
-  llvm::SMLoc NameLoc;
+  SMLoc NameLoc;
 
 public:
-  Decl(DeclKind K, llvm::StringRef N, llvm::SMLoc NL);
+  Decl(DeclKind K, StringRef N, SMLoc NL);
   virtual ~Decl() = default;
 
   /// Returns declaration kind.
@@ -57,71 +57,71 @@ public:
   bool isValDecl() const;
 
   /// Returns declaration identifier as string.
-  llvm::StringRef getName() const { return Name; }
+  StringRef getName() const { return Name; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Declaration of value-holdable node
 class ValDecl : public Decl {
   /// Value Location
-  llvm::SMLoc ValLoc;
+  SMLoc ValLoc;
 
   Expr *Value;
 
 public:
-  ValDecl(DeclKind K, llvm::StringRef N, llvm::SMLoc NL, Expr *V);
+  ValDecl(DeclKind K, StringRef N, SMLoc NL, Expr *V);
 
-  llvm::SMLoc getValLoc() const { return ValLoc; }
+  SMLoc getValLoc() const { return ValLoc; }
   Expr *getValue() const { return Value; }
 };
 
 /// Declaration of a variable
 class VarDecl : public ValDecl {
   /// Location of \c var keyword
-  llvm::SMLoc VarLoc;
+  SMLoc VarLoc;
 
 public:
-  VarDecl(llvm::StringRef N, llvm::SMLoc NL, llvm::SMLoc VarL, Expr *V);
+  VarDecl(StringRef N, SMLoc NL, SMLoc VarL, Expr *V);
 
-  llvm::SMLoc getVarLoc() const { return VarLoc; }
-  virtual llvm::SMRange getSourceRange() const override;
+  SMLoc getVarLoc() const { return VarLoc; }
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Declaration of a constant
 class ConstDecl : public ValDecl {
   /// Location of \c const keyword
-  llvm::SMLoc ConstLoc;
+  SMLoc ConstLoc;
 
 public:
-  ConstDecl(llvm::StringRef N, llvm::SMLoc NL, llvm::SMLoc ConstL, Expr *V);
+  ConstDecl(StringRef N, SMLoc NL, SMLoc ConstL, Expr *V);
 
-  llvm::SMLoc getConstLoc() const { return ConstLoc; }
+  SMLoc getConstLoc() const { return ConstLoc; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Declaration of function parameter
 class ParamDecl : public Decl {
 public:
-  ParamDecl(llvm::StringRef N, llvm::SMLoc NL);
+  ParamDecl(StringRef N, SMLoc NL);
 };
 
 /// Function declaration
 class FuncDecl : public Decl {
   /// Location of \c func keyword
-  llvm::SMLoc FuncLoc;
+  SMLoc FuncLoc;
 
   /// Function arguments
-  Pattern *Params;
+  VarPattern *Params;
 
 public:
-  FuncDecl(llvm::StringRef N, llvm::SMLoc NL, llvm::SMLoc FuncL, Pattern *A);
+  FuncDecl(StringRef N, SMLoc NL, SMLoc FuncL, VarPattern *A);
 
-  llvm::SMLoc getFuncLoc() const { return FuncLoc; }
-  Pattern *getArgs() const { return Params; }
+  SMLoc getFuncLoc() const { return FuncLoc; }
+  VarPattern *getArgs() const { return Params; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// A signle module
@@ -131,10 +131,10 @@ class ModuleDecl : public Decl {
   std::vector<ASTNode *> Contents;
 
 public:
-  ModuleDecl(llvm::StringRef N, std::vector<ASTNode *> &&C);
+  ModuleDecl(StringRef N, std::vector<ASTNode *> &&C);
 
-  llvm::ArrayRef<ASTNode *> getContents() const { return Contents; }
-  virtual llvm::SMRange getSourceRange() const override;
+  ArrayRef<ASTNode *> getContents() const { return Contents; }
+  virtual SMRange getSourceRange() const override;
 };
 
 } // namespace dusk
diff --git a/include/dusk/AST/Diagnostics.h b/include/dusk/AST/Diagnostics.h
index 7ec0d8a166b83f5838d8e2f2491ad9e0fda33e60..f011490b767ab55c420be68798b1ff48baccc132 100644
--- a/include/dusk/AST/Diagnostics.h
+++ b/include/dusk/AST/Diagnostics.h
@@ -37,17 +37,17 @@ enum struct DiagID : unsigned;
 class DiagnosticConsumer {
 public:
   /// Consumes a single diagnotic.
-  virtual void consume(llvm::SMDiagnostic &Diagnostic) = 0;
+  virtual void consume(SMDiagnostic &Diagnostic) = 0;
 };
 
 /// Represents a single diagnostic.
 ///
 /// This is a container object holding all necessary information to create
-/// a \c llvm::SMDiagnostic for a diagnostic consumer.
+/// a \c SMDiagnostic for a diagnostic consumer.
 class Diagnostic {
   diag::DiagID ID;
-  llvm::SmallVector<llvm::SMFixIt, 2> FixIts;
-  llvm::SMLoc SourceLoc;
+  SmallVector<SMFixIt, 2> FixIts;
+  SMLoc SourceLoc;
 
   friend class DiagnosticEngine;
 
@@ -59,14 +59,14 @@ public:
   // Accessors
 
   diag::DiagID getID() const { return ID; }
-  llvm::ArrayRef<llvm::SMFixIt> getFixIts() const { return FixIts; }
-  llvm::SMLoc getLoc() const { return SourceLoc; }
+  ArrayRef<SMFixIt> getFixIts() const { return FixIts; }
+  SMLoc getLoc() const { return SourceLoc; }
 
   /// Sets the default location of the diagnostic.
-  void setLoc(llvm::SMLoc Loc) { SourceLoc = Loc; }
+  void setLoc(SMLoc Loc) { SourceLoc = Loc; }
 
   /// Adds a \c FixIt to the diagnostic.
-  void addFixIt(llvm::SMFixIt &&FixIt) { FixIts.push_back(std::move(FixIt)); }
+  void addFixIt(SMFixIt &&FixIt) { FixIts.push_back(std::move(FixIt)); }
 };
 
 /// Reference interface to a diagnostic, which is currently active within the
@@ -112,17 +112,17 @@ public:
   /// Adds a fixit.
   ///
   /// A fixit will reference a provided \c Loc.
-  DiagnosticRef &fixIt(llvm::StringRef FixIt, llvm::SMLoc Loc);
+  DiagnosticRef &fixIt(StringRef FixIt, SMLoc Loc);
 
   /// Adds a fixit before a token located at provided location.
-  DiagnosticRef &fixItBefore(llvm::StringRef FixIt, llvm::SMLoc Loc);
+  DiagnosticRef &fixItBefore(StringRef FixIt, SMLoc Loc);
 
   /// Adds a fixit after a token located at provided location.
-  DiagnosticRef &fixItAfter(llvm::StringRef FixIt, llvm::SMLoc Loc);
+  DiagnosticRef &fixItAfter(StringRef FixIt, SMLoc Loc);
 };
 
 /// This class is acts as a pipeline between custom diagnostic objects and
-/// the diagnostic consumers which consume standart \c llvm::SMDiagnostic
+/// the diagnostic consumers which consume standart \c SMDiagnostic
 /// objects.
 class DiagnosticEngine {
   llvm::SourceMgr &SourceManager;
@@ -131,7 +131,7 @@ class DiagnosticEngine {
   std::vector<DiagnosticConsumer *> Consumers;
 
   /// Currently active diagnostic
-  llvm::Optional<Diagnostic> ActiveDiag;
+  Optional<Diagnostic> ActiveDiag;
 
   friend class Diagnostic;
   friend class DiagnosticRef;
@@ -160,7 +160,7 @@ public:
   /// \return A \c DiagnosticRef object, which is an interface referencing
   /// created diagnostic. User can add additional information via this
   /// diagnostic reference.
-  DiagnosticRef diagnose(llvm::SMLoc SourceLoc, diag::DiagID ID) {
+  DiagnosticRef diagnose(SMLoc SourceLoc, diag::DiagID ID) {
     assert(!ActiveDiag && "Cannot have two active diagnostics at one.");
 
     ActiveDiag = Diagnostic(ID);
@@ -182,3 +182,4 @@ private:
 } // namespace dusk
 
 #endif /* DUSK_DIAGNOSTICS_H */
+
diff --git a/include/dusk/AST/DiagnosticsParse.h b/include/dusk/AST/DiagnosticsParse.h
index 4f407702408eab78ad402137b33d662a8d8a0644..10cdbed7d7497e1dafd6a63dab11cf88beb8094f 100644
--- a/include/dusk/AST/DiagnosticsParse.h
+++ b/include/dusk/AST/DiagnosticsParse.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_DIAGNOSTICS_PARSE_H
 #define DUSK_DIAGNOSTICS_PARSE_H
 
+#include "dusk/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
 
 namespace dusk {
@@ -38,7 +39,7 @@ enum struct DiagID : unsigned {
   expected_r_brace
 };
 
-static llvm::StringRef getTextForID(DiagID ID) {
+static StringRef getTextForID(DiagID ID) {
   switch (ID) {
   // Lexer diagnostics
   case DiagID::lex_unexpected_symbol:
diff --git a/include/dusk/AST/Expr.h b/include/dusk/AST/Expr.h
index 7cbcb1a04e1b8a7aa203bd5504e1bd447bcba07e..398880883470d55e3d1cd765399725fd50f23be7 100644
--- a/include/dusk/AST/Expr.h
+++ b/include/dusk/AST/Expr.h
@@ -57,28 +57,28 @@ public:
 /// Number literal expression encalsulation.
 class NumberLiteralExpr : public Expr {
   int Value;
-  llvm::SMRange ValueLoc;
+  SMRange ValueLoc;
 
 public:
-  NumberLiteralExpr(int V, llvm::SMRange ValL);
+  NumberLiteralExpr(int V, SMRange ValL);
 
-  llvm::SMRange getValLoc() const { return ValueLoc; }
+  SMRange getValLoc() const { return ValueLoc; }
   int getValue() const { return Value; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 class IdentifierExpr : public Expr {
-  llvm::StringRef Name;
-  llvm::SMLoc NameLoc;
+  StringRef Name;
+  SMLoc NameLoc;
 
 public:
-  IdentifierExpr(llvm::StringRef N, llvm::SMLoc L);
+  IdentifierExpr(StringRef N, SMLoc L);
 
-  llvm::StringRef getName() const { return Name; }
-  llvm::SMLoc getNameLoc() const { return NameLoc; }
+  StringRef getName() const { return Name; }
+  SMLoc getNameLoc() const { return NameLoc; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Represents a paranthesized expression
@@ -89,17 +89,17 @@ class ParenExpr : public Expr {
   Expr *Expression;
 
   /// Left parethensis
-  llvm::SMLoc LPar;
+  SMLoc LPar;
 
   /// Right parethensis
-  llvm::SMLoc RPar;
+  SMLoc RPar;
 
 public:
-  ParenExpr(Expr *E, llvm::SMLoc L, llvm::SMLoc R);
+  ParenExpr(Expr *E, SMLoc L, SMLoc R);
 
   Expr *getExpr() const { return Expression; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// An infix expression
@@ -115,7 +115,7 @@ public:
   Expr *getRHS() const { return RHS; }
   Token getOp() const { return Op; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 class AssignExpr : public Expr {
@@ -128,7 +128,7 @@ public:
   Expr *getDest() const { return Dest; }
   Expr *getSource() const { return Source; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 class PrefixExpr : public Expr {
@@ -141,7 +141,7 @@ public:
   Expr *getDest() const { return Dest; }
   Token getOp() const { return Op; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 class CallExpr : public Expr {
@@ -157,7 +157,7 @@ public:
   Expr *getCalle() const { return Callee; }
   Pattern *getArgs() { return Args; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 class SubscriptExpr : public Expr {
@@ -173,9 +173,10 @@ public:
   Expr *getBase() { return Base; }
   Pattern *getSubscript() { return Subscript; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 } // namespace dusk
 
 #endif /* DUSK_EXPR_H */
+
diff --git a/include/dusk/AST/Pattern.h b/include/dusk/AST/Pattern.h
index e5b86a3facd0ba72d9617fb38eb1d264c5fe063e..1d9057163ab82e472562e6f2a0993d8447952e2d 100644
--- a/include/dusk/AST/Pattern.h
+++ b/include/dusk/AST/Pattern.h
@@ -1,4 +1,6 @@
-//===--- Pattern.h - Dusk patterns ------------------------------*- C++ -*-===//
+
+
+  //===--- Pattern.h - Dusk patterns ------------------------------*- C++ -*-===//
 //
 //                                 dusk-lang
 // This source file is part of a dusk-lang project, which is a semestral
@@ -32,31 +34,31 @@ class Pattern : public ASTNode {
 public:
   Pattern(PatternKind K);
   PatternKind getKind() const { return Kind; }
-
-  llvm::SMLoc getLocStart() const { return getSourceRange().Start; }
-  llvm::SMLoc getLocEnd() const { return getSourceRange().End; }
+  
+  virtual size_t count() const = 0;
 };
 
 /// Expression pattern
 ///
 /// Used in function calls. Each of the items must be a valid expression.
 class ExprPattern : public Pattern {
-  llvm::SmallVector<Expr *, 128> Values;
+  SmallVector<Expr *, 128> Values;
 
   /// Location of left parenthesis
-  llvm::SMLoc LPar;
+  SMLoc LPar;
 
   /// Location of right parenthesis
-  llvm::SMLoc RPar;
+  SMLoc RPar;
 
 public:
-  ExprPattern(llvm::SmallVector<Expr *, 128> &&V, llvm::SMLoc L, llvm::SMLoc R);
+  ExprPattern(SmallVector<Expr *, 128> &&V, SMLoc L, SMLoc R);
 
-  llvm::ArrayRef<Expr *> getValues() const { return Values; }
-  llvm::SMLoc getLPar() const { return LPar; }
-  llvm::SMLoc getRPar() const { return RPar; }
+  ArrayRef<Expr *> getValues() const { return Values; }
+  SMLoc getLPar() const { return LPar; }
+  SMLoc getRPar() const { return RPar; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual size_t count() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Variable pattern
@@ -65,23 +67,23 @@ public:
 /// declaration.
 class VarPattern : public Pattern {
   /// Variables of the expression
-  llvm::SmallVector<Decl *, 128> Vars;
+  SmallVector<Decl *, 128> Vars;
 
   /// Location of left parenthesis
-  llvm::SMLoc LPar;
+  SMLoc LPar;
 
   /// Location of right parenthesis
-  llvm::SMLoc RPar;
+  SMLoc RPar;
 
 public:
-  VarPattern(llvm::SmallVector<Decl *, 128> &&V, llvm::SMLoc L,
-             llvm::SMLoc R);
+  VarPattern(SmallVector<Decl *, 128> &&V, SMLoc L, SMLoc R);
 
-  llvm::ArrayRef<Decl *> getVars() const { return Vars; }
-  llvm::SMLoc getLPar() const { return LPar; }
-  llvm::SMLoc getRPar() const { return RPar; }
+  ArrayRef<Decl *> getVars() const { return Vars; }
+  SMLoc getLPar() const { return LPar; }
+  SMLoc getRPar() const { return RPar; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual size_t count() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Subscript pattern
@@ -92,19 +94,20 @@ class SubscriptPattern : public Pattern {
   Expr *Value;
 
   /// Location of left bracket
-  llvm::SMLoc LBracet;
+  SMLoc LBracet;
 
   /// Location of right bracket
-  llvm::SMLoc RBracet;
+  SMLoc RBracet;
 
 public:
-  SubscriptPattern(Expr *V, llvm::SMLoc L, llvm::SMLoc R);
+  SubscriptPattern(Expr *V, SMLoc L, SMLoc R);
 
   Expr *getValue() const { return Value; }
-  llvm::SMLoc getLBracket() const { return LBracet; }
-  llvm::SMLoc getRBracket() const { return RBracet; }
+  SMLoc getLBracket() const { return LBracet; }
+  SMLoc getRBracket() const { return RBracet; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual size_t count() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 } // namespace dusk
diff --git a/include/dusk/AST/Stmt.h b/include/dusk/AST/Stmt.h
index 0e04d890a9d38292e136094810e9105ce8b7305e..6ce554c09ae940812ad67ed97161f056c62101c6 100644
--- a/include/dusk/AST/Stmt.h
+++ b/include/dusk/AST/Stmt.h
@@ -42,27 +42,27 @@ public:
 /// Represents a `break` statement in a loop.
 class BreakStmt : public Stmt {
   /// Range of \c break keyword
-  llvm::SMRange BreakLoc;
+  SMRange BreakLoc;
 
 public:
-  BreakStmt(llvm::SMRange BR);
+  BreakStmt(SMRange BR);
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Represents a `return` statement.
 class ReturnStmt : public Stmt {
   /// Location of \c return keyword
-  llvm::SMLoc RetLoc;
+  SMLoc RetLoc;
 
   /// Value that is to be returned.
   Expr *Value;
 
 public:
-  ReturnStmt(llvm::SMLoc RL, Expr *V);
+  ReturnStmt(SMLoc RL, Expr *V);
 
   Expr *getValue() const { return Value; }
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Represents a range.
@@ -86,25 +86,25 @@ public:
   /// Return \c true, if range is inclusive, \c false otherwise.
   bool isInclusive() const;
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Represents an arbitrary block of code.
 class BlockStmt : public Stmt {
   /// Location of block's opening \c {
-  llvm::SMLoc BlockStart;
+  SMLoc BlockStart;
 
   /// Location of block's closing \c }
-  llvm::SMLoc BlockEnd;
+  SMLoc BlockEnd;
 
   /// Blocks children nodes
   std::vector<ASTNode *> Nodes;
 
 public:
-  BlockStmt(llvm::SMLoc S, llvm::SMLoc E, std::vector<ASTNode *> &&N);
+  BlockStmt(SMLoc S, SMLoc E, std::vector<ASTNode *> &&N);
 
-  llvm::ArrayRef<ASTNode *> getNodes() { return Nodes; }
-  virtual llvm::SMRange getSourceRange() const override;
+  ArrayRef<ASTNode *> getNodes() { return Nodes; }
+  virtual SMRange getSourceRange() const override;
 };
 
 /// Represents a Function statement a.k.a declaration and definition.
@@ -118,13 +118,13 @@ public:
   Decl *getPrototype() { return Prototype; }
   Stmt *getBody() { return Body; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// For-in statement representation
 class ForStmt : public Stmt {
   /// Location of \c for keyword
-  llvm::SMLoc ForLoc;
+  SMLoc ForLoc;
 
   /// Iterabling variable
   Expr *Var;
@@ -136,36 +136,36 @@ class ForStmt : public Stmt {
   Stmt *Body;
 
 public:
-  ForStmt(llvm::SMLoc FL, Expr *V, Stmt *R, Stmt *C);
+  ForStmt(SMLoc FL, Expr *V, Stmt *R, Stmt *C);
 
   Expr *getVar() const { return Var; }
   Stmt *getRange() const { return Range; }
   Stmt *getBody() const { return Body; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// While statement encapsulation
 class WhileStmt : public Stmt {
   /// Location of \c while keyword
-  llvm::SMLoc WhileLoc;
+  SMLoc WhileLoc;
 
   Expr *Cond;
   Stmt *Body;
 
 public:
-  WhileStmt(llvm::SMLoc WL, Expr *C, Stmt *B);
+  WhileStmt(SMLoc WL, Expr *C, Stmt *B);
 
   Expr *getCond() const { return Cond; }
   Stmt *getBody() const { return Body; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 /// If/If-Else statement encapsulation
 class IfStmt : public Stmt {
   /// Location of \c if keyword
-  llvm::SMLoc IfLoc;
+  SMLoc IfLoc;
 
   Expr *Cond;
   Stmt *Then;
@@ -174,16 +174,18 @@ class IfStmt : public Stmt {
   Stmt *Else;
 
 public:
-  IfStmt(llvm::SMLoc IL, Expr *C, Stmt *T, Stmt *E = nullptr);
+  IfStmt(SMLoc IL, Expr *C, Stmt *T, Stmt *E = nullptr);
 
   Expr *getCond() const { return Cond; }
   Stmt *getThen() const { return Then; }
   Stmt *getElse() const { return Else; }
   bool hasElseBlock() const { return Else != nullptr; }
 
-  virtual llvm::SMRange getSourceRange() const override;
+  virtual SMRange getSourceRange() const override;
 };
 
 } // namesapce dusk
 
 #endif /* DUSK_STMT_H */
+
+
diff --git a/include/dusk/Basic/CMakeLists.txt b/include/dusk/Basic/CMakeLists.txt
index 679847920393c28ad83bb8b4b65456699b087343..64b308681a0617345228e85a0ada7190ebf3c975 100644
--- a/include/dusk/Basic/CMakeLists.txt
+++ b/include/dusk/Basic/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(HEADERS
+    ${CMAKE_CURRENT_SOURCE_DIR}/LLVM.h
     ${CMAKE_CURRENT_SOURCE_DIR}/SourceManager.h
     ${HEADERS}
     PARENT_SCOPE
diff --git a/include/dusk/Basic/LLVM.h b/include/dusk/Basic/LLVM.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d0d2a951b31c4145c71026333885793742c1cbf
--- /dev/null
+++ b/include/dusk/Basic/LLVM.h
@@ -0,0 +1,61 @@
+//===--- LLVM.h - LLVM imports and declarations -----------------*- C++ -*-===//
+//
+//                                 dusk-lang
+// This source file is part of a dusk-lang project, which is a semestral
+// assignement for BI-PJP course at Czech Technical University in Prague.
+// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DUSK_LLVM_H
+#define DUSK_LLVM_H
+
+#include "llvm/ADT/None.h"
+
+namespace llvm {
+
+// ADTs
+class StringRef;
+class Twine;
+template <typename T> class ArrayRef;
+template <unsigned InternalLen> class SmallString;
+template <typename T, unsigned N> class SmallVector;
+template <typename T> class Optional;
+
+// Support
+class SMLoc;
+class SMRange;
+class SourceMrg;
+class SMDiagnostic;
+class SMFixIt;
+
+// Streams
+class raw_ostream;
+class raw_os_ostream;
+
+} // namespace llvm
+
+namespace dusk {
+
+// ADTs
+using llvm::StringRef;
+using llvm::Twine;
+using llvm::ArrayRef;
+using llvm::SmallString;
+using llvm::SmallVector;
+using llvm::Optional;
+  
+// Support
+using llvm::SMLoc;
+using llvm::SMRange;
+using llvm::SourceMrg;
+using llvm::SMDiagnostic;
+using llvm::SMFixIt;
+
+// Streams
+using llvm::raw_ostream;
+using llvm::raw_os_ostream;
+
+} // namespace dusk
+
+#endif /* DUSK_LLVM_H */
diff --git a/include/dusk/Basic/SourceManager.h b/include/dusk/Basic/SourceManager.h
index b4c395d5d6824ffe144191258e5e82ad45a425b8..5f1555f078390275862ffc55829566389b12bff7 100644
--- a/include/dusk/Basic/SourceManager.h
+++ b/include/dusk/Basic/SourceManager.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_SOURCE_MANAGER_H
 #define DUSK_SOURCE_MANAGER_H
 
+#include "dusk/Basic/LLVM.h"
 #include "llvm/Support/SourceMgr.h"
 #include <cassert>
 
@@ -22,18 +23,7 @@ namespace dusk {
 /// \param Loc Location refering to a buffer.
 ///
 /// \return ID of buffer containing provided location.
-static unsigned getBufferForLoc(const llvm::SourceMgr &SM, llvm::SMLoc Loc) {
-  // Validate location
-  assert(Loc.isValid());
-  
-  auto ptr = Loc.getPointer();
-  for (unsigned i = 1; i <= SM.getNumBuffers(); i++) {
-    auto Buff = SM.getMemoryBuffer(i);
-    if (ptr >= Buff->getBufferStart() && ptr <= Buff->getBufferEnd())
-      return i;
-  }
-  llvm_unreachable("Location in non-existing buffer.");
-}
+unsigned getBufferForLoc(const llvm::SourceMgr &SM, SMLoc Loc);
   
 } // namespace dusk
 
diff --git a/include/dusk/Frontend/Compiler.h b/include/dusk/Frontend/Compiler.h
index 7b1ec48a6ea9d75b3bdd43f6a95dd3b36ddf9f57..ed230f491431aeb86cf4d96fd64d5714144d4a07 100644
--- a/include/dusk/Frontend/Compiler.h
+++ b/include/dusk/Frontend/Compiler.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_COMPILER_H
 #define DUSK_COMPILER_H
 
+#include "dusk/Basic/LLVM.h"
 #include "dusk/AST/Diagnostics.h"
 #include "dusk/AST/Diagnostics.h"
 #include "dusk/Frontend/InputFile.h"
@@ -33,12 +34,12 @@ class Compiler : public DiagnosticConsumer {
   llvm::raw_os_ostream OS;
 
 public:
-  Compiler(std::vector<llvm::StringRef> Filenames);
+  Compiler(std::vector<StringRef> Filenames);
 
   void Compile();
   void Lex();
 
-  void consume(llvm::SMDiagnostic &Diag);
+  void consume(SMDiagnostic &Diag);
 };
 
 } // namesapce dusk
diff --git a/include/dusk/Frontend/Formatter.h b/include/dusk/Frontend/Formatter.h
index 8872ab1e9f2afbb19cc64ac8d9ccf260e7274c9a..22ea10bb119366c5c10343ad9ca057a202f1ebbd 100644
--- a/include/dusk/Frontend/Formatter.h
+++ b/include/dusk/Frontend/Formatter.h
@@ -17,7 +17,7 @@ namespace dusk {
 
 class Formatter {
 public:
-  void format(ASTNode *N, llvm::raw_ostream &OS);
+  void format(ASTNode *N, raw_ostream &OS);
 };
 
 } // namespace dusk
diff --git a/include/dusk/Frontend/InputFile.h b/include/dusk/Frontend/InputFile.h
index 99bd3abb60ae2bcbad2e31a35b3b8d9bd9980012..d84b670141e7136f0d804702e5539a38cfc3439f 100644
--- a/include/dusk/Frontend/InputFile.h
+++ b/include/dusk/Frontend/InputFile.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_INPUT_FILE_H
 #define DUSK_INPUT_FILE_H
 
+#include "dusk/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -30,7 +31,7 @@ class InputFile {
 
 public:
   /// \brief Opens and reads a file with provided name.
-  InputFile(llvm::SourceMgr &SM, const llvm::StringRef F);
+  InputFile(llvm::SourceMgr &SM, const StringRef F);
 
   /// \bried Returns an ID of the opened buffer.
   unsigned bufferID() const { return BufferID; }
diff --git a/include/dusk/IRGen/CMakeLists.txt b/include/dusk/IRGen/CMakeLists.txt
index bda14a6727dc05b723138974f11cd2bffa7b6e13..7c9df5ca67fa2dda671b7954bd526167bce034c9 100644
--- a/include/dusk/IRGen/CMakeLists.txt
+++ b/include/dusk/IRGen/CMakeLists.txt
@@ -1,6 +1,6 @@
 set(HEADERS
+    ${CMAKE_CURRENT_SOURCE_DIR}/Context.h
     ${CMAKE_CURRENT_SOURCE_DIR}/IRGenerator.h
-    ${CMAKE_CURRENT_SOURCE_DIR}/Scope.h
     ${HEADERS}
     PARENT_SCOPE
 )
diff --git a/include/dusk/IRGen/Context.h b/include/dusk/IRGen/Context.h
new file mode 100644
index 0000000000000000000000000000000000000000..c21c347d558117afd5e1f736cc1ebea5ea741a13
--- /dev/null
+++ b/include/dusk/IRGen/Context.h
@@ -0,0 +1,164 @@
+//===--- Context.h - Dusck context interface --------------------*- C++ -*-===//
+//
+//                                 dusk-lang
+// This source file is part of a dusk-lang project, which is a semestral
+// assignement for BI-PJP course at Czech Technical University in Prague.
+// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Dusk context interaface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DUSK_CONTEXT_H
+#define DUSK_CONTEXT_H
+
+#include "dusk/Basic/LLVM.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Value.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Module.h"
+#include <memory>
+
+namespace dusk {
+class VarDecl;
+class ConstDecl;
+class FuncDecl;
+
+namespace irgen {
+
+/// Represents current context declaration level.
+///
+/// Constructors of this struct are private, instances of \c ContextVals class
+/// can be made by only \c Context instances.
+struct ContextVals {
+  /// Holds pointer to the parent context.
+  std::unique_ptr<ContextVals> Parent = nullptr;
+
+  /// Holds constant declarations of current scope.
+  llvm::StringMap<llvm::Value *> Consts;
+
+  /// Holds variable declarations of current scope.
+  llvm::StringMap<llvm::Value *> Vars;
+
+public:
+  /// Returns \c true if there is a reachable value delcaration for given name
+  /// the scope, \c false otherwise.
+  bool contains(StringRef Str) const { return get(Str) != nullptr; }
+
+  /// Returns \c true if a declaration for given name was performed in current
+  /// scope.
+  bool isDeclared(StringRef Str) const;
+
+  /// Returns variable for given name, if found, \c nullptr otherwise.
+  llvm::Value *getVar(StringRef Str) const;
+
+  /// Returns variable for given name, if found, \c nullptr otherwise.
+  llvm::Value *getVar(StringRef Str);
+
+  /// Returns variable for given name, if found, \c nullptr otherwise.
+  llvm::Value *get(StringRef Str) const;
+
+  /// Pushes a new context to the stack and returns a pointer to the top of the
+  /// stack.
+  ContextVals *push();
+
+  /// Pop a top context from the stack and returns a pointer to the top of the
+  /// stack.
+  ///
+  /// \note This method calls \c delete \c this on itself, therefore noone
+  /// should access this object after calling this method.
+  ContextVals *pop();
+
+private:
+  friend class Context;
+  ContextVals() = default;
+  ContextVals(ContextVals *P);
+
+  ContextVals(const ContextVals &other) = delete;
+  ContextVals &operator=(const ContextVals &other) = delete;
+};
+
+/// Represents a current declaration context.
+///
+/// Holds declaration of variables, constatnts and functions.
+class Context {
+  llvm::LLVMContext &Ctx;
+  llvm::Module *Module;
+  llvm::IRBuilder<> &Builder;
+  llvm::StringMap<llvm::FunctionType *> Funcs;
+  ContextVals *Vals;
+
+  unsigned Depth;
+
+public:
+  Context(llvm::LLVMContext &C, llvm::Module *M, llvm::IRBuilder<> &B);
+  ~Context();
+
+  operator llvm::LLVMContext &() { return Ctx; }
+
+  llvm::IRBuilder<> &getBuilder() { return Builder; }
+  
+  /// Returns current depth of the context.
+  unsigned getDepth() const { return Depth; }
+
+  /// \brief Declares a variable in current scope.
+  ///
+  /// \return \c true on success, \c false if the current scope is already
+  /// a variable, constatnt or function with the same identifier.
+  bool declare(const VarDecl *);
+
+  /// \brief Declares a variable in current scope.
+  ///
+  /// \return \c true on success, \c false if the current scope is already
+  /// a variable, constatnt or function with the same identifier.
+  bool declare(const ConstDecl *);
+
+  /// \brief Declares a function.
+  ///
+  /// \note Function can be delcared only in the global scope.
+  ///
+  /// \return \c true on success, \c false if a function with given identifier
+  /// already exists.
+  bool declare(const FuncDecl *);
+
+  /// Returns a value for given identifier. Can be both, reference variable
+  /// and constant.
+  ///
+  /// If no value is found, \c nullptr is returned.
+  llvm::Value *getVal(StringRef Str) const;
+
+  /// Returns a value for given identifier. Returns only variables.
+  ///
+  /// If no value is found, \c nullptr is returned.
+  llvm::Value *getVar(StringRef Str);
+
+  /// Returns function type for given identifier.
+  ///
+  /// If no type is found, \c nullptr is returned.
+  llvm::FunctionType *getFuncProto(StringRef Str);
+  
+  /// Return function for given identifier.
+  llvm::Function *getFunc(StringRef Str);
+
+  /// Returns \c true, if in the current scope if a declaration associated with
+  /// given identifier.
+  bool contains(StringRef Str) const;
+
+  /// Pushes a new scope to the internal stack.
+  void push();
+
+  /// Pops current scope from the internal stack.
+  void pop();
+};
+
+} // namespace irgen
+
+} // namespace dusk
+
+#endif /* DUSK_CONTEXT_H */
diff --git a/include/dusk/IRGen/IRGenerator.h b/include/dusk/IRGen/IRGenerator.h
index ec336956903f37c2e4792101d9b64d8df359b2ba..9368eadd99458c4f223875ed4d1ac17469b41ea8 100644
--- a/include/dusk/IRGen/IRGenerator.h
+++ b/include/dusk/IRGen/IRGenerator.h
@@ -42,43 +42,17 @@ class IRGenerator : public ASTWalker {
   llvm::LLVMContext Context;
   llvm::IRBuilder<> Builder;
   std::unique_ptr<llvm::Module> Module;
+  
+  
 
 public:
   IRGenerator(DiagnosticEngine &Diag);
   ~IRGenerator();
   
-  void gen(ModuleDecl *Module);
+  void gen(ModuleDecl *Module) {}
   
 private:
-  
-  
-  llvm::Value *codeGen(Expr *E) {
-    switch (E->getKind()) {
-      case ExprKind::NumberLiteral:
-        return codeGen(static_cast<NumberLiteralExpr *>(E));
-      case ExprKind::Identifier:
-        return codeGen(static_cast<IdentifierExpr *>(E));
-      case ExprKind::Paren:
-        return codeGen(static_cast<ParenExpr *>(E)->getExpr());
-      case ExprKind::Infix:
-        return codeGen(static_cast<InfixExpr *>(E));
-        //  case ExprKind::Assign:
-        //    return codeGen(static_cast<AssignExpr *>(E));
-      case ExprKind::Prefix:
-        return codeGen(static_cast<PrefixExpr *>(E));
-      case ExprKind::Call:
-        return codeGen(static_cast<CallExpr *>(E));
-      default:
-        llvm_unreachable("Unsupported expression");
-    }
-  }
-  
-  llvm::Function *wrapTopLevelExpr(llvm::Value *Val);
-  llvm::Value *codeGen(NumberLiteralExpr *E);
-  llvm::Value *codeGen(IdentifierExpr *E);
-  llvm::Value *codeGen(InfixExpr *E);
-  llvm::Value *codeGen(PrefixExpr *E);
-  llvm::Value *codeGen(CallExpr *E);
+    
 };
 
 } // namespace ir
diff --git a/include/dusk/IRGen/Scope.h b/include/dusk/IRGen/Scope.h
deleted file mode 100644
index d6a310706755c9ab1343d9a03940398bf4956a72..0000000000000000000000000000000000000000
--- a/include/dusk/IRGen/Scope.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//===--- Scope.h - Dusck scope interface ------------------------*- C++ -*-===//
-//
-//                                 dusk-lang
-// This source file is part of a dusk-lang project, which is a semestral
-// assignement for BI-PJP course at Czech Technical University in Prague.
-// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Dusk scope interaface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef DUSK_SCOPE_H
-#define DUSK_SCOPE_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/IR/Value.h"
-
-namespace dusk {
-  
-namespace irgen {
-
-enum struct EntryKind {
-  Var,
-  Const,
-  Func
-};
-  
-struct ScopeEntry {
-  EntryKind Kind;
-  llvm::StringRef ID;
-  llvm::Value *Value;
-};
-  
-/// RAII object for changing the scope.
-class ScopeChange {
-  
-};
-  
-/// Creates a linked list of storage objects, each representing a single layer
-/// of declarations. If an entry is not found withing a given scope storage,
-/// the call is forwared to its parent.
-class ScopeStorage {
-  ScopeStorage *Parent;
-  llvm::StringMap<ScopeEntry> Entries;
-  friend class ScopeStorage;
-  
-public:
-  ScopeEntry *get(llvm::StringRef Str);
-};
-  
-class Scope {
-  friend class ScopeStorage;
-  ScopeStorage *Storage;
-  unsigned Depth;
-  
-public:
-  ScopeEntry *getEntry(llvm::StringRef Str);
-  
-};
-  
-} // namespace irgen
-  
-} // namespace dusk
-
-#endif /* DUSK_SCOPE_H */
diff --git a/include/dusk/Parse/Lexer.h b/include/dusk/Parse/Lexer.h
index 8b2dc6fb3a15b9b0aa01414c0bd55c16a9ad2b5f..5dd8f3fc6f7c212e7883e930d2ec1726ad4fe0a1 100644
--- a/include/dusk/Parse/Lexer.h
+++ b/include/dusk/Parse/Lexer.h
@@ -65,7 +65,7 @@ public:
 
   /// Sets the state (position) of the lexer. The position can be either
   /// a location before or after the current location.
-  void setState(llvm::SMLoc Loc) {
+  void setState(SMLoc Loc) {
     assert(Loc.isValid());
     CurPtr = Loc.getPointer();
     lexToken();
@@ -84,11 +84,11 @@ public:
   ///
   /// \return \c tok::identifier, if the string does not match any keyword,
   ///   otherwise approriate \c tok::... token type.
-  static tok kindOfIdentifier(llvm::StringRef Str);
+  static tok kindOfIdentifier(StringRef Str);
 
   /// Returns a location for given \c Ptr.
-  static llvm::SMLoc getSourceLoc(const char *Ptr) {
-    return llvm::SMLoc::getFromPointer(Ptr);
+  static SMLoc getSourceLoc(const char *Ptr) {
+    return SMLoc::getFromPointer(Ptr);
   }
 
   /// \brief Retrieve a Token, which starts at location \c Loc.
@@ -97,7 +97,7 @@ public:
   ///
   /// \param Loc The source location at which the token starts. The location
   ///  must be from provided source manager.
-  static Token getTokenAtLocation(const llvm::SourceMgr &SM, llvm::SMLoc Loc);
+  static Token getTokenAtLocation(const llvm::SourceMgr &SM, SMLoc Loc);
 
   /// \brief Retrieve a location that points one character pass the end
   ///  of the Token referenced by the \c Loc.
@@ -105,21 +105,17 @@ public:
   /// \param SM A \c SourceMgr instance, which provides the buffer context.
   ///
   /// \param Loc Location of the beginning of the token.
-  static llvm::SMLoc getLocForEndOfToken(const llvm::SourceMgr &SM,
-                                         llvm::SMLoc Loc);
+  static SMLoc getLocForEndOfToken(const llvm::SourceMgr &SM, SMLoc Loc);
 
   /// Retrieve a location for the start of the line referenced by the \c Loc.
-  static llvm::SMLoc getLocForStartOfLine(const llvm::SourceMgr &SM,
-                                          llvm::SMLoc Loc);
+  static SMLoc getLocForStartOfLine(const llvm::SourceMgr &SM, SMLoc Loc);
 
   /// Retrieve a location for end of line (start of next line) referenced
   /// by the \c Loc.
-  static llvm::SMLoc getLocForEndOfLine(const llvm::SourceMgr &SM,
-                                        llvm::SMLoc Loc);
+  static SMLoc getLocForEndOfLine(const llvm::SourceMgr &SM, SMLoc Loc);
 
   /// Retrive a line in the source code referenced by the \c Loc.
-  static llvm::StringRef getLineForLoc(const llvm::SourceMgr &SM,
-                                       llvm::SMLoc Loc);
+  static StringRef getLineForLoc(const llvm::SourceMgr &SM, SMLoc Loc);
 
 private: // MARK: - Private interface
   void skipToEndOfLine(bool ConsumeNewline);
@@ -146,3 +142,4 @@ private: // MARK: - Private interface
 } // namespace dusk
 
 #endif /* DUSK_LEXER_H */
+
diff --git a/include/dusk/Parse/Parser.h b/include/dusk/Parse/Parser.h
index bd008e6d2dab3a8146e6ad86ddf701147286b5ab..f9ef38097996dbf087b26eca28fd17b9f8874631 100644
--- a/include/dusk/Parse/Parser.h
+++ b/include/dusk/Parse/Parser.h
@@ -43,7 +43,7 @@ class Parser {
   Token Tok;
 
   /// Location of previous token
-  llvm::SMLoc PreviousLoc;
+  SMLoc PreviousLoc;
 
 public:
   Parser(llvm::SourceMgr &SM, InputFile &SF, DiagnosticEngine &Engine,
@@ -55,10 +55,10 @@ public:
   const Token &peekToken() const;
 
   /// Consumes current token and returns it's location.
-  llvm::SMLoc consumeToken();
+  SMLoc consumeToken();
 
   /// Consumes token if and only if the token kind is the same as specified.
-  llvm::SMLoc consumeToken(tok T);
+  SMLoc consumeToken(tok T);
 
   /// Consumes token, if it's of expected type
   ///
@@ -74,7 +74,7 @@ public:
   /// Force immediate termination of parsing.
   void terminateParsing() { Tok.setKind(tok::eof); }
 
-  DiagnosticRef diagnose(llvm::SMLoc Loc,
+  DiagnosticRef diagnose(SMLoc Loc,
                          diag::DiagID ID = diag::DiagID::unexpected_token);
 
   /// Main parsing method.
@@ -156,11 +156,11 @@ private:
   // MARK: - Patterns
 
   Pattern *parseExprPattern();
-  llvm::SmallVector<Expr *, 128> parseExprPatternBody();
+  SmallVector<Expr *, 128> parseExprPatternBody();
   Expr *parseExprPatternItem();
 
   Pattern *parseVarPattern();
-  llvm::SmallVector<Decl *, 128> parseVarPatternBody();
+  SmallVector<Decl *, 128> parseVarPatternBody();
   Decl *parseVarPatternItem();
 
   Pattern *parseSubscriptPattern();
@@ -176,3 +176,4 @@ private:
 } // namespace dusk
 
 #endif /* DUSK_PARSER_H */
+
diff --git a/include/dusk/Parse/Token.h b/include/dusk/Parse/Token.h
index 21da34e56ef9564609673548c666f41245411028..f8a8e11f362a8e9d380b337a3cba304d66e82820 100644
--- a/include/dusk/Parse/Token.h
+++ b/include/dusk/Parse/Token.h
@@ -10,6 +10,7 @@
 #ifndef DUSK_TOKEN_H
 #define DUSK_TOKEN_H
 
+#include "dusk/Basic/LLVM.h"
 #include "dusk/Parse/TokenDefinition.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/SMLoc.h"
@@ -22,15 +23,15 @@ class Token {
   tok Kind = tok::unknown;
 
   /// The actual text representation in source buffer.
-  llvm::StringRef Text;
+  StringRef Text;
 
 public:
   Token() = default;
-  Token(tok Kind, llvm::StringRef Text) : Kind(Kind), Text(Text) {}
+  Token(tok Kind, StringRef Text) : Kind(Kind), Text(Text) {}
 
   // MARK: - Setting token properties
 
-  void setToken(tok K, llvm::StringRef T) {
+  void setToken(tok K, StringRef T) {
     Kind = K;
     Text = T;
   }
@@ -40,17 +41,15 @@ public:
   // MARK: - Getting token properties
   tok getKind() const { return Kind; }
 
-  llvm::StringRef getText() const { return Text; }
+  StringRef getText() const { return Text; }
 
   unsigned getLength() const { return Text.size(); }
 
-  llvm::SMLoc getLoc() const {
-    return llvm::SMLoc::getFromPointer(Text.begin());
-  }
+  SMLoc getLoc() const { return SMLoc::getFromPointer(Text.begin()); }
 
-  llvm::SMRange getRange() const {
+  SMRange getRange() const {
     auto E = getLoc().getPointer() + getLength();
-    return {getLoc(), llvm::SMLoc::getFromPointer(E)};
+    return {getLoc(), SMLoc::getFromPointer(E)};
   }
 
   // MARK: - Token predicates
diff --git a/include/dusk/Parse/TokenDefinition.h b/include/dusk/Parse/TokenDefinition.h
index fbeb2c45282b369b2ea5b0bc9ba703fc9432aa5a..e0671aaf8162ccf86ce75dee3b90ff9043757ccb 100644
--- a/include/dusk/Parse/TokenDefinition.h
+++ b/include/dusk/Parse/TokenDefinition.h
@@ -84,8 +84,7 @@ enum struct tok {
 } // namespace dusk
 
 namespace llvm {
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
-                                     const dusk::tok &T) {
+inline raw_ostream &operator<<(raw_ostream &OS, const dusk::tok &T) {
   switch (T) {
   // Keywords
   case dusk::tok::kwVar:
@@ -169,7 +168,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
   }
   return OS;
 }
-  
+
 } // namespace llvm
 
 #endif /* DUSK_TOKEN_DEFINITION_H */
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 0706388bdfe60b64611c1c7baf408bf91b277012..0b890508f15429289fa77ae5dbbbdf551e5b0ddf 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -86,7 +86,7 @@ public:
   bool visit(NumberLiteralExpr *E) {
     auto St = E->getLocStart().getPointer();
     auto En = E->getLocEnd().getPointer();
-    llvm::StringRef Str = {St, (size_t)(En - St)};
+    StringRef Str = {St, (size_t)(En - St)};
     Printer << Str;
     return true;
   }
@@ -369,27 +369,27 @@ Indentation::Indentation(unsigned SL) : Indentation(IndKind::Space, SL) {}
 
 Indentation::Indentation(IndKind K, unsigned SL) : Kind(K), SpaceLen(SL) {}
 
-llvm::StringRef Indentation::getIndent() const {
-  llvm::SmallString<MAX_SPACE_LEN * MAX_INDENTATION> Str;
+StringRef Indentation::getIndent() const {
+  SmallString<MAX_SPACE_LEN * MAX_INDENTATION> Str;
   for (unsigned i = 0; i < Depth; i++)
     Str += getIndentBlock();
   return Str;
 }
 
-llvm::StringRef Indentation::getSpaceIndent() const {
+StringRef Indentation::getSpaceIndent() const {
   assert(Kind == IndKind::Space && "Invalid indentation.");
-  llvm::SmallString<MAX_SPACE_LEN> Str;
+  SmallString<MAX_SPACE_LEN> Str;
   for (unsigned i = 0; i < SpaceLen; i++)
     Str += " ";
   return Str;
 }
 
-llvm::StringRef Indentation::getTabIndent() const {
+StringRef Indentation::getTabIndent() const {
   assert(Kind == IndKind::Space && "Invalid indentation.");
   return "\t";
 }
 
-llvm::StringRef Indentation::getIndentBlock() const {
+StringRef Indentation::getIndentBlock() const {
   if (Kind == IndKind::Space)
     return getSpaceIndent();
   else
@@ -420,20 +420,20 @@ void ASTPrinter::printNewline() {
   printText(Newline);
 }
 
-void ASTPrinter::printSeparator(bool &IsFirst, llvm::StringRef S) {
+void ASTPrinter::printSeparator(bool &IsFirst, StringRef S) {
   if (IsFirst)
     IsFirst = false;
   else
     printText(S);
 }
 
-ASTPrinter &ASTPrinter::operator<<(llvm::StringRef Text) {
+ASTPrinter &ASTPrinter::operator<<(StringRef Text) {
   print(Text);
   return *this;
 }
 
 ASTPrinter &ASTPrinter::operator<<(uint64_t N) {
-  llvm::SmallString<32> Str;
+  SmallString<32> Str;
   llvm::raw_svector_ostream OS(Str);
   OS << N;
   print(OS.str());
@@ -441,7 +441,7 @@ ASTPrinter &ASTPrinter::operator<<(uint64_t N) {
 }
 
 ASTPrinter &ASTPrinter::operator<<(tok T) {
-  llvm::SmallString<16> Buffer;
+  SmallString<16> Buffer;
   llvm::raw_svector_ostream OS(Buffer);
   OS << T;
   print(OS.str());
@@ -460,9 +460,9 @@ ASTPrinter &ASTPrinter::operator--() {
   return *this;
 }
 
-void ASTPrinter::printKeyword(llvm::StringRef KW) { *this << KW; }
+void ASTPrinter::printKeyword(StringRef KW) { *this << KW; }
 
-void ASTPrinter::print(llvm::StringRef Text) {
+void ASTPrinter::print(StringRef Text) {
   if (isAtStartOfLine())
     printIndent();
   printText(Text);
@@ -470,13 +470,13 @@ void ASTPrinter::print(llvm::StringRef Text) {
 
 // MARK: - StreamPrinter
 
-StreamPrinter::StreamPrinter(llvm::raw_ostream &OS) : OS(OS) {}
+StreamPrinter::StreamPrinter(raw_ostream &OS) : OS(OS) {}
 
-void StreamPrinter::printText(llvm::StringRef Text) { OS << Text; }
+void StreamPrinter::printText(StringRef Text) { OS << Text; }
 
 // MARK: - Formatter
 
-void Formatter::format(ASTNode *N, llvm::raw_ostream &OS) {
+void Formatter::format(ASTNode *N, raw_ostream &OS) {
   PrettyPrinter pp(OS);
   PrintAST p(pp);
   p.ASTVisitor::visit(N);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 68f3bb8d010e83f2b56e74b1ec854cb32a532360..ba02233839aba68135aafb3ab430030ed33cabe6 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -16,8 +16,7 @@ using namespace dusk;
 
 // MARK: - Decl class
 
-Decl::Decl(DeclKind K, llvm::StringRef N, llvm::SMLoc NL)
-    : Kind(K), Name(N), NameLoc(NL) {}
+Decl::Decl(DeclKind K, StringRef N, SMLoc NL) : Kind(K), Name(N), NameLoc(NL) {}
 
 bool Decl::isValDecl() const {
   switch (Kind) {
@@ -30,59 +29,55 @@ bool Decl::isValDecl() const {
   }
 }
 
-llvm::SMRange Decl::getSourceRange() const {
+SMRange Decl::getSourceRange() const {
   auto EndLoc = Name.data() + Name.size();
-  return {NameLoc, llvm::SMLoc::getFromPointer(EndLoc)};
+  return {NameLoc, SMLoc::getFromPointer(EndLoc)};
 }
 
 // MARK: - ValDecl class
 
-ValDecl::ValDecl(DeclKind K, llvm::StringRef N, llvm::SMLoc NL, Expr *E)
+ValDecl::ValDecl(DeclKind K, StringRef N, SMLoc NL, Expr *E)
     : Decl(K, N, NL), Value(E) {}
 
 // MARK: - VarDecl class
 
-VarDecl::VarDecl(llvm::StringRef N, llvm::SMLoc NL, llvm::SMLoc VarL, Expr *V)
+VarDecl::VarDecl(StringRef N, SMLoc NL, SMLoc VarL, Expr *V)
     : ValDecl(DeclKind::Var, N, NL, V), VarLoc(VarL) {}
 
-llvm::SMRange VarDecl::getSourceRange() const {
+SMRange VarDecl::getSourceRange() const {
   return {VarLoc, getValue()->getLocEnd()};
 }
 
 // MARK: - ConstDecl class
 
-ConstDecl::ConstDecl(llvm::StringRef N, llvm::SMLoc NL, llvm::SMLoc ConstL,
-                     Expr *V)
+ConstDecl::ConstDecl(StringRef N, SMLoc NL, SMLoc ConstL, Expr *V)
     : ValDecl(DeclKind::Const, N, NL, V), ConstLoc(ConstL) {}
 
-llvm::SMRange ConstDecl::getSourceRange() const {
+SMRange ConstDecl::getSourceRange() const {
   return {ConstLoc, getValue()->getLocEnd()};
 }
 
 // MARK: - ParamDecl class
 
-ParamDecl::ParamDecl(llvm::StringRef N, llvm::SMLoc NL)
-    : Decl(DeclKind::Param, N, NL) {}
+ParamDecl::ParamDecl(StringRef N, SMLoc NL) : Decl(DeclKind::Param, N, NL) {}
 
 // MARK: - FuncDecl class
 
-FuncDecl::FuncDecl(llvm::StringRef N, llvm::SMLoc NL, llvm::SMLoc FuncL,
-                   Pattern *A)
+FuncDecl::FuncDecl(StringRef N, SMLoc NL, SMLoc FuncL, VarPattern *A)
     : Decl(DeclKind::Func, N, NL), FuncLoc(FuncL), Params(A) {}
 
-llvm::SMRange FuncDecl::getSourceRange() const {
+SMRange FuncDecl::getSourceRange() const {
   return {FuncLoc, Params->getLocEnd()};
 }
 
 // MARK: - Module declaration
 
-ModuleDecl::ModuleDecl(llvm::StringRef N, std::vector<ASTNode *> &&C)
-    : Decl(DeclKind::Module, N, llvm::SMLoc()), Contents(C) {}
+ModuleDecl::ModuleDecl(StringRef N, std::vector<ASTNode *> &&C)
+    : Decl(DeclKind::Module, N, SMLoc()), Contents(C) {}
 
-llvm::SMRange ModuleDecl::getSourceRange() const {
+SMRange ModuleDecl::getSourceRange() const {
   if (Contents.size() > 0) {
     return {Contents.front()->getLocStart(), Contents.back()->getLocEnd()};
   }
-  return llvm::SMRange();
+  return SMRange();
 }
-
diff --git a/lib/AST/Diagnostics.cpp b/lib/AST/Diagnostics.cpp
index 02430fed4a65fc08b9e48d3db5ec984b11970169..3e12ad76e3ceb261260ea6826afe7704b39e2ac1 100644
--- a/lib/AST/Diagnostics.cpp
+++ b/lib/AST/Diagnostics.cpp
@@ -26,7 +26,7 @@ void DiagnosticRef::flush() {
     Engine->flushActiveDiag();
 }
 
-DiagnosticRef &DiagnosticRef::fixIt(llvm::StringRef FixIt, llvm::SMLoc Loc) {
+DiagnosticRef &DiagnosticRef::fixIt(StringRef FixIt, SMLoc Loc) {
   // Verify that the referenced diagnostic is till active.
   assert(IsActive && "Cannot modify inactive diagnostic.");
   // Add location iff there is an engine and the location is valid.
@@ -35,8 +35,7 @@ DiagnosticRef &DiagnosticRef::fixIt(llvm::StringRef FixIt, llvm::SMLoc Loc) {
   return *this;
 }
 
-DiagnosticRef &DiagnosticRef::fixItBefore(llvm::StringRef FixIt,
-                                          llvm::SMLoc Loc) {
+DiagnosticRef &DiagnosticRef::fixItBefore(StringRef FixIt, SMLoc Loc) {
   // Add location iff there is an engine and the location is valid.
   if (Engine && Loc.isValid()) {
     auto T = Lexer::getTokenAtLocation(Engine->SourceManager, Loc);
@@ -46,8 +45,7 @@ DiagnosticRef &DiagnosticRef::fixItBefore(llvm::StringRef FixIt,
   return *this;
 }
 
-DiagnosticRef &DiagnosticRef::fixItAfter(llvm::StringRef FixIt,
-                                         llvm::SMLoc Loc) {
+DiagnosticRef &DiagnosticRef::fixItAfter(StringRef FixIt, SMLoc Loc) {
   // Add location iff there is an engine and the location is valid.
   if (Engine && Loc.isValid()) {
     auto L = Lexer::getLocForEndOfToken(Engine->SourceManager, Loc);
@@ -72,8 +70,8 @@ void DiagnosticEngine::emitDiagnostic(const Diagnostic &Diag) {
   auto K = llvm::SourceMgr::DiagKind::DK_Error;
   auto Line = Lexer::getLineForLoc(SourceManager, Loc);
   auto Msg = diag::getTextForID(Diag.getID());
-  auto D = llvm::SMDiagnostic(SourceManager, Loc, FN, L, C, K, Msg, Line,
-                              llvm::None, Diag.getFixIts());
+  auto D = SMDiagnostic(SourceManager, Loc, FN, L, C, K, Msg, Line, llvm::None,
+                        Diag.getFixIts());
 
   for (auto C : Consumers) {
     C->consume(D);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 74c4f5f1d619b1de83d3c258cfb268f7f55bda86..5f37462c5b05fafe8544c56031b42bc2b445366b 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -16,34 +16,34 @@ using namespace dusk;
 
 // MARK: - Number literal expresssion
 
-NumberLiteralExpr::NumberLiteralExpr(int V, llvm::SMRange ValL)
+NumberLiteralExpr::NumberLiteralExpr(int V, SMRange ValL)
     : Expr(ExprKind::NumberLiteral), Value(V), ValueLoc(ValL) {}
 
-llvm::SMRange NumberLiteralExpr::getSourceRange() const { return ValueLoc; }
+SMRange NumberLiteralExpr::getSourceRange() const { return ValueLoc; }
 
 // MARK: - Identifier expression
 
-IdentifierExpr::IdentifierExpr(llvm::StringRef N, llvm::SMLoc L)
+IdentifierExpr::IdentifierExpr(StringRef N, SMLoc L)
     : Expr(ExprKind::Identifier), Name(N), NameLoc(L) {}
 
-llvm::SMRange IdentifierExpr::getSourceRange() const {
-  auto E = llvm::SMLoc::getFromPointer(Name.data() + Name.size());
+SMRange IdentifierExpr::getSourceRange() const {
+  auto E = SMLoc::getFromPointer(Name.data() + Name.size());
   return {NameLoc, E};
 }
 
 // MARK: - Parenthesis expression
 
-ParenExpr::ParenExpr(Expr *E, llvm::SMLoc L, llvm::SMLoc R)
+ParenExpr::ParenExpr(Expr *E, SMLoc L, SMLoc R)
     : Expr(ExprKind::Paren), Expression(E), LPar(L), RPar(R) {}
 
-llvm::SMRange ParenExpr::getSourceRange() const { return {LPar, RPar}; }
+SMRange ParenExpr::getSourceRange() const { return {LPar, RPar}; }
 
 // MARK: - Infix expression
 
 InfixExpr::InfixExpr(Expr *L, Expr *R, Token O)
     : Expr(ExprKind::Infix), LHS(L), RHS(R), Op(O) {}
 
-llvm::SMRange InfixExpr::getSourceRange() const {
+SMRange InfixExpr::getSourceRange() const {
   return {LHS->getLocStart(), RHS->getLocEnd()};
 }
 
@@ -52,7 +52,7 @@ llvm::SMRange InfixExpr::getSourceRange() const {
 AssignExpr::AssignExpr(Expr *L, Expr *R)
     : Expr(ExprKind::Assign), Dest(L), Source(R) {}
 
-llvm::SMRange AssignExpr::getSourceRange() const {
+SMRange AssignExpr::getSourceRange() const {
   return {Dest->getLocStart(), Source->getLocEnd()};
 }
 
@@ -61,7 +61,7 @@ llvm::SMRange AssignExpr::getSourceRange() const {
 PrefixExpr::PrefixExpr(Expr *D, Token O)
     : Expr(ExprKind::Prefix), Dest(D), Op(O) {}
 
-llvm::SMRange PrefixExpr::getSourceRange() const {
+SMRange PrefixExpr::getSourceRange() const {
   return {Op.getLoc(), Dest->getLocEnd()};
 }
 
@@ -70,7 +70,7 @@ llvm::SMRange PrefixExpr::getSourceRange() const {
 CallExpr::CallExpr(Expr *C, Pattern *A)
     : Expr(ExprKind::Call), Callee(C), Args(A) {}
 
-llvm::SMRange CallExpr::getSourceRange() const {
+SMRange CallExpr::getSourceRange() const {
   return {Callee->getLocStart(), Args->getLocEnd()};
 }
 
@@ -79,6 +79,6 @@ llvm::SMRange CallExpr::getSourceRange() const {
 SubscriptExpr::SubscriptExpr(Expr *B, Pattern *S)
     : Expr(ExprKind::Subscript), Base(B), Subscript(S) {}
 
-llvm::SMRange SubscriptExpr::getSourceRange() const {
+SMRange SubscriptExpr::getSourceRange() const {
   return {Base->getLocStart(), Subscript->getLocEnd()};
 }
diff --git a/lib/AST/Pattern.cpp b/lib/AST/Pattern.cpp
index d9246631aa149d3818aac722d5d7211c83e52458..9357e408b2b4f9f9759550b225f5c118d6e853bc 100644
--- a/lib/AST/Pattern.cpp
+++ b/lib/AST/Pattern.cpp
@@ -20,25 +20,24 @@ Pattern::Pattern(PatternKind K) : Kind(K) {}
 
 // MARK: - Expression pattern
 
-ExprPattern::ExprPattern(llvm::SmallVector<Expr *, 128> &&V, llvm::SMLoc L,
-                         llvm::SMLoc R)
+ExprPattern::ExprPattern(SmallVector<Expr *, 128> &&V, SMLoc L, SMLoc R)
     : Pattern(PatternKind::Expr), Values(V), LPar(L), RPar(R) {}
 
-llvm::SMRange ExprPattern::getSourceRange() const { return {LPar, RPar}; }
+SMRange ExprPattern::getSourceRange() const { return {LPar, RPar}; }
+size_t ExprPattern::count() const { return Values.size(); }
 
 // MARK: - Variable pattern
 
-VarPattern::VarPattern(llvm::SmallVector<Decl *, 128> &&V, llvm::SMLoc L,
-                       llvm::SMLoc R)
+VarPattern::VarPattern(SmallVector<Decl *, 128> &&V, SMLoc L, SMLoc R)
     : Pattern(PatternKind::Variable), Vars(V), LPar(L), RPar(R) {}
 
-llvm::SMRange VarPattern::getSourceRange() const { return {LPar, RPar}; }
+SMRange VarPattern::getSourceRange() const { return {LPar, RPar}; }
+size_t VarPattern::count() const { return Vars.size(); }
 
 // MARK: - Subscript pattern
 
-SubscriptPattern::SubscriptPattern(Expr *V, llvm::SMLoc L, llvm::SMLoc R)
+SubscriptPattern::SubscriptPattern(Expr *V, SMLoc L, SMLoc R)
     : Pattern(PatternKind::Subscript), Value(V), LBracet(L), RBracet(R) {}
 
-llvm::SMRange SubscriptPattern::getSourceRange() const {
-  return {LBracet, RBracet};
-}
+SMRange SubscriptPattern::getSourceRange() const { return {LBracet, RBracet}; }
+size_t SubscriptPattern::count() const { return 1; }
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index bc2f740454fa1079ffb7b080f99bbb3cd6a74616..48c69f6f74ebe41be3d77758b37264ed757736ba 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -16,16 +16,16 @@ using namespace dusk;
 
 // MARK: - Break statement
 
-BreakStmt::BreakStmt(llvm::SMRange BL) : Stmt(StmtKind::Break), BreakLoc(BL) {}
+BreakStmt::BreakStmt(SMRange BL) : Stmt(StmtKind::Break), BreakLoc(BL) {}
 
-llvm::SMRange BreakStmt::getSourceRange() const { return BreakLoc; }
+SMRange BreakStmt::getSourceRange() const { return BreakLoc; }
 
 // MARK: - Return statement
 
-ReturnStmt::ReturnStmt(llvm::SMLoc RL, Expr *V)
+ReturnStmt::ReturnStmt(SMLoc RL, Expr *V)
     : Stmt(StmtKind::Return), RetLoc(RL), Value(V) {}
 
-llvm::SMRange ReturnStmt::getSourceRange() const {
+SMRange ReturnStmt::getSourceRange() const {
   return {RetLoc, Value->getLocEnd()};
 }
 
@@ -36,52 +36,48 @@ RangeStmt::RangeStmt(Expr *S, Expr *E, Token O)
 
 bool RangeStmt::isInclusive() const { return Op.is(tok::elipsis_incl); }
 
-llvm::SMRange RangeStmt::getSourceRange() const {
+SMRange RangeStmt::getSourceRange() const {
   return {Start->getLocStart(), End->getLocEnd()};
 }
 
 // MARK: - Block statement
 
-BlockStmt::BlockStmt(llvm::SMLoc S, llvm::SMLoc E, std::vector<ASTNode *> &&N)
+BlockStmt::BlockStmt(SMLoc S, SMLoc E, std::vector<ASTNode *> &&N)
     : Stmt(StmtKind::Block), BlockStart(S), BlockEnd(E), Nodes(N) {}
 
-llvm::SMRange BlockStmt::getSourceRange() const {
-  return {BlockStart, BlockEnd};
-}
+SMRange BlockStmt::getSourceRange() const { return {BlockStart, BlockEnd}; }
 
 // MARK: - Funcion statement
 
 FuncStmt::FuncStmt(Decl *FP, Stmt *B)
     : Stmt(StmtKind::Func), Prototype(FP), Body(B) {}
 
-llvm::SMRange FuncStmt::getSourceRange() const {
+SMRange FuncStmt::getSourceRange() const {
   return {Prototype->getLocStart(), Body->getLocEnd()};
 }
 
 // MARK: Fot-in statement
 
-ForStmt::ForStmt(llvm::SMLoc FL, Expr *V, Stmt *R, Stmt *B)
+ForStmt::ForStmt(SMLoc FL, Expr *V, Stmt *R, Stmt *B)
     : Stmt(StmtKind::For), ForLoc(FL), Var(V), Range(R), Body(B) {}
 
-llvm::SMRange ForStmt::getSourceRange() const {
-  return {ForLoc, Body->getLocEnd()};
-}
+SMRange ForStmt::getSourceRange() const { return {ForLoc, Body->getLocEnd()}; }
 
 // MARK: - While statement
 
-WhileStmt::WhileStmt(llvm::SMLoc WL, Expr *C, Stmt *B)
+WhileStmt::WhileStmt(SMLoc WL, Expr *C, Stmt *B)
     : Stmt(StmtKind::While), WhileLoc(WL), Cond(C), Body(B) {}
 
-llvm::SMRange WhileStmt::getSourceRange() const {
+SMRange WhileStmt::getSourceRange() const {
   return {WhileLoc, Body->getLocEnd()};
 }
 
 // MARK: - If statement
 
-IfStmt::IfStmt(llvm::SMLoc IL, Expr *C, Stmt *T, Stmt *E)
+IfStmt::IfStmt(SMLoc IL, Expr *C, Stmt *T, Stmt *E)
     : Stmt(StmtKind::If), IfLoc(IL), Cond(C), Then(T), Else(E) {}
 
-llvm::SMRange IfStmt::getSourceRange() const {
+SMRange IfStmt::getSourceRange() const {
   if (Else != nullptr)
     return {IfLoc, Else->getLocEnd()};
   else
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ebe0fc733fe64d354a4fe5f4f074c50e99f2ea0d 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(SOURCE
+    ${CMAKE_CURRENT_SOURCE_DIR}/SourceManager.cpp
+    ${SOURCE}
+    PARENT_SCOPE
+)
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5c26f7b0d785d80fd374021d4a5fca3b0de29b93
--- /dev/null
+++ b/lib/Basic/SourceManager.cpp
@@ -0,0 +1,25 @@
+//===--- SourceManager.cpp ------------------------------------------------===//
+//
+//                                 dusk-lang
+// This source file is part of a dusk-lang project, which is a semestral
+// assignement for BI-PJP course at Czech Technical University in Prague.
+// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dusk/Basic/SourceManager.h"
+
+using namespace dusk;
+
+unsigned dusk::getBufferForLoc(const llvm::SourceMgr &SM, SMLoc Loc) {
+  // Validate location
+  assert(Loc.isValid());
+  
+  auto ptr = Loc.getPointer();
+  for (unsigned i = 1; i <= SM.getNumBuffers(); i++) {
+    auto Buff = SM.getMemoryBuffer(i);
+    if (ptr >= Buff->getBufferStart() && ptr <= Buff->getBufferEnd())
+      return i;
+  }
+  llvm_unreachable("Location in non-existing buffer.");
+}
diff --git a/lib/Frontend/Compiler.cpp b/lib/Frontend/Compiler.cpp
index 00abdcc3ac16ac6da7238bc8009545619db0fd81..575c554d6e47d3b5e9e1330bdcdfec888eabede7 100644
--- a/lib/Frontend/Compiler.cpp
+++ b/lib/Frontend/Compiler.cpp
@@ -11,8 +11,8 @@
 
 using namespace dusk;
 
-Compiler::Compiler(std::vector<llvm::StringRef> Filenames)
-  : Engine(SourceManager), OS(llvm::raw_os_ostream(std::cerr)) {
+Compiler::Compiler(std::vector<StringRef> Filenames)
+  : Engine(SourceManager), OS(raw_os_ostream(std::cerr)) {
   Engine.addConsumer(this);
   for (auto &F : Filenames) {
     auto File = std::make_unique<InputFile>(SourceManager, F);
@@ -22,7 +22,7 @@ Compiler::Compiler(std::vector<llvm::StringRef> Filenames)
 
 void Compiler::Compile() {
   Formatter F;
-  llvm::raw_os_ostream OS(std::cout);
+  raw_os_ostream OS(std::cout);
   std::vector<ParserResult> Results;
 
   for (auto &&File : InputFiles) {
diff --git a/lib/Frontend/InputFile.cpp b/lib/Frontend/InputFile.cpp
index 8455e7b957708f71ce8c0a7dff7e47301c69ddfd..f5567c08ba2b2171beb4b02ddbb5e52f60e2cb63 100644
--- a/lib/Frontend/InputFile.cpp
+++ b/lib/Frontend/InputFile.cpp
@@ -2,13 +2,13 @@
 
 using namespace dusk;
 
-InputFile::InputFile(llvm::SourceMgr &SM, const llvm::StringRef F)
+InputFile::InputFile(llvm::SourceMgr &SM, const StringRef F)
     : Filename(F), SourceManager(SM) {
   assert(!Filename.empty() && "Filename must not be an empty string.");
 
   if (auto Res = llvm::MemoryBuffer::getFile(Filename)) {
     auto B = std::move(*Res);
-    auto L = llvm::SMLoc::getFromPointer(B->getBufferStart());
+    auto L = SMLoc::getFromPointer(B->getBufferStart());
     Buffer = B.get();
     BufferID = SourceManager.AddNewSourceBuffer(std::move(B), L);
 
diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt
index bfb0f3d49189930c775941494db71169cadc4417..6b115e3f8579fe89c634904a1fbf6a70c81b6e2d 100644
--- a/lib/IRGen/CMakeLists.txt
+++ b/lib/IRGen/CMakeLists.txt
@@ -1,8 +1,10 @@
 set(SOURCE
+    ${CMAKE_CURRENT_SOURCE_DIR}/Context.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/GenExpr.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/GenExpr.h
     ${CMAKE_CURRENT_SOURCE_DIR}/IRGenerator.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/Scope.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.h
     ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.h
     ${SOURCE}
     PARENT_SCOPE
 )
diff --git a/lib/IRGen/Context.cpp b/lib/IRGen/Context.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d0dbd25ae6fd3180e37bf0a01c235aa27209647
--- /dev/null
+++ b/lib/IRGen/Context.cpp
@@ -0,0 +1,144 @@
+
+//===--- Context.cpp - Dusck context implementation -----------------------===//
+//
+//                                 dusk-lang
+// This source file is part of a dusk-lang project, which is a semestral
+// assignement for BI-PJP course at Czech Technical University in Prague.
+// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Dusk context implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dusk/IRGen/Context.h"
+#include "dusk/AST/Decl.h"
+#include "dusk/AST/Pattern.h"
+#include <vector>
+
+using namespace dusk;
+using namespace irgen;
+
+// MARK: - Context values
+
+ContextVals::ContextVals(ContextVals *P) : Parent(P) {}
+
+ContextVals *ContextVals::push() { return new ContextVals(this); }
+
+ContextVals *ContextVals::pop() {
+  auto Ret = Parent.release();
+  delete this;
+  return Ret;
+}
+
+bool ContextVals::isDeclared(StringRef Str) const {
+  return Vars.find(Str) != Vars.end() || Consts.find(Str) != Consts.end();
+}
+
+llvm::Value *ContextVals::getVar(StringRef Str) const {
+  auto Var = Vars.find(Str);
+  if (Var != Vars.end())
+    return Var->second;
+
+  if (Parent != nullptr)
+    return Parent->getVar(Str);
+  return nullptr;
+}
+
+llvm::Value *ContextVals::getVar(StringRef Str) {
+  auto Var = Vars.find(Str);
+  if (Var != Vars.end())
+    return Var->second;
+
+  if (Parent != nullptr)
+    return Parent->getVar(Str);
+  return nullptr;
+}
+
+llvm::Value *ContextVals::get(StringRef Str) const {
+  if (auto Var = getVar(Str))
+    return Var;
+
+  auto Const = Consts.find(Str);
+  if (Const != Consts.end())
+    return Const->second;
+
+  if (Parent != nullptr)
+    return Parent->get(Str);
+  return nullptr;
+}
+
+// MARK: - Context
+
+Context::Context(llvm::LLVMContext &C, llvm::Module *M, llvm::IRBuilder<> &B)
+    : Ctx(C), Module(M), Builder(B), Vals(new ContextVals()) {}
+
+Context::~Context() { delete Vals; }
+
+bool Context::declare(const VarDecl *D) {
+  // Check if already declared in current scope
+  if (!Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr)
+    return false;
+
+  auto Ty = llvm::Type::getInt32Ty(Ctx);
+  auto Val = Builder.CreateAlloca(Ty, 0, D->getName());
+  Vals->Vars[D->getName()] = Val;
+  return true;
+}
+
+bool Context::declare(const ConstDecl *D) {
+  // Check if already declared in current scope
+  if (!Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr)
+    return false;
+
+  auto Ty = llvm::Type::getInt32Ty(Ctx);
+  auto Val = Builder.CreateAlloca(Ty, 0, D->getName());
+  Vals->Consts[D->getName()] = Val;
+  return true;
+}
+
+bool Context::declare(const FuncDecl *Fn) {
+  // Validate that we're in global scope.
+  assert(Depth == 0 && "Function declaration must be declared in global scope");
+
+  // Check if already declared in current scope
+  if (Funcs[Fn->getName()] != nullptr)
+    return false;
+
+  auto Ty = llvm::Type::getInt32Ty(Ctx);
+  auto Args = std::vector<llvm::Type *>(Fn->getArgs()->count(), Ty);
+  auto FT = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), Args, false);
+  Funcs[Fn->getName()] = FT;
+  return true;
+}
+
+llvm::Value *Context::getVal(StringRef Str) const { return Vals->get(Str); }
+
+llvm::Value *Context::getVar(StringRef Str) { return Vals->getVar(Str); }
+
+llvm::FunctionType *Context::getFuncProto(StringRef Str) { return Funcs[Str]; }
+
+llvm::Function *Context::getFunc(StringRef Str) {
+  if (auto F = Module->getFunction(Str))
+    return F;
+  return nullptr;
+}
+
+bool Context::contains(StringRef Str) const {
+  return Funcs.find(Str) != Funcs.end() || Vals->contains(Str);
+}
+
+void Context::push() {
+  ++Depth;
+  // Update the 'virtual' stack.
+  Vals = Vals->push();
+}
+
+void Context::pop() {
+  assert(Depth != 0 && "Cannot pop from global scope");
+  --Depth;
+  // Update the 'virtual' stack.
+  Vals = Vals->pop();
+}
+
diff --git a/lib/IRGen/GenExpr.cpp b/lib/IRGen/GenExpr.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a12278b254f330f6d9dc367720ffad67bdae2d3
--- /dev/null
+++ b/lib/IRGen/GenExpr.cpp
@@ -0,0 +1,124 @@
+//===--- GenExpr.cpp ------------------------------------------------------===//
+//
+//                                 dusk-lang
+// This source file is part of a dusk-lang project, which is a semestral
+// assignement for BI-PJP course at Czech Technical University in Prague.
+// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GenExpr.h"
+
+#include "llvm/ADT/APSInt.h"
+#include "llvm/IR/Constant.h"
+#include <vector>
+
+using namespace dusk;
+using namespace irgen;
+
+GenExpr::GenExpr(Expr *R, Context &C) : Root(R), Ctx(C) {}
+
+llvm::Value *GenExpr::gen() { return codegen(Root); }
+
+llvm::Value *GenExpr::codegen(Expr *E) { return nullptr; }
+
+llvm::Value *GenExpr::codegen(NumberLiteralExpr *E) {
+  auto Value = llvm::APSInt::get(E->getValue());
+  return llvm::ConstantInt::get(Ctx, Value);
+}
+
+llvm::Value *GenExpr::codegen(IdentifierExpr *E) {
+  auto Addr = Ctx.getVal(E->getName());
+  return Ctx.getBuilder().CreateLoad(Addr, E->getName());
+}
+
+llvm::Value *GenExpr::codegen(InfixExpr *E) {
+  auto LHS = codegen(E->getLHS());
+  auto RHS = codegen(E->getRHS());
+  if (!LHS || !RHS)
+    return nullptr;
+
+  switch (E->getOp().getKind()) {
+  // Arithemtic operations
+  case tok::plus:
+    return Ctx.getBuilder().CreateAdd(LHS, RHS, "addtmp");
+  case tok::minus:
+    return Ctx.getBuilder().CreateSub(LHS, RHS, "subtmp");
+  case tok::multipy:
+    return Ctx.getBuilder().CreateMul(LHS, RHS, "multmp");
+  case tok::divide:
+    return Ctx.getBuilder().CreateSDiv(LHS, RHS, "divtmp");
+
+  // Logical operations
+  case tok::equals:
+    return Ctx.getBuilder().CreateICmpEQ(LHS, RHS, "eqtmp");
+  case tok::nequals:
+    return Ctx.getBuilder().CreateICmpNE(LHS, RHS, "neqtmp");
+  case tok::greater:
+    return Ctx.getBuilder().CreateICmpSGT(LHS, RHS, "gttmp");
+  case tok::greater_eq:
+    return Ctx.getBuilder().CreateICmpSGE(LHS, RHS, "getmp");
+  case tok::less:
+    return Ctx.getBuilder().CreateICmpSLT(LHS, RHS, "lttmp");
+  case tok::less_eq:
+    return Ctx.getBuilder().CreateICmpSLE(LHS, RHS, "letmp");
+
+  default:
+    llvm_unreachable("Invalid infix operand");
+  }
+}
+
+llvm::Value *GenExpr::codegen(PrefixExpr *E) {
+  auto Val = codegen(E->getDest());
+  if (!Val)
+    return nullptr;
+  
+  switch (E->getOp().getKind()) {
+    case tok::neg:
+      return Ctx.getBuilder().CreateNot(Val);
+      
+      // TODO: fix unary minus
+    case tok::minus:
+    default:
+      llvm_unreachable("Invalid prefix operand");
+  }
+}
+
+llvm::Value *GenExpr::codegen(AssignExpr *E) {
+  // Ensure the LHS is a identifier.
+  auto VarExpr = dynamic_cast<IdentifierExpr *>(E);
+  if (!VarExpr)
+    return nullptr;
+  
+  // Get variable address
+  auto VarAddr = Ctx.getVar(VarExpr->getName());
+  auto Val = codegen(E->getSource());
+  if (!VarAddr || !Val)
+    return nullptr;
+  
+  return Ctx.getBuilder().CreateStore(Val, VarAddr, "assign");
+}
+
+llvm::Value *GenExpr::codegen(CallExpr *E) {
+  // Ensure the callee is identifier.
+  auto CalleeID = dynamic_cast<IdentifierExpr *>(E->getCalle());
+  
+  // Ensure args is expression pattern
+  auto ArgsPttrn = dynamic_cast<ExprPattern *>(E->getArgs());
+  if (!CalleeID || !ArgsPttrn)
+    return nullptr;
+
+  // Ensure calling a declared function
+  auto Fn = Ctx.getFunc(CalleeID->getName());
+  if (!Fn)
+    return nullptr;
+
+  // Invalid number of arguments
+  if (Fn->arg_size() != ArgsPttrn->count())
+    return nullptr;
+  
+  auto Args = std::vector<llvm::Value *>(Fn->arg_size());
+  for (auto Arg : ArgsPttrn->getValues())
+    Args.push_back(codegen(Arg));
+  return Ctx.getBuilder().CreateCall(Fn, Args);
+}
diff --git a/lib/IRGen/GenExpr.h b/lib/IRGen/GenExpr.h
new file mode 100644
index 0000000000000000000000000000000000000000..520df270a08f6c21ebffb5fc18b6ed57f60321bc
--- /dev/null
+++ b/lib/IRGen/GenExpr.h
@@ -0,0 +1,50 @@
+//===--- GenExpr.h - Dusk IR expresssion generation -------------*- C++ -*-===//
+//
+//                                 dusk-lang
+// This source file is part of a dusk-lang project, which is a semestral
+// assignement for BI-PJP course at Czech Technical University in Prague.
+// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DUSK_GEN_EXPR_H
+#define DUSK_GEN_EXPR_H
+
+#include "dusk/AST/Decl.h"
+#include "dusk/AST/Expr.h"
+#include "dusk/AST/Stmt.h"
+#include "dusk/AST/Pattern.h"
+#include "dusk/IRGen/Context.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Value.h"
+#include "llvm/IR/LLVMContext.h"
+
+namespace dusk {
+  
+namespace irgen {
+
+class GenExpr {
+  Expr *Root;
+  Context &Ctx;
+  
+public:
+  GenExpr(Expr *R, Context &C);
+  
+  llvm::Value *gen();
+  
+private:
+  llvm::Value *codegen(Expr *E);
+  llvm::Value *codegen(NumberLiteralExpr *E);
+  llvm::Value *codegen(IdentifierExpr *E);
+  llvm::Value *codegen(InfixExpr *E);
+  llvm::Value *codegen(PrefixExpr *E);
+  llvm::Value *codegen(AssignExpr *E);
+  llvm::Value *codegen(CallExpr *E);
+};
+  
+} // namespace irgen
+  
+} // namespace dusk
+
+#endif /* DUSK_GEN_EXPR_H */
+
diff --git a/lib/IRGen/IRGenerator.cpp b/lib/IRGen/IRGenerator.cpp
index ed9b02cb13f25578973d4d09d0eaf767c8156248..e9f0529e43c916bb43459dc89987092c8f53c9bb 100644
--- a/lib/IRGen/IRGenerator.cpp
+++ b/lib/IRGen/IRGenerator.cpp
@@ -8,7 +8,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "dusk/IRGen/IRGenerator.h"
-#include "dusk/IRGen/Scope.h"
+#include "dusk/IRGen/Context.h"
+
+#include "GenExpr.h"
 
 using namespace dusk;
 using namespace irgen;
@@ -16,105 +18,4 @@ using namespace irgen;
 IRGenerator::IRGenerator(DiagnosticEngine &Diag)
     : Diag(Diag), Builder({Context}) {}
 
-IRGenerator::~IRGenerator() { /*delete Module;*/ }
-
-void IRGenerator::gen(ModuleDecl *D) {
-  Module = llvm::make_unique<llvm::Module>(D->getName(), Context);
-  wrapTopLevelExpr(codeGen(static_cast<Expr *>(D->getContents().front())));
-  Module->print(llvm::errs(), nullptr);
-}
-
-llvm::Function *IRGenerator::wrapTopLevelExpr(llvm::Value *Val) {
-  assert(Val && "Value cannot be NUL");
-
-  auto Ft = llvm::FunctionType::get(llvm::Type::getInt32Ty(Context), false);
-  auto Fn = llvm::Function::Create(Ft, llvm::Function::ExternalLinkage,
-                                   "__anon_expr", Module.get());
-
-  auto BB = llvm::BasicBlock::Create(Context, "entry", Fn);
-  Builder.SetInsertPoint(BB);
-  Builder.CreateRet(Val);
-  llvm::verifyFunction(*Fn);
-  return Fn;
-}
-
-llvm::Value *IRGenerator::codeGen(NumberLiteralExpr *E) {
-  auto Value = llvm::APSInt::get(E->getValue());
-  return llvm::ConstantInt::get(Context, Value);
-}
-
-llvm::Value *IRGenerator::codeGen(IdentifierExpr *E) {
-  auto Value = NamedValues[E->getName()];
-  // Use of undeclared variable
-  if (!Value)
-    return nullptr;
-  return Value;
-}
-
-llvm::Value *IRGenerator::codeGen(InfixExpr *E) {
-  auto LHS = codeGen(E->getLHS());
-  auto RHS = codeGen(E->getRHS());
-  if (!LHS || !RHS)
-    return nullptr;
-  
-  switch (E->getOp().getKind()) {
-    case tok::plus:
-      return Builder.CreateAdd(LHS, RHS, "addtmp");
-    case tok::minus:
-      return Builder.CreateSub(LHS, RHS, "sumtmp");
-    case tok::mod:
-    case tok::divide:
-      return Builder.CreateSDiv(LHS, RHS, "divtmp");
-    case tok::multipy:
-      return Builder.CreateMul(LHS, RHS, "multmp");
-    case tok::equals:
-      return Builder.CreateICmpEQ(LHS, RHS, "eqtmp");
-    case tok::nequals:
-      return Builder.CreateICmpNE(LHS, RHS, "neqtmp");
-    case tok::less:
-      return Builder.CreateICmpSLT(LHS, RHS);
-    case tok::less_eq:
-      return Builder.CreateICmpSLE(LHS, RHS);
-    case tok::greater:
-      return Builder.CreateICmpSGT(LHS, RHS, "greattmp");
-    case tok::greater_eq:
-      return Builder.CreateICmpSGE(LHS, RHS, "great_eqtmp");
-    default:
-      return nullptr;
-  }
-}
-
-llvm::Value *IRGenerator::codeGen(PrefixExpr *E) {
-  auto Value = codeGen(E->getDest());
-  if (!Value)
-    return nullptr;
-  
-  switch (E->getOp().getKind()) {
-    case tok::neg:
-      return Builder.CreateNot(Value);
-    default:
-      return nullptr;
-  }
-}
-
-llvm::Value *IRGenerator::codeGen(CallExpr *E) {
-  auto Callee = dynamic_cast<IdentifierExpr *>(E);
-  auto Args = dynamic_cast<ExprPattern *>(E->getArgs());
-  if (!Callee || !Args)
-    return nullptr;
-  
-  auto Fn = Module->getFunction(Callee->getName());
-  if (!Fn)
-    return nullptr;
-  
-  if (Fn->arg_size() != Args->getValues().size())
-    return nullptr;
-  llvm::SmallVector<llvm::Value *, 128> ArgsV;
-  for (unsigned i = 0; i < Args->getValues().size(); i++) {
-    ArgsV.push_back(codeGen(Args->getValues()[i]));
-    if (!ArgsV.back())
-      return nullptr;
-  }
-  return Builder.CreateCall(Fn, ArgsV, "calltmp");
-}
-
+IRGenerator::~IRGenerator() {}
diff --git a/lib/IRGen/Scope.cpp b/lib/IRGen/Scope.cpp
deleted file mode 100644
index b4b09e7fc18766c63cbfa1006864ce10f0994d03..0000000000000000000000000000000000000000
--- a/lib/IRGen/Scope.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===--- Scope.cpp - Dusck scope implementation ---------------------------===//
-//
-//                                 dusk-lang
-// This source file is part of a dusk-lang project, which is a semestral
-// assignement for BI-PJP course at Czech Technical University in Prague.
-// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements Dusk scope implementation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "dusk/IRGen/Scope.h"
-
-using namespace dusk;
-using namespace irgen;
-
-ScopeEntry *ScopeStorage::get(llvm::StringRef Str) {
-  if (Entries.find(Str) != Entries.end())
-    return &Entries[Str];
-  if (Parent)
-    return Parent->get(Str);
-  return nullptr;
-}
-
-ScopeEntry *Scope::getEntry(llvm::StringRef Str) {
-  return Storage->get(Str);
-}
-
diff --git a/lib/Parser/Lexer.cpp b/lib/Parser/Lexer.cpp
index 1c441caa93cf94f792e2175c1e1243cd03e0b5c1..62b25a4901b7f34ef67cea5e2c58ef42d6793930 100644
--- a/lib/Parser/Lexer.cpp
+++ b/lib/Parser/Lexer.cpp
@@ -136,7 +136,7 @@ void Lexer::lexToken() {
     case '\t':
     case '\n':
     case '\r':
-        break;
+      break;
 
     case '=':
       if (*CurPtr == '=') {
@@ -268,7 +268,7 @@ void Lexer::diagnose(Token T, diag::DiagID ID) {
 
 // MARK: - Static methods
 
-tok Lexer::kindOfIdentifier(llvm::StringRef Str) {
+tok Lexer::kindOfIdentifier(StringRef Str) {
   return llvm::StringSwitch<tok>(Str)
       .Case("var", tok::kwVar)
       .Case("const", tok::kwConst)
@@ -285,7 +285,7 @@ tok Lexer::kindOfIdentifier(llvm::StringRef Str) {
       .Default(tok::identifier);
 }
 
-Token Lexer::getTokenAtLocation(const llvm::SourceMgr &SM, llvm::SMLoc Loc) {
+Token Lexer::getTokenAtLocation(const llvm::SourceMgr &SM, SMLoc Loc) {
   // Invalid address
   if (!Loc.isValid())
     return Token();
@@ -299,14 +299,12 @@ Token Lexer::getTokenAtLocation(const llvm::SourceMgr &SM, llvm::SMLoc Loc) {
   return L.peekNextToken();
 }
 
-llvm::SMLoc Lexer::getLocForEndOfToken(const llvm::SourceMgr &SM,
-                                       llvm::SMLoc Loc) {
+SMLoc Lexer::getLocForEndOfToken(const llvm::SourceMgr &SM, SMLoc Loc) {
   auto Tok = getTokenAtLocation(SM, Loc);
   return Tok.getRange().End;
 }
 
-llvm::SMLoc Lexer::getLocForStartOfLine(const llvm::SourceMgr &SM,
-                                        llvm::SMLoc Loc) {
+SMLoc Lexer::getLocForStartOfLine(const llvm::SourceMgr &SM, SMLoc Loc) {
   // Invalid address
   if (!Loc.isValid())
     return Loc;
@@ -314,7 +312,7 @@ llvm::SMLoc Lexer::getLocForStartOfLine(const llvm::SourceMgr &SM,
   auto BufferID = getBufferForLoc(SM, Loc);
   // Buffer not found in currently opened buffers
   if (BufferID > SM.getNumBuffers())
-    return llvm::SMLoc();
+    return SMLoc();
 
   auto B = SM.getMemoryBuffer(BufferID);
   auto BuffStart = B->getBufferStart();
@@ -323,8 +321,7 @@ llvm::SMLoc Lexer::getLocForStartOfLine(const llvm::SourceMgr &SM,
   return getSourceLoc(StartLoc);
 }
 
-llvm::SMLoc Lexer::getLocForEndOfLine(const llvm::SourceMgr &SM,
-                                      llvm::SMLoc Loc) {
+SMLoc Lexer::getLocForEndOfLine(const llvm::SourceMgr &SM, SMLoc Loc) {
   // Invalid address
   if (!Loc.isValid())
     return Loc;
@@ -332,15 +329,14 @@ llvm::SMLoc Lexer::getLocForEndOfLine(const llvm::SourceMgr &SM,
   auto BufferID = getBufferForLoc(SM, Loc);
   // Buffer not found in currently opened buffers
   if (BufferID > SM.getNumBuffers())
-    return llvm::SMLoc();
+    return SMLoc();
   Lexer L(SM, BufferID);
   L.setState(Loc);
   L.skipToEndOfLine(/*ConsumeNewLine: */ true);
   return getSourceLoc(L.CurPtr);
 }
 
-llvm::StringRef Lexer::getLineForLoc(const llvm::SourceMgr &SM,
-                                     llvm::SMLoc Loc) {
+StringRef Lexer::getLineForLoc(const llvm::SourceMgr &SM, SMLoc Loc) {
   auto S = getLocForStartOfLine(SM, Loc);
   auto E = getLocForEndOfLine(SM, Loc);
   return {S.getPointer(), (size_t)(E.getPointer() - S.getPointer())};
@@ -385,7 +381,7 @@ void Lexer::skipMultilineComment() {
   const char *TokStart = CurPtr - 1;
   // Validate start of line comment
   assert(CurPtr[-1] == '/' && CurPtr[0] == '*' && "Not a /* comment");
-  
+
   CurPtr++;
   while (true) {
     switch (*CurPtr++) {
@@ -414,7 +410,7 @@ void Lexer::skipMultilineComment() {
 }
 
 void Lexer::formToken(tok Kind, const char *TokStart) {
-  llvm::StringRef TokenText = {TokStart, (size_t)(CurPtr - TokStart)};
+  StringRef TokenText = {TokStart, (size_t)(CurPtr - TokStart)};
   NextToken.setToken(Kind, TokenText);
 }
 
@@ -448,7 +444,7 @@ void Lexer::lexIdentifier() {
   while (consumeIfValidIdentifierCont(CurPtr));
 
   // Construct token
-  auto TokenText = llvm::StringRef{TokStart, (size_t)(CurPtr - TokStart)};
+  auto TokenText = StringRef{TokStart, (size_t)(CurPtr - TokStart)};
   tok Kind = kindOfIdentifier(TokenText);
   return formToken(Kind, TokStart);
 }
@@ -479,13 +475,15 @@ void Lexer::lexHexNumber() {
 
   // Consume [0-9][a-z][A-Z] character to get token string.
   // We'll validate it later.
-  while (consumeIfValidIdentifierCont(CurPtr));
+  while (consumeIfValidIdentifierCont(CurPtr))
+    ;
 
   const char *TokEnd = CurPtr;
   CurPtr = TokStart + 2; // skip `0x` prefix
 
   // Consume only valid [0-9][a-f][A-F] character.
-  while (consumeIfValidHexDigit(CurPtr));
+  while (consumeIfValidHexDigit(CurPtr))
+    ;
 
   // Validate number of consumed characters.
   if (TokEnd == CurPtr)
diff --git a/lib/Parser/ParseDecl.cpp b/lib/Parser/ParseDecl.cpp
index 0bf096829909c5ee29fb3eaedd95d8c76b3eed03..372272f36114d73f546834da046176f49b9dff89 100644
--- a/lib/Parser/ParseDecl.cpp
+++ b/lib/Parser/ParseDecl.cpp
@@ -79,8 +79,9 @@ Decl *Parser::parseFuncDecl() {
     diagnose(Tok.getLoc(), diag::DiagID::expected_identifier);
     return nullptr;
   }
-
-  return make<FuncDecl>(ID.getText(), ID.getLoc(), FL, parseVarPattern());
+  
+  auto Args = static_cast<VarPattern *>(parseVarPattern());
+  return make<FuncDecl>(ID.getText(), ID.getLoc(), FL, (Args));
 }
 
 /// Param declaration
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index c065611af84729e494b0542e368afc481b65e1fa..ed18760bdba22e7fa9fb2c46bf008a08a1690e85 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -26,7 +26,7 @@ Parser::~Parser() { delete L; }
 
 const Token &Parser::peekToken() const { return L->peekNextToken(); }
 
-llvm::SMLoc Parser::consumeToken() {
+SMLoc Parser::consumeToken() {
   PreviousLoc = Tok.getLoc();
   assert(Tok.isNot(tok::eof) && "Lexing past EOF.");
 
@@ -34,12 +34,12 @@ llvm::SMLoc Parser::consumeToken() {
   return PreviousLoc;
 }
 
-llvm::SMLoc Parser::consumeToken(tok T) {
+SMLoc Parser::consumeToken(tok T) {
   assert(Tok.is(T) && "Consumption of invalid token kind.");
   return consumeToken();
 }
 
-DiagnosticRef Parser::diagnose(llvm::SMLoc Loc, diag::DiagID ID) {
+DiagnosticRef Parser::diagnose(SMLoc Loc, diag::DiagID ID) {
   if (diag::DiagID::unexpected_token == ID && R.isError())
     // No better diagnostics than already given.
     return DiagnosticRef();