www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - no macros in D?

reply "Maxime Larose" <mlarose broadsoft.com> writes:
I'm I missing something or is there no way to have true macros in D?  The
facilities to generate boiler plate code doesn't seem to go far enough.

For instance, I want to define an alias/template/mixin/whatever for
simplifying the syntax to create stuff on the stack. Here is how the code
would look ideally:

void main()
{
  char[] abc = stack_char(1000);
}

stack_char being a specialization of a stack_array!(T) or something like
that.

I tried a thousand variations with mixins, templates and aliases, the
compiler is always complaining one way or the other. And when it works, a
function is called (defeating the purpose of creating the variable in the
local stack).

Even doing something very simply like:
alias cast(char*)std.c.stdlib.alloca stack_char;

doesn't work. The compiler complains about the (char*).


Less ideally, I thought of doing:
stack_array(abc, char, 1000);

which would expand to:
char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]

This seems simple enough. However, it doesn't work because "abc" is not
defined prior to use. (Even when I use an "alias" parameter for the
template.)

I'm I missing something? This seems like very simple stuff...
May 04 2005
next sibling parent reply "Andrew Fedoniouk" <news terrainformatica.com> writes:
Maxime,

could you check your code again?
Following just works:
----------------------------------
import std.stdio;
import std.c.stdlib;

template stackArray(T, uint N)
{
  char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
}

int main(char[][] args)
{
  mixin stackArray!(char,1000);
  v[0] = 'h';
  writef("%d\n", v.length );
  return 0;
}
-----------------------------------


"Maxime Larose" <mlarose broadsoft.com> wrote in message 
news:d5apgr$279m$1 digitaldaemon.com...
 I'm I missing something or is there no way to have true macros in D?  The
 facilities to generate boiler plate code doesn't seem to go far enough.

 For instance, I want to define an alias/template/mixin/whatever for
 simplifying the syntax to create stuff on the stack. Here is how the code
 would look ideally:

 void main()
 {
  char[] abc = stack_char(1000);
 }

 stack_char being a specialization of a stack_array!(T) or something like
 that.

 I tried a thousand variations with mixins, templates and aliases, the
 compiler is always complaining one way or the other. And when it works, a
 function is called (defeating the purpose of creating the variable in the
 local stack).

 Even doing something very simply like:
 alias cast(char*)std.c.stdlib.alloca stack_char;

 doesn't work. The compiler complains about the (char*).


 Less ideally, I thought of doing:
 stack_array(abc, char, 1000);

 which would expand to:
 char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]

 This seems simple enough. However, it doesn't work because "abc" is not
 defined prior to use. (Even when I use an "alias" parameter for the
 template.)

 I'm I missing something? This seems like very simple stuff...




 
May 04 2005
next sibling parent reply Vathix <vathix dprogramming.com> writes:
On Wed, 04 May 2005 11:41:23 -0400, Andrew Fedoniouk  
<news terrainformatica.com> wrote:

 Maxime,

 could you check your code again?
 Following just works:
 ----------------------------------
 import std.stdio;
 import std.c.stdlib;

 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }

 int main(char[][] args)
 {
   mixin stackArray!(char,1000);
   v[0] = 'h';
   writef("%d\n", v.length );
   return 0;
 }
 -----------------------------------
Beat me to it :p private import std.c.stdlib, std.stdio; template stack_array(T, size_t count) { T[] value = (cast(T*)std.c.stdlib.alloca(count * T.sizeof))[0 .. count]; } int main() { mixin stack_array!(char, 500) abc; abc.value[0 .. 500] = 'f'; writefln("The length is %d", abc.value.length); writefln("The answer is '%s'", abc.value); return 0; }
May 04 2005
parent reply "Andrew Fedoniouk" <news terrainformatica.com> writes:
Oh, yeh :)))

Thanks a lot.
As always with concept cars
they can move in theory but in practice only on podium.
That was just such a car. Quick and ugly.

Beg my pardon,

Uwe, thanks you too.

Andrew.




"Vathix" <vathix dprogramming.com> wrote in message 
news:op.sp9cntpqkcck4r esi...
 On Wed, 04 May 2005 11:41:23 -0400, Andrew Fedoniouk 
 <news terrainformatica.com> wrote:

 Maxime,

 could you check your code again?
 Following just works:
 ----------------------------------
 import std.stdio;
 import std.c.stdlib;

 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }

 int main(char[][] args)
 {
   mixin stackArray!(char,1000);
   v[0] = 'h';
   writef("%d\n", v.length );
   return 0;
 }
 -----------------------------------
Beat me to it :p private import std.c.stdlib, std.stdio; template stack_array(T, size_t count) { T[] value = (cast(T*)std.c.stdlib.alloca(count * T.sizeof))[0 .. count]; } int main() { mixin stack_array!(char, 500) abc; abc.value[0 .. 500] = 'f'; writefln("The length is %d", abc.value.length); writefln("The answer is '%s'", abc.value); return 0; }
May 04 2005
parent reply "Maxime Larose" <mlarose broadsoft.com> writes:
 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }
This variant is not really re-useable because the variable name is fixed, i.e. "v". It prevents you from having many such variables in the same function (or forces you to define many different templates...) (I had tried it)
 template stack_array(T, size_t count)
 {
    T[] value = (cast(T*)std.c.stdlib.alloca(count * T.sizeof))[0 ..
 count];
 }

 int main()
 {
    mixin stack_array!(char, 500) abc;

    abc.value[0 .. 500] = 'f';
This variant is good and generally useable. I didn't try it, because I didn't know it was possible to put the name of a variable after the mixin... It's not in the doc at any rate and not really intuitive (IMO). But if it works... ;) All right, thanks. I'll try it out tonight. Max "Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d5ariq$29j2$1 digitaldaemon.com...
 Oh, yeh :)))

 Thanks a lot.
 As always with concept cars
 they can move in theory but in practice only on podium.
 That was just such a car. Quick and ugly.

 Beg my pardon,

 Uwe, thanks you too.

 Andrew.




 "Vathix" <vathix dprogramming.com> wrote in message
 news:op.sp9cntpqkcck4r esi...
 On Wed, 04 May 2005 11:41:23 -0400, Andrew Fedoniouk
 <news terrainformatica.com> wrote:

 Maxime,

 could you check your code again?
 Following just works:
 ----------------------------------
 import std.stdio;
 import std.c.stdlib;

 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }

 int main(char[][] args)
 {
   mixin stackArray!(char,1000);
   v[0] = 'h';
   writef("%d\n", v.length );
   return 0;
 }
 -----------------------------------
Beat me to it :p private import std.c.stdlib, std.stdio; template stack_array(T, size_t count) { T[] value = (cast(T*)std.c.stdlib.alloca(count * T.sizeof))[0 .. count]; } int main() { mixin stack_array!(char, 500) abc; abc.value[0 .. 500] = 'f'; writefln("The length is %d", abc.value.length); writefln("The answer is '%s'", abc.value); return 0; }
May 04 2005
next sibling parent "Andrew Fedoniouk" <news terrainformatica.com> writes:
 This variant is not really re-useable because the variable name is fixed,
 i.e. "v". It prevents you from having many such variables in the same
 function (or forces you to define many different templates...)  (I had 
 tried
 it)
What about this: import std.stdio; import std.c.stdlib; template stackArray(T, uint N) { char[] elements = (cast(T*)std.c.stdlib.alloca(N*T.sizeof))[0..N]; } int main(char[][] args) { mixin stackArray!(char,1000) one; mixin stackArray!(char,2000) two; one.elements[0] = 'h'; two.elements[0] = 'h'; writef("%d\n", one.elements.length ); writef("%d\n", two.elements.length ); return 0; } "Maxime Larose" <mlarose broadsoft.com> wrote in message news:d5atv3$2c3j$1 digitaldaemon.com...
 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }
This variant is not really re-useable because the variable name is fixed, i.e. "v". It prevents you from having many such variables in the same function (or forces you to define many different templates...) (I had tried it)
 template stack_array(T, size_t count)
 {
    T[] value = (cast(T*)std.c.stdlib.alloca(count * T.sizeof))[0 ..
 count];
 }

 int main()
 {
    mixin stack_array!(char, 500) abc;

    abc.value[0 .. 500] = 'f';
This variant is good and generally useable. I didn't try it, because I didn't know it was possible to put the name of a variable after the mixin... It's not in the doc at any rate and not really intuitive (IMO). But if it works... ;) All right, thanks. I'll try it out tonight. Max "Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d5ariq$29j2$1 digitaldaemon.com...
 Oh, yeh :)))

 Thanks a lot.
 As always with concept cars
 they can move in theory but in practice only on podium.
 That was just such a car. Quick and ugly.

 Beg my pardon,

 Uwe, thanks you too.

 Andrew.




 "Vathix" <vathix dprogramming.com> wrote in message
 news:op.sp9cntpqkcck4r esi...
 On Wed, 04 May 2005 11:41:23 -0400, Andrew Fedoniouk
 <news terrainformatica.com> wrote:

 Maxime,

 could you check your code again?
 Following just works:
 ----------------------------------
 import std.stdio;
 import std.c.stdlib;

 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }

 int main(char[][] args)
 {
   mixin stackArray!(char,1000);
   v[0] = 'h';
   writef("%d\n", v.length );
   return 0;
 }
 -----------------------------------
Beat me to it :p private import std.c.stdlib, std.stdio; template stack_array(T, size_t count) { T[] value = (cast(T*)std.c.stdlib.alloca(count * T.sizeof))[0 .. count]; } int main() { mixin stack_array!(char, 500) abc; abc.value[0 .. 500] = 'f'; writefln("The length is %d", abc.value.length); writefln("The answer is '%s'", abc.value); return 0; }
May 04 2005
prev sibling parent Chris Sauls <ibisbasenji gmail.com> writes:
Maxime Larose wrote:
 This variant is good and generally useable. I didn't try it, because I
 didn't know it was possible to put the name of a variable after the mixin...
 It's not in the doc at any rate and not really intuitive (IMO). But if it
 works... ;)
It is in the docs... see ( http://www.digitalmars.com/d/mixin.html ) in two places. Once at the beginning where the mixin grammar is given as:
 TemplateMixin:
   mixin TemplateIdentifier ;
   mixin TemplateIdentifier MixinIdentifier ;
   mixin TemplateIdentifier !( TemplateArgumentList ) ;
   mixin TemplateIdentifier !( TemplateArgumentList ) MixinIdentifier ;

 MixinIdentifier:
   Identifier
And again fairly near the end, where it says "If a mixin has a MixinIdentifier, it can be used to disambiguate" and then gives an example. I know its easy to miss some things in the docs... all kinds of hidden treasures in there if one gets out the proverbial fine-toothed comb. -- Chris Sauls
May 05 2005
prev sibling parent "Uwe Salomon" <post uwesalomon.de> writes:
 template stackArray(T, uint N)
 {
   char[] v = (cast(T*)std.c.stdlib.alloca(N))[0..N];
 }
Uh. Isn't that better? : template stackArray(T, size_t N) { T[] vec = (cast(T*) std.c.stdlib.alloca(N * T.sizeof))[0 .. N]; } And some specialization for N*T.sizeof > xxx bytes would do some good, to... Ciao uwe
May 04 2005
prev sibling next sibling parent "Uwe Salomon" <post uwesalomon.de> writes:
It is not that simple, because alloca() allocates on the stack of the  
called function, thus you cannot insert it into a sub-function (if it  
returns, the allocated space is gone). You have to write a little more  
sophisticated template like QVarLengthArray from Qt 4.0 (should be at  
http://doc.trolltech.com/4.0/qvarlengtharray.html). When i have finished  
indigo.string (a QString lookalike), i will perhaps work on that. Just to  
give you a hint:


struct VarLengthArray(T, size_t stackSize)
{
private:
   T[stackSize] m_stackData;

public:
   T[] data(size_t neededSize)
   {
     if (neededSize <= stackSize)
       return m_stackData[0 .. neededSize];
     else
       return new T[neededSize];
   }	
}


Well, this is really a simple algorithm, but it shows the principle quite  
well. You allocate a fixed size on the stack, and if that's not enough,  
you take from the heap. You can use that like this:


void myFunc(int someParam, size_t elemCountToWorkWith)
{
   VarLengthArray!(uint, 256) stackArray;
   uint[] vec = stackArray.data(elemCountToWorkWith);

   // Do something with vec...
   foreach (uint x; vec)
     // ...
}


Here you have a function that has to do something with a certain number of  
uint's, which will be less than 256 in 90% of the cases (or whatever  
percentage you need). If elemCountToWorkWith is under 256, this array will  
be allocated on the stack (very fast), otherwise on the heap. If you call  
this function often, this will make a significant speed improvement (and  
of course create less garbage). But i do not know how much faster/slower  
than alloca() this variant is (at least it does not safe you some typing.  
:)

Ciao
uwe
May 04 2005
prev sibling next sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
"Maxime Larose" <mlarose broadsoft.com> wrote in message 
news:d5apgr$279m$1 digitaldaemon.com...
 I'm I missing something or is there no way to have true macros in D?  The
 facilities to generate boiler plate code doesn't seem to go far enough.
[snip]
 char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]
It would be nice if placement worked for char[]s: char[] abc = new(alloca(1000))char[1000]; From my experiments the line above compiles but it looks like it winds up allocating from the GC. Note in the example about alloca it would be nice if the "std.c.stdlib" were removed since it makes the code look nastier than it has to be. I suppose it tells the reader that alloca is in std.c.stdlib but it gives the impression it should always be used when allocating from the stack.
May 04 2005
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <d5apgr$279m$1 digitaldaemon.com>, Maxime Larose says...
I'm I missing something or is there no way to have true macros in D?  The
facilities to generate boiler plate code doesn't seem to go far enough.
Mixins are about as close as you can get. Why not use plain old functions and compile with -inline? That should address performance concerns in most cases. Sean
May 04 2005
parent reply "Maxime Larose" <mlarose broadsoft.com> writes:
In debug mode, that would simply crash... I.e. the "stack" allocated
variable would be allocated on the stack of the callee, not the caller.
Inlining only partially solves the problem in that you are never sure of
what gets inlined and what does not. It leads to non-portable code at its
worst.



"Sean Kelly" <sean f4.ca> wrote in message
news:d5asqh$2arf$1 digitaldaemon.com...
 In article <d5apgr$279m$1 digitaldaemon.com>, Maxime Larose says...
I'm I missing something or is there no way to have true macros in D?  The
facilities to generate boiler plate code doesn't seem to go far enough.
Mixins are about as close as you can get. Why not use plain old functions
and
 compile with -inline?  That should address performance concerns in most
cases.
 Sean
May 04 2005
parent Sean Kelly <sean f4.ca> writes:
I'd forgotten you were doing stack allocations :p  What about a memory manager
that uses a static array of ubyte as a memory pool?


In article <d5b0d5$2en9$1 digitaldaemon.com>, Maxime Larose says...
In debug mode, that would simply crash... I.e. the "stack" allocated
variable would be allocated on the stack of the callee, not the caller.
Inlining only partially solves the problem in that you are never sure of
what gets inlined and what does not. It leads to non-portable code at its
worst.

"Sean Kelly" <sean f4.ca> wrote in message
news:d5asqh$2arf$1 digitaldaemon.com...
 In article <d5apgr$279m$1 digitaldaemon.com>, Maxime Larose says...
I'm I missing something or is there no way to have true macros in D?  The
facilities to generate boiler plate code doesn't seem to go far enough.
Mixins are about as close as you can get. Why not use plain old functions
and
 compile with -inline?  That should address performance concerns in most
cases.
 Sean
May 04 2005
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
How about
   void main()
   {
     char[1000] abc;
   }
?

Maxime Larose wrote:
 I'm I missing something or is there no way to have true macros in D?  The
 facilities to generate boiler plate code doesn't seem to go far enough.
 
 For instance, I want to define an alias/template/mixin/whatever for
 simplifying the syntax to create stuff on the stack. Here is how the code
 would look ideally:
 
 void main()
 {
   char[] abc = stack_char(1000);
 }
 
 stack_char being a specialization of a stack_array!(T) or something like
 that.
 
 I tried a thousand variations with mixins, templates and aliases, the
 compiler is always complaining one way or the other. And when it works, a
 function is called (defeating the purpose of creating the variable in the
 local stack).
 
 Even doing something very simply like:
 alias cast(char*)std.c.stdlib.alloca stack_char;
 
 doesn't work. The compiler complains about the (char*).
 
 
 Less ideally, I thought of doing:
 stack_array(abc, char, 1000);
 
 which would expand to:
 char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]
 
 This seems simple enough. However, it doesn't work because "abc" is not
 defined prior to use. (Even when I use an "alias" parameter for the
 template.)
 
 I'm I missing something? This seems like very simple stuff...
 
 
 
 
 
May 04 2005
parent reply "Maxime Larose" <mlarose broadsoft.com> writes:
This will create an arrray in the heap, not on the stack. (That's a main
difference between C(++) and D)


"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:d5b42s$2hns$1 digitaldaemon.com...
 How about
    void main()
    {
      char[1000] abc;
    }
 ?

 Maxime Larose wrote:
 I'm I missing something or is there no way to have true macros in D?
The
 facilities to generate boiler plate code doesn't seem to go far enough.

 For instance, I want to define an alias/template/mixin/whatever for
 simplifying the syntax to create stuff on the stack. Here is how the
code
 would look ideally:

 void main()
 {
   char[] abc = stack_char(1000);
 }

 stack_char being a specialization of a stack_array!(T) or something like
 that.

 I tried a thousand variations with mixins, templates and aliases, the
 compiler is always complaining one way or the other. And when it works,
a
 function is called (defeating the purpose of creating the variable in
the
 local stack).

 Even doing something very simply like:
 alias cast(char*)std.c.stdlib.alloca stack_char;

 doesn't work. The compiler complains about the (char*).


 Less ideally, I thought of doing:
 stack_array(abc, char, 1000);

 which would expand to:
 char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]

 This seems simple enough. However, it doesn't work because "abc" is not
 defined prior to use. (Even when I use an "alias" parameter for the
 template.)

 I'm I missing something? This seems like very simple stuff...
May 04 2005
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I'm pretty sure that this is not correct.  Fixed-length arrays are 
created on the stack.  Dynamic arrays, of course, are on the heap.  Try 
running this program:

   import std.stdio;
   void main() {
     int i;
     char[1000] abc;
     int j;
     writefln("&i=%d &abc=%d &abc[0]=%d &j=%d\n", &i,&abc,&abc[0],&j);
   }

I get:
   &i=bffff458 &abc=bffff45c &abc[0]=bffff45c &j=bffff844

Maxime Larose wrote:
 This will create an arrray in the heap, not on the stack. (That's a main
 difference between C(++) and D)
 
 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:d5b42s$2hns$1 digitaldaemon.com...
 
How about
   void main()
   {
     char[1000] abc;
   }
?

Maxime Larose wrote:

I'm I missing something or is there no way to have true macros in D?
The
facilities to generate boiler plate code doesn't seem to go far enough.

For instance, I want to define an alias/template/mixin/whatever for
simplifying the syntax to create stuff on the stack. Here is how the
code
would look ideally:

void main()
{
  char[] abc = stack_char(1000);
}

stack_char being a specialization of a stack_array!(T) or something like
that.

I tried a thousand variations with mixins, templates and aliases, the
compiler is always complaining one way or the other. And when it works,
a
function is called (defeating the purpose of creating the variable in
the
local stack).

Even doing something very simply like:
alias cast(char*)std.c.stdlib.alloca stack_char;

doesn't work. The compiler complains about the (char*).


Less ideally, I thought of doing:
stack_array(abc, char, 1000);

which would expand to:
char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]

This seems simple enough. However, it doesn't work because "abc" is not
defined prior to use. (Even when I use an "alias" parameter for the
template.)

I'm I missing something? This seems like very simple stuff...
May 04 2005
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
I don't think this is true.  Static arrays should be allocated on the stack just
as in C.  The page on arrays and the page on memory management seem to confirm
this.  The only catch is that this syntax *will* zero out the array contents,
which may be undesirable from a performance perspective.

In article <d5b9dl$2n39$1 digitaldaemon.com>, Maxime Larose says...
This will create an arrray in the heap, not on the stack. (That's a main
difference between C(++) and D)


"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:d5b42s$2hns$1 digitaldaemon.com...
 How about
    void main()
    {
      char[1000] abc;
    }
May 04 2005
parent "Maxime Larose" <mlarose broadsoft.com> writes:
Reading the section on memory management, I really got the feeling that
arrays were created on the heap... I got confused with classes apparently.
Very sorry to have wasted your time... (Though I'm glad I now know the
"mixin template!(T) var" way of using mixins...)



"Sean Kelly" <sean f4.ca> wrote in message
news:d5bakl$2oau$1 digitaldaemon.com...
 I don't think this is true.  Static arrays should be allocated on the
stack just
 as in C.  The page on arrays and the page on memory management seem to
confirm
 this.  The only catch is that this syntax *will* zero out the array
contents,
 which may be undesirable from a performance perspective.

 In article <d5b9dl$2n39$1 digitaldaemon.com>, Maxime Larose says...
This will create an arrray in the heap, not on the stack. (That's a main
difference between C(++) and D)


"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:d5b42s$2hns$1 digitaldaemon.com...
 How about
    void main()
    {
      char[1000] abc;
    }
May 04 2005
prev sibling next sibling parent Kramer <Kramer_member pathlink.com> writes:
In article <d5b9dl$2n39$1 digitaldaemon.com>, Maxime Larose says...
This will create an arrray in the heap, not on the stack. (That's a main
difference between C(++) and D)
Is that bad? Would that cause performance problems? I'm guessing the answers to these questions are it depends (what application domain?; what's bad?) Is that a fundamental shift from other languages? -Kramer
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:d5b42s$2hns$1 digitaldaemon.com...
 How about
    void main()
    {
      char[1000] abc;
    }
 ?

 Maxime Larose wrote:
 I'm I missing something or is there no way to have true macros in D?
The
 facilities to generate boiler plate code doesn't seem to go far enough.

 For instance, I want to define an alias/template/mixin/whatever for
 simplifying the syntax to create stuff on the stack. Here is how the
code
 would look ideally:

 void main()
 {
   char[] abc = stack_char(1000);
 }

 stack_char being a specialization of a stack_array!(T) or something like
 that.

 I tried a thousand variations with mixins, templates and aliases, the
 compiler is always complaining one way or the other. And when it works,
a
 function is called (defeating the purpose of creating the variable in
the
 local stack).

 Even doing something very simply like:
 alias cast(char*)std.c.stdlib.alloca stack_char;

 doesn't work. The compiler complains about the (char*).


 Less ideally, I thought of doing:
 stack_array(abc, char, 1000);

 which would expand to:
 char[] abc = (cast(char*)std.c.stdlib.alloca(1000))[0..1000]

 This seems simple enough. However, it doesn't work because "abc" is not
 defined prior to use. (Even when I use an "alias" parameter for the
 template.)

 I'm I missing something? This seems like very simple stuff...
May 04 2005
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Maxime Larose" <mlarose broadsoft.com> wrote in message
news:d5b9dl$2n39$1 digitaldaemon.com...
 This will create an arrray in the heap, not on the stack. (That's a main
 difference between C(++) and D)
No, it'll be on the stack just like in C/C++.
May 04 2005
parent reply "Maxime Larose" <mlarose broadsoft.com> writes:
Then, how are arrays returned? Is't not safe to return a char[] from a
function if it's allocated on the stack?!?
I must have been messed up really good then, because as a GC'ed language I
assumed one was free to return a string (char[]) from a function. I *think*
I even already did it, but I may be mistaken (or I was just very luck that
the stack didn't get corrupted)...




"Walter" <newshound digitalmars.com> wrote in message
news:d5bc2t$2pca$1 digitaldaemon.com...
 "Maxime Larose" <mlarose broadsoft.com> wrote in message
 news:d5b9dl$2n39$1 digitaldaemon.com...
 This will create an arrray in the heap, not on the stack. (That's a main
 difference between C(++) and D)
No, it'll be on the stack just like in C/C++.
May 05 2005
parent reply Chris Sauls <ibisbasenji gmail.com> writes:
Maxime Larose wrote:
 Then, how are arrays returned? Is't not safe to return a char[] from a
 function if it's allocated on the stack?!?
 I must have been messed up really good then, because as a GC'ed language I
 assumed one was free to return a string (char[]) from a function. I *think*
 I even already did it, but I may be mistaken (or I was just very luck that
 the stack didn't get corrupted)...
Dynamic arrays (such as char[]) are on the heap, so may be freely returned. I assume that if one returns a static array (such as char[256]) then a copy would be made. Of course, you could define a function as returning a dynamic array, and still return the value of a static array. As I understand it, its data is copied to a new dynamic array, and a referance to the anonymous dynamic array is returned. -- Chris Sauls
May 05 2005
next sibling parent reply "Maxime Larose" <mlarose broadsoft.com> writes:
"Chris Sauls" <ibisbasenji gmail.com> wrote in message
news:d5csgj$sha$1 digitaldaemon.com...
 Maxime Larose wrote:
 Then, how are arrays returned? Is't not safe to return a char[] from a
 function if it's allocated on the stack?!?
 I must have been messed up really good then, because as a GC'ed language
I
 assumed one was free to return a string (char[]) from a function. I
*think*
 I even already did it, but I may be mistaken (or I was just very luck
that
 the stack didn't get corrupted)...
Dynamic arrays (such as char[]) are on the heap, so may be freely returned. I assume that if one returns a static array (such as char[256]) then a copy would be made. Of course, you could define a function as returning a dynamic array, and still return the value of a static array. As I understand it, its data is copied to a new dynamic array, and a referance to the anonymous dynamic array is returned. -- Chris Sauls
Hmm.... The behavior for static arrays seems fairly innefficient... And what about: classA [1000] array; Then I guess the classes themselves are on the heap, but the array is not? And if the array is returned, then it is copied to the heap. Or does the compiler detects this case and immediately allocate the array on the heap? What's the best way to allocate a fixed-size array directly on the heap? Is this documented anywhere? I read the docs from cover to cover but it seems I missed a few things... I checked again in the sections that seem relevant and didn't find any of this mentionned.
May 05 2005
parent Vladimir <kv11111 mail.ru> writes:
Maxime Larose wrote:

 
 "Chris Sauls" <ibisbasenji gmail.com> wrote in message
 news:d5csgj$sha$1 digitaldaemon.com...
 Maxime Larose wrote:
 Then, how are arrays returned? Is't not safe to return a char[] from a
 function if it's allocated on the stack?!?
 I must have been messed up really good then, because as a GC'ed
 language
I
 assumed one was free to return a string (char[]) from a function. I
*think*
 I even already did it, but I may be mistaken (or I was just very luck
that
 the stack didn't get corrupted)...
Dynamic arrays (such as char[]) are on the heap, so may be freely returned. I assume that if one returns a static array (such as char[256]) then a copy would be made. Of course, you could define a function as returning a dynamic array, and still return the value of a static array. As I understand it, its data is copied to a new dynamic array, and a referance to the anonymous dynamic array is returned. -- Chris Sauls
Hmm.... The behavior for static arrays seems fairly innefficient... And what about: classA [1000] array; Then I guess the classes themselves are on the heap, but the array is not?
Yes. Array just contains references to classes.
 And if the array is returned, then it is copied to the heap.
Array can't be returned, only reference i.e. dynamic array. So actually reference to stack is return, and your program will crash.
 Or does the 
 compiler detects this case and immediately allocate the array on the heap?
Fixed-size arrays defined inside a function are always on stack.
 What's the best way to allocate a fixed-size array directly on the heap?
int[] array = new int[1000];
 
 Is this documented anywhere? I read the docs from cover to cover but it
 seems I missed a few things... I checked again in the sections that seem
 relevant and didn't find any of this mentionned.
-- Vladimir
May 05 2005
prev sibling next sibling parent reply Vladimir <kv11111 mail.ru> writes:
Chris Sauls wrote:

 Maxime Larose wrote:
 Then, how are arrays returned? Is't not safe to return a char[] from a
 function if it's allocated on the stack?!?
 I must have been messed up really good then, because as a GC'ed language
 I assumed one was free to return a string (char[]) from a function. I
 *think* I even already did it, but I may be mistaken (or I was just very
 luck that the stack didn't get corrupted)...
Dynamic arrays (such as char[]) are on the heap, so may be freely returned. I assume that if one returns a static array (such as char[256]) then a copy would be made.
Function can't return static arrays, only dynamic. Look at the following: int[] test() { int[10] x; x[0] = 10; return x; // Converting int[10] to int[] means getting reference of int, // so this function returns reference to array on the stack // which is error. } int main() { int[] u; u = test(); writefln(u[0]); // prints 10 int[100] g; writefln(u[0]); // prints garbage } May be compiler should produce a warning here.
 Of course, you could define a 
 function as returning a dynamic array, and still return the value of a
 static array.  As I understand it, its data is copied to a new dynamic
 array, and a referance to the anonymous dynamic array is returned.
 
 -- Chris Sauls
-- Vladimir
May 05 2005
parent reply Benji Smith <dlanguage xxagg.com> writes:
Vladimir wrote:

 int[] test()
 {
         int[10] x;
         x[0] = 10;
         return x;  // Converting int[10] to int[] means getting reference of
int,
                    // so this function returns reference to array on the stack
                    // which is error.
 }
 
 int main()
 {
         int[] u;
         u = test();
         writefln(u[0]); // prints 10
         int[100] g;
         writefln(u[0]); // prints garbage
 }
 
 May be compiler should produce a warning here.
That's insane. The compiler shouldn't issue a warning. And it shouldn't cause the program to crash. Or to print garbage. The compiler should be able to detect when a function returns a static array. In such cases, it should allocate the array on the heap instead of the stack. --BenjiSmith
May 05 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Benji Smith" <dlanguage xxagg.com> wrote in message 
news:d5dls4$1jat$2 digitaldaemon.com...
 Vladimir wrote:

 int[] test()
 {
         int[10] x;
         x[0] = 10;
         return x;  // Converting int[10] to int[] means getting reference 
 of int,
                    // so this function returns reference to array on the 
 stack
                    // which is error.
 }

 int main()
 {
         int[] u;
         u = test();
         writefln(u[0]); // prints 10
         int[100] g;
         writefln(u[0]); // prints garbage
 }

 May be compiler should produce a warning here.
That's insane. The compiler shouldn't issue a warning. And it shouldn't cause the program to crash. Or to print garbage. The compiler should be able to detect when a function returns a static array. In such cases, it should allocate the array on the heap instead of the stack. --BenjiSmith
The D spec http://www.digitalmars.com/d/function.html section Local Variables says its illegal to return the address of a local variable - which presumably should be expanded to include addresses of local static arrays. None of the errors in the Local Variables section are enforced by dmd.
May 05 2005
next sibling parent reply Benji Smith <dlanguage xxagg.com> writes:
Ben Hinkle wrote:
 The D spec http://www.digitalmars.com/d/function.html section Local 
 Variables says its illegal to return the address of a local variable - which 
 presumably should be expanded to include addresses of local static arrays. 
 None of the errors in the Local Variables section are enforced by dmd. 
So this code should produce an error? char[] getMyString() { char[6] myString = "string"; return myString; } I repeat: that's insane. --BenjiSmith
May 05 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Benji Smith" <dlanguage xxagg.com> wrote in message 
news:d5dnmt$1lfp$1 digitaldaemon.com...
 Ben Hinkle wrote:
 The D spec http://www.digitalmars.com/d/function.html section Local 
 Variables says its illegal to return the address of a local variable - 
 which presumably should be expanded to include addresses of local static 
 arrays. None of the errors in the Local Variables section are enforced by 
 dmd.
So this code should produce an error? char[] getMyString() { char[6] myString = "string"; return myString; }
yes - the initializer "string" is copied onto the stack space for myString. The "return myString" is independent of the inialization and it would behave exactly the same as if myString had been left in its initial state (filled with 0xFF's).
 I repeat: that's insane.
IYHO. It makes complete sense to me. I would be shocked if the compiler automatically allocated space on the heap and started copying data from the stack to the heap in order to avoid returning a stack object. In particular why stop at static arrays? Why not copy any pointer to a local variable to the heap and return that instead?
May 05 2005
parent reply Benji Smith <dlanguage xxagg.com> writes:
Ben Hinkle wrote:
 IYHO. It makes complete sense to me. I would be shocked if the compiler 
 automatically allocated space on the heap and started copying data from the 
 stack to the heap in order to avoid returning a stack object. In particular 
 why stop at static arrays? Why not copy any pointer to a local variable to 
 the heap and return that instead?
I don't think the compiler should *copy* data from the stack to the heap. I think--if I'm returning a variable from a function--the compiler should be smart enough to allocate it on the heap in the first place. And I don't think this is just a problem with static arrays. I think it's problem with any locally allocated variable. If I use the "return" keyword, the variable should be allocated on the heap. --BenjiSmith
May 05 2005
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Benji Smith wrote:
 Ben Hinkle wrote:
 
 IYHO. It makes complete sense to me. I would be shocked if the 
 compiler automatically allocated space on the heap and started copying 
 data from the stack to the heap in order to avoid returning a stack 
 object. In particular why stop at static arrays? Why not copy any 
 pointer to a local variable to the heap and return that instead?
I don't think the compiler should *copy* data from the stack to the heap. I think--if I'm returning a variable from a function--the compiler should be smart enough to allocate it on the heap in the first place. And I don't think this is just a problem with static arrays. I think it's problem with any locally allocated variable. If I use the "return" keyword, the variable should be allocated on the heap.
One problem here is that this will lead to inconsitent behavior of the language, or else great compiler complexity. What happens when somebody passes a pointer to a stack variable to a function, and then returns what the function returns? How is the compiler to know whether the function returns a pointer to the local variable, or something totally unrelated?
May 05 2005
prev sibling parent reply "Maxime Larose" <mlarose broadsoft.com> writes:
Hmmm..... No wonder I was messed up. All of this is *extremely* error-prone.
It should be either:
1) all arrays are allocated on the heap; or
2) compiler detects return of static array and issues an _error_ (and not a
warning); or
3) allocation of static array to dynamic automatically copies to the heap
(this is an inferior solution IMO because hidden things are happening under
the hood)

It suits my purposes just fine in this case (I want speed over (almost)
anything else), but honestly, as Benji puts it, it is insane...

Max



"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d5dmil$1kaa$1 digitaldaemon.com...
 "Benji Smith" <dlanguage xxagg.com> wrote in message
 news:d5dls4$1jat$2 digitaldaemon.com...
 Vladimir wrote:

 int[] test()
 {
         int[10] x;
         x[0] = 10;
         return x;  // Converting int[10] to int[] means getting
reference
 of int,
                    // so this function returns reference to array on
the
 stack
                    // which is error.
 }

 int main()
 {
         int[] u;
         u = test();
         writefln(u[0]); // prints 10
         int[100] g;
         writefln(u[0]); // prints garbage
 }

 May be compiler should produce a warning here.
That's insane. The compiler shouldn't issue a warning. And it shouldn't cause the
program
 to crash. Or to print garbage.

 The compiler should be able to detect when a function returns a static
 array. In such cases, it should allocate the array on the heap instead
of
 the stack.

 --BenjiSmith
The D spec http://www.digitalmars.com/d/function.html section Local Variables says its illegal to return the address of a local variable -
which
 presumably should be expanded to include addresses of local static arrays.
 None of the errors in the Local Variables section are enforced by dmd.
May 05 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <d5do0j$1lvt$1 digitaldaemon.com>, Maxime Larose says...
Hmmm..... No wonder I was messed up. All of this is *extremely* error-prone.
It should be either:
1) all arrays are allocated on the heap; or
Not desirable.
2) compiler detects return of static array and issues an _error_ (and not a
warning); or
This would be nice, but the C++ compilers I've used don't typically error here so I don't expect D to either. Perhaps it could at least try to warn though? (I wouldn't expect 100% accuracy)
3) allocation of static array to dynamic automatically copies to the heap
(this is an inferior solution IMO because hidden things are happening under
the hood)
Not desirable. Say I did this: void f(int[] x) {} void main() { int[100] a; f(a); } By your argument, a should be copied when f is called, while I clearly want it to be passed by reference. There's an easy fix for the sample code though: int[] test(){ int[10] x; x[0]=10; return x.dup; } This should create a dynamic copy of the static array. Sean
May 05 2005
next sibling parent "Maxime Larose" <mlarose broadsoft.com> writes:
(The problem here is solely with arrays. All other return values (ints,
bits, long, etc.) will be returned via a register - well, perhaps there is a
problem with 64-bits and 128-bits types afterall... On 32 bits machines at
least).

Anyway, the bottom line is that it is very easy to loose track of how the
array was constructed. There is no difference in syntax that would make it
easy to spot that a particular array was allocated on the stack and another
one not.

void someMethod(char [] string);

main {
char [1000] array1;
.... I'm doing stuff...
... for a long time, say 60+ lines...
someMethod(array1);   // will crash
}

The above call will crash, even if syntaxically everything is 100% kosher
(the call respect the caller's signature to the letter). Now, that's error
prone... (and don't tell me that methods shouldn't be 60 lines long, that's
not the point)

Your analogy to C++ doesn't really hold, because C++ isn't GC'ed. Yes, C++
will cut corners and take away convenience because its a stone age language.
In C++, you save 0.00005% of CPU time (which costs nothing) rather than
saving:
(the 3 seconds it takes _every time_ for the developper to check how the
array was constructed * how many times he has to check during the lifetime
of the system) + the hours it takes to debug the occasional core dump + all
the indirect costs if the core dump happened at a customer's site and/or on
a critical system.

A new language should eliminate such problems completely - or at least by
default. There is _absolutely_ no good reasons why arrays shouldn't be
created on the heap in D. However, easily allowing one to create arrays on
the stack shouldn't be prohibited. Deviating from the default, it would then
become the responsibility of the programmer to know what he is doing. Doing
it the other way around is backwards.

So, at the _very_ least, it should be a compiler error. No matter how C++
does it.

Max

BTW, a very interesting essay was written by Paul Graham about languages of
the future. The "hundred year language" if I remember correctly. Maybe you'd
like to check it out. It discusses convenience (for programmers) vs raw
speed. I don't fully agree with him in that I think there are still more
applications needing raw speed than he seems to think, but I believe he is
right about the overall tangent things will take.


"Sean Kelly" <sean f4.ca> wrote in message
news:d5dqh7$1ntc$1 digitaldaemon.com...
 In article <d5do0j$1lvt$1 digitaldaemon.com>, Maxime Larose says...
Hmmm..... No wonder I was messed up. All of this is *extremely*
error-prone.
It should be either:
1) all arrays are allocated on the heap; or
Not desirable.
2) compiler detects return of static array and issues an _error_ (and not
a
warning); or
This would be nice, but the C++ compilers I've used don't typically error
here
 so I don't expect D to either.  Perhaps it could at least try to warn
though? (I
 wouldn't expect 100% accuracy)

3) allocation of static array to dynamic automatically copies to the heap
(this is an inferior solution IMO because hidden things are happening
under
the hood)
Not desirable. Say I did this: void f(int[] x) {} void main() { int[100] a; f(a); } By your argument, a should be copied when f is called, while I clearly
want it
 to be passed by reference.

 There's an easy fix for the sample code though:

 int[] test(){
 int[10] x;
 x[0]=10;
 return x.dup;
 }

 This should create a dynamic copy of the static array.


 Sean
May 05 2005
prev sibling parent reply Benji Smith <dlanguage xxagg.com> writes:
Sean Kelly wrote:
 In article <d5do0j$1lvt$1 digitaldaemon.com>, Maxime Larose says...
1) all arrays are allocated on the heap; or
Not desirable.
Sean, would you mind elaborating on this a little bit? To me, it seems much more reasonable to allocate arrays on the heap (as the default behavior) and to only allocate them on the stack when specifically requested by the programmer through some sort of obviously-different syntax. If the "not desirable" response is primarily just because of a change in semantics from c/c++, then I don't think that's a reasonable argument. But if there's some other reason why heap-allocation wouldn't be a desirable default for arrays, please let me know. --Benji
May 05 2005
next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Benji Smith wrote:
 Sean Kelly wrote:
 
 In article <d5do0j$1lvt$1 digitaldaemon.com>, Maxime Larose says...

 1) all arrays are allocated on the heap; or
Not desirable.
Sean, would you mind elaborating on this a little bit? To me, it seems much more reasonable to allocate arrays on the heap (as the default behavior) and to only allocate them on the stack when specifically requested by the programmer through some sort of obviously-different syntax.
I think the thing that both you and Maxime are missing is the concept of dynamic arrays. You can think of a dynamic array variable as like this template struct: struct DynArray(T) { T *array; uint length; } Fixed length arrays, on the other hand, are just like C arrays. If you think about things this way, then it is very obvious why things work the way they do. char[10] a1; // the 10 bytes are literally on the stack char[] a2; // think of this like: DynArray!(char) a2; With dynamic arrays, the dynamic array *variable* is stored on the stack. But all that that variable contains is pointer and length data. The pointer doesn't point to anything until you initialize it. Then the stuff that it points to is on the heap. The rule is consistent: local function variables are stored on the stack. The difference between fixed-length and dynamic arrays is what constitutes the variable.
May 05 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
[snip]
 With dynamic arrays, the dynamic array *variable* is stored on the stack. 
 But all that that variable contains is pointer and length data. The 
 pointer doesn't point to anything until you initialize it.  Then the stuff 
 that it points to is on the heap.
umm - a dyanmic array can point to the stack. That's what happens with char[10] x; char[] y = x; There is no heap allocation going on there. If you try to resize y by doing something like y.length = 20; then since the stack space doesn't have the capacity a new pointer to 20 chars will be allocated from the heap and y's pointer will then indeed point to the heap.
 The rule is consistent: local function variables are stored on the stack. 
 The difference between fixed-length and dynamic arrays is what constitutes 
 the variable. 
May 05 2005
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Ben Hinkle wrote:
 [snip]
 
With dynamic arrays, the dynamic array *variable* is stored on the stack. 
But all that that variable contains is pointer and length data. The 
pointer doesn't point to anything until you initialize it.  Then the stuff 
that it points to is on the heap.
umm - a dyanmic array can point to the stack. That's what happens with
True, of course. I was being overliy simplistic :/
May 05 2005
prev sibling parent Sean Kelly <sean f4.ca> writes:
In article <d5dtim$1qhn$1 digitaldaemon.com>, Benji Smith says...
Sean Kelly wrote:
 In article <d5do0j$1lvt$1 digitaldaemon.com>, Maxime Larose says...
1) all arrays are allocated on the heap; or
Not desirable.
Sean, would you mind elaborating on this a little bit? To me, it seems much more reasonable to allocate arrays on the heap (as the default behavior) and to only allocate them on the stack when specifically requested by the programmer through some sort of obviously-different syntax. If the "not desirable" response is primarily just because of a change in semantics from c/c++, then I don't think that's a reasonable argument. But if there's some other reason why heap-allocation wouldn't be a desirable default for arrays, please let me know.
Perhaps it's because I'm so accustomed to C++, but I don't see any reason to pay for a heap allocation if I don't need to. If I'm using a fixed-size array that doesn't need to be passed out of scope then why not put it on the stack? To me, the syntax clearly differentiates between the two declaration types so I see little risk of a mistake. Here are both versions for comparison: int[1000] a; // 1000 int array on the stack int[] b = new int[1000]; // 1000 int array on the heap int[] c; c.length = 1000; // also a 1000 int array on the heap Returning a reference to stack data is a mistake I've personally never made (probably because I've had it drummed into me since day 1 that this is a Bad Thing), so I can't comment on the potential increase in safety that defaulting to heap allocations would provide. I'll grant that heap allocations in a good GC language can be exceedingly fast, but then that's just more stuff to clean up later on. Sean
May 05 2005
prev sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Chris Sauls wrote:
 Dynamic arrays (such as char[]) are on the heap, so may be freely 
 returned.  I assume that if one returns a static array (such as 
 char[256]) then a copy would be made.  Of course, you could define a 
 function as returning a dynamic array, and still return the value of a 
 static array.  As I understand it, its data is copied to a new dynamic 
 array, and a referance to the anonymous dynamic array is returned.
This is not correct. If you assign a static array to a dynamic array variable, then you get a dynamic array which points to the same memory as the static array. However, you can dup the array: char[1000] static_array; return static_array.dup; 'dup' copies the array to a new location. This, of course, must be on the heap.
May 05 2005