Re: Segfault with std.container.Array but not regular dynamic array

2012-11-29 Thread Maxim Fomin

On Wednesday, 28 November 2012 at 22:13:05 UTC, Dan wrote:
On Wednesday, 28 November 2012 at 20:30:41 UTC, Maxim Fomin 
wrote:

On Wednesday, 28 November 2012 at 18:08:59 UTC, Dan wrote:

This code with version=bug produces garbage because of 
opAssign. It seems that opAssign is actually called before 
accessing map:




Maxim, thanks for looking more at this. This bug is not 
affecting my work in any way - I'm just trying to learn more 
about D and how to debug, and your responses are helpful.


I've now built druntime and phobos with debug to see if I can 
see what is going on more.


For me the relevant assembly of your code looks like below. I 
see the value in the assoc array get created and memset 
initialized to 0 inside aaA.d function _aaGetX with this line:


memset(ptail + aligntsize(keytitsize), 0, valuesize); // 
zero value


Then between +62 and +102 it goes off the rails and upon entry 
to opAssign *this* is likely garbage. I can't be certain 
because the values I see are 0, which would be consistent with 
0 initialization - but could also just be luck. At this point I 
wish I knew some assembly. Anyway, I don't know if it is a 
problem with associative array code, per se, or the code 
generated by the compiler when opAssign and/or postblit are 
defined for the value type. I do know that if you have no 
postblit and no opAssign there are no issues - even with a 
destructor. This is consistent with the examples you have 
shown, they have postblit and/or opAssign as well as the 
RefCount code which has postblit and dtor. In both your example 
crash and the RefCount crash the actual seg fault is in the 
dtor accessing bogus data because as you pointed out it was not 
correctly initialized.


Thanks
Dan

 skipped


This doesn't look like assembly for previous source. Please 
provide the source for which you have assembly and tell which dmd 
options do you use.


Re: assertion failure with template instantiation of forward reference class

2012-11-29 Thread comco

On Thursday, 29 November 2012 at 01:38:50 UTC, bearophile wrote:

comco:


Looks like a bug?


This is what DMD 2.061alpha prints, it doesn't crash:

...\dmd2\src\phobos\std\range.d(603): Error: static assert  
Cannot put a string into a LockingTextWriter
...\dmd2\src\phobos\std\format.d(2349):instantiated 
from here: put!(LockingTextWriter, string)
...\dmd2\src\phobos\std\format.d(2782):instantiated 
from here: formatValue!(LockingTextWriter, TypeInfo_Class, char)
...\dmd2\src\phobos\std\format.d(415):instantiated from 
here: formatGeneric!(LockingTextWriter, TypeInfo_Class, char)
...\dmd2\src\phobos\std\stdio.d(712):... (1 
instantiations, -v to show) ...
...\dmd2\src\phobos\std\stdio.d(1618):instantiated from 
here: write!(TypeInfo_Class,char)
test.d(5):instantiated from here: 
writeln!(TypeInfo_Class)


Bye,
bearophile


Nice. Thanks!


Re: Is there a portable way to limit memory/cpu usage of a D application?

2012-11-29 Thread Dejan Lekic

On Thursday, 29 November 2012 at 04:44:34 UTC, Mike Young wrote:
On Wednesday, 9 November 2011 at 17:13:14 UTC, Dejan Lekic 
wrote:

Sure
nothing prevents me from using setrlimit() in my D app, but 
perhaps it is

something to think about a portable way of doing that.


I know I'm over a year late coming in on this conversation, but 
how would you use setrlimit() in your D app at all?  I can't 
seem to figure out what the correct library is to include in my 
program to be able to call set/getrlimit in any manner.  Thanks!


Well, if it is not in the posix module, then you simply use it by 
declaring extern(C) int setrlimit(int resource, const void* 
rlim); or something similar if you define the rlimit struct 
somewhere.
Remember, you can call C functions from your D code anytime, 
anywhere.


static assert

2012-11-29 Thread Jack Applegame

Another funny thing.

import std.conv;
static assert(0, 1 !=  ~ text(2));

outputs
Error: static assert  ['1',' ','!','=',' ','2']


Re: static assert

2012-11-29 Thread bearophile

Jack Applegame:


import std.conv;
static assert(0, 1 !=  ~ text(2));

outputs
Error: static assert  ['1',' ','!','=',' ','2']


This is known problem, it's already in Bugzilla, and maybe 
there's already a patch for it (there are about one hundred 
patches waiting in Bugzilla).


Bye,
bearophile


Re: Segfault with std.container.Array but not regular dynamic array

2012-11-29 Thread Dan

On Thursday, 29 November 2012 at 07:59:02 UTC, Maxim Fomin wrote:

This doesn't look like assembly for previous source. Please 
provide the source for which you have assembly and tell which 
dmd options do you use.


Well, I'm using the latest dmd (from the trunk), phobos, 
druntime, so I could build and step through.


rdmd -version=bug --force --build-only -g -w -property 
-I/home/dbdavidson/stage/vibe.d/source 
-I/home/dbdavidson/plusauri/dlang -L-levent_pthreads -L-levent 
-L-lssl -L-lcrypto /home/dbdavidson/tmp/again.d


dmd -v
DMD v2.061 DEBUG
DMD64 D Compiler v2.061

---
import core.stdc.stdio : printf;

struct S {
  long x = 42;
  version(bug) {
void opAssign(S rhs)
{
  printf(Assign %d\n, this.x);
}
  }
}

//alias RefCounted!(int) Foo;
alias S Foo;
Foo[int] map;

void main() {
  map[3] = Foo();
  printf(%d\n, map[3].x);
}



(gdb) disass
Dump of assembler code for function _Dmain:
   0x0041a630 +0:   push   %rbp
   0x0041a631 +1:   mov%rsp,%rbp
   0x0041a634 +4:   sub$0x38,%rsp
   0x0041a638 +8:   push   %rbx
= 0x0041a639 +9:mov$0x3,%eax
   0x0041a63e +14:  mov%eax,-0x30(%rbp)
   0x0041a641 +17:  lea-0x30(%rbp),%rcx
   0x0041a645 +21:  movabs $0x8,%rdx
   0x0041a64f +31:  movabs $0x43cc10,%rsi
   0x0041a659 +41:  mov%fs:0x0,%rdi
   0x0041a662 +50:	add0x229957(%rip),%rdi# 
0x643fc0

   0x0041a669 +57:  callq  0x41ae84 _aaGetX
   0x0041a66e +62:  mov%rax,-0x28(%rbp)
   0x0041a672 +66:  test   %rax,%rax
   0x0041a675 +69:  jne0x41a681 _Dmain+81
   0x0041a677 +71:  mov$0x12,%edi
   0x0041a67c +76:  callq  0x41a710 _D5again7__arrayZ
   0x0041a681 +81:  movabs $0x2a,%rax
   0x0041a68b +91:  mov%rax,-0x18(%rbp)
   0x0041a68f +95:  mov%rax,%rsi
   0x0041a692 +98:  lea-0x20(%rbp),%rdi
   0x0041a696 +102:	callq  0x41a5c8 
_D5again1S8opAssignMFS5again1SZv

   0x0041a69b +107: mov-0x20(%rbp),%rcx
   0x0041a69f +111: mov-0x28(%rbp),%rdx
   0x0041a6a3 +115: mov%rcx,(%rdx)



canFind typing

2012-11-29 Thread bearophile
I have used std.algorithm.canFind with different tuple types by 
mistake, and the compiler has not complained. So to show it I 
have written some reduced code that uses just numbers:



import std.algorithm: canFind;
void main() {
int[] arr1 = [1, 2];
double x1 = 2.0;
assert(arr1.canFind(x1));
double[] arr2 = [1.0, 2.0];
int x2 = 2;
assert(arr2.canFind(x2));
}


Are both of those canFind calls acceptable?

Bye,
bearophile


Re: telnet and D

2012-11-29 Thread maarten van damme
 vibe.d is very modular, just import what you need.
 I hate to push it, but it has very good documentation and examples.

 Its designed for web apps, but it makes a nice little web library as well.

 import vibe.vibe;

 void main()
 {
 auto client = new HttpClient;
 client.connect(www.google.com, 80);

 auto res = client.request((req){
 req.url = /;
 });

 logInfo(Response: %d, res.statusCode);

 foreach( k, v; res.headers )
 logInfo(Header: %s: %s, k, v);

 (new NullOutputStream).write(res.bodyReader);
 client.disconnect();
 }



That does indeed look clean. Now I'm using a ubyte[1] buffer to try
and read single bytes from my sockets.

their tcp example looks pretty clean:
import vibe.d;

static this()
{
auto conn = connectTcp(time-b.timefreq.bldrdoc.gov, 13);
logInfo(The time is: %s, cast(string)conn.readAll());
}

let's see how it'll hold up when I try to deal with raw bytes :)


Re: Segfault with std.container.Array but not regular dynamic array

2012-11-29 Thread Maxim Fomin

On Thursday, 29 November 2012 at 12:38:03 UTC, Dan wrote:
On Thursday, 29 November 2012 at 07:59:02 UTC, Maxim Fomin 
wrote:


This doesn't look like assembly for previous source. Please 
provide the source for which you have assembly and tell which 
dmd options do you use.


Well, I'm using the latest dmd (from the trunk), phobos, 
druntime, so I could build and step through.




This is version generated by rdmd -version=bug --force 
--build-only -g -w -property. The only difference between this 
and yours is in +71.


+00:push   %rbp
+01:mov%rsp,%rbp
+04:sub$0x38,%rsp
+08:push   %rbx
// push 3 as a pkey, -0x30(%rbp) is 3
+09:mov$0x3,%eax
+14:mov%eax,-0x30(%rbp)
+17:lea-0x30(%rbp),%rcx
// push valuesize
+21:movabs $0x8,%rdx
// push keyti
+31:movabs $0x430f50,%rsi
// push map address, it is tls object
+41:mov%fs:0x0,%rdi
+50:add0x21e22f(%rip),%rdi# 0x636fb0
// call, keyti=8, aa=map, valuesize=8, pkey=3
+57:callq  0x419140 _aaGetX
// store return value in -0x28(%rbp)
+62:mov%rax,-0x28(%rbp)
// check array bounds
+66:test   %rax,%rax
+69:jne0x418d99 _Dmain+81
+71:mov$0x13,%edi
+76:callq  0x418e28 _D4main7__arrayZ
// constructing S rhs for opAssign
+81:movabs $0x2a,%rax
+91:mov%rax,-0x18(%rbp) // rhs
+95:mov%rax,%rsi
// making this from -0x20(%rbp), but it was stored in -0x28(%rbp)
+98:lea-0x20(%rbp),%rdi
// opAssign loads this from %rdi
+102:   callq  0x418ce0 _D4main1S8opAssignMFS4main1SZv
// replace content in -0x28(%rbp) by -0x20(%rbp)
+107:   mov-0x20(%rbp),%rcx
+111:   mov-0x28(%rbp),%rdx
+115:   mov%rcx,(%rdx)
// load previously created object
+118:   movl   $0x3,-0x10(%rbp)
+125:   lea-0x10(%rbp),%rcx
+129:   movabs $0x8,%rdx
+139:   movabs $0x430f50,%rsi
+149:   mov%fs:0x0,%rax
+158:   mov0x21e1c3(%rip),%rbx# 0x636fb0
+165:   mov(%rax,%rbx,1),%rdi
+169:   callq  0x4192b8 _aaGetRvalueX
// store pointer to existed object
+174:   mov%rax,-0x8(%rbp)
// check array bounds
+178:   test   %rax,%rax
+181:   jne0x418e09 _Dmain+193
+183:   mov$0x14,%edi
+188:   callq  0x418e28 _D4main7__arrayZ
// load x member
+193:   mov-0x8(%rbp),%rcx
+197:   mov(%rcx),%rsi
+200:   movabs $0x430ac0,%rdi
+210:   xor%eax,%eax
+212:   callq  0x4188e0 printf@plt
+217:   xor%eax,%eax
+219:   pop%rbx
+220:   leaveq
+221:   retq
End of assembler dump.

Main stack frame looks follows:
-0x30(%rbp):-0x28(%rbp) 3 as a pkey arg to _aaGetX
-0x28(%rbp):-0x20(%rbp) pointer to S allocated by _aaGetX
-0x20(%rbp):-0x18(%rbp) uninitialized struct - this ptr
-0x18(%rbp):-0x10(%rbp) constructed struct passed as rhs to 
opAssign

-0x10(%rbp):-0x08(%rbp) 3 as a pkey arg to _aaGetRvalueX
-0x08(%rbp):-0x00(%rbp) pointer to S returned from _aaGetRvalueX

It seems that dmd allocates space for two structs, one 
non-initialized, second initialized, issues call to druntime, 
then places a call to opAssign with non-initialized as this 
object with initialized as rhs argument, then writes content on 
non-initialized to allocated by druntime. So, this looks like a 
codegen bug.


By the way, if the code is compiled with command dmd main -g 
-release -noboundscheck -version=bug, opAssign call is placed 
before calling _aaGetX.


Re: Calls to struct methods and immutable

2012-11-29 Thread Joseph Rushton Wakeling

On 11/27/2012 05:31 PM, Dan wrote:

I'm using a custom gdup that recursively copies fields and requires no support
from nested structs. If a dup is provided by a struct it will be called. No
guarantees, but have a look.
https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d


Thanks for that -- I'll look through it carefully.

My one caveat here is that in general I'm reluctant to rely too strongly on 
3rd-party libraries at this stage of D's development.  That's particularly true 
where stuff like this is concerned -- which might well be best placed in the 
standard library itself.  Generic, broadly-applicable .dup and .idup commands 
would seem to be something that should be available in Phobos ...


... anyway, back to the specifics -- even though I could use opmix, I'd still 
really like to understand for myself how to solve the problems described in my 
previous emails -- in particular, how to effectively idup my struct containing 
the Node[uint] associative array _without_ relying on some external library.  My 
feeling is I'll learn more about D this way ... :-)




Can operators return type?

2012-11-29 Thread Zhenya

Hi!
It would useful for some my project,if operators could be a 
template,that return

type.Something like

alias TypeTuple!(int,char) types;

static assert(types[1] == char) //opIndex

So can I define something like that?


Re: opSlice Bug?

2012-11-29 Thread Ali Çehreli

On 11/29/2012 08:15 AM, Namespace wrote:

Why I have to write
arr2[] += arr[][]
instead of
arr2[] += arr[]
? Bug or 'feature'? :P

Code:
http://dpaste.dzfl.pl/4c732f4c


opSplice, eh? Is that another undocumented feature or one that has been 
deprecated?


Ali


Re: opSlice Bug?

2012-11-29 Thread Namespace

On Thursday, 29 November 2012 at 16:46:45 UTC, Ali Çehreli wrote:

On 11/29/2012 08:15 AM, Namespace wrote:

Why I have to write
arr2[] += arr[][]
instead of
arr2[] += arr[]
? Bug or 'feature'? :P

Code:
http://dpaste.dzfl.pl/4c732f4c


opSplice, eh? Is that another undocumented feature or one that 
has been deprecated?


Ali


http://dlang.org/operatoroverloading.html#Slice


Re: Can operators return type?

2012-11-29 Thread bearophile

Zhenya:

It would useful for some my project,if operators could be a 
template,that return

type.


D operators are functions, and D functions return values. And in 
D types are not values (unlike Python and several other 
languages), unless you use a Typeinfo or something.


Maybe if you explain better what you are trying to do someone 
will be able to suggest you an alternative solution. D is not as 
flexible as Lisp, but it doesn't lack 
meta-programming/type-processing capabilities.


Bye,
bearophile


Re: opSlice Bug?

2012-11-29 Thread bearophile

Ali Çehreli:

opSplice, eh? Is that another undocumented feature or one that 
has been deprecated?


I think it's not deprecated:
http://dlang.org/operatoroverloading.html#Slice

Bye,
bearophile


Re: Can operators return type?

2012-11-29 Thread Simen Kjaeraas

On 2012-11-29, 17:33, Zhenya wrote:


Hi!
It would useful for some my project,if operators could be a  
template,that return

type.Something like

alias TypeTuple!(int,char) types;

static assert(types[1] == char) //opIndex

So can I define something like that?


This works out of the box. If you want to define your own
TypeTuple-like construct, the answer is most likely going to be no.

--
Simen


Re: opSlice Bug?

2012-11-29 Thread Ali Çehreli

On 11/29/2012 08:50 AM, Namespace wrote:

On Thursday, 29 November 2012 at 16:46:45 UTC, Ali Çehreli wrote:

On 11/29/2012 08:15 AM, Namespace wrote:

Why I have to write
arr2[] += arr[][]
instead of
arr2[] += arr[]
? Bug or 'feature'? :P

Code:
http://dpaste.dzfl.pl/4c732f4c


opSplice, eh? Is that another undocumented feature or one that has
been deprecated?

Ali


http://dlang.org/operatoroverloading.html#Slice


Thanks. I really did read it as opS_p_lice, found a few references on 
dlang.org, none on any spec page and got a little frustrated. I did not 
realize that I had clearly misread it.


I had even written some notes about opSlice:

  http://ddili.org/ders/d.en/operator_overloading.html

Apparently I had thought that it better returned a special type:

struct Range
{
// ...
}

struct Container
{
// For the object[] syntax
Range opSlice()
{
Range allElements;
// ... must provide access to all elements ...
return allElements;
}

/* ... */
}

Ali


Re: opSlice Bug?

2012-11-29 Thread Namespace
Yes, that could be better (but I don't like it), but my code 
should compile as well, or not?


Re: opSlice Bug?

2012-11-29 Thread Ali Çehreli

On 11/29/2012 08:15 AM, Namespace wrote:

Why I have to write
arr2[] += arr[][]
instead of
arr2[] += arr[]
? Bug or 'feature'? :P

Code:
http://dpaste.dzfl.pl/4c732f4c


Apparently, the array-wise operations require the following syntax:

a[] += b[];

In other words, the compiler wants to see [] on the right-hand side as 
well. The following does not work with the same error message that you get:


int[] a, b;
a[] += b;

Error: invalid array operation a[] += b (did you forget a [] ?)

It is the same in your case. You have a function that returns a slice 
but the compiler still wants to see [] on the rigth-hand side:


int[] foo()
{
int[] b;
return b;
}

void main()
{
int[] a;
a[] += foo();// -- Same compilation error
}

That's why you need to put the [] after it:

a[] += foo()[];

I think it is just the requirement of the syntax. (?)

Ali


Re: opSlice Bug?

2012-11-29 Thread Namespace

That is what I thought also.
That is awfully and limited. :/


Initializing values in associative arrays

2012-11-29 Thread Joseph Rushton Wakeling

How safe is it to rely on doing something like this:

uint[size_t] x;

foreach(i; iota(0, 10))
x[i]++;

foreach(i; iota(5, 15))
x[i]++;

... ?  In this case correct output comes out -- that is, values for keys 1-4 
and 10-14 come out as 1, values for keys 5-9 come out as 2 -- but it seems a bit 
shaky to assume that just incrementing x[i] without first checking ((i in x) !is 
null) will come out correctly.


I note that the above works even if uint[size_t] is changed to real[size_t], 
which is a surprise, because I'd have assumed that everything would come out as 
nan's.


Re: canFind typing

2012-11-29 Thread bearophile

Jonathan M Davis:

Why wouldn't they be? You can compare int and double, and 
that's what find and canFind care about.


Right, it's a matter of equality operator.

In my code I was performing canFind on an array of tuples. So I 
didn't realize that the following code (where both tuple field 
type and field name are different) is accepted in D (probably I 
am getting used to the higher type strictness of functional 
languages):



import std.typecons: Tuple;
alias T1 = Tuple!(int, x);
alias T2 = Tuple!(double, y);
void main(string[] args) {
assert(T1(1) == T2(1));
}


Bye,
bearophile


Re: Initializing values in associative arrays

2012-11-29 Thread bearophile

Joseph Rushton Wakeling:


How safe is it to rely on doing something like this:

uint[size_t] x;

foreach(i; iota(0, 10))
x[i]++;

foreach(i; iota(5, 15))
x[i]++;


This is part of the D associative array specs, so in theory it's 
safe, but you have to keep this implementation bug in account:

http://d.puremagic.com/issues/show_bug.cgi?id=3825


I note that the above works even if uint[size_t] is changed to 
real[size_t], which is a surprise, because I'd have assumed 
that everything would come out as nan's.


This is a known AA bug :-( I think that there is not yet a patch 
to fix it.


Bye,
bearophile


Re: Apparent problem with GC not collecting on Windows

2012-11-29 Thread Michael
Because you used uint instead of ubyte, array is bigger, memory 
exhausts faster.

Oh, I see.


3. Why it helps?
GC.free(data.ptr);


Initial leak happened because for some reason array allocated 
in previous iteration was not collected by GC when allocating 
new one, so the new one was allocated in another space growing 
the heap. If you place GC.free the array gets removed from heap 
on each iteration and each new allocation reuses the same 
memory, heap doesn't grow.

If we do this manually it's works, but automatically is broken?



Re: Calls to struct methods and immutable

2012-11-29 Thread Dan
On Thursday, 29 November 2012 at 16:28:42 UTC, Joseph Rushton 
Wakeling wrote:
My one caveat here is that in general I'm reluctant to rely too 
strongly on 3rd-party libraries at this stage of D's 
development.  That's particularly true where stuff like this is 
concerned -- which might well be best placed in the standard 
library itself.  Generic, broadly-applicable .dup and .idup 
commands would seem to be something that should be available in 
Phobos ...


... anyway, back to the specifics -- even though I could use 
opmix, I'd still really like to understand for myself how to 
solve the problems described in my previous emails -- in 
particular, how to effectively idup my struct containing the 
Node[uint] associative array _without_ relying on some external 
library.  My feeling is I'll learn more about D this way ... :-)


I feel the same way - as I said there are no guarantees, I'm 
using it but it may not cover the majority of cases and it may be 
obviated by whatever solution Walter is cooking up for copy 
construction and copying of const reference types. Doing it 
yourself is the best way to learn. What I really like about D is 
that you can have what seems like a crippling issue (no way to 
copy const objects) and use features like mixin compile time 
recursion to have a potentially nice general solution. I also 
think the dup should be formalized, maybe not as a keyword but a 
strong convention supported by the language, maybe phobos. For 
example, in your code you have already written 2 idup functions. 
The code below works as well with no need to write those custom 
functions. Besides, it should be safer (assuming it works ;-) 
because you can add new fields and have less to update. BTW: if 
you are still working on this be aware you may eventually have 
some (unwanted?) data sharing going on since there are no 
postblits and you have reference types with aliasing.


Some descriptions of the code and its intentions are:

https://github.com/patefacio/d-help/blob/master/doc/canonical.pdf

Thanks
Dan


import std.stdio;
import std.typecons;
import std.conv;
import std.exception;
import opmix.mix;

alias Tuple!(uint, id) Link;

struct Node
{
  uint id;
  Link[] links;

  void addLink(uint l)
  {
links ~= Link(l);
  }
}


struct Network
{
  Node[uint] nodes;

  void add(uint i, uint j)
  {
if((i in nodes) is null)
  nodes[i] = Node(i);
if((j in nodes) is null)
  nodes[j] = Node(j);

nodes[i].addLink(j);
nodes[j].addLink(i);
  }

  void print()
  {
foreach(k; nodes.keys)
  {
write([, k, ]);
foreach(l; nodes[k].links)
  write( , l.id);
writeln();
  }
writeln();
  }
}

unittest {
  auto n1 = Node(1);

  n1.addLink(5);
  n1.addLink(6);
  writeln(n1.links);

  immutable n2 = cast(immutable)n1.gdup;
  writeln(n2.links);

  Network net1;
  net1.add(1,2);
  immutable Network net2 = cast(immutable)net1.gdup;
  writeln(net1);
  writeln(net2);
}




Re: Apparent problem with GC not collecting on Windows

2012-11-29 Thread Ali Çehreli


On 11/29/2012 12:06 PM, Michael wrote:
 Because you used uint instead of ubyte, array is bigger, memory
 exhausts faster.
 Oh, I see.

 3. Why it helps?
 GC.free(data.ptr);

 Initial leak happened because for some reason array allocated in
 previous iteration was not collected by GC when allocating new one, so
 the new one was allocated in another space growing the heap. If you
 place GC.free the array gets removed from heap on each iteration and
 each new allocation reuses the same memory, heap doesn't grow.
 If we do this manually it's works, but automatically is broken?


Nothing is broken. GC.free would have been applied by the GC only if 
there have been no more references to the allocated block of memory.


The fact is, dmd uses a conservative GC. The issue is due to the 
combination of conservative GC, 32-bit address space, and a large chunk 
of memory. When that happens, it is very likely that any other value in 
the system, including an innocent int, has the risk of looking like a 
reference into that memory. For that reason the GC keeps that memory 
block allocated.


The risk of that happening is grossly reduced in a 64-bit address space. 
Similarly, allocating a much smaller buffer helps as well.


Alternatively, we can use a better GC or a runtime that has a better GC.

Ali



Re: Segfault with std.container.Array but not regular dynamic array

2012-11-29 Thread Dan

On Thursday, 29 November 2012 at 15:06:07 UTC, Maxim Fomin wrote:

On Thursday, 29 November 2012 at 12:38:03 UTC, Dan wrote:
On Thursday, 29 November 2012 at 07:59:02 UTC, Maxim Fomin 
wrote:


This doesn't look like assembly for previous source. Please 
provide the source for which you have assembly and tell which 
dmd options do you use.


Well, I'm using the latest dmd (from the trunk), phobos, 
druntime, so I could build and step through.




This is version generated by rdmd -version=bug --force 
--build-only -g -w -property. The only difference between this 
and yours is in +71.


+00:push   %rbp
+01:mov%rsp,%rbp
+04:sub$0x38,%rsp
+08:push   %rbx
// push 3 as a pkey, -0x30(%rbp) is 3
+09:mov$0x3,%eax
+14:mov%eax,-0x30(%rbp)
+17:lea-0x30(%rbp),%rcx
// push valuesize
+21:movabs $0x8,%rdx
// push keyti
+31:movabs $0x430f50,%rsi
// push map address, it is tls object
+41:mov%fs:0x0,%rdi
+50:add0x21e22f(%rip),%rdi# 0x636fb0
// call, keyti=8, aa=map, valuesize=8, pkey=3
+57:callq  0x419140 _aaGetX
// store return value in -0x28(%rbp)
+62:mov%rax,-0x28(%rbp)
// check array bounds
+66:test   %rax,%rax
+69:jne0x418d99 _Dmain+81
+71:mov$0x13,%edi
+76:callq  0x418e28 _D4main7__arrayZ
// constructing S rhs for opAssign
+81:movabs $0x2a,%rax
+91:mov%rax,-0x18(%rbp) // rhs
+95:mov%rax,%rsi
// making this from -0x20(%rbp), but it was stored in 
-0x28(%rbp)

+98:lea-0x20(%rbp),%rdi
// opAssign loads this from %rdi
+102:   callq  0x418ce0 _D4main1S8opAssignMFS4main1SZv
// replace content in -0x28(%rbp) by -0x20(%rbp)
+107:   mov-0x20(%rbp),%rcx
+111:   mov-0x28(%rbp),%rdx
+115:   mov%rcx,(%rdx)
// load previously created object
+118:   movl   $0x3,-0x10(%rbp)
+125:   lea-0x10(%rbp),%rcx
+129:   movabs $0x8,%rdx
+139:   movabs $0x430f50,%rsi
+149:   mov%fs:0x0,%rax
+158:   mov0x21e1c3(%rip),%rbx# 0x636fb0
+165:   mov(%rax,%rbx,1),%rdi
+169:   callq  0x4192b8 _aaGetRvalueX
// store pointer to existed object
+174:   mov%rax,-0x8(%rbp)
// check array bounds
+178:   test   %rax,%rax
+181:   jne0x418e09 _Dmain+193
+183:   mov$0x14,%edi
+188:   callq  0x418e28 _D4main7__arrayZ
// load x member
+193:   mov-0x8(%rbp),%rcx
+197:   mov(%rcx),%rsi
+200:   movabs $0x430ac0,%rdi
+210:   xor%eax,%eax
+212:   callq  0x4188e0 printf@plt
+217:   xor%eax,%eax
+219:   pop%rbx
+220:   leaveq
+221:   retq
End of assembler dump.

Main stack frame looks follows:
-0x30(%rbp):-0x28(%rbp) 3 as a pkey arg to _aaGetX
-0x28(%rbp):-0x20(%rbp) pointer to S allocated by _aaGetX
-0x20(%rbp):-0x18(%rbp) uninitialized struct - this ptr
-0x18(%rbp):-0x10(%rbp) constructed struct passed as rhs to 
opAssign

-0x10(%rbp):-0x08(%rbp) 3 as a pkey arg to _aaGetRvalueX
-0x08(%rbp):-0x00(%rbp) pointer to S returned from _aaGetRvalueX

It seems that dmd allocates space for two structs, one 
non-initialized, second initialized, issues call to druntime, 
then places a call to opAssign with non-initialized as this 
object with initialized as rhs argument, then writes content on 
non-initialized to allocated by druntime. So, this looks like a 
codegen bug.


By the way, if the code is compiled with command dmd main -g 
-release -noboundscheck -version=bug, opAssign call is placed 
before calling _aaGetX.


Very educational - thanks!



Re: Can operators return type?

2012-11-29 Thread Zhenya

On Thursday, 29 November 2012 at 16:55:01 UTC, bearophile wrote:

Zhenya:

It would useful for some my project,if operators could be a 
template,that return

type.


D operators are functions, and D functions return values. And 
in D types are not values (unlike Python and several other 
languages), unless you use a Typeinfo or something.


Maybe if you explain better what you are trying to do someone 
will be able to suggest you an alternative solution. D is not 
as flexible as Lisp, but it doesn't lack 
meta-programming/type-processing capabilities.


Bye,
bearophile


Of course I understand,that type is not value in D.I meant that 
maybe we can declare non-function template operators.For example:


struct MyIntType
{
alias int type;
template opSlice()
{
alias type opSlice;
}


Re: Can operators return type?

2012-11-29 Thread bearophile

Zhenya:


For example:

struct MyIntType
{
alias int type;
template opSlice()
{
alias type opSlice;
}


As you guess, this is not supported in D.

Bye,
bearophile


Re: Can operators return type?

2012-11-29 Thread Zhenya

On Thursday, 29 November 2012 at 21:53:20 UTC, bearophile wrote:

Zhenya:


For example:

struct MyIntType
{
alias int type;
template opSlice()
{
alias type opSlice;
}


As you guess, this is not supported in D.

Bye,
bearophile


Thank you,understood(


Newb's questions constructor

2012-11-29 Thread js.mdnq
Reading 'the book' and it states that D does not allow one to 
nest construction calls that are not complete.


e.g.,

this()
{
   if (x  1) { this(x); }
}

will fail.

First, I do not know why this is required. It seems to me it 
would be better to allow one optionally use another constructor 
if it is desired rather than forcing all paths to use it.


Also, It is easy to avoid this by alaising this(...)(using 
member functions that this(...) wraps). This, then is exactly the 
same semantically above but avoids the error:


this()
{
   if (x  1) { thiswrapper(x); }
}

this(double x) { thiswrapper(x); }


(so, the constraint in D only increases code bloat as far as I 
can tell and, hence, unnecessary)



Second, steaming from this issue with constructors, how can we 
get the address of a constructor, or alternative, store it in a 
delegate/function:


class Test
{
   static void function(Test, double) thiswrapper;

   this()
   {
  thiswrapper = this(double);
  if (x  1) { thiswrapper(x); }
   }

   this(double x) { }
}


The point of the example code(only an example, I know it is 
rather useless but so are babies, right?) is to simply do the 
same the previous example but sort of backwards. The previous 
example has thiswrapper being wrapped by this(double) while in 
this case thiswrapper wraps this(double). They will will have 
virtually identical semantics with different syntax.


The second case allows us to solve the original problem a bit 
more logical. (in fact, if we had some type of multi-function 
pointer that allowed overloads we could, say, assign all the 
constructor functions to thiswrapper and let the compiler choose 
the appropriate one)


In any case the second question involves assigning functions to 
function pointers/delegates, specifically the constructor 
functions.


I guess it would be the a similar problem if I wanted to assign a 
function pointer to a member of a class from a pointer to that 
class.


class Test { void mymethod(...){} void mymethod(){}}

void function(...) mymethodptr = t-mymethod; (which should be 
the same as Test.mymethod?)


Thanks





Templated Function pointers

2012-11-29 Thread js.mdnq



I need to store a templated function in a function pointer, how 
can I do this?



e.g.,

void function(double) myfuncptr;
void myfunc(double d) { }
myfuncptr = myfunc;

Now I would like to use a template parameter instead of double.

In C++ one can do this by using boosts binding's and function 
types.


For example, I want something like this

void function(F)(F) funcptr;

void Bind(T)(void function(T)(T) v)
{
funcptr = v; // F is sort of deduced automatically as being 
T. Obviously problematic but effectively what I want to do.

}

This way I can bind to any function that takes a single type 
parameter and returns a void.



void function(F) myfuncptr;  // F is undefined
void myfunc(T)(T d) { }  //
myfuncptr = myfunc;

To do this using boost I would simply bind the parameter so 
myfuncptr would not depend on an arbitrary type.


I need a rather performant way to do this too.





prune with dirEntries

2012-11-29 Thread Dan
Is there a way to walk files with std.file.dirEntries such that 
certain directories are skipped (i.e. how to avoid .git 
entirely/recursively)?


Thanks
Dan


Re: prune with dirEntries

2012-11-29 Thread Jonathan M Davis
On Friday, November 30, 2012 01:24:07 Dan wrote:
 Is there a way to walk files with std.file.dirEntries such that
 certain directories are skipped (i.e. how to avoid .git
 entirely/recursively)?

You can use std.algorithm.filter on its result. Then when it would iterate to 
something which doesn't match filter's predicate, it skips it.

- Jonathan M Davis


Re: prune with dirEntries

2012-11-29 Thread Dan
On Friday, 30 November 2012 at 01:13:13 UTC, Jonathan M Davis 
wrote:

On Friday, November 30, 2012 01:24:07 Dan wrote:

Is there a way to walk files with std.file.dirEntries such that
certain directories are skipped (i.e. how to avoid .git
entirely/recursively)?


You can use std.algorithm.filter on its result. Then when it 
would iterate to

something which doesn't match filter's predicate, it skips it.

- Jonathan M Davis


That will do the filtering correctly - but what I was hoping was 
to actually prune at the directory level and not drill down to 
the files in of an unwanted directory (e.g. .git). The problem 
with this and what I'm trying to overcome is accessing lots of 
files and directories recursively all of which I want to skip. 
Much like there is a *followSymlink* it would be nice if a 
predicate were accepted to *followDirectory* in general or some 
way to cause that.


---

static bool desired(string m) {
  bool unwanted = match(m, _uninterestRe)? true : false;
  writeln(Is unwanted , m,  , unwanted);
  return !unwanted;
}
static Regex!(char) _uninterestRe = regex(`\.git\b`);
filter!(desired)(dirEntries(root, SpanMode.depth))) {
...
}


Re: prune with dirEntries

2012-11-29 Thread Jonathan M Davis
On Friday, November 30, 2012 02:57:20 Dan wrote:
 On Friday, 30 November 2012 at 01:13:13 UTC, Jonathan M Davis
 
 wrote:
  On Friday, November 30, 2012 01:24:07 Dan wrote:
  Is there a way to walk files with std.file.dirEntries such that
  certain directories are skipped (i.e. how to avoid .git
  entirely/recursively)?
  
  You can use std.algorithm.filter on its result. Then when it
  would iterate to
  something which doesn't match filter's predicate, it skips it.
  
  - Jonathan M Davis
 
 That will do the filtering correctly - but what I was hoping was
 to actually prune at the directory level and not drill down to
 the files in of an unwanted directory (e.g. .git). The problem
 with this and what I'm trying to overcome is accessing lots of
 files and directories recursively all of which I want to skip.
 Much like there is a *followSymlink* it would be nice if a
 predicate were accepted to *followDirectory* in general or some
 way to cause that.
 
 ---
 
 static bool desired(string m) {
 bool unwanted = match(m, _uninterestRe)? true : false;
 writeln(Is unwanted , m,  , unwanted);
 return !unwanted;
 }
 static Regex!(char) _uninterestRe = regex(`\.git\b`);
 filter!(desired)(dirEntries(root, SpanMode.depth))) {
 ...
 }

You can use the glob matching overload then:

auto dirEntries(string path, string pattern, SpanMode mode,
 bool followSymlink = true)

I don't really know how to use it though, so you'll have to read the docs and 
figure it out.

- Jonathan M Davis


Type converter from build in to user type

2012-11-29 Thread js.mdnq
I have a struct I am trying convert from int's to the type. Since 
I can't add a opCast overload to an int I don't know how to do 
it. My opCast convertors in my class do not work for the 
assignment operator:



class myType
{
   opCast, opAssign
}

mytype = 3;

Error that we can't convert an int to myType. While it's very 
easy to go from a myType to whatever by writing a cast for it(in 
the class), how do I go from an int to myType(in the class)?


For example, I can do

mytype = mytype.opCast(3);
or mytype.opAssign(3);

but these are too verbose to be useful.




Re: Type converter from build in to user type

2012-11-29 Thread Jonathan M Davis
On Friday, November 30, 2012 03:59:05 js.mdnq wrote:
 I have a struct I am trying convert from int's to the type. Since
 I can't add a opCast overload to an int I don't know how to do
 it. My opCast convertors in my class do not work for the
 assignment operator:
 
 
 class myType
 {
 opCast, opAssign
 }
 
 mytype = 3;
 
 Error that we can't convert an int to myType. While it's very
 easy to go from a myType to whatever by writing a cast for it(in
 the class), how do I go from an int to myType(in the class)?
 
 For example, I can do
 
 mytype = mytype.opCast(3);
 or mytype.opAssign(3);
 
 but these are too verbose to be useful.

You can put a constructor on your type which takes an int and then use 
std.conv.to instead of casting. It's generally preferred to use std.conv.to 
anyway, since it's generally safer (since it allows fewer (no?) unsafe casts 
and checks conversions in some cases - e.g. whether the value in the int being 
cast to ubyte will fit in a ubyte). It will also use your opCast if you define 
one, so you can then use std.conv.to in both directions.

- Jonathan M Davis


Re: Type converter from build in to user type

2012-11-29 Thread jerro

On Friday, 30 November 2012 at 02:59:06 UTC, js.mdnq wrote:
I have a struct I am trying convert from int's to the type. 
Since I can't add a opCast overload to an int I don't know how 
to do it. My opCast convertors in my class do not work for the 
assignment operator:



class myType
{
   opCast, opAssign
}

mytype = 3;

Error that we can't convert an int to myType. While it's very 
easy to go from a myType to whatever by writing a cast for 
it(in the class), how do I go from an int to myType(in the 
class)?


For example, I can do

mytype = mytype.opCast(3);
or mytype.opAssign(3);

but these are too verbose to be useful.


Why can't you use opAssign? This works fine:

class A
{
void opAssign(int i)
{
writeln(i);
}
}

auto a = new A();
a = 1; // prints 1



Re: Type converter from build in to user type

2012-11-29 Thread Ali Çehreli

On 11/29/2012 07:24 PM, jerro wrote:

On Friday, 30 November 2012 at 02:59:06 UTC, js.mdnq wrote:

I have a struct I am trying convert from int's to the type. Since I
can't add a opCast overload to an int I don't know how to do it. My
opCast convertors in my class do not work for the assignment operator:


class myType
{
opCast, opAssign
}

mytype = 3;

Error that we can't convert an int to myType. While it's very easy to
go from a myType to whatever by writing a cast for it(in the class),
how do I go from an int to myType(in the class)?

For example, I can do

mytype = mytype.opCast(3);
or mytype.opAssign(3);

but these are too verbose to be useful.


Why can't you use opAssign? This works fine:

class A
{
void opAssign(int i)
{
writeln(i);
}
}

auto a = new A();
a = 1; // prints 1



A complete example:

import std.conv;

class C
{
int i;

this(int i)
{
this.i = i;
}

C opAssign(int i)
{
this.i = i;
return this;
}

int opCast(T : int)() const
{
return i;
}
}

void main()
{
auto c = new C(42);
c = 43;
auto i = to!int(c);
assert(i == 43);
}

Ali


Re: Calls to struct methods and immutable

2012-11-29 Thread Ali Çehreli

On 11/27/2012 06:05 AM, Joseph Rushton Wakeling wrote:

On 11/27/2012 01:16 PM, Joseph Rushton Wakeling wrote:

immutable(Node) idup() pure const @property
{
auto linkCopy = to!(Link[])(links);
immutable ilinks = assumeUnique(linkCopy);
return immutable(Node)(id, ilinks);
}


Actually I'm being overly complicated here as with dynamic arrays I can
simply do,

immutable(Node) idup() pure const @property
{
return immutable(Node)(id, links.idup);
}

... so the real issue here seems to be that there's no canonical way
(that I can find) to idup an _associative_ array.


I've forced it pretty hard: :D

immutable(Network) idup() pure const @property
{
Node[uint] nodesCopy;

foreach (key, node; nodes) {
immutable(Node) nodeCopy = node.idup;
nodesCopy[key] = cast(Node)nodeCopy;
}

immutable imnodes = assumeUnique(nodesCopy);
return immutable(Network)(imnodes);
}

I hope it is safe. :p

Ali


Re: prune with dirEntries

2012-11-29 Thread Joshua Niehus

On Friday, 30 November 2012 at 01:57:21 UTC, Dan wrote:
That will do the filtering correctly - but what I was hoping 
was to actually prune at the directory level and not drill down 
to the files in of an unwanted directory (e.g. .git). The 
problem with this and what I'm trying to overcome is accessing 
lots of files and directories recursively all of which I want 
to skip. Much like there is a *followSymlink* it would be nice 
if a predicate were accepted to *followDirectory* in general or 
some way to cause that.


what about the following?

import std.algorithm, std.array, std.regex;
import std.stdio, std.file;
void main()
{
  auto exclude = regex(r\.git, g);
  dirEntries(/path/GIT, SpanMode.breadth)
.filter!(a = match(a.name, exclude).empty)
.writeln();
}

I think if you go breadth first, you can filter out the unwanted 
directories before it delves into them




Re: prune with dirEntries

2012-11-29 Thread Joshua Niehus

On Friday, 30 November 2012 at 06:29:01 UTC, Joshua Niehus wrote:
I think if you go breadth first, you can filter out the 
unwanted directories before it delves into them


oh wait... it probably still looks through all those dir's.
What about this?

import std.algorithm, std.regex, std.stdio, std.file;
import std.parallelism;
DirEntry[] prune(string path, ref DirEntry[] files)
{
  auto exclude = regex(r\.git|\.DS_Store, g);
  foreach(_path; taskPool.parallel(dirEntries(path, 
SpanMode.shallow)

.filter!(a = match(a.name, exclude).empty)))
  {
files ~= _path;
if (isDir(_path.name)) { prune(_path.name, files); }
  }
return files;
}

void main()
{
  DirEntry[] files;
  prune(/path, files);
  foreach(file;files) { writeln(file.name); }
}