www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Readonly asserts and more

reply bearophile <bearophileHUGS lycos.com> writes:
If you think the following idea is useful, then I can turn it into an
enhancement request (or even a little DEP).

Many of the features that D adds to C seems to consist in statically verified
fences and walls that can be added to the flow of information across different
parts of a program state. So such parts can't change each other, hopefully
helping avoid some bugs.

Recently Michel Fortin has written:
What you really need is to have a const view of the global state. And this
could apply to all asserts too.<
Generally I'd like a program to behave in the same way in release and not release mode (Bug 3856 too is related to this). So it can be nice if the type system assures that asserts have only a const view of the program state. This shows what I'd like to avoid: import std.stdio: writeln; bool test(ref int x) { x++; return true; } void main() { int x; writeln(x); assert(test(x)); writeln(x); // prints 0 in release mode, 1 otherwise } To avoid that, according to Michel, it can be defined a readonly attribute that is transitive and is similar to pure: import std.stdio: writeln; readonly bool test(ref int x) { x++; // not allowed in a readonly function return true; } void main() { int x; writeln(x); assert(test(x)); writeln(x); } readonly disallows writing global variables, and instance/static attributes, but they can be read if visible. Local variables inside the function can be written/created too as in pure functions. pure functions are a subset of readonly functions, so the type system has to allow (code untested): pure int sqr1(int x) { return x * x; } readonly int sqr2(int x) { return x * x; } void main() { readonly int function(int x)[] funcs = [&sqr1, &sqr2]; } And it has to disallow: pure int sqr1(int x) { return x * x; } readonly int sqr2(int x) { return x * x; } void main() { pure int function(int x)[] funcs = [&sqr1, &sqr2]; } If the D language gains a little more reflectivity, that is a little more read-only access to some of the metainformation the compiler has about the code, then readonly can even become an user-defined attribute defined in a Phobos module, using only the D language itself (you have to import it to compile the module). This is a way to extend a bit the D type system with D. Maybe you can do that with a __traits that allows to know the global and local names used inside a function plus if they are just read or read/written: int y; void foo(int x) { writeln(x); y++; } foreach (name; __traits(getNamesUsedIn, "foo")) writefln(typeid(typeof(name)), " ", __traits(isWrittenIn, name, "foo")); Prints: int false int true Time ago I have shown something related, but here it uses a second language, JavaScript, on C++ code: http://lwn.net/Articles/370717/ https://developer.mozilla.org/En/Dehydra/Using_Dehydra Maybe the outer attribute I have discussed time ago too can be defined with those getNamesUsedIn and isWrittenIn traits: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=106098 Bye, bearophile
Mar 01 2010
parent bearophile <bearophileHUGS lycos.com> writes:
In Java there are few uncommon situations where it's useful to put side effects
inside asserts.

This Java code manipulates an array, and then wants to assert something about
this computation. To perform such tests it needs the old array, that has to be
copied. But in release mode the programmer doesn't want to perform such extra
array copy, so the array copy too is inside an assert:


void foo(final int[] array) {
    // Inner class that saves state and performs final consistency check
    class DataCopy {
        private int[] arrayCopy;
        DataCopy() { arrayCopy = (int[]) array.clone(); }
        boolean isConsistent() { return Arrays.equals(array, arrayCopy); }
    }

    DataCopy copy = null;

    // Always succeeds; has side effect of saving a copy of array
    assert ((copy = new DataCopy()) != null);

    ... // Manipulate array

    // Ensure array has same ints in same order as before manipulation.
    assert copy.isConsistent();
} 


In D code I prefer to solve this problem with a debug{/*array copy*/}, and keep
my asserts side-effects free.

Bye,
bearophile
Mar 02 2010