Building an Interpreter from scratch
4.9 (19 ratings)
Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.
111 students enrolled

Building an Interpreter from scratch

Semantics of programming languages
4.9 (19 ratings)
Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.
111 students enrolled
Created by Dmitry Soshnikov
Last updated 3/2020
Current price: $34.99 Original price: $49.99 Discount: 30% off
5 hours left at this price!
30-Day Money-Back Guarantee
This course includes
  • 3 hours on-demand video
  • Full lifetime access
  • Access on mobile and TV
  • Certificate of Completion
Training 5 or more people?

Get your team access to 4,000+ top Udemy courses anytime, anywhere.

Try Udemy for Business
What you'll learn
  • Build a programing language from scratch
  • Interpreters and Compilers
  • AOT, JIT-compilers and Transpilers
  • AST-interpreters and Virtual Machines
  • Bytecode, LLVM, Stack-machines
  • First-class functions, Lambdas and Closures
  • Call-stack and Activation Records
  • OOP: Classes, Instances and Prototypes
  • Modules and Abstractions
Course content
Expand all 18 lectures 02:59:35
+ Compilers crash course
3 lectures 36:26

In this lecture:

  • Introduction and course overview

  • Parsing pipeline

  • Tokenizer, tokens

  • Abstract Syntax Trees (AST)

  • Static/Compile time vs. Runtime

  • Interpreters vs. Compilers

  • AST-interpreters (recursive)

  • Bytecode-interpreters

  • Ahead-of-time (AOT) compilers

  • Just-in-time (JIT) compilers

  • Transpilers

Preview 12:07

You will learn:

  • AST interpreters

  • AST explorer

  • JavaScript AST example

  • Bytecode interpreters

  • Stack machine vs. Register machine

  • Stack VM bytecode evaluation example

  • Compiler explorer

  • Java bytecode example

  • Python bytecode example

  • Register VM bytecode evaluation example

AST Interpreters and Virtual Machines

You will learn:

  • Ahead-of-time (AOT) compiler

  • Just-in-time (JIT) compiler

  • LLVM

  • Intermediate representation (IR)

  • Bytecode

  • Clang

  • x64 Assembly

  • AST-transformer (Transpiler)

Preview 12:18
+ Interpreters: Basic expressions and Variables
6 lectures 59:05

You will learn:

  • AST formats

  • S-expression

  • Eva programming language

  • Eval -- the core of an interpreter

  • Statement vs. Expression

  • Closures

  • Lambda functions

  • IILE: Immediately-invoked lambda expressions

Preview 11:11

You will learn:

  • Eval -- the core of an interpreter

  • Self-evaluating expressions

  • Numbers and Strings

  • TDD (Test-driven development)

  • Addition operation


  • Implement and fix complex addition: (+ (+ 2 3) 5)

Preview 07:02

You will learn:

  • Recursive nature of the interpreter

  • Environment: repository of variables

  • Environment Record

  • Define, Assign, Lookup

  • The Global Environment

Example: environments in JavaScript:

Variables and Environments

You will learn:

  • Blocks: groups of expressions

  • Block scope

  • Identifier resolution

  • Scope chain traversal

  • Variable assignment

Blocks: expression groups and Nested Scopes

You will learn:

  • Program control-flow

  • Branches: if-expression

  • Cycles: while-loops


  • Implement ++ operator: (++ foo)

  • Implement logical operators: (or foo default), (and x y), (not value)

Control flow: If and While expressions

You will learn:

  • S-expressions

  • BNF (Backus-Naur form) grammars

  • Syntax tool: language-agnostic parser generator

  • Atoms and Lists

  • LALR(1) parser creation


  • Add support for floating point numbers parsing: (+ 0.5 1.42)

Back to parsers: S-expression to AST
+ Functions and Functional programming
5 lectures 45:52

You will learn:

  • Built-in functions

  • Native functions

  • Function calls

  • Global environment

Built-in and Native functions

You will learn:

  • User-defined functions

  • Closures: capturing environment

  • Function calls

  • Activation Environments and Activation Records

  • Static scope vs. Dynamic scope

  • Free variables

User-defined functions, Activation Records and Closures

You will learn:

  • Lambda functions

  • Anonymous function expressions

  • Callbacks

  • IILE: Immediately-involved lambda expressions

  • Function declaration

  • Syntactic sugar

Lambda functions and Functional programming

You will learn:

  • Call-stack

  • Recursive calls

  • Heap-environments

  • Execution context

  • Closures

  • Tail calls


  • Implement Execution context stack. A stack frame is pushed every time a function is called. The stack should contain a reference to the Environment, and store the called function name

  • Implement print_stack_trace function which prints the all stack frames info with function names

Call-stack and Recursive calls

You will learn:

  • Transpilers

  • Nicer syntax, same semantics

  • Switch-expression

  • For-loops

  • JIT-translation


  • Implement for-loop translation to while-loop (see description in the lecture)

  • Implement ++, --, +=, -=, etc syntactic sugar operators, translating to get / set instructions

Syntactic sugar: Switch, For, Inc, Dec operators
+ Object-oriented programming
4 lectures 38:12

You will learn:

  • Object-oriented programming

  • Class-based semantics

  • Prototype-based semantics

  • Named environments

  • Instances

  • New expression

  • Property access

Object-oriented Eva: Classes

You will learn:

  • Class inheritance

  • Child and Parent classes

  • Super calls

Class inheritance and Super calls

You will learn:

  • Module expressions

  • Named environments

  • First-class module objects

  • Import and export expressions

  • Property access


  • Implement named imports: (import (abs, square) Math)

  • Implement module exports: (exports (abs, square))

  • Implement inline exports: (export (def square (x) (* x x)))

Code isolation: Modules and Imports

You will learn:

  • Eva interpreter

  • CLI support

  • Evaluating expressions and files

  • Further data structures

  • Objects, prototypes, lists, async functions

  • Eva specification

  • Instructions format, examples and spec

  • Building a Virtual Machine


  • Implement Eva REPL: read any expression, evaluate, print result, loop back to reading

Final executable and specification
  • Basic data structures and algorithms
  • Graphs, trees, traversal

How programming languages work under the hood? What’s the difference between compiler and interpreter? What is a virtual machine, and JIT-compiler? And what about the difference between functional and imperative programming?

There are so many questions when it comes to implementing a programming language!

The problem with “compiler classes” in school is they usually are presented as some “hardcore rocket science” which is only for advanced engineers.

Moreover, classic compiler books start from the least significant topic, such as Lexical analysis, going right away deep down to the theoretical aspects of formal grammars. And by the time of implementing a first Tokenizer module, students simply lose an interest to the topic, not having a chance to actually start implementing a programing language itself. And all this is spread to a whole semester of messing with tokenizers and BNF grammars, without understanding an actual semantics of programming languages.

I believe we should be able to build and understand a full programming language semantics, end-to-end, in 4-6 hours — with a content going straight to the point, showed in live coding session as pair-programming, and described in a comprehensible way.

In the Essentials of Interpretations class we focus specifically on runtime semantics, and build a interpreter for a programming language very similar to JavaScript or Python.

Implementing a programing language would also make your practical usage level of other programming languages more professional.

Who this class is for?

This class is for any curious engineer, who would like to gain skills of building complex systems (and building a programming language is really a pretty advanced engineering task!), and obtain a transferable knowledge for building such systems.

If you are interested specifically in compilers, interpreters, and source code transformation tools, then this class is also for you.

The only pre-requisite for this class is basic data structures and algorithms: trees, lists, traversal.

What is used for implementation?

Since we build a language very similar in semantics to JavaScript or Python (the two most popular programming languages today) we use specifically JavaScript — its elegant multi-paradigm structure which combines functional programming, class-based, and prototype-based OOP fits ideal for that.

Many engineers are familiar with JavaScript so it should be easier to start coding right away. However in implementation we don’t rely on too specific to JS constructs, and the code from the course is easily portable to TypeScript, Python, Java, C++, Rust, and any other language of your taste.

Note: we want our students to actually follow, understand and implement every detail of the interpreter themselves, instead of just copy-pasting from final solution. The full source code for the language is available in video lectures, showing and guiding how to structure specific modules.

What’s specific in this class?

The main features of these lectures are:

  • Concise and straight to the point. Each lecture is self-sufficient, concise, and describes information directly related to the topic, not distracting on unrelated materials or talks.

  • Animated presentation combined with live-editing notes. This makes understanding of the topics easier, and shows how (and when at time) the object structures are connected. Static slides simply don’t work for a complex content.

  • Live coding session end-to-end with assignments. The full source code, starting from scratch, and up to the very end is presented in the class

What is in the course?

The course is divided into four parts, in total of 18 lectures, and many sub-topics in each lecture. Please address curriculum for detailed lectures descriptions.


In this part we describe different compilation and interpretation pipelines, see the difference between JIT-compilers and AOT-compilers, talk about what is a Virtual machine and Bytecode-interpreter, and how it difference from an AST-interpreter, show examples of native code, and LLVM IR, and other topics.


In this part we start building our programming language, and consider basic expressions, such as numbers, strings, talk about variables, scopes, and lexical environments, control structures, and touching parser generator.


In this part we start talking and implementing function abstraction, and function calls. We describe concept of closures, lambda function, and IILEs (Immediately-invoked lambda expressions). In addition, we touch topics of Call-stack, recursion, and syntactic sugar.


The final part of the course is devoted to the object-oriented support in our language. We describe the class-based, and prototype-based approaches, implement concept of classes, instance and modules.

I hope you’ll enjoy the class, and will be glad to discuss any questions and suggestion in comments.

- Dmitry Soshnikov

Who this course is for:
  • Curious engineers who want to know and understand how programming languages work under the hood