Difference between revisions of "DIP83"

From D Wiki
Jump to: navigation, search
Line 38: Line 38:
 
If DMD is called with this flag it will then rewrite the AST to replace calls to  
 
If DMD is called with this flag it will then rewrite the AST to replace calls to  
  
```D
+
<syntaxhighlight lang="d">
 
assert(lhs == rhs)
 
assert(lhs == rhs)
```
+
</syntaxhighlight>
  
 
with
 
with
  
```D
+
<syntaxhighlight lang="d">
 
assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs)
 
assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs)
```
+
</syntaxhighlight>
  
 
where
 
where
  
```D
+
<syntaxhighlight lang="d">
 
assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs)
 
assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs)
```
+
</syntaxhighlight>
 +
 
 
and similarly for unary expressions.
 
and similarly for unary expressions.
  
Line 65: Line 66:
 
For example a failing
 
For example a failing
  
```D
+
<syntaxhighlight lang="d">
 
assert([1,2,3] == [1,2,4]);
 
assert([1,2,3] == [1,2,4]);
```
+
</syntaxhighlight>
  
 
could fancy-print
 
could fancy-print
  
```
+
<syntaxhighlight lang="d">
 
([1,2,3][2] being 3) != ([1,2,4][2] being 4)
 
([1,2,3][2] being 3) != ([1,2,4][2] being 4)
```
+
</syntaxhighlight>
  
 
or for aggregates a failing
 
or for aggregates a failing
  
```D
+
<syntaxhighlight lang="d">
 
struct A { int x, y; }
 
struct A { int x, y; }
 
auto a = A(1,2);
 
auto a = A(1,2);
 
auto b = A(1,3);
 
auto b = A(1,3);
 
assert(a == b);
 
assert(a == b);
```
+
<syntaxhighlight>
  
 
could fancy-print
 
could fancy-print
  
```
+
<syntaxhighlight lang="d">
 
(a.y being 2) != (b.y being 3)
 
(a.y being 2) != (b.y being 3)
```
+
<syntaxhighlight>
 
 
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
+
Parts of the solution list at
  
 
https://issues.dlang.org/show_bug.cgi?id=5547#c3
 
https://issues.dlang.org/show_bug.cgi?id=5547#c3
  
can be reused, right?
+
including rewriting/expansion of '''AssertExpr''' could probably reused.
  
 
== Impact ==
 
== Impact ==

Revision as of 17:11, 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 from within 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

assert(lhs == rhs)

with

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

where

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

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

<syntaxhighlight lang="d"> struct A { int x, y; } auto a = A(1,2); auto b = A(1,3); assert(a == b); <syntaxhighlight>

could fancy-print

<syntaxhighlight lang="d"> (a.y being 2) != (b.y being 3) <syntaxhighlight>

Parts of the solution list at

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

including rewriting/expansion of AssertExpr could probably reused.

Impact

Copyright

This document has been placed in the Public Domain.