Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

6 Commits

Repository files navigation

PrologLint

Prolog-powered static analyzer for Python code. Detects 13+ code smells through declarative pattern matching on ASTs.

Python 3.xSWI-PrologAcademic License

AboutFeaturesQuick StartUsageDetected PatternsTesting


About

PrologLint leverages Prolog's logical inference capabilities to perform static analysis on Python source code. The tool converts Python's Abstract Syntax Tree (AST) into Prolog facts, enabling powerful declarative pattern matching to detect code smells and anti-patterns.

How It Works

Python Source (.py) → JSON AST → Prolog Facts (.pl) → Pattern Analysis
↓ ↓ ↓ ↓
ast_parser.py ast2json json_to_prolog.pl analyzer.pl

Features

Core Capabilities

  • AST Parsing — Converts Python code to structured Prolog facts
  • Tree Navigation — Hierarchical traversal with parent/2, children/2, ancestor/2
  • Tree Visualization — Pretty-print AST with configurable verbosity
  • Pattern Detection — 13+ code smell detectors

Advanced Analysis

  • Accumulator Pattern Detection — Identifies proper accumulator usage in loops
  • Infinite Loop Detection — Catches always-true conditions and unmodified loop variables
  • Complexity Analysis — Flags excessive nesting, long functions, too many parameters

Quick Start

Prerequisites

  • Python 3.x
  • SWI-Prolog 9.x
  • ast2json Python package

Installation

# Clone the repository
git clone https://github.com/mathisdelsart/PrologLint.git
cd PrologLint
# Install Python dependencies
pip install -r requirements.txt

Analyze Your First File

# Option 1: Using the automation script
./src/analyze.sh path/to/your_file.py
# Option 2: Using Make
make analyze FILE=path/to/your_file.py
# Option 3: Step by step (see Usage section)

Usage

Automated Pipeline

The easiest way to analyze a Python file:

./src/analyze.sh examples/demo/lot_of_bad_patterns.py

This will:

  1. Parse the Python file to JSON
  2. Convert JSON to Prolog facts
  3. Launch SWI-Prolog with the analysis loaded

Manual Step-by-Step

Step 1: Convert Python to JSON

python3 src/ast_parser.py examples/demo/lot_of_bad_patterns.py
# Output: examples/demo/lot_of_bad_patterns.json

Step 2: Convert JSON to Prolog Facts

swipl -g "consult('src/json_to_prolog.pl'), load_and_save_python('examples/demo/lot_of_bad_patterns.json')" -t halt
mv facts.pl examples/demo/lot_of_bad_patterns.pl

Step 3: Analyze the Code

swipl src/analyzer.pl examples/demo/lot_of_bad_patterns.pl

Analysis Commands

Once in the Prolog REPL:

% Check all patterns at once
?- check_all_patterns_respected.
% Visualize the AST
?- print_tree. % Condensed view
?- print_tree(verbose). % Detailed view
?- print_tree(12). % Subtree from node 12% Specific pattern checks
?- has_accumulator_patterns.
?- has_all_functions_have_return_as_last_statement.
?- has_all_loop_have_used_vars.

Detected Patterns

PatternDescriptionPredicate
Empty Constructor__init__ with only passhas_empty_constructor/0
Constructor Returns__init__ returning a valuehas_constructor_return/0
Parameter ReassignmentReassigning function parametershas_parameters_reassignement/0
Increment in For-LoopManual loop variable modificationhas_increment_in_forloop/0
Early ReturnReturn statements inside loopshas_early_return/0
Too Much Indentation3+ levels of nestinghas_too_much_indent/0
Print Instead of ReturnFunctions ending with printhas_print_instead_return/0
Infinite LoopAlways-true while conditionshas_infinite_loop/0
Too Long FunctionFunctions exceeding 15 statementshas_too_long_function/0
Too Many ParametersFunctions with 5+ parametershas_too_many_parameters/0
Unused Loop VariablesLoop variables never usedhas_all_loop_have_used_vars/0
Missing ReturnFunctions not ending with returnhas_all_functions_have_return_as_last_statement/0
Accumulator PatternProper accumulator usagehas_accumulator_patterns/0

Repository Structure

PrologLint/
├── src/
│ ├── analyzer.pl # Main analysis engine (pattern detection)
│ ├── json_to_prolog.pl # JSON to Prolog facts converter
│ ├── ast_parser.py # Python AST to JSON parser
│ ├── tests.pl # Test suite (76 tests)
│ └── analyze.sh # Automation script
├── examples/
│ ├── demo/ # Good/bad practice demonstrations
│ ├── basic_predicates/ # Tree navigation examples
│ ├── accumulator_patterns/ # Accumulator pattern tests
│ ├── constructor_empty/ # Empty constructor tests
│ ├── constructor_return/ # Constructor return tests
│ ├── early_return/ # Early return tests
│ ├── increment_in_forloop/ # For-loop increment tests
│ ├── infinite_loop/ # Infinite loop tests
│ ├── parameters_reassignement/# Parameter reassignment tests
│ ├── print_instead_return/ # Print vs return tests
│ ├── return_last_statement/ # Return placement tests
│ ├── too_long_function/ # Function length tests
│ ├── too_many_parameters/ # Parameter count tests
│ ├── too_much_indent/ # Indentation depth tests
│ └── unused_loop_vars/ # Unused variable tests
├── Makefile # Build automation
├── requirements.txt # Python dependencies
└── README.md

Testing

Run the complete test suite:

make test# or
swipl -g "consult('src/tests.pl'), run_tests" -t halt

The test suite includes 76 tests covering:

  • Basic predicates (parent/2, children/2, ancestor/2)
  • Tree visualization (print_tree/0, print_tree/1)
  • All 13 pattern detection predicates
  • Both positive (yes.pl) and negative (no.pl) test cases

Author

Mathis DELSART

License

This project is developed for academic purposes as part of university coursework.


Built for LINFO2335 - Programming Paradigms @ UCLouvain (Université catholique de Louvain).

Leveraging declarative programming for smarter code analysis

About

Prolog-powered static analyzer for Python code. Detects 13+ code smells through declarative pattern matching on ASTs.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages