Пытаюсь написать макрос отсюда:
http://nemerle.org/Macros_tutorial
Add a new syntactic construct forpermutation to your program. It should be defined as the macro
macro forp (i, n : int, m : int, body)
and introduce syntax, which allows writing the following program
mutable i = 0;
forpermutation (i in 3 to 10) Nemerle.IO.printf ("%d\n", i)
It should create a random permutation p of numbers x_j, m <= x_j <= n at the compile-time. Then generate the code executing body of the loop n — m + 1 times, preceding each of them with assignment of permutation element to i.
Написал пока так:
macro @forpermutation (i, n : int, m : int, body)
syntax ("forpermutation", "(", i, "from", n, "to", m, ")", body)
{
<[
$i = 0;
// foreach ($i in [$n..$m]) {
$body;
// }
]>
}
Для начала хочется сделать просто цикл от n до m,
но в этом и загвоздка, как вытащить значение из n и засунуть скажем в i?
Вот так не работает:
$i = $n;
Пытался изпользовать так:
[Hygienic]
cache(e : Expr) : Expr * Expr
{ | <[ $obj.$mem ]> => (<[ def tmp = $obj ]>, <[ tmp.$mem ]>)
| <[ $tab [$idx] ]> =>
(<[ def (tmp1, tmp2) = ($tab, $idx) ]>, <[ tmp1 [tmp2] ]>)
| _ => (<[()]>, e)
}
После этого:
def (cached1, safe1) = cache(n);
<[
$cached1;
$i = safe1;
Но компилятор ругается на Hygienic
Методом тыка нашел, что надо писать $(n: int) чтобы получить ее значение,
по макросам документация какая-то невнятная
теперь собирается, но не работает, вернее не так как хочется,
почему-то значение $(perm[n — 1]: int) не меняется,
хотя n меняется,
как бы исправить?
macro @forpermutation (i, n : int, m : int, body)
syntax ("forpermutation", "(", i, "from", n, "to", m, ")", body)
{
def size = m - n + 1;
mutable perm = array(size);
def r = System.Random();
for (mutable k = 0; k < size; ++k)
perm[k] = m + k;
for (mutable k = 0; k < size; ++k)
perm[r.Next(perm.Length)] <-> perm[k];
System.Console.WriteLine($"perm: ..$perm");
// here kvasi citation begin rsdn bug?
def loop(n) {
when (n > 0) {
System.Console.WriteLine("boo i {0}, n {1}, perm[n - 1] {2}",
$i, n, $(perm[n - 1]: int));
$i = $(perm[n - 1]: int);
$body;
loop(n - 1);
}
}
loop($(size: int));
]>
}
Вот что получается, можно написать так:
macro m(): int {
Nemerle.IO.printf ("m: compile-time\n");
def arr = 1;
<[ Nemerle.IO.printf ("m: run-time\n");
$(arr: int)
]>;
}
а вот так нельзя:
macro m(): int {
Nemerle.IO.printf ("m: compile-time\n");
def arr = array[1];
<[ Nemerle.IO.printf ("m: run-time\n");
($(arr: array[int]))[0]
]>;
}
Что здесь надо поправить, или не возможна работа с массивами?
можно обойти это написав так:
А>можно обойти это написав так:
macro m(): int {
Nemerle.IO.printf ("m: compile-time\n");
def arr = array[1];
mutable p = [];
for (mutable i = 0; i < arr.Length; ++i)
p = <[ $(arr[i]: int) ]> :: p;
<[
def arr = array[..$p];
Nemerle.IO.printf ("m: run-time\n");
arr[0]
]>;
}
или короче:
macro m(): int {
Nemerle.IO.printf ("m: compile-time\n");
def arr = array[1];
<[
Nemerle.IO.printf ("m: run-time\n");
$(arr[0]: int)
]>;
}
но с последним вариантом проблема,
если написать
macro m(): int {
Nemerle.IO.printf ("m: compile-time\n");
def arr = array[1];
<[
def k = 0;
Nemerle.IO.printf ("m: run-time\n");
$(arr[k]: int)
]>;
}
то уже проблема, как бы ту k засунуть?
тогда бы мой forpermutation заработал