9.0.0.1

9 — Static Types🔗

Due Thursday, 06 November 2025, 11:59:59pm

Purpose to build a model of a type checker for a class-based language

Delivery Deliver your solutions in a directory called 9 within your assigned GitHub repository. The directory should contain the following items:

  • the executables xtypes as specified below;

  • the sub-directory 9/Tests/ with the required integration test; and

  • an optional sub-directory called 9/Other/ for all auxiliary files.

The directory 9/ may also contain a Makefile (see Make) in case you need us to build your executable. An executable should not be checked into a repository.

Programming Task Using your favorite programming language, you are to create a complete model of the Type language: its syntax and its semantics. The Type language impose type constraints that “harden” well-formed and valid syntax—meaning, running such a program will not create many of the situations that causes the existing CESK machine to stop and signal an error.

  Type       ::= Number | Shape

  Shape      ::= ((FieldType^*) (MethodType^*))

  FieldType  ::= (FieldName Type)

  MethodType ::= (MethodName (Type^*) Type)

Here Number is the literal word 'Number'.

Any two FieldNames in a Shape must be distinct. Any two MethodNamess in a Shape must also be distinct.

Figure 26: The concrete syntax of types in the Type language

The articulation of such stringent type constraints on well-formed systems requires a language of its own, the language of types. Figure 26 presents the grammar of this notation. While Number describes expressions that are going to yield a numeric value in the CESK machine—if their evaluation terminates properly—Shape describes both classes in program text and and expressions that yield objects in the machine.

  TypedSystem ::= (TypedModule^*

                   Import^*

                   Declaration^*

                   Statement^*

                   Expression)

  

  TypedModule ::= (tmodule ModuleName Import^* Class Shape)

Figure 27: The concrete syntax of typed systems in the Type language

The BNF grammar in figure 27 describes the syntax of The next milestone will deal with a language that mixes typed and untyped modules. Hence, we use the keyword tmoodule in this BNF Type. It differs from the syntax of Class in only one place: every module comes with a Shape constraint that the class in the module must satisfy. In the context of type systems, we call such a constraint a judgment. Checking the validity of a Type program requires two kinds of judgments:
  • A judgment of the shape CC ⊢ Syn says that “in context CC the well-formed syntax Syn is also valid.” For example, ⊢ (mod1 ... modK imp1 ... impI def* stmt* exp) says a complete system—consisting of K modules, I import specifications, a sequence of definitions (def*), a sequence of statements (stmt*), and a final expression (exp) is valid syntax.

  • A judgment of the shape CC ⊢ Syn ⟹ R says that “in context CC the well-formed syntax Syn is valid and the judgment results in R.” For example, read SClasses, TVar ⊢ n ⟹ Number as “in the context of class types according to SClasses and variable types according to TVar, n is valid syntax, and the judgment produces the type Number.”

A collection of antecedent-conclusion or inference rules is used to state when we may conclude that such judgments hold. Figures 20, 21, 22, 23, 24, and 25 display rules that express how the satisfaction of this constraint is checked. These rules rely on the following assumptions:
  • Modules is a set of modules.

  • SClasses is a function that maps ClassNames to Shapes.

  • TVar is a function that maps Variables to Types.

  • Subscripts range over an (interval of the) natural numbers.

Each set of rules in the referenced figures covers a cluster of syntax:
  • Figure 20 covers the distinct judgments for complete systems, sequences of modules, individual modules, and (sequences of) import specifications.

  • Figure 21 displays judgments about the validity of individual classes and methods.

  • The rules in figure 22 determine the validity of bodies of blocks, systems, and methods.

  • Figure 23 explain the validity of sequences of declarations and individual declarations.

  • Figures 24 and 25 cover the validity of statements and expressions, respectively.

Plan The following is a concrete plan for building the model of Type:
  • Adapt the AST data representation from Module Types to Types Mixed. It must accommodate one extra attribute of modules—the Shape of the defined Class. Update your parser for Module accordingly.

    Hint In anticipation of the remaining milestones, modify your AST representation of class so that it may optionally come with a Shape.

  • Modify the existing validity checks for Module to accommodate the extra attribute as needed.

  • Implement the type checker in a bottom-up fashion, one set of rules after another.

    Hint Since the type checker is called only when the preceding validity-checking passes have “blessed” the AST, your implementation of the type checker may rely on the logical properties of ASTs that these passes establish.

  • Add a pass that turns the AST of a well-formed and well-typed Type system into a Module AST so that the linker from 8 — Modules can create a Class program, which can then be run on the Class CESK machine.

    Note Depending on your chosen implementation language and your choice of AST data representation, your linker might already work for Typed ASTs or you might find it easy to adapt the linker so that it works this way.

  • Comment out the cases of the CESK transition function that are superfluous due to the type system. That is, identify the cases in the transition function that a well-formed and valid system can no longer trigger.

Notice that the presentation of the rules—the construction plan—is presented in a top-down fashion. Building the type checking functions in a bottom-up manner is needed so you can unit-test each layer by itself and gain confidence about its functionality before proceeding to the next layer upwards.}

ExampleFF is an Example whose Names also contain the following keywords: if0, while0, block, def, =, /, +, ==, class, isa, method, new, >, tmodule, import.

The xtypes program reads one ExampleFF from STDIN, constructs the AST, performs the validity checks, links the system into a complete program, runs the CESK machine, and writes one of the following strings to STDOUT: The outcomes are listed in the order in which they may occur for a given program.
  • "parser error" if the given ExampleFF is not an element of the Type grammar;

  • "duplicate module name" if in the well-formed Type system two of the module definitions come with the same name;

  • "duplicate method, field, or parameter name" if in the well-formed Type system one class definition one method definition, or one Shape comes with (at least) two fields, methods, or parameters that have the same name;

  • "undeclared variable error" if in the well-formed Type system one of its variable occurrences comes without declaration or one occurrence of a ClassName in a statement or an expression comes without class definition;

  • "type error" if the well-formed Type system fails to satisfy one of the typing judgments;

  • a number n if the CESK machine produces a number n for the well-formed and valid Typed system;

  • "run-time error" if the CESK machine produces an error outcome for the well-formed and valid Typed system.

Stop! Why does the above list not include "object" anymore? Compare with 8 — Modules.

Testing Task Create 10 integration tests for xtypes.

A test always consists of inputs, expected output, and an automated procedure for comparing the actual output with the expected one. — For this course, an integration test consists of a pair of files: n-in.ss, the input file, and n-out.ss, the expected output file, where n is an integer between 0 and the requested number of tests (exclusive). The comparison procedure is (string or numeric) equality on the content of the output file and the actual output. — Constraint No test file may exceed the size limit of 5Kb.