Есть разница между компиляцией процедурного кода (в процедурный же) и декларативного (в процедурный).
В первом случае мы знаем, что код выполняется как нами задумано, хоть и на другом языке (машинном коде). Зная в каком месте ошибка, нетрудно найти соответствие в исходном высокоуровневом коде.
В случае же декларативного языка мы часто понятия не имеем, как оно выполняется. И соответствие порождённого кода исходному может быть весьма отдалённым. Я неоднократно имел опыт отладки кода от YACC, и это малоприятное занятие. 😀
Но это всё объяснения, а медицинский факт тот, что активность вокруг asdlGen прекратилась двадцать лет назад. Очевидно, невостребовано.
Когда я писалъ кодъ на Скалѣ, мнѣ очень рѣдко нуженъ былъ отладчикъ. А вѣдь это JVM + JIT compiler, тамъ довольно трудно было бы найти соотвѣтствiе кода на Скалѣ и выполняемаго машиной кода. Но когда отладчикъ былъ нуженъ, то просто ставилъ breakpoint въ кодѣ и потомъ вычислялъ выраженiя и смотрѣлъ на текущiя значенiя аргументовъ и все. Почему то же самое нельзя сдѣлать для декларативныхъ грамматикъ?
Въ случаѣ YACC отвѣтъ можетъ быть въ томъ, что алгоритмъ LALR-парсинга генерируетъ нѣкiй сложный push-down автоматъ. Послѣ чего непонятно, какiе фрагменты кода этого автомата соотвѣтствуютъ грамматикѣ, и что дѣлать, если результатъ парсинга неправильный. Ошибки парсинга тоже тамъ очень плохо сообщаются, потому что алгоритмъ LALR хорошъ лишь для случаевъ, когда входной текстъ парсится безъ ошибокъ.
Замѣтимъ, что генерируемый YACC кодъ автомата никогда не вызоветъ сбоевъ типа segmentation fault, тамъ никогда не будетъ забыта иницiализацiя перемѣнныхъ. Тамъ не будетъ примитивныхъ ошибокъ. Ошибки будутъ болѣе высокаго уровня, на уровнѣ спецификацiи.
Можно ли было бы рѣшить проблемы съ YACC, если бы:
- Существовалъ бы отладчикъ, который показывалъ бы, гдѣ въ декларативной грамматикѣ "мы сейчасъ находимся" во время парсинга, - Если бы ошибки парсинга сообщались въ терминахъ декларативной грамматики, - Если бы никогда не было бы непонятныхъ "shift/reduce conflict", а проблемы декларативной грамматики сообщались бы пользователю въ терминахъ этой грамматики? ("входной текстъ XYZ неоднозначенъ изъ-за правилъ такихъ-то")
Есть нѣсколько декларативныхъ системъ, гдѣ вродѣ какъ нѣтъ такихъ проблемъ.
Первый основной примѣръ - синтаксисъ для ариѳметики. Мы пишемъ кодъ "a + b * c - d" и не задумываемся. Мы больше не пишемъ тестовъ для такого кода, чтобы провѣрить, что b * c было вычислено сперва, и лишь потомъ сумма; или что память была вовремя распредѣлена и освобождена; или что первый былъ плюсъ, а второй минусъ, а не наоборотъ. Мы не отлаживаемъ такой кодъ, мы не ставимъ тамъ breakpoint и не дѣлаемъ логи. Такой кодъ просто очевидно работаетъ и все. Мы уже привыкли, что это такъ во всѣхъ языкахъ. Но это было не всегда такъ. Это на самомъ дѣлѣ всеобъемлющая декларативная система для ариѳметики. Она порождаетъ ассемблерный кодъ или байтъ-кодъ, который не всегда прямо соотвѣтствуетъ написанному декларативному коду. Но это не вызываетъ почему-то проблемъ.
Второй примѣръ - языкъ SQL. Тамъ пишется декларативный кодъ "select blah from foo where bar = qux" и дальше это конвертируется очень сложнымъ образомъ въ "планы запросовъ" (query plan), индексированiе и т.д. Но мы никогда не отлаживаемъ такой кодъ путемъ декомпилированiя. Почему-то это не требуется.
no subject
В первом случае мы знаем, что код выполняется как нами задумано, хоть и на другом языке (машинном коде). Зная в каком месте ошибка, нетрудно найти соответствие в исходном высокоуровневом коде.
В случае же декларативного языка мы часто понятия не имеем, как оно выполняется. И соответствие порождённого кода исходному может быть весьма отдалённым. Я неоднократно имел опыт отладки кода от YACC, и это малоприятное занятие. 😀
Но это всё объяснения, а медицинский факт тот, что активность вокруг asdlGen прекратилась двадцать лет назад. Очевидно, невостребовано.
no subject
Въ случаѣ YACC отвѣтъ можетъ быть въ томъ, что алгоритмъ LALR-парсинга генерируетъ нѣкiй сложный push-down автоматъ. Послѣ чего непонятно, какiе фрагменты кода этого автомата соотвѣтствуютъ грамматикѣ, и что дѣлать, если результатъ парсинга неправильный. Ошибки парсинга тоже тамъ очень плохо сообщаются, потому что алгоритмъ LALR хорошъ лишь для случаевъ, когда входной текстъ парсится безъ ошибокъ.
Замѣтимъ, что генерируемый YACC кодъ автомата никогда не вызоветъ сбоевъ типа segmentation fault, тамъ никогда не будетъ забыта иницiализацiя перемѣнныхъ. Тамъ не будетъ примитивныхъ ошибокъ. Ошибки будутъ болѣе высокаго уровня, на уровнѣ спецификацiи.
Можно ли было бы рѣшить проблемы съ YACC, если бы:
- Существовалъ бы отладчикъ, который показывалъ бы, гдѣ въ декларативной грамматикѣ "мы сейчасъ находимся" во время парсинга,
- Если бы ошибки парсинга сообщались въ терминахъ декларативной грамматики,
- Если бы никогда не было бы непонятныхъ "shift/reduce conflict", а проблемы декларативной грамматики сообщались бы пользователю въ терминахъ этой грамматики? ("входной текстъ XYZ неоднозначенъ изъ-за правилъ такихъ-то")
no subject
Первый основной примѣръ - синтаксисъ для ариѳметики. Мы пишемъ кодъ "a + b * c - d" и не задумываемся. Мы больше не пишемъ тестовъ для такого кода, чтобы провѣрить, что b * c было вычислено сперва, и лишь потомъ сумма; или что память была вовремя распредѣлена и освобождена; или что первый былъ плюсъ, а второй минусъ, а не наоборотъ. Мы не отлаживаемъ такой кодъ, мы не ставимъ тамъ breakpoint и не дѣлаемъ логи. Такой кодъ просто очевидно работаетъ и все. Мы уже привыкли, что это такъ во всѣхъ языкахъ. Но это было не всегда такъ. Это на самомъ дѣлѣ всеобъемлющая декларативная система для ариѳметики. Она порождаетъ ассемблерный кодъ или байтъ-кодъ, который не всегда прямо соотвѣтствуетъ написанному декларативному коду. Но это не вызываетъ почему-то проблемъ.
Второй примѣръ - языкъ SQL. Тамъ пишется декларативный кодъ "select blah from foo where bar = qux" и дальше это конвертируется очень сложнымъ образомъ въ "планы запросовъ" (query plan), индексированiе и т.д. Но мы никогда не отлаживаемъ такой кодъ путемъ декомпилированiя. Почему-то это не требуется.