Final Project – Object-Oriented Programming Languages (LPO)
📌 Project Overview
This repository contains the final project for the course Object-Oriented Programming Languages (LPO) @ University of Genoa.
The project consists of the implementation of an extension of a custom programming language interpreter, originally developed during the final Java laboratories of the course. The interpreter is implemented in Java, while the static and dynamic semantics of the language are defined following the Visitor design pattern, as required.
🛠️ Technologies and Design Choices
Java – implementation of the interpreter
Visitor Pattern – used for both static and dynamic semantics
Command-line interface (CLI) – interaction with the interpreter
TreeMap (java.util) – used for dictionary values to preserve key ordering
⚙️ Command Line Interface
The interpreter can be executed from the command line with the following options:
-i Reads the program to execute from a text file. If not specified, input is read from standard input.
-o Writes the output of the program to a text file. If not specified, output is written to standard output.
-ntc (no-type-checking) Executes the program without performing static type checking before execution.
🧩 Language Extension
The project extends the base language with new syntactic constructs, data types, and statements.
🔹 New Language Features
Dictionary literal
[ Exp : Exp ]
Dictionary operations
Access (get): Exp [ Exp ]
Deletion (delete): Exp [ Exp : ]
Update (update): Exp [ Exp : Exp ]
Iteration statement
for ( var IDENT of Exp ) Block
All dictionary operators have the same precedence, are left-associative, and bind more tightly than unary operators.
🧠 Static Semantics
Dictionaries have type DictType ty
Keys must always be of type Int
Values must be homogeneous within the same dictionary
The for statement introduces a new scoped variable of type Pair(Int, ty)
Static semantics are enforced unless the -ntc option is used
⚡ Dynamic Semantics
Dictionary values are represented using immutable maps
Dictionary operations are functional (they do not modify existing dictionaries)
Keys are iterated in ascending order
Runtime exceptions are raised for invalid operations (e.g. invalid key access)