Homework 12
Last updated: Thu, 30 Apr 2026 09:57:03 -0400
Out: Thu Apr 30 2026, 11am EST
Due: Thu May 07 2026, 11am EST
Overview
In this assignment, we will add type checking to the high-level programming language we have created, which will allow our language to catch some programmer errors before the program is run!
This hw will be graded accordingly:
correctness (Autograded) (25 pts)
design recipe (15 pts)
testing (14 pts)
style (24 pts)
README (2 pt)
Setup
Create a new repository for this assignment by going to the CS450 Spring 2026 GitHub Organization and clicking "New".
Note: The CS450 Spring 2026 GitHub Organization must be the owner of the repository. Please do not create the repository in your own account.
On the "Create a new repository" screen:
Name the repository hw<X>-<LASTNAME>-<FIRSTNAME> where <X> is the current homework number.
For example, I would name my hw12 repository hw12-Chang-Stephen.
Mark the repository as Private.
Check "Add a README file".
Select the Racket template for the .gitignore.
Choose whatever you wish for the license.
When done click "Create repository".
Updating Racket450
Make sure you have the latest version of racket450.
To do this from DrRacket, go to File -> Package Manager -> Currently Installed, search for "racket450", and then click "Update".
Alternatively, if you prefer the command line, run:
raco pkg update racket450
Reading
Review Chapters 21 and 23 of the Textbook.
NOTE: The textbook will refer to "Student Languages" which we do not use in this course (and a "Stepper" that only works with the Student Languages). Instead, we use a version of Racket tailored for this course, which is invoked by putting #lang racket450 at the top of a file (see also Before Submitting).
Also, read any relevant sections of the The Design Recipe section of the course website (topics that will be covered in future lectures are marked as such).
Tasks
The main code should go in a file named hw12.rkt that uses #lang racket450, as described previously.
As usual, all submitted code must follow the The Design Recipe. This means that language features may only be used in the correct scenarios, as called for by The Design Recipe.
Conditionals such as if and cond are only to be used with the appropriate Data Definitions or in other appropriate scenarios described in class.
Signatures should use define/contract and the predicates defined in the Data Design Recipe step. In this assignment, you may use the listof contract constructor where appropriate.
For Examples and Tests, do not use check-expect from the Beginning Student Language (even though the textbook says to). Instead, use check-equal? or other testing forms from rackunit (which are built into racket450, so do not explicitly require rackunit).
Examples for a function definition should be put before the define in hw12.rkt.
Tests should be put a into hw12-tests.rkt file that uses #lang racket450/testing. Try to think about corner cases and code coverage.
NOTE, on one-line helper functions: If the name and description of a "helper" function clearly describe what it does, and it clearly follows some Data Definition and all other Design Recipe steps (the course staff is the final arbiter of this), it does not need to be submitted with Examples and Tests if they are covered by other tests. ("Helper" functions are defined as functions not described in the homework assignment description.) NOTE: This does not change the Design Recipe. It is only changing submission requirements. As usual, however, we will not be able to help debug code that does not follow the Design Recipe, so omit these steps at your own risk.
All other functions should have at minimum one Example and "sufficient" Tests.
Programming
Create your typed programming language by implementing parse and the type checking functions—
Program Data Definitions
For each of these data definitions, you should complete them by writing the necessary predicates, constructors, etc.
A Variable (Var) is a Symbol
An TypeEnvironment (TyEnv) is a Listof<(list Var Type)> (a list of 2-element lists) Holds type information for in-scope variables and the types of the values they stand for. Entries closer to the head of the list shadow those further in the back.
- A Program is one of:
Number
Variable (Var)
`(iffy ,Program ,Program ,Program)
`(bind [,Var ,Program] ,Program)
`(lm [,Var : ,TypeStx] ... ,Program)
(cons Program List<Program>)
Represents: the surface-level syntax of a new typed programming language (i.e., this is what programmers write).It is similar to previous hws except some Programs require type annotations.
TypeStx is how programmer write Types and is defined as either’Int
’(-> TypeStx ... TypeStx)
TypeStx should get parsed to Type, using parse-type (see below), in the same way that a Program is parsed to an AST.lm has an additional invariant that the list of Vars should be unique. Racket has check-duplicates that should help with this.
- An AST is one of:
(mk-num Number)
(mk-var Symbol) (do not name your struct var because that is a Racket match pattern)
(mk-ify AST AST AST)
(mk-bind Symbol AST AST)
(mk-tylm-ast List<Var> List<Type> AST)
(mk-appl AST List<AST>)
Represents: an abstract syntax tree data structure that is produced from parsing the surface program - A Type is one of:
(mk-Int)
(mk-FnTy Listof<Type> Type)
Represents: an abstract syntax tree data structure for Types, that is produced from parsing types that the programmer might write
Functions (define and provide)
parse : takes a Program and produces an AST abstract syntax tree data value. When the input is not a valid Program, this function should call raise-syntax-error with an exn:fail:syntax:cs450 exception, which is given in racket450/hw12, and an appropriate error message. Be careful here because what is a valid/invalid Program has changed and may require more sophisticated parsing to determine.
parse-type : Given TypeStx input, returns a valid Type. Should be called by parse. Should raise an exn:fail:syntax:cs450 exception if the parsing fails.
type=? : given two Types, evaluates to true when they are equal. Type equality should be computed by doing a deep structural comparison of the given types, following a Multi-argument Templates
typeof: given an AST, computes its Type
Note : This function should call a helper that uses an TypeEnvironment accumulator (that follows all steps of the Accumulator Design Recipe). Normally this function should be "internal", but since internal functions cannot be tested as easily, this assignment requires that this accumulator function be defined external to the main typeof function.
You will also need to define and use typeof-apply (described below), which should also normally be inside the typeof function define, but for this assignment define it at the top-level to make it easier to test.
Initial environment: should contain bindings for + and *, which should have binary function types on integers only.
Some more specific type checking specifications:Since iffy allows anything in the test position, there should similarly be no restriction on the type of the test expression. If the types of the branches of an iffy don’t match, however, an exn:fail:typecheck:cs450 exception should be raised.
tyenv-add : Takes a TypeEnvironment, Var, and Type and returns a new TypeEnvironment where the given Var is bound to the given Type
tyenv-lookup : Takes a TypeEnvironment and Var and returns either the Type of the value that the Var represents, or raises an exn:fail:typecheck:cs450 exception if the given Var is not in the environment.
typeof-apply : Takes a Type representing a function and a Listof<Type> representing arguments. Produces either the Type of result of the application, if given a valid FnTy type for the function and the correct number of arguments, or raises exn:fail:typecheck:cs450 if the application failed.
Library Functions
A library racket450/hw12 provides some functions that will make it easier to implement the hw.
(Note: This library will not be available until all students have submitted the previous hws.)
Import this library by writing (require racket450/hw12).
The library will contain the following functions:
exn:fail:typecheck:cs450 Exception to use for typechecking failures.
exn:fail:typecheck:cs450? predicate for above
exn:fail:syntax:cs450 Exception for syntax errors produced by your parse function.
exn:fail:syntax:cs450? predicate for cs450 syntax error exceptions.
Before Submitting
Testing (and Autograders)
Before submitting, note:
Each programmer is solely responsible for testing their program to make sure it’s correct. Do not submit until all code has been has a "sufficient" number of Test cases that verify its correctness.
Note that there is no GradeScope "Autograder" available for students to use (an Autograder is not a software development/testing tool anyways, so it should not be used as one).
Thus, no questions mentioning an Autograder will be answered, e.g., posts asking "why is the Autograder giving an error?" are not allowed.
If you happen to find an Autograder and decide to look at its output despite this warning, please understand that it may be incorrect or incomplete, change at any time, or have random behavior, and that it in no way indicates the grade of the submitted hw.
Anyone that does get useful information from an Autograder, e.g., a failing test case or crashing code report, should treat it as bonus information (that you otherwise would not have had) that you and you alone must determine what to do with.
Regardless of what any Autograder might say, all code must still be independently tested to be correct before it is submitted.
The proper way to ask questions is with small code examples. This means that each question must include a small example code snippet along with what the "expected" result should be!
Further, any posted examples should contain the minimal amount of code needed to explain the question. Full file dumps or anything more than a few lines will not be accepted. More is not better. In fact it’s worse because it takes longer to read and is less likely to get a good answer.
Style
All code should follow proper Racket Style.
Also, the repository itself must follow proper style. Specifically, it must have appropriate commit messages. See How to Write a Git Commit Message if you are unsure how to write a commit message.
Note: Do not use the "file upload" feature on Github. The course staff may not accept hw uploaded in this way.
Files
A submission must have the following files in the repository root:
hw12.rkt: Contains the hw solution code.
The first line should be #lang racket450.
All defines should use the name specified in the exercise (ask if you are unsure).
hw12-tests.rkt: This file should use the #lang racket450/testing language.
It should also require hw12.rkt and define tests for it.
Specifically, it should contain "sufficient" Test cases (e.g., check-equal?, etc.) for each defined function.
README.md: Contains the required README information, including the GitHub repo url.
Submitting
When you are done, submit your work to Gradescope hw12. You must use the "GitHub" Submission Method and select your hw<X>-<LASTNAME>-<FIRSTNAME> repository.
Note that this is the only acceptable way to submit homework in this course. (Do not manually upload files and do not email files to the course staff. Homework submitted via any unapproved methods will not be graded.)

