Closed Mazdaywik closed 3 years ago
С недавних пор (#96) в языке стали поддерживаться имена на маленькую букву. А значит, команды print arg
, print vf
и другие уже становятся неоднозначными. Есть предложение служебные понятия начинать со знака $
:
print $arg
print $callee
print $viewfield
Задача вполне подходит на курсовой проект.
Предыдущая задача про отладчик — #49.
Также не хватает неинтерактивного режима, когда отладчик читает команды из заданного пользователем файла. Например, можно создать такой файл:
trace Func1 > log.txt
trace Func2 > log.txt
, указать его в опции командной строки ++enable+debugger=debug.txt
и программа отработает самостоятельно, при её завершении будет создан файл log.txt
с трассировками двух функций.
Никто не взял как тему курсового.
Эта задача опять выносится на курсовую работу по компиляторам.
К слову, в отладчике что-то сломалось, он останавливается не по breakpoint’у, а в какие-то рандомные моменты через десяток шагов. Это тоже надо починить.
Задача не была выбрана в качестве курсовой.
Не, не надо её на ВКР. Она больше подходит для курсовой.
На летнюю практику этот отладчик достаточно заставить работать (на тройку). Расширение его новыми командами желательно (оценка выше тройки), но не обязательно.
Студент делал другое задание на практику, вне Рефала-5λ.
@Santalov, поставьте, пожалуйста галочки против тех пунктов, которые Вы сделали.
@Santalov, а комментарии Вы не прочитали: https://github.com/bmstu-iu9/refal-5-lambda/issues/85#issuecomment-324217770, https://github.com/bmstu-iu9/refal-5-lambda/issues/85#issuecomment-410936966. 🙂
Извините, не заметил. Доработаю. Насчет #85(comment)
, не очень понял, зачем это нужно, если имена переменных начинаются с типа и всегда содержат точку, а команды отладчика не содержат точек.
Насчёт
#85(comment)
, не очень понял, зачем это нужно, если имена переменных начинаются с типа и всегда содержат точку, а команды отладчика не содержат точек.
Я уже сам забыл, что имел ввиду в этом комментарии. Наверное, чтобы можно было писать $vf
без print
, как и в случае переменных.
Когда будет время, создайте, пожалуйста, багу про ошибку с условиями.
По поводу комментария https://github.com/bmstu-iu9/refal-5-lambda/issues/85#issuecomment-410936966 и коммита bca16da26c4da1eb996df69427b639a1768907b7.
Дурная голова ногам покоя не даёт, в смысле дурной руководитель — исполнителям. 🤦♂️ Опция командной строки ++enable-debugger=
не поддерживается уже давно (вызов find_debugger_flag()
удалён в 50ec68f627c88cb3c3c4b5fc077c651f3a162194). Вместо неё используются параметры из @refal-5-lambda-diagnostics.ini
. А сама функция find_debugger_flag()
осталась в исходниках по ошибке.
Если посмотреть на коммит, где был удалён вызов этой функции:
видно, что после получения позиции флага этот флаг из массива аргументов удалялся. Иначе приложение, читающее аргументы командной строки, об эту опцию бы «спотыкалось».
Я в прошлую субботу указал на комментарий, но не догадался уточнить, что эту функцию следовало реализовать иначе. 🤦♂️ Следовало добавить параметр debugger_script
в @refal-5-lambda-diagnostics.ini
. Для этого нужно поправить refalrts-diagnostics-defs.h
и refalrts-diagnostics-initializer.cpp
. Лучше всего добавить параметр в refalrts::debugger::create_debugger(VM *vm, const char *script);
и поле debugger_script
в DiagnosticConfig
.
Ай-нанэ-нанэ:
D:\Mazdaywik\Documents\Refal-5-lambda\autotests>run 1-dry-run.sref
Prepare common prefix...
+Linking (+ natives) ../src/lib\refalrts.rasl
+Linking (+ natives) ../src/lib/debug\refalrts-debugger.rasl
+Linking (+ natives) ../src/lib/debug\refalrts-diagnostic-initializer.rasl
+Linking (+ natives) ../src/lib\refalrts-dynamic.rasl
+Linking (+ natives) ../src/lib\refalrts-functions.rasl
+Linking (+ natives) ../src/lib\exe\refalrts-main.rasl
+Linking (+ natives) ../src/lib/debug\refalrts-profiler.rasl
+Linking (+ natives) ../src/lib\refalrts-vm.rasl
+Linking (+ natives) ../src/lib\refalrts-vm-api.rasl
+Linking (+ natives) ../src/lib/platform-Windows\refalrts-platform-specific.rasl
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
../src/lib\refalrts.cpp:
../src/lib/debug\refalrts-debugger.cpp:
Warning W8057 ../src/lib/debug\refalrts-debugger.cpp 716: Parameter 'callee' is never used in function RefalDebugger::is_debug_stop(Node *,RefalFunction *)
Error E2291 ../src/lib/debug\refalrts-debugger.cpp 919: } expected in function RefalDebugger::trace_option(Cmd &,FILE *)
Error E2034 ../src/lib/debug\refalrts-debugger.cpp 921: Cannot convert 'FILE *' to 'FileAndName' in function RefalDebugger::trace_option(Cmd &,FILE *)
Error E2141 ../src/lib/debug\refalrts-debugger.cpp 921: Declaration syntax error in function RefalDebugger::trace_option(Cmd &,FILE *)
Error E2139 ../src/lib/debug\refalrts-debugger.cpp 921: Declaration missing ; in function RefalDebugger::trace_option(Cmd &,FILE *)
Warning W8004 ../src/lib/debug\refalrts-debugger.cpp 921: 'file' is assigned a value that is never used in function RefalDebugger::trace_option(Cmd &,FILE *)
Warning W8057 ../src/lib/debug\refalrts-debugger.cpp 921: Parameter 'out' is never used in function RefalDebugger::trace_option(Cmd &,FILE *)
Error E2190 ../src/lib/debug\refalrts-debugger.cpp 921: Unexpected }
Error E2141 ../src/lib/debug\refalrts-debugger.cpp 922: Declaration syntax error
Error E2190 ../src/lib/debug\refalrts-debugger.cpp 923: Unexpected }
Warning W8057 ../src/lib/debug\refalrts-debugger.cpp 997: Parameter 'skeleton' is never used in function RefalDebugger::print_view_field_option(FILE *,bool,bool)
*** 7 errors in Compile ***
../src/lib/debug\refalrts-diagnostic-initializer.cpp:
../src/lib\refalrts-dynamic.cpp:
../src/lib\refalrts-functions.cpp:
../src/lib\exe\refalrts-main.cpp:
../src/lib/debug\refalrts-profiler.cpp:
../src/lib\refalrts-vm.cpp:
../src/lib\refalrts-vm-api.cpp:
../src/lib/platform-windows\refalrts-platform-specific.cpp:
Исправил проблемы с Borland C++ Compiler 5.5.1.
На данный момент отладчик поддерживает отображение текущего вызова (
print call
,print callee
,print arg
), переменных в текущем вызове (vars
,print t.Var
,t.Var
), переходы на следующий шаг (step
) и до полного завершения текущего вызова (next
). Точки останова можно ставить на имя функции (при этом одноимённые локальные функции разных файлов не различаются) либо на номер шага. Есть и другие возможности, которые не имеют прямого отношения к текущей задаче.Это неплохая функциональность, но её мало. Помимо отображения текущего вызова нужно ещё и понимание контекста этого вызова. Что влечёт как минимум печать всего поля зрения:
Но поле зрения может быть громадным, да и не наглядным. Нужна более узкая выжимка данных. Что-то вроде стека вызовов.
Классического стека вызовов в Рефале нет, вместо него есть поле зрения, переписываемое на каждом шаге. И ближайшим аналогом может быть список функций, подлежащих вызову после завершения текущей. Но контекст вызова функции — это не только те функции, которые будут вычисляться после текущей, но и функция, которая потребит результат вычисления текущей. Например, для поля зрения
после выполнения функции
H
будет вызвана функцияI
, но контекст её вызова — функцияG
. Аналогично, послеG
будет вызванаJ
, но нам может быть интересен вызовG
как аргумент функцииF
.Следовательно, нужна команда трассировки стека (назовём её по аналогии с GDB,
backtrace
,bt
), которая будет отображать стек вызовов как с функциями после текущей, так и с функциями вокруг текущей.Введём обозначения. Будем обозначать следующую функцию, на которую будет передано управление как
@N
, гдеN
— порядковый номер, объемлющую функцию как^N
. При этом текущий вызов будет обозначаться одновременно как@0
и^0
. В примере выше@1
будет ссылаться на вызовI
,^1
будет ссылаться на вызовG
. Полная трассировка стека (примерный вывод дляbacktrace
) будет выглядеть так:Ссылки на вызовы
@N
,^N
можно использовать в командеprint
(распечатывают соответствующий функциональный вызов), а также на них можно ставить точки останова. Точки останова можно отображать в трассировке стека:С точки зрения эффективности, поиск точек
@N
выполняется эффективно (просто идём по списку вызовов), но точки^N
придётся искать, перебирая поле зрения в обратном направлении. Если это окажется медленным, то придётся придумывать что-нибудь для оптимизации.Можно заметить, что команда
next
в этом случае оказывается эквивалентной паре командbreakpoint @1
,run
. Идея благодатная, и она развивается в расширение синтаксиса командыnext
. А именно, командаnext ???
в некотором смысле эквивалентна паре командbreakpoint ???
,run
. При этом если использовалась командаnext FuncName
, то воображаемая точка останова не добавляется в таблицу точек останова, как если бы использовалась явная командаbreakpoint FuncName
.Если во время выполнения команды
next
илиnext ???
произойдёт останов по другой причине (превышение лимита памяти, точка останова), то продолжить движение к следующей точке можно командойnext continue
илиnext c
(илиn c
,nc
).Отладчик должен давать пользователю информацию, полезную для отладки. А для этого нужно выводить читабельные сообщения. А читабельность понятие растяжимое. Распечатка выражения в несколько строк с отступами позволяет наглядно увидеть структуру. Однако, распечатка выражения в одну строку экономит вертикальное место на экране.
Полный дамп поля зрения позволяет узнать всё, но может выдать слишком много информации. Трассировка стека позволяет увидеть такую выжимку, как порядок вызова функций, но по ней невозможно всё узнать о соотношении между различными вызовами (видно, в какие функции вложен текущий, но не видны соотношения между другими вызовами). Компромиссом между ними было бы скелетное отображение — дамп поля зрения (или какого-нибудь вызова
@N
,^N
), в котором присутствуют только скобки вызова без обрабатываемых данных (в примере выше было скелетное отображение).Интеллектуальное отображение, когда сама среда выбирает оптимальный режим, во-первых, сложно в реализации, во-вторых, всё равно не даст 100%-ного предсказания того, что нужно пользователю. Поэтому предлагается более простой вариант: пользователь выбирает режимы отображения. Режимы доступны следующие:
oneline
— вывод выражения в одну строку,multiline
— вывод выражения в несколько строк,skeleton
— скелетное отображение,full
— полное отображение. Вышеперечисленные слова — это, во-первых, самостоятельные команды. Напечатав их, можно глобально установить выбранный режим. Во-вторых, их можно использовать как префиксы для командprint
,s.varname
иvars
:Префиксов может быть сколько угодно, хотя на практике больше двух задавать бессмысленно.
Ну и раз есть режимы, потребуется команда
mode
, отображающая текущие установки.Другие мелкие улучшения:
list
(вместо текущейprint
) для вывода списков точек останова и трассировок,.
бессмысленна — её следует заменить на команду «пустая строка».Итого:
backtrace
,next
,oneline
,multiline
,skeleton
,full
,list
,list trace
,