7400: iPPL (Fall 2024)

Implementation Assignment

Instructions

For this artifact format, you will write an interpreter in a language of your choice for a small core calculus implementing your chosen topic. See the project page for a list of approved topics.

This spec will refer to the language representing your topic as the object language and the language you're using to implement the interpreter as the host language.

Your interpreter should be an explanatory artifact in the sense that:

  • The code should be executable, but the main purpose of it is to help explain the object language.
  • The code implementing the main interpreter should be concise and easily readable by someone familiar with basic features of the host language, not relying on esoteric libraries or language features.
  • The code should be well-commented.
  • The source repository should contain multiple tests and examples, along with explanations of why they were chosen and how to run them.
  • The repository should contain a README file with a description of the goal of the project, an explanation of how the constructs (types, expressions, etc.) of the object-language are represented in the host language, and instructions for how to build the project and run the interpreter on the included examples.

Your work will be evaluated primarily on its success as an explanatory artifact, so prioritize writing simple, straightforward code whose correctness is easy to check by inspection, rather than coming up with clever optimizations and implementation tricks.

What is an interpreter?

An interpreter for a language (or core calculus) L has the following end-to-end interface:

  • Input: an abstract syntax tree representing an expression E in L
  • Output: a value in L representing the outcome of running E (if it terminates)
  • Effects: any observable effects represented by E.
Note that you do not need to write a parser to turn text files into abstract syntax: you can write your examples directly in terms of however you choose to represent ASTs in your host language. Typically, your interpreter will expose at the top level a function eval : expression -> expression such that calling eval(E) behaves as ``running'' E. An interpreter correctly implements the operational semantics of the language definition if, for all E in the language, eval(E) returns V iff E -->* V and V is a value.

If you've never implemented an interpreter before, here are a few guides to get you started:

Credit and sources

Programming is a social activity, and humanity benefits from our collective ability to share and reuse software. To respect this practice, it's important to give appropriate credit for ideas and implementations. You may reference other implementations of your topic, use existing libraries, and consult standard references, but you must document each instance.

Include in your submission a file named credits.md that enumerates the library implementors, learning resources, book chapters, academic papers, and any other resources you consulted to inform your implementation. If you wind up building on someone else's work in a way that makes up a large percentage of your submitted contribution, you must clearly delineate which work was yours and how you benefited from and extended prior work. Part of your grade will be based on originality in this sense (see below).

Unfortunately, code generation tools like Copilot and ChatGPT use proprietary datasets that make it difficult to ascribe credit appropriately to all of the programmers whose code was used to train their models. We heavily discourage the use of these tools for this reason, but we also understand that they can be convenient when documentation is unreliable or unavailable. If you use a code generation tool to help you write your code, please provide a transcript of all prompts that you used, a statement about why you chose to use the tool, and a statement about the training dataset (including what information is and isn't publicly available about it).

Grading

Submitted interpreters will be graded as follows:

50% of the grade is based on explanatory power: does your development lend insight into the chosen topic that would be difficult to convey without a runnable implementation? Do you provide sufficient explanation and instructions that someone new to the topic could learn something by exploring it that they wouldn't be able to learn with a textbook?

20% of the grade is based on implementation correctness, completeness, and depth of engagement with the topic: did you choose a topic appropriate to the course? Does your interpreter correctly and completely implement the language you chose? Is it possible to run on the examples based on the README? Did you select examples that illustrate the nature of your topic and what makes it a particularly useful, expressive, or fundamental idea?

20% of the grade is based on originality: does your implementation do something that it isn't easy to find public examples of already? If it is easy to find examples of similar developments, do you clearly identify how your work extends, generalizes, simplifies, or otherwise improves upon prior work?

10% of the grade is based on references/citations/sources: Does your credit.md file adhere to the guidelines above? Do you point your readers to the source of ideas pertaining to your topic (including the publications that orginated it and resources for learning more)?

Submission

Your code is due by 11:59:59pm on the project deadline. You should submit your source repository either as a .zip file or as a github or bitbucket repository on Gradescope (Gradescope has a mechanism for linking with repositories on those two sites).

Resources

Acknowledgments