Skip to content
 
 

Repository files navigation

MiniC - A C-like Language Interpreter in Rust

Rust Tests

MiniC is a small C-like programming language with a full compiler pipeline implemented in Rust: parser → type checker → tree-walking interpreter. The codebase is intentionally compact and well-documented, making it easy to read and extend.

This repository started as the base project for the CIn-UFPE compilers course and was extended by student teams. Each team implemented a language feature end-to-end across all pipeline stages.

int factorial(int n) {
  if n <= 1 { return 1; }
  return n * factorial(n - 1);
}

void main() {
  int result = factorial(10);
  print(result);
}

Features

Area What's included
Language Functions, blocks, if/else, while, arrays, recursion
Types int, float, bool, str, void, arrays (T[])
Pipeline Parser (nom), static type checker, tree-walking interpreter
Stdlib print, readInt, readFloat, readString, sqrt, pow
CLI --check (parse + type-check) and --run (full execution)
Testing Integration tests, CLI tests (shelltest), property-based tests (proptest)
Tooling Nix flake for reproducible dev environment

Tech Stack

  • Rust (2021 edition)
  • nom — parser combinators
  • proptest — property-based testing
  • Nix — reproducible development shell (optional)

Architecture

Source (.minic)
      │
      ▼
┌──────────┐
│  Parser  │  src/parser/     → unchecked AST
└──────────┘
      │
      ▼
┌──────────────┐
│ Type Checker │  src/semantic/  → checked AST
└──────────────┘
      │
      ▼
┌─────────────┐
│ Interpreter │  src/interpreter/ → stdout / runtime errors
└─────────────┘

Shared infrastructure lives in src/ir/ (AST), src/environment/ (symbol table), and src/stdlib/ (built-in functions).


Team Contribution — Project 7: Constant Declarations

Group 7 extended MiniC with immutable bindings via the const keyword, implemented across the full pipeline.

Team

Member
@EGMux
@Shellyda_Barbosa
@rsb6
@Juliana_serafim
@oruns

What we built

Parser (src/parser/statements.rs, src/parser/program.rs)

  • New syntax: const T name = expr;
  • Local constants inside function bodies → Statement::ConstDecl
  • Global constants at program scope → collected in Program::constants

Type Checker (src/semantic/type_checker.rs)

  • Extended the symbol table with mutability (Mutable / Const) alongside type information
  • Rejects any assignment to a const binding (local or global)
  • Type-checks and registers global constants before user-defined functions
  • Global constants are visible in every function body

Interpreter (src/interpreter/exec_stmt.rs)

  • Executes const declarations like regular bindings (enforcement is static)
  • Global constants are evaluated before any function runs

Tests

  • Unit teststests/constant_declaration.rs (parser, type checker, interpreter)
  • Property-based teststests/property/conststatementproperties.rs with configurable complexity via ConstStrategy

Example

const int MAX_SIZE = 100;
const float PI = 3.14159;

int capped(int x) {
  if x > MAX_SIZE { return MAX_SIZE; }
  return x;
}

void main() {
  const int n = 42;
  // n = 5;  ← type error: cannot assign to constant
  print(capped(n));
}
$ minic --check program.minic
'program.minic' is well-typed.

Quick Start

Requirements: Rust toolchain (or Nix — see Nix Development Environment)

cargo build
cargo test
cargo run -- --run tests/fixtures/full_program.minic

Run CLI integration tests (requires a prior cargo build):

shelltest tests/cli/

CLI Usage

minic --check <file.minic>   # parse + type-check only
minic --run   <file.minic>   # parse + type-check + interpret

Run a program

void main() {
  str name = "Alice";
  print(name)
}
$ cargo run -- --run hello.minic
Alice

Type-check without running

$ cargo run -- --check hello.minic
'hello.minic' is well-typed.

Common type errors

Program Error
int x = "hello" expected Int, got Str
double("hello") where double(int) expected Int, got Str
x + true in arithmetic arithmetic operands must be Int or Float
n = 5 where n is const assignment to constant rejected

Exit codes

Situation Code
Success 0
Parse, type, or runtime error 1
Wrong arguments or missing file 1

Documentation

# Document Topic
1 Language reference Syntax, types, operators
2 Pipeline overview Source → execution flow
3 The AST Program representation
4 The parser Grammar and parsing
5 The type checker Static analysis
6 The interpreter Execution model
7 The standard library Built-in functions
8 Testing Test organisation
9 Evolution projects All team project specs

Project Layout

src/
├── ir/           # AST node definitions
├── parser/       # Source text → unchecked AST
├── semantic/     # Type checker: unchecked AST → checked AST
├── environment/  # Shared symbol table
├── interpreter/  # Tree-walking interpreter
└── stdlib/       # Built-in functions (print, sqrt, pow, …)

tests/
├── constant_declaration.rs   # Project 7 — const feature tests
├── property/                 # Property-based tests (proptest)
└── cli/                      # Shelltest CLI integration tests

docs/             # Full documentation

Nix Development Environment

This project ships a Nix flake that pins Rust, Clippy, rustfmt, rust-analyzer, and shelltestrunner to reproducible versions.

Prerequisites

  1. Install Nix

  2. Enable flakes in ~/.config/nix/nix.conf:

    experimental-features = nix-command flakes
    
  3. (Optional) direnv + nix-direnv — the .envrc activates the shell on cd

Usage

nix develop          # enter the dev shell
direnv allow         # or auto-activate with direnv

Inside the shell:

cargo build
cargo test
shelltest tests/cli/
cargo fmt --check
cargo clippy -- -D warnings

Acknowledgements

Base MiniC implementation and course materials by Prof. Rodrigo Bonifacio and the CIN compilers course. Team extensions (Projects 1–10) were developed collaboratively by student groups - see docs/09-projects01.md for the full list.

About

C-like interpreter in Rust: parser, type checker & tree-walking interpreter. Extended with immutable const bindings (Project 7).

Topics

Resources

Stars

Watchers

Forks

Packages

Contributors

Languages