Ste nas srečali na Brdu? Sestanek
← Back to Toni

Compilers & Language Engineering

PINS Compiler Course

Teaching Assistant, Compilers and Virtual Machines · University of Ljubljana, Faculty of Computer and Information Science

The compilers course taught at the University of Ljubljana: 8 progressive assignments that take 100+ students from lexer to working interpreter

2022-2024 Java
PINS Compiler Course screenshot

Overview

Teaching assistant work for the Compilers and Virtual Machines (PINS) course at the University of Ljubljana: a complete set of 8 progressive compiler assignments (DN1-DN8), designed and maintained for the students taking it. Each assignment builds incrementally on the previous one, guiding students from lexical analysis through to a working interpreter -- growing from 12 Java source files to 73 files. The course framework includes a clean visitor-based architecture, external semantic maps (NodeDescription<T>), progressive pretty-printers, and an annotation-driven CLI.

Architecture

PINS Compiler Course architecture

The architecture uses the visitor pattern for phase separation -- an 18-overload Visitor interface where each compiler phase is a separate implementation. External semantic maps via NodeDescription<T> (a generic HashMap<Ast, T> wrapper) attach semantic information to AST nodes without mutating them. Phase-gated execution chains phases sequentially with early termination, letting students test each assignment in isolation.

Key concepts

NodeDescription<T> External Semantic Maps

A generic HashMap<Ast, T> wrapper that attaches semantic information (definitions, types, frames, accesses) to AST nodes without mutating them. Each phase creates its own NodeDescription and passes it to subsequent phases, enforcing clean phase separation and making semantic analysis results explicit.

Code highlights

NodeDescription<T> -- The Central Teaching Abstraction
public class NodeDescription<T> {
    private Map<Ast, T> storage = new HashMap<>();

    public Optional<T> valueFor(Ast node) {
        return Optional.ofNullable(storage.get(node));
    }

    public boolean store(T value, Ast forNode) {
        return storage.put(forNode, value) == null;
    }
}

Highlights

  • Taught the course as teaching assistant at the Faculty of Computer and Information Science, University of Ljubljana
  • Designed a complete 8-assignment compiler course from lexical analysis to a working interpreter (12 to 73 source files incrementally)
  • NodeDescription<T> as central teaching abstraction: semantic analysis results as maps from AST nodes to values, enforcing phase separation
  • Progressive pretty-printers (V1-V4) where each version accumulates more semantic data, visualizing compiler understanding growth
  • Course framework directly derived from own BSc/MSc compilers, compressed into an accessible educational format