Jump to page: 1 2
Thread overview
How to insert code in place with templates/mixins?
Dec 20, 2021
rempas
Dec 20, 2021
rumbu
Dec 20, 2021
rempas
Dec 20, 2021
rumbu
Dec 20, 2021
Tejas
Dec 20, 2021
rempas
Dec 20, 2021
rempas
Dec 20, 2021
rempas
Dec 20, 2021
Stanislav Blinov
Dec 20, 2021
rempas
Dec 20, 2021
bachmeier
Dec 20, 2021
rempas
December 20, 2021

Here I am having a problem with templates again. No matter how much I read, I can't seem to understand how templates/mixins work. So I'm having the following code (just a snippet of the real code):

    if (c != '%') {
      if (stdout_index < STDOUT_BUF_LEN) {
        stdout_buffer[stdout_index++] = c;
        continue;
      } else {
        sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index);
        stdout_index = 0;
        stdout_buffer[stdout_index++] = c;
        continue;
      }
    }

And I want to create a macro (using the C terms) to make the code inside the first if statement (if (c != '%')) into a template that will be able to used and added in place (not as a function as I don't want to function call). I tried to make it both a template and a mixin template and It will not compile, rather it will give my the following error:

Error: declaration expected, not `if`
Error: declaration expected, not `continue`
Error: declaration expected, not `else`
Error: basic type expected, not `0`
Error: found `0` when expecting `;`
Error: no identifier for declarator `stdout_buffer[stdout_index++]`
Error: declaration expected, not `=`
Error: declaration expected, not `continue`
Error: unrecognized declaration

It should be clear what I tried to still I will post what I tried in case someone is curious to see:

mixin template add_char() {
  if (stdout_index < STDOUT_BUF_LEN) {
    stdout_buffer[stdout_index++] = c;
    continue;
  } else {
    sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index);
    stdout_index = 0;
    stdout_buffer[stdout_index++] = c;
    continue;
  }
}

So any ideas why this doesn't work?

December 20, 2021

On Monday, 20 December 2021 at 08:45:50 UTC, rempas wrote:

>

Here I am having a problem with templates again. No matter how much I read, I can't seem to understand how templates/mixins work.

So any ideas why this doesn't work?

because you cannot have statements directly in a template (the fact that is a mixin template is irelevant), only declarations.

If you want to just insert some random code, use strings. You can create a templated enum to store your parametrized string. Please note how your parameter (c) becomes part of the resulting string through concatenation (~):

enum add_char(char c) =

  `if (stdout_index < STDOUT_BUF_LEN) {
    stdout_buffer[stdout_index++] =` ~ c ~ `;
    continue;
  } else {
    sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index);
    stdout_index = 0;
    stdout_buffer[stdout_index++] =` ~ c ~ `;
    continue;
  }`;

and when you want the code inserted:

mixin(add_char!'%');

If you want to be sure that your string is syntactically correct, use token strings (https://dlang.org/spec/lex.html#token_strings)

December 20, 2021

On Monday, 20 December 2021 at 09:30:30 UTC, rumbu wrote:

>

because you cannot have statements directly in a template (the fact that is a mixin template is irelevant), only declarations.

If you want to just insert some random code, use strings. You can create a templated enum to store your parametrized string. Please note how your parameter (c) becomes part of the resulting string through concatenation (~):

enum add_char(char c) =

  `if (stdout_index < STDOUT_BUF_LEN) {
    stdout_buffer[stdout_index++] =` ~ c ~ `;
    continue;
  } else {
    sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index);
    stdout_index = 0;
    stdout_buffer[stdout_index++] =` ~ c ~ `;
    continue;
  }`;

and when you want the code inserted:

mixin(add_char!'%');

If you want to be sure that your string is syntactically correct, use token strings (https://dlang.org/spec/lex.html#token_strings)

Thanks a lot for the info. When I try to use this code, I'm getting the following error:

Error: expression expected, not `%`
Error: expression expected, not `%`

So I suppose there is a problem with string concatenation. I couldn't use it anyway because it is inefficient and because I'm using betterC. Do you know any other way that I can concatenate strings that does not depend an the Garbage Collector or the standard library?

December 20, 2021

On Monday, 20 December 2021 at 10:49:20 UTC, rempas wrote:

>

On Monday, 20 December 2021 at 09:30:30 UTC, rumbu wrote:

Thanks a lot for the info. When I try to use this code, I'm getting the following error:

Error: expression expected, not `%`
Error: expression expected, not `%`

My fault, I forgot to put some char delimiters. You can find tested code here:

https://run.dlang.io/is/KfdED0

>

So I suppose there is a problem with string concatenation. I couldn't use it anyway because it is inefficient and because I'm using betterC. Do you know any other way that I can concatenate strings that does not depend an the Garbage Collector or the standard library?

Enums (that's why the string is declarated as enum) are evaluated at compile time, the concatenation op will not end in your code as instruction, so you can do anything outside betterC rules as long you do it at compile time. You are just building some code to use later, the compiler does not generate any instruction for it.

In the example above you can press the AST button to see exactly how your code is generated.

Wnen you have doubts about a generated string you can always test it with pragma msg. In this case, if you write:

pragma(msg, add_char!'%');

you will have in the output exactly what the compiler will generate for your mixin.

December 20, 2021

On Monday, 20 December 2021 at 11:30:09 UTC, rumbu wrote:

>

On Monday, 20 December 2021 at 10:49:20 UTC, rempas wrote:

>

On Monday, 20 December 2021 at 09:30:30 UTC, rumbu wrote:

Thanks a lot for the info. When I try to use this code, I'm getting the following error:

Error: expression expected, not `%`
Error: expression expected, not `%`

My fault, I forgot to put some char delimiters. You can find tested code here:

https://run.dlang.io/is/KfdED0

>

So I suppose there is a problem with string concatenation. I couldn't use it anyway because it is inefficient and because I'm using betterC. Do you know any other way that I can concatenate strings that does not depend an the Garbage Collector or the standard library?

Enums (that's why the string is declarated as enum) are evaluated at compile time, the concatenation op will not end in your code as instruction, so you can do anything outside betterC rules as long you do it at compile time. You are just building some code to use later, the compiler does not generate any instruction for it.

In the example above you can press the AST button to see exactly how your code is generated.

Wnen you have doubts about a generated string you can always test it with pragma msg. In this case, if you write:

pragma(msg, add_char!'%');

you will have in the output exactly what the compiler will generate for your mixin.

Ehh, it still fails; should've explicitly put the length of the array and the extern (C) in main

module demo;

//i am just declaring these to have them.
size_t stdout_index;
enum STDOUT_BUF_LEN = 42;
char[STDOUT_BUF_LEN] stdout_buffer; /+indexing an uninitialized dynamic array resulted in out of bounds error even for index == 0+/
alias i32 = int;
void sys_write(int i, void* p, int index) {}
//


enum add_char(char c) =

  `if (stdout_index < STDOUT_BUF_LEN) {
    stdout_buffer[stdout_index++] ='` ~ c ~ `';
    continue;
  } else {
    sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index);
    stdout_index = 0;
    stdout_buffer[stdout_index++] ='` ~ c ~ `';
    continue;
  }`;

extern(C) /+added this because you used -betterC+/ void main()
{

    while (true) {
		mixin(add_char!'%');
		mixin(add_char!'$');
    }



}
December 20, 2021

On Monday, 20 December 2021 at 11:30:09 UTC, rumbu wrote:

>

Enums (that's why the string is declarated as enum) are evaluated at compile time, the concatenation op will not end in your code as instruction, so you can do anything outside betterC rules as long you do it at compile time. You are just building some code to use later, the compiler does not generate any instruction for it.

In the example above you can press the AST button to see exactly how your code is generated.

Wnen you have doubts about a generated string you can always test it with pragma msg. In this case, if you write:

pragma(msg, add_char!'%');

you will have in the output exactly what the compiler will generate for your mixin.

That's cool! And I was wondering how I can make sting literal concatenation at compile time. Now the problem is that I want it to get the name of so symbol and add it to a string literal. Let's check this example: enum state(alias name) = name ~ = 10;;

I want this to add the token of that will be used as name in the string. For example, I want state!val; to get "expanded" as val = 10; rather than 10 = 10;. So I don't want it to take the value of "val" but the word/token "val" itself. I tried using alias instead of char for the parameter but it didn't worked. Do you know how I can do that?

December 20, 2021

On Monday, 20 December 2021 at 11:58:58 UTC, Tejas wrote:

>

Ehh, it still fails; should've explicitly put the length of the array and the extern (C) in main

module demo;

[ ... ]

extern(C) /+added this because you used -betterC+/ void main() {

    while (true) {
		mixin(add_char!'%');
		mixin(add_char!'$');
    }
}

Thanks! A mixin is not necessary, it will do the same thing without it.

December 20, 2021

On Monday, 20 December 2021 at 18:03:09 UTC, rempas wrote:

> >

Now the problem is that I want it to get the name of so symbol and add it to a string literal.
Let's check this example: enum state(alias name) = name ~ = 10;;

https://dlang.org/spec/traits.html#identifier

December 20, 2021

On Monday, 20 December 2021 at 18:12:35 UTC, Stanislav Blinov wrote:

>

https://dlang.org/spec/traits.html#identifier

Thanks!!! Finally I was able to do it! The code is the following (well not in my final project but it's a demonstration):

enum add_char(string c) =
  `if (stdout_index < STDOUT_BUF_LEN) {
    stdout_buffer[stdout_index++] =` ~ c ~ `;
    continue;
  } else {
    sys_write(1, stdout_buffer.ptr, cast(i32)stdout_index);
    stdout_index = 0;
    stdout_buffer[stdout_index++] =` ~ c ~ `;
    continue;
  }`;

void main() {
  mixin(add_char!(__traits(identifier, c)));
}

I don't know if there is another way to do it but this works for me. Also another thing that I want to ask is if the "mixin" is generated every time inside a loop and if there is a better way to do that?

December 20, 2021

On Monday, 20 December 2021 at 18:06:32 UTC, rempas wrote:

>

On Monday, 20 December 2021 at 11:58:58 UTC, Tejas wrote:

>

Ehh, it still fails; should've explicitly put the length of the array and the extern (C) in main

module demo;

[ ... ]

extern(C) /+added this because you used -betterC+/ void main() {

    while (true) {
		mixin(add_char!'%');
		mixin(add_char!'$');
    }
}

Thanks! A mixin is not necessary, it will do the same thing without it.

Well it seem that it actually needs it...

« First   ‹ Prev
1 2