2012-07-29 18 views
7

pragmas, như autodie, theo các tài liệu, được lexically scoped.pragmas lexically scoped

{ 
use autodie; 
.. 
.. 
} 
# Can die here 

điều này có áp dụng cho tất cả các mô-đun được tải bằng use không? như xa như tôi biết, sử dụng là gần như giống nhau như:

BEGIN { 
require autodie; 
autodie->import(LIST); 
} 

BEGIN xảy ra tại thời gian biên dịch, yêu cầu không được lexically scoped, vậy làm thế nào đến, hầu cho autodie nhận thức về phạm vi của nó?

Cảm ơn,

+0

Có điều gì bạn muốn làm không? Hay điều này hoàn toàn nằm ngoài sự tò mò? – ikegami

Trả lời

10

Câu trả lời ngắn gọn là phạm vi từ vựng pragmatic modules được viết rõ ràng để xử lý theo cách đó và sử dụng các biến nội bộ ma thuật $^H%^H trong thời gian biên dịch để bật và tắt các tính năng.

Trình biên dịch đóng vai trò của nó bằng cách ngầm định địa hoá các biến này để giá trị của chúng được khôi phục vào cuối khi biên dịch một khối mã vào lúc bắt đầu. Theo cách đó, nó cung cấp cơ sở ngữ nghĩa từ vựng.

Ban đầu chỉ có biến số $^H. Nó chứa một mặt nạ bit mà ra lệnh tùy chọn trình biên dịch có sẵn bất cứ lúc nào trong quá trình biên dịch. Do đó, các pragma từ vựng duy nhất có thể được viết là các ký tự điều khiển các bit ma thuật đã xác định trong $^H.

Sau đó, băm %^H được giới thiệu và bất kỳ pragma nào cũng có thể lưu trữ các giá trị trong băm này bằng các khóa bắt đầu bằng tên của pragma. Bởi vì trình biên dịch bản địa hóa băm theo cách tương tự như vô hướng, bất kỳ pragma nào cũng có thể lưu trữ thông tin trạng thái phạm vi tự động tại đây.

Mô-đun autodie không điều khiển một trong các biến này, nhưng phân lớp mô-đun Fatal làm tất cả công việc khó khăn. Nó sử dụng %^H để theo dõi các toán tử nào đã bị gây tử vong và dựa vào trình biên dịch để loại bỏ thông tin này ở cuối khối.

+1

đề cập đến perlpragma sẽ tốt – ysth

7

Từ phương pháp nhập khẩu Fatal.pm là backend của autodie, thưởng thức này:

# Dark magic to have autodie work under 5.8 
# Copied from namespace::clean, that copied it from 
# autobox, that found it on an ancient scroll written 
# in blood. 

# This magic bit causes %^H to be lexically scoped. 
$^H |= 0x020000; 

Vì vậy, câu trả lời là có thực sự là một cách để làm cho nhập khẩu của bạn nhận thức từ vựng của họ phạm vi, nhưng nó vô cùng vướng víu với sự can đảm của perl và không có nghĩa là cho các lập trình viên bình thường sử dụng.

+1

Không, nó chỉ giải thích thêm bước cần thiết để làm cho các pragma dựa trên '%^H' hoạt động trong 5.8, không chỉ 5.10+. – ysth

+0

vâng, tôi thực sự chỉ cho thấy phần đáng sợ nhất của nó để truyền tải một cảm giác chung cho phép thuật có liên quan. Đó là một câu trả lời theo nghĩa là nó khẳng định cảm giác của người hỏi rằng các pragmas từ vựng không thể được thực hiện bằng các kỹ thuật nhập khẩu mô-đun "bình thường". –

+1

nhưng điều đó hoàn toàn sai ... chúng có thể dễ dàng được triển khai. xem http://perldoc.perl.org/perlpragma.html – ysth

1

Nó không phải là require thật thú vị; đó là những gì pragma làm trong import.

Hầu hết (tất cả?) Pragmas sử dụng $^H hoặc %^H. Trình phân tích cú pháp bản địa hóa các giá trị này thành phạm vi được phân tích cú pháp, có nghĩa là nó khôi phục chúng theo giá trị mà chúng đã có trước khi

Lấy ví dụ strict. import sửa đổi $^H của nó. $^H chứa một loạt cờ hướng dẫn trình biên dịch cách xử lý.

$ perl -e' 
    BEGIN { printf "%04X\n", $^H } 
    { 
     use strict; 
     BEGIN { printf "%04X\n", $^H } 
    } 
    BEGIN { printf "%04X\n", $^H } 
' 
0100 
0702 
0100 

$^H được dành riêng cho việc sử dụng Perl, nhưng tương tự cục bộ %^H có sẵn để sử dụng chung. Ví dụ: feature::qw_comment móc vào trình phân tích cú pháp một lần khi được tải bởi require, nhưng không làm bất kỳ điều gì trừ khi $^H{'feature::qw_comments::'} là đúng. Nhập của nó tương đương với

sub import { $^H{'feature::qw_comments::'} = 1; }