Skip to content

t3hn3rd/rewrite-pascal

Repository files navigation

rewrite-pascal

An OpenRewrite language module for Pascal. Enables lossless semantic tree (LST) parsing, round-trip printing, visitor-based analysis, and recipe-driven refactoring of Pascal source code.

Motivation

This project exists to bring the Moderne platform's tooling - Prethink for AI-assisted code comprehension, TriGrep for structural search, and OpenRewrite recipes for automated refactoring - to Pascal codebases.

The immediate goal is to support analysis of two Free Pascal projects:

  • Asuro OS - a hobby operating system written in Free Pascal (~660 source files, ~100K lines)
  • Wasuro - a WebAssembly virtual machine, also in Free Pascal

Current Status

  • The parser handles pure Pascal syntax and successfully parses 659 of 660 files in the Asuro codebase with full round-trip fidelity (the remaining file uses an unsupported Free Pascal extension)
  • The rewrite-pascal-generator module produces Moderne-compatible V2 LST artifacts that the Moderne CLI (mod run) accepts
  • Prethink runs against the generated LSTs, though its built-in discovery recipes are Java/JS-focused - Pascal-specific discovery recipes (unit dependency graphs, procedure signatures, record types) are a planned next step

Language Support

The parser currently supports pure Pascal syntax (ISO 7185 / Turbo Pascal style). It does not yet support Delphi or ObjFPC language extensions such as:

  • Classes and objects (class, object, interface as OOP construct)
  • Generics (TList<T>)
  • Anonymous methods and closures
  • Advanced RTTI and attributes
  • Operator overloading
  • try/except/finally exception handling
  • String interpolation

Support for Free Pascal's {$mode objfpc} and {$mode delphi} extensions is planned for future phases. Compiler directives are parsed and preserved but not interpreted.

Supported Constructs

  • Programs and units with uses clauses, interface/implementation sections
  • Declarations: var, const, type sections
  • Types: records (packed/bitpacked), enums, sets, arrays, pointers, variant records, subranges
  • Procedures and functions with parameters (var, const, out), local declarations, nested routines
  • Control flow: if/then/else, for/to/downto, while/do, repeat/until, case/of, with
  • Expressions: arithmetic, comparison, boolean, bitwise (shl/shr/xor), field access, indexing, type casts, set values
  • Comments: { }, (* *), // line comments
  • Compiler directives: {$mode}, {$H+}, etc.
  • Inline assembly blocks (asm ... end)

All whitespace and comments are preserved in the LST for lossless round-trip fidelity.

Project Structure

Module Description
rewrite-pascal Core language module: parser, printer, visitor, and LST node definitions
rewrite-pascal-remote Remote serialization support (Sender/Receiver/Validator) for distributed LST processing
rewrite-pascal-generator Standalone tool to parse Pascal projects and produce Moderne-compatible LST artifacts

Building

Requires Java 17+ and uses Gradle 8.12 (wrapper included).

./gradlew build

Run tests:

./gradlew test

Generating LST Artifacts

The rewrite-pascal-generator module produces Moderne-compatible .ast.jar artifacts from Pascal source trees. It requires the Moderne CLI to be installed (for its bundled Java 25 runtime and serialization library).

# Build the generator fat JAR
./gradlew :rewrite-pascal-generator:fatJar

# Run it against a Pascal project (use ; as classpath separator on Windows, : on Linux/macOS)
~/.moderne/cli/dist/jre/bin/java \
  -cp "rewrite-pascal-generator/build/libs/*-all.jar;~/.moderne/cli/dist/lib/moderne-cli.jar" \
  org.openrewrite.pascal.generator.PascalLstGenerator /path/to/pascal/project

The output is written to /path/to/pascal/project/.moderne/build/ as a V2-format LST artifact. This artifact can then be used with mod run to execute OpenRewrite recipes:

mod run /path/to/pascal/project --recipe=<RecipeName>

Using the Parser Programmatically

import org.openrewrite.pascal.PascalParser;
import org.openrewrite.SourceFile;

PascalParser parser = PascalParser.builder().build();
Stream<SourceFile> trees = parser.parse(
    """
    program Hello;
    begin
      WriteLn('Hello, World!');
    end.
    """
);

Architecture

The LST reuses the Java tree infrastructure (Pas extends J) following the same pattern as rewrite-python. This means:

  • PascalVisitor extends JavaVisitor - Java-based visitors can traverse Pascal trees
  • Padding types (JLeftPadded, JRightPadded, JContainer) preserve whitespace
  • The Markers system stores keyword casing and other source-level metadata

The parser is a hand-written recursive descent parser with a custom lexer - no external parser generator dependency.

Dependencies

  • OpenRewrite BOM 8.45.0 (rewrite-core, rewrite-java)
  • rewrite-remote 0.28.0 (for the remote module)
  • Lombok 1.18.34 (compile-only)
  • JUnit 5.11.4 (test)

AI Disclosure

This project was built in part with the assistance of AI (Claude Opus 4.6). The development workflow followed a tight feedback loop:

  1. Write or generate parser code for a Pascal construct
  2. Compile and run the test suite
  3. Analyze failures by comparing printed output against the original source
  4. Fix the parser or printer and repeat

This loop is a natural fit for OpenRewrite's lossless parsing model. The correctness criterion is simple and absolute - the printed output of a parsed file must be identical to the original input, byte for byte. There is no ambiguity about whether the parser is correct: either the round-trip produces the exact original source (including all whitespace, comments, and casing), or it doesn't. That binary signal made it straightforward for AI to identify what was wrong, propose a fix, and verify it in the next iteration.

License

Apache License 2.0

About

An OpenRewrite language module for Pascal. (Github Mirror)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors