Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Mathias LANG via Digitalmars-d-learn

On Monday, 16 August 2021 at 05:36:07 UTC, Tejas wrote:


That is why I was using heapAllocate, because using `new` on 
scope allocates exception on stack, and if you exit, then the 
exception is basically freed before it even gets caught. It 
fails even when you catch within the same function.


But allocate on heap and giving ownership to a `scope` 
qualified variable is no problem at all. No `signal 11` killing 
my process ^_^


You are relying on an accept-invalid though. The compiler *should 
not* accept that code, but currently erroneously does so.


Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Tejas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 20:23:03 UTC, Paul Backus wrote:

On Sunday, 15 August 2021 at 18:47:27 UTC, Tejas wrote:
Do you see anything wrong with the following 
`emplace`-allocated, RAII following exceptions:


[...]

Is this good enough for general use now? Any other drawbacks?


It only works if you're throwing and catching in the same 
function. Otherwise you are essentially returning a pointer to 
an expired stack frame, which is UB.


Guess I should've verified before accepting this as true.

```d

import std;
import core.lifetime:emplace;
import core.stdc.stdlib:malloc;

T heapAllocate(T, Args...)(Args args)@nogc{
auto size = __traits(classInstanceSize, T);
auto memory = malloc(size)[0 .. size];
auto instance = emplace!(T,Args)(memory, args);
return instance;
}

void throws()@nogc{
scope a = heapAllocate!(Exception)("works fine with scope, 
apparently");

throw a;
}


void main()@nogc
{
try{
throws();
} catch(Exception exp){
printf("%s", cast(char*)exp.msg);
}
}
```


That is why I was using heapAllocate, because using `new` on 
scope allocates exception on stack, and if you exit, then the 
exception is basically freed before it even gets caught. It fails 
even when you catch within the same function.


But allocate on heap and giving ownership to a `scope` qualified 
variable is no problem at all. No `signal 11` killing my process 
^_^


Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread Tejas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc wrote:

Greetings,

I have been trying to get a working example of slice assignment 
operator
overloading ... and am befuddled.  From the spec (section 
20.6.2), the

code below appears:

struct A
{
int opIndexAssign(int v);  // overloads a[] = v
int opIndexAssign(int v, size_t[2] x);  // overloads 
a[i .. j] = v
int[2] opSlice(size_t x, size_t y); // overloads i 
.. j

}

void test()
{
A a;
int v;

a[] = v;  // same as a.opIndexAssign(v);
a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

}

I have hacked at this trying to get a simple working example.  
Could

anyone guide me here please?

Best Regards,
James


If you're finding the spec too hard, please try Ali's book. I'm 
sharing the part on operator overloading below:


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

Please ping if you still have problems; I'll then write a full 
program.




Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Paul Backus via Digitalmars-d-learn

On Monday, 16 August 2021 at 02:26:04 UTC, Tejas wrote:


 Agh >_<

if I remove the `scope`and replace it with `auto`?
No longer having anything to do with the stack or RAII, just 
using malloc + emplace instead of GC?


Yeah it might leak memory unless the catch block explicitly 
frees the exception object, but other than that?


Yeah, other than needing to manually free the exception it should 
be fine.


Though at that point, you might just be better off using 
statically-allocated exceptions.


Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Tejas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 20:23:03 UTC, Paul Backus wrote:

On Sunday, 15 August 2021 at 18:47:27 UTC, Tejas wrote:
Do you see anything wrong with the following 
`emplace`-allocated, RAII following exceptions:


[...]

Is this good enough for general use now? Any other drawbacks?


It only works if you're throwing and catching in the same 
function. Otherwise you are essentially returning a pointer to 
an expired stack frame, which is UB.


 Agh >_<

if I remove the `scope`and replace it with `auto`?
No longer having anything to do with the stack or RAII, just 
using malloc + emplace instead of GC?


Yeah it might leak memory unless the catch block explicitly frees 
the exception object, but other than that?


Re: Anyway to achieve the following

2021-08-15 Thread Carl Sturtivant via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:10:17 UTC, JG wrote:

Hi,

This is exactly the behaviour I was trying to obtain.

It however comes with a fair amount of overhead, as can be seen 
in the following llvm ir:


[...]


What you are asking for are reference variables. C++ has them: 
the example here illustrates the behavior you want.

https://www.geeksforgeeks.org/references-in-c/

D does not have them, as mentioned above:
https://forum.dlang.org/post/mailman.2714.1628875187.3446.digitalmars-d-le...@puremagic.com

So to get the behavior you want, they have to be simulated, which 
is what this does:

https://forum.dlang.org/post/lcrrnszslpyazoziy...@forum.dlang.org

Next version: no `toString` and storage passed in by reference 
rather than by pointer.


```
struct S {
  int x = 1234;
}

void main() {
  import std.stdio;
   S s;
   auto p = 
   //construction of a using &(s.x)
   auto a = Ref!(int)(*p);
   //auto a = Ref!(int)(s.x);
   writeln(a); //displays 1234
   s.x += 1;
   writeln(a); //displays 1235
   a += 1;
   writeln(s.x); //displays 1236
}

struct Ref(T)
{
  T* ptr;
  this(ref T x) { ptr =  }
  @property ref T var() { return *ptr; }
  alias var this;
}
```

I see no way to avoid overhead, as I see no simpler simulation.



Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 15 August 2021 at 21:28:53 UTC, james.p.leblanc wrote:

On Sunday, 15 August 2021 at 21:15:02 UTC, Bastiaan Veelo wrote:

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc



— Bastiaan.


Bastiaan,


Thanks once again,
James


On Sunday, 15 August 2021 at 21:28:53 UTC, james.p.leblanc wrote:


Okay!  Great!  Thanks everyone Bastiaan, ag0aep6g, and russhy  ...
I see more replies come in while I was typing.

There is some excellent information here that I
need to digest.  I believe that I have what I need.

This group has been great!

BR,
James


Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

On Sunday, 15 August 2021 at 21:15:02 UTC, Bastiaan Veelo wrote:

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc



— Bastiaan.


Bastiaan,

Thanks kindly for your response!

Unfortunately, I do not see what the program does.  I mean A is a 
structure
that has only functions.  So, how are any elements of this being 
set to

the value of v?

I tried extending the code mentioned by adding a member array, 
but no

luck.

I often have difficulties to understand the notations used in the 
spec,

and only sometimes can I extend them to working examples.

Would it be possible to add the last couple of details regarding
an array member?  I attempted but the values always remain zero
even when I set v=4.


import std;

struct A
{
   int[5] a;
   int opIndexAssign(int v) // overloads a[] = v
   {
  writeln(__FUNCTION__);
  return 42;
   }
   int opIndexAssign(int vh, size_t[2] x)  // overloads a[i 
.. j] = v

   {
  writeln(__FUNCTION__);
  return 43;
   }
   int[2] opSlice(size_t x, size_t y) // overloads i .. j
   {
  writeln(__FUNCTION__);
  return [44, 45];
   }
}

void main()
{
   A a;
   int v=4;
   writeln(a);

   a[] = v;  // same as a.opIndexAssign(v);
   writeln(a);
   a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

   writeln(a);
}


Thanks once again,
James














Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread russhy via Digitalmars-d-learn

There is an example here:

http://www.rosettacode.org/wiki/Multi-dimensional_array#D

Look at the Matrix struct


Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread ag0aep6g via Digitalmars-d-learn

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc wrote:
I have been trying to get a working example of slice assignment 
operator
overloading ... and am befuddled.  From the spec (section 
20.6.2), the

code below appears:

struct A
{
int opIndexAssign(int v);  // overloads a[] = v
int opIndexAssign(int v, size_t[2] x);  // overloads 
a[i .. j] = v
int[2] opSlice(size_t x, size_t y); // overloads i 
.. j

}

void test()
{
A a;
int v;

a[] = v;  // same as a.opIndexAssign(v);
a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

}


I have no experience with this, but from a cursory look it seems 
that that example is wrong.


For starters, the type of `opIndexAssign`'s second parameter must 
match the return type of `opSlice`. This is easily fixed, but the 
code still doesn't work.


Further down on the spec page [1], there is this little table:

| op| rewrite 
 |

|---|--|
| `arr[1, 2..3, 4] = c` | `arr.opIndexAssign(c, 1, 
arr.opSlice!1(2, 3), 4)`|
| `arr[2, 3..4] += c`   | `arr.opIndexOpAssign!"+"(c, 2, 
arr.opSlice!1(2, 3))` |


Note the `!1` on `opSlice`. So you need to make `opSlice` a 
template with an integer parameter.


Working example:

```d
import std.stdio;

struct A
{
int opIndexAssign(int v, size_t[2] x)
{
writeln("opIndexAssign: ", v, ", ", x);
return v;
}
size_t[2] opSlice(size_t i)(size_t x, size_t y)
{
return [x, y];
}
}

void main()
{
A a;
int v = 42;
a[3..4] = v; /* Prints "opIndexAssign: 42, [3, 4]". */
}
```


[1] https://dlang.org/spec/operatoroverloading.html#slice


Re: Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread Bastiaan Veelo via Digitalmars-d-learn

On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc wrote:

struct A
{
int opIndexAssign(int v);  // overloads a[] = v
int opIndexAssign(int v, size_t[2] x);  // overloads 
a[i .. j] = v
int[2] opSlice(size_t x, size_t y); // overloads i 
.. j

}

void test()
{
A a;
int v;

a[] = v;  // same as a.opIndexAssign(v);
a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

}

I have hacked at this trying to get a simple working example.


Not sure if this does enough of what you’re looking for, but this 
covers the minimal steps to get it working: 
https://run.dlang.io/is/m5svQ2


```d

import std;

struct A
{
int opIndexAssign(int v) // overloads a[] = v
{
writeln(__FUNCTION__);
return 42;
}
int opIndexAssign(int vh, size_t[2] x)  // overloads a[i .. 
j] = v

{
writeln(__FUNCTION__);
return 43;
}
int[2] opSlice(size_t x, size_t y) // overloads i .. j
{
writeln(__FUNCTION__);
return [44, 45];
}
}

void main()
{
A a;
int v;

a[] = v;  // same as a.opIndexAssign(v);
a[3..4] = v;  // same as a.opIndexAssign(v, a.opSlice(3,4));
}
```

— Bastiaan.




Getting a working example of opIndexAssign using opSlice ... have troubles ...

2021-08-15 Thread james.p.leblanc via Digitalmars-d-learn

Greetings,

I have been trying to get a working example of slice assignment 
operator
overloading ... and am befuddled.  From the spec (section 
20.6.2), the

code below appears:

struct A
{
int opIndexAssign(int v);  // overloads a[] = v
int opIndexAssign(int v, size_t[2] x);  // overloads a[i 
.. j] = v
int[2] opSlice(size_t x, size_t y); // overloads i .. 
j

}

void test()
{
A a;
int v;

a[] = v;  // same as a.opIndexAssign(v);
a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));

}

I have hacked at this trying to get a simple working example.  
Could

anyone guide me here please?

Best Regards,
James



Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 15 August 2021 at 18:47:27 UTC, Tejas wrote:
Do you see anything wrong with the following 
`emplace`-allocated, RAII following exceptions:


[...]

Is this good enough for general use now? Any other drawbacks?


It only works if you're throwing and catching in the same 
function. Otherwise you are essentially returning a pointer to an 
expired stack frame, which is UB.


Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Tejas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 16:23:25 UTC, Ali Çehreli wrote:

On 8/15/21 2:10 AM, Alexandru Ermicioi wrote:

>> This may be useful in some cases but in general, these
colatteral
>> exceptions don't carry much information and I don't think
anybody
>> looks at them. Usually, the first one is the one that
explains the
>> error case.

> That is just an assumption.

Agreed but it's based on hands-on experience as well as 
exposure to these forums. :)


> There could be designs where original
> exception gets wrapped in another one

Wrapping is different and yes, it is useful. There have been 
cases where I hit a ConvException which only tells me a 
conversion failed. I do catch and augment it in outer contexts 
to saying something similar ot "That happened while doing this".


> Regarding exception chaining, do you mean that it will
automatically get
> chained, even without explicitly passing it as constructor of
wrapping
> exception?

Yes. That's the functionality which isn't very useful because 
the collateral exceptions are usually because of the main one: 
Imagine the file system is full and a destructor cannot flush a 
file. The destructor's error is not interesting in this case.


class Main : Exception {
  this() {
super("Main failed");
  }
}

class Dtor : Exception {
  this() {
super("The destructor failed");
  }
}

struct S {
  ~this() {
throw new Dtor();
  }
}

import std.stdio;

void main() {
  try {
auto s = S();
throw new Main();

  } catch (Exception exc) {
stderr.writeln("Failed: ", exc.msg);
stderr.writeln("This failed too: ", exc.next.msg);
// (Of course, real code should stop when 'next' is null.)
  }
}

That output contains two automatically chained exceptions:

Failed: Main failed
This failed too: The destructor failed

Ali


Do you see anything wrong with the following `emplace`-allocated, 
RAII following exceptions:


```d
import std;
import core.stdc.stdlib;

class Main : Exception {
  this() @nogc{
super("Main Failed");
  }
}

class Dtor : Exception {
  this() @nogc{
super("The destructor failed");
  }
}

T heapAllocate(T, Args...)(Args args)@nogc{
auto size = __traits(classInstanceSize, T);
auto memory = malloc(size)[0 .. size];
auto instance = emplace!(T,Args)(memory, args);
return instance;
}

struct S {
  ~this()@nogc {
scope a = heapAllocate!Dtor();
throw a;
  }
}

void main() @nogc{
  try {
auto s = S();
scope a = heapAllocate!Main();
throw a;

  } catch (Exception exc) {
printf("Failed: %s\n", cast(char*)exc.msg);
printf("This failed too: %s\n", cast(char*)exc.next.msg);
// (Of course, real code should stop when 'next' is null.)
  }
}

```

Is this good enough for general use now? Any other drawbacks?


Re: partial initialization of fixed size ("static") arrays

2021-08-15 Thread kdevel via Digitalmars-d-learn

On Saturday, 14 August 2021 at 23:09:14 UTC, Paul Backus wrote:

On Saturday, 14 August 2021 at 14:04:47 UTC, kdevel wrote:

~~~
   char [7] d7 = "x"; // okay

   string s = "x";
   char [7] c7 = s; // throws RangeError
~~~

What justifies that the compiler behaves differently on two 
terms ('s', '"x"') which are of equal size, type, length and 
value?


Literals in D can have different types in different contexts. 
For example:


```d
byte b = 16; // 16 is treated as a byte literal
int n = 16; // 16 is treated as an int literal
b = n; // Error: cannot convert int to byte
```


The wording of the error message

~~~d
void main () // bi.d
{
   byte b = 257;
}

$ dmd bi.d
bi.d(3): Error: cannot implicitly convert expression `257` of 
type `int` to `byte`

~~~

does not seem to support your interpretation. The term `257` does 
not encode a ‘polymorphic’ entity but the int value 257 which is 
used to initialize a variable. If necessary, the value is 
converted. The literal is not “typeless” as in Go [1] either.


Similarly, the string literal `"x"` can be treated either as a 
`string` (a dynamic array of `immutable(char)`) or as a static 
array of `char`, depending on the type of variable it's 
assigned to.


[1] https://blog.golang.org/constants


Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Alexandru Ermicioi via Digitalmars-d-learn

On Sunday, 15 August 2021 at 16:23:25 UTC, Ali Çehreli wrote:

That output contains two automatically chained exceptions:

Failed: Main failed
This failed too: The destructor failed

Ali


Hmm, wasn't aware of such use case (results of too much java :)). 
Considering this case I'd say it is better to keep it, because 
having more info than less is better for debugging. Even in your 
example, you already catch an use case that wasn't accounted for, 
that may or may not require fixing, i.e. it is better to know it 
then be in blissfull unawareness.


Though it is annoying to view those chained stacks, since they 
have repetitions. It would be nice if stack traces of nested 
exceptions would just show lines up to next exception thrown 
similar to how java does.


Regards,
Alexandru


Re: Anyway to achieve the following

2021-08-15 Thread Johan via Digitalmars-d-learn

On Sunday, 15 August 2021 at 16:49:22 UTC, Paul Backus wrote:

On Sunday, 15 August 2021 at 07:10:17 UTC, JG wrote:


Hi,

This is exactly the behaviour I was trying to obtain.

It however comes with a fair amount of overhead, as can be 
seen in the following llvm ir:


[...]


I'm not really familiar with llvm ir, but looking at it on 
godbolt, it seems like the main difference is that taking the 
address of `s.x` forces the compiler to place `s` in memory, 
rather than keeping it entirely in registers:


https://d.godbolt.org/z/1afbsM6fv


The function `std.stdio.writeln!(example.Ref!(int))` is not 
trivial. I doubt there is a reasonable 
optimization/transformation path from a call to 
`std.stdio.writeln!(example.Ref!(int))` to a call to 
`std.stdio.writeln!(int).writeln(int)`.
Without being able to simplify it to that call, `s` has to be put 
in memory. It's the opaqueness of 
`std.stdio.writeln!(example.Ref!(int))` and that it (must) takes 
the address of `s.x` as parameter.


-Johan



Re: Anyway to achieve the following

2021-08-15 Thread Paul Backus via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:10:17 UTC, JG wrote:


Hi,

This is exactly the behaviour I was trying to obtain.

It however comes with a fair amount of overhead, as can be seen 
in the following llvm ir:


[...]


I'm not really familiar with llvm ir, but looking at it on 
godbolt, it seems like the main difference is that taking the 
address of `s.x` forces the compiler to place `s` in memory, 
rather than keeping it entirely in registers:


https://d.godbolt.org/z/1afbsM6fv


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread Steven Schveighoffer via Digitalmars-d-learn

On 8/15/21 2:10 AM, rempas wrote:

So when I'm doing something like the following: `string name = "John";`
Then what's the actual type of the literal `"John"`?
In the chapter [Calling C 
functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) 
in the "Interfacing with C" page, the following is said:
Strings are not 0 terminated in D. See "Data Type Compatibility" for 
more information about this. However, string literals in D are 0 
terminated.


Which is really interesting and makes me suppose that `"John"` is a 
string literal right?
However, when I'm writing something like the following: `char *name = 
"John";`,

then D will complain with the following message:
Error: cannot implicitly convert expression `"John"` of type `string` 
to `char*`


Which is interesting because this works in C. If I use `const char*` 
instead, it will work. I suppose that this has to do with the fact that 
`string` is an alias for `immutable(char[])` but still this has to mean 
that the actual type of a LITERAL string is of type `string` (aka 
`immutable(char[])`).


Another thing I can do is cast the literal to a `char*` but I'm 
wondering what's going on under the hood in this case. Is casting 
executed at compile time or at runtime? So am I going to have an extra 
runtime cost having to first construct a `string` and then ALSO cast it 
to a string literal?


I hope all that makes sense and the someone can answer, lol


Lots of great responses in this thread!

I wanted to stress that a string literal is sort of magic. It has extra 
type information inside the compiler that is not available in the normal 
type system. Namely that "this is a literal, and so can morph into other 
things".


To give you some examples:

```d
string s = "John";
immutable(char)* cs = s; // nope
immutable(char)* cs2 = "John"; // OK!
wstring ws = s; // nope
wstring ws2 = "John"; // OK!
```

What is going on? Because the compiler knows this is a string *literal*, 
it can modify the type (and possibly the data itself) at will to match 
what you are assigning it to. In the case of zero-terminated C strings, 
it allows usage as a pointer instead of a D array. In the case of 
different width strings (wstring uses 16-bit code-units), it can 
actually transform the underlying data to what you wanted.


Note that even when you do lose that "literal" magic by assigning to a 
variable, you can still rely on D always putting a terminating zero in 
the data segment for a string literal. So it's valid to just do:


```d
string s = "John";
printf(s.ptr);


As long as you *know* the string came from a literal.

-Steve


Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Ali Çehreli via Digitalmars-d-learn

On 8/15/21 2:10 AM, Alexandru Ermicioi wrote:

>> This may be useful in some cases but in general, these colatteral
>> exceptions don't carry much information and I don't think anybody
>> looks at them. Usually, the first one is the one that explains the
>> error case.

> That is just an assumption.

Agreed but it's based on hands-on experience as well as exposure to 
these forums. :)


> There could be designs where original
> exception gets wrapped in another one

Wrapping is different and yes, it is useful. There have been cases where 
I hit a ConvException which only tells me a conversion failed. I do 
catch and augment it in outer contexts to saying something similar ot 
"That happened while doing this".


> Regarding exception chaining, do you mean that it will automatically get
> chained, even without explicitly passing it as constructor of wrapping
> exception?

Yes. That's the functionality which isn't very useful because the 
collateral exceptions are usually because of the main one: Imagine the 
file system is full and a destructor cannot flush a file. The 
destructor's error is not interesting in this case.


class Main : Exception {
  this() {
super("Main failed");
  }
}

class Dtor : Exception {
  this() {
super("The destructor failed");
  }
}

struct S {
  ~this() {
throw new Dtor();
  }
}

import std.stdio;

void main() {
  try {
auto s = S();
throw new Main();

  } catch (Exception exc) {
stderr.writeln("Failed: ", exc.msg);
stderr.writeln("This failed too: ", exc.next.msg);
// (Of course, real code should stop when 'next' is null.)
  }
}

That output contains two automatically chained exceptions:

Failed: Main failed
This failed too: The destructor failed

Ali



Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread Ali Çehreli via Digitalmars-d-learn
Lot's of great information and pointers already. I will try from another 
angle. :)


On 8/14/21 11:10 PM, rempas wrote:

> So when I'm doing something like the following: `string name = "John";`
> Then what's the actual type of the literal `"John"`?

As you say and as the code shows, there are two constructs in that line. 
The right-hand side is a string literal. The left-hand side is a 'string'.


>> Strings are not 0 terminated in D. See "Data Type Compatibility" for
>> more information about this. However, string literals in D are 0
>> terminated.

The string literal is embedded into the compiled program as 5 bytes in 
this case: 'J', 'o', 'h', 'n', '\0'. That's the right-hand side of your 
code above.


'string' is an array in D and arrays are stored as the following pair:

  size_t length;// The number of elements
  T * ptr;  // The pointer to the first element

(This is called a "fat pointer".)

So, if we assume that the literal 'John' was placed at memory location 
0x1000, then the left-hand side of your code will satisfy the following 
conditions:


  assert(name.length == 4);// <-- NOT 5
  assert(name.ptr == 0x1000);

The important part to note is how even though the string literal was 
stored as 5 bytes but the string's length is 4.


As others said, when we add a character to a string, there is no '\0' 
involved. Only the newly added char will the added.


Functions in D do not need the '\0' sentinel to know where the string 
ends. The end is already known from the 'length' property.


Ali



Re: how to import .lib library

2021-08-15 Thread Marcone via Digitalmars-d-learn

On Sunday, 15 August 2021 at 10:12:17 UTC, Timofeyka wrote:

Thank you for your reply!
I wanted to link to my project another project without source 
code.


This tutorial can help you create yours libs: 
https://wiki.dlang.org/Win32_DLLs_in_D


Re: how to import .lib library

2021-08-15 Thread Marcone via Digitalmars-d-learn

On Sunday, 15 August 2021 at 09:49:39 UTC, Timofeyka wrote:

Hello!
I may have a very stupid question, but still.
How do I include a .lib library? How to use it in your code?


Inside the source code you can use pragma. Example:

pragma(lib, "gdi32.lib");

In DMD command line you can use -L flag that pass the lib to 
linker. Example:


dmd -Lgdi32.lib mycode.d


Re: how to import .lib library

2021-08-15 Thread Mike Parker via Digitalmars-d-learn

On Sunday, 15 August 2021 at 10:40:36 UTC, jfondren wrote:



Yeah, that's not possible. You either need the source or a set 
of D interface files that declares all the symbols you need.


Meaning, it is possible. On Windows where I assume these .lib 
files are:


I mentioned C libraries in an earlier post. But the OP did not 
say whether the library is a C library or a D one. If it's a D 
library, then you can't simply declare the functions locally 
because the module name is part of the fully-qualifed name. You 
absolutely need the source or the interface files.


Declaring C functions locally where you need them is fine if you 
only need a handful of sybmols. But when you need multiple 
functions and types from the API, that's going to get unwieldy.


Re: how to import .lib library

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 10:19:33 UTC, Mike Parker wrote:

On Sunday, 15 August 2021 at 10:12:17 UTC, Timofeyka wrote:


Thank you for your reply!
I wanted to link to my project another project without source 
code.


Yeah, that's not possible. You either need the source or a set 
of D interface files that declares all the symbols you need.


Meaning, it is possible. On Windows where I assume these .lib 
files are:


```
PS C:\Users\jfond> cat math.d
extern(C) int twice(int n) { return n * 2; }

PS C:\Users\jfond> cat mathuser.d
extern (C) int twice(int n);

void main() {
import std.stdio : writeln;

writeln(twice(21));
}

PS C:\Users\jfond> ldc2 -lib math.d
PS C:\Users\jfond> ldc2 mathuser.d math.lib
PS C:\Users\jfond> ./mathuser
42
```

math.lib is written in D but it could've been written just as 
well in C or C++ or anything, as long as it's targeting the C ABI 
in whatever language.


When mathuser.d is compiled, D does not need the source for 
math.lib. That one extern(C) function without a body is 
sufficient to, again targeting the C ABI, say "I am expecting to 
be linked with a function like this", and math.lib supplies that 
function at link time.


D is identical to pretty much every other native-compiled 
language in this respect.


The question you probably want to be asking is, "given a specific 
library from this vendor, what's the most *convenient* way to 
link D against it", or "how should I tell dub to link this D 
application with a .lib file in a parent directory", etc.




Re: Nondeterministic unittest debugging problem.

2021-08-15 Thread Rekel via Digitalmars-d-learn
Note you might need to open the screenshots externally, as they 
are cut off by the forum.


Nondeterministic unittest debugging problem.

2021-08-15 Thread Rekel via Digitalmars-d-learn
I am unsure where to mention this as I am utterly lost as to what 
the issue is, which I can simply best describe with 2 
screenshots. Though I'll first give a short description.


For some reason my debugger is "\" for 
one of my variables in one of my unittests. This is however not 
the case when a random unused variable is inserted in front of 
it. (For reference I'm building the unittest using something 
similar to `dub build --build=unittest --config=unittest --force 
--archType=x86_64`, though the project is a library thus there 
are some complications: 
https://github.com/dlang/dub/issues/1856#issuecomment-899022431)


Not readable:
![](https://www.dropbox.com/s/j6bt3gaxu05om2j/Fout.png?dl=0=1)
Readable:
![](https://www.dropbox.com/s/lnj3ugmuoh339oi/Fout2.png?dl=0=1)

```d
int x = 0;
Mat!(3, 3, float) a = Mat!(3, 3, float)([1, 2, 3, 4, 5, 6, 7, 8, 
9]);

```

Note the x variable is entirely unused while Mat is a struct of a 
union that is essentially just a 2d array of floats.


I have no more clue where to look as I have no clue what could 
cause this, am I overlooking something trivial? Thanks in advance.


Re: how to import .lib library

2021-08-15 Thread Mike Parker via Digitalmars-d-learn

On Sunday, 15 August 2021 at 10:12:17 UTC, Timofeyka wrote:


Thank you for your reply!
I wanted to link to my project another project without source 
code.


Yeah, that's not possible. You either need the source or a set of 
D interface files that declares all the symbols you need. The 
compiler *has* to be able to see the symbols to know what's 
available for you to use.


Re: how to import .lib library

2021-08-15 Thread Timofeyka via Digitalmars-d-learn

On Sunday, 15 August 2021 at 10:05:15 UTC, Mike Parker wrote:
You don't import a .lib file. They are for the linker, not the 
compiler. How you make use of it depends on what sort of 
library it is and how you're building your project.


If this is all new to you, it will be easier just to specify 
here which library it is that you're wanting to use, then I or 
someone else can give you directions. But the general idea is 
as follows.


If it's a D library, you'll need access to the source code (or 
alternatively, D interface files that have a .di extension, but 
that's another topic). That's what you use at compile time via 
the `import` statement. When you import, for example, 
`std.stdio`, you are importing the module from the Phobos 
source tree that ships with the compiler.


If the library is registered with the dub repository, then you 
can use dub to manage and build your project to make life 
easier. The library's source will be available to import, and 
dub will build the library and make sure it's linked.


If the library is not registered with dub, you'll need to 
download the source somewhere, make sure it's on the import 
path (use the `-I` switch on the compiler command line with the 
source path, e.g., `-I/path/to/source`), you'll need to make 
sure the library is compiled separately from your project, and 
then you'll need to give the lib file to the compiler on the 
command line along with your source (e.g., `dmd app.d 
library.lib`).


If it's a C library, you'll need to translate the C API to D 
(not the source code, just the type and function declarations) 
if it hasn't been done already. Then you import the translated 
D files and give the .lib file to the compiler as above.


Thank you for your reply!
I wanted to link to my project another project without source 
code.


Re: how to import .lib library

2021-08-15 Thread Mike Parker via Digitalmars-d-learn

On Sunday, 15 August 2021 at 09:49:39 UTC, Timofeyka wrote:

Hello!
I may have a very stupid question, but still.
How do I include a .lib library? How to use it in your code?


You don't import a .lib file. They are for the linker, not the 
compiler. How you make use of it depends on what sort of library 
it is and how you're building your project.


If this is all new to you, it will be easier just to specify here 
which library it is that you're wanting to use, then I or someone 
else can give you directions. But the general idea is as follows.


If it's a D library, you'll need access to the source code (or 
alternatively, D interface files that have a .di extension, but 
that's another topic). That's what you use at compile time via 
the `import` statement. When you import, for example, 
`std.stdio`, you are importing the module from the Phobos source 
tree that ships with the compiler.


If the library is registered with the dub repository, then you 
can use dub to manage and build your project to make life easier. 
The library's source will be available to import, and dub will 
build the library and make sure it's linked.


If the library is not registered with dub, you'll need to 
download the source somewhere, make sure it's on the import path 
(use the `-I` switch on the compiler command line with the source 
path, e.g., `-I/path/to/source`), you'll need to make sure the 
library is compiled separately from your project, and then you'll 
need to give the lib file to the compiler on the command line 
along with your source (e.g., `dmd app.d library.lib`).


If it's a C library, you'll need to translate the C API to D (not 
the source code, just the type and function declarations) if it 
hasn't been done already. Then you import the translated D files 
and give the .lib file to the compiler as above.


how to import .lib library

2021-08-15 Thread Timofeyka via Digitalmars-d-learn

Hello!
I may have a very stupid question, but still.
How do I include a .lib library? How to use it in your code?


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 09:06:14 UTC, Mike Parker wrote:


The D `string` is an alias for `immutable(char)[]`, immutable 
contents of a mutable array reference (`immutable(char[])` 
would mean the array reference is also immutable). You don't 
want to assign that to a `char*`, because then you'd be able to 
mutate the contents of the string, thereby violating the 
contract of immutable. (`immutable` means the data to which 
it's applied, in this case the contents of an array, will not 
be mutated through any reference anywhere in the program.)


[...]


Thanks a lot for the info!


Re: Drawbacks of exceptions being globally allocated

2021-08-15 Thread Alexandru Ermicioi via Digitalmars-d-learn

On Sunday, 15 August 2021 at 00:15:32 UTC, Ali Çehreli wrote:

Even though this feature is probably never used, in D, multiple 
exception objects are chained. For example, you can throw e.g. 
in a destructor when there is an active exception in flight and 
that second object gets attached to the first one in linked 
list fashion.


This may be useful in some cases but in general, these 
colatteral exceptions don't carry much information and I don't 
think anybody looks at them. Usually, the first one is the one 
that explains the error case.
That is just an assumption. There could be designs where original 
exception gets wrapped in another one to comply with some 
interface, and in such cases, having entire chain visible, is 
useful. Also exceptions carry the stack trace which is useful, in 
debugging, allowing you to know possible location of the bug.


Regarding exception chaining, do you mean that it will 
automatically get chained, even without explicitly passing it as 
constructor of wrapping exception?


If so, it indeed might be best to remove such functionality, and 
just force user to do this by himself. He will then be able to 
decide whether chained exception does or does not carry any 
useful meaning.


Regards,
Alexandru




Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread Mike Parker via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:11:39 UTC, rempas wrote:



I mean that in C, we can assign a string literal into a `char*` 
and also a `const char*` type without getting a compilation 
error while in D, we can only assign it to a `const char*` 
type. I suppose that's because of C doing explicit conversion. 
I didn't talked about mutating a string literal


The D `string` is an alias for `immutable(char)[]`, immutable 
contents of a mutable array reference (`immutable(char[])` would 
mean the array reference is also immutable). You don't want to 
assign that to a `char*`, because then you'd be able to mutate 
the contents of the string, thereby violating the contract of 
immutable. (`immutable` means the data to which it's applied, in 
this case the contents of an array, will not be mutated through 
any reference anywhere in the program.)


Assigning it to `const(char)*` is fine, because `const` means the 
data can't be mutated through that particular reference (pointer 
in this case). And because strings in C are quite frequently 
represented as `const(char)*`, especially in function parameter 
lists, D string literals are explicitly convertible to 
`const(char)*` and also NUL-terminated. So you can do something 
like `puts("Something")` without worry.


This blog post may be helpful:

https://dlang.org/blog/2021/05/24/interfacing-d-with-c-strings-part-one/



Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 09:01:17 UTC, jfondren wrote:
They don't do the same thing. toStringz always copies, always 
GC-allocates, and always NUL-terminates. `cast(char*)` only 
does what you want in the case that you're applying it a string 
literal. But in that case you shouldn't cast, you should just


```d
const char* s = "John";
```

If you need cast cast the const away to work with a C API, 
doing that separately, at the point of the call to the C 
function, makes it clearer what you're doing and what the risks 
are there (does the C function modify the string? If so this 
will segfault).


Yeah I won't cast when having a `const char*`. I already 
mentioned that it works without cast with `const` variables ;)





Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:56:07 UTC, rempas wrote:

On Sunday, 15 August 2021 at 08:53:50 UTC, Tejas wrote:
External C libraries expect strings to be null terminated, so 
if you do use `.dup`, use `.toStringz` as well.


Yeah, yeah I got that. My question is, if I should avoid 
`cast(char*)` and use `.toStringz` while both do the exact same 
thing?


They don't do the same thing. toStringz always copies, always 
GC-allocates, and always NUL-terminates. `cast(char*)` only does 
what you want in the case that you're applying it a string 
literal. But in that case you shouldn't cast, you should just


```d
const char* s = "John";
```

If you need cast cast the const away to work with a C API, doing 
that separately, at the point of the call to the C function, 
makes it clearer what you're doing and what the risks are there 
(does the C function modify the string? If so this will segfault).


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:53:50 UTC, Tejas wrote:
External C libraries expect strings to be null terminated, so 
if you do use `.dup`, use `.toStringz` as well.


Yeah, yeah I got that. My question is, if I should avoid 
`cast(char*)` and use `.toStringz` while both do the exact same 
thing?


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread Tejas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:51:19 UTC, rempas wrote:

On Sunday, 15 August 2021 at 08:47:39 UTC, jfondren wrote:


dup() isn't aware of the NUL since that's outside the slice of 
the string. It only copies the chars in "John". You can use 
toStringz to ensure NUL termination:

https://dlang.org/phobos/std_string.html#.toStringz


Is there something bad than just casting it to `char*` that I 
should be aware of?


External C libraries expect strings to be null terminated, so if 
you do use `.dup`, use `.toStringz` as well.


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:47:39 UTC, jfondren wrote:


dup() isn't aware of the NUL since that's outside the slice of 
the string. It only copies the chars in "John". You can use 
toStringz to ensure NUL termination:

https://dlang.org/phobos/std_string.html#.toStringz


Is there something bad than just casting it to `char*` that I 
should be aware of?


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:11:39 UTC, rempas wrote:

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```



Well, that one didn't worked out really well for me. Using 
`.dup.ptr`, didn't added a null terminated character


dup() isn't aware of the NUL since that's outside the slice of 
the string. It only copies the chars in "John". You can use 
toStringz to ensure NUL termination:

https://dlang.org/phobos/std_string.html#.toStringz


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:47:27 UTC, jfondren wrote:

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```

So am I going to have an extra runtime cost having to first 
construct a `string` and then ALSO cast it to a string 
literal?


In the above case, "John" is a string that's compiled into the 
resulting executable and loaded into read-only memory, and this 
code is reached that string is duplicated, at runtime, to 
create a copy in writable memory.


Probably a more useful way to think about this is to consider 
what happens in a loop:


```d
void static_lifetime() @nogc {
foreach (i; 0 .. 100) {
string s = "John";
// some code
}
}
```

^^ At runtime a slice is created on the stack 100 times, with a 
pointer to the 'J' of the literal, a length of 4, etc. The cost 
of this doesn't change with the length of the literal, and the 
bytes of the literal aren't copied, so this code would be just as 
fast if the string were megabytes in length.


```d
void dynamically_allocated() { // no @nogc
foreach (i; 0 .. 100) {
char[] s = "John".dup;
// some code
}
}
```

^^ Here, the literal is copied into freshly GC-allocated memory a 
hundred times, and a slice is made from that.


And for completeness:

```d
void stack_allocated() @nogc {
foreach (i; 0 .. 100) {
char[4] raw = "John";
char[] s = raw[0..$];
// some code
}
}
```

^^ Here, a static array is constructed on the stack a hundred 
times, and the literal is copied into the array, and then a slice 
is constructed on the stack with a pointer into the array on the 
stack, a length of 4, etc. This doesn't use the GC but the stack 
is limited in size and now you have worry about the slice getting 
copied elsewhere and outliving the data on the stack:


```d
char[] stack_allocated() @nogc {
char[] ret;
foreach (i; 0 .. 100) {
char[4] raw = "John";
char[] s = raw[0 .. $];
ret = s;
}
return ret; // errors with -preview=dip1000
}

void main() {
import std.stdio : writeln;

char[] s = stack_allocated();
writeln(s); // prints garbage
}
```


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 08:17:47 UTC, rikki cattermole wrote:


pragma is a set of commands to the compiler that may be 
compiler specific.


In the case of the msg command, it tells the compiler to output 
a message to stdout during compilation.


Thanks man!


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rikki cattermole via Digitalmars-d-learn



On 15/08/2021 8:11 PM, rempas wrote:

Still don't know what "pragma" does but thank you.


pragma is a set of commands to the compiler that may be compiler specific.

In the case of the msg command, it tells the compiler to output a 
message to stdout during compilation.


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

```d
unittest {
pragma(msg, typeof("John"));  // string
pragma(msg, is(typeof("John") == immutable(char)[]));  // 
true

}
```


Still don't know what "pragma" does but thank you.


```d
void zerort(string s) {
assert(s.ptr[s.length] == '\0');
}

unittest {
zerort("John"); // assertion success
string s = "Jo";
s ~= "hn";
zerort(s); // assertion failure
}
```

If a function takes a string as a runtime parameter, it might 
not be NUL terminated. This might be more obvious with 
substrings:


```d
unittest {
string j = "John";
string s = j[0..2];
assert(s == "Jo");
assert(s.ptr == j.ptr);
assert(s.ptr[s.length] == 'h'); // it's h-terminated
}
```


That's interesting!


```c
void mutate(char *s) {
s[0] = 'X';
}

int main() {
char *s = "John";
mutate(s); // segmentation fault
}
```

`char*` is just the wrong type, it suggests mutability where 
mutability ain't.


I mean that in C, we can assign a string literal into a `char*` 
and also a `const char*` type without getting a compilation error 
while in D, we can only assign it to a `const char*` type. I 
suppose that's because of C doing explicit conversion. I didn't 
talked about mutating a string literal


Compile-time. std.conv.to is what you'd use at runtime. Here 
though, what you want is `dup` to get a `char[]`, which you can 
then take the pointer of if you want:


```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```



Well, that one didn't worked out really well for me. Using 
`.dup.ptr`, didn't added a null terminated character while 
`cast(char*)` did. So I suppose the first way is more better when 
you want a C-like `char*` and not a D-like `char[]`.


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 07:43:59 UTC, jfondren wrote:

On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```

So am I going to have an extra runtime cost having to first 
construct a `string` and then ALSO cast it to a string literal?


In the above case, "John" is a string that's compiled into the 
resulting executable and loaded into read-only memory, and this 
code is reached that string is duplicated, at runtime, to create 
a copy in writable memory.


Re: What exactly are the String literrals in D and how they work?

2021-08-15 Thread jfondren via Digitalmars-d-learn

On Sunday, 15 August 2021 at 06:10:53 UTC, rempas wrote:
So when I'm doing something like the following: `string name = 
"John";`

Then what's the actual type of the literal `"John"`?


```d
unittest {
pragma(msg, typeof("John"));  // string
pragma(msg, is(typeof("John") == immutable(char)[]));  // true
}
```

In the chapter [Calling C 
functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) in the "Interfacing with C" page, the following is said:
Strings are not 0 terminated in D. See "Data Type 
Compatibility" for more information about this. However, 
string literals in D are 0 terminated.


```d
void zerort(string s) {
assert(s.ptr[s.length] == '\0');
}

unittest {
zerort("John"); // assertion success
string s = "Jo";
s ~= "hn";
zerort(s); // assertion failure
}
```

If a function takes a string as a runtime parameter, it might not 
be NUL terminated. This might be more obvious with substrings:


```d
unittest {
string j = "John";
string s = j[0..2];
assert(s == "Jo");
assert(s.ptr == j.ptr);
assert(s.ptr[s.length] == 'h'); // it's h-terminated
}
```



Which is really interesting and makes me suppose that `"John"` 
is a string literal right?
However, when I'm writing something like the following: `char 
*name = "John";`,

then D will complain with the following message:
Error: cannot implicitly convert expression `"John"` of type 
`string` to `char*`


Which is interesting because this works in C.


Well, kinda:

```c
void mutate(char *s) {
s[0] = 'X';
}

int main() {
char *s = "John";
mutate(s); // segmentation fault
}
```

`char*` is just the wrong type, it suggests mutability where 
mutability ain't.


If I use `const char*` instead, it will work. I suppose that 
this has to do with the fact that `string` is an alias for 
`immutable(char[])` but still this has to mean that the actual 
type of a LITERAL string is of type `string` (aka 
`immutable(char[])`).


Another thing I can do is cast the literal to a `char*` but I'm 
wondering what's going on under the hood in this case.


The same thing as in C:

```d
void mutate(char *s) {
s[0] = 'X';
}

void main() {
char* s = cast(char*) "John";
mutate(s); // program killed by signal 11
}
```


Is casting executed at compile time or at runtime?


Compile-time. std.conv.to is what you'd use at runtime. Here 
though, what you want is `dup` to get a `char[]`, which you can 
then take the pointer of if you want:


```d
unittest {
char* s = "John".dup.ptr;
s[0] = 'X'; // no segfaults
assert(s[0..4] == "Xohn"); // ok
}
```

So am I going to have an extra runtime cost having to first 
construct a `string` and then ALSO cast it to a string literal?


I hope all that makes sense and the someone can answer, lol





Re: Anyway to achieve the following

2021-08-15 Thread JG via Digitalmars-d-learn
On Saturday, 14 August 2021 at 20:50:47 UTC, Carl Sturtivant 
wrote:

```
struct S {
  int x = 1234;
}

void main() {
  import std.stdio;
   S s;
   //construction of a using &(s.x)
   auto a = Ref!(int)();
   writeln(a); //displays 1234
   s.x += 1;
   writeln(a); //displays 1235
   a += 1;
   writeln(s.x); //displays 1236
}

struct Ref(T) {
  T* ptr;
  this(T* p) { ptr = p; }
  string toString() { import std.conv; return to!string(*ptr); }
  ref T var() { return *ptr; }
  alias var this;
}
```


Hi,

This is exactly the behaviour I was trying to obtain.

It however comes with a fair amount of overhead, as can be seen 
in the following llvm ir:


define i32 @_Dmain({ i64, { i64, i8* }* } %unnamed) #0 {
  %s = alloca %onlineapp.S, align 4   ; [#uses = 
4, size/byte = 4]
  %a = alloca %"onlineapp.Ref!int.Ref", align 8   ; [#uses = 
5, size/byte = 8]
  %1 = bitcast %onlineapp.S* %s to i8*; [#uses = 
1]
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %1, i8* 
align 1 bitcast (%onlineapp.S* @onlineapp.S.__init to i8*), i64 
4, i1 false)
  %2 = bitcast %"onlineapp.Ref!int.Ref"* %a to i8* ; [#uses = 
1]
  call void @llvm.memset.p0i8.i64(i8* align 1 %2, i8 0, i64 
8, i1 false)
  %3 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, 
i32 0, i32 0 ; [#uses = 1, type = i32*]
  %4 = call %"onlineapp.Ref!int.Ref"* @pure nothrow ref @nogc 
@safe onlineapp.Ref!(int).Ref 
onlineapp.Ref!(int).Ref.__ctor(int*)(%"onlineapp.Ref!int.Ref"* 
nonnull returned %a, i32* %3) #4 ; [#uses = 0]
  %5 = load %"onlineapp.Ref!int.Ref", 
%"onlineapp.Ref!int.Ref"* %a, align 8 ; [#uses = 1]
  call void @@safe void 
std.stdio.writeln!(onlineapp.Ref!(int).Ref).writeln(onlineapp.Ref!(int).Ref)(%"onlineapp.Ref!int.Ref" %5) #4
  %6 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, 
i32 0, i32 0 ; [#uses = 2, type = i32*]
  %7 = load i32, i32* %6, align 4 ; [#uses = 
1]
  %8 = add i32 %7, 1  ; [#uses = 
1]

  store i32 %8, i32* %6, align 4
  %9 = load %"onlineapp.Ref!int.Ref", 
%"onlineapp.Ref!int.Ref"* %a, align 8 ; [#uses = 1]
  call void @@safe void 
std.stdio.writeln!(onlineapp.Ref!(int).Ref).writeln(onlineapp.Ref!(int).Ref)(%"onlineapp.Ref!int.Ref" %9) #4
  %10 = call i32* @pure nothrow ref @nogc @safe int 
onlineapp.Ref!(int).Ref.var()(%"onlineapp.Ref!int.Ref"* nonnull 
%a) #4 ; [#uses = 2]
  %11 = load i32, i32* %10, align 4   ; [#uses = 
1]
  %12 = add i32 %11, 1; [#uses = 
1]

  store i32 %12, i32* %10, align 4
  %13 = getelementptr inbounds %onlineapp.S, %onlineapp.S* 
%s, i32 0, i32 0 ; [#uses = 1, type = i32*]
  %14 = load i32, i32* %13, align 4   ; [#uses = 
1]
  call void @@safe void 
std.stdio.writeln!(int).writeln(int)(i32 %14) #4

  ret i32 0
}


What exactly are the String literrals in D and how they work?

2021-08-15 Thread rempas via Digitalmars-d-learn
So when I'm doing something like the following: `string name = 
"John";`

Then what's the actual type of the literal `"John"`?
In the chapter [Calling C 
functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) in the "Interfacing with C" page, the following is said:
Strings are not 0 terminated in D. See "Data Type 
Compatibility" for more information about this. However, string 
literals in D are 0 terminated.


Which is really interesting and makes me suppose that `"John"` is 
a string literal right?
However, when I'm writing something like the following: `char 
*name = "John";`,

then D will complain with the following message:
Error: cannot implicitly convert expression `"John"` of type 
`string` to `char*`


Which is interesting because this works in C. If I use `const 
char*` instead, it will work. I suppose that this has to do with 
the fact that `string` is an alias for `immutable(char[])` but 
still this has to mean that the actual type of a LITERAL string 
is of type `string` (aka `immutable(char[])`).


Another thing I can do is cast the literal to a `char*` but I'm 
wondering what's going on under the hood in this case. Is casting 
executed at compile time or at runtime? So am I going to have an 
extra runtime cost having to first construct a `string` and then 
ALSO cast it to a string literal?


I hope all that makes sense and the someone can answer, lol