Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nrc/libhoare
Design by contract style assertions for Rust
https://github.com/nrc/libhoare
Last synced: 17 days ago
JSON representation
Design by contract style assertions for Rust
- Host: GitHub
- URL: https://github.com/nrc/libhoare
- Owner: nrc
- Created: 2014-07-13T08:10:53.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2021-01-04T22:29:16.000Z (almost 4 years ago)
- Last Synced: 2024-09-17T15:53:10.392Z (about 2 months ago)
- Language: Rust
- Size: 56.6 KB
- Stars: 245
- Watchers: 14
- Forks: 18
- Open Issues: 8
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# LibHoare
Simple Rust support for design by contract-style assertions. Supports
* preconditions (`precond`),
* postconditions (`postcond`),
* invariants (pre and post) (`invariant`).Each macro takes a predicate given as a string parameter. Each macro is
available in a `debug_` version which only checks the assertion in debug builds,
they should be zero overhead in non-debug builds. You can use `result` inside a
postcondition to get the value returned by the function.Preconditions are checked on entry to a function. Postconditions are checked when
leaving the function by any path.(The library is named for Tony, not Graydon. Or rather it is named for the logic
which was named after Tony).## Using libhoare
You can use libhoare with Cargo by adding
```toml
[dependencies.hoare]
git = "https://github.com/nick29581/libhoare.git"
```to your projects Cargo manifest.
Otherwise, download this repo, build it (see build instructions below), make
sure the path to the compiled libhoare is on your library path in some way (one
way of doing this is to `export LD_LIBRARY_PATH=/path/to/libhoare/obj` before
building).Then (whether or not you used Cargo), in your crate you will need the following
boilerplate:```rust
#![feature(plugin, custom_attribute)]#![plugin(hoare)]
```Then you can use the macros as shown below.
## Examples:
```rust
#[precond="x > 0"]
#[postcond="result > 1"]
fn foo(x: int) -> int {
let y = 45 / x;
y + 1
}struct Bar {
f1: int,
f2: int
}#[invariant="x.f1 < x.f2"]
fn baz(x: &mut Bar) {
x.f1 += 10;
x.f2 += 10;
}fn main() {
foo(12);
foo(26);
// task '' failed at 'precondition of foo (x > 0)'
// foo(-3);let mut b = Bar { f1: 0, f2: 10 };
baz(&mut b);
b.f2 = 100;
baz(&mut b);
b.f2 = -5;
// task '' failed at 'invariant entering baz (x.f1 < x.f2)'
// baz(&mut b);
}
```You can use contracts on methods as well as functions, but they are not as well
tested.## Contents
All the code for checking conditions is in `libhoare`. Currently, there is only
a single file, `lib.rs`.The `test` directory contains unit tests for the library.
The `eg` directory contains a few examples of how to use the library:
* hello.rs is a very simple (hello world!) example of how to use an invariant
(useful as a basic test case);
* doc.rs contains the examples above, so we can check they compiler and run;
* lexer.rs is a more realistic example of use - a simple (and certainly not
industrial-strength) lexer for a very small language.## Building
To build libhoare from the top level of your checked out repo run
```
cargo build
```(if using cargo) or
```
$RUSTC ./libhoare/lib.rs
```This will create libhoare.rs in the current directory, you might want to specify
an output file using `-o`.To build the examples run `eg.sh` in the top level and to run the tests run `tests.sh`.
Both of these assume that you have a sibling directory called `obj` and that you
used```
$RUSTC ./libhoare/lib.rs -o "../obj/libhoare.so"
```to build libhoare. Examples are created in `../obj`
## TODO
* add tests to RustCI
* tests for debug_ versions of macros - what is the best way to test this?
* better use of macro stuff? (I'm a total beginner at syntax extensions, this all
could probably be implemented better).
* better spans.
* better names for scopes (`` rather than ``, etc.
These appear in the user-visible error messages, so it would be nice if they could
be informative).Wish list:
* object invariants (I think this would need compiler support, if it is possible
at all. You would add `[#invariant="..."]` to a struct, enum, etc. and the
invariant would be checked on entering and leaving every method defined in any
impl for the object).