February 05, 2013
On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote:
> On 05/02/2013 16:17, Nick Treleaven wrote:
>> On 03/02/2013 13:22, bearophile wrote:
>>> Era Scarecrow:
>>>
>>>> On Sunday, 3 February 2013 at 09:11:59 UTC, Namespace wrote:
>>>>> Sure, but alloca has the same ugly interface as malloc. :/
>>>>
>>>> You mean that you have to specify how many raw bytes you want, then
>>>> cast it to what you need? I never thought alloca or malloc were that
>>>> ugly.
>>>
>>> The interface of alloca() is bug-prone. And it's not handy if you want
>>> to create a 2D or nD array on the stack :-) In bugzilla there is a
>>> preliminary request for better and less bug-prone VLAs for D.
>>
>> ^ I know you're aware of this, but maybe others might not know the
>> default-argument alloca wrapping trick:
>
> I've just realized this doesn't work for variable-length allocation:
>
> T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N))
>
> Error: undefined identifier N, did you mean alias T?
>
> N is not visible in the caller's scope.

It does, just alias it.

//----
import std.stdio;
import core.stdc.stdlib:alloca;

T* stack(T)(void* m = alloca(T.sizeof))
{
    return cast(T*)m;
}
T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
{
    return (cast(T*)m)[0 .. N];
}

void main(string[] args)
{
    int*  p   = stack!int();
    int[] arr = stack!(int, 5)();
    *p = 2;
    arr[0] = 5;
    writeln(*p);
    writeln(arr);
}
//----
February 05, 2013
Why not:
[code]
T[] stack(T, const size_t N)(void* m = alloca(T.sizeof * N))
{
    return (cast(T*)m)[0 .. N];
}
[/code]
?
February 05, 2013
On 05/02/2013 16:47, monarch_dodra wrote:
> On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote:
>> I've just realized this doesn't work for variable-length allocation:
>>
>> T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N))
>>
>> Error: undefined identifier N, did you mean alias T?
>>
>> N is not visible in the caller's scope.
>
> It does, just alias it.
>
> //----
> import std.stdio;
> import core.stdc.stdlib:alloca;
>
> T* stack(T)(void* m = alloca(T.sizeof))
> {
>      return cast(T*)m;
> }
> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
> {
>      return (cast(T*)m)[0 .. N];
> }

This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.:

// allocate as many ints as command-line parameters
int[] arr = stack!int(args.length);
February 05, 2013
On Tuesday, 5 February 2013 at 20:47:46 UTC, Nick Treleaven wrote:
> On 05/02/2013 16:47, monarch_dodra wrote:
>> On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote:
>>> I've just realized this doesn't work for variable-length allocation:
>>>
>>> T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N))
>>>
>>> Error: undefined identifier N, did you mean alias T?
>>>
>>> N is not visible in the caller's scope.
>>
>> It does, just alias it.
>>
>> //----
>> import std.stdio;
>> import core.stdc.stdlib:alloca;
>>
>> T* stack(T)(void* m = alloca(T.sizeof))
>> {
>>     return cast(T*)m;
>> }
>> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
>> {
>>     return (cast(T*)m)[0 .. N];
>> }
>
> This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.:
>
> // allocate as many ints as command-line parameters
> int[] arr = stack!int(args.length);

I don't have access to my compiler, but that *should*work. Did you try it? BTW, the syntax would be:

int[] arr = stack!(int, args.length)();
February 05, 2013
On 05/02/2013 21:02, monarch_dodra wrote:
> On Tuesday, 5 February 2013 at 20:47:46 UTC, Nick Treleaven wrote:
>> On 05/02/2013 16:47, monarch_dodra wrote:
>>> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
>>> {
>>>     return (cast(T*)m)[0 .. N];
>>> }
>>
>> This works if you know N at compile-time. But there doesn't seem to be
>> a way to wrap alloca to accept a runtime-only value, e.g.:
>>
>> // allocate as many ints as command-line parameters
>> int[] arr = stack!int(args.length);
>
> I don't have access to my compiler, but that *should*work. Did you try
> it? BTW, the syntax would be:
>
> int[] arr = stack!(int, args.length)();

I've just tried it with dmd 2.059 (haven't upgraded yet). I got:

Error: variable args cannot be read at compile time

void main(string[] args)
{
    int[] arr = stack!(int, args.length)();
}
February 05, 2013
On 05/02/2013 21:13, Nick Treleaven wrote:
> I've just tried it with dmd 2.059 (haven't upgraded yet)

sorry, 2.060
February 05, 2013
On Tuesday, 5 February 2013 at 21:14:32 UTC, Nick Treleaven wrote:
> On 05/02/2013 21:13, Nick Treleaven wrote:
>> I've just tried it with dmd 2.059 (haven't upgraded yet)
>
> sorry, 2.060

Right, it's "alias" being finicky, because "args.length" isn't an actual variable (it's a property). The problem is not so much that it can't be "read" at compile time, that the compiler doesn't know what to alias to.

I'll file a bug report to try and see if we can't get a better message.

Use a named variable, or use a manifest constant:

//----
import std.stdio;
import core.stdc.stdlib:alloca;

T* stack(T)(void* m = alloca(T.sizeof))
{
    return cast(T*)m;
}
T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
{
    return (cast(T*)m)[0 .. N];
}

void main(string[] args)
{
    auto n = args.length;
    int[] arr = stack!(int, n)();
}
//----
February 06, 2013
On 05/02/2013 22:15, monarch_dodra wrote:
> On Tuesday, 5 February 2013 at 21:14:32 UTC, Nick Treleaven wrote:
>> On 05/02/2013 21:13, Nick Treleaven wrote:
>>> I've just tried it with dmd 2.059 (haven't upgraded yet)
>>
>> sorry, 2.060
>
> Right, it's "alias" being finicky, because "args.length" isn't an actual
> variable (it's a property). The problem is not so much that it can't be
> "read" at compile time, that the compiler doesn't know what to alias to.
>
> I'll file a bug report to try and see if we can't get a better message.

OK, please post the link if/when you file it.

> Use a named variable, or use a manifest constant:

This works, thanks.

> //----
> import std.stdio;
> import core.stdc.stdlib:alloca;
>
> T* stack(T)(void* m = alloca(T.sizeof))
> {
>      return cast(T*)m;
> }
> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
> {
>      return (cast(T*)m)[0 .. N];
> }
>
> void main(string[] args)
> {
>      auto n = args.length;
>      int[] arr = stack!(int, n)();
> }
> //----

February 06, 2013
On 05/02/2013 16:39, bearophile wrote:
> Nick Treleaven:
>
>> ^ I know you're aware of this, but maybe others might not know the
>> default-argument alloca wrapping trick:
>
> For some usages it's an improvement over raw usage of alloca.
> I did see this in past, but sometimes I forget.

Sorry if I sounded critical, I didn't mean to ;-)
1 2 3 4
Next ›   Last »