Здравствуйте, mkizub, Вы писали:
M>Кроме тулзов работающих с текстом как таковым, вроде regexp-ов, но у них и нет такого понятия как M>"функция f(x)", и никуда они единицу не прибавляют. Нечем, не умеют, у них нет такого понятия как M>функция или сложение.
Да ладно при желании и из regexp-ов можно выстроить Марковскую цепочку с полной подержкой арифметики
Re[15]: Мартин Фаулер о развитии систем программирования (Re
Здравствуйте, FR, Вы писали:
M>>Кроме тулзов работающих с текстом как таковым, вроде regexp-ов, но у них и нет такого понятия как M>>"функция f(x)", и никуда они единицу не прибавляют. Нечем, не умеют, у них нет такого понятия как M>>функция или сложение.
FR>Да ладно при желании и из regexp-ов можно выстроить Марковскую цепочку с полной подержкой арифметики
Вот это и будет некий интерпретатор, у которого будет понятие арифметики, чисел и функций,
который и будет через некое своё внутреннее понимание реализовывать трансформации согласно
меры своего понимания. У этой твоей Марковской цепочки будет понимание, семантика арифметики,
а не у текста и не у regexp-ов.
Здравствуйте, mkizub, Вы писали:
M>Здравствуйте, FR, Вы писали:
M>>>Кроме тулзов работающих с текстом как таковым, вроде regexp-ов, но у них и нет такого понятия как M>>>"функция f(x)", и никуда они единицу не прибавляют. Нечем, не умеют, у них нет такого понятия как M>>>функция или сложение.
FR>>Да ладно при желании и из regexp-ов можно выстроить Марковскую цепочку с полной подержкой арифметики
M>Вот это и будет некий интерпретатор, у которого будет понятие арифметики, чисел и функций, M>который и будет через некое своё внутреннее понимание реализовывать трансформации согласно M>меры своего понимания. У этой твоей Марковской цепочки будет понимание, семантика арифметики, M>а не у текста и не у regexp-ов.
Забавная у вас логика, однако...
Тогда выходит у JVM есть понимание байткода, а у светофора понимание красного и прочих цветов
Далеко пойдёте.
Re[17]: Мартин Фаулер о развитии систем программирования (Re
Здравствуйте, Курилка, Вы писали:
M>>>>Кроме тулзов работающих с текстом как таковым, вроде regexp-ов, но у них и нет такого понятия как M>>>>"функция f(x)", и никуда они единицу не прибавляют. Нечем, не умеют, у них нет такого понятия как M>>>>функция или сложение.
FR>>>Да ладно при желании и из regexp-ов можно выстроить Марковскую цепочку с полной подержкой арифметики
M>>Вот это и будет некий интерпретатор, у которого будет понятие арифметики, чисел и функций, M>>который и будет через некое своё внутреннее понимание реализовывать трансформации согласно M>>меры своего понимания. У этой твоей Марковской цепочки будет понимание, семантика арифметики, M>>а не у текста и не у regexp-ов.
К>Забавная у вас логика, однако... К>Тогда выходит у JVM есть понимание байткода,
Конечно есть. Она умеет много чего относительно байткода — верифицировать, исполнять и т.п.
У неё есть некое своё внутреннее представление байткода, она это представление умеет трансформировать,
скажем для оптимизации выполнения.
К>а у светофора понимание красного и прочих цветов
У светофора нет понимания красного цвета. Он умеет включать и выключать лампочки.
А понимание красного цвета у светофора есть у человека.
К>Далеко пойдёте.
Конечно. Ты тоже можешь задуматься над тем, отличается ли твоё понимание байткода
от понимания им JVM, и есть ли в этих процессах принципиальная разница. Узнаешь
о себе много нового. И чем больше нового узнаешь — тем дальше пойдёшь
Здравствуйте, serg baburin, Вы писали:
SB>Здравствуйте, Курилка, Вы писали:
К>>Ну а если серьёзней, то какими чувствами кроме зрения ты воспринимаешь программу? Ну и какие чувства кроме зрения есть в том, что пишет Фаулер? SB>Как сказал один мой знакомый — "ж..ой чую, что там ошибка!"
Ну, ж..ой — не ж..ой, но чем-то бессознательным — точно. Особенно в 4-5 утра...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: Мартин Фаулер о развитии систем программирования (Rep
Здравствуйте, Sinclair, Вы писали:
S>С год назад пробегали скриншоты MS VS 2010.
Это какие то мысли вслух какого то левого чувака были. Вот если бы ты появился в Редмонде в апреле, у тебя был бы шанс посмотреть на редактор Dev10, отцепленный от умершего наутилуса.
Здравствуйте, Sinclair, Вы писали:
C>>В бинарном формате хранится только дизайн, код — в виде старого доброго текста. S>Начиная с версии 6.0 дизайн стал по умолчанию храниться в текстовом формате.
Раньше.
S> До этого разработчики пользовали самописанные приблуды для перевода .dfm в текст, т.к. бинарный формат оказался катастрофически несовместимым с системами контроля версий.
Здравствуйте, Курилка, Вы писали:
К>Плюс в студии (которая явно отчасти продолжает идеи дельфи), вроде же resx (или как там оно зовётся, года 4 студию не трогал) нормально читаемый xml (хотя в уме транслировать координаты кнопок в картинку не особо сподручно)
resx это конечно xml, только формы храняться не в нем, а в коде на C#. А resx это просто файл с ресурсами.
Здравствуйте, AndrewVK, Вы писали: AVK>Это какие то мысли вслух какого то левого чувака были.
AVK>Вот если бы ты появился в Редмонде в апреле, у тебя был бы шанс посмотреть на редактор Dev10, отцепленный от умершего наутилуса.
Увы. Пользуясь случаем, передаю привет американскому посольству в Москве.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[10]: Мартин Фаулер о развитии систем программирования (Re
Здравствуйте, Sinclair, Вы писали:
S>Насколько я помню, с 6й. Имеется в виду — формат хранения. Редактор форм в текстовом формате был как максимум в тройке.
Ну и вот. Зачем тогда говорить о "железе образца 1995 года"?
Но речь шла вообще не об этом.
Re[11]: Мартин Фаулер о развитии систем программирования (Re
AF>Ну и вот. Зачем тогда говорить о "железе образца 1995 года"?
Еще раз поясняю на пальцах: текстовый формат мог работать и в 1995. И это бы никак не повлияло на производительность.
Не сделали его не по техническим причинам, а потому что у разработчиков был клин в голове.
Так что я 100% уверен, что его поддержку сделали не потому, что "железо доросло", а потому что product manager пришел в команду и дал дюлей кому надо, основываясь на фидбеке от пользователей Delphi.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: Мартин Фаулер о развитии систем программирования (Re
mkizub,
M>Конечно. Ты тоже можешь задуматься над тем, отличается ли твоё понимание байткода M>от понимания им JVM, и есть ли в этих процессах принципиальная разница. Узнаешь M>о себе много нового. И чем больше нового узнаешь — тем дальше пойдёшь
Предлагаю вернуться на землю. Я вот молча прочитал все твои сообщения про внутреннее представление и различные отображения. Понял, что чего-то не догоняю. Позволь тебе задать практический вопрос.
Рассмотрим код на Cкале:
trait Type1 {
type T1
}
trait Monad {
type M <: Type1
def return[A](a : A) : M { type T1 = A }
def bind[A,B](m : M { type T1 = A }, f : A => M { type T1 = B })
: M { type T1 = B }
}
Здесь трейт Type1 определяет атрибут-тип T1, к которому потом осуществляется доступ в трейте Monad. Компиляция этого года выдаёт некий байт-код, который невоспроизводим в Java. (Есть аналогичные случаи для Немерла и C#, то есть существует код на Немерле который будучи скомпилирован в MSIL недостижим из C#).
Если мы возьмём внутреннее представление = байт-коду JVM, то окажется что внешнее преставление в виде Скалы возможно, а в виде Джавы — нет.
Если мы возьмём более крупноблочное преставление, скажем в виде AST для Джавы, то с помощью этого AST мы не сможем закодировать не только параметры-типы, а вообще почти любую скалистую фичу, которая идёт дальше обычного ООП.
Если мы возьмём внутреннее преставление = AST Скалы, то скажем банальный static не будет иметь аналога в Скале (static плохо дружит с компонентностью, поэтому он был выброшен).
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>Предлагаю вернуться на землю. Я вот молча прочитал все твои сообщения про внутреннее представление и различные отображения. Понял, что чего-то не догоняю. Позволь тебе задать практический вопрос.
LCR>Если мы возьмём внутреннее представление = байт-коду JVM, то окажется что внешнее преставление в виде Скалы возможно, а в виде Джавы — нет.
LCR>Если мы возьмём более крупноблочное преставление, скажем в виде AST для Джавы, то с помощью этого AST мы не сможем закодировать не только параметры-типы, а вообще почти любую скалистую фичу, которая идёт дальше обычного ООП.
LCR>Если мы возьмём внутреннее преставление = AST Скалы, то скажем банальный static не будет иметь аналога в Скале (static плохо дружит с компонентностью, поэтому он был выброшен).
LCR>И что теперь?
Вначале о внутреннем представлении. Всё, что мы с него имеем, это именованые типы семантических узлов, именованые атрибуты
и под-узлы этих семантических узлов, минимальные констрайнты (вроде — это необязательный скалярный атрибут, а это
вектор под-узлов типа "expression"). Это налагает достаточно мало ограничений, и достаточно удобно для работы.
Собственно, это почти лисповский список, разве только его элементы поименованы, а не имеют фиксированный индекс,
и заданы кой-какие вспомогательные данные. Можно уменьшать количество данных в описании узла (отказаться от имён,
или разрешить каждому атрибуту быть как скаляром так и вектором, отказаться от типизации вообще — любой атрибут
будет любого типа и т.п.), можно увеличивать требования к количеству данных в описании типа узла — каждый
из создающих tree-based среду разработки программ (IP, MPS, SOP) выбирает как ему удобнее.
Правильней было-бы создать некий стандарт на это описание, который будет поддерживаться всеми средами.
Так же как есть единый стандарт на текст (включая кодировки).
Так вот, теперь назад к Scala, Java, JVM и прочим.
Перво наперво, наша среда разработки программ должна позволить отображать и редактировать эти объявленные
узлы дерева. Для этого можно задавать "отображатели", некий "синтаксис". Узлы могут отображаться как
в виде текста, так и в виде графики, и конечно в смешанном виде. Скажем, мы можем задать отображение
таких узлов как "AccessModifier_Private" и "AccessModifier_Public" в виде иконки и соответственно,
а узел "InfixExpression { Operator op; Expression left, right}" в виде последовательности $left$ $op$ $right$,
где $...$ означает, что отображение задаётся отображениями для этих children узлов.
Конечно, если отображение для встретившегося конкретного типа узла не задано, то среда разработки
будет использовать некое отображение по умолчанию. Скажем, рисовать <<InfixExpression:{ $op$ $left$ $right$ }>.
Или рисовать <<InfixExpression>> и позволять редактировать его атрибуты в отдельном окне, где узел отображается
в виде дерева и т.п.
То есть отобразить среда сможет всё, и всё позволит редактировать — но если задать синтаксис отображения и
редактирования — работать с этими узлами будет удобней.
Кстати, это конечно не должно быть однозначным и полным отображением. Мы можем отображать в некоем текстовом
представлении, которое не сможет распарсить ни один парсер. Мы можем отображать только часть атрибутов узла.
И т.д.
Итак, мы задали некие семантические узлы для Scala, Java, JVM и их отображение. Можем не задавать отображения
некоторых узлов. Скажем, не задавать отображение для GOTO узла (семантического понятия), который есть в JVM.
И теперь мы пишем программу. При этом мы можем использовать любые известные системе (описанные во внутреннем
представлении) семантические узлы. Можем использовать скаловские трейты и абстрактные типы, которых нет в Java.
Можем использовать Java return и wildcard-ы в типах, которых нет в Scala. Можем использовать GOTO из JVM,
которого нет ни в Scala ни в Java. В смысле редактирования мы можем использовать всё, что угодно, постольку,
поскольку оно соответствует констрайнтам заданным во внутреннем представлении. Скажем, во внутреннем представлении
у нас сказано, что у InfixExpression есть скаляреый под-узел Operator — так мы в этот слот не сможем вставить
больше одного под-узла, или вставить туда узел типа Expression.
Теперь о компиляции всего этого бардака.
Компиляция происходит просто. Это tree rewriting. Задача среды программирования переписать дерево так, чтоб
в нём остались только узлы понимаемые target платформой. Скажем, у нас target платформа — это набор узлов
определённых для Java (то есть мы хотим, видимо, выдать на выходе явовский исходный текст).
А в программе у нас есть скаловские трейты.
Можем мы переписать наше дерево, заменив эти трейты на явовские узлы? Можем. Заменим узел ScalaTrait
на пару JavaInterface, а код из методов повставляем во все классы, которые extends наш трэйт.
Чаще всего это сработает, но иногда и не получится, как в твоём примере с монадой и абстрактным типом.
Можем мы заменить GOTO из JVM на явовский исходный код? Иногда можем. Скажем, заменим код
{
foo();
label: bar();
goto label;
}
на
{
int $label = 0;
$dogoto: for(;;) {
switch ($label) {
case 0:
foo();
case 1:
bar();
$label = 1; continue $dogoto; // goto "label"
}
}
А если мы не сможем трансформировать дерево так, чтоб привести к набору узлов target платформы?
Сюрприз — выдадим ошибку компиляции.
Проблема здесь в чём? Проблема в том, что программист должен будет иметь квалификацию лучше, чем
обычно имеют сейчас. Если сейчас программист на java пишет static и не задумывается о том,
что при этом реально происходит, и это скомпилируется и будет работать — то программируя
в SymADE он должен будет понимать всю семантику происходящего, в том числе и понимать,
почему он неожиданно получить ошибку компиляции используя одновременно static и скаловские
семантические узлы. Или в крайнем случае, он добавит свой плагин для трансформации дерева,
который позволит в его конкретном случае таки скомпилировать программу в target платформу.
С другой стороны, программист может иметь и меньшую квалификацию и всё равно работать
в SymADE. Если ему сказать, или настроить редактор так, чтоб нельзя было использовать
произвольные узлы (семантические понятия), а только узлы из определённого набора
(то есть фактически написать некий DSL) — то он и не напорется на проблемы с тем,
что его программа неожиданно стала выдавать ошибку компиляции. А этот DSL язык может
быть намного проще, чем Java. И в то же время, его будет вполне хватать для задачь,
которые должен решать этот малоквалифицированный программист.
Больше того, SymADE будет легче в освоении этим малоквалифицированным программистом
(или скорее квалифицированным специалистом в своей области, но который не программист —
скажем, некий менеджер программирующий workflow). Потому как SymADE намного гибче
в отображении кода с одной стороны, и будет подсказывать неопытному пользователю —
какие именно конструкции можно вставить конкретно в этом месте. Ему не надо будет
знать, что объявление функции пишется как "def $name ( $args ) : $return_type".
Он скажет среде — вставить в это место новый узел, она ему скажет — можно вставить
объявление метода или поля. Он говорит — мне нужно метод вставить. Ему этот метод
и вставят. Потом он заполнит поле имени метода, и ему скажут — а теперь вставь
тип результата, это может быть то-то и то-то. И так далее.
С точки зрения осовения нового языка (онтологии семантических понятий) это намного
легче, чем выучивать синтаксис и продиратся через дебри, пока не освоишь этот
язык более полно. С точки зрения удобства, ну привык он к C-style синтаксису —
выберет отображалку объявления методов в виде "$return_type $name($args) { ... }",
а если он привык к паскалевскому синтаксису, он тот-же узел сможет отображать как
"method $name ($args) : $return_type begin ... end". И ему не надо будет
напрягаться с изучением нового синтаксиса только потому, что он захотел использовать
ScalaTrait в своей программе.
Здравствуйте, mkizub, Вы писали:
M>Больше того, SymADE будет легче в освоении этим малоквалифицированным программистом M>(или скорее квалифицированным специалистом в своей области, но который не программист - M>скажем, некий менеджер программирующий workflow). Потому как SymADE намного гибче M>в отображении кода с одной стороны, и будет подсказывать неопытному пользователю - M>какие именно конструкции можно вставить конкретно в этом месте. Ему не надо будет M>знать, что объявление функции пишется как "def $name ( $args ) : $return_type". M>Он скажет среде — вставить в это место новый узел, она ему скажет — можно вставить M>объявление метода или поля. M>Он говорит — мне нужно метод вставить. Ему этот метод M>и вставят. Потом он заполнит поле имени метода, и ему скажут — а теперь вставь M>тип результата, это может быть то-то и то-то. И так далее. M>С точки зрения осовения нового языка (онтологии семантических понятий) это намного M>легче, чем выучивать синтаксис и продиратся через дебри, пока не освоишь этот M>язык более полно.
Это неработающая утопия. Проблема разработки софта — вовсе не в синтаксисе. Синтаксис — это такая вещь, которая изучается за 15 минут.
Собственно разработка состоит в том, чтобы вставлять "в дерево" то, что нужно, в нужном порядке. Вот изучение этого "того, чего нужно" и представляет основную сложность.
А ты по какой-то причине считаешь, что боль — в продирании через дебри синтаксиса. Ну вот у Java и C# синтаксис близкий к С++. И что? Основная боль разработчиков C++ при миграции в управляемые среды — непонимание того, куда девать деструкторы.
M>С точки зрения удобства, ну привык он к C-style синтаксису - M>выберет отображалку объявления методов в виде "$return_type $name($args) { ... }", M>а если он привык к паскалевскому синтаксису, он тот-же узел сможет отображать как M>"method $name ($args) : $return_type begin ... end". И ему не надо будет M>напрягаться с изучением нового синтаксиса только потому, что он захотел использовать M>ScalaTrait в своей программе.
Для того, чтобы применять ScalaTrait в своей программе, нужно сначала понять, что такое trait. Если этого не понять, то никакой синтаксис не поможет — будь то C, Pascal, или Basic. А если понять — то синтаксис никаких проблем не вызовет.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Мартин Фаулер о развитии систем программирования (Re
Здравствуйте, Sinclair, Вы писали:
S>Еще раз поясняю на пальцах: текстовый формат мог работать и в 1995. И это бы никак не повлияло на производительность.
Интересный вывод, только абсолютно беспочвенный.
Но речь шла, еще раз повторю, не об этом.
Re[20]: Мартин Фаулер о развитии систем программирования (Re
Сначала небольшое оффтопическое замечание, чтобы потом не отвлекаться: в дженериках Скалы вайлдкарды присутствуют в виде экзистенциальных типов (вернее вайлдкарды являются их частным случаем). Появились не так давно, кажется с версии 2.6.
Теперь вернёмся.
M>Вначале о внутреннем представлении. Всё, что мы с него имеем, это именованые типы семантических узлов, именованые атрибуты и под-узлы этих семантических узлов, минимальные констрайнты (вроде — это необязательный скалярный атрибут, а это вектор под-узлов типа "expression"). M> ... M>Правильней было-бы создать некий стандарт на это описание, который будет поддерживаться всеми средами. M>Так же как есть единый стандарт на текст (включая кодировки).
Пока всё понятно. Хотя есть сомнения в том, что возможен стандарт на это описание. Так как всегда возможна ситуация, что какая-то фича уже не будет укладываться в стандарт. В данном случае получается, что нам надо будет выбрать внутреннее представление таким образом, что оно будет покрывать и язык Scala, и язык Java и язык опкодов JVM как частные случаи. То есть будет очень низкоуровневым! И каждый новый не укладывающийся в прежние рамки язык будет раздувать и дробить это внутреннее представление. Есть языки, где тела функций отделены от сигнатур, и сигнатуры являются FCO, есть языки где ветки в паттерн-матчинге являются FCO, есть Хаскелл со своей страшной системой типов, есть наконец Epigram, который я даже не представляю как подогнать под Java+Scala+JVM, настолько он другой. Естественно, общая база есть — это лямбда-исчисление. Или система команд x86. Или опкоды LLVM.
Таким образом, перевод языков во внутреннее представление возможен, хоть и труден. А вот обратный процесс равносилен декомпиляции, и в общем случае не решается.
M>Так вот, теперь назад к Scala, Java, JVM и прочим.
M>Перво наперво, наша среда разработки программ должна позволить отображать и редактировать эти объявленные M>узлы дерева. Для этого можно задавать "отображатели", некий "синтаксис". M>... M>Кстати, это конечно не должно быть однозначным и полным отображением. Мы можем отображать в некоем текстовом M>представлении, которое не сможет распарсить ни один парсер. Мы можем отображать только часть атрибутов узла. M>И т.д.
Хм, а почему отображение не должно быть однозначным? Возможна ведь какая ситуация: код на Скале содержащий хвостовую рекурсию преобразуется во внутреннее представление, затем мы это поддерево (в форме внутреннего представления) редактируем на уровне Джавы (в Джаве этот кусок виден как цикл). И потом мы снова переключаемся в Скалу. Что теперь?
В какой код нужно преобразовывать это? В тупой for? Или всё же попытаться представить в виде хвостовой рекурсии? Как долго нужно пытаться представить в виде хвостовой рекурсии?
Если не нравится пример с рекурсией, можно рассмотреть паттерн матчинг. Мы создаём выражение в Скале, редактируем в Джаве и снова переключаемся на Скалу. Выражение "взорвётся" из паттерн-матчинга в тучу if-ов и обилием синтетических переменных. Что будем делать? Пытаться подогнать паттерн-матчинг и свернуть if-ы? Или бить линейкой по рукам при любой попытке поправить "паттернматчинговое поддерево" не из Скалы?
M>Итак, мы задали некие семантические узлы для Scala, Java, JVM и их отображение. Можем не задавать отображения M>некоторых узлов. Скажем, не задавать отображение для GOTO узла (семантического понятия), который есть в JVM. M>И теперь мы пишем программу. При этом мы можем использовать любые известные системе (описанные во внутреннем M>представлении) семантические узлы. Можем использовать скаловские трейты и абстрактные типы, которых нет в Java. M>Можем использовать Java return и wildcard-ы в типах, которых нет в Scala. Можем использовать GOTO из JVM, M>которого нет ни в Scala ни в Java. В смысле редактирования мы можем использовать всё, что угодно, постольку, M>поскольку оно соответствует констрайнтам заданным во внутреннем представлении. Скажем, во внутреннем представлении M>у нас сказано, что у InfixExpression есть скаляреый под-узел Operator — так мы в этот слот не сможем вставить M>больше одного под-узла, или вставить туда узел типа Expression.
Хм, вот мы берём веточку, переключаемся в JVM и пошли:
Потом переключаемся на Скалу. Отобразит ли оно нам вышеупомянутую веточку в виде:
def foo = {
val baz = new Array[Int](3);
bar(baz, 3);
}
def bar[T](ts : Array[T], t : T) = ts(0) = t;
? Я очень, очень сильно сомневаюсь. Это ведь опять задача декомпиляции.
Но это ещё полбеды. Принимая вывод выше о том, что внутреннее представление будет достаточно низкоуровневое — программировать в этих терминах будет убийственно сложно, примерно как программирование на ассемблере.
M>Теперь о компиляции всего этого бардака M>. ... M>А если мы не сможем трансформировать дерево так, чтоб привести к набору узлов target платформы? M>Сюрприз — выдадим ошибку компиляции.
Да! Именно. Как только AST одного внешнего языка будет достаточно сильно отличаться от AST другого внешнего языка, мы будем получать ошибку компиляции. А это будет очень и очень часто, потому что некоторые локальные конструкции в одном языке могут иметь глобальное действие — на уровне всего AST или его большого куска. Например, директива package, использование макросов или аспектов, использование какого-то типа или объекта повсюду в программе (его изменение может сломать весь остальной код). Если в другом языке нет непосредственного доступа к подобным вещам, то AST языков будут очень сильно различаться, и следовательно преобразование между ними невозможно. Введение промежуточного шага преобразования во внутреннее представление ничуть не облегчит задачу преобразования между AST.
Таким образом завязавшись на один язык будет очень трудно переключаться на другой, следовательно это будут делать очень и очень редко. Будет иметь смысл только в случаях, когда AST языков примерно одинаковы, как скажем для C# и Джавы (и то проблемы, как клеить полноценные дженерики с уничтожаемыми). Как только появляется перекос в какую-либо сторону, автоматически появляются сложности с переводом из менее высокоуровневого языка в более высокоуровневый.
M>Проблема здесь в чём? Проблема в том, что программист должен будет иметь квалификацию лучше, чем M>обычно имеют сейчас. Если сейчас программист на java пишет static и не задумывается о том, M>что при этом реально происходит, и это скомпилируется и будет работать — то программируя M>в SymADE он должен будет понимать всю семантику происходящего, в том числе и понимать, M>почему он неожиданно получить ошибку компиляции используя одновременно static и скаловские M>семантические узлы. Или в крайнем случае, он добавит свой плагин для трансформации дерева, M>который позволит в его конкретном случае таки скомпилировать программу в target платформу.
Подозреваю, что написание таких плагинов будет жосткой задачей, к тому же не имеющей решения в общем виде. Это я возвращаюсь к своим аргументам о невозможности декомпиляции и преобразованиях между сильно разными AST.
M>С другой стороны, программист может иметь и меньшую квалификацию и всё равно работать M>в SymADE. Если ему сказать, или настроить редактор так, чтоб нельзя было использовать M>произвольные узлы (семантические понятия), а только узлы из определённого набора M>(то есть фактически написать некий DSL) — то он и не напорется на проблемы с тем, M>что его программа неожиданно стала выдавать ошибку компиляции. А этот DSL язык может M>быть намного проще, чем Java. И в то же время, его будет вполне хватать для задачь, M>которые должен решать этот малоквалифицированный программист.
Вот именно, посадить его за написание бизнес рулов на DSL, и потом эти скрипты вызвать откуда нибудь. Ну на крайняк распарсить. Как сейчас и делают. Ты же предагаешь этому товарищу загаживать наше дерево, делая ветку на неком DSL, которая потом должна быть преобразована в основной таргет-язык. Здесь будет замена шила на мыло, картинка примерно такая (IR=inner representation):
классический путь:
DSL ----------> DSL_AST ---------> Scala
^ ^
| анализ и генерация, может быть довольно сложным
для обычных DSL это легко, antlr в зубы и вперёд
путь СиМэйд:
DSL -> IR -> Scala
^ ^
| жопа
|
это примерно равно анализу и генерации из классического пути
Мы избавились от парсера и лексера (за нас это сделала СиМэйд), но зато получили очень нетривиальный шаг. Я не прав?
M>Больше того, SymADE будет легче в освоении этим малоквалифицированным программистом M>(или скорее квалифицированным специалистом в своей области, но который не программист - M>скажем, некий менеджер программирующий workflow). Потому как SymADE намного гибче M>в отображении кода с одной стороны, и будет подсказывать неопытному пользователю - M>какие именно конструкции можно вставить конкретно в этом месте. Ему не надо будет M>знать, что объявление функции пишется как "def $name ( $args ) : $return_type". M>Он скажет среде — вставить в это место новый узел, она ему скажет — можно вставить M>объявление метода или поля. Он говорит — мне нужно метод вставить. Ему этот метод M>и вставят. Потом он заполнит поле имени метода, и ему скажут — а теперь вставь M>тип результата, это может быть то-то и то-то. И так далее.
В принципе это я уже где-то видел Примерно такой мастер выдаётся, когда я эклипс прошу добавить новый класс. Здесь задача облегчается тем, что нужно лишь одно направления преобразований от примитивного языка диалог-боксов и графических изображений в таргет-язык. Здесь СиМэйд скорее всего будет себя чувствовать хорошо
M>С точки зрения осовения нового языка (онтологии семантических понятий) это намного M>легче, чем выучивать синтаксис и продиратся через дебри, пока не освоишь этот M>язык более полно. С точки зрения удобства, ну привык он к C-style синтаксису - M>выберет отображалку объявления методов в виде "$return_type $name($args) { ... }", M>а если он привык к паскалевскому синтаксису, он тот-же узел сможет отображать как M>"method $name ($args) : $return_type begin ... end". И ему не надо будет M>напрягаться с изучением нового синтаксиса только потому, что он захотел использовать M>ScalaTrait в своей программе.
Здесь будет всё хорошо, потому что с такими тривиальными заменами, AST одного и AST другого языков будут практически 1-в-1. Задача весьма специфическая, и на моей памяти был только один случай её возникновения. Это когда мы на первом курсе учили Паскаль, а на втором учились программирвать на C. В то время, чтобы снизошло озарение, как работает список на С (построенный на указателях ессно) потребовалось сперва написать аналог на Паскале.
Здравствуйте, Lazy Cjow Rhrr, Вы писали:
LCR>mkizub,
LCR>Сначала небольшое оффтопическое замечание, чтобы потом не отвлекаться: в дженериках Скалы вайлдкарды присутствуют в виде экзистенциальных типов (вернее вайлдкарды являются их частным случаем). Появились не так давно, кажется с версии 2.6.
Ок, интересно, посмотрю сейчас.
LCR>Теперь вернёмся.
M>>Вначале о внутреннем представлении. Всё, что мы с него имеем, это именованые типы семантических узлов, именованые атрибуты и под-узлы этих семантических узлов, минимальные констрайнты (вроде — это необязательный скалярный атрибут, а это вектор под-узлов типа "expression"). M>> ... M>>Правильней было-бы создать некий стандарт на это описание, который будет поддерживаться всеми средами. M>>Так же как есть единый стандарт на текст (включая кодировки).
LCR>Пока всё понятно. Хотя есть сомнения в том, что возможен стандарт на это описание. Так как всегда возможна ситуация, что какая-то фича уже не будет укладываться в стандарт. В данном случае получается, что нам надо будет выбрать внутреннее представление таким образом, что оно будет покрывать и язык Scala, и язык Java и язык опкодов JVM как частные случаи. То есть будет очень низкоуровневым! И каждый новый не укладывающийся в прежние рамки язык будет раздувать и дробить это внутреннее представление. Есть языки, где тела функций отделены от сигнатур, и сигнатуры являются FCO, есть языки где ветки в паттерн-матчинге являются FCO, есть Хаскелл со своей страшной системой типов, есть наконец Epigram, который я даже не представляю как подогнать под Java+Scala+JVM, настолько он другой. Естественно, общая база есть — это лямбда-исчисление. Или система команд x86. Или опкоды LLVM.
LCR>Таким образом, перевод языков во внутреннее представление возможен, хоть и труден. А вот обратный процесс равносилен декомпиляции, и в общем случае не решается.
LCR>Ы? Где у меня поломалась логическая цепочка?
Э-э-э... нигде не поламалась, всё правильно, только это не имеет к SymADE никакого отношения.
Это здорово, что ты так всё расписал. И теперь мне совершенно ясно, в чём именно ты напутал с концепцией.
Ты, как я понял, представляешь себе это как в Nemerle — есть некий код, он макросами
загоняется в набор узлов из внутреннего представления поддерживаемого Nemerle, и потом
компиляется. Попутно давая возможность обратного преобразования этого внутреннего представления
в исходных код. То есть макросы стали чем-то вроде линз.
Всё обстоит прямо противоположным образом.
Если сравнивать, скажем с XML. У XML есть внутреннее представление. Упрощённо, это
text, element, attribute, entity и набор констрайнтов которые можно в этих entity задавать
(например, можно задать, что element с именем phonebook содержит список элементов
с именем entry, и каждый элемент с именем entry может содержать только один элемент
с именем name и один элемент с именем phone, а элементы с именем name и phone
содержат только текст). Всё, это внутреннее представление XML-я. А потом, при помощи
DTD, мы задаём конкретный набор element-ов и их attribute-ов, это уже будет
конкретный язык, онтология.
Аналогично, я под внутренним представлением имел в виду именно это — набор того, что
мы можем задавать относительно свойств семантического узла. Это его тип (аналог
tag-name в XML, но в отличии от XML типы наследуются, как в OOP). Это список
аттрибутов узла (как и в XML — именованный, но в отличии от него — типизированный,
а не просто текст). Это список child узлов (в отличии от XML — именованный
список).
Именно об этом внутреннем представлении я говорил, что его надо-бы стандартизировать.
Так же как стандартизирован XML. Но стандартизирован XML, а не каждый конкретный
DTD надо стандартизировать.
Далее.
Мы можем определять новые типы семантических узлов, и их онтологии. То есть язык это
некий аналог DTD в XML-е. Его, конечно, можно делать как закрытым (то есть
нельзя вставлять узлы из другого языка), а можно и открытым (как в XML — можно
вставлять какие угодно элементы и атрибуты, если это не запрещено констрайнтами
в DTD).
И главное — программа это и есть это дерево узлов, в их изначальной форме,
как программист их вставил. Она не преобразовывается автоматом в некий фиксированный
внутренний набор узлов, поддерживаемых компилятором, как это делают макросы Nemerle.
Трансформация дерева в target набор узлов — это и есть компиляция. Если тебе
компилятор трансформировал твоё дерево — ты, конечно, можешь его редактировать
дальше, но зачем? Ты же не редактируешь ассемблер, полученный из компиляции
С-шного кода. И не редактируешь C-шный код полученный из парсера написанного
на yacc.
В чём фишка, зачем нужно отказываться от единого внутреннего представления,
куда всё приводится, как в Nemerle? Для того, чтоб поддерживать разные
target платформы.
Скажем, если мы имеем unerasable type arguments у generic типа. Мы его
можем скомпилировать в Java, вставляя hidden аргумент в конструктор и сохраняя
его в final поле. Скажем, преобразовать
@unerasable class Vector<E> {
E[] data;
Vector(int size) { data = new E[size]; }
}
...
new Vector<String>(5);
в
public class TypeInfo {
final Class cls;
TypeInfo(Class cls) { this.cls = cls; }
Object[] makeArray(int sz) { return this.cls.newArray(sz); }
}
class Vector {
public static class VectorTypeInfo extends TypeInfo {
TypeInfo arg$E;
VectorTypeInfo(Class cls, TypeInfo arg$E) {
super(cls);
this.arg$E = arg$E;
}
}
private final VectorTypeInfo $typeinfo
Object[] data;
Vector(int size, VectorTypeInfo $typeinfo) {
this.$typeinfo = $typeinfo;
data = this.$typeinfo.arg$E.newArray(size);
}
}
...
new Vector(5, new VectorTypeInfo(Vector.class,String.class))
Уф. Приблизительно так оно делается у меня. И работает под JVM, хотя в ней
нет ран-тайм информации об аргументах generic типов.
А вот для .NET всей этой кодогенерации не нужно!!! Там мы так и оставим,
new Vector<String>(5), и оно будет работать. Потому как CLR это понимет,
и информацию о типах запомнит. И старый код будет работать эффективней
на CLR, но сможет скопилироваться и под JVM.
А если у нас фиксированное внутреннее представление, то эффективно под CLR
мы компилировать не сможем. Оно будет всё так-же вставлять ненужные
hidden параметры и генерировать ненужные классы. Потому как оно уже
преобразовалось в это внутреннее представление, а в нём нет понятия
"взять аргумент типа в рантайме". Или нам надо будет менять внутреннее
представление компилятора, а это как правило очень и очень сложно.
В SymADE мы просто напишем плагин, который будет трансформировать
дерево (в процессе компиляции), или не трансформировать, если не нужно.
Мы не переключаемся между языками. Мы в одно и то-же дерево (то есть в код)
можем вставлять семантические узлы из разных онтологий. В коде мы можем
вставлять и scala trait-ы и java interface-ы, и можем вставить
call-with-recursion, и можем вставить match. И оно скомпилируется
в target платформу, если есть плагины, которые смогут трансформировать
call-with-recursion в loop, и match в набор switch/if/else.
Или не трансформировать, если наша target платформа уже поддерживает
call-with-recursion или pattern-matching. А если такого плагина
нет — его можно написать, для данной конкретной target платформы,
или некий обобщённый — скажем, преобразовать match в набор if/else-ов,
и преобразовать if/else в match, и выбирать эти плагины при компиляции
в зависимости от того, что для target платформы является родным,
if-else или match, loop или call-with-recursion.
Здравствуйте, Sinclair, Вы писали:
S>Это неработающая утопия. Проблема разработки софта — вовсе не в синтаксисе. Синтаксис — это такая вещь, которая изучается за 15 минут. S>Собственно разработка состоит в том, чтобы вставлять "в дерево" то, что нужно, в нужном порядке. Вот изучение этого "того, чего нужно" и представляет основную сложность.
Это заблуждение. Это всё равно, что сказать — я могу выучить алфавит за 15 минут, и значит я смогу читать текст
с этим алфавитом. Ну сможешь. А толку? Человек учится читать годами, он распознаёт слова не по буквам, а словами
и даже целыми строками. И синтаксис языка программирования после 10 лет кодинга распознаётся так-же
автоматом, а не "по буквам" через 15 минут.
S>А ты по какой-то причине считаешь, что боль — в продирании через дебри синтаксиса. Ну вот у Java и C# синтаксис близкий к С++. И что? Основная боль разработчиков C++ при миграции в управляемые среды — непонимание того, куда девать деструкторы.
Я не писал о миграции С++ в ява. Я писал об освоении нового языка.
S>Для того, чтобы применять ScalaTrait в своей программе, нужно сначала понять, что такое trait. Если этого не понять, то никакой синтаксис не поможет — будь то C, Pascal, или Basic. А если понять — то синтаксис никаких проблем не вызовет.
Для того, чтоб его там применять — надо вначале иметь компилятор, который его поймёт.
Здравствуйте, mkizub, Вы писали: M>Это заблуждение. Это всё равно, что сказать — я могу выучить алфавит за 15 минут, и значит я смогу читать текст M>с этим алфавитом. Ну сможешь. А толку? Человек учится читать годами, он распознаёт слова не по буквам, а словами M>и даже целыми строками.
Для того, чтобы "распознавать слова", слова надо сначала знать. А ты, фактически, предполагаешь, что от переписывания в другой алфавит станет понятнее.
Ну вот тебе "переписанный" текст:
Что, стало сильно понятнее, чем во вражеском алфавите? M>И синтаксис языка программирования после 10 лет кодинга распознаётся так-же M>автоматом, а не "по буквам" через 15 минут.
Лично я за 10 лет научился распознавать синтаксисы далеко не одного языка. Наверное, у меня какой-то быстрообучаемый автомат.
M>Для того, чтоб его там применять — надо вначале иметь компилятор, который его поймёт.
Это как раз самое простое. В компиляторе парсер — далеко не самое сложное. Те "трансформации", которые ты предлагаешь оставить в качестве домашнего упражнения, как раз и являются самым сложным. Ты случайно Аппеля не читал? Серию про modern compiler?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.