General Category > Ideas

Macros again

<< < (2/2)

lerno:
The SMART C macro system has a bit more stuff to consider: https://repository.upenn.edu/cgi/viewcontent.cgi?referer=https://www.google.com/&httpsredir=1&article=1474&context=cis_papers

Worth a read. Note that they add macro FOR, IF-ELSE, SWITCH. I think this is a reasonable thing to do. "SWITCH" is present in the __Generic macro in C, IF-ELSE is obviously there already, then finally the FOR loop... I think that is an important additions since its lack is making a lot of macros much more complicated.

lerno:
More about macros: http://www.wilfred.me.uk/blog/2014/09/15/comparative-macrology/

lerno:
A tiny way to modify macros would be to simply extend "#define" with a { ... } syntax:


--- Code: ---#define ADD_TO(x, y) {
   x += y;
}

ADD_TO(x, 1)

--- End code ---

The { } introduces a multiline macro that does not need explicit linebreaks.

Secondly we could add the "$" symbol to introduce hygienic temporaries:


--- Code: ---#define SWAP(x, y) {
   typeof(x) $tmp = x;
   x = y;
   y = $tmp;
}

--- End code ---

Here $tmp will actually be replaced by __<macro>_<variable_name>_<instance> when translating to C, so __SWAP_tmp_1, __SWAP_tmp_2 etc.

We then introduce the syntax macros using:


--- Code: ---macro swap(&a, &b) {
   typeof(a) $tmp = a;
   b = a;
   a = $tmp;
}

--- End code ---

The use of &a follows C++ standard: it simply refers to a variable OR EXPRESSION that is imported into its scope. Using the unadorned variable name as evaluated expression allows us to write this code:


--- Code: ---macro max(a, b) {
  return (a > b ? a : b)
}

--- End code ---

The above code is equivalent to:


--- Code: ---macro max(&a, &b) {
  typeof(a) $tmp_a = a;
  typeof(b) $tmp_b = b;
  $tmp_a > $tmp_b ? $tmp_a : $tmp_b
}

--- End code ---

Or in (GNU) C:

[/code]


--- Code: --- #define max(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })

--- End code ---

To recap:

1. We add the { } format to #define for multiline defines.
2. We add the $<name> format as hygienic variable names.
3. We add the syntax "macro" type of definition.
4. The syntax macro makes a difference between "normal" parameters (with & as prefix) and "evaluated" parameters (unadorned variables)

In addition we need to make macros have a definite scope. I suggest the following:

#define is always defined local to a scope (unlike in C).

This means that


--- Code: ---#define FOO printf("foo");
{
   #define BAR printf("bar");
}
FOO // adds printf("foo");
BAR; // Error, define not available in scope;

--- End code ---

This also means that a define can be declared public to be accessed as if defined from the top of the file scope:


--- Code: ---// file 1
module foo
public #define FOO { printf("FOO!\n"); }

// file 2
import foo

func void test() {
  foo.FOO
}

--- End code ---

Only defines in the file scope that exists in the file scope may be public and used in other modules.

lerno:
Another C type lang with semantic macros worth looking at: http://zl-lang.org/zl-dissertation-univf.pdf

Navigation

[0] Message Index

[*] Previous page

Go to full version