Program analysis playground for a simple, imperative language

Overview

Proggers

Proggers is a program analysis playground for a simple, imperative language.

Features

  • Numerical analysis using abstract interpretation
  • Type-checking
  • Compilation to native code
  • Data-flow analyses (planned)
  • Symbolic execution (planned)

Installation

This program needs ELINA to work. See elina-rs for more information and installation instructions. Also, LLVM version 13 is required. Their website may be of interest.

Neither ELINA nor LLVM are required for type-checking and CFG visualization, hence they could be turned into a crate feature. Please, feel free to contribute!

Once the prerequisites are installed, you can install Proggers with: cargo install --git https://github.com/skius/progge.rs

Usage

proggers
  <sourcefile>        # the sourcefile to analyze
  --cfg               # visualize the control flow graph
  --typecheck         # type-check the source
  --analyze           # run the abstract interpreter over the source
  --ast               # print the abstract syntax tree
  -o <outputfile>     # compile source into the executable <outputfile>
  --verbose           # print LLVM IR when compiling

Progge

Proggers can analyze programs written in the Progge language.

Syntax

program:    funcdef*
funcdef:    fn var((var: type,)*) -> type { block }
block:      stmt;*
stmt:       let var = expr
            | var = expr
            | expr[expr] = expr
            | if expr { block } [ else { block } ]
            | while expr { block }
            | return [expr]
expr:       var
            | int
            | bool
            | expr binop expr
            | unop expr
            | var(expr,*)
            | [expr,*]
            | [expr; expr]
binop:      + | - | * | / | % | < | <= | > | >= | == | !=
unop:       - | !
var:        [A-Za-z_][A-Za-z0-9_]*
type:       int | bool | [type]

Semantics

Nothing special. The let-bindings are allowed to shadow previous bindings.

Examples

Numerical Analysis: Proggers is able to analyze below program and find possible return values, as one can see from the bottom right "z: [-1,0]" indicating z may be -1 or 0.

fn analyze(x: int, y: int) -> int {
    if x < y {
        while x < y {
            x = x + 1;
            y = y - 1;
        }
        let z = y - x;
        return z;
    }
    return -2;
}

numerical analysis CFG

Proggers also supports a few directives that make use of the abstract interpretation results.

analyze!: Explicitly prints possible values for a given expression. For example, running proggers --typecheck --analyze analyzer-examples/analyze_loop.progge gives the following feedback (image does not show the full output):

Note that the returned possible values for an expression are an over-approximation.

analyze! feedback

unreachable!: Asserts that a statement is unreachable. For example, running proggers --typecheck --analyze analyzer-examples/unreachable.progge gives the following feedback:

Note that again, unreachability analysis using abstract interpretation computes an over-approximation - that is it may give false positives (warn about reachable unreachable! statements that are in truth unreachable), but may never give false negatives (if there are no warnings about a unreachable!, then it is guaranteed that the statement is unreachable). Once symbolic execution is implemented, that can be used to make guaranteed statements about reachability, i.e. under-approximate.

unreachable! feedback

Type-checking: Proggers notices that there are five distinct variables called x, as one can see in the cleaned-up AST that Proggers returns:

// Original source code
fn analyze(x: int) -> int {
    let x_2 = 10;
    let x = x;
    let x = x + 1;
    x_2 = 5;
    if true {
        let x = 2;
        x = 3;
    } else {
        let x = 4;
    }

    // returns 1
    return x;
}


// Type-checked AST
fn analyze(x_1: int) {
    let x_2_1 = 10;
    let x_2 = x_1;
    let x_3 = (x_2 + 1);
    x_2_1 = 5;
    if true {
        let x_4 = 2;
        x_4 = 3;
    } else {
        let x_5 = 4;
    }
    return x_3;
}

Furthermore, Proggers is able to give nice error messages (thanks to Ariadne):

// Source
fn foo() -> int {
    return true;
}

error message in terminal

See analyzer-examples/tc_bad for more examples.

Compilation: Proggers can compile programs to native code.

$ proggers codegen-examples/factorial.progge -t -o factorial
$ ./factorial 4
24
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
A dynamically typed, interpreted, stack-based language.

Stacc A dynamically typed, interpreted, stack-based language. How does it work? Each call-frame/scope has its own variables and stack, so you can get/

A small scripting language running on V8.

Rook A small scripting language running on V8. After spending a few hours playing with V8, it seems like the only way to make this work is by transpil

Yet Another Programming Language

Yet Another Programming Language

🐱‍👤 Cross-language static library for accessing the Lua state in Garry's Mod server plugins

gmserverplugin This is a utility library for making Server Plugins that access the Lua state in Garry's Mod. Currently, accessing the Lua state from a

luau bindings for the Rust programming language

🌔 luau-rs Luau bindings for the Rust programming language using bindgen ⚠️ Disclaimer This does not provide bindings for everything as luau does not

Czech for the Rust programming language
Czech for the Rust programming language

rez Nejsi you tired from writing Rust programs in English? Do you like saying do prdele or pivo a lot? Would you like to try something different, in a

The official home of the Nyson Programming Language, built off Rust.
The official home of the Nyson Programming Language, built off Rust.

Nyson Programming Language The official home of the Nyson Programming Language, built off Rust. (created by Nyelsonon and AMTitan, 2021) Advertisement

The programming language for scalable development

Pen programming language Pen is the programming language that makes software development scalable, focusing on software maintainability and portabilit

A newborn programming language for extensible software

A newborn programming language for extensible software.

Owner
Niels Saurer
Niels Saurer
A programming environment that aims to help people learn how to program in JavaScript, while giving them a tour on how old computers and their limitations used to be.

This repository is for the new under renovation rewrite of the LIKO-12 project. The legacy version with the original stars and contributions is still

null 1k Jan 5, 2023
A simple programming language made for scripting inspired on rust and javascript.

FnXY Programming Language Quick move: CONTRIBUTING | LICENSE What? FnXY is a simple programming language made for scripting inspired on rust and javas

null 2 Nov 27, 2021
Ethereal - a general-purpose programming language that is designed to be fast and simple

Ethereal is a general-purpose programming language that is designed to be fast and simple. Heavly inspired by Monkey and written in Rust

Synthesized Infinity 21 Nov 25, 2022
A simple interpreter language written in Rust.

Glang Backstory Hello and welcome to the Glang git repository. Game Slang or in short Glang is a super simple interpreted language written in Rust wit

null 6 Nov 12, 2022
A shell scripting language

Slash The system level language for getting the job done. Detailed documentation is available on the Slash site Motivation Bash is an awesome shell, b

null 27 Jun 17, 2022
An interactive scripting language where you can read and modify code comments as if they were regular strings

An interactive scripting language where you can read and modify code comments as if they were regular strings. Add and view text-based visualizations and debugging information inside your source code file.

Sumeet Agarwal 13 Apr 28, 2022
A script language like Python or Lua written in Rust, with exactly the same syntax as Go's.

A script language like Python or Lua written in Rust, with exactly the same syntax as Go's.

null 1.4k Jan 1, 2023
Tyrade: a pure functional language for type-level programming in Rust

A pure functional language for type-level programming in Rust

Will Crichton 286 Jan 1, 2023
An OOP programming language I am making by following Crafting Interpreters.

horba An OOP programming language I am making by following Crafting Interpreters. https://craftinginterpreters.com/ I intend it to have a somewhat C-s

Thomas 3 Dec 5, 2021
Lagoon is a dynamic, weakly-typed and minimal scripting language. 🏞

Lagoon is a dynamic, weakly-typed and minimal scripting language. It draws inspiration from a handful of modern languages including JavaScript, Rust and PHP.

Ryan Chandler 25 Jul 5, 2022