Создается неправильный код
От: dsorokin Россия  
Дата: 23.04.10 08:55
Оценка:
Ничего не понимаю. Создается какой-то левый код (using ncc 1.0.0.8745) в методе MoveNext (). К счастью, рефлектор его показывает, хотя сам рефлектор тоже может ошибаться. За этим примером следует кусок из рефлектора. Возможно дело в оптимизации хвостовой рекурсии. MoveNext () вызывает сам себя. Может быть, дело в другом. Рефлектор показывает, вообще, не то.

Компилятор довольно свежий.

using System;
using System.Collections.Generic;

public class SubEnumerator[T]: IEnumerator[T]
{
  private mutable ts1 : IEnumerator[T];
  private mutable ts2 : IEnumerator[T];
  private cont : void -> IEnumerator[T];
  
  public this (ts1 : IEnumerator[T], cont : void -> IEnumerator[T])
  {
    this.ts1 = ts1;
    this.ts2 = null;
    this.cont = cont;
  }
  
  public Reset () : void
  {
    throw NotSupportedException ()
  }
  
  public Dispose () : void
  {
    when (ts1 != null)
      ts1.Dispose ();
    
    when (ts2 != null)
      ts2.Dispose ();
  }
  
  public MoveNext () : bool
  {
    if (ts2 != null)
      ts2.MoveNext ()
    else
    {
      if (ts1.MoveNext ())
        true
      else
      {
        
        ts1.Dispose ();
        ts1 = null;
        ts2 = cont ();
        
        match (ts2)
        {
          | ts is SubEnumerator[T] => 
          
            ts1 = ts.ts1;
            ts2 = ts.ts2;
          
            MoveNext ();
            
          | _ => 
            ts2.MoveNext ();
        }
      }
    }
  }
  
  public Current : T
  {
    get
    {
      if (ts2 != null)
        ts2.Current
      else
        ts1.Current
    }
  }
}


Вот, метод MoveNext () в рефлекторе:

public bool MoveNext()
{
    this.ts1.Dispose();
    this.ts1 = null;
    this.ts2 = this.cont.apply();
    IEnumerator<T> enumerator2 = this.ts2;
    if (enumerator2 is SubEnumerator<T>)
    {
        SubEnumerator<T> enumerator = (SubEnumerator<T>) enumerator2;
        this.ts1 = enumerator.ts1;
        this.ts2 = enumerator.ts2;
    }
    return ((this.ts2 == null) ? (!this.ts1.MoveNext() ? this.ts2.MoveNext() : true) : this.ts2.MoveNext());
}
Re: Создается неправильный код
От: WolfHound  
Дата: 23.04.10 10:28
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Рефлектор показывает, вообще, не то.

Похоже глюки рефлектора.
Посмотри IL.
    L_0000: nop 
    L_0001: nop 
    L_0002: nop 
    L_0003: ldarg.0 
    L_0004: ldfld class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> SubEnumerator`1<!T>::ts2
    L_0009: ldnull 
    L_000a: ceq 
    L_000c: ldc.i4.0 
    L_000d: ceq 
    L_000f: brfalse L_0026
    L_0014: nop 
    L_0015: nop 
    L_0016: ldarg.0 
    L_0017: ldfld class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> SubEnumerator`1<!T>::ts2
    L_001c: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
    L_0021: br L_00bf
    L_0026: nop
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Создается неправильный код
От: WolfHound  
Дата: 23.04.10 10:38
Оценка:
Здравствуйте, dsorokin, Вы писали:

Кстати если я правильно понял задумку то этот код должен выглядеть так:
public class SubEnumerator[T]: IEnumerator[T]
{
  private mutable ts : IEnumerator[T];
  private mutable cont : void -> IEnumerator[T];
  
  public this (ts : IEnumerator[T], cont : void -> IEnumerator[T])
  {
    this.ts = ts;
    this.cont = cont;
  }
  
  public Reset () : void
  {
    throw NotSupportedException ()
  }
  
  public Dispose () : void
  {
    ts.Dispose ();
  }
  
  public MoveNext () : bool
  {
    if (ts.MoveNext ())
      true
    else if (cont != null)
    {
      ts.Dispose ();
      ts = cont ();
      cont = null;
      match (ts)
      {
        | subTs is SubEnumerator[T] => 
          ts = subTs.ts;
          cont = subTs.cont;
        | _ => ()
      }
      MoveNext ();
    }
    else
      false
  }
  
  public Current : T
  {
    get
    {
      ts.Current
    }
  }
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Создается неправильный код
От: dsorokin Россия  
Дата: 23.04.10 11:30
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Кстати если я правильно понял задумку то этот код должен выглядеть так:


Большое спасибо! То, что надо! Но все равно непонятно, что не так с моим кодом. Или переработал к концу недели...

Это — оптимизатор хвостовой части для enumerable comprehension. Без него comprehension был бы неюзабельным. Как тебя внести в список авторов?
Re[2]: Создается неправильный код
От: dsorokin Россия  
Дата: 23.04.10 11:46
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Кстати если я правильно понял задумку то этот код должен выглядеть так:


Дошло до меня... У меня cont не менялся. Рефлектор — бажный, и он ввел меня в заблуждение. Компилятор Nemerle был прав.
Re[3]: Создается неправильный код
От: WolfHound  
Дата: 23.04.10 12:08
Оценка: +1
Здравствуйте, dsorokin, Вы писали:

D>Большое спасибо! То, что надо! Но все равно непонятно, что не так с моим кодом. Или переработал к концу недели...

Если ты про рефлектор то он может реверснуть только очень простой код. Чуть в сторону и тушите весла.
Если ты про логику то то я вообще не понял что ты там мудрил. Мне удалось разгадать только намерение.

D>Это — оптимизатор хвостовой части для enumerable comprehension. Без него comprehension был бы неюзабельным.

Я подожду пока ты закоммитишь и посмотрю на использование.
Возможно там можно будет еще пооптимизировать за счет кодогенерации.

Но это потом.
Сейчас нужно все фичи сделать и тесты написать.

D>Как тебя внести в список авторов?

Примерно так http://code.google.com/p/nemerle/source/browse/nemerle/trunk/lib/Map.n
... << RSDN@Home 1.2.0 alpha 4 rev. 1305>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.