Όριο μήκους αναγνωριστικών (Identifier too long)#
Διατύπωση του upstream#
Το perl5-upstream/pod/perlvar.pod αναφέρει, στην ενότητα Syntax of Variable Names:
Variable names in Perl can have several formats. Usually, they must begin with a letter or underscore, in which case they can be arbitrarily long (up to an internal limit of 251 characters) and may contain letters, digits, underscores, or the special sequence
::or'.
Αυτή η διατύπωση είναι παραπλανητική σε δύο σημεία.
Διόρθωση#
Η σωστή διατύπωση, για την σταθερή σειρά Perl 5.42, είναι:
Τα αναγνωριστικά μπορούν να έχουν μήκος έως 251 bytes. Ονόματα που υπερβαίνουν αυτό το μήκος προκαλούν σφάλμα κατά την ανάλυση:
Identifier too long.
Δύο πράγματα προκύπτουν από αυτό:
Bytes, όχι χαρακτήρες. Το όριο μετράται σε bytes της αναπαράστασης πηγής, όχι σε σημεία κώδικα Unicode. Τα αναγνωριστικά UTF-8 φτάνουν επομένως το όριο σε λιγότερους χαρακτήρες:
Πλάτος χαρακτήρα
Τελευταίο αποδεκτό
Πρώτο απορριπτέο
1 byte (ASCII)
251 χαρακτήρες
252 χαρακτήρες
2 bytes (π.χ.
é)125 χαρακτήρες
126 χαρακτήρες
3 bytes (π.χ.
ㄚ)83 χαρακτήρες
84 χαρακτήρες
4 bytes (π.χ.
𐌰— Γοτθικό)62 χαρακτήρες
63 χαρακτήρες
Σε κάθε περίπτωση η απόρριψη συμβαίνει όταν το μήκος σε bytes υπερβεί για πρώτη φορά τα 251. Οι «251 χαρακτήρες» του κειμένου του upstream είναι σωστοί μόνο για την περίπτωση ASCII.
Σκληρό σφάλμα, όχι «εσωτερικό όριο». Η διατύπωση «up to an internal limit» υπαινίσσεται κάτι ήπιο. Δεν είναι — ο αναλυτής του perl5 εγείρει μοιραία εξαίρεση
Identifier too long. Το μήνυμα είναι το μόνο που βλέπει ο χρήστης· δεν υπάρχει αποκοπή, προειδοποίηση ή εφεδρική συμπεριφορά.
Η άμεση αιτία στην 5.42 είναι ο ενταμιευτής tokenbuf[256] στην κατάσταση του αναλυτή, σε συνδυασμό με το e = dest_end - 3 (byte sigil + τελικό \0 + περιθώριο ασφαλείας) που υπολογίζεται μέσα στην S_parse_ident. Ο συνδυασμός δίνει 252 bytes συνολικά ÷ αφαιρώντας το sigil = 251 bytes καθαρού ονόματος αναγνωριστικού.
Το blead του upstream έχει ήδη ανεβάσει το όριο#
Ανεξάρτητα από αυτό το errata, η ανάπτυξη του perl5 (μετά την 5.42) έχει ήδη ανεβάσει το όριο. Το commit 8785c114b5 («parser.h Allow up to 256 characters in a token»), που εμφανίζεται για πρώτη φορά στο tag ανάπτυξης v5.43.4, αντικαθιστά το tokenbuf των 256 bytes με ενταμιευτή 1024 bytes. Η επόμενη σταθερή σειρά (Perl 5.44) αναμένεται επομένως να επιτρέπει αναγνωριστικά έως περίπου 1020 bytes από προεπιλογή. Το όριο των 251 bytes είναι χαρακτηριστικό της 5.42 και παλαιότερων.
runtime p5#
Το runtime p5 του PetaPerl είναι η μεταγλώττιση μέσω c2rust του διερμηνευτή C του perl5. Η συμπεριφορά του ως προς το μήκος αναγνωριστικών είναι:
Μήκος | perl5 5.42.2 | pperl |
|---|---|---|
251 bytes | αποδοχή | αποδοχή |
252 bytes | απόρριψη | αποδοχή (απόκλιση) |
1019 bytes | απόρριψη | αποδοχή (απόκλιση) |
1020 bytes | απόρριψη | απόρριψη |
1024 bytes | απόρριψη | απόρριψη |
Η απόκλιση είναι πραγματική και ορατή στον κώδικα του χρήστη. Η αιτία δεν βρίσκεται στην ίδια τη μεταγλώττιση μέσω c2rust. Η έξοδος του c2rust είναι πιστός, γραμμή προς γραμμή, καθρέφτης του πηγαίου C που δίνεται. Η αιτία είναι η μετατόπιση του upstream-checkout: το perl5-upstream/ είναι αυτή τη στιγμή καρφιτσωμένο σε στιγμιότυπο blead (μετά την 5.43.4) και όχι σε ετικέτα συντήρησης 5.42.x. Το blead έχει το ανεβασμένο tokenbuf — ο καθρέφτης του c2rust το κληρονομεί.
Πρόκειται για ένα παράδειγμα μιας ευρύτερης κατηγορίας λανθανουσών αποκλίσεων: το blead του upstream έχει συσσωρεύσει 140+ commits μόνο στο toke.c από την ετικέτα 5.42.2, και η ίδια αριθμητική — ό,τι κάνει το blead, αυτό κάνει και το pperl --p5 — ισχύει για κάθε ένα από αυτά. Άλλες πιθανώς επηρεαζόμενες περιοχές (ορατές μόνο στον αναλυτή):
Το βελτιωμένο
qr/.../xx(PPC 0026) προσγειώνεται στο blead· ο χειρισμός κενών/σχολίων μέσα στις κλάσεις χαρακτήρων διαφέρει από την 5.42.Διορθώσεις σφαλμάτων στην
intuit_more(πολλαπλά commits): οι οριακές περιπτώσεις στην επίλυση ασάφειας μεταξύ$foo[bar]και$foo{bar}συμπεριφέρονται καλύτερα στο pperl--p5από ό,τι στην 5.42.Επανεγγραφή του API της
S_parse_ident: η θέση σφάλματος που αναφέρεται για τα σφάλματα ανάλυσης που σχετίζονται με αναγνωριστικά μετακινήθηκε ανάμεσα στην 5.42 και το blead.
Η αποκατάσταση δεν είναι να μπαλωθεί η έξοδος του c2rust· είναι να καρφιτσωθεί το perl5-upstream/ στο v5.42.2 και να επανεκτελεστεί ο αγωγός μεταγλώττισης.
Μέχρι να γίνει αυτό, το runtime p5 είναι — αυστηρά μιλώντας — «perl5 next» και όχι «perl5 5.42 stable». Για τον περισσότερο κώδικα χρήστη αυτό είναι αόρατο· για τις γωνιακές περιπτώσεις παραπάνω, η συμπεριφορά ταιριάζει με το blead, όχι με την 5.42.
runtime pp#
Το runtime pp (pperl --pp) χρησιμοποιεί τον δικό του εγγενή αναλυτή (src/parser/lexer.rs). Δεν επιβάλλει κανένα όριο — ο σαρωτής αναγνωριστικών επαναλαμβάνεται πάνω από τους χαρακτήρες αναγνωριστικού χωρίς όριο μήκους. Ονόματα αυθαίρετου μήκους (10 000 bytes και πάνω) γίνονται σιωπηρά αποδεκτά.
Αυτή είναι μια σκόπιμη απόκλιση. Το runtime pp δεν δεσμεύεται από τη byte-προς-byte συμμόρφωση με το upstream perl5· όπου το pp συμπεριφέρεται καλύτερα από το upstream — και η απουσία αυθαίρετης οροφής 251 bytes είναι αρκούντως καλύτερη — το έργο διατηρεί αυτή τη βελτίωση. Σημειώστε ότι το ίδιο το blead του upstream κινείται προς την ίδια κατεύθυνση (η αύξηση του ενταμιευτή από 256 σε 1024), που υποδηλώνει ότι η ανησυχία αυτή είναι ευρέως κοινή.
Τεστ#
Τα τεστ συμμόρφωσης που καλύπτουν αυτό το errata βρίσκονται στα:
t/01-parsing/090-identifier-length-ascii.tt/01-parsing/091-identifier-length-utf8.t
Διερευνούν το όριο στα 251 bytes (ASCII και UTF-8 2/3/4 bytes) και στη δευτερεύουσα αποκοπή του upstream-blead κοντά στα 1024 bytes, καθώς και μήκη σχετικά με το runtime pp έως 10 000 bytes. Κάθε υπο-τεστ κωδικοποιεί μια προσδοκία της perl5 5.42· το pperl αυτή τη στιγμή αποτυγχάνει σε υποσύνολα της σουίτας όπως τεκμηριώνεται παραπάνω. Τα υπο-τεστ που αποτυγχάνουν αποτελούν το λειτουργικό ίχνος παρακολούθησης για αυτή την καταχώριση errata.