В Perl есть блоки BEGIN, которые запускают пользовательский код Perl во время компиляции. Этот код может повлиять на смысл другого компилируемого кода, что делает «невозможным» разбор Perl.
Например, код:
sub foo { return "OH HAI" }
"действительно":
BEGIN {
*{"${package}::foo"} = sub { return "OH HAI" };
}
Это означает, что кто-то может написать на Perl так:
BEGIN {
print "Hi user, type the code for foo: ";
my $code = <>;
*{"${package}::foo"} = eval $code;
}
Очевидно, что ни один инструмент статического анализа не может угадать, какой код собирается ввести здесь пользователь. (И если пользователь скажет sub ($) {}
вместо sub {}
, это даже повлияет на то, как вызовы foo
интерпретируются в остальной части программы, что может привести к сбою синтаксического анализа.)
Хорошая новость заключается в том, что невозможные случаи очень краеугольные; технически возможно, но почти наверняка бесполезно в реальном коде. Так что, если вы пишете инструмент статического анализа, это, вероятно, не доставит вам проблем.
Честно говоря, у каждого достойного языка есть эта проблема или что-то подобное. В качестве примера бросьте ваш любимый код-проходчик на этот код Lisp:
(iter (for i from 1 to 10) (collect i))
Вы, вероятно, не можете предсказать, что это цикл, который создает список, потому что макрос iter
непрозрачен, и для его понимания потребуются специальные знания. Реальность такова, что это раздражает в теории (я не могу понять свой код, не запустив его или, по крайней мере, не запустив макрос iter
, который никогда не перестанет выполняться с этим вводом), но очень полезно на практике (итерация проста для программисту писать, а будущему программисту читать).
Наконец, многие люди думают, что в Perl отсутствуют инструменты статического анализа и рефакторинга, как в Java, из-за относительной сложности его разбора. Я сомневаюсь, что это правда, я просто думаю, что в этом нет нужды и никто не удосужился это написать. (Линт нужен, например, Perl::Critic.)
Любой статический анализ Perl, который мне нужно было выполнить для генерации кода (некоторые макросы emacs для поддержки счетчиков тестов и Makefile.PL), работал нормально. Могут ли странные угловые случаи сбить мой код? Конечно, но я не изо всех сил пишу код, который невозможно поддерживать, хотя мог бы.
person
jrockway
schedule
14.08.2009
$_
(или выбирает функцию). - person Paul Biggar   schedule 19.08.2009