perlpragma =head1 НАЗВАНИЕ perlpragma - Как писать пользовательские прагмы =head1 ОПИСАНИЕ Прагма - это модуль, который влияет на некоторые моменты во время компиляции и во время выполнения Perl-кода. Пример прагмы: Cили C. С выходом Perl 5.10 вы не ограничены в разработке прагм, теперь можете создавать пользовательские прагмы, которые будут менять поведение пользовательских функций в лексическом контексте. =head1 Основной пример Например, вам нужно создать класс, который реализует перегрузку математических операторов, и вы хотели бы использовать свою прагму с функционалом похожим на C. Пример кода: use MyMaths; my $l = MyMaths->new(1.2); my $r = MyMaths->new(3.4); print "A: ", $l + $r, "\n"; use myint; print "B: ", $l + $r, "\n"; { no myint; print "C: ", $l + $r, "\n"; } print "D: ", $l + $r, "\n"; no myint; print "E: ", $l + $r, "\n"; Результат выполнения кода: A: 4.6 B: 4 C: 4.6 D: 4 E: 4.6 I<В примере>, в котором используется C, оператор сложения работает с целыми числами, значения по умолчанию не определены. Поведение по умолчанию будет восстановлено C Минимальная реализация пакета C будет примерно такой: package MyMaths; use warnings; use strict; use myint(); use overload '+' => sub { my ($l, $r) = @_; # проверка вызова if (myint::in_effect(1)) { int($$l) + int($$r); } else { $$l + $$r; } }; sub new { my ($class, $value) = @_; bless \$value, $class; } 1; Примечание. При загрузке пользовательской прагмы C без параметров С<()> функция C не будет вызвана. Взаимодействие с Perl во время компиляции внутри пакета C: package myint; use strict; use warnings; sub import { $^H{myint} = 1; } sub unimport { $^H{myint} = 0; } sub in_effect { my $level = shift // 0; my $hinthash = (caller($level))[10]; return $hinthash->{myint}; } 1; Прагма реализована как модуль, поэтому C означает: BEGIN { require myint; myint->import(); } соответственно, C: BEGIN { require myint; myint->unimport(); } Следовательно, C и C вызываются B<во время компиляции> пользовательского кода. Пользовательские прагмы сохраняют свое состояние в магическом хеше C<%^H>, следовательно эти две подпрограммы управляют им. Информация о состоянии в C<%^H> сохраняется в op-дереве, и может быть получено во время выполнения с помощью C, под индексом 10 в возвращённом списке. В прагме из примера восстановление инкапсулировано в подпрограмме C, которая в качестве аргументов принимает единственный параметр - число вызовов, оставшихся для нахождения значения прагмы в пользовательском скрипте. Здесь используется C, чтобы определить значение C<$^H{myint}>, когда каждая строка пользовательского скрипта была вызвана. Поэтому в подпрограмме, реализующей перегрузку оператора сложения, используется корректная семантика. =head1 Детали реализации op-дерево является общим для всех потоков. Это означает, что существует возможность, при которой op-дерево "переживет" поток (и следовательно экземпляр интерпретатора), породивший его. Таким образом, настоящие Perl-скаляры не могут храниться в op-дереве. Вместо этого используется компактная форма, которая может хранить только целые значения (со знаком или без), строки или C; ссылки и числа с плавающей точкой преобразуются в строку. Если вам нужно хранить составные значения или сложные структуры, вам следует сериализовать их , например с помощью C. Ключи хеша из C<%^H> можно удалять и, как всегда, с помощью C можно понять, является ли это значение определённым или C. B<Не> пытайтесь хранить указатели на структуры данных как целые числа, которые получены из C и преобразованы обратно, т.к. это будет не безопасным для потоков. Доступ к структуре будет неблокирующим (что не безопасно для Perl скаляров). Такие структуры могут давать утечки памяти, либо быть освобождены, когда породивший их поток завершится. Это может произойти до того, как op-дерево удалит ссылки на них, если его поток переживёт их. ------------------------------------------------------------------------------- http://translated.by/you/perlpragma/into-ru/trans/ Original (English): perlpragma (http://perldoc.perl.org/perlpragma.html) Translation: © sharifulin, mikhail.lyubimov. translated.by crowd