макрос forpermutation
От: Аноним  
Дата: 09.04.07 19:45
Оценка:
Пытаюсь написать макрос отсюда:
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
Re: макрос forpermutation
От: Аноним  
Дата: 10.04.07 06:47
Оценка:
Методом тыка нашел, что надо писать $(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));
      
    ]>
}
Re: макрос forpermutation
От: Аноним  
Дата: 10.04.07 09:13
Оценка:
Вот что получается, можно написать так:

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]
  ]>;
}


Что здесь надо поправить, или не возможна работа с массивами?

можно обойти это написав так:
Re[2]: макрос forpermutation
От: Аноним  
Дата: 10.04.07 09:20
Оценка:
А>можно обойти это написав так:


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 заработал
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.