CS 214: Programming Languages
Spring 2009

Home|Syllabus|Schedule
<<|>>|ANTLR API|CITkit API|PolyD API|EasyMock API

The Purposes and Goals of the Labs of Interpreters
Interpreters, Iteration 0

Programming Language Courses

There many levels at which to talk about "Programming Languages" and to practice them. A typical Programming Languages course will take one of two approaches. One way, you learn a bunch of different languages (hopefully from different paradigms); this way you get to appreciate the commonalities between languages and take advantage of the differences.

The other way has you implement different languages semantics (e.g., dynamic and lexical scopes) and paradigms with your own interpreter. In seeing how languages are implemented is supposed to give you better insight into what makes for an effective lanaguage.

Implementing Interpreters

These lab exercises take this latter approach but wth a twist. We will use standard techniques of Software Engineering to build interpreters. In particular, we'll use two techniques taken from agile software development: incremental development and test-driven development.

Incremental Development

Incremental development is a slightly ambiguous term (as seen from that wikipedia entry). For me (and therefore for the purposes of these lab exercises) it means implementing a feature from beginning to end. So the very first lab will have you implement a complete interpreter that interprets integers. The second lab exericse will have you incrementally modify that interpreter so that it also interprets strings. The third lab exercise will have you add a little bit. And so on.

This is in contrast to building up an entire front end (lexer and parser) without knowing of fully appreciating how it will be used until several weeks later in the course. By seeing the lexer plug into the parser which plugs into the interpreters, you should have a greater appreciation for and understanding of the interaction bewteen the stages.

Also, incremental development should make it easier to implement multiple interpreters.

Test-Driven Development

Test Driven Development (TDD) consists of two other practices: test-first programming and refactoring. The Wikipedia entry describes TDD fairly well. For our purposes, TDD and refactoring are based, in difference ways, on programming-languages principles which we can model and demonstrate with our interpreters.

Programming Paradigms

This is not to say that programming paradigms will be ignored. One of the benefits of learning different languages is to appreciate their syntax and conventions.

Object-Oriented Programming

You will implement your interpreters in Java. In these implementations, you will see many different OOP techniques which cannot be modeled well (or are modeled quite differently) in other language paradigms. You will also see some of the shortcomings of OOP and Java in modeling certain computations.

You'll also do quite a bit of programming in Ruby which is completely OO in ways that Java is not and never will be.

So, in other words, you'll hit OOP pretty hard.

Functional Programming

The first complete interpreters you write will interpret functional languages. In this way, you will get some experience with this paradigm in its own language.

You will also use Ruby in a functional way (which is the way true Ruby hackers use it).

And you'll look at Haskell, which is a pure functional programming language.

Social Aspects of Programming Languages

Two aspects of programming languages which often get neglected are the social context for a language or language paradigm and the tools provided by that community.

For example, (La)TeX, Perl, Ruby, Python, and many other languages have fantastic community support for third-party libraries. If you need a priority queue in one of these languages, someone has probably already written one.

Communities also build tools like IDEs, XML editors, etc.

It is good experience playing around with and installing these tools.