Здравствуйте, nikov, Вы писали:
N>Здравствуйте, mkizub, Вы писали:
M>>Так зачем ложить что-то в поля объекта итератора, если среда для вызова M>>у нас уже есть в точке вызова?
N>В C# нельзя менять вызывающий код, так как он вообще может не знать, что он вызывает итератор — например, он может вызывать его через интерфейс. Поэтому нельзя добавлять еще один параметр метода, содержащий среду для вызова.
Посмотрел на С#-повский yield — оказывается, он возвращает только IEnumerable, а не любой объект.
Тогда ещё проще, делатся inner class, который этот IEnumerable имплементит, и в этом классе уже все поля и создаются,
он же и играет роль CallEnv из предыдущего моего примера.
И не надо никаких текущих тредов и прочую кучу полей генерить.
Enumeration iterate() {
yield val1;
yield val2;
}
заменить на
Enumeration iterate() {
return new Enumeration() {
int state;
Object getNext() {
switch (state) {
case 0:
// init heregoto case 1;
case 1:
state = 2;
return val1;
case 2:
state = 3;
return val2;
case 3:
return null;
}
};
}
}
Здравствуйте, Andrei N.Sobchuck, Вы писали:
AVK>>1) Короче и понятнее запись.
ANS>Короче — согласен. Понятнее — не согласен.
О вкусах не спорят. Лично мне было бы понятнее.
AVK>>2) Возможны дополнительные оптимизации, устраняющие реальный цикл.
ANS>Это можно и без выдумывания всяких синтаксисов сделать.
Теоретически да, а на практике чревато, слишком сильно при этом семантика меняется.
Здравствуйте, mkizub, Вы писали:
M>Здравствуйте, nikov, Вы писали:
N>>Здравствуйте, mkizub, Вы писали:
M>>>Так зачем ложить что-то в поля объекта итератора, если среда для вызова M>>>у нас уже есть в точке вызова?
N>>В C# нельзя менять вызывающий код, так как он вообще может не знать, что он вызывает итератор — например, он может вызывать его через интерфейс. Поэтому нельзя добавлять еще один параметр метода, содержащий среду для вызова.
M>Посмотрел на С#-повский yield — оказывается, он возвращает только IEnumerable, а не любой объект. M>Тогда ещё проще, делатся inner class, который этот IEnumerable имплементит, и в этом классе уже все поля и создаются, M>он же и играет роль CallEnv из предыдущего моего примера. M>И не надо никаких текущих тредов и прочую кучу полей генерить.
M>Enumeration iterate() {
M> return new Enumeration() {
M> int state;
M> Object getNext() {
M> switch (state) {
M> case 0:
M> // init here
M> goto case 1;
M> case 1:
M> state = 2;
M> return val1;
M> case 2:
M> state = 3;
M> return val2;
M> case 3:
M> return null;
M> }
M> };
M> }
M>}
M>
ой-ли?
если на код тела итератора не наложено существенных ограничений, там может быть yield return из произвольного места. например из каких-то вложенных блоков кода или там условных операторов. а это вы не распишите в виде одного плоского switch.
пример
if (cond1)
{
if (cond2) yield return 1;
else yield return 2;
switch(x)
{
case 1: if (cond3) yield return 3 else yield return 3;
case 10: yield return 5;
};
}
а также при повторном входе должны восстанвливаться все локальные переменные итератора. то исть грамотный метод решения — тот который я тут где-то описал.
Здравствуйте, merk, Вы писали:
M>ой-ли? M>если на код тела итератора не наложено существенных ограничений, там может быть yield return из произвольного места. например из каких-то вложенных блоков кода или там условных операторов. а это вы не распишите в виде одного плоского switch.
А пофиг. switch в байткоде может прыгать в любое место, это же не source code генерить.
Локальные переменные выносятся в поля класса.
Здравствуйте, mkizub, Вы писали:
M>Здравствуйте, merk, Вы писали:
M>>ой-ли? M>>если на код тела итератора не наложено существенных ограничений, там может быть yield return из произвольного места. например из каких-то вложенных блоков кода или там условных операторов. а это вы не распишите в виде одного плоского switch.
M>А пофиг. switch в байткоде может прыгать в любое место, это же не source code генерить. M>Локальные переменные выносятся в поля класса.
ну прально. тогда все будет ок.
я просто имел ввиду, что если вы будете это генерить в скрытый код на с#, а потом его компилировать — трюк не пройдет. а если в msil — то пройдет.
Здравствуйте, merk, Вы писали: M>ну прально. тогда все будет ок. M>я просто имел ввиду, что если вы будете это генерить в скрытый код на с#, а потом его компилировать — трюк не пройдет. а если в msil — то пройдет.
Очевидно, пройдет в любом случае. Пример C# кода, декомпилированного из yield return, желающим уже приводили.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, merk, Вы писали: M>>ну прально. тогда все будет ок. M>>я просто имел ввиду, что если вы будете это генерить в скрытый код на с#, а потом его компилировать — трюк не пройдет. а если в msil — то пройдет. S>Очевидно, пройдет в любом случае. Пример C# кода, декомпилированного из yield return, желающим уже приводили.
пройдет на уровне восстановления из мсила некоей эквивалентой программы на с#?
ну вполне возможно.
тока чтобы ее сгенерить без генерации через мсил или какое-то иное промежуточное представление — это вряд ли.
а главное лобовой вопрос — зачем?
если прямая генерация в мсил тривиальна.
хотя есть конечто борцы с трудностями, ими и создаваемыми.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, merk, Вы писали: M>>ну прально. тогда все будет ок. M>>я просто имел ввиду, что если вы будете это генерить в скрытый код на с#, а потом его компилировать — трюк не пройдет. а если в msil — то пройдет. S>Очевидно, пройдет в любом случае. Пример C# кода, декомпилированного из yield return, желающим уже приводили.
кстати чиста теоретическая задачка. пришедшая на ум.
пишите например такой вот итератор на сишарпе, компилируете, восстанвливаете потом из ассебмлера.
получаете код на сишарпе.
компилируете опять
восстанавливаете.
компилируете опять.
восстанавливаете...
вопрос.
сойдется ли процесс, то есть будет ли код на шарпе на этапе N визуально таким же как на этапе N-1.
хотел сказать эквивалентным, но эквивалентность нужно доказывать таки.
Здравствуйте, merk, Вы писали:
M>Здравствуйте, AndrewVK, Вы писали:
AVK>>Здравствуйте, merk, Вы писали:
AVK>>>>Все на самом деле совсем не так, как ты тут рассказываешь. M>>>СОВСЕМ не как??? M>>>можно поразвернутей?
AVK>>Можно. Компилятор шарпа генерирует FSM, который прекрасно работает без ломания стека и прочих низкоуровневых хаков. M>видимо нужно иметь особую проницательность, чтобы заметить, что то что я написал — запуск фцнкции в прежнем контексте...и есть ваша fsm... причием если я написал метод реализации, вы написали просто название того, что должно быть реализовано. M>да уш.
что это???????????????
каким образом кусок топика про реализацию C# стало отдельным топиком?
или это глюк???
я ничего особенного не делал!
Здравствуйте, merk, Вы писали: M>пройдет на уровне восстановления из мсила некоей эквивалентой программы на с#?
Пройдет на уровне подготовки некой эквивалентной программы на C# "без yield" и последующей её компиляции. M>тока чтобы ее сгенерить без генерации через мсил или какое-то иное промежуточное представление — это вряд ли.
непонятны причины такой убежденности. M>если прямая генерация в мсил тривиальна.
Насчет тривиальна я, конечно, не уверен. Мне почему-то кажется что трансформация кода достаточно нетривиальна — нужно определить замыкание, перенести переменные в поля объекта, а также перестроить код в стейт-машину в соответствии с правилами взаимодействия конструкций lock(), using(), и try/finally с yield return и yield break.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, merk, Вы писали: M>>пройдет на уровне восстановления из мсила некоей эквивалентой программы на с#? S>Пройдет на уровне подготовки некой эквивалентной программы на C# "без yield" и последующей её компиляции. M>>тока чтобы ее сгенерить без генерации через мсил или какое-то иное промежуточное представление — это вряд ли. S>непонятны причины такой убежденности. M>>если прямая генерация в мсил тривиальна. S>Насчет тривиальна я, конечно, не уверен. Мне почему-то кажется что трансформация кода достаточно нетривиальна — нужно определить замыкание, перенести переменные в поля объекта, а также перестроить код в стейт-машину в соответствии с правилами взаимодействия конструкций lock(), using(), и try/finally с yield return и yield break.
у меня есть серьезное подозрение в виде гипотезы...что вы с этой генерацией шарпа из мсила сильно попались.
дело в том, что мсил как ассемблер повыразительней шарпа, и потому восстановление конструкций из мсила в шарп приводит к аццкому коду на шарпе, откомпилировав который обратно в мсил, вы первого кода уже не получите.
и то, что вы тут демонстрируете как результат работы шарпа с итератором, на самом деле, ни что иное, как просто попытка дизассеблера наколбасить эквивалентный код на шарпе. что вы выдаете как раз за результат работы компилятора шарпа.
что конечно же есть аццкое заблуждение.
Здравствуйте, merk, Вы писали: M>вопрос. M>сойдется ли процесс, то есть будет ли код на шарпе на этапе N визуально таким же как на этапе N-1.
Да. И эквивалентным тоже будет.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, merk, Вы писали: M>>пройдет на уровне восстановления из мсила некоей эквивалентой программы на с#? S>Пройдет на уровне подготовки некой эквивалентной программы на C# "без yield" и последующей её компиляции. M>>тока чтобы ее сгенерить без генерации через мсил или какое-то иное промежуточное представление — это вряд ли. S>непонятны причины такой убежденности.
тогда вам нужно просто задуматься над эквивалентными преобразованиями программ. ну типа почитать, или просто поразмыслить.
M>>если прямая генерация в мсил тривиальна. S>Насчет тривиальна я, конечно, не уверен. Мне почему-то кажется что трансформация кода достаточно нетривиальна — нужно определить замыкание, перенести переменные в поля объекта, а также перестроить код в стейт-машину в соответствии с правилами взаимодействия конструкций lock(), using(), и try/finally с yield return и yield break.
как сделать в общем виде функцию входящую в прошлый контекст я тут где-то написал. вариантом такой фукнции является итератор. тело такой функции строится по правилам обычной. у нее только иначе резервируются локальные переменные и запоминатся в контексте номер метки адреса выхода . при компиляции тела такой функции компилятор делает все тоже самое что и с обычной. есть только увеличение некоторых требований для yield в catch и работы при исключении(если оно вообще не ловится в такой функции). это должно приводить к закрытию контекста такой функции вызывающей ее стороной.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, merk, Вы писали: M>>вопрос. M>>сойдется ли процесс, то есть будет ли код на шарпе на этапе N визуально таким же как на этапе N-1. S>Да. И эквивалентным тоже будет.
откуда дровишки? обосновать не трудно? и на каком шаге сойдется?
Здравствуйте, merk, Вы писали:
S>>непонятны причины такой убежденности. M>тогда вам нужно просто задуматься над эквивалентными преобразованиями программ. ну типа почитать, или просто поразмыслить.
По-моему, Вам стоит слегка сменить стиль общения, и вместо завуалированых намеков на некомпетентность собеседника, отвечать по существу, если имеется что сказать.