Mainstream programming languages share most of their core concepts, such as functions, variables, scopes, heap storage, and many more. In this course, we explore these concepts in a systematic and principled way, that is independent of specific languages and their syntax. Notably, starting from nothing, we implement a family of toy languages that have successively more and more advanced features, enabling to understand these important but abstract concepts very concretely, and enabling experimentation with different language features.