Difference between revisions of "DIP83"

From D Wiki
Jump to: navigation, search
(Created page with "{| class="wikitable" !Title: !'''Configurable Assert Diagnostics''' |- |DIP: |83 |- |Version: |1 |- |Status: |Draft |- |Created: |2015-10-01 |- |Last Modified: |{{REVISIONYEAR...")
 
Line 28: Line 28:
  
 
== Rationale ==
 
== Rationale ==
 +
 +
Typically added/modified by the developer by changing the flags to calls to rdmd/dub/scons etc upon failure with `-unittest` for a specific failing module. This will be more convenient than explicitly adding the prints of `lhs` and `rhs` in the failing unittest.
  
 
== Description ==
 
== Description ==
 
This DIP proposes to add library-level configurable diagnostics to failing calls to '''assert(expr)''' typically called in '''unittest'''-blocks.
 
This DIP proposes to add library-level configurable diagnostics to failing calls to '''assert(expr)''' typically called in '''unittest'''-blocks.
 +
 +
This diagnostics is activated only when DMD is called with a specific command line flag, say `-unittest=verbose`.
 +
 +
If DMD is called with this flag it will then rewrite the AST to replace calls to
 +
 +
```D
 +
assert(lhs == rhs)
 +
```
 +
 +
with
 +
 +
```D
 +
assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs)
 +
```
 +
 +
where
 +
 +
```D
 +
assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs)
 +
```
 +
and similarly for unary expressions.
 +
 +
The default implementation of `assertBinOp` (preferrably defined somewhere in `druntime`) would be some standard D code that mimics the current behaviour of `assert(expression)` by throwing an `AssertExpression` if `cast(bool)expression` is `false` (dont know about the behaviour of nothrow/@nogc discussed above though). The Phobos-developer can then do what he likes with the information he needs in the extra arguments in specific templated overloads of `assertBinOp`.
 +
 +
This specific behaviour could be extendable by adding (typically templated) overloads of `assertBinOp` for specific sets of types (concepts).
 +
 +
Then we could get the extendability we want in testing-frameworks such as this without adding a new `assert`-overload-set and without sacrifycing default memory usage in DMD/Phobos unittests.
 +
 +
Further with this solution we could add cool diagnostics behaviour in `assertBinOp` for failing array/range comparisons aswell in a format. This diagnostics could even have different pretty printing backends such as HTML.
 +
 +
For example a failing
 +
 +
```D
 +
assert([1,2,3] == [1,2,4]);
 +
```
 +
 +
could fancy-print
 +
 +
```
 +
([1,2,3][2] being 3) != ([1,2,4][2] being 4)
 +
```
 +
 +
or for aggregates a failing
 +
 +
```D
 +
struct A { int x, y; }
 +
auto a = A(1,2);
 +
auto b = A(1,3);
 +
assert(a == b);
 +
```
 +
 +
could fancy-print
 +
 +
```
 +
(a.y being 2) != (b.y being 3)
 +
```
 +
 +
Thereby giving D yet another feature, I've not seen in any other language :)
 +
 +
If needed I'd be more than happy to help out implementing this solution in dmd/druntime/phobos. I'm guessing that parts of the solution list at
 +
 +
https://issues.dlang.org/show_bug.cgi?id=5547#c3
 +
 +
can be reused, right?
  
 
== Impact ==
 
== Impact ==

Revision as of 17:04, 1 October 2015

Title: Configurable Assert Diagnostics
DIP: 83
Version: 1
Status: Draft
Created: 2015-10-01
Last Modified: 2015-10-1
Author: Per Nordlöw
Links:

Abstract

Allow for assert's to do pretty printing of its failing expression. Printing is configurable via specific sets of (template) function overloads.

Rationale

Typically added/modified by the developer by changing the flags to calls to rdmd/dub/scons etc upon failure with `-unittest` for a specific failing module. This will be more convenient than explicitly adding the prints of `lhs` and `rhs` in the failing unittest.

Description

This DIP proposes to add library-level configurable diagnostics to failing calls to assert(expr) typically called in unittest-blocks.

This diagnostics is activated only when DMD is called with a specific command line flag, say `-unittest=verbose`.

If DMD is called with this flag it will then rewrite the AST to replace calls to

```D assert(lhs == rhs) ```

with

```D assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs) ```

where

```D assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs) ``` and similarly for unary expressions.

The default implementation of `assertBinOp` (preferrably defined somewhere in `druntime`) would be some standard D code that mimics the current behaviour of `assert(expression)` by throwing an `AssertExpression` if `cast(bool)expression` is `false` (dont know about the behaviour of nothrow/@nogc discussed above though). The Phobos-developer can then do what he likes with the information he needs in the extra arguments in specific templated overloads of `assertBinOp`.

This specific behaviour could be extendable by adding (typically templated) overloads of `assertBinOp` for specific sets of types (concepts).

Then we could get the extendability we want in testing-frameworks such as this without adding a new `assert`-overload-set and without sacrifycing default memory usage in DMD/Phobos unittests.

Further with this solution we could add cool diagnostics behaviour in `assertBinOp` for failing array/range comparisons aswell in a format. This diagnostics could even have different pretty printing backends such as HTML.

For example a failing

```D assert([1,2,3] == [1,2,4]); ```

could fancy-print

``` ([1,2,3][2] being 3) != ([1,2,4][2] being 4) ```

or for aggregates a failing

```D struct A { int x, y; } auto a = A(1,2); auto b = A(1,3); assert(a == b); ```

could fancy-print

``` (a.y being 2) != (b.y being 3) ```

Thereby giving D yet another feature, I've not seen in any other language :)

If needed I'd be more than happy to help out implementing this solution in dmd/druntime/phobos. I'm guessing that parts of the solution list at

https://issues.dlang.org/show_bug.cgi?id=5547#c3

can be reused, right?

Impact

Copyright

This document has been placed in the Public Domain.