Forth

Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια

Η Forth είναι μια δομημένη, προστακτική, ανακλαστική και επεκτάσιμη γλώσσα προγραμματισμού, βασισμένη στη στοίβα, ενώ με το ίδιο όνομα αποκαλείται και το περιβάλλον προγραμματισμού της. Αν και το όνομά της δεν αποτελείται από αρχικά κάποιων λέξεων, πολλές φορές γράφεται με κεφαλαία FORTH, για ιστορικούς λόγους.

Σαν διαδικαστική γλώσσα προγραμματισμού χωρίς σύστημα τύπων, η Forth περιλαμβάνει διαδραστική εκτέλεση εντολών (κάτι που την κάνει κατάλληλη σαν κέλυφος συστημάτων χωρίς λειτουργικό σύστημα) και την ικανότητα να μεταγλωττίζει ακολουθίες εντολών για μεταγενέστερη εκτέλεση. Κάποιες υλοποιήσεις της Forth (συνήθως πρώιμες εκδόσεις, ή εκδόσεις που έχουν γραφτεί για να είναι πλήρως μεταφέρσιμες) μεταγλωττίζουν σε threaded code, αλλά πολλές σύγχρονες υλοποιήσεις παράγουν βελτιστοποιημένο κώδικα μηχανής όπως άλλοι μεταγλωττιστές γλωσσών.

Αν και δεν είναι τόσο διάσημη όλες άλλα συστήματα προγραμματισμού, η Forth έχει αρκετή υποστήριξη ώστε να απασχολούνται εμπορικά πολλοί δημιουργοί υλοποιήσεών της, καθώς και εταιρείες. Η Forth χρησιμοποιείται σε boot loaders όπως το Open Firmware, σε διαστημικές εφαρμογές,[1] και σε άλλα ενσωματωμένη συστήματα. Η Gforth, μια υλοποίηση της Forth από το εγχείρημα GNU είναι σε διαρκή ανάπτυξη, με την τελευταία της έκδοση το Δεκέμβριο του 2008. Το πρότυπο του 1994 βρίσκεται υπό αναθεώρηση, με το όνομα 200x.[2]

Γενικά[Επεξεργασία | επεξεργασία κώδικα]

Ένα περιβάλλον της Forth συνδυάζει το μεταγλωττιστή με ένα διαδραστικό κέλυφος. Ο χρήστης μπορεί να ορίζει με αυτό και να εκτελεί υπορουτίνες, ή "λέξεις" ("words"), σε μια εικονική μηχανή που μοιάζει με το περιβάλλον χρόνου εκτέλεσης (runtime environment). Οι λέξεις μπορούν να δοκιμαστούν, να οριστούν ξανά και να γίνει αποσφαλμάτωσή τους καθώς εισάγεται ο πηγαίος κώδικας, χωρίς επανάληψη της μεταγλώττισης ή της εκτέλεσης του προγράμματος. Όλα τα συντακτικά στοιχεία, συμπεριλαμβανομένων των μεταβλητών και των βασικών τελεστών, φαίνονται σαν διαδικασίες (procedures) αυτής της μορφής. Ακόμα και αν μια συγκεκριμένη λέξη έχει βελτιστοποιηθεί ώστε να μη χρειάζεται κλήση υπορουτίνας, εξακολουθεί να είναι διαθέσιμη και σαν υπορουτίνα. Από την άλλη πλευρά, το κέλυφος μπορεί να μεταγλωττίζει σε κώδικα μηχανής εντολές που πληκτρολογούνται διαδραστικά, πριν να τις τρέξει. (Κοινή συμπεριφορά που όμως δεν είναι απαραίτητη.) Τα περιβάλλοντα της Forth διαφέρουν ως προς το πώς αποθηκεύεται το πρόγραμμα που προκύπτει, αλλά η εκτέλεση του προγράμματος πρέπει ιδανικά να έχει το ίδιο αποτέλεσμα με την εισαγωγή του πηγαίου κώδικά του. Αυτό έρχεται σε αντίθεση με το συνδυασμό της C με τα κελύφη του Unix, όπου οι μεταγλωττισμένες συναρτήσεις είναι μια ειδική κλάση προγραμματιστικών αντικειμένων και οι διαδραστικές εντολές αυστηρά διερμηνεύονται. Από αυτήν την αρχή πηγάζουν οι περισσότερες από τις μοναδικές ιδιότητες της Forth. Περιλαμβάνοντας διαλογικές δυνατότητες, συγγραφή σεναρίων (scripting) και μεταγλώττιση, η Forth ήταν διαδεδομένη σε υπολογιστές με περιορισμένους πόρους όπως οι σειρές BBC Micro και Apple II, και συνεχίζει να είναι σε εφαρμογές όπως το υλικολογισμικό (firmware) και οι μικροί μικροελεγκτές. Αν και πολλοί μεταγλωττιστές της C πια παράγουν κώδικα με μεγαλύτερη ορθότητα και καλύτερη απόδοση από ότι στο παρελθόν, η Forth εξακολουθεί να έχει το πλεονέκτημα της διαλογικότητας.

Στοίβες[Επεξεργασία | επεξεργασία κώδικα]

Τα περισσότερα προγραμματιστικά περιβάλλοντα με αναδρομικές υπορουτίνες χρησιμοποιούν στοίβα για τη ροή ελέγχου (control flow). Αυτή η δομή συνήθως αποθηκεύει τοπικές μεταβλητές, συμπεριλαμβανομένων παραμέτρων των υπορουτινών (σε γλώσσα με κλήση κατά τιμή (call by value) όπως η C). Συχνά η Forth δεν έχει τοπικές μεταβλητές και δεν ακολουθεί το πέρασμα παραμέτρων κατά τιμή αλλά οι ενδιάμεσες τιμές κρατούνται σε μια δεύτερη στοίβα. Οι λέξεις λειτουργούν κατευθείαν πάνω στις λέξεις στην κορυφή της πρώτης στοίβας. Επομένως, αυτή μπορεί να ονομαστεί η λίστα "παραμέτρων" ή "δεδομένων", αν και συνήθως είναι απλά "η στοίβα". Η δεύτερη στοίβα, των κλήσεων των συναρτήσεων, καλείται τότε στοίβα "σύνδεσης" ("linkage") ή επιστροφής ("return"), με συντομογραφία τον όρο rstack. Ο πυρήνας του συστήματος παρέχει ειδικές συναρτήσεις χειρισμού της rstack που επιτρέπουν να χρησιμοποιηθεί για προσωρινή αποθήκευση μέσα σε μια λέξη, αλλά σε κάθε άλλη περίπτωση δε μπορεί να χρησιμοποιηθεί για να περάσει παραμέτρους ή να επεξεργαστεί δεδομένα.

Οι περισσότερες λέξεις ορίζονται με βάση το αποτέλεσμά τους στη στοίβα. Συνήθως οι παράμετροι τοποθετούνται στην κορυφή της στοίβας πριν την εκτέλεση μιας λέξης. Μετά την εκτέλεσή της, οι παράμετροι έχουν διαγραφεί και έχουν αντικατασταθεί από τις τιμές επιστροφής που μπορεί να υπάρχουν. Όσον αφορά τους αριθμητικούς τελεστές, αυτή η διαδικασία ακολουθεί τον κανόνα της αντίστροφης Πολωνικής γραφής (reverse Polish notation). Δείτε παρακάτω για παραδείγματα που δείχνουν τον τρόπο χρήσης της στοίβας.

Συντήρηση[Επεξεργασία | επεξεργασία κώδικα]

Η Forth είναι μια απλή αλλά επεκτάσιμη γλώσσα που επιτρέπει τη συγγραφή προγραμμάτων υψηλού επιπέδου όπως συστήματα Σχεδίασης με τη Βοήθεια Υπολογιστή ((Computer-aided design, CAD). Η επεκτασιμότητα αυτή όμως επιτρέπει στον προγραμματιστή να γράφει ακατανόητο κώδικα, κάτι που έχει συμβάλλει στη φήμη της Forth σαν "γλώσσας μόνο για γράψιμο" ("write-only language"). Η Forth έχει χρησιμοποιηθεί με επιτυχία σε μεγάλα και πολύπλοκα εγχειρήματα, όπου εφαρμογές που έχουν αναπτυχθεί από ικανούς προγραμματιστές με πειθαρχία, έχουν αποδειχτεί εύκολες στη συντήρηση σε εξελισσόμενες πλατφόρμες υλικού, στο πέρασμα δεκαετιών χρήσης.[3] Η Forth έχει ένα σημαντικό μερίδιο στην περιοχή των αστρονομικών και διαστημικών εφαρμογών.[4] Η Forth χρησιμοποιείται ακόμα σήμερα σε πολλά ενσωματωμένα συστήματα (μικρές υπολογιστικές συσκευές) λόγω της μεταφερσιμότητάς της (portability), της αποδοτικής χρήσης της μνήμης, του σύντομου χρόνου ανάπτυξης και της γρήγορης ταχύτητας εκτέλεσης. Έχει υλοποιηθεί αποδοτικές σε σύγχρονους επεξεργαστές RISC και έχουν παραχθεί επεξεργαστές που χρησιμοποιούν τη Forth σαν γλώσσα μηχανής.[5] Άλλες χρήσεις της Forth περιλαμβάνουν τις ROM εκκίνησης του Open Firmware (boot ROMs) που χρησιμοποιούνται από την Apple, την IBM, τη Sun, και το OLPC XO-1, και τον ελεγκτή του πρώτου σταδίου της εκκίνησης του λειτουργικού συστήματος FreeBSD που είναι βασισμένος στο FICL.

Ιστορία[Επεξεργασία | επεξεργασία κώδικα]

Η Forth προέκυψε από το προσωπικό σύστημα προγραμματισμού του Charles H. Moore, το οποίο ήταν σε συνεχή ανάπτυξη από το 1958.[6] Η Forth δόθηκε αρχικά σε άλλους προγραμματιστές στις αρχές της δεκαετίας του 1970, αρχίζοντας από την Elizabeth Rather στο Εθνικό Ραδιο-Αστρονομικό Παρατηρητήριο (National Radio Astronomy Observatory, NRAO) των Ηνωμένων Πολιτειών.[6] Μετά από την εργασία τους στο NRAO, ο Charles Moore και η Elizabeth Rather δημιούργησαν την εταιρεία FORTH, Inc. το 1973, βελτιώνοντας και μεταφέροντας συστήματα Forth σε δεκάδες άλλες πλατφόρμες κατά την επόμενη δεκαετία.

Η ονομασία "Forth" προέκυψε επειδή το 1968 "το αρχείο του διερμηνέα ονομάστηκε FOURTH, δηλαδή λογισμικό 4ης γενιάς - αλλά το λειτουργικό σύστημα του IBM 1130 περιόριζε τα ονόματα αρχείων σε 5 χαρακτήρες".[7] Ο Moore θεωρούσε τη Forth σαν διάδοχο των γλωσσών τρίτης γενιάς που ακολουθούσαν τη λογική μεταγλώττιση-σύνδεση-εκτέλεση (compile-link-go), και του λογισμικού για υλικό "τέταρτης γενιάς", όχι με την έννοια του όρου "γλώσσα προγραμματισμού τέταρτης γενιάς" όπως αυτή έτεινε να χρησιμοποιείται.

Επειδή ο Charles Moore άλλαζε συχνά δουλειές στην καριέρα του, η γλώσσα από την αρχή πιέστηκε να είναι εύκολη στη μεταφορά σε διαφορετικές αρχιτεκτονικές προγραμματισμού. Συχνά χρησιμοποιήθηκαν συστήματα Forth για να εισάγουν νέο υλικό. Για παράδειγμα, η Forth ήταν το πρώτο μόνιμο λογισμικό (resident software) του νέου τσιπ Intel 8086 το 1978 και η MacFORTH ήταν το πρώτο μόνιμο σύστημα ανάπτυξης για τον πρώτο Apple Macintosh το 1984.[6]

Η microFORTH της FORTH, Inc. αναπτύχθηκε για τους μικροεπεξεργαστές Intel 8080, Motorola 6800 και Zilog Z80 από το 1976. Η microFORTH χρησιμοποιήθηκε αργότερα από ερασιτέχνες για την παραγωγή συστημάτων Forth για άλλες αρχιτεκτονικές, όπως ο 6502 το 1978. Η ευρεία διάδοση τελικά οδήγησε σε προτυποποίηση της γλώσσας. Η συνήθης πρακτική αποτυπώθηκε στα ντε φάκτο πρότυπα FORTH-79[8] και FORTH-83,[9] το 1979 και το 1983, αντίστοιχα. Τα πρότυπα αυτά ενοποιήθηκαν από το ANSI το 1994, με το αποτέλεσμα συχνά να αποκαλείται ANS Forth.[10]

Η Forth υπήρξε πολύ δημοφιλής κατά τη δεκαετία του 1980[11] γιατί ταίριαζε με τους μικροϋπολογιστές της εποχής επειδή ήταν μικρή και μεταφέρσιμη. Τουλάχιστον ένας μικρός υπολογιστής (home computer), ο βρετανικός Jupiter ACE, περιείχε τη Forth στο λειτουργικό σύστημα που είχε μόνιμα στη ROM του. Ο Canon Cat επίσης χρησιμοποιούσε τη Forth γα τον προγραμματισμό του συστήματός του. Η Rockwell κατασκεύασε επίσης μικροϋπολογιστές ενός τσιπ με μόνιμους πυρήνες Forth, τους R65F11 και R65F12. Ένα πλήρες γενεαλογικό δένδρο βρίσκεται στο TU-Wien.

Από την πλευρά του προγραμματιστή[Επεξεργασία | επεξεργασία κώδικα]

Η Forth βασίζεται στη ρητή χρήση στοίβας και σε αντίστροφη Πολωνική γραφή (reverse Polish notation, RPN) γνωστής και σαν γραφής επιθέματος (postfix notation), η οποία χρησιμοποιείται συχνά σε αριθμομηχανές της Hewlett-Packard. Στην RPN, ο τελεστής τοποθετείται μετά τους τελεστέους του, σε αντίθεση με την κοινή ενθεματική γραφή (infix notation) όπου ο τελεστής τοποθετείται ανάμεσα στους τελεστέους του. Η επιθεματική γραφή κάνει τη γλώσσα ευκολότερη στη συντακτική ανάλυση (parsing) και πιο επεκτάσιμη - η Forth δε χρησιμοποιεί γραμματική BNF και δεν έχει μονολιθικό μεταγλωττιστή. Η επέκταση του μεταγλωττιστή απαιτεί μόνο τη συγγραφή μιας νέας λέξης και όχι την τροποποίηση κάποιας γραμματικής και την αλλαγή της υλοποίησης.

Με τη χρήση RPN, μπορεί κανείς να πάρει το αποτέλεσμα της μαθηματικής έκφρασης (25 * 10 + 50) με τον εξής τρόπο:

25 10 * 50 + . <cr> 300 ok

Αυτές οι εντολές αρχικά βάζουν τους αριθμούς 25 και 10 στη στοίβα (που υπονοείται).


Η λέξη * πολλαπλασιάζει τους δύο αριθμούς στην κορυφή της στοίβας και τους αντικαθιστά με το γινόμενό τους.

Στη συνέχεια τοποθετείται στη στοίβα ο αριθμός 50.


Η λέξη + τον προσθέτει στο προηγούμενο γινόμενο. Τέλος η εντολή . τυπώνει το αποτέλεσμα στο τερματικό του χρήστη.[12]

Ακόμα και τα σχετικά με δομές χαρακτηριστικά της Forth είναι βασισμένα στη στοίβα. Για παράδειγμα:

: FLOOR5 ( n -- n' )   DUP 6 < IF DROP 5 ELSE 1 - THEN ;

Ο κώδικας παραπάνω ορίζει μια νέα λέξη (όπου ο όρος λέξη χρησιμοποιείται όπως και πριν για να δηλώσει μια υπορουτίνα) που ονομάζεται FLOOR5 χρησιμοποιώντας τις εξής εντολές: η DUP διπλασιάζει τον αριθμό στη στοίβα, η 6 τοποθετεί ένα 6 στην κορυφή της στοίβας, η < συγκρίνει τους δύο αριθμούς στην κορυφή της στοίβας (το 6 και την είσοδο που έχει γίνει DUP) και τους αντικαθιστά με μια αληθοτιμή ("αληθής" ή "ψευδής"), η IF παίρνει μια αληθοτιμή και επιλέγει αν θα εκτελέσει τις εντολές ακριβώς μετά από αυτήν ή θα μεταφερθεί στο ELSE, η DROP αγνοεί την τιμή στη στοίβα και η THEN λήγει την εντολή υπό συνθήκη. Το κείμενο στις παρενθέσεις είναι σχόλιο που συμβουλεύει ότι αυτή η λέξη περιμένει έναν αριθμό στη στοίβα και επιστρέφει ένα αριθμό που ίσως έχει τροποποιηθεί. Η λέξη FLOOR5 είναι ισοδύναμη με την εξής συνάρτηση γραμμένη στη γλώσσα προγραμματισμού C με τη χρήση του τριαδικού τελεστή (ternary operator):

int floor5(int v) { return (v < 6) ? 5 : (v - 1); }

Η συνάρτηση γράφεται πιο σύντομα ως εξής:

: FLOOR5 ( n -- n' ) 1- 5 MAX ;

Η λέξη αυτή εκτελείται όπως ακολουθεί:

1 FLOOR5 . <cr> 5 ok
8 FLOOR5 . <cr> 7 ok

Αρχικά ο διερμηνέας βάζει στη στοίβα έναν αριθμό (1 ή 8), στη συνέχεια καλεί τη FLOOR5, που αφαιρεί τον αριθμό από τη στοίβα και βάζει σε αυτή το αποτέλεσμα. Τέλος, μια κλήση στην "." αφαιρεί το αποτέλεσμα από την κορυφή της στοίβας και το τυπώνει στο τερματικό του χρήστη.

Εργαλεία[Επεξεργασία | επεξεργασία κώδικα]

Η συντακτική ανάλυση της Forth είναι απλή, αν και δεν υπάρχει τυπική γραμματική της γλώσσας. Ο διερμηνέας διαβάζει μια γραμμή εισόδου από τη συσκευή εισόδου του χρήστη, την οποία στη συνέχεια αναλύει συντακτικά για να εντοπίσει μια λέξη, χρησιμοποιώντας κενά για διαχωριστικά - κάποια συστήματα αναγνωρίζουν επιπλέον χαρακτήρες κενού (whitespace). Όταν ο διερμηνέας βρει κάποια λέξη, την αναζητά στο λεξικό (dictionary). Αν η λέξη βρεθεί, ο διερμηνέας εκτελεί τον κώδικα που της αντιστοιχεί και στη συνέχεια επιστρέφει για να αναλύσει συντακτικά το υπόλοιπο του ρεύματος εισόδου (input stream). Αν η λέξη δε βρεθεί, θεωρείται αριθμός και γίνεται προσπάθεια μετατροπής της σε αριθμητική τιμή και τοποθέτησής της στη στοίβα - αν αυτό είναι επιτυχές, ο διερμηνέας συνεχίζει να αναλύει συντακτικά το ρεύμα εισόδου. Αλλιώς, αν αποτύχουν τόσο η αναζήτηση, όσο και η μετατροπή σε αριθμό, ο διερμηνέας τυπώνει τη λέξη μαζί με ένα μήνυμα λάθους ότι αυτή δεν αναγνωρίζεται, καθαρίζει (flush) το ρεύμα εισόδου και περιμένει για νέα είσοδο από το χρήστη.[13]

Ο ορισμός μιας νέας λέξης αρχίζει με τη λέξη : (άνω και κάτω τελεία) και τελειώνει με τη λέξη ; (αγγλική άνω τελεία, ελληνικό ερωτηματικό). Για παράδειγμα, ο κώδικας:

: X DUP 1+ . . ;

θα μεταγλωττίσει τη λέξη X, με αποτέλεσμα το όνομά της να αναζητείται με επιτυχία στο λεξικό. Όταν εκτελεστεί με την πληκτρολόγηση στην κονσόλα του κώδικα 10 X, θα τυπώσει 11 10.[14]

Τα περισσότερα συστήματα Forth περιλαμβάνουν έναν εξειδικευμένο συμβολομεταφραστή που παράγει εκτελέσιμες λέξεις. Ο συμβολομεταφραστής είναι μια ειδική διάλεκτος του μεταγλωττιστή. Οι μεταγλωττιστές της Forth συχνά χρησιμοποιούν αντίστροφη πολωνική γραφή. Ένας συμβολομεταφραστής της Forth συχνά σχεδιάζεται ώστε να κατασκευάζει μια εντολή στη στοίβα και στη συνέχεια να την αντιγράφει στη μνήμη σαν τελευταίο βήμα. Οι καταχωρητές μπορούν να κατονομάζονται με το όνομα του κατασκευαστή τους, αριθμητικά (0..n, όπως χρησιμοποιούνται σε πραγματικό λειτουργικό κώδικα) ή να ονομάζονται με βάση το σκοπό τους στο σύστημα της Forth: π.χ. "S" για τον καταχωρητή που είναι δείκτης της στοίβας (stack).[15]

Λειτουργικό σύστημα, αρχεία και πολυδιεργασία[Επεξεργασία | επεξεργασία κώδικα]

Τα κλασικά συστήματα Forth συνηθίζουν να μη χρησιμοποιούν το λειτουργικό σύστημα ούτε τα αρχεία. Αντί να αποθηκεύουν κώδικα σε αρχεία, ο πηγαίος κώδικας αποθηκεύεται σε ενότητες δίσκου (disk blocks) που γράφονται σε πραγματικές διευθύνσεις του δίσκου. Η λέξη BLOCK χρησιμοποιείται για να μεταφραστεί ο αριθμός των ενοτήτων δίσκου με μέγεθος 1K στη διεύθυνση του ενταμιευτή (buffer) που περιέχει τα δεδομένα, ο χειρισμός του οποίου γίνεται αυτόματα από το σύστημα της Forth. Κάποια συστήματα υλοποιούν συνεχή (contiguous) αρχεία δίσκου χρησιμοποιώντας την πρόσβαση δίσκου του συστήματος, όπου τα αρχεία βρίσκονται σε συγκεκριμένο εύρος ενοτήτων δίσκου. Συνήθως υλοποιούνται σαν δυαδικές εγγραφές (records) σταθερού μήκους, με έναν ακέραιο αριθμό εγγραφών ανά ενότητα δίσκου. Η γρήγορη αναζήτηση γίνεται με αναζήτηση κατακερματισμού (hashed access) στα δεδομένα του κλειδιού.

Η πολυδιεργασία (multitasking), γνωστή και σαν συνεργατικός χρονοκαταμερισμός εκ περιτροπής (cooperative round-robin scheduling), συνήθως είναι διαθέσιμη (αν και οι λέξεις πολυδιεργασίας και η υποστήριξη για αυτή δεν καλύπτονται από το πρότυπο Forth του ANSI). Η λέξη PAUSE χρησιμοποιείται για να αποθηκεύει το περιβάλλον εκτέλεσης της τρέχουσας διεργασίας, να βρίσκει την επόμενη διεργασία και να επαναφέρει το περιβάλλον εκτέλεσής της. Κάθε διεργασία έχει τις δικές της στοίβες, ιδιωτικά αντίγραφα κάποιων μεταβλητών ελέγχου και μια περιοχή πρόχειρου (scratch area). Η εναλλαγή διεργασιών είναι απλή και αποδοτική - αυτό έχει αποτέλεσμα η Forth να υποστηρίζει πολυδιεργασία ακόμα και σε πολύ απλούς μικροελεγκτές όπως ο Intel 8051, ο Atmel AVR και ο TI MSP430.[16]

Από την άλλη πλευρά, κάποια συστήματα Forth εκτελούνται μέσα σε κάποιο λειτουργικό σύστημα όπως τα Microsoft Windows, το Linux ή κάποια έκδοση του Unix και χρησιμοποιούν το σύστημα αρχείων του λειτουργικού συστήματος για αρχεία πηγαίου κώδικα και δεδομένων - το πρότυπο ANSI της Forth περιγράφει τις λέξεις που χρησιμοποιούνται για είσοδο/έξοδο (I/O). Άλλα βοηθήματα που δεν είναι πάντα παρόντα, είναι ο μηχανισμός για κλήσεις συστήματος στο λειτουργικό σύστημα ή στο παραθυρικό σύστημα (windowing system) και οι επεκτάσεις που αλληλεπιδρούν με τον χρονοπρογραμματισμό που παρέχεται από το λειτουργικό σύστημα. Συνήθως παρέχονται περισσότερες και διαφορετικές λέξεις από την κλασική λέξη PAUSE της Forth για τη δημιουργία διεργασιών, την προσωρινή παύση τους, την καταστροφή τους και την τροποποίηση της προτεραιότητάς τους.

Αυτομεταγλώττιση και διαμεταγλώττιση[Επεξεργασία | επεξεργασία κώδικα]

Ένα πλήρες σύστημα της Forth, με όλον τον πηγαίο κώδικά του, μπορεί να μεταγλωττίσει τον εαυτό του, μια τεχνική που οι προγραμματιστές της Forth ονομάζουν μετα-μεταγλώττιση (meta-compilation, που σαν χρήση διαφέρει από τη συνηθισμένη χρήση του όρου σε άλλες γλώσσες). Η συνηθέστερη μέθοδος είναι να οριστεί ένα σύνολο από λέξεις που τοποθετούν μεταγλωττισμένες δυαδικές λέξεις (bits) στη μνήμη. Οι γλώσσες του μεταγλωττιστή χρησιμοποιούν ειδικά ονομασμένες εκδόσεις των εντολών fetch (διάβασμα) και store (αποθήκευση) που μπορούν να ανακατευθυνθούν σε έναν προσωρινό χώρο (buffer) στη μνήμη. Ο προσωρινός χώρος προσομοιώνει ή έχει πρόσβαση σε ένα χώρο στη μνήμη που αρχίζει από διαφορετική διεύθυνση από προσωρινό χώρο του κώδικα. Οι μεταγλωττιστές αυτού του τύπου ορίζουν λέξεις που να έχουν πρόσβαση και στη μνήμη του υπολογιστή-προορισμού, και στη μνήμη του υπολογιστή στον οποίο γίνεται η μεταγλώττιση.[17]

Όταν οι λειτουργίες fetch και store οριστούν πάλι στο χώρο του κώδικα, μπορούν να χρησιμοποιηθούν οι νέοι αυτοί ορισμοί τους για να μεταγλωττιστούν πάλι ο μεταγλωττιστής, ο συμβολομεταφραστής, κλπ. Αυτό πρακτικά επαναχρησιμοποιεί όλον τον κώδικα του μεταγλωττιστή και του διερμηνέα. Στη συνέχεια, ο κώδικας του συστήματος της Forth έχει μεταγλωττιστεί και έχει αποθηκευτεί στον προσωρινό χώρο στη μνήμη. Ο προσωρινός χώρος της μνήμης γράφεται στο δίσκο και υπάρχουν τρόποι να φορτωθεί προσωρινά στη μνήμη για δοκιμές. Όταν η νέα έκδοση φαίνεται να λειτουργεί σωστά, γράφεται πάνω στην προηγούμενη έκδοση.

Υπάρχουν πολλές εκδόσεις τέτοιων μεταγλωττιστών για διαφορετικά περιβάλλοντα. Στα ενσωματωμένα συστήματα (embedded systems), ο κώδικας μπορεί να γράφεται σε έναν άλλο υπολογιστή, μια τεχνική που είναι γνωστή σαν διαμεταγλώττιση (cross compilation), μέσω σειριακής θύρας ή ενός TTL bit, κρατώντας τα ονόματα των λέξεων και άλλα μη-εκτελέσιμα τμήματα του λεξικού στον αρχικό υπολογιστή που κάνει τη μεταγλώττιση. Οι ελάχιστοι ορισμοί για έναν μεταγλωττιστή Forth αυτού του είδους είναι οι λέξεις που διαβάζουν και αποθηκεύουν ένα byte και η λέξη που προστάζει την εκτέλεση μια λέξης Forth. Συχνά το πιο χρονοβόρο μέρος της συγγραφής μιας έκδοσης για κάποια άλλη πλατφόρμα είναι η τροποποίηση του αρχικού προγράμματος ώστε να υλοποιεί την αποθήκευση, το διάβασμα και την εκτέλεση, αλλά πολλοί σύγχρονοι μικροεπεξεργαστές περιλαμβάνουν χαρακτηριστικά αποσφαλμάτωσης που ελαχιστοποιούν αυτήν την απαίτηση (όπως η ΚΜΕ Motorola CPU32).[18]

Δομή της γλώσσας[Επεξεργασία | επεξεργασία κώδικα]

Η βασική δομή δεδομένων της Forth είναι το "λεξικό" ("dictionary") που αντιστοιχίζει "λέξεις" με εκτελέσιμο κώδικα ή δομές δεδομένων με όνομα. Το λεξικό υπάρχει στη μνήμη σαν δένδρο από συνδεδεμένες λίστες με τους συνδέσμους από τις πιο πρόσφατα ορισμένες λέξεις στις πιο παλιές, μέχρι να βρεθεί ένας ειδικός χαρακτήρας (sentinel), που συνήθως είναι κάποιος δείκτης NULL. Μια θεματική εναλλαγή (context switch) προκαλεί την έναρξη μιας αναζήτησης στη λίστα από άλλον κόμβο-φύλλο. Μια αναζήτηση στη συνδεδεμένη λίστα συνεχίζεται όσο το τρέχον κλαδί ενσωματώνεται στο βασικό σώμα του δένδρου, οδηγώντας τελικά στον κόμβο sentinel, που είναι η ρίζα (root).

Μπορούν να υπάρχουν πολλά λεξικά. Σπάνια (π.χ. μετα-μεταγλώττιση) ένα λεξικό μπορεί να είναι απομονωμένο και ξεχωριστό. Αυτό το αποτέλεσμα μοιάζει με αυτό των εμφωλευμένων χώρων ονομάτων (nesting namespaces) και μπορεί να υπερφορτώσει λέξεις-κλειδιά που να εξαρτώνται από το περιβάλλον.

Μια ορισμένη λέξη γενικά αποτελείται από την κεφαλή (head) και το σώμα (body) με την κεφαλή να αποτελείται από ένα πεδίο ονόματος (name field, NF) και ένα πεδίο σύνδεσης (link field, LF) και το σώμα να αποτελείται από ένα πεδίο κώδικα (code field, CF) και ένα πεδίο παραμέτρων (parameter field, PF).

Ο χειρισμός της κεφαλής και του σώματος μιας εγγραφής του λεξικού γίνεται με διαφορετικό τρόπο γιατί μπορεί να μην είναι συνεχόμενα. Για παράδειγμα όταν ένα πρόγραμμα Forth μεταγλωττίζεται πάλι για μια νέα πλατφόρμα, η κεφαλή μπορεί να παραμείνει στον υπολογιστή που γίνεται η μεταγλώττιση ενώ το σώμα πάει στη νέα πλατφόρμα. Σε κάποια περιβάλλοντα, όπως τα ενσωματωμένα συστήματα (embedded systems), οι κεφαλές καταλαμβάνουν χώρο στη μνήμη χωρίς λόγο. Όμως, κάποιοι διαμεταγλωττιστές (cross-compilers) μπορεί να τοποθετήσουν τις κεφαλές στον κώδικα-προορισμό, αν αυτός πρόκειται να υποστηρίζει κάποια διαδραστική Forth.[19]

Εισαγωγή στο λεξικό[Επεξεργασία | επεξεργασία κώδικα]

Η ακριβής μορφή μιας λέξης στο λεξικό δεν είναι προκαθορισμένη και διαφέρει ανάμεσα στις υλοποιήσεις. Παρόλα αυτά, κάποια στοιχεία υπάρχουν στις περισσότερες υλοποιήσεις, αν και μπορεί να αλλάζει το μέγεθός τους ή η σειρά τους. Η εισαγωγή μιας λέξης στο λεξικό, σαν δομή, μπορεί να περιλαμβάνει:[20]

structure
  byte:       flag           \ 3bit σημαίες (flags) + μήκος του ονόματος της λέξης
  char-array: name           \ το μήκος του ονόματος στο χρόνο εκτέλεσης δεν είναι γνωστό στη μεταγλώττιση
  address:    previous       \ πεδίο σύνδεσης, ανάποδος δείκτης στην προηγούμενη λέξη
  address:    codeword       \ δείκτης στον κώδικα που εκτελεί η λέξη
  any-array:  parameterfield \ δεδομένα, λέξεις ή εντολές άγνωστου μεγέθους
end-structure forthword

Το πεδίο ονόματος ξεκινά με ένα πρόθεμα που δίνει το μήκος του ονόματος της λέξης (συνήθως μέχρι 32 bytes) και κάποια bits για σημαίες (flags). Στη συνέχεια, μετά το πρόθεμα, ακολουθεί, η αναπαράσταση χαρακτήρων του ονόματος της λέξης. Ανάλογα με την υλοποίηση της Forth, μπορεί να υπάρχουν ένα ή περισσότερα bytes με την τιμή NUL ('\0') για στοίχιση (alignment).

Το πεδίο σύνδεσης περιλαμβάνει ένα δείκτη στην προηγούμενα ορισμένη λέξη. Ο δείκτης μπορεί να είναι μια σχετική μετατόπιση ή μια απόλυτη διεύθυνση που να δείχνει το επόμενο παλαιότερο μέλος.

Ο δείκτης του πεδίου κώδικα μπορεί να είναι είτε η διεύθυνση της λέξης που θα εκτελέσει τον κώδικα ή τα δεδομένα στο πεδίο παραμέτρων ή η αρχή του κώδικα μηχανής που θα εκτελεστεί άμεσα από τον επεξεργαστή. Για λέξεις που ορίζονται με τον τελεστή : ο δείκτης του πεδίου κώδικα δείχνει στη λέξη που θα αποθηκεύσει τον τρέχοντα δείκτη εντολής (instruction pointer, IP) της Forth στη στοίβα επιστροφής και θα φορτώσει τον IP με τη νέα διεύθυνση από την οποία θα συνεχίσει η εκτέλεση των λέξεων. Με τον ίδιο τρόπο λειτουργούν και οι εντολές κλήση/επιστροφή (call/return) ενός επεξεργαστή.

Δομή του μεταγλωττιστή[Επεξεργασία | επεξεργασία κώδικα]

Ο μεταγλωττιστής δεν είναι μονολιθικό πρόγραμμα. Αποτελείται από λέξεις της Forth που είναι ορατές στο σύστημα και μπορούν να χρησιμοποιηθούν από τον προγραμματιστή. Αυτό επιτρέπει σε έναν προγραμματιστή να αλλάξει τις λέξεις του μεταγλωττιστή για ειδικούς σκοπούς.

Η σημαία "χρόνος μεταγλώττισης" ("compile time") του πεδίου ονόματος τίθεται για λέξεις με συμπεριφορά "χρόνου μεταγλώττισης". Οι περισσότερες απλές λέξεις εκτελούν τον ίδιο κώδικα, χωρίς να έχει σημασία αν πληκτρολογήθηκαν στη γραμμή εντολών ή βρίσκονται μέσα σε κάποιο κώδικα. Όταν μεταγλωττίζονται, ο μεταγλωττιστής απλά τοποθετεί κώδικα ένα δείκτη threaded στη λέξη.[14]

Κλασικά παραδείγματα λέξεων χρόνου μεταγλώττισης είναι οι δομές ελέγχου όπως το IF και το WHILE. Όλες οι δομές ελέγχου της Forth, καθώς και το μεγαλύτερο τμήμα του μεταγλωττιστή της, υλοποιούνται σαν λέξεις χρόνου μεταγλώττισης. Όλες οι λέξεις ελέγχου ροής (control flow) εκτελούνται κατά τη μεταγλώττιση ώστε να μεταγλωττίσουν διάφορους συνδυασμούς των πρωτογενών λέξεων BRANCH (διακλάδωση) και ?BRANCH (διακλάδωση αν ψευδές). Κατά τη μεταγλώττιση, η στοίβα δεδομένων χρησιμοποιείται για να υποστηρίζεται η διακλάδωση δομών ελέγχου, οι εμφωλευμένες δομές και η διόρθωση (backpatching) των διευθύνσεων διακλάδωσης. Το κομμάτι κώδικα:

... DUP 6 < IF DROP 5 ELSE 1 - THEN ...

θα μεταγλωττιζόταν στην εξής ακολουθία εντολών μέσα σε έναν ορισμό:

... DUP LIT 6 < ?BRANCH 5  DROP LIT 5  BRANCH 3  LIT 1 - ...

Οι αριθμοί μετά την BRANCH αναπαριστούν σχετικές διευθύνσεις διακλάδωσης. Η πρωτογενής λέξη LIT τοποθτεί στην κορυφή της στοίβας δεδομένων έναν καννικό αριθμό ("literal").

Κατάσταση μεταγλώττισης και διερμηνείας[Επεξεργασία | επεξεργασία κώδικα]

Η λέξη : (άνω-κάτω τελεία) διαβάζει ένα όνομα σαν παράμετρο, εισάγει στο λεξικό έναν ορισμό (colon definition) και μπαίνει σε κατάσταση μεταγλώττισης. Ο διερμηνέας συνεχίζει να διαβάζει λέξεις χωρισμένες με κενό από τη συσκευή εισόδου του χρήστη. Αν βρεθεί μια λέξη, ο διερμηνέας εκτελεί τη σημασιολογία μεταγλώττισης (compilation semantics) που συνδέεται με τη λέξη, αντί για τη σημασιολογία διερμηνείας (interpretation semantics). Η προκαθορισμένη σημασιολογία μεταγλώττισης μιας λέξης είναι η σημασιολογία διερμηνείας της να προστίθεται στον τρέχοντα ορισμό.[14]

Η λέξη ; (ελληνικό ερωτηματικό) λήγει τον τρέχοντα ορισμό και επιστρέφει στην κατάσταση διερμηνείας. Είναι παράδειγμα λέξης της οποίας η σημασιολογία μεταγλώττισης διαφέρει από την προκαθορισμένη. Η σημασιολογία διερμηνείας της ;, των περισσότερων λέξεων ελέγχου ροής και αρκετών άλλων λέξεων δεν ορίζεται στην ANS Forth, το οποίο σημαίνει ότι πρέπει να χρησιμοποιούνται μόνο μέσα σε ορισμούς και όχι στη διαλογική γραμμή εντολών.[14]

Η κατάσταση του διερμηνέα μπορεί να αλλάξει χειροκίνητα με τις λέξεις [ (αριστερή τετράγωνη αγκύλη) και ] (δεξιά τετράγωνη αγκύλη) που μπαίνουν σε κατάσταση διερμηνείας ή μεταγλώττισης, αντίστοιχα. Οι λέξεις αυτές μπορούν να χρησιμοποιηθούν με τη λέξη LITERAL για να υπολογίσουν μια τιμή κατά τη μεταγλώττιση και να εισάγουν την υπολογισμένη τιμή στον τρέχοντα ορισμό. Η LITERAL έχει τη σημασιολογία μεταγλώττισης να παίρνει ένα αντικείμενο από τη στοίβα δεδομένων και να προσθέτει σημασιολογία στον τρέχοντα ορισμό για να τοποθετήσει αυτό το αντικείμενο στη στοίβα δεδομένων.

Στην ANS Forth, η τρέχουσα κατάσταση του διερμηνέα μπορεί να διαβαστεί από τη σημαία (flag) STATE που περιέχει την τιμή true στην κατάσταση μεταγλώττισης και false σε κάθε άλλη περίπτωση. Αυτό επιτρέπει την υλοποίηση των λεγόμενων state-smart words, λέξεων με συμπεριφορά που αλλάζει ανάλογα με την τρέχουσα κατάσταση του διερμηνέα.

Άμεσες λέξεις[Επεξεργασία | επεξεργασία κώδικα]

Η λέξη IMMEDIATE σημειώνει τον πιο πρόσφατο ορισμό με άνω-κάτω τελεία σαν άμεση λέξη (immediate word), αντικαθιστώντας πρακτικά τη σημασιολογία μεταγλώττισής της με τη σημασιολογία διερμηνείας της.[21] Οι άμεσες λέξεις συνήθως εκτελούνται κατά τη μεταγλώττιση, δε μεταγλωττίζονται αλλά αυτό μπορεί να αλλαχθεί από τον προγραμματιστή, σε κάθε περίπτωση. Για παράδειγμα η ; είναι άμεση λέξη. Στην ANS Forth, η λέξη POSTPONE παίρνει ένα όνομα σαν παράμετρο και προσθέτει τη σημασιολογία μεταγλώττισης της λέξης που ονομάζεται στον τρέχοντα ορισμό, ακόμα και αν η λέξη σημειώθηκε σαν άμεση. Η Forth-83 ορίζει ξεχωριστές λέξεις COMPILE και [COMPILE] που να προκαλούν τη μεταγλώττιση των μη-άμεσων και των άμεσων λέξεων αντίστοιχα.

Ανώνυμες λέξεις και μονάδες εκτέλεσης[Επεξεργασία | επεξεργασία κώδικα]

Στην ANS Forth, μπορούν να οριστούν ανώνυμες λέξεις με τη λέξη :NONAME που μεταγλωττίζει τις επόμενες λέξεις μέχρι το επόμενο ; (ελληνικό ερωτηματικό) και αφήνει μια μονάδα εκτέλεσης (execution token) στη στοίβα δεδομένων. Η μονάδα εκτέλεσης παρέχει έναν τρόπο χειρισμού της μεταγλωττισμένης σημασιολογίας, όμοια με τους δείκτες συναρτήσεων (function pointers) της γλώσσας προγραμματισμού C.

Οι μονάδες εκτέλεσης μπορούν να αποθηκευτούν σε μεταβλητές. Η λέξη EXECUTE παίρνει μια μονάδα εκτέλεσης από τη στοίβα δεδομένων και εκτελεί την αντίστοιχη σημασιολογία. Η λέξη COMPILE, (συμπεριλαμβανόμενου και του ",") παίρνει μια μονάδα εκτέλεσης από τη στοίβα δεδομένων και προσθέτει την αντίστοιχη σημασιολογία στον τρέχοντα ορισμό.

Η λέξη ' (απόστροφος) παίρνει το όνομα μιας λέξης σαν παράμετρο και επιστρέφει στη τη μονάδα εκτέλεσης που αντιστοιχεί σε αυτή τη λέξη στη στοίβα δεδομένων. Σε κατάσταση διερμηνείας, ο κώδικας ' RANDOM-WORD EXECUTE είναι ισοδύναμος με τον RANDOM-WORD.[22]

Συντακτική ανάλυση και σχόλια[Επεξεργασία | επεξεργασία κώδικα]

Οι λέξεις : (άνω-κάτω τελεία), POSTPONE, ' (απόστροφος) και :NONAME είναι παραδείγματα λέξεων συντακτικής ανάλυσης (parsing words) που δέχονται τα ορίσματά τους από τη συσκευή εισόδου του χρήστη αντί για τη στοίβα δεδομένων. Ένα άλλο παράδειγμα είναι η λέξη ( (αριστερή παρένθεση) που διαβάζει και αγνοεί όλες τις λέξεις μέχρι και την επόμενη δεξιά παρένθεση και χρησιμοποιείται για την τοποθέτηση σχολίων σε έναν ορισμό. Όμοια, η λέξη \ (κάθετος) χρησιμοποιείται για σχόλια που συνεχίζονται μέχρι το τέλος της τρέχουσας γραμμής. Για να γίνει η σωστή συντακτική τους ανάλυση, οι ( (παρένθεση) και \ (κάθετος) πρέπει να διαχωρίζονται από το υπόλοιπο κείμενο των σχολίων μέσω κενών.

Δομή του κώδικα[Επεξεργασία | επεξεργασία κώδικα]

Στα περισσότερα συστήματα της Forth, το σώμα ενός ορισμού κώδικα αποτελείται είτε από γλώσσα μηχανής, είτε από κάποια μορφή threaded code. Η πρώτη Forth, που ακολουθεί το ανεπίσημο πρότυπο FIG (Forth Interest Group), είναι TIL (Threaded Interpretive Language). Αυτό αποκαλείται επίσης indirect-threaded code, αλλά εκδόσεις της γλώσσας τύπου direct-threaded ή subroutine threaded έχουν επίσης διαδοθεί τα τελευταία χρόνια. Οι πιο γρήγορες σύγχρονες Forth χρησιμοποιούν subroutine threading, εισάγουν τις απλές λέξεις σαν μακροεντολές και κάνουν βελτιστοποίηση κλειδαρότρυπας (peephole optimization) ή άλλες στρατηγικές βελτιστοποίησης για να κάνουν τον κώδικα μικρότερο και ταχύτερο.[23]

Αντικείμενα δεδομένων[Επεξεργασία | επεξεργασία κώδικα]

Όταν μια λέξη είναι μεταβλητή ή άλλο αντικείμενο δεδομένων, το πεδίο κώδικα δείχνει στον κώδικα χρόνου εκτέλεσης που αντιστοιχεί στη ορίζουσα λέξη που το δημιούργησε. Μια ορίζουσα λέξη έχει μια χαρακτηριστική "ορίζουσα συμπεριφορά" (δημιουργία μιας εγγραφής στο λεξικό και δέσμευση και αρχικοποίηση χώρου δεδομένων) και επίσης ορίζει τη συμπεριφορά ενός στιγμιότυπου της κλάσης των λέξεων που κατασκευάζονται από την ορίζουσα λέξη. Παραδείγματα:

VARIABLE
Ονομάζει μια αρχικοποιημένη θέση μνήμης ενός κελιού (cell). Η συμπεριφορά στιγμιότυπου μιας VARIABLE επιστρέφει τη διεύθυνσή της στη στοίβα.
CONSTANT
Ονομάζει μια τιμή (ορισμένη σαν παράμετρο στην CONSTANT). Η συμπεριφορά στιγμιότυπου της επιστρέφει την τιμή.
CREATE
Ονομάζει μια θέση - μπορεί να καταχωρείται χώρος στη θέση αυτή ή μπορεί αυτή να περιέχει μια συμβολοσειρά ή άλλη αρχικοποιημένη τιμή. Η συμπεριφορά στιγμιότυπου επιστρέφει τη διεύθυνση στην αρχή αυτού του χώρου.

Η Forth παρέχει επίσης τη δυνατότητα στον προγραμματιστή να ορίζει νέες ορίζουσες λέξεις, δηλώνοντας κάποια συμπεριφορά ορισμού και στιγμιοτύπων. Παραδείγματα είναι οι κυκλικοί αποταμιευτές (circular buffers), οι δυαδικές λέξεις με όνομα (named bits) σε κάποια θύρα εισόδου/εξόδου και οι πίνακες με αυτόματη δεικτοδότηση.

Τα αντικείμενα δεδομένων που ορίζονται από λέξεις σαν τις παραπάνω έχουν καθολική εμβέλεια. Η λειτουργία που σε άλλες γλώσσες γίνεται με τις τοπικές μεταβλητές, στη Forth παρέχεται από τη στοίβα δεδομένων (αν και η Forth έχει επίσης κανονικές τοπικές μεταβλητές). Το στυλ προγραμματισμού της Forth χρησιμοποιεί πολύ λίγα αντικείμενα δεδομένων με όνομα σε σχέση με άλλες γλώσσες - συνήθως τέτοια αντικείμενα χρησιμοποιούνται για να περιέχουν δεδομένα που χρησιμοποιούνται από αρκετές λέξεις ή διεργασίες (αν η υλοποίηση υποστηρίζει πολλαπλές διεργασίες).[24]

Η Forth δεν επιβάλλει τη συνέπεια της χρήσης των τύπων δεδομένων - είναι ευθύνη του προγραμματιστή να χρησιμοποιήσει τους κατάλληλους τελεστές για να διαβάσει και να αποθηκεύσει τιμές ή να εκτελέσει άλλες λειτουργίες σε δεδομένα.

Προγραμματισμός[Επεξεργασία | επεξεργασία κώδικα]

Οι λέξεις που γράφονται σε Forth μεταγλωττίζονται σε εκτελέσιμη μορφή. Οι κλασικές υλοποιήσεις τύπου "indirect threaded" μεταγλωττίζουν λίστες από διευθύνσεις λέξεων που πρόκειται να εκτελεστούν - πολλά σύγχρονα συστήματα παράγουν πραγματικό κώδικα μηχανής (που περιλαμβάνει κλήσεις σε κάποιες εξωτερικές λέξεις και κώδικα για άλλες που αναπτύσσεται επιτόπου). Κάποια συστήματα έχουν μεταγλωττιστές που κάνουν βελτιστοποιήσεις. Γενικά μιλώντας, ένα πρόγραμμα σε Forth αποθηκεύεται σαν ένα αποτύπωμα στη μνήμη (memory image) του μεταγλωττισμένου προγράμματος με μια μοναδική εντολή (π.χ. RUN) που εκτελείται όταν φορτώνεται η μεταγλωττισμένη έκδοση.

Κατά τη διάρκεια της ανάπτυξης, ο προγραμματιστής χρησιμοποιεί το διερμηνέα για να εκτελέσει και να ελέγξει κάθε μικρό τμήμα που αναπτύσσεται. Οι περισσότεροι προγραμματιστές Forth υποστηρίζουν μια χαλαρή σχεδίαση από πάνω προς τα κάτω (loose top-down design) και ανάπτυξη από κάτω προς τα πάνω (bottom-up development) με συνεχόμενες δοκιμές και ενοποίηση (testing & integration).[25]

Η σχεδίαση από πάνω προς τα κάτω μοιράζει συνήθως το πρόγραμμα σε "λεξικά" που χρησιμοποιούνται στη συνέχεια σαν σύνολα εργαλείων υψηλού επιπέδου για τη συγγραφή του τελικού προγράμματος. Ένα καλά σχεδιασμένο πρόγραμμα Forth διαβάζεται σαν φυσική γλώσσα, και υλοποιεί, όχι μόνο μια λύση, αλλά και εργαλεία για την επίλυση παρόμοιων προγραμμάτων.[26]

Γεια σου, κόσμε[Επεξεργασία | επεξεργασία κώδικα]

Παραδείγματα κώδικα[Επεξεργασία | επεξεργασία κώδικα]

Μια πιθανή υλοποίηση:

: HELLO  ( -- )  CR ." Γεια σου, κόσμε!" ; HELLO <cr>
Γεια σου, κόσμε!

Η λέξη CR (Carriage Return, επιστροφή φορέα ή αλλαγή γραμμής) έχει σαν αποτέλεσμα η έξοδος που ακολουθεί να εμφανιστεί σε νέα γραμμή. Η γραμμή συντακτικής ανάλυσης ." (τελεία-εισαγωγικό) διαβάζει μια συμβολοσειρά με εισαγωγικά σαν διαχωριστικά και προσθέτει κώδικα στον τρέχοντα ορισμό ώστε η συμβολοσειρά που αναλύεται συντακτικά να εμφανίζεται στην εκτέλεση. Ο χαρακτήρας κενού μεταξύ της λέξης ." και της συμβολοσειράς Γεια σου, κόσμε! δεν περιλαμβάνεται στη συμβολοσειρά. Χρειάζεται ώστε ο συντακτικός αναλυτής να αναγνωρίσει τη λέξη ." σαν λέξη της Forth.

Ένα κλασικό σύστημα Forth έχει επίσης ένα διερμηνέα και η ίδια έξοδος μπορεί να προκύψει αν πληκτρολογηθεί ο εξής κώδικας στην κονσόλα της Forth:

CR .( Γεια σου, κόσμε!)

Η .( (τελεία-παρένθεση) είναι μια άμεση λέξη που αναλύει συντακτικά μια συμβολοσειρά με διαχωριστικό την παρένθεση και την εμφανίζει. Όπως και με τη λέξη ." ο χαρακτήρας κενού μεταξύ της .( και της Γεια σου, κόσμε! δεν είναι μερος της συμβολοσειράς.

Η λέξη CR προηγείται του κειμένου προς εκτύπωση. Από σύμβαση, ο διερμηνέας της Forth δεν αρχίζει την έξοδο σε νέα γραμμή και περιμένει για είσοδο στο έλος της προηγούμενης γραμμής, μετά την προτροπή ok. Δεν υπάρχει έμμεσα κάποιος ενταμιευτής ('flush-buffer') που να καθαρίζεται από τη λέξη CR, όπως συμβαίνει σε άλλες γλώσσες.

Αναμιγνύοντας τις καταστάσεις μεταγλώττισης και διερμηνείας[Επεξεργασία | επεξεργασία κώδικα]

Ακολουθεί ο ορισμός της λέξης EMIT-Q που παράγει ένα χαρακτήρα Q όταν εκτελείται:

: EMIT-Q   81 ( ο κώδικας ASCII για το χαρακτήρα 'Q' ) EMIT ;

Αυτός ο ορισμός χρησιμοποιεί την τιμή ASCII του χαρακτήρα Q (81) άμεσα. Το κείμενο μεταξύ των παρενθέσεων είναι σχόλιο και αγνοείται από το μεταγλωττιστή. Η λέξη EMIT παίρνει μια τιμή από τη στοίβα δεδομένων και δείχνει τον αντίστοιχο χαρακτήρα.

Η EMIT-Q μπορεί να οριστεί πάλι χρησιμοποιώντας τις λέξεις [ (αριστερή τετράγωνη αγκύλη), ] (δεξιά τετράγωνη αγκύλη), CHAR και LITERAL για να μεταβεί προσωρινά σε κατάσταση διερμηνέα, να υπολογίσει την τιμή ASCII του χαρακτήρα Q, να επιστρέψει σε κατάσταση μεταγλώττισης και να προσθέσει την υπολογισμένη τιμή στον τρέχοντα ορισμό άνω-κάτω τελείας (colon definition):

: EMIT-Q   [ CHAR Q ]  LITERAL  EMIT ;

Η λέξη συντακτικής ανάλυσης CHAR παίρνει μια λέξη με διαχωριστικά κενά σαν παράμετρο και βάζει την τιμή του πρώτου χαρακτήρα στη στοίβα δεδομένων. Η λέξη [CHAR] είναι μια άμεση έκδοση της CHAR. Με τη χρήση [CHAR], το παράδειγμα ορισμού της EMIT-Q μπορεί να γραφεί και σαν:

: EMIT-Q   [CHAR] Q  EMIT ; \ Παράγει τον χαρακτήρα 'Q'

Αυτός ο ορισμός χρησιμοποιεί την \ (κάθετος) για το σχόλιο.

Και η CHAR και η [CHAR] είναι ορισμένες εκ των προτέρων στην ANS Forth. Με τη χρήση της IMMEDIATE και της POSTPONE, η [CHAR] θα μπορούσε να είχε οριστεί και ως εξής:

: [CHAR]   CHAR  POSTPONE LITERAL ; IMMEDIATE

Ένα πλήρες πρόγραμμα για τον κρυπτογραφικό αλγόριθμο RC4[Επεξεργασία | επεξεργασία κώδικα]

Το 1987 ο Ron Rivest ανέπτυξε το κρυπτογραφικό σύστημα RC4 για την RSA Data Security, Inc. Ο κώδικας είναι πολύ απλός και μπορεί να γραφεί από τους περισσότερους προγραμματιστές από την περιγραφή και μόνο.

Έχουμε έναν πίνακα από 256 bytes, όλα διαφορετικά. Κάθε φορά που ο πίνακας χρησιμοποιείται, αλλάζει με την αντιμετάθεση δύο bytes. Οι αντιμεταθέσεις ελέγχονται από τους μετρητές i και j, ο καθένας από τους οποίους αρχικά είναι 0. Για μια νέα τιμή του i, προστίθεται 1. Για μια νέα τιμή του j, προστίθεται το byte του πίνακα στη νέα θέση i. Τα bytes του πίνακα στις θέσεις i και j αντιμετατίθενται. Ο κώδικας βρίσκεται στο byte του πίνακα στο άθροισμα των bytes των θέσεων i και j. Γίνεται τότε η πράξη Αποκλειστικό-Ή (XOR) μεταξύ αυτού και ενός byte του κείμενου προς κρυπτογράφηση ή ενός κρυπτογραφημένου κειμένου προς αποκρυπτογράφηση. Ο πίνακας αρχικοποιείται με αρχικές τιμές από 0 έως 255. Στη συνέχεια διατρέχεται με τη χρήση των i και j, με το νέο j να προκύπτει με την πρόσθεσή του στο byte του πίνακα στο i και ένα byte κλειδί, και αντιμεταθέτοντας τα bytes του πίνακα στα i και j. Τέλος, τα i και j τίθενται ίσα με 0. Όλες οι προσθέσεις είναι με υπόλοιπο 256.

Η παρακάτω έκδοση για Standard Forth χρησιμοποιεί μόνο βασικές (Core) λέξεις.

0 VALUE ii
0 VALUE jj
CREATE S[] 256 CHARS ALLOT
 : ARCFOUR  ( c -- x )
	ii 1+ DUP TO ii 255 AND		( -- i )
	S[] +  DUP C@			( -- 'S[i] S[i] ) 
	DUP jj +  255 AND DUP TO jj	( -- 'S[i] S[i] j )
	S[] +  DUP C@ >R		( -- 'S[i] S[i] 'S[j] )
	OVER SWAP C!			( -- 'S[i] S[i] )
	R@ ROT C!			( -- S[i] )
	R> +				( -- S[i]+S[j] )
	255 AND S[] + C@		( -- c x )
	XOR ;
: ARCFOUR-INIT	( key len -- )
	256 MIN LOCALS| len key |
	256 0 DO  I  S[] I + C!  LOOP
	0 TO jj 
	256 0  DO			( key len -- )
		  key I len MOD + C@  
		  S[] I  + C@  + jj + 255 AND TO jj
		  S[] I  + DUP C@  SWAP ( c1 addr1 )
		  S[] jj + DUP C@  ( c1 addr1 addr2 c2 ) ROT C! C!
	     LOOP
	0 TO ii  0 TO jj ;

Ακολουθεί μια δοκιμή επαλήθευσης του κώδικα.

CREATE KEY: 64 CHARS ALLOT
: !KEY ( c1 c2 ... cn n—αποθηκεύει το κλειδί που ορίζεται, μήκους n )
	DUP 63 U> ABORT" το κλειδί είναι πολύ μεγάλο (<64)"
	DUP KEY: C! KEY: + KEY: 1+ SWAP ?DO  I C!  -1 +LOOP ;
 
	HEX  61 8A 63 D2 FB  5 !KEY
	KEY: COUNT ARCFOUR-INIT
	CR 
	   DC ARCFOUR 2 .R SPACE
	   EE ARCFOUR 2 .R SPACE
	   4C ARCFOUR 2 .R SPACE
	   F9 ARCFOUR 2 .R SPACE
	   2C ARCFOUR 2 .R
	CR .( Θα έπρεπε να είναι: F1 38 29 C9 DE )

Υλοποιήσεις[Επεξεργασία | επεξεργασία κώδικα]

Επειδή η εικονική μηχανή της Forth είναι εύκολη στην υλοποίηση και δεν υπάρχει κάποια πρότυπη υλοποίηση αναφοράς, υπάρχουν πολλές υλοποιήσεις της γλώσσας. Πολλά από αυτά τα συστήματα Forth, εκτός από την υποστήριξη των συνηθισμένων συστημάτων (POSIX, Microsoft Windows, Mac OS X), στοχεύουν στη λειτουργία σε ενσωματωμένα συστήματα (embedded systems). Ακολουθεί ένας κατάλογος από κάποια από τα πιο γνωστά συστήματα που συμφωνούν με το πρότυπο ANS Forth του 1994.

Δείτε επίσης[Επεξεργασία | επεξεργασία κώδικα]

Αναφορές[Επεξεργασία | επεξεργασία κώδικα]

  1. «NASA applications of Forth». Αρχειοθετήθηκε από το πρωτότυπο στις 4 Φεβρουαρίου 2011. Ανακτήθηκε στις 8 Νοεμβρίου 2010. 
  2. Προσπάθεια προτύπου Forth 200x
  3. «Forth Success Stories». Ανακτήθηκε στις 9 Ιουνίου 2006. 
  4. «Space Related Applications of Forth». Αρχειοθετήθηκε από το πρωτότυπο στις 4 Φεβρουαρίου 2011. Ανακτήθηκε στις 4 Σεπτεμβρίου 2007. 
  5. «Forth Chips Page». σελ. 54. Ανακτήθηκε στις 9 Ιουνίου 2006. 
  6. 6,0 6,1 6,2 «The Evolution of Forth». ACM SIGPLAN Notices, Volume 28, No. 3. March, 1993. ACM SIGPLAN History of Programming Languages Conference. 1993.  Unknown parameter |coauthors= ignored (|author= suggested) (βοήθεια); Unknown parameter |month= ignored (βοήθεια)
  7. "[t]he file holding the interpreter was labeled FOURTH, for 4th (next) generation software—but the IBM 1130 operating system restricted file names to 5 characters."Moore, Charles Η (1991). «Forth - The Early Years». Αρχειοθετήθηκε από το πρωτότυπο στις 15 Ιουνίου 2006. Ανακτήθηκε στις 3 Ιουνίου 2006. 
  8. «The Forth-79 Standard» (PDF). Αρχειοθετήθηκε από το πρωτότυπο (PDF) στις 13 Ιουλίου 2011. Ανακτήθηκε στις 8 Νοεμβρίου 2010. 
  9. «The Forth-83 Standard». 
  10. «Programming Languages: Forth». ANSI technical committee X3J14. 24 Μαρτίου 1994. Ανακτήθηκε στις 3 Ιουνίου 2006. 
  11. «The Forth Language», BYTE Magazine 5 (8), 1980 
  12. Brodie, Leo (1987). Starting Forth (paperback) (Δεύτερη έκδοση). Prentice-Hall. σελίδες 20. ISBN 0-13-843079-9. 
  13. Brodie, Leo (1987). Starting Forth (paperback) (Δεύτερη έκδοση). Prentice-Hall. σελίδες 14. ISBN 0-13-843079-9. 
  14. 14,0 14,1 14,2 14,3 Brodie, Leo (1987). Starting Forth (paperback) (Δεύτερη έκδοση). Prentice-Hall. σελίδες 16. ISBN 0-13-843079-9. 
  15. Rodriguez, Brad. «B.Y.O.ASSEMBLER». Αρχειοθετήθηκε από το πρωτότυπο στις 23 Ιουνίου 2006. Ανακτήθηκε στις 19 Ιουνίου 2006. 
  16. Rodriguez, Brad. «MULTITASKING 8051 CAMELFORTH» (PDF). Αρχειοθετήθηκε από το πρωτότυπο (PDF) στις 22 Ιουνίου 2006. Ανακτήθηκε στις 19 Ιουνίου 2006. 
  17. Rodriguez, Brad (1995). «MOVING FORTH». Αρχειοθετήθηκε από το πρωτότυπο στις 23 Ιουνίου 2006. Ανακτήθηκε στις 19 Ιουνίου 2006.  Unknown parameter |month= ignored (βοήθεια)
  18. Shoebridge, Peter (21 Δεκεμβρίου 1998). «Motorola Background Debugging Mode Driver for Windows NT». Αρχειοθετήθηκε από το πρωτότυπο στις 6 Ιουνίου 2007. Ανακτήθηκε στις 19 Ιουνίου 2006. 
  19. Martin, Harold M. (1991). «Developing a tethered Forth model». ACM Press. Ανακτήθηκε στις 19 Ιουνίου 2006.  Unknown parameter |month= ignored (βοήθεια)
  20. Brodie, Leo (1987). Starting Forth (paperback) (Second έκδοση). Prentice-Hall. σελίδες 200–202. ISBN 0-13-843079-9. 
  21. Brodie, Leo (1987). Starting Forth (paperback) (Second έκδοση). Prentice-Hall. σελίδες 273. ISBN 0-13-843079-9. 
  22. Brodie, Leo (1987). Starting Forth (paperback) (Second έκδοση). Prentice-Hall. σελίδες 199. ISBN 0-13-843079-9. 
  23. Ertl, M. Anton. «Implementation Issues for Superinstructions in Gforth» (PDF). Αρχειοθετήθηκε από το πρωτότυπο (PDF) στις 25 Ιουνίου 2006. Ανακτήθηκε στις 19 Ιουνίου 2006.  Unknown parameter |coauthors= ignored (|author= suggested) (βοήθεια)
  24. Brodie, Leo (1987). «Under The Hood». Starting Forth (paperback) (2nd έκδοση). Prentice-Hall. σελίδες 241. ISBN 0-13-843079-9. To summarize, there are three kinds of variables: System variables contain values used by the entire Forth system. User variables contain values that are unique for each task, even though the definitions can be used by all tasks in the system. Regular variables can be accessible either system-wide or within a single task only, depending upon whether they are defined within OPERATOR or within a private task. 
  25. Brodie, Leo (1984). Thinking ForthΑπαιτείται δωρεάν εγγραφή (paperback). Prentice-Hall. ISBN 0-13-917568-7. 
  26. Το κλασικό παράδειγμα του πλυντηρίου (washing machine) περιγράφει τη διαδικασία δημιουργίας ενός λεξικού για τη φυσική αναπαράσταση του πεδίου του προβλήματος με ευανάγνωστο τρόπο.

Περαιτέρω διάβασμα[Επεξεργασία | επεξεργασία κώδικα]

Εξωτερικοί σύνδεσμοι[Επεξεργασία | επεξεργασία κώδικα]