זרימת בקרה

evalbytes#

הידור והרצה של מחרוזת קוד מקור של Perl, תוך אילוץ פירוש המקור כבתים ולא כתווים.

evalbytes הוא התאום מוכוון־הבתים של eval על מחרוזת. הוא מקבל EXPR (או את $_ כאשר EXPR מושמט), מתייחס למחרוזת כזרם בתים גולמי, ומפענח אותה כקוד מקור של Perl. הפענוח מבודד מפרגמת use utf8 של הקורא: כללי הקידוד שהמחרוזת עצמה מצהירה הם הקובעים. יש להישען עליו כאשר הקוד שעומדים להדר נקרא מהדיסק, מהחוט, או משלב build, ונדרש שהמפענח יראה בדיוק את הבתים שנמסרו לו.

תקציר#

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

מה מקבלים בחזרה#

בהקשר סקלר, ערך הביטוי האחרון שהוערך; בהקשר רשימה, רשימה. בשגיאת הידור או זמן ריצה, undef (או רשימה ריקה) ו־$@ נקבע להודעת השגיאה; $@ הוא המחרוזת הריקה בהצלחה. צורת ההחזרה תואמת בדיוק את eval על מחרוזת - ההבדל היחיד הוא איך טקסט המקור עצמו מפוענח.

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

כיצד הוא שונה מ־eval על מחרוזת#

שתי התנהגויות קונקרטיות מבדילות את evalbytes מ־eval EXPR:

  • המקור מפוענח כבתים. כל אוקטט במחרוזת הוא תו קלט נפרד ל־lexer, ללא תלות בכך שהמחרוזת מסומנת פנימית כ־utf8. רצף UTF-8 רב־בתים במקור מופיע ל־parser כבתים הבודדים, לא כנקודת הקוד המפוענחת.

  • נקודות קוד מעל 255 הן שגיאה קשה. אם המחרוזת מכילה תו כלשהו שערכו הסידורי עולה על 0xFF, היא לא יכולה להיות זרם בתים וההידור נכשל עם Wide character in eval מאוחסן ב־$@. יש להוריד את הקידוד עם utf8::encode תחילה אם המקור מחזיק כעת טקסט מפוענח.

use utf8 ו־no utf8 בתוך הקוד המוערך פועלים כרגיל: הפרגמה מופעלת ברגע שה־parser מגיע אליה ומשפיעה על שאר ההידור הזה. המסגרת החיצונית של המקור היא זו הקבועה לבתים, לא מה שהמקור עצמו מצהיר.

הפעלת השם ללא CORE::#

evalbytes שמור מאחורי שער תכונה. כדי לקרוא לו כ־bareword:

use feature 'evalbytes';

הצהרת use v5.16 (או גבוהה יותר) מפעילה את תכונת evalbytes באופן אוטומטי, יחד עם שאר חבילת התכונות :5.16. ללא אחד מהשניים, השם הלא מוסמך אינו מזוהה ויש לכתוב CORE::evalbytes במפורש - שימושי בתוך קוד שנוצר אוטומטית או one-liners שאינם נושאים הצהרת גרסה.

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

מצב גלובלי שהוא נוגע בו#

  • $@ - מאופס לפני ההידור, ואז נקבע להודעת השגיאה בכישלון או למחרוזת הריקה בהצלחה. אותו חוזה כמו eval.

  • $_ - נקרא כטקסט המקור כאשר EXPR מושמט.

מסנני מקור המופעלים בתוך הקוד המוערך חלים על הקוד עצמו, בדיוק כפי שהיו חלים בתוך eval על מחרוזת. המסנן רואה את אותם בתים שה־parser רואה.

דוגמאות#

הערכת מחרוזת בתים ליטרלית - ללא הפתעות, ללא החלטות קידוד:

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

הערכת מקור שנקרא מקובץ הידוע כמקודד UTF-8 אך הפרגמה המוצהרת בתוך המקור היא זו שאמורה לשלוט בפענוח:

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 כמחרוזת בתים. לאחר מכן evalbytes מזין את הבתים האלה ל־parser כפשוטם; שורת use utf8; בראש הסקריפט תעשה את העבודה שלה ברגע שה־parser מגיע אליה.

השוואה עם 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 מאלץ את אותו מקור להיות מפוענח כרצף הבתים c a f 0xC3 0xA9, כך ש־length מדווח את מספר הבתים.

תפיסת שגיאת תו רחב:

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";
}

מקרי קצה#

  • תו רחב במקור: כל נקודת קוד מעל 0xFF עוצרת את ההידור ומשאירה Wide character in eval ב־$@. יש להריץ utf8::encode על המקור (או לקרוא את הקובץ ב־:raw) לפני הקריאה.

  • use utf8 הוא לוקלי לקוד המוערך. הוא משפיע על ליטרלי מחרוזת ומזהים בתוך הטקסט המוערך ברגע שה־parser מגיע לשורת הפרגמה. הוא אינו משנה את הדרך שבה evalbytes ממסגר את המקור החיצוני - מסגור זה תמיד ”בתים“.

  • התכונה אינה מופעלת: ללא use feature 'evalbytes' וללא חבילת use v5.16+, ה־bareword אינו מזוהה. יש לכתוב CORE::evalbytes כדי לעקוף את שער התכונה.

  • evalbytes ללא ארגומנט ועם $_ לא־מוגדר: מהדר מחרוזת ריקה, מה שמצליח ומחזיר undef בהקשר סקלר, רשימה ריקה בהקשר רשימה, עם $@ ריק.

  • מסנני מקור בתוך הקוד המוערך רואים את זרם הבתים. מסנן שמצפה לתווים מפוענחים יתנהג לא נכון; יש לכתוב מסננים עבור evalbytes במונחי בתים.

  • לקסיקליים ומצב חבילה: אותם כללים כמו eval על מחרוזת. הקוד המוערך חולק את החבילה הנוכחית של הקורא ורואה את המשתנים הלקסיקליים בתחום של הקורא; משתני my משלו נעלמים כשה־eval מסתיים.

  • die בתוך evalbytes: נתפס באותה דרך כמו עבור eval. הערך שנזרק נוחת ב־$@; הביצוע ממשיך לאחר קריאת evalbytes.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • eval - המקבילה במצב תווים; מפענחת EXPR לפי מסגור Unicode של הקורא, כך ש־use utf8 בקורא משנה כיצד המקור מפורש

  • die - זריקת חריגה מתוך קוד מוערך; קובע את $@ בדיוק כמו כל שגיאת זמן ריצה אחרת

  • do - הידור והרצה של קובץ; לוקח את המקור שלו מהדיסק ולא ממחרוזת, ואינו מושפע ממסגור utf8 של הקורא

  • require - טעינת והידור קובץ פעם אחת; הכלי הסטנדרטי כאשר המקור נמצא בדיסק ואמור לרוץ רק בהפניה ראשונה

  • utf8 - הפרגמה השולטת בסמנטיקת תווים מול בתים של ליטרלי מחרוזת; evalbytes קיים בדיוק כדי לקבע את המסגור החיצוני לבתים ללא תלות בפרגמה זו

  • $@ - חריץ השגיאה המאוכלס בכישלון evalbytes, מאופס בהצלחה