Re: Tuple DIP

2018-09-20 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 13 January 2018 at 18:28:55 UTC, Timon Gehr wrote:
However, this proposal is independent of all the other ones, so 
in the end it is up to Walter and Andrei.


Have there been any discussions regarding the semantics of _?

struct G { ~this() { writeln("destruct"); } }
void main() {
auto _ = G();
writeln("here");
}

The DIP currently says this should print first "here" and then 
"destruct".


However, as you cannot access the variable later, you most often 
want to discard the data right away, i.e. print first "destruct" 
and then "here".


I personally find the second interpretation more useful.



Re: John Regehr on "Use of Assertions"

2018-09-01 Thread Guillaume Boucher via Digitalmars-d
On Saturday, 1 September 2018 at 20:15:15 UTC, Walter Bright 
wrote:
Note the "may or may not be evaluated." We've debated this here 
before. I'm rather pleased that John agrees with me on this.


I.e. the optimizer can assume the expression is true and use 
that information to generate better code, even if the assert 
code generation is turned off.


You only read what you want to hear or what?

His essay is built up in a way where he shows two opposing 
interpretations of
asserts.  Assertions as "bug detectors" or as "optimizer hints".  
He then
discusses which one of those is the better one.  The quote you 
gave is the
definition from a proponent of the "optimizer hint" camp and not 
necessarily what

John agrees with.

His conclusion in the essay is that in general it makes sense to 
have assertions
enabled even in release builds because a slightly worse 
performance is worth it
to have more robust programs and he has backed this up by a lot 
of examples.


Furthermore, he wrote a follow-up post about "assume"
(https://blog.regehr.org/archives/1096).  Assume seems to be what 
you think

assert is, but there is actually a *huge* difference.

We assert a condition when we believe it to be true in every 
non-buggy
execution of our program, but we want to be notified if this 
isn’t the case. In
contrast, we assume a condition when our belief in its truth is 
so strong that
we don’t care what happens if it is ever false. In other words, 
while
assertions are fundamentally pessimistic, assumptions are 
optimistic.


So no, John doesn't agree with you on this *at all*.



Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread Guillaume Boucher via Digitalmars-d

On Tuesday, 31 July 2018 at 07:49:40 UTC, Shachar Shemesh wrote:

On 31/07/18 10:29, Mike Franklin wrote:

Please clarify if I'm missing the point.


You are. I want something along the lines of:
assertEQ(a, b, "a and b are not equal");

When run, it would issue an assert that says:
Assertion failed: 3!=7: a and b are not equal


What D really needs is power asserts.  assertEQ's and its 
companions (assertLT, assertLE, ...) feel just like hacks.


Power asserts come from Groovy and look like this 
(http://groovy-lang.org/semantics.html#_power_assertion):


assert calc(x,y) == [x,z].sum()
   || |  |   | |  |
   15   2 7  |   2 5  7
 false

A poorer version exists in C++ 
(https://www.boost.org/doc/libs/1_67_0/libs/test/doc/html/boost_test/testing_tools/boost_test_universal_macro.html)
and of course any language with decent metaprogramming facilities 
can implement them as a library solution (such as Rust: 
https://github.com/gifnksm/power-assert-rs and Go: 
https://github.com/ToQoz/gopwt).
If you can not go the route of metaprogramming, provide an assert 
backend (Javascript: 
https://github.com/power-assert-js/power-assert).
D needs something like this as well, and you can not get there 
just with lazy.


Re: Tuple DIP

2018-01-16 Thread Guillaume Boucher via Digitalmars-d

On Friday, 12 January 2018 at 22:44:48 UTC, Timon Gehr wrote:
foreach((sum, diff); [(1, 2), (4, 3)].map!((a, b) => (a + b, a 
- b)))

{
writeln(sum, " ", diff);
}


I'm not a big fan of the foreach syntax.  It's so easy to forget 
or accidentally add parentheses while coding, or read it wrongly 
while skimming over the code.


Not sure if anything can be done against that, though.  Maybe add 
an alternate "for (.. in ..)" syntax that doesn't have that 
problem?




Re: Should we add `a * b` for vectors?

2017-10-06 Thread Guillaume Boucher via Digitalmars-d
On Thursday, 5 October 2017 at 22:04:10 UTC, Jonathan M Davis 
wrote:
It's far cleaner for them to be tied to the type - especially 
when you consider that it's not possible to differentiate 
between conflicting overloadeded operators.


In other words, we lose global uniqueness of operators if we were 
to allow free functions to implement operators.


Knowing which function is called when we see its name is very 
important for reading code.  That's why we have those anti 
hijacking rules: they disallow cases where the compiler knows 
that the call can be misleading (or can silently break existing 
code).  Another, more tricky case is when there are two functions 
with the same name in the project you are working on, but only 
one of them is being imported.  If you read the code, you are 
unsure which one is called.  The anti-hijacking rules won't work 
in that case.
Fortunately, a good naming scheme avoids those problems so they 
are not a big problem in practice.


Those problems will pop up, however, if we allow them for 
operators.  Without further regulations, different 
implementations for operators are almost guaranteed, which will 
lead to uncertainty and distrust in code using operators.




Besides, I don't how it should work without changes to lookup 
rules.  How should sum() be able to use a +-operator defined in 
an imported module?  Not even ADL is helping here.


In my opinion, operators should only be defined in the module 
defining the type.




Re: @safe(bool)

2017-08-19 Thread Guillaume Boucher via Digitalmars-d

On Thursday, 17 August 2017 at 16:32:20 UTC, bitwise wrote:
In a high-performance context though, the performance hit may 
be unacceptable.


Well in those super rare situations, there's always the 
workaround with mixins:


mixin template funcWithAttr(string decl, string attributes, 
string code) {

pragma(msg, "<<<" ~ code ~ ">>>");
mixin(decl ~ attributes ~ "{" ~ code ~" }");
}

struct Container(T, bool safetyOn = true)
{
static if(safe)
RefCounted!(T[]) data;
else
T[] data;

mixin funcWithAttr!("auto opSlice()", safetyOn ? "@safe" : "", q{
return Range(data, 0, data.length);
});
}




Re: @safe(bool)

2017-08-19 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 19 August 2017 at 16:02:27 UTC, bitwise wrote:

We have to consider the potential for abuse.


I don't like measuring features on the potential for abuse, but 
this feature cries for abuse.  Even in the simpler form of your 
proposal.


Let's say there are two functions with conditional @safe

f(T)(...) @safe(!hasAliasing!T) {...}
g(bool B)(...) @safe(B) {...}

and we combine them into another function,

h(T,bool B) @safe(!hasAliasing!T && B) {
  f(T)(...);
  g(B)(...);
}

then in the correct @safe specification there is an additional 
clause for every conditionally-safe function.


This doesn't scale well.

So the guideline would be to use your feature very rarely and 
only if it's obvious from the meaning of the template arguments; 
if it gets too complicated, just don't specify it.


Which would mean the feature should only be used in few corner 
cases, and is thus not worth the cost of complicating the 
language.



You already commented on the other usage of dip 1012, the @nice 
and @naughty attributes.  They just don't scale in a similar way.



C++ has had the same feature for some time: noexcept(true) means 
noexcept, noexcept(false) means an exception may be thrown (of 
course this works with any constant expressions).
I just grepped through Boost and I have found 53 uses of 
noexcept(expression), from 5264 total uses of noexcept (excluding 
the math library). And Boost is one of those libraries that are 
overly precise with such things to a degree that the code becomes 
unreadable.  In code outside of Boost and the standard library, 
noexcept(expression) it is basically unused.




Re: C++17 Init statement for if/switch

2017-08-16 Thread Guillaume Boucher via Digitalmars-d

On Wednesday, 16 August 2017 at 12:58:03 UTC, Joakim wrote:
That is correct. After a while it gets tiring to see a 
neverending stream of complexity added to the language while 
things that would actually help (like IDE support) do not get 
any attention.


+1, though I'd go for bug-fixing over IDEs.


I like that.  Feature freeze D until *all* bug reports are closed.
While that would mean no more features for several years, I think 
it would benefit the language in the long run, both internally 
(less discussions about incorrect behavior) and externally (D is 
a mature and stable language).


Re: proposed @noreturn attribute

2017-07-16 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 16 July 2017 at 20:15:11 UTC, Timon Gehr wrote:

On 16.07.2017 21:49, Guillaume Boucher wrote:

On Sunday, 16 July 2017 at 12:41:06 UTC, Timon Gehr wrote:

It is therefore most natural to say that Bottom.sizeof == ∞.


True, but size_t.max doesn't have the properties of ∞.
The only sane choice to me seems to be a value of type Bottom, 
i.e. is(typeof(Bottom.sizeof) == Bottom).




In this case, Bottom.sizeof is a value of type Bottom, which 
must not exist.


It doesn't exist during runtime, but there's no problem to just 
generate assert(0) where it's used.


I think my interpretation produces the least exceptions, but if 
you have a better idea go ahead.




Re: proposed @noreturn attribute

2017-07-16 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 16 July 2017 at 20:04:25 UTC, Timon Gehr wrote:
The issue isn't purism, it is type safety. If you create an 
EvolvedPenguin, upcast it to a Penguin and call the fly method 
you get UB. So noreturn would indeed need to enforce that all 
overrides are also noreturn.


I see it as some kind of weak guarantee, where the compiler can 
assume noreturn only if he knows there are no subtypes involved 
(e.g. if he's applying devirtualization).


Automatically inheriting the attribute could break existing code 
(especially if it's inferred).


Re: proposed @noreturn attribute

2017-07-16 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 16 July 2017 at 12:41:06 UTC, Timon Gehr wrote:

It is therefore most natural to say that Bottom.sizeof == ∞.


True, but size_t.max doesn't have the properties of ∞.
The only sane choice to me seems to be a value of type Bottom, 
i.e. is(typeof(Bottom.sizeof) == Bottom).




Re: proposed @noreturn attribute

2017-07-16 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 16 July 2017 at 13:03:40 UTC, Timon Gehr wrote:
I don't think that's true.  A Bottom type does not cover all 
use cases of @noreturn/@pragma(noreturn).

...


I think it does, but it is a significantly more invasive 
language change.


The best you can hope for is that any code with pragma(noreturn) 
can be rewritten into functionally equivalent code that uses 
Bottom and gives the same hints to the optimizer.


pragma(noreturn) can be inferred implicitly which makes it more 
impactful in practice.


I'd say a function with return type Bottom can override any 
function in the base class.


That solves the "Penguin : Bird" step, but not "EvolvedPenguin : 
Penguin" (which can fly).


Andrei argues that my example don't comply with a puristic 
understanding of inheritance.  Maybe that's enough of a reason to 
not optimize such use cases, but it still shows that 
pragma(noreturn) is somehow stronger than Bottom.



pragma(noreturn) is indeed the simpler solution, as it does not 
interact with anything else. The fact that template constraints 
in some cases need to be aware of the existence of Bottom in 
order to work for Bottom is clearly a negative property of this 
solution in the context of D.


Yes, basically this.


You can return 'auto' instead of U. Then the return type will 
be inferred either as U or Bottom.


Sure there are workarounds.  Also here:

auto deref(T)(ref T* x) { return deref(*x); }
ref T deref(T)(ref T x) if (!isPointer!T) { return x; }

But when every small function needs a rewrite, something seems 
off.


Re: proposed @noreturn attribute

2017-07-14 Thread Guillaume Boucher via Digitalmars-d

On Monday, 10 July 2017 at 04:02:59 UTC, Nicholas Wilson wrote:

1)@noreturn
2)@disable(return)
3)none

w.r.t optimisation assuming both 1 & 3  impact DMD equally [...]


I don't think that's true.  A Bottom type does not cover all use 
cases of @noreturn/@pragma(noreturn).


Example 1: Polymorphism

class Bird { void fly() { ... } };
class Penguin : Bird { override void fly() @pragma(noreturn) { 
assert(0); }  };

class EvolvedPenguin : Penguin { override void fly() { ... } };

There's no way to encode that information in a return type.

Example 2: Compile-time polymorphism

Same as above, except during compile time.  While it looks ok in 
theory (just return Bottom, and everything is alright), it seems 
very tricky to get right.  Example from checkedint.d:


auto r = hook.hookOpUnary!op(payload);
return Checked!(typeof(r), Hook)(r);

Let's say the hook refuses to perform hookOpUnary, so r is 
Bottom.  Unfortunately, Checked!(Bottom, Hook)(r) doesn't compile 
(because "if (isIntegral!T || is(T == Checked!(U, H), U, H))" 
fails).  While Bottom may be substituted into all expressions 
(which doesn't seem easy anyway), it for sure can't be inserted 
as any template argument.  As seen before, Checked is not 
Bottom-proof.  I would think that most templates are not 
Bottom-proof and making them Bottom-proof seems quite a bit of 
work.


With @pragma(noreturn) that situation would be no problem.

Example 3: Unreachable statements/Implicit noreturn inference

As pointed out by Steven Schveighoffer, the current 
unreachability errors should probably be removed in generic code.


If we do that, then generic functions can be @pragma(noreturn) if 
certain conditions are met.  A compiler can easily figure that 
out, but writing it inside static ifs could be almost impossible.


Assume we have a hook to Checked that disallows casts.  Current 
signature:


U opCast(U, this _)() if (isIntegral!U || isFloatingPoint!U || 
is(U == bool))


The compiler can figure out that all code paths end with an 
@pragma(noreturn), so it can add that pragma implicitly to the 
signature.  However, the compiler can't change the return type 
from U to Bottom (otherwise static equality checks with U will 
fail).




Re: Checked vs unchecked exceptions

2017-06-26 Thread Guillaume Boucher via Digitalmars-d
On Monday, 26 June 2017 at 18:42:24 UTC, Ola Fosheim Grøstad 
wrote:
On Monday, 26 June 2017 at 17:44:15 UTC, Guillaume Boucher 
wrote:
Java uses A, Rust/Go use B.  C++ uses B to some extend (e.g. 
in std::experimental::filesystem).


The C++17 filesystem api provides two alternatives, the 
standard filesystem_error exception and an output-paramater for 
capturing os-specific error codes. I'm not quite sure why they 
provide both, but I guess performance and the ability to 
compile for  runtimes with exceptions turned off could explain 
it.


Quoting the C++ standard:

Filesystem library functions often provide two overloads, one 
that
throws an exception to report file system errors, and another 
that sets an error_code.


[Note: This supports two common use cases:

   - Uses where file system errors are truly exceptional
 and indicate a serious failure.
 Throwing an exception is an appropriate response.
   - Uses where file system errors are routine
 and do not necessarily represent failure.
 Returning an error code is the most appropriate response.
 This allows application specific error handling, including 
simply ignoring the error.


 -- end note]


I would say that the overload without exceptions is the 
"standard" one.


It is rather clear though that C++ std lib relies heavily on 
exceptions.


[Citation needed]



Re: Checked vs unchecked exceptions

2017-06-26 Thread Guillaume Boucher via Digitalmars-d

On Monday, 26 June 2017 at 17:50:47 UTC, Moritz Maxeiner wrote:
I have tried using such Monads in D, but in the end it always 
ended up being too verbose or too hard to read compared to 
using exceptions or even simple error codes (with 0 == no 
error).


I haven't tried that yet, tbh.  visit is nice, but can't always 
be used.  So I guess unless D introduces syntax for pattern 
matching, it will always be verbose.


In that case a reference to an error code would be the most 
viable design in D.




Re: Checked vs unchecked exceptions

2017-06-26 Thread Guillaume Boucher via Digitalmars-d

On Monday, 26 June 2017 at 16:52:22 UTC, Sebastien Alaiwan wrote:
Checked exceptions allow a lot more precision about what types 
of exceptions a function can throw.


I totally agree that this is a problem with D right now.  If you 
want to catch all errors, how are you supposed to remember what 
std.file.readText throws?  Or std.file.mkdir?


There are two solutions to this problem that I know of:

A) Checked exceptions
B) Error codes that can't be implicitly ignored

Java uses A, Rust/Go use B.  C++ uses B to some extend (e.g. in 
std::experimental::filesystem).


In my opinion, option B better than A because checked exceptions 
are incredibly verbose.  However, both are better than nothing 
(which is the current state of D right now).


It is very well possible to use option B in D.  The most 
convenient one is making functions nothrow and use Algebraic!(T, 
ErrorCode), or, for void functions, have a parameter "ref 
ErrorCode".
If all functions in Phobos would either follow that pattern or 
provide an alternative nothrow overload, I would consider that 
problem solved.


Re: DIP 1009--Improve Contract Usability--Preliminary Review Round 1

2017-06-25 Thread Guillaume Boucher via Digitalmars-d
On Sunday, 25 June 2017 at 15:46:12 UTC, Petar Kirov [ZombineDev] 
wrote:

out result > 0 // perhaps the best


How would you handle things like this:

T minimum(T)(RedBlackTree!T tree)
in (!tree.empty)
out result in (tree)
{
return tree.front;
}

That could either mean "out(result){assert(result in (tree));}" 
or out(result){assert(result);} in{assert(tree);}"


Re: Makefile experts, unite!

2017-06-11 Thread Guillaume Boucher via Digitalmars-d
On Sunday, 11 June 2017 at 19:17:36 UTC, Andrei Alexandrescu 
wrote:
Instead of an error, I get a no-op result that looks like 
success. How can that situation be converted to an error?


That makefile target is poorly written.

It was probably intended to have a dependency on the directory 
itself, so by adding "%/" to the pattern it correctly produces an 
error (since std.algorithm.d doesn't exist):


%.test : $(LIB) %/
...

To allow for your case, just add this line:

std.%.test : std/%.test


While that should work (at least for the first level), it still 
is very poorly written.  It doesn't use the white-listed 
modules/packages despite the rest of the makefile seems to use 
that fairly consistently.


I would replace all the ".test" targets with the following code:

# Target for quickly running a single unittest (using static 
phobos library).

# For example: "make std/algorithm/mutation.test"
# The mktemp business is needed so .o files don't clash in 
concurrent unittesting.

$(addsuffix .test,$(D_MODULES)): %.test : %.d $(LIB)
T=`mktemp -d /tmp/.dmd-run-test.XX` &&
  \
  (   
  \
$(DMD) -od$$T $(DFLAGS) -main -unittest $(LIB) 
-defaultlib= -debuglib= $(LINKDL) -cov -run $< ; \
RET=$$? ; rm -rf $$T ; exit $$RET 
  \

  )

# Target for quickly unittesting all modules and packages within 
a package,

# transitively. For example: "make std/algorithm.test"
define PACKAGETEST_template
$(1).test: $$(patsubst %,$(1)/%.test,$$(PACKAGE_$(subst 
/,_,$(1

endef
$(foreach package,$(STD_PACKAGES),$(eval $(call 
PACKAGETEST_template,$(package


# Target for quickly unittesting all modules and packages by 
using dot as a separator.

# For example: "make std.algorithm.sorting.test"
define MODULESYNTAXTEST_template
$(subst /,.,$(1)).test : $(1).test
endef
$(foreach module,$(STD_PACKAGES) $(D_MODULES),$(eval $(call 
MODULESYNTAXTEST_template,$(module



(I'm not going to make a pull request though.)



Re: Another "D is cool" post

2017-05-29 Thread Guillaume Boucher via Digitalmars-d

On Monday, 29 May 2017 at 19:07:03 UTC, H. S. Teoh wrote:
So, recently in one of my pet projects I have a bit of code 
that takes a string, fills in a code template, invokes the D 
compiler to create a shared object, then loads the object with 
dlopen() and calls dlsym() to get the entry point into the 
compiled code as a function pointer.


Seems like the perfect job for a scripting language like Python.

I'm not sure why you decided to compare everything to C.  Even C 
programmers will agree with you that in D you can do things in a 
shorter way -- just slower/bloated/more magic/with less 
control/not portable/.


In all the examples you bring, there's nothing special about D.  
You can do anything in C++/Go/Rust/Swift/Python/language> with comparable complexity.


The tricky part, though, is that .mangleof only works on an 
identifier defined in the *current* program; the compiler can't 
do it for a symbol in a string that's to be passed at runtime 
to another invocation of the compiler.  And AFAIK, there's 
currently no way to ask the compiler "what would be the 
mangling of mymodule.symbol?" if 'mymodule' and 'symbol' only 
exist in the shared object, not in the main program.


Not a problem in any other language (C++ has a well-defined ABI, 
dynamic languages don't need that).


I enjoy D, but some of those fanboy posts are just totally 
worthless.


Re: Idea: Reverse Type Inference

2017-05-22 Thread Guillaume Boucher via Digitalmars-d

On Monday, 22 May 2017 at 13:20:41 UTC, Stefan Koch wrote:
type inference is not magic, it's a search for a pattern over 
the syntax (sub)tree.

Hence it can have quadratic time/memory complexity.


Well, the type system of Scala is turing complete, hence it can 
take arbitrarily long:

https://michid.wordpress.com/2010/01/29/scala-type-level-encoding-of-the-ski-calculus/




Re: Fantastic exchange from DConf

2017-05-14 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 14 May 2017 at 09:42:05 UTC, Patrick Schluter wrote:
But completely removing the code when one encounters for 
example: if(val+1 == INT_MIN) is simply nuts.


Removing such code is precisely what dmd does: 
https://issues.dlang.org/show_bug.cgi?id=16268




Re: Fantastic exchange from DConf

2017-05-10 Thread Guillaume Boucher via Digitalmars-d
On Wednesday, 10 May 2017 at 01:19:08 UTC, Nick Sabalausky 
(Abscissa) wrote:
The moral of this story: Sometimes, breaking people's code is 
GOOD! ;)


I don't get the hate that compiler warnings get in the D 
community.


Sure you can disable them if you don't care, but then don't 
complain about C being inherently unsafe and bug-prone while 
praising D for breaking things.


Uninitialized variables is an example that I think does not need 
to be a language feature: If the compiler can prove the usage is 
sound, everything is fine.  The compiler has much deeper 
knowledge about the concrete case than static language rules.  If 
analysis fails, issue a warning.  Usually the problematic code is 
far from obvious and refactoring is a good idea.  If the 
programmer still thinks that no action is needed, just suppress 
that warning with a pragma.


Re: Fantastic exchange from DConf

2017-05-10 Thread Guillaume Boucher via Digitalmars-d

On Wednesday, 10 May 2017 at 05:26:11 UTC, H. S. Teoh wrote:

int myfunc(blah_t *blah, bleh_t *bleh, bluh_t *bluh) {
void *resource1, *resource2, *resource3;
int ret = RET_ERROR;

/* Vet arguments */
if (!blah || !bleh || !bluh)
return ret;

/* Acquire resources */
resource1 = acquire_resource(blah->blah);
if (!resource1) goto EXIT;

resource2 = acquire_resource(bleh->bleh);
if (!resource1) goto EXIT;

resource3 = acquire_resource(bluh->bluh);
if (!resource1) goto EXIT;

/* Do actual work */
if (do_step1(blah, resource1) == RET_ERROR)
goto EXIT;

if (do_step2(blah, resource1) == RET_ERROR)
goto EXIT;

if (do_step3(blah, resource1) == RET_ERROR)
goto EXIT;

ret = RET_OK;
EXIT:
/* Cleanup everything */
if (resource3) release(resource3);
if (resource2) release(resource2);
if (resource1) release(resource1);

return ret;
}



In modern C and with GLib (which makes use of a gcc/clang 
extension) you can write this as:


gboolean myfunc(blah_t *blah, bleh_t *bleh, bluh_t *bluh) {
/* Cleanup everything automatically at the end */
g_autoptr(GResource) resource1 = NULL, resource2 = NULL, 
resource3 = NULL;

gboolean ok;

/* Vet arguments */
g_return_if_fail(blah != NULL, FALSE);
g_return_if_fail(bleh != NULL, FALSE);
g_return_if_fail(bluh != NULL, FALSE);

/* Acquire resources */
ok = acquire_resource(resource1, blah->blah);
g_return_if_fail(ok, FALSE);

ok = acquire_resource(resource2, bleh->bleh);
g_return_if_fail(ok, FALSE);

ok = acquire_resource(resource3, bluh->bluh);
g_return_if_fail(ok, FALSE);

/* Do actual work */
ok = do_step1(blah, resource1);
g_return_if_fail(ok, FALSE);

ok = do_step2(blah, resource1);
g_return_if_fail(ok, FALSE);

return do_step3(blah, resource1);
}

Some random example of this style of coding: 
https://github.com/flatpak/flatpak/blob/master/common/flatpak-db.c




Re: Fantastic exchange from DConf

2017-05-09 Thread Guillaume Boucher via Digitalmars-d

On Tuesday, 9 May 2017 at 16:55:54 UTC, H. S. Teoh wrote:
Ouch.  Haha, even I forgot about this particularly lovely 
aspect of C. Hooray, freely call functions without declaring 
them, and "obviously" they return int! Why not?


To be fair, most of your complaints can be fixed by enabling 
compiler warnings and by avoiding the use of de-facto-deprecated 
functions (strnlen).  The remaining problems theoretically 
shouldn't occur by disciplined use of commonly accepted C99 
guidelines.  But I agree that even then and with the use of 
sanitizers writing correct C code remains very hard.


Re: Static foreach pull request

2017-05-09 Thread Guillaume Boucher via Digitalmars-d

On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:
If you are interested in static foreach making it into the 
language, please play with the implementation and tell me how 
to break it.


Code:

void main() {
void f() { idonotexist(); }
static foreach(j;0..0) {
f();
}
}


Output:

test_staticforeach.d(3): Error: undefined identifier 'idonotexist'
Statement::blockExit(0x7f38d5cd35e0)
static foreach (j; __error)
{
f();
}

core.exception.AssertError@ddmd/blockexit.d(90): Assertion failure

??:? _d_assertp [0x72e590]
??:? _ZN9blockExit9BlockExit5visitEP9Statement [0x637bd0]
??:? _ZN7Visitor5visitEP22StaticForeachStatement [0x625b45]
??:? _ZN22StaticForeachStatement6acceptEP7Visitor [0x61ebf8]
??:? int ddmd.blockexit.blockExit(ddmd.statement.Statement, 
ddmd.func.FuncDeclaration, bool) [0x637b69]

??:? _ZN9blockExit9BlockExit5visitEP17CompoundStatement [0x637ef9]
??:? _ZN17CompoundStatement6acceptEP7Visitor [0x61dc61]
??:? int ddmd.blockexit.blockExit(ddmd.statement.Statement, 
ddmd.func.FuncDeclaration, bool) [0x637b69]

??:? _ZN15FuncDeclaration9semantic3EP5Scope [0x5bba3d]
??:? _ZN6Module9semantic3EP5Scope [0x563f31]
??:? int ddmd.mars.tryMain(ulong, const(char)**) [0x5e2b46]
??:? _Dmain [0x5e3a12]
??:? 
_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFNlZv 
[0x7301da]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x730124]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll() [0x730196]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate()) [0x730124]

??:? _d_run_main [0x7300a2]
??:? main [0x5e411f]
??:? __libc_start_main [0xd4999510]



Re: Making AssertError a singleton

2016-12-12 Thread Guillaume Boucher via Digitalmars-d
On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu 
wrote:
I think all Errors should be singletons - multiple objects in 
that hierarchy arguably make no sense.


With that logic, why does Throwable have the field "next"?



Re: dmd -Wl=comma_separated_linker_flags (cf clang++ -Wl, comma_separated_linker_flags)

2016-12-11 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 11 December 2016 at 21:39:26 UTC, Timothee Cour wrote:

is there a way to pass linker flags?
dmd -Wl=comma_separated_linker_flags
eg:
dmd -Wl=-lbar,-Ldir,--export-dynamic,-pie

(same functionality as clang++ 
-Wl,-lbar,-Ldir,--export-dynamic,-pie)


If not could we support it? Would make a lot of things easier.


Just use shell expansions?

dmd -Wl,-{lbar,Ldir,-export-dynamic,pie}



Re: Fun: Shooting yourself in the foot in D

2016-10-27 Thread Guillaume Boucher via Digitalmars-d
On Thursday, 27 October 2016 at 19:59:09 UTC, Steven 
Schveighoffer wrote:
You create a large meta-template library called footMassage, 
which then ends up via compiler inference compiling into a gun 
instead.


Accidentally compiling a massage into a gun is not a high 
priority bug.  In order to become the safest language available, 
we should concentrate our effort implementing a nitrogen oxide 
detector (which handles all non-pathological examples of smoke).




Re: Anyone has time for a unittesting issue?

2016-10-01 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 1 October 2016 at 19:51:05 UTC, Dicebot wrote:
I think that is OK but only if actual file inside the dir is 
created with `mktemp --tmpdir=/tmp/.dmd-test-run/` (or using a 
similar technique).


This is not sufficient.  Any user can create a symlink from 
/tmp/.dmd-test-run/ to e.g. /very/private/root/directory/ (that 
user can't access it, but symlinks don't check the permission of 
the target).  Executed as root user, mktemp then creates a unique 
file in /very/private/root/directory/.  Which can be used for 
example to litter a filesystem, which hurts performance or fills 
disks.


That's why I was saying /tmp/.dmd-test-run/ should have 
permissions 0700.  I think a better naming scheme would be 
/tmp/dmd-testrun-username/, or if that already exists with wrong 
permissions /tmp/dmd-testrun-username-RANDOMCHARS/.  The files 
inside that directory don't need to have random names (afaik).


It seems like more practical issue is simply that no regular 
destruction of /tmp/ happens on your system.


I'm not sure what you were implying by this.  Deleting anything 
in /tmp while it's mounted is a very bad idea.  The 
permission-check of /tmp/dmd-testrun-username/ relies on the fact 
that the directory won't be deleted.  If it will, then this 
introduces a race condition.


Re: Anyone has time for a unittesting issue?

2016-10-01 Thread Guillaume Boucher via Digitalmars-d
On Saturday, 1 October 2016 at 16:46:56 UTC, Guillaume Boucher 
wrote:

On Saturday, 1 October 2016 at 16:43:29 UTC, Stefan Koch wrote:
On Saturday, 1 October 2016 at 16:05:25 UTC, Andrei 
Alexandrescu wrote:

https://issues.dlang.org/show_bug.cgi?id=16568

TIA! -- Andrei


Please post some code/instructions to reproduce the issue.

The fix for this will be quite simple create a directory with 
the DDMMYY timestamp as directory name, and bundle the files 
under it.


Any predictable name is a security issue.  Use e.g. mkdtemp.


Well I guess checking for 700 is sufficient.  But this does not 
scale with multiple users.


Re: Anyone has time for a unittesting issue?

2016-10-01 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 1 October 2016 at 16:43:29 UTC, Stefan Koch wrote:
On Saturday, 1 October 2016 at 16:05:25 UTC, Andrei 
Alexandrescu wrote:

https://issues.dlang.org/show_bug.cgi?id=16568

TIA! -- Andrei


Please post some code/instructions to reproduce the issue.

The fix for this will be quite simple create a directory with 
the DDMMYY timestamp as directory name, and bundle the files 
under it.


Any predictable name is a security issue.  Use e.g. mkdtemp.


Re: Overloading relational operators separately; thoughts?

2016-09-28 Thread Guillaume Boucher via Digitalmars-d
On Wednesday, 28 September 2016 at 14:27:58 UTC, Chris Wright 
wrote:

Increment, decrement, and
test for equality is sufficient mathematically, but we want 
programs that

terminate in our lifetimes.



Only for BigInts you need those three.  For ints decrement is not 
needed.  And for most other data types increment/decrement is not 
sufficient, e.g. for reals or any kind of vectors/matrices.


Re: ADL

2016-09-06 Thread Guillaume Boucher via Digitalmars-d

On Monday, 5 September 2016 at 23:50:33 UTC, Timon Gehr wrote:
One hacky way is to provide a mixin template to create a 
wrapper type within each module that needs it, with 
std.typecons.Proxy. Proxy picks up UFCS functions in addition 
to member functions and turns them into member functions. But 
this leads to a lot of template bloat, because callers that 
share the same added UFCS functions don't actually share the 
instantiation. Also, it only works one level deep and 
automatically generated Wrapper types are generally prone to be 
somewhat brittle.


I don't think cloning a type just to add functionality can 
possibly be the right way.


A C++-style of customizing behavior is using traits. Those traits 
would be a compile time argument to the algorithm function.  
Instead of arg.addone() one would use trait.addone(arg).  It is 
not hard to write a proxy that merges trait and arg into one 
entity, but this should to be done from the callee.


The default trait would be type.addone_trait if it exists, or 
else some default trait that uses all available functions and 
member function from the module of the type.  In most of the 
cases this is enough, but it enables adding traits to existing 
types and also different implementations of the same traits.


This gets really bloaty in C++, and that's why usually ADL is 
preferred, but D has the capability to reduce the overhead to a 
minimum.


It doesn't quite make it possible to separate the implementation 
of types, algorithms and traits (UFCS) into different modules 
such that they don't know each other.  Either the user has to 
specify the trait each call or either the type's module or the 
algorithm's module has to import the traits.


What I call traits is very similar to type classes in other 
languages where (among other features) the traits are 
automatically being attached to the type.  (Type classes are also 
what C++ concepts originally wanted to be.)


Re: integral to floating point conversion

2016-07-03 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 3 July 2016 at 09:08:14 UTC, Ola Fosheim Grøstad wrote:
On Saturday, 2 July 2016 at 20:17:59 UTC, Andrei Alexandrescu 
wrote:
So what's the fastest way to figure that an integral is 
convertible to a floating point value precisely (i.e. no other 
integral converts to the same floating point value)? Thanks! 
-- Andrei


If it is within what the mantissa can represent then it is 
easy. But you also have to consider the cases where the 
mantissa is shifted.


So the real answer is:

n is an unsigned 64 bit integer

mbits = representation bits for mantissa +1

tz = trailing_zero_bits(n)
lz = leading_zero_bits(n)

assert(mbits >= (64 - tz - lz))


This is the correct answer for another definition of "precisely 
convertible", not the one Andrei gave.


Re: Has someone encountered similar issues with -cov?

2016-07-02 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 2 July 2016 at 15:15:39 UTC, Guillaume Boucher wrote:

E.g. opCast!(int, ubyte) should not require any checks.


Or opCast!(long, int) and opCast!(int, int).


Re: Has someone encountered similar issues with -cov?

2016-07-02 Thread Guillaume Boucher via Digitalmars-d
On Saturday, 2 July 2016 at 12:26:34 UTC, Andrei Alexandrescu 
wrote:
How would you reshape this? It's important that the call to 
hook is physically at the end of the function and issued just 
in that place, and that the code does not do any redundant work.


Your function does redundant work.  E.g. opCast!(int, ubyte) 
should not require any checks.  I also don't understand why 
opCast!(int, ubyte) is not allowed.


The following code should do the same as yours, but without 
unnecessary checks:


U opCast(U, T)(T payload)
{
import std.traits;
enum Tsizeof = is(T==bool) ? 0 : T.sizeof;
enum Usizeof = is(U==bool) ? 0 : U.sizeof;
enum noCheck = isUnsigned!T == isUnsigned!U && Tsizeof <= 
Usizeof ||

   isUnsigned!T && Tsizeof < Usizeof;
enum checkPayload = !isUnsigned!T && isUnsigned!U;
enum checkResult = isUnsigned!T && !isUnsigned!U;
static if (checkResult)
{
static assert(U.sizeof <= T.sizeof);  // I don't 
understand this

}

if (!checkPayload || payload >= 0)
{
auto result = cast(U) payload;
if (noCheck || result == payload && (!checkResult 
|| result >= 0))

return result;
}
return hook!U(payload);
}



Re: Should % ever "overflow"?

2016-06-25 Thread Guillaume Boucher via Digitalmars-d

On Friday, 24 June 2016 at 20:43:38 UTC, deadalnix wrote:

Most reasonable is

numerator = quotient * divisor + remainder

Which means it can be negative.


Depends on the definition.

If division truncates towards negative infinity, the remainder 
will always be nonegative (in case of a positive divisor).


I personally find rounding towards negative infinity the most 
practical; every time I used modulo, I wanted the result to be in 
the range [0, divisor).  Python does it this way and I find it 
very convenient.




Re: size_t vs uintptr_t

2016-06-17 Thread Guillaume Boucher via Digitalmars-d

I was referring to this diff in the pull linked request:

-private size_t _alignUp(size_t alignment)(size_t n)
+private uintptr_t _alignUp(uintptr_t alignment)(uintptr_t n)

size_t is the correct type.  There is no reason to change it.


Re: size_t vs uintptr_t

2016-06-14 Thread Guillaume Boucher via Digitalmars-d

On Tuesday, 14 June 2016 at 21:59:32 UTC, Walter Bright wrote:

A related issue is I see much code of the form:

cast(size_t)ptr & 3

to check alignment. A better (possibly faster) method is:

cast(uint)ptr & 3

because even 64 bit CPUs often operate faster with 32 bit 
operations (thanks to some research by Andrei).


Isn't it guaranteed that x.sizeof >= x.alignof?  (At least it is 
in C and C++.)  So the alignment should be of type size_t and not 
of type uintptr_t.


Also in general cast(uint)ptr%alignment is wrong since alignment 
does not need to be 32 bit.  However, cast(size_t)ptr%alignment 
is be correct in any case.


Re: The Problem With DIPs

2016-06-12 Thread Guillaume Boucher via Digitalmars-d

On Sunday, 12 June 2016 at 12:16:11 UTC, Dicebot wrote:

On 06/09/2016 01:12 AM, Walter Bright wrote:

On 6/8/2016 1:47 PM, Dicebot wrote:
I will finish description for proposed process this weekend 
and send

it to
dmd-internal mail list.


Cool!


http://forum.dlang.org/thread/d5996d6d-1f8e-2fa7-31a7-177c121a9...@dicebot.lv


What are the reasons for putting the DIPs into several 
directories (Drafts, Approved, Implemented and Discarded)?  Rust 
also did that at first, but they merged them later into one 
folder (see https://github.com/rust-lang/rfcs/issues/360).  If 
you keep the structure as is, what is the preferred way to link 
to a certain DIP?


Re: Need a Faster Compressor

2016-05-24 Thread Guillaume Boucher via Digitalmars-d

On Tuesday, 24 May 2016 at 20:16:32 UTC, Walter Bright wrote:

On 5/24/2016 9:22 AM, Timon Gehr wrote:
Yes, it does. The compiler does not use exponential space to 
store the AST.


BTW, all types in dmd have a 'deco' string which is the AST 
linearized as a string. This string is also used to build the 
mangled names.


All the deco's are put into a hashtable, and then all types can 
be uniquely identified by their address in the hashtable. This 
reduces type comparisons to a single pointer comparison.


There's no reason not to use the compression in the deco name.  
Just make sure the references are relative and you're set.  No 
exponential space to store the AST.


Please, if you change the ABI, do it right the first time.  Some 
arbitrary compression algorithm doesn't solve the problem.





Re: Need a Faster Compressor

2016-05-24 Thread Guillaume Boucher via Digitalmars-d

On Monday, 23 May 2016 at 20:34:19 UTC, Walter Bright wrote:

On 5/23/2016 12:32 PM, Timon Gehr wrote:

Isn't it enough to create
references to previously embedded mangled symbols (i-th symbol 
already mangled)

while generating the mangled string?


That's been covered upthread, and VC++/g++ do that. But as 
shown, it is inadequate. There's a lot more redundancy than 
just the identifiers.


Yes, not all redundancy is covered.  However, I think all 
non-pathologic blow-ups are avoided.


Let's look at the properties of the Itanium C++ ABI mangling:

1. Guaranteed linear size name for recursive types that have 
exponential size names.
2. Compression speed can be linear to the size of the compressed 
name (i.e. no need to create an exponential garbage name just to 
compress it).
3. Decompression easy, possible without tools and speed linear to 
size of the compressed name.
4. Name retains some redundancy (in itself and when compared to 
other mangled names), well suited for a follow-up compression.


Compare this to apply some arbitrary compression algorithm to a 
name of exponential size:


1. Exponential size names remain exponential size.  Yes, up until 
the view size, some compression algorithms guarantee that, but 
they can not guarantee it in the general case.

2. Compression needs the whole name first.
3. Decompression only possible with tools.
4. Multiple mangled names can not be compressed well.



Re: Need a Faster Compressor

2016-05-21 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 21 May 2016 at 22:07:27 UTC, Walter Bright wrote:
As mentioned elsewhere, the C++ mangling scheme has a primitive 
and ineffective LZ77 scheme built in, so I wouldn't waste time 
on that.


Sorry if I didn't memorize everything in this forum from the last 
20 years, can you give a link to some reasoning?


The only thing I found are some statements in 
https://github.com/dlang/dmd/pull/5793:


Note that the VC++ and g++ name mangling schemes for C++ each 
use a similar, but primitive (and fairly ineffective) form of 
compression. It's like people who invent their own crypto 
algorithms.


The name mangling in the Itanium C++ ABI is similar to LZ77 but 
heavily optimized for the typical use case in symbol names.  I 
don't really see how the general LZ77 would be better.  It's 
almost as if using information about the actual data leads to a 
better compression scheme.


This is what C++ does, and results are pretty poor compression. 
Scanning to determine the backward references would consume the 
same order of time, anyway.


It uses a constant amount of time if implemented correctly, which 
is much faster.




Re: DMD producing huge binaries

2016-05-21 Thread Guillaume Boucher via Digitalmars-d

On Saturday, 21 May 2016 at 18:25:46 UTC, Walter Bright wrote:

On 5/20/2016 11:18 PM, poliklosio wrote:

foo!(boo!(bar!(baz!(int))), #1, #2)
Where #1 and #2 are special symbols that refer to stuff that 
was **already in

the name**, particularly:
#1: bar!(baz!(int))
#2: baz!(int)


This is what LZW compression does, except that LZW does it in 
general rather than just for identifiers.


It's more like LZ77 than LZW.