2  Course Approach

\(\newcommand{\TirName}[1]{\text{#1}} \newcommand{\inferrule}[3][]{ \let\and\qquad \begin{array}{@{}l@{}} \TirName{#1} \\ \displaystyle \frac{#2}{#3} \end{array} } \newcommand{\infer}[3][]{\inferrule[#1]{#2}{#3}} \)

We will construct language interpreters to get experience with the “guts” of programming language design and implementation. The semester project will be to build and understand interpreters for mini-versions of JavaScript—our example source language. The source language is what called the object language (i.e., the under under study). We will see that interpreters are the basis for realizing computation, and we will study the programming language theory that enable us to reason carefully about a language’s design and implementation. Our approach will be gradual in that we will initially consider a small subset of JavaScript and then slowly grow the aspects of the language that we consider (and see how they underlie many other programming languages).

Our implementation language of study will be Scala. The implementation language is the meta language (i.e., the language used to study another). Scala is a modern, general-purpose programming language that includes many advanced ideas from programming language research. In particular, we are interested in it because it is especially well suited for building language tools. As quoted above, Scala “blends” concepts from object-oriented and functional programming [1] and in many ways tries to support each in its “native environment.” Scala has also found a myriad of other applications, including being a important language for building data-processing pipelines. It is compatible with Java and runs on the Java Virtual Machine (JVM) and has been applied in industrial practice by such companies as LinkedIn.

Incoming students often expect this course to be what I will call a trip to the Zoo of Programming Languages. While it is certainly interesting to go to the zoo, we seek a more informative and scientific study of the underlying principles. A more apt analogy is an anatomy course where we will study the “guts” and inner-workings of programming languages. After this course, such an anatomical study will enable us to compare and contrast programming languages in a substantive manner and address the learning goals outlined above in Chapter 1.

2.1 Expectations and Finding Success

The study of programming languages gets at the core of computation and introduces abstract concepts. Past experience suggests that the study of programming languages can lead to unnecessary panic and anxiety. At times, it may appear like a lot of effort and complexity to study a toy language and to define and describe seemingly simple language features. In the end, this “dissection”-based approach pays off in distilling computation into simple, composable concepts that enable you to see how they appear over-and-over again to realize modern software.

This course is an active learning course, which means the learning is driven primarily by active discovery in doing the assignments. To succeed in the course, we suggest to the student to keep the following in mind:

Principles Exist

While everyday programming languages seem complex, underlying principles exist. They take work to uncover and see, but they can be understood. Knowing the underlying principles are there, you should not panic and always seek help from course guides.

Practioners Exist

Programming languages come alive from the people that use them to create amazing software. Everyday languages, like Scala, have a community and are well documented. You should join the community and get used to reading documentation.

Learn by Doing

Concepts may look simple when the course guides walk you through them. However, until you dive deep and get your hands dirty on code — run it, modify it, write it, play with it, talk about it in your own words, you will not own the knowledge. You will make mistakes and get confused along the way, but with hard work and help from your course guides, you will truly master the concepts.