Re: Dscanner: is it possible to switch off style checks case-by-case?

2020-02-14 Thread Basile B. via Digitalmars-d-learn

On Thursday, 13 February 2020 at 17:15:50 UTC, mark wrote:

I'm starting out with GtkD and have this function:

void main(string[] args) {
Main.init(args);
auto game = new GameWindow();
Main.run();
}

and this method:

void quit(Widget widget) {
Main.quit();
}

When I run dscanner --styleCheck it reports:

./src/app.d(10:10)[warn]: Variable game is never used.
./src/app.d(22:22)[warn]: Parameter widget is never used.

These are correct. However, is it possible to switch them off 
individually?


Yes you can but in the present case the analysis is right because 
you can write


void main(string[] args) {
Main.init(args);
new GameWindow();
Main.run();
}

and for the other

void quit(Widget) {
Main.quit();
}

or even

void quit() {
Main.quit();
}

Otherwise here is an example of how you can tune the different 
checks:



https://raw.githubusercontent.com/dlang/phobos/master/.dscanner.ini


See also the last section of


https://raw.githubusercontent.com/dlang-community/D-Scanner/master/README.md


Re: Building for multiple platforms

2020-02-14 Thread Neils via Digitalmars-d-learn
Since your project is already on GitHub, I think the easiest 
solution would be to use GitHub Actions [1] + setup-dlang 
action [2] + upload-release-asset action [3]  to automate the 
whole process.


[1]: https://help.github.com/en/actions
[2]: https://github.com/mihails-strasuns/setup-dlang
[3]: https://github.com/actions/upload-release-asset


This looks very promising, thanks!


Re: Strange instruction sequence with DMD while calling functions with float parameters

2020-02-14 Thread Basile B. via Digitalmars-d-learn

On Friday, 14 February 2020 at 22:36:20 UTC, PatateVerte wrote:

Hello
I noticed a strange behaviour of the DMD compiler when it has 
to call a function with float arguments.


I build with the flags "-mcpu=avx2 -O  -m64" under windows 64 
bits using "DMD32 D Compiler v2.090.1-dirty"


I have the following function :
   float mul_add(float a, float b, float c); //Return a * b + c

When I try to call it :
   float f = d_mul_add(1.0, 2.0, 3.0);

I tested with other functions with float parameters, and there 
is the same problem.


Then the following instructions are generated :
//Loads the values, as it can be expected
vmovss xmm2,dword [rel 0x64830]
vmovss xmm1,dword [rel 0x64834]
vmovss xmm0,dword [rel 0x64838]
//Why ?
movq r8,xmm2
movq rdx,xmm1
movq rcx,xmm0
//
call 0x400   //0x400 is where the mul_add function is located

My questions are :
 - Is there a reason why the registers xmm0/1/2 are saved in 
rcx/rdx/r8 before calling ? The calling convention specifies 
that the floating point parameters have to be put in xmm 
registers, and not GPR, unless you are using your own calling 
convention.
 - Why is it done using non-avx instructions ? Mixing AVX and 
non-AVX instructions may impact the speed greatly.


Any idea ? Thank you in advance.


It's simply the bad codegen (or rather a missed opportunity to 
optimize) from DMD, its backend doesn't see that the parameters 
are already in the right order and in the right registers so it 
copy them and put them in the regs for the inner func call.


I had observed this in the past too, i.e unexplained round 
tripping from GP to SSE regs. For good FP codegen use LDC2 or GDC 
or write iasm (but loose inlining).


For other people who'd like to observe the problem: 
https://godbolt.org/z/gvqEqz.
By the way I had to deactivate AVX2 targeting because otherwise 
the result is even more weird (https://godbolt.org/z/T9NwMc)


Re: rt/aaA.d Line: 553

2020-02-14 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
On Friday, 14 February 2020 at 23:28:39 UTC, Steven Schveighoffer 
wrote:

On 2/14/20 5:57 PM, Ferhat Kurtulmuş wrote:


One thing to learn, you can select a section of lines from 
github (click on first line, then shift-click on last line), 
then press the 'y' key, and it will generate a permanent link 
to those lines.


https://github.com/dlang/druntime/blob/a581dc6d1d3bf796fcebd982221d0b3d6bbae437/src/rt/aaA.d#L553-L562


Thank you, I didn't know that.





Re: rt/aaA.d Line: 553

2020-02-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/14/20 6:36 PM, Ferhat Kurtulmuş wrote:

     İf ((aa.used + 1)* GROW_DEN > aa.dim * GROW_NUM)
     aa.grow(ti.key);


This call is expensive (it reallocates all the buckets and reinserts all 
the existing data into the new bucket), it should be avoided if in the 
end we will not be incrementing used.


-Steve


Re: rt/aaA.d Line: 553

2020-02-14 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Friday, 14 February 2020 at 23:19:31 UTC, Paul Backus wrote:
On Friday, 14 February 2020 at 22:57:31 UTC, Ferhat Kurtulmuş 
wrote:

findSlotInsert are called two times. Why not:

if (++aa.used * GROW_DEN > aa.dim * GROW_NUM)
aa.grow(ti.key);

auto p = aa.findSlotInsert(hash); // only one call is 
enough?


if (p.deleted)
--aa.deleted;
...

If I am not wrong this modification will not corrupt the 
current state of the hash table?


`used` counts both filled and deleted buckets, so it shouldn't 
be incremented when changing a deleted bucket into a filled 
bucket.


İf ((aa.used + 1)* GROW_DEN > aa.dim * GROW_NUM)
aa.grow(ti.key);

auto p = aa.findSlotInsert(hash); // only one call is enough?

if (p.deleted)
--aa.deleted;
else
++aa.used;


Re: rt/aaA.d Line: 553

2020-02-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/14/20 5:57 PM, Ferhat Kurtulmuş wrote:
I hesitated to post this on the topic of druntime because probably I 
will learn something new if I am totally/stupidly wrong.


There are no stupid questions, and this is the learn forum. So you are 
in the right place!




In druntime/blob/master/src/rt/aaA.d Lines 553-562:


One thing to learn, you can select a section of lines from github (click 
on first line, then shift-click on last line), then press the 'y' key, 
and it will generate a permanent link to those lines.


https://github.com/dlang/druntime/blob/a581dc6d1d3bf796fcebd982221d0b3d6bbae437/src/rt/aaA.d#L553-L562



...
     auto p = aa.findSlotInsert(hash);
     if (p.deleted)
     --aa.deleted;
     // check load factor and possibly grow
     else if (++aa.used * GROW_DEN > aa.dim * GROW_NUM)
     {
     aa.grow(ti.key);
     p = aa.findSlotInsert(hash);
     assert(p.empty);
     }
...

findSlotInsert are called two times. Why not:

     if (++aa.used * GROW_DEN > aa.dim * GROW_NUM)
     aa.grow(ti.key);

     auto p = aa.findSlotInsert(hash); // only one call is enough?

     if (p.deleted)
     --aa.deleted;
...

If I am not wrong this modification will not corrupt the current state 
of the hash table?


A cursory reading:

I think the case where you find the insert slot and the p.deleted is 
true, you can avoid the grow function.


The grow function is much more expensive than findInsertSlot, so calling 
it twice is preferable.


The reason we have the deleted status is because we want to reuse 
memory, but we can't free the memory if it had a dangling reference to it.


The only time those deleted nodes turn into garbage is on a resize.

HOWEVER, one case where we can avoid the double search is if there are 
no deleted nodes (we keep a count of them). This should be reasonably 
often in most cases because you insert nodes and don't remove them, or 
you grew the AA and all deleted nodes are purged.


So maybe change to:

Bucket *p;

if(aa.deleted > 0 && (p = aa.findSlotInsert(hash)).deleted)
   --aa.deleted;
else // everything else the same

-Steve


Re: rt/aaA.d Line: 553

2020-02-14 Thread Paul Backus via Digitalmars-d-learn
On Friday, 14 February 2020 at 22:57:31 UTC, Ferhat Kurtulmuş 
wrote:

findSlotInsert are called two times. Why not:

if (++aa.used * GROW_DEN > aa.dim * GROW_NUM)
aa.grow(ti.key);

auto p = aa.findSlotInsert(hash); // only one call is 
enough?


if (p.deleted)
--aa.deleted;
...

If I am not wrong this modification will not corrupt the 
current state of the hash table?


`used` counts both filled and deleted buckets, so it shouldn't be 
incremented when changing a deleted bucket into a filled bucket.


rt/aaA.d Line: 553

2020-02-14 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
I hesitated to post this on the topic of druntime because 
probably I will learn something new if I am totally/stupidly 
wrong.


In druntime/blob/master/src/rt/aaA.d Lines 553-562:

...
auto p = aa.findSlotInsert(hash);
if (p.deleted)
--aa.deleted;
// check load factor and possibly grow
else if (++aa.used * GROW_DEN > aa.dim * GROW_NUM)
{
aa.grow(ti.key);
p = aa.findSlotInsert(hash);
assert(p.empty);
}
...

findSlotInsert are called two times. Why not:

if (++aa.used * GROW_DEN > aa.dim * GROW_NUM)
aa.grow(ti.key);

auto p = aa.findSlotInsert(hash); // only one call is enough?

if (p.deleted)
--aa.deleted;
...

If I am not wrong this modification will not corrupt the current 
state of the hash table?


Strange instruction sequence with DMD while calling functions with float parameters

2020-02-14 Thread PatateVerte via Digitalmars-d-learn

Hello
I noticed a strange behaviour of the DMD compiler when it has to 
call a function with float arguments.


I build with the flags "-mcpu=avx2 -O  -m64" under windows 64 
bits using "DMD32 D Compiler v2.090.1-dirty"


I have the following function :
   float mul_add(float a, float b, float c); //Return a * b + c

When I try to call it :
   float f = d_mul_add(1.0, 2.0, 3.0);

I tested with other functions with float parameters, and there is 
the same problem.


Then the following instructions are generated :
//Loads the values, as it can be expected
vmovss xmm2,dword [rel 0x64830]
vmovss xmm1,dword [rel 0x64834]
vmovss xmm0,dword [rel 0x64838]
//Why ?
movq r8,xmm2
movq rdx,xmm1
movq rcx,xmm0
//
call 0x400   //0x400 is where the mul_add function is located

My questions are :
 - Is there a reason why the registers xmm0/1/2 are saved in 
rcx/rdx/r8 before calling ? The calling convention specifies that 
the floating point parameters have to be put in xmm registers, 
and not GPR, unless you are using your own calling convention.
 - Why is it done using non-avx instructions ? Mixing AVX and 
non-AVX instructions may impact the speed greatly.


Any idea ? Thank you in advance.


static foreach over enum symbols

2020-02-14 Thread Ben Jones via Digitalmars-d-learn

Hi all,

I'm getting unexpected results while trying to process symbols 
from a module, some of which are enums.


Depending on whether or not I comment out the first static 
foreach loop below, fullyQualifiedName gives me different results 
in the second loop.


In either case, I'm surprised I can't grab the UDAs in the second 
static foreach loop.  Any ideas what's going on?


Test case:
---a.d---
module a;

@Object
enum x = "hello";

@Object
enum y = "goodbye";

@Object
struct z{}


---main.d---

template symbols(alias Mod){
import std.meta;
alias toSymbol(alias T) = __traits(getMember, Mod, T);
alias symbols = staticMap!(toSymbol, __traits(allMembers, 
Mod));

}


void main(){
import std.traits;
import std.meta;
import a;
//commenting this out changes the results below
static foreach(sym; symbols!a){
pragma(msg, fullyQualifiedName!sym);
pragma(msg, __traits(getAttributes, sym));
}

pragma(msg, "\nget with UDAs\n");
pragma(msg, getSymbolsByUDA!(a, Object));
alias udaSyms = getSymbolsByUDA!(a, Object);
pragma(msg, staticMap!(fullyQualifiedName, udaSyms));
static foreach(us; udaSyms){
pragma(msg, fullyQualifiedName!us);
pragma(msg, __traits(getAttributes, us));
}
}

---

annotated output of dmd main.d:

with the first loop commented out:

get with UDAs

tuple("hello", "goodbye", (z))
tuple("a.x", "a.y", "a.z")
a.x
tuple()  //why is the UDA gone?
a.y
tuple()
a.z
tuple((Object))


and with the first loop:

object
tuple()
main.main.sym  //it's not a.x anymore, it's the name of the local 
var for static foreach?

tuple()
main.main.sym
tuple()
a.z
tuple((Object))

get with UDAs

tuple("hello", "goodbye", (z))
tuple("main.main.sym", "main.main.sym", "a.z") //and the results 
are changed here too?

main.main.sym
tuple()
main.main.sym
tuple()
a.z
tuple((Object))



Re: can't run D project on Visual studio

2020-02-14 Thread Rainer Schuetze via Digitalmars-d-learn



On 13/02/2020 15:54, Akomire Samson wrote:
> I am having this error on running D project using Visual studio 2019 and
> Visual D
> 
> 
> Build Log
> 
> Building Win32\Debug\LearningD.exe
> 
> Command Line
> 
> set PATH=C:\D\ldc2-1.19.0-windows-multilib\bin;C:\Program Files
> (x86)\Microsoft Visual
> Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\HostX86\x64;C:\Program
> Files (x86)\Microsoft Visual
> Studio\2019\Community\Common7\IDE;C:\Program Files (x86)\Windows
> Kits\10\bin;%PATH%
> set LIB=C:\Program Files (x86)\Microsoft Visual
> Studio\2019\Community\VC\Tools\MSVC\14.24.28314\lib\x86;C:\Program Files
> (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86
> set VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual
> Studio\2019\Community\VC\
> set VCTOOLSINSTALLDIR=C:\Program Files (x86)\Microsoft Visual
> Studio\2019\Community\VC\Tools\MSVC\14.24.28314\
> set VSINSTALLDIR=C:\Program Files (x86)\Microsoft Visual
> Studio\2019\Community\
> set WindowsSdkDir=C:\Program Files (x86)\Windows Kits\10\
> set WindowsSdkVersion=10.0.18362.0
> set UniversalCRTSdkDir=C:\Program Files (x86)\Windows Kits\10\
> set UCRTVersion=10.0.18362.0
> "C:\Program Files (x86)\VisualD\pipedmd.exe" -deps
> Win32\Debug\LearningD.dep ldc2 -m32 -g -d-debug -X
> -Xf="Win32\Debug\LearningD.json" -of="Win32\Debug\LearningD.exe"
> -L/PDB:"Win32\Debug\LearningD.pdb" -L/SUBSYSTEM:CONSOLE -L/noopttls
> -od="Win32\Debug" LearningD.d
> if %errorlevel% neq 0 goto reportError
> if not exist "Win32\Debug\LearningD.exe" (echo
> "Win32\Debug\LearningD.exe" not created! && goto reportError)
> 
> goto noError
> 
> :reportError
> echo Building Win32\Debug\LearningD.exe failed!
> 
> :noError
> Output
> 
> LINK : fatal error LNK1181: cannot open input file 'kernel32.lib'
> Error: C:\Program Files (x86)\Microsoft Visual
> Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\HostX86\x64\link.exe
> failed with status: 1181
> Building Win32\Debug\LearningD.exe failed!
> 
> 
> 
> I will appreciate any help.

Maybe you don't have a Windows SDK installed? With the settings as shown
above, kernel32.lib would be expected to exist in "c:\Program Files
(x86)\Windows Kits\10\Lib\10.0.18362.0\um\x86".

If that looks ok, maybe it has to do with using LDC to do the linking.
Does it work when using DMD instead? Or try compilation model "Separate
compile and link".


Re: How to use labeled break in static foreach?

2020-02-14 Thread Steven Schveighoffer via Digitalmars-d-learn

On 2/14/20 1:41 AM, cc wrote:

import std.meta;
enum A = AliasSeq!(1, 2, 3, 4);
THREELOOP: static foreach (idx, field; A) {
 static if (field == 3) {
     pragma(msg, "Got a 3!");
     break THREELOOP;
 }
 static if (idx == A.length - 1) {
     static assert(0, "Got no 3...");
 }
}

What I'd like to achieve in this example is for compilation to fail if 
the given tuple doesn't contain a matching item.  Is there an easy way 
to do this?  Trying to break out of the static foreach gives me

Error:enclosing label `THREELOOP` for `break` not found

In this reduced example, I was able to accomplish this by setting some 
enum within the successful comparison body and then checking e.g. static 
if (!__traits(compiles, FOUND)) but this breaks down once I start 
dealing with multiple levels of scope.


static foreach does not support break. Partly because the places where 
static foreach is allowed do not allow break statements. In your example 
above, if you are not in a function context, a break statement is not 
allowed. Note that a naked break statement inside a static foreach 
that's inside e.g. a switch statement needs a label to ensure the user 
understands they are breaking the switch, not the static foreach.


foreach does allow breaks. If you use foreach on an AliasSeq, it will 
work. But again, you must be in a function context.


But remember that static foreach and foreach implement all the bodies 
given. So every single one has to be compiled, even if it's not used. 
This can cause problems for things like return statements that make 
further code not executable.


AND static foreach doesn't introduce a new scope (foreach does). Other 
than recursive templates, I can't think of a great way to do this. Your 
enum solution has limits, as you say.


-Steve


Re: How to get to body of HTTP 500 error with std.net.curl.get()?

2020-02-14 Thread Andre Pany via Digitalmars-d-learn

On Friday, 14 February 2020 at 00:24:27 UTC, Gregor Mückl wrote:

Hi!

I am trying to write a client for pretty... well... creatively 
designed web API. The server gives HTTP status 500 replies if 
the requests are malformed, but the actual error message is 
hidden in the body of the reply (an XML document!). 
std.net.curl.get() throws an exception in this case. But I 
would like to get the body to process the error message within. 
How can I do that?


Thanks in advance,
Gregor


Hi Gregor,

If I am not completely wrong, the exception has an attribute
"msg" which should contain the body of the http response.

Kind regards
André


Re: How to use labeled break in static foreach?

2020-02-14 Thread Adam D. Ruppe via Digitalmars-d-learn
this kind of thing doesn't work super well due to the nature of 
compile time. My suggestion is to put the checks and the 
implementation in separate things.


void foo(T...)() {
static bool checkHelper() {
bool passed;
static foreach(t; T) {
static if(is(t == whatever)) {
  passed = false;
}
}
return passed;
}

static assert(checkHelper());

// then foreach to do the rest of it
}


something like that. maybe returning string instead of bool to 
have an error message you print out with the static assert.


i don't love this but it is the simplest way I know.