Ροή ελέγχου

evalbytes#

Μεταγλωττίζει και εκτελεί μια συμβολοσειρά πηγαίου κώδικα Perl, αναγκάζοντας την πηγή να ερμηνευτεί ως bytes αντί ως χαρακτήρες.

Η evalbytes είναι το byte-προσανατολισμένο δίδυμο της string eval. Δέχεται μια EXPR (ή την $_ όταν η EXPR παραλείπεται), αντιμετωπίζει τη συμβολοσειρά ως ωμή ροή bytes και την αναλύει ως πηγαίο κώδικα Perl. Η ανάλυση είναι μονωμένη από την pragma use utf8 του καλούντος: όποιους κανόνες κωδικοποίησης δηλώνει η ίδια η συμβολοσειρά, αυτοί υπερισχύουν. Χρησιμοποιήστε την όταν ο κώδικας που πρόκειται να μεταγλωττίσετε διαβάστηκε από δίσκο, από το δίκτυο ή από κάποιο βήμα build και χρειάζεστε ο αναλυτής να δει ακριβώς τα bytes που του δώσατε.

Σύνοψη#

evalbytes EXPR
evalbytes
CORE::evalbytes EXPR    # when the feature is not enabled

Τι επιστρέφεται#

Σε βαθμωτό περιβάλλον, η τιμή της τελευταίας έκφρασης που αποτιμήθηκε· σε περιβάλλον λίστας, μια λίστα. Σε σφάλμα μεταγλώττισης ή χρόνου εκτέλεσης, undef (ή κενή λίστα) και η $@ τίθεται στο μήνυμα σφάλματος· η $@ είναι η κενή συμβολοσειρά σε επιτυχία. Η μορφή επιστροφής ταιριάζει ακριβώς με την string eval - η μόνη διαφορά είναι ο τρόπος αποκωδικοποίησης του ίδιου του κειμένου της πηγής.

my $result = evalbytes $source;
die $@ if $@;

Πώς διαφέρει από την string eval#

Δύο συγκεκριμένες συμπεριφορές διακρίνουν την evalbytes από την eval EXPR:

  • Η πηγή αναλύεται ως bytes. Κάθε οκτάδα στη συμβολοσειρά είναι ξεχωριστός χαρακτήρας εισόδου για τον λεκτικό αναλυτή, ανεξάρτητα από το αν η συμβολοσειρά είναι εσωτερικά σημειωμένη ως utf8. Μια ακολουθία UTF-8 πολλαπλών bytes στην πηγή εμφανίζεται στον αναλυτή ως τα επιμέρους bytes, όχι ως το αποκωδικοποιημένο σημείο κώδικα.

  • Σημεία κώδικα πάνω από το 255 είναι σκληρό σφάλμα. Αν η συμβολοσειρά περιέχει οποιονδήποτε χαρακτήρα του οποίου ο τακτικός αριθμός υπερβαίνει το 0xFF, δεν μπορεί να είναι ροή bytes και η μεταγλώττιση αποτυγχάνει με Wide character in eval αποθηκευμένο στην $@. Υποβαθμίστε πρώτα με την utf8::encode αν η πηγή κρατά αυτή τη στιγμή αποκωδικοποιημένο κείμενο.

Οι use utf8 και no utf8 μέσα στον υπό αξιολόγηση κώδικα έχουν τη συνηθισμένη τους επίδραση: η pragma ενεργοποιείται μόλις την φτάσει ο αναλυτής και επηρεάζει το υπόλοιπο εκείνης της μεταγλώττισης. Είναι το εξωτερικό πλαίσιο της πηγής που είναι καθηλωμένο στα bytes, όχι αυτό που δηλώνει η ίδια η πηγή.

Ενεργοποίηση του ονόματος χωρίς CORE::#

Η evalbytes είναι feature-gated. Για να την καλέσετε ως bareword:

use feature 'evalbytes';

Μια δήλωση use v5.16 (ή υψηλότερη) ενεργοποιεί αυτόματα το χαρακτηριστικό evalbytes, μαζί με το υπόλοιπο bundle χαρακτηριστικών :5.16. Χωρίς κάποιο από τα δύο, το μη πλήρως κατονομασμένο όνομα δεν αναγνωρίζεται και πρέπει να γράψετε ρητά CORE::evalbytes - χρήσιμο μέσα σε παραγόμενο κώδικα ή σε μονόγραμμα που δεν φέρουν δήλωση έκδοσης.

use v5.16;
my $n = evalbytes '1 + 2';        # 3
# no feature, no version bundle:
my $n = CORE::evalbytes '1 + 2';  # 3

Καθολική κατάσταση που επηρεάζει#

  • $@ - καθαρίζεται πριν τη μεταγλώττιση, κατόπιν τίθεται στο μήνυμα σφάλματος σε αποτυχία ή στην κενή συμβολοσειρά σε επιτυχία. Ίδιο συμβόλαιο με την eval.

  • $_ - διαβάζεται ως το κείμενο πηγής όταν η EXPR παραλείπεται.

Source filters ενεργοποιημένα μέσα στον υπό αξιολόγηση κώδικα εφαρμόζονται στον ίδιο τον κώδικα, ακριβώς όπως θα έκαναν μέσα σε μια string eval. Το filter βλέπει τα ίδια bytes που βλέπει ο αναλυτής.

Παραδείγματα#

Αποτίμηση μιας κυριολεκτικής συμβολοσειράς bytes - καμία έκπληξη, καμία επιλογή κωδικοποίησης:

use feature 'evalbytes';
my $n = evalbytes 'my $x = 40; $x + 2';   # 42

Αποτίμηση πηγής που διαβάστηκε από αρχείο που είναι γνωστό ότι είναι κωδικοποιημένο σε UTF-8 αλλά για το οποίο η δηλωμένη pragma μέσα στην πηγή είναι αυτό που πρέπει να διέπει την ανάλυση:

use feature 'evalbytes';
open my $fh, '<:raw', 'script.pl' or die $!;
my $src = do { local $/; <$fh> };
my @values = evalbytes $src;
die "compile failed: $@" if $@;

Η ανάγνωση με :raw διατηρεί τη $src ως συμβολοσειρά bytes. Η evalbytes τότε τροφοδοτεί αυτά τα bytes στον αναλυτή αυτούσια· μια γραμμή use utf8; στην κορυφή του σεναρίου θα κάνει τη δική της δουλειά μόλις τη φτάσει ο αναλυτής.

Συγκρίνετε με τη string eval όταν ο καλών έχει use utf8:

use utf8;
use feature 'evalbytes';

my $src = "length('caf\xc3\xa9')";   # bytes for 'café' in UTF-8

print eval $src;         # 3  (characters: c, a, f, é)
print "\n";
print evalbytes $src;    # 5  (bytes:     c, a, f, 0xC3, 0xA9)
print "\n";

Υπό use utf8 το ίδιο το κυριολεκτικό "length('caf\xc3\xa9')" του καλούντος είναι συμβολοσειρά χαρακτήρων για την eval, οπότε η length μέσα στον υπό αξιολόγηση κώδικα βλέπει έναν χαρακτήρα é. Η evalbytes αναγκάζει την ίδια πηγή να αναλυθεί ως η ακολουθία bytes c a f 0xC3 0xA9, οπότε η length αναφέρει το πλήθος bytes.

Πιάσιμο ενός wide-character σφάλματος:

use feature 'evalbytes';
my $src = "print \x{2603}";          # contains U+2603 SNOWMAN
evalbytes $src;
warn "rejected: $@" if $@;           # "Wide character in eval ..."

Παράλειψη της EXPR - η πηγή προέρχεται από την $_:

use feature 'evalbytes';
for ('1+1', '2*3', '10-7') {
    my $r = evalbytes;
    print "$_ = $r\n";
}

Οριακές περιπτώσεις#

  • Wide character στην πηγή: οποιοδήποτε σημείο κώδικα πάνω από το 0xFF ματαιώνει τη μεταγλώττιση και αφήνει Wide character in eval στην $@. Τρέξτε utf8::encode στην πηγή (ή διαβάστε το αρχείο με :raw) πριν την κλήση.

  • Η use utf8 είναι τοπική στον υπό αξιολόγηση κώδικα. Επηρεάζει κυριολεκτικά συμβολοσειρών και αναγνωριστικά μέσα στο αποτιμώμενο κείμενο μόλις ο αναλυτής φτάσει στη γραμμή της pragma. Δεν αλλάζει τον τρόπο που η evalbytes πλαισιώνει την εξωτερική πηγή - εκείνο το πλαίσιο είναι πάντα «bytes».

  • Το χαρακτηριστικό δεν είναι ενεργοποιημένο: χωρίς use feature 'evalbytes' και χωρίς bundle use v5.16+, το bareword δεν αναγνωρίζεται. Γράψτε CORE::evalbytes για να παρακάμψετε την πύλη χαρακτηριστικού.

  • evalbytes χωρίς όρισμα και με $_ undef: μεταγλωττίζει κενή συμβολοσειρά, πράγμα που πετυχαίνει και επιστρέφει undef σε βαθμωτό περιβάλλον, την κενή λίστα σε περιβάλλον λίστας, με την $@ κενή.

  • Τα source filters μέσα στον υπό αξιολόγηση κώδικα βλέπουν τη ροή bytes. Ένα filter που περιμένει αποκωδικοποιημένους χαρακτήρες θα δυσλειτουργήσει· γράψτε filters για την evalbytes σε όρους bytes.

  • Λεξιλογικά και κατάσταση πακέτου: ίδιοι κανόνες με τη string eval. Ο υπό αξιολόγηση κώδικας μοιράζεται το τρέχον πακέτο του καλούντος και βλέπει τα εντός εμβέλειας λεξιλογικά του καλούντος· οι δικές του μεταβλητές my εξαφανίζονται όταν ολοκληρωθεί η eval.

  • die μέσα σε evalbytes: πιάνεται με τον ίδιο τρόπο όπως για την eval. Η εκτοξευμένη τιμή προσγειώνεται στην $@· η εκτέλεση συνεχίζεται μετά την κλήση evalbytes.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • eval - το αντίστοιχο σε character-mode· αναλύει την EXPR σύμφωνα με το Unicode πλαίσιο του καλούντος, οπότε η use utf8 στον καλούντα αλλάζει τον τρόπο ερμηνείας της πηγής

  • die - εκτοξεύει εξαίρεση μέσα από υπό αξιολόγηση κώδικα· θέτει την $@ όπως κάθε άλλο σφάλμα χρόνου εκτέλεσης

  • do - μεταγλωττίζει και εκτελεί ένα αρχείο· παίρνει την πηγή του από τον δίσκο αντί από συμβολοσειρά και δεν επηρεάζεται από το utf8 πλαίσιο του καλούντος

  • require - φορτώνει και μεταγλωττίζει ένα αρχείο μία φορά· το πρότυπο εργαλείο όταν η πηγή βρίσκεται στον δίσκο και πρέπει να εκτελεστεί μόνο κατά την πρώτη αναφορά

  • utf8 - η pragma που ελέγχει τη σημασιολογία χαρακτήρων έναντι bytes στα κυριολεκτικά συμβολοσειρών· η evalbytes υπάρχει ακριβώς για να καθηλώσει το εξωτερικό πλαίσιο στα bytes ανεξάρτητα από αυτή την pragma

  • $@ - η θέση σφάλματος που συμπληρώνεται σε αποτυχία της evalbytes, καθαρίζεται σε επιτυχία