Nie planuję pisać kompilatora w najbliższej przyszłości; nadal jestem dość zainteresowany technologiami kompilatora i tym, jak można to ulepszyć.
Zaczynając od języków skompilowanych, większość kompilatorów ma dwa poziomy błędów: ostrzeżenia i błędy, z których pierwszy to najczęściej niekrytyczne rzeczy, które należy naprawić, oraz błędy wskazujące przez większość czasu, że niemożliwe jest wygenerowanie maszyny (lub bajtu) kod z wejścia.
Chociaż jest to dość słaba definicja. W niektórych językach, takich jak Java, niektóre ostrzeżenia są po prostu niemożliwe do usunięcia bez zastosowania @SuppressWarning
dyrektywy. Ponadto Java traktuje niektóre niekrytyczne problemy jako błędy (na przykład nieosiągalny kod w Javie powoduje błąd z powodu, który chciałbym wiedzieć).
C # nie ma takich samych problemów, ale ma kilka. Wygląda na to, że kompilacja zachodzi w kilku przebiegach, a niepowodzenie przejścia uniemożliwi dalsze wykonywanie. Z tego powodu liczba błędów pojawiających się w przypadku niepowodzenia kompilacji jest często rażąco niedoceniana. Przy jednym uruchomieniu może to oznaczać, że masz dwa błędy, ale kiedy je naprawisz, może otrzymasz 26 nowych.
Kopanie w C i C ++ po prostu pokazuje złą kombinację słabości diagnostycznych kompilacji Java i C # (choć może bardziej trafne jest stwierdzenie, że Java i C # po prostu poszły z każdą połową problemów). Niektóre ostrzeżenia naprawdę powinny być błędami (na przykład, gdy nie wszystkie ścieżki kodu zwracają wartość), a mimo to są ostrzeżeniami, ponieważ, jak sądzę, w czasie, gdy pisali standard, technologia kompilatora nie była wystarczająco dobra, aby tworzyć tego rodzaju kontrole obowiązkowe. W tym samym duchu kompilatory często sprawdzają więcej niż mówi standard, ale nadal używają „standardowego” poziomu błędu ostrzegawczego dla dodatkowych ustaleń. I często kompilatory nie zgłaszają od razu wszystkich błędów, które mogą znaleźć; pozbycie się wszystkich może zająć kilka kompilacji. Nie wspominając o tajemniczych błędach, które kompilatory C ++ lubią pluć,
Dodając teraz, że wiele systemów kompilacji można konfigurować w celu zgłaszania awarii, gdy kompilatory emitują ostrzeżenia, otrzymujemy dziwną mieszankę: nie wszystkie błędy są krytyczne, ale niektóre ostrzeżenia powinny; nie wszystkie ostrzeżenia są zasłużone, ale niektóre są wyraźnie tłumione bez dalszej wzmianki o ich istnieniu; a czasami wszystkie ostrzeżenia stają się błędami.
Języki nieskompilowane nadal mają nieprzyjemny raport błędów. Literówki w Pythonie nie będą zgłaszane, dopóki kod nie zostanie faktycznie uruchomiony, i tak naprawdę nigdy nie można wykopać więcej niż jednego błędu naraz, ponieważ skrypt przestanie działać po tym, jak go napotka.
Z drugiej strony PHP ma kilka mniej lub bardziej znaczących poziomów błędów i wyjątków. Błędy analizy są zgłaszane pojedynczo, ostrzeżenia są często tak złe, że powinny przerwać skrypt (ale nie domyślnie), powiadomienia naprawdę często pokazują poważne problemy logiczne, niektóre błędy naprawdę nie są wystarczająco złe, aby zatrzymać skrypt, ale nadal tak, jak zwykle w przypadku PHP, jest tam kilka naprawdę dziwnych rzeczy (dlaczego, do cholery, potrzebujemy poziomu błędu dla błędów krytycznych, które nie są tak naprawdę fatalne ? E_RECOVERABLE_E_ERROR
, mówię do ciebie).
Wydaje mi się, że każda implementacja raportowania błędów kompilatora, o której myślę, jest zepsuta. To wielka szkoda, ponieważ wszyscy dobrzy programiści nalegają na to, jak ważne jest prawidłowe radzenie sobie z błędami, a jednocześnie nie mogą zdobyć własnych narzędzi.
Jak myślisz, jaki powinien być właściwy sposób zgłaszania błędów kompilatora?
źródło
Odpowiedzi:
Twoje pytanie nie wydaje się dotyczyć tego , w jaki sposób zgłaszamy błędy kompilatora - chodzi raczej o klasyfikację problemów i co z nimi zrobić.
Jeśli zaczniemy od założenia, że dychotomia ostrzeżenie / błąd jest poprawna, zobaczmy, jak dobrze możemy na tym opierać się. Jakieś pomysły:
Różne „poziomy” ostrzeżenia. Wiele kompilatorów sortuje to zaimplementować (na przykład GCC ma wiele przełączników do konfigurowania dokładnie tego, o czym będzie ostrzegał), ale potrzebuje pracy - na przykład, raportowania o tym, jak poważne jest zgłaszane ostrzeżenie i możliwości ustawiania „ostrzeżeń” są błędami ”tylko w przypadku ostrzeżeń powyżej określonego poziomu ważności.
Rozsądna klasyfikacja błędów i ostrzeżeń. Błąd należy zgłaszać tylko wtedy, gdy kod nie spełnia specyfikacji, a zatem nie można go skompilować. Nieosiągalne instrukcje, choć prawdopodobnie błąd kodowania, powinny być ostrzeżeniem , a nie błędem - kod jest nadal „poprawny”, a istnieją uzasadnione przypadki, w których można by skompilować z nieosiągalnym kodem (na przykład szybkie modyfikacje do debugowania) .
Teraz rzeczy, z którymi się nie zgadzam:
Dokładamy wszelkich starań, aby zgłosić każdy problem. Jeśli wystąpi błąd, psuje kompilację. Kompilacja jest zepsuta. Kompilacja nie będzie działać, dopóki ten błąd nie zostanie naprawiony. Dlatego lepiej jest natychmiast zgłosić ten błąd, niż „kontynuować”, aby spróbować zidentyfikować wszystko „źle” za pomocą kodu. Zwłaszcza, gdy wiele z tych rzeczy jest prawdopodobnie spowodowanych początkowym błędem.
Twój konkretny przykład ostrzeżenia, które powinno być błędem. Tak, to prawdopodobnie błąd programisty. Nie, nie powinno to zepsuć kompilacji. Jeśli wiem, że dane wejściowe do funkcji zawsze zwracają wartość, powinienem móc uruchomić kompilację i wykonać kilka testów bez konieczności dodawania tych dodatkowych kontroli. Tak, powinno to być ostrzeżenie. I to cholernie poważne. Ale nie powinno to samo z siebie przerywać kompilacji, chyba że kompiluje się z ostrzeżeniami-są-błędami.
Myśli?
źródło
Jednym z poruszonych przez ciebie problemów było niekompletne zgłaszanie błędów - np. Zgłoszenie 2 błędów, a kiedy je naprawisz, dostaniesz więcej.
Jest to (w dużej mierze) kompromis ze strony autora kompilatora. W zależności od tego, jaki błąd popełniłeś, kompilatorowi bardzo łatwo jest źle zrozumieć, co robisz , na tyle, że zaczyna zgłaszać błędy, które mają niewiele wspólnego z rzeczywistością. Na przykład rozważ prostą literówkę, w której
itn x;
zamiast czegoś masz coś takiegoint x;
. Jeśli nie zrobiłeś czegoś innego, co sprawia, żeitn
coś znaczy, to zostanie to zgłoszone jako błąd. Na razie jest to w porządku, ale teraz zastanów się, co będzie dalej - kompilator patrzy na wiele kodów, które próbują użyćx
jako zmiennej. Czy A) powinien przestać i pozwolić Ci to naprawić, lub B) wyrzucić 2000 błędówerror: "x": undeclared identifier
lub coś w tej kolejności? Rozważ inną możliwość:To kolejna dość oczywista literówka - oczywiście powinna to być
{
zamiast[
. Kompilator może dość łatwo powiedzieć ci tę część - ale czy powinien następnie zgłosić błąd w przypadkux=1;
powiedzenia czegoś takiegoerror: statement only allowed inside a function
?Zauważ, że są to nawet dość trywialne problemy - znacznie gorsze są łatwe do znalezienia (zwłaszcza, jak większość z nas wie, kiedy wchodzisz w szablony C ++). Najważniejsze jest to, że pisarz kompilatora zwykle utknął w próbie kompromisu między zgłaszaniem fałszywych błędów (tj. Zgłaszaniem czegoś jako błędu, nawet jeśli jest w porządku) a nie zgłaszaniem prawdziwych błędów. Istnieją pewne podstawowe zasady, których należy przestrzegać, aby uniknąć zbytniego popełniania błędów w obu kierunkach, ale prawie żadna z nich nie jest bliska ideału.
Innym problemem, o którym wspominałeś był Java i
@SupressWarning
. Jest to zupełnie inne od powyższego - naprawienie tego byłoby dość proste. Jedynym powodem, dla którego nie zostało to naprawione, jest to, że nie pasuje to do podstawowego „charakteru” Javy - tzn. Ich zdaniem „to nie jest błąd, to funkcja”. Mimo że zwykle jest to żart, w tym przypadku ludzie są tak wprowadzeni w błąd, że naprawdę wierzą, że to prawda.Problem, o którym wspominasz w C i C ++ ze ścieżkami kodu, które nie zwracają wartości, tak naprawdę nie pozwala na proste kompilatory. Pozwala to na dekady istnienia kodu , którego część nikt nie chce naprawić, dotknąć, a nawet przeczytać. Jest pradawny i brzydki, ale działa, i nikt nie chce niczego poza tym, aby mógł dalej działać. Na dobre lub złe, komitety językowe są mocno utkwione w utrzymywaniu wstecznej kompatybilności, więc nadal dopuszczają rzeczy, których nikt tak naprawdę nie lubi - ale niektórzy ludzie (przynajmniej myślą, że potrzebują).
źródło
csc
poddaje.