On this page:
Interpreters
Type Checkers

CSCI 1730 · Fall 2026

Code🔗

To aid you in the migration from Plait to Shplait, here are some of the programs from the lectures, rewritten in Shplait. You are welcome (indeed, encouraged!) to download and run these and play along.

The descriptions below are not substitutes for the lecture/book, nor are they meant to make sense in their absence.

Interpreters🔗

A key detail: The tests in these files are deliberately sparse. That is an expository choice, not something you should emulate! Your homeworks are required to have extensive testing. They’re just left out here to reduce clutter (and to avoid doing your homework for you!).

File

  

What it adds

calc.rhm

  

The smallest possible language: numbers, +, and *. No parser yet. Write abstract syntax trees by hand!

calc-with-parse.rhm

  

A parse function that turns text of type Syntax into the corresponding syntax tree, so you can write much more convenient programs. Observe that single-quotes create values of type Syntax, which is what parse consumes.

calc-parse-cond.rhm

  

Booleans and if. The result of evaluation now needs its own datatype.

interp-let.rhm

  

Variables and let. Evaluation now needs an environment.

interp-lam-dynamic.rhm

  

Functions (lam) and application. A function value records only its parameter and body, and is applied in the environment of the call. This is dynamic scope; the tests at the end show the resulting behavior, which is not what we want.

interp-lam-static.rhm

  

Fixes the above: a function value is now a closure that also records the environment where the lam was evaluated, and the body is evaluated in that environment. The argument, however, must still be evaluated in the caller’s environment; the last test checks this.

interp-sugar.rhm

  

Syntactic sugar: subtraction, unary negation, and, and cond. Now features a new datatype to represent surface terms. The key is a desugar function that turns surface programs into core ones. A critical detail is that the interpreter is imported: there is no definition in this file. This shows that we could grow the language without modifying the interpreter at all.

Type Checkers🔗

Each language comes in three files:

  • the type checker: the core language’s abstract syntax and type_of, with tests written directly as syntax trees;

  • the front end: the surface syntax, a parser, and a desugarer (the checker only ever sees the desugared, core program);

  • the interpreter, which runs a program only if it type-checks, and also shows what happens when programs are run without checking them.

Unlike the interpreters above, these files are extensively tested: the tests are where the interesting examples are, including programs the checker rejects that would have run fine, and programs it accepts that still go wrong.

Language

  

Features

  

Files

tc-ops

  

Numbers with +, *, and /; strings with ++ (concatenation); and s[i], the one-character string at position i of s: the one operation that takes both a string and a number. Subtraction and negation are sugar. There are two types, Num and Str. Division by zero and out-of-range indexing type-check, and fail only when run.

  

type checker
front end
interpreter