Ανέβηκαν δυο αναθεωρήσεις: Η αναθεώρηση 17 που διόρθωσε ένα λάθος, το οποίο διέγραφε το σωρό επιστροφής ρουτινών όταν χρησιμοποιούσαμε την φόρμα Έλεγχος. Η αναθεώρηση 18 που διόρθωσε ένα ζήτημα σε linux, με την φόρμα ελέγχου, όταν έμπαινε σε κατάσταση αναμονής "πάτωνε" το σύστημα λόγω μη σωστής απόκρισης σε ένα χαρακτηριστικό των Windows στο οποίο το wine δεν το δουλεύει σωστά (το wine είναι το πρόγραμμα που επιτρέπει να τρέχουν εφαρμογές των Windows σε linux). Δεν υπάρχουν ξεχωριστά αρχεία εκτέλεσης του διερμηνευτή, για windows και linux, ένα αρχείο m2000.exe καλεί ένα m2000.dll. Το m2000.dll είναι αντικείμενο που μπορεί να φορτωθεί από άλλες γλώσσες και να στέλνει κανείς πρόγραμμα και να το εκτελεί σε αυτό (το ίδιο κάνει το m2000.exe, όπου απλά το ξεκινάει, και η μόνη ευκολία είναι σε windows να εμφανίζει μια ετικέτα στο taskbar των windows)
Παρακάτω θα δούμε ένα πρόγραμμα, πώς δουλεύει και μαζί θα δούμε και μερικά στοιχεία της γλώσσας. Η Μ2000 βασίζεται μεν στην Basic αλλά δεν μένει εκεί, έχει πρόσθετα που την διαφοροποιούν.
Το πρόγραμμα Λατινικοί_Αριθμοί υπάρχει με αγγλικές εντολές, αλλά αποφάσισα να το γράψω με ελληνικές. Γίνεται εύκολα η μετατροπή στο διορθωτή (ενσωματωμένο στο διερμηνευτή της γλώσσας Μ2000), επιλέγουμε μια λέξη με απλό αριστερό κλικ σε κάποιο γράμμα της, και μετά πατάμε το F5. Ανοίγει μια φόρμα διαλόγου και ή κάνουμε άμεσα αντιγραφή από το πρόχειρο με ctrl+V ή γράφουμε αυτό που θέλουμε και με το ΟΚ αλλάζει παντού. Αυτή η αλλαγή έχει αναίρεση, πολλαπλή με Ctrl+Z (undo) και Ctrl+Y (redo).
Για να το τρέξουμε ξεκινάμε την Μ2000 με κλικ στο m2000.exe γράφουμε Σ Α και ανοίγει ο διορθωτής (Συγγραφή Α είναι κανονικά αλλά το Σ είναι συντόμευση - μπορούμε να έχουμε ταυτόχρονα τη Σ μεταβλητή, δεν έχει θέμα ο διερμηνευτής). Εκεί αντιγράφουμε το παρακάτω και με esc επιστρέφουμε στην γραμμή εντολών της Μ2000.
Γενικά μπορούμε να έχουμε πολλά τμήματα φορτωμένα, με μεγαλύτερα ονόματα από το Α, και έτσι δουλεύουμε αν θέλουμε να τρέχουμε δυο τρεις διαφορετικές εκδόσεις του ίδιου προγράμματος. Το τμήμα Α είναι εξ ορισμού γενικό, δηλαδή αν φτιάξουμε το Β με Σ Β τότε από το Β μπορούμε να καλέσουμε το Α εκτός και αν έχουμε τοπικό τμήμα Α το οποίο σκιάζει το γενικό. Η Μ2000 έχει δυο ειδών σκιάσεις, μια τοπική σκιάζει πάντα μια γενική με το ίδιο όνομα, και μια γενική με το ίδιο όνομα σκιάζει πάντα μια άλλη γενική με το ίδιο όνομα. Η διαφορά τους είναι ότι ένα τμήμα μέσα σε αυτό που επισκίασε την γενική έχει δικό του χώρο ονομάτων και έτσι αν η σκίαση στο πατρικό έγινε με τοπική τότε σε αυτό θα φαίνεται η υπάρχουσα γενική, αλλά αν έγινε με γενική τότε σε αυτό θα φαίνεται η νέα γενική. Η Μ2000 δηλαδή χρησιμοποιεί με τις σκιάσεις δυναμική συμπεριφορά ως προς τις μεταβλητές και τα τμήματα/συναρτήσεις.
Σημαντικά στοιχεία της Μ2000 είναι ο σωρός τιμών καθώς και το αντικείμενο εκτέλεσης. Σε κάθε εκτέλεση ο "δείκτης" προγράμματος δείχνει την εντολή σε ένα τμήμα/συνάρτηση/νήμα και αυτό δηλώνει το χώρο ονομάτων που ανήκει. Μπορεί ένα τμήμα να ανήκει σε ένα αντικείμενο (είναι μέθοδος). Βάσει του χώρου ονομάτων υπάρχει πρόσβαση στις τοπικές μεταβλητές. Ο "εκτελεστής" είναι συνάρτηση στον κώδικα του διερμηνευτή και συνδέεται με ένα αντικείμενο εκτέλεσης. Αυτό το αντικείμενο έχει διάφορα χρήσιμα στοιχεία μόνο για την συγκεκριμένη εκτέλεση. Ένα διαφορετικό νήμα έχει άλλο αντικείμενο εκτέλεσης ενώ τυγχάνει να έχει κοινό όνομα χώρου με άλλο νήμα. Κάθε τμήμα, συνάρτηση και νήμα εκτελείται σε δικό του αντικείμενο εκτέλεσης. Οι ρουτίνες δεν έχουν αντικείμενο εκτέλεσης, εκτελούνται από το τρέχον, και έχουν όνομα χώρου το όνομα του αντικείμενου εκτέλεσης. Υπάρχουν δυο ειδών ρουτίνες, οι απλές και αυτές με παρενθέσεις. Οι πρώτες δεν έχουν τοπικές μεταβλητές οι δεύτερες έχουν και αυτές για όσο τρέχει η ρουτίνα σκιάζουν τις τοπικές στο αντικείμενο εκτέλεσης. Στο πρόγραμμα παρακάτω χρησιμοποιώ μια ρουτίνα απλή για αρχικοποίηση, επειδή ότι φτιάχνει μένει (σε αντίθεση οι ρουτίνες με παρενθέσεις που φτιάχνονται με το Ρουτίνα/Τέλος Ρουτίνας, διαγράφουν ότι νέο αναγνωριστικό φτιάχνουμε).
Κάθε αντικείμενο εκτέλεσης εκτελεί κώδικα και εκτός από τιμές που βάζει και διαβάζει με αναγνωριστικά (μεταβλητές - πίνακες), έχει πρόσβαση στο σωρό τιμών. Η ιστορία με το σωρό τιμών ξεκίνησε με την FORTH, όταν την ανακάλυψα τη δεκαετία του 80. Ο σωρός εδώ δεν σχετίζεται με την έννοια του σωρού επιστροφής (return stack). Χρησιμοποιώ την λέξη σωρός ενώ και η λέξη Στοίβα θα ταίριαζε. Ο Σωρός λοιπόν είναι μια λίστα συνδεδεμένων τιμών, που μεγαλώνει όσο θέλουμε (όσο υπάρχει μνήμη), και μπορούμε να βάζουμε τιμές ή στη κορυφή ή στο πυθμένα. Επειδή ανασύρουμε τιμές από την κορυφή, όταν βάζουμε τιμές στη κορυφή ο σωρός λειτουργεί σαν LIFO (last in first out, ή το τελευταίο που μπαίνει βγαίνει πρώτο), ενώ όταν βάζουμε στο πυθμένα, ή τέλος, ο σωρός λειτουργεί ως FIFO (first in first out, ή το πρώτο που μπαίνει βγαίνει πρώτο). Η ανάσυρση τιμής λέγεται στα αγγλικά pop, ενώ το απλό διάβασμα peek. Στη Μ2000 δεν χρησιμοποιούμε αυτές τις λέξεις. Οι τιμές του σωρού μπορεί να είναι οτιδήποτε εκτός από τμήματα, δηλαδή μπορούμε ακόμα και συναρτήσεις να περάσουμε, και για τμήματα μπορούμε να περάσουμε αντικείμενα που έχουν τμήματα, δηλαδή έμμεσα περνάμε και τμήματα. Οι βασικές εντολές του σωρού είναι πέντε, η Διάβασε (ή Read) για να διαβάζουμε από τη κορυφή (ταυτόχρονα πετάει την τιμή, δηλαδή είναι το λεγόμενο pop), η Βάλε (ή Push) για να βάζουμε στη κορυφή, η Σειρά (ή Data) για να βάζουμε στο πυθμένα, η Άδειασε (ή Flush) για να διαγράφουμε όλες τις τιμές και η Πέτα για να πετάξουμε έναν αριθμό τιμών. Υπάρχουν εντολές που μετακινούν ένα ή περισσότερα στοιχεία από την κορυφή προς μια θέση και το ανάποδο (Φέρε και ΦέρεΠίσω, ή Shift και ShiftBack), καθώς και εντολή για αντιγραφή στοιχείων, ενός ή περισσότερων (Πάνω ή Over). Υπάρχουν συναρτήσεις (και μεταβλητές μόνο για ανάγνωση) που διαβάζουν από κορυφή και πετάνε το στοιχείο, αλλά και άλλες που διαβάζουν μόνο, από κορυφή ή άλλη θέση. Επίσης υπάρχουν συναρτήσεις που ελέγχουν τους τύπους των στοιχείων σε μια σειρά θέσεων, ή σε συγκεκριμένη.
Κάθε τμήμα δέχεται το σωρό τιμών αυτού που το κάλεσε, δηλαδή δεν έχει δικό του αποκλειστικό σωρό. Οι συναρτήσεις όταν κληθούν σε παράσταση καθώς και τα νήματα ξεκινούν με δικό τους σωρό τιμών. Το αναγνωριστικό [] κάνει κάτι πρωτότυπο, γυρνάει ένα δείκτη στο σωρό τιμών, και αφήνει ένα νέο αντικείμενο στο σωρό τιμών του τρέχοντος αντικείμενου εκτέλεσης (αυτό σημαίνει ότι αν έχουμε εκτέλεση σε τμήμα, θα αλλάξει και το αντικείμενο Σωρός του πατρικού). Με το δείκτη σε σωρό μπορούμε να κάνουμε εργασίες όπως στον τρέχοντα σωρό, με πρόσκαιρη σύνδεσή του ως τρέχοντα σωρό. Επίσης δεν υπάρχει δυνατότητα να κρατήσουμε σε δείκτη ένα σωρό αντικειμένου εκτέλεσης ταυτόχρονα με το αντικείμενο εκτέλεσης (αυτό για ασφάλεια). Δείτε στη συνάρτηση Τιμήλατινικού$() (το $ δηλώνει ότι επιστρέφει αλφαριθμητικό, αυτό είναι βασικό για τον διερμηνευτή), όπου με την Βάλε, γεμίζουμε τον τρέχον σωρό. Επιπλέον φτιάχνουμε ένα νέο αντικείμενο Σωρός με τιμές ανάμικτες, αλφαριθμητικές και αριθμητικές. Εδώ έχει σημασία η σειρά που διαβάζουμε. Η συνάρτηση πρώτα εκτελεί μια Διάβασε Λατ$, και μετά την Άδειασε, για να καθαρίσουμε το σωρό από τυχόν άλλες τιμές. Στη Μ2000 δεν γίνεται έλεγχος του αριθμού και του τύπου στο σημείο της κλήσης αλλά στο προορισμό της κλήσης, μέσω της Διάβασε. Δεν μπορούμε να διαβάσουμε αλφαριθμητικό αν υπάρχει αριθμητική τιμή. Επίσης αν θέλουμε λέμε στην Διάβασε τι τύπο θέλουμε να διαβάσουμε και αν δει κάτι μη συμβατό τότε γυρνάει σφάλμα. Αν και δεν βλέπουμε στη σύνταξη την εντολή Διάβασε Λατ$, ο διερμηνευτής την βάζει αυτόματα, επειδή η παρένθεση μετά το όνομα είναι μια συντακτική "ζάχαρη" που απλά μας δείχνει πιο ωραία στην εμφάνιση αλλά μένει "υπόγεια" στο πραγματικό τρόπο σύνταξης:
Συνάρτηση ΤιμήΛατινικού$ {
Διάβασε Λατ$
\\ άλλες εντολές
}
Ενώ στα τμήματα μπορούμε να επιστρέψουμε τιμές μέσω του σωρού τιμών, στις συναρτήσεις όταν καλούνται σε παραστάσεις (μπορούν να κληθούν με την Κάλεσε ως τμήματα), η επιστροφή τιμής γίνεται με το = (ή το -> αν γυρνούν δείκτη σε αντικείμενο Ομάδα - προχωρημένο θέμα). Η επιστροφή τιμής μπορεί να γίνει περισσότερες από μια φορές, και η συνάρτηση θα τερματίσει όταν εξαντλήσει το κώδικά της (μια εντολή Έξοδος τον εξαντλεί αμέσως). Εδώ λοιπόν βάζουμε το "άκυρο" ως αρχική τιμή επιστροφής.
Μετά εκτελούμε δυο δομές Σωρός { } όπου στο τέλος κάθε μπλοκ έχουμε την Κυκλικά. Αυτή η εντολή κάνει το μπλοκ να εκτελεστεί ξανά, θέτοντας μια σημαία για επανάληψη. Η σημαία ελέγχεται όταν εξαντληθεί ο κώδικας του μπλοκ. Μια εντολή έξοδος έχει προτεραιότητα σε σχέση με την σημαία επανάληψης. Η εντολή Κυκλικά (loop) πρέπει να εκτελεστεί κάθε φορά για να κάνει το μπλοκ να έχει επανάληψη, επειδή η σημαία είναι μιας χρήσεως και μετά γίνεται Ψευδής (χωρίς επανάληψη). Η εντολή Διέκοψε είναι η "βαριά" έξοδος, γιατί όχι μόνο κάνει έξοδο από το μπλοκ αλλά συνεχίζει και πιο πάνω, εδώ κάνει έξοδο και από την συνάρτηση (και για το λόγο αυτό έχουμε δώσει τιμή επιστροφής- αν δεν είχαμε δώσει μια τιμή η συνάρτηση θα γύρναγε την εξορισμού τιμή για αλφαριθμητικές συναρτήσεις, το κενό αλφαριθμητικό). Έτσι στη συνάρτηση η Διέκοψε σημαίνει ότι έχουμε άκυρη τιμή στο Λατ$, δεν υπάρχει αριθμός για επιστροφή (ο αριθμός γυρνάει ως αλφαριθμητικό).
Πριν εκτελέσουμε άλλες εντολές το μπλοκ στη Σωρός κοιτάμε αν αυτός είναι άδειος με την Κενό, μια μεταβλητή μόνο για ανάγνωση που σχετίζεται με τον τρέχον σωρό. Αν έχουμε κενό τότε κάνουμε έξοδο (σημαίνει ότι δεν υπάρχουν άλλες τιμές για επεξεργασία). Αλλιώς συνεχίζουμε διαβάζοντας τρεις τιμές κάθε φορά. Μας ενδιαφέρει ένα αλφαριθμητικό που μας λέει ποιοι χαρακτήρες δεν πρέπει να υπάρχουν μετά, μετά μια αριθμητική τιμή και τέλος το διπλό χαρακτήρα που θα αλλάξουμε - στο πρώτο μπλοκ-. Για κάθε διπλό χαρακτήρα κάνουμε μια αναζήτηση θέσης με την Θέση(). Αν υπάρχει αυτός ο διπλός χαρακτήρας τότε η θέση του θα είναι μεγαλύτερη από μηδέν. Σε ένα αλφαριθμητικό προσωρινή_τιμή$ (αν και αυτή η μεταβλητή δεν είναι προσωρινή, γιατί θα μείνει μετά την έξοδο από το μπλοκ, και απλά εδώ την δημιουργούμε με εκχώρηση τιμής) βάζουμε το υπόλοιπο μετά τη θέση όπου βρήκαμε το διπλό χαρακτήρα για να κάνουμε έλεγχο.
Στη συνέχεια επειδή θέλουμε να δούμε αν υπάρχουν κάποιοι μη επιτρεπτοί χαρακτήρες, τους αφαιρούμε με τη Φίλτρο$() (δεν θα γίνει τίποτα αν δεν υπάρχουν), και μετά κοιτάμε το τελικό μήκος. Αν δεν έχει αλλάξει είμαστε εντάξει αλλιώς πάμε για Διέκοψε (Break).
Η ουσιαστική εντολή εδώ είναι η Παρεμβολή, ένας τρόπος να αλλάξουμε χαρακτήρες σε ένα αλφαριθμητικό χωρίς να βγάλουμε αντίγραφο.(διαφορετικά θα έπρεπε να πάρουμε δυο μέρη του αλφαριθμητικού και να συνθέταμε το πρώτο, αυτό που θέλουμε να παρεμβληθεί, και το τελευταίο, σε ένα αλφαριθμητικό, και το αποτέλεσμα να το γράφαμε στο τρέχον αλφαριθμητικό). Η ιδέα εδώ είναι να προετοιμάσουμε το αλφαριθμητικό Λατ$, με "μονάδες", ώστε να αθροιστούν σωστά. Εδώ η Παρεμβολή αφαιρεί χαρακτήρες. Για κάθε τιμή που αφαιρούμε ως χαρακτήρες αυξάνουμε το άθροισμα.
Την τελική άθροιση την κάνει το τελευταίο μέρος, όπου ένα αντικείμενο σωρός μας λέει τι πρέπει να κάνουμε. Δείτε εδώ ότι έχει σημασία ότι κάθε φορά ψάχνουμε από το μεγαλύτερης αξίας, και δεν το αναζητούμε ξανά σε άλλες θέσεις εκτός από τις πρώτες. Αν στο τέλος το Λατ$ δεν μείνει κενό αλφαριθμητικό τότε έχουμε άκυρο νούμερο! Εδώ κάθε χαρακτήρας το πολύ να έχει τρεις εγγραφές. Έχει γίνει ξεκαθάρισμα από πριν για εκείνους τους χαρακτήρες που δεν επιτρέπονται μετά από ζευγάρια χαρακτήρων.
Παρακάτω θα δούμε ένα πρόγραμμα, πώς δουλεύει και μαζί θα δούμε και μερικά στοιχεία της γλώσσας. Η Μ2000 βασίζεται μεν στην Basic αλλά δεν μένει εκεί, έχει πρόσθετα που την διαφοροποιούν.
Το πρόγραμμα Λατινικοί_Αριθμοί υπάρχει με αγγλικές εντολές, αλλά αποφάσισα να το γράψω με ελληνικές. Γίνεται εύκολα η μετατροπή στο διορθωτή (ενσωματωμένο στο διερμηνευτή της γλώσσας Μ2000), επιλέγουμε μια λέξη με απλό αριστερό κλικ σε κάποιο γράμμα της, και μετά πατάμε το F5. Ανοίγει μια φόρμα διαλόγου και ή κάνουμε άμεσα αντιγραφή από το πρόχειρο με ctrl+V ή γράφουμε αυτό που θέλουμε και με το ΟΚ αλλάζει παντού. Αυτή η αλλαγή έχει αναίρεση, πολλαπλή με Ctrl+Z (undo) και Ctrl+Y (redo).
Για να το τρέξουμε ξεκινάμε την Μ2000 με κλικ στο m2000.exe γράφουμε Σ Α και ανοίγει ο διορθωτής (Συγγραφή Α είναι κανονικά αλλά το Σ είναι συντόμευση - μπορούμε να έχουμε ταυτόχρονα τη Σ μεταβλητή, δεν έχει θέμα ο διερμηνευτής). Εκεί αντιγράφουμε το παρακάτω και με esc επιστρέφουμε στην γραμμή εντολών της Μ2000.
Γενικά μπορούμε να έχουμε πολλά τμήματα φορτωμένα, με μεγαλύτερα ονόματα από το Α, και έτσι δουλεύουμε αν θέλουμε να τρέχουμε δυο τρεις διαφορετικές εκδόσεις του ίδιου προγράμματος. Το τμήμα Α είναι εξ ορισμού γενικό, δηλαδή αν φτιάξουμε το Β με Σ Β τότε από το Β μπορούμε να καλέσουμε το Α εκτός και αν έχουμε τοπικό τμήμα Α το οποίο σκιάζει το γενικό. Η Μ2000 έχει δυο ειδών σκιάσεις, μια τοπική σκιάζει πάντα μια γενική με το ίδιο όνομα, και μια γενική με το ίδιο όνομα σκιάζει πάντα μια άλλη γενική με το ίδιο όνομα. Η διαφορά τους είναι ότι ένα τμήμα μέσα σε αυτό που επισκίασε την γενική έχει δικό του χώρο ονομάτων και έτσι αν η σκίαση στο πατρικό έγινε με τοπική τότε σε αυτό θα φαίνεται η υπάρχουσα γενική, αλλά αν έγινε με γενική τότε σε αυτό θα φαίνεται η νέα γενική. Η Μ2000 δηλαδή χρησιμοποιεί με τις σκιάσεις δυναμική συμπεριφορά ως προς τις μεταβλητές και τα τμήματα/συναρτήσεις.
Σημαντικά στοιχεία της Μ2000 είναι ο σωρός τιμών καθώς και το αντικείμενο εκτέλεσης. Σε κάθε εκτέλεση ο "δείκτης" προγράμματος δείχνει την εντολή σε ένα τμήμα/συνάρτηση/νήμα και αυτό δηλώνει το χώρο ονομάτων που ανήκει. Μπορεί ένα τμήμα να ανήκει σε ένα αντικείμενο (είναι μέθοδος). Βάσει του χώρου ονομάτων υπάρχει πρόσβαση στις τοπικές μεταβλητές. Ο "εκτελεστής" είναι συνάρτηση στον κώδικα του διερμηνευτή και συνδέεται με ένα αντικείμενο εκτέλεσης. Αυτό το αντικείμενο έχει διάφορα χρήσιμα στοιχεία μόνο για την συγκεκριμένη εκτέλεση. Ένα διαφορετικό νήμα έχει άλλο αντικείμενο εκτέλεσης ενώ τυγχάνει να έχει κοινό όνομα χώρου με άλλο νήμα. Κάθε τμήμα, συνάρτηση και νήμα εκτελείται σε δικό του αντικείμενο εκτέλεσης. Οι ρουτίνες δεν έχουν αντικείμενο εκτέλεσης, εκτελούνται από το τρέχον, και έχουν όνομα χώρου το όνομα του αντικείμενου εκτέλεσης. Υπάρχουν δυο ειδών ρουτίνες, οι απλές και αυτές με παρενθέσεις. Οι πρώτες δεν έχουν τοπικές μεταβλητές οι δεύτερες έχουν και αυτές για όσο τρέχει η ρουτίνα σκιάζουν τις τοπικές στο αντικείμενο εκτέλεσης. Στο πρόγραμμα παρακάτω χρησιμοποιώ μια ρουτίνα απλή για αρχικοποίηση, επειδή ότι φτιάχνει μένει (σε αντίθεση οι ρουτίνες με παρενθέσεις που φτιάχνονται με το Ρουτίνα/Τέλος Ρουτίνας, διαγράφουν ότι νέο αναγνωριστικό φτιάχνουμε).
Κάθε αντικείμενο εκτέλεσης εκτελεί κώδικα και εκτός από τιμές που βάζει και διαβάζει με αναγνωριστικά (μεταβλητές - πίνακες), έχει πρόσβαση στο σωρό τιμών. Η ιστορία με το σωρό τιμών ξεκίνησε με την FORTH, όταν την ανακάλυψα τη δεκαετία του 80. Ο σωρός εδώ δεν σχετίζεται με την έννοια του σωρού επιστροφής (return stack). Χρησιμοποιώ την λέξη σωρός ενώ και η λέξη Στοίβα θα ταίριαζε. Ο Σωρός λοιπόν είναι μια λίστα συνδεδεμένων τιμών, που μεγαλώνει όσο θέλουμε (όσο υπάρχει μνήμη), και μπορούμε να βάζουμε τιμές ή στη κορυφή ή στο πυθμένα. Επειδή ανασύρουμε τιμές από την κορυφή, όταν βάζουμε τιμές στη κορυφή ο σωρός λειτουργεί σαν LIFO (last in first out, ή το τελευταίο που μπαίνει βγαίνει πρώτο), ενώ όταν βάζουμε στο πυθμένα, ή τέλος, ο σωρός λειτουργεί ως FIFO (first in first out, ή το πρώτο που μπαίνει βγαίνει πρώτο). Η ανάσυρση τιμής λέγεται στα αγγλικά pop, ενώ το απλό διάβασμα peek. Στη Μ2000 δεν χρησιμοποιούμε αυτές τις λέξεις. Οι τιμές του σωρού μπορεί να είναι οτιδήποτε εκτός από τμήματα, δηλαδή μπορούμε ακόμα και συναρτήσεις να περάσουμε, και για τμήματα μπορούμε να περάσουμε αντικείμενα που έχουν τμήματα, δηλαδή έμμεσα περνάμε και τμήματα. Οι βασικές εντολές του σωρού είναι πέντε, η Διάβασε (ή Read) για να διαβάζουμε από τη κορυφή (ταυτόχρονα πετάει την τιμή, δηλαδή είναι το λεγόμενο pop), η Βάλε (ή Push) για να βάζουμε στη κορυφή, η Σειρά (ή Data) για να βάζουμε στο πυθμένα, η Άδειασε (ή Flush) για να διαγράφουμε όλες τις τιμές και η Πέτα για να πετάξουμε έναν αριθμό τιμών. Υπάρχουν εντολές που μετακινούν ένα ή περισσότερα στοιχεία από την κορυφή προς μια θέση και το ανάποδο (Φέρε και ΦέρεΠίσω, ή Shift και ShiftBack), καθώς και εντολή για αντιγραφή στοιχείων, ενός ή περισσότερων (Πάνω ή Over). Υπάρχουν συναρτήσεις (και μεταβλητές μόνο για ανάγνωση) που διαβάζουν από κορυφή και πετάνε το στοιχείο, αλλά και άλλες που διαβάζουν μόνο, από κορυφή ή άλλη θέση. Επίσης υπάρχουν συναρτήσεις που ελέγχουν τους τύπους των στοιχείων σε μια σειρά θέσεων, ή σε συγκεκριμένη.
Κάθε τμήμα δέχεται το σωρό τιμών αυτού που το κάλεσε, δηλαδή δεν έχει δικό του αποκλειστικό σωρό. Οι συναρτήσεις όταν κληθούν σε παράσταση καθώς και τα νήματα ξεκινούν με δικό τους σωρό τιμών. Το αναγνωριστικό [] κάνει κάτι πρωτότυπο, γυρνάει ένα δείκτη στο σωρό τιμών, και αφήνει ένα νέο αντικείμενο στο σωρό τιμών του τρέχοντος αντικείμενου εκτέλεσης (αυτό σημαίνει ότι αν έχουμε εκτέλεση σε τμήμα, θα αλλάξει και το αντικείμενο Σωρός του πατρικού). Με το δείκτη σε σωρό μπορούμε να κάνουμε εργασίες όπως στον τρέχοντα σωρό, με πρόσκαιρη σύνδεσή του ως τρέχοντα σωρό. Επίσης δεν υπάρχει δυνατότητα να κρατήσουμε σε δείκτη ένα σωρό αντικειμένου εκτέλεσης ταυτόχρονα με το αντικείμενο εκτέλεσης (αυτό για ασφάλεια). Δείτε στη συνάρτηση Τιμήλατινικού$() (το $ δηλώνει ότι επιστρέφει αλφαριθμητικό, αυτό είναι βασικό για τον διερμηνευτή), όπου με την Βάλε, γεμίζουμε τον τρέχον σωρό. Επιπλέον φτιάχνουμε ένα νέο αντικείμενο Σωρός με τιμές ανάμικτες, αλφαριθμητικές και αριθμητικές. Εδώ έχει σημασία η σειρά που διαβάζουμε. Η συνάρτηση πρώτα εκτελεί μια Διάβασε Λατ$, και μετά την Άδειασε, για να καθαρίσουμε το σωρό από τυχόν άλλες τιμές. Στη Μ2000 δεν γίνεται έλεγχος του αριθμού και του τύπου στο σημείο της κλήσης αλλά στο προορισμό της κλήσης, μέσω της Διάβασε. Δεν μπορούμε να διαβάσουμε αλφαριθμητικό αν υπάρχει αριθμητική τιμή. Επίσης αν θέλουμε λέμε στην Διάβασε τι τύπο θέλουμε να διαβάσουμε και αν δει κάτι μη συμβατό τότε γυρνάει σφάλμα. Αν και δεν βλέπουμε στη σύνταξη την εντολή Διάβασε Λατ$, ο διερμηνευτής την βάζει αυτόματα, επειδή η παρένθεση μετά το όνομα είναι μια συντακτική "ζάχαρη" που απλά μας δείχνει πιο ωραία στην εμφάνιση αλλά μένει "υπόγεια" στο πραγματικό τρόπο σύνταξης:
Συνάρτηση ΤιμήΛατινικού$ {
Διάβασε Λατ$
\\ άλλες εντολές
}
Ενώ στα τμήματα μπορούμε να επιστρέψουμε τιμές μέσω του σωρού τιμών, στις συναρτήσεις όταν καλούνται σε παραστάσεις (μπορούν να κληθούν με την Κάλεσε ως τμήματα), η επιστροφή τιμής γίνεται με το = (ή το -> αν γυρνούν δείκτη σε αντικείμενο Ομάδα - προχωρημένο θέμα). Η επιστροφή τιμής μπορεί να γίνει περισσότερες από μια φορές, και η συνάρτηση θα τερματίσει όταν εξαντλήσει το κώδικά της (μια εντολή Έξοδος τον εξαντλεί αμέσως). Εδώ λοιπόν βάζουμε το "άκυρο" ως αρχική τιμή επιστροφής.
Μετά εκτελούμε δυο δομές Σωρός { } όπου στο τέλος κάθε μπλοκ έχουμε την Κυκλικά. Αυτή η εντολή κάνει το μπλοκ να εκτελεστεί ξανά, θέτοντας μια σημαία για επανάληψη. Η σημαία ελέγχεται όταν εξαντληθεί ο κώδικας του μπλοκ. Μια εντολή έξοδος έχει προτεραιότητα σε σχέση με την σημαία επανάληψης. Η εντολή Κυκλικά (loop) πρέπει να εκτελεστεί κάθε φορά για να κάνει το μπλοκ να έχει επανάληψη, επειδή η σημαία είναι μιας χρήσεως και μετά γίνεται Ψευδής (χωρίς επανάληψη). Η εντολή Διέκοψε είναι η "βαριά" έξοδος, γιατί όχι μόνο κάνει έξοδο από το μπλοκ αλλά συνεχίζει και πιο πάνω, εδώ κάνει έξοδο και από την συνάρτηση (και για το λόγο αυτό έχουμε δώσει τιμή επιστροφής- αν δεν είχαμε δώσει μια τιμή η συνάρτηση θα γύρναγε την εξορισμού τιμή για αλφαριθμητικές συναρτήσεις, το κενό αλφαριθμητικό). Έτσι στη συνάρτηση η Διέκοψε σημαίνει ότι έχουμε άκυρη τιμή στο Λατ$, δεν υπάρχει αριθμός για επιστροφή (ο αριθμός γυρνάει ως αλφαριθμητικό).
Πριν εκτελέσουμε άλλες εντολές το μπλοκ στη Σωρός κοιτάμε αν αυτός είναι άδειος με την Κενό, μια μεταβλητή μόνο για ανάγνωση που σχετίζεται με τον τρέχον σωρό. Αν έχουμε κενό τότε κάνουμε έξοδο (σημαίνει ότι δεν υπάρχουν άλλες τιμές για επεξεργασία). Αλλιώς συνεχίζουμε διαβάζοντας τρεις τιμές κάθε φορά. Μας ενδιαφέρει ένα αλφαριθμητικό που μας λέει ποιοι χαρακτήρες δεν πρέπει να υπάρχουν μετά, μετά μια αριθμητική τιμή και τέλος το διπλό χαρακτήρα που θα αλλάξουμε - στο πρώτο μπλοκ-. Για κάθε διπλό χαρακτήρα κάνουμε μια αναζήτηση θέσης με την Θέση(). Αν υπάρχει αυτός ο διπλός χαρακτήρας τότε η θέση του θα είναι μεγαλύτερη από μηδέν. Σε ένα αλφαριθμητικό προσωρινή_τιμή$ (αν και αυτή η μεταβλητή δεν είναι προσωρινή, γιατί θα μείνει μετά την έξοδο από το μπλοκ, και απλά εδώ την δημιουργούμε με εκχώρηση τιμής) βάζουμε το υπόλοιπο μετά τη θέση όπου βρήκαμε το διπλό χαρακτήρα για να κάνουμε έλεγχο.
Στη συνέχεια επειδή θέλουμε να δούμε αν υπάρχουν κάποιοι μη επιτρεπτοί χαρακτήρες, τους αφαιρούμε με τη Φίλτρο$() (δεν θα γίνει τίποτα αν δεν υπάρχουν), και μετά κοιτάμε το τελικό μήκος. Αν δεν έχει αλλάξει είμαστε εντάξει αλλιώς πάμε για Διέκοψε (Break).
Η ουσιαστική εντολή εδώ είναι η Παρεμβολή, ένας τρόπος να αλλάξουμε χαρακτήρες σε ένα αλφαριθμητικό χωρίς να βγάλουμε αντίγραφο.(διαφορετικά θα έπρεπε να πάρουμε δυο μέρη του αλφαριθμητικού και να συνθέταμε το πρώτο, αυτό που θέλουμε να παρεμβληθεί, και το τελευταίο, σε ένα αλφαριθμητικό, και το αποτέλεσμα να το γράφαμε στο τρέχον αλφαριθμητικό). Η ιδέα εδώ είναι να προετοιμάσουμε το αλφαριθμητικό Λατ$, με "μονάδες", ώστε να αθροιστούν σωστά. Εδώ η Παρεμβολή αφαιρεί χαρακτήρες. Για κάθε τιμή που αφαιρούμε ως χαρακτήρες αυξάνουμε το άθροισμα.
Την τελική άθροιση την κάνει το τελευταίο μέρος, όπου ένα αντικείμενο σωρός μας λέει τι πρέπει να κάνουμε. Δείτε εδώ ότι έχει σημασία ότι κάθε φορά ψάχνουμε από το μεγαλύτερης αξίας, και δεν το αναζητούμε ξανά σε άλλες θέσεις εκτός από τις πρώτες. Αν στο τέλος το Λατ$ δεν μείνει κενό αλφαριθμητικό τότε έχουμε άκυρο νούμερο! Εδώ κάθε χαρακτήρας το πολύ να έχει τρεις εγγραφές. Έχει γίνει ξεκαθάρισμα από πριν για εκείνους τους χαρακτήρες που δεν επιτρέπονται μετά από ζευγάρια χαρακτήρων.
Τμήμα Λατινικοί_Αριθμοί
{
Άδειασε
Διαμέσου Αρχικοποίηση
Έγγραφο Εγγ$
Ενώ όχι κενό {
Διάβασε λατ$
Τύπωσε λατ$;"=";ΤιμήΛατινικού$(λατ$)
Εγγ$=λατ$+"="+ΤιμήΛατινικού$(λατ$)+{
}
}
Πρόχειρο Εγγ$
Τέλος
Αρχικοποίηση:
Συνάρτηση ΤιμήΛατινικού$(λατ$) {
Άδειασε
Βάλε "CM", 900,"MD","CD", 400,"MD", "XC", 90,"DL", "XL", 40,"X", "IX",9,"V", "IV",4,"I"
διπλό_λατινικό=[]
απλό_λατινικό=Σωρός:="M", 1000, "D", 500, "C",100, "L",50,"X", 10, "V", 5, "I",1
="άκυρο"
σύνολο=0
μια_τιμή=0
μετρητής=0
Σωρός διπλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε μη_έγγυροι_χαρακτήρες$, μια_τιμή, χαρακτ$
i=Θέση(λατ$,χαρακτ$)
Αν i >0 Τότε {
προσωρινή_τιμή$=Μεσ$(λατ$,i+2)
L=Μήκος(προσωρινή_τιμή$)
Αν L>0 Τότε Αν Μήκος(Φίλτρο$(προσωρινή_τιμή$, μη_έγγυροι_χαρακτήρες$))<>L Τότε λατ$="A": Διέκοψε
Αν Θέση(λατ$,Μεσ$(λατ$,i,1))<i Τότε λατ$="A": Διέκοψε
Παρεμβολή i, 2 λατ$="" : σύνολο+=μια_τιμή
}
Κυκλικά
}
Σωρός απλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε χαρακτ$, μια_τιμή
μετρητής=0
Ενώ Αρισ$(λατ$,1)=χαρακτ$ {
Παρεμβολή 1, 1 λατ$=""
μετρητής++
σύνολο+=μια_τιμή
}
Αν μετρητής>3 Τότε Διέκοψε
Κυκλικά
}
Αν Μήκος(λατ$)>0 Τότε Έξοδος
=Str$(σύνολο,1033)
}
Σειρά "MMMCMXCIX", "LXXIIX", "MMXVII", "LXXIX", "CXCIX","MCMXCIX","MMMDCCCLXXXVIII"
Σειρά "CMXI","M","MCDXLIV","CCCC","IXV", "XLIXL","LXXIIX","XXXIX", "XXXX", "XIXX","IVI", "XLIX"
Επιστροφή
}
Λατινικοί_Αριθμοί
Άδειασε
Διαμέσου Αρχικοποίηση
Έγγραφο Εγγ$
Ενώ όχι κενό {
Διάβασε λατ$
Τύπωσε λατ$;"=";ΤιμήΛατινικού$(λατ$)
Εγγ$=λατ$+"="+ΤιμήΛατινικού$(λατ$)+{
}
}
Πρόχειρο Εγγ$
Τέλος
Αρχικοποίηση:
Συνάρτηση ΤιμήΛατινικού$(λατ$) {
Άδειασε
Βάλε "CM", 900,"MD","CD", 400,"MD", "XC", 90,"DL", "XL", 40,"X", "IX",9,"V", "IV",4,"I"
διπλό_λατινικό=[]
απλό_λατινικό=Σωρός:="M", 1000, "D", 500, "C",100, "L",50,"X", 10, "V", 5, "I",1
="άκυρο"
σύνολο=0
μια_τιμή=0
μετρητής=0
Σωρός διπλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε μη_έγγυροι_χαρακτήρες$, μια_τιμή, χαρακτ$
i=Θέση(λατ$,χαρακτ$)
Αν i >0 Τότε {
προσωρινή_τιμή$=Μεσ$(λατ$,i+2)
L=Μήκος(προσωρινή_τιμή$)
Αν L>0 Τότε Αν Μήκος(Φίλτρο$(προσωρινή_τιμή$, μη_έγγυροι_χαρακτήρες$))<>L Τότε λατ$="A": Διέκοψε
Αν Θέση(λατ$,Μεσ$(λατ$,i,1))<i Τότε λατ$="A": Διέκοψε
Παρεμβολή i, 2 λατ$="" : σύνολο+=μια_τιμή
}
Κυκλικά
}
Σωρός απλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε χαρακτ$, μια_τιμή
μετρητής=0
Ενώ Αρισ$(λατ$,1)=χαρακτ$ {
Παρεμβολή 1, 1 λατ$=""
μετρητής++
σύνολο+=μια_τιμή
}
Αν μετρητής>3 Τότε Διέκοψε
Κυκλικά
}
Αν Μήκος(λατ$)>0 Τότε Έξοδος
=Str$(σύνολο,1033)
}
Σειρά "MMMCMXCIX", "LXXIIX", "MMXVII", "LXXIX", "CXCIX","MCMXCIX","MMMDCCCLXXXVIII"
Σειρά "CMXI","M","MCDXLIV","CCCC","IXV", "XLIXL","LXXIIX","XXXIX", "XXXX", "XIXX","IVI", "XLIX"
Επιστροφή
}
Λατινικοί_Αριθμοί
Εμφάνιση
στην οθόνη (και συνάμα αντιγράφει και
στο πρόχειρο):
MMMCMXCIX=3999
LXXIIX=άκυρο
MMXVII=2017
LXXIX=79
CXCIX=199
MCMXCIX=1999
MMMDCCCLXXXVIII=3888
CMXI=911
M=1000
MCDXLIV=1444
CCCC=άκυρο
IXV=άκυρο
XLIXL=99
LXXIIX=άκυρο
XXXIX=39
XXXX=άκυρο
XIXX=29
IVI=άκυρο
XLIX=49
LXXIIX=άκυρο
MMXVII=2017
LXXIX=79
CXCIX=199
MCMXCIX=1999
MMMDCCCLXXXVIII=3888
CMXI=911
M=1000
MCDXLIV=1444
CCCC=άκυρο
IXV=άκυρο
XLIXL=99
LXXIIX=άκυρο
XXXIX=39
XXXX=άκυρο
XIXX=29
IVI=άκυρο
XLIX=49
Ανώτερο από το παραπάνω, το XLIXL πρέπει να βγαίνει άκυρο, όπως και το ΧΙΧΧ και το IVM.
Τμήμα Λατινικοί_Αριθμοί {
Άδειασε
Διαμέσου Αρχικοποίηση
Έγγραφο Εγγ$
Ενώ όχι κενό
Διάβασε λατ$
Τύπωσε λατ$;"=";ΤιμήΛατινικού$(λατ$)
Εγγ$=λατ$+"="+ΤιμήΛατινικού$(λατ$)+{
}
Τέλος Ενώ
Πρόχειρο Εγγ$
Τέλος
Αρχικοποίηση:
Συνάρτηση ΤιμήΛατινικού$(λατ$) {
Άδειασε
="άκυρο"
Αν Φίλτρο$(λατ$,"MDCLXVI")<>"" Τότε Έξοδος
\\ θα μπουν ανάποδα, το τελευταίο πρώτο.
Βάλε "CM", "MD", "Q","CD", "MD","W", "XC", "DL", "E","XL", "X","R", "IX","V","T", "IV","I","Y"
διπλό_λατινικό=[]
\\ θα μπουν με το τελευταίο να είναι τελευταίο.
Σειρά "M", 1000, "Q",900,"D", 500,"W", 400,"C",100,"E",90, "L",50,"R", 40,"X", 10, "T", 9, "V", 5, "Y", 4, "I",1
απλό_λατινικό=[]
σύνολο=0
μια_τιμή=0
μετρητής=0
Σωρός διπλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε απ$, μη_έγγυροι_χαρακτήρες$,χαρακτ$
ι=Θέση(λατ$,χαρακτ$)
Αν ι >0 Τότε
προσωρινή_τιμή$=Μεσ$(λατ$,ι+2)
λ=Μήκος(προσωρινή_τιμή$)
Αν λ>0 Τότε Αν Μήκος(Φίλτρο$(προσωρινή_τιμή$, μη_έγγυροι_χαρακτήρες$))<>λ Τότε λατ$="A": Έξοδος
Αν Θέση(λατ$,Μεσ$(λατ$,ι,1))<ι Τότε λατ$="A": Έξοδος
insert ι, 2 λατ$=απ$ ' 2 λέμε αλλα δίνουμε 1 χαρακτήρα και ο μεταφραστής θα βάλει ένα διάστημα
Τέλος Αν
Κυκλικά
}
λατ$=Φίλτρο$(λατ$," ")
Σωρός απλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε χαρακτ$, μια_τιμή
μετρητής=0
Ενώ Αρισ$(λατ$,1)=χαρακτ$
Παρεμβολή 1, 1 λατ$=""
μετρητής++
σύνολο+=μια_τιμή
Τέλος Ενώ
Αν μετρητής>3 Τότε έξοδος
Κυκλικά
}
Αν Μήκος(λατ$)>0 ή μετρητής>3 Αλλιώς
=Γραφή$(σύνολο,1033)
Τέλος Αν
}
Σειρά "MMMCMXCIX", "LXXIIX", "MMXVII", "LXXIX", "CXCIX","MCMXCIX","MMMDCCCLXXXVIII"
Σειρά "CMXI","M","MCDXLIV","CCCC","IXV", "XLIXL","LXXIIX","IVM"
Σειρά "XXXIX", "XXXX", "XIXX","IVI", "XLIX","XCIX","XCIV","XLVIII"
Επιστροφή
}
Λατινικοί_Αριθμοί
Τμήμα Λατινικοί_Αριθμοί {
Άδειασε
Διαμέσου Αρχικοποίηση
Έγγραφο Εγγ$
Ενώ όχι κενό
Διάβασε λατ$
Τύπωσε λατ$;"=";ΤιμήΛατινικού$(λατ$)
Εγγ$=λατ$+"="+ΤιμήΛατινικού$(λατ$)+{
}
Τέλος Ενώ
Πρόχειρο Εγγ$
Τέλος
Αρχικοποίηση:
Συνάρτηση ΤιμήΛατινικού$(λατ$) {
Άδειασε
="άκυρο"
Αν Φίλτρο$(λατ$,"MDCLXVI")<>"" Τότε Έξοδος
\\ θα μπουν ανάποδα, το τελευταίο πρώτο.
Βάλε "CM", "MD", "Q","CD", "MD","W", "XC", "DL", "E","XL", "X","R", "IX","V","T", "IV","I","Y"
διπλό_λατινικό=[]
\\ θα μπουν με το τελευταίο να είναι τελευταίο.
Σειρά "M", 1000, "Q",900,"D", 500,"W", 400,"C",100,"E",90, "L",50,"R", 40,"X", 10, "T", 9, "V", 5, "Y", 4, "I",1
απλό_λατινικό=[]
σύνολο=0
μια_τιμή=0
μετρητής=0
Σωρός διπλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε απ$, μη_έγγυροι_χαρακτήρες$,χαρακτ$
ι=Θέση(λατ$,χαρακτ$)
Αν ι >0 Τότε
προσωρινή_τιμή$=Μεσ$(λατ$,ι+2)
λ=Μήκος(προσωρινή_τιμή$)
Αν λ>0 Τότε Αν Μήκος(Φίλτρο$(προσωρινή_τιμή$, μη_έγγυροι_χαρακτήρες$))<>λ Τότε λατ$="A": Έξοδος
Αν Θέση(λατ$,Μεσ$(λατ$,ι,1))<ι Τότε λατ$="A": Έξοδος
insert ι, 2 λατ$=απ$ ' 2 λέμε αλλα δίνουμε 1 χαρακτήρα και ο μεταφραστής θα βάλει ένα διάστημα
Τέλος Αν
Κυκλικά
}
λατ$=Φίλτρο$(λατ$," ")
Σωρός απλό_λατινικό {
Αν κενό Τότε Έξοδος
Διάβασε χαρακτ$, μια_τιμή
μετρητής=0
Ενώ Αρισ$(λατ$,1)=χαρακτ$
Παρεμβολή 1, 1 λατ$=""
μετρητής++
σύνολο+=μια_τιμή
Τέλος Ενώ
Αν μετρητής>3 Τότε έξοδος
Κυκλικά
}
Αν Μήκος(λατ$)>0 ή μετρητής>3 Αλλιώς
=Γραφή$(σύνολο,1033)
Τέλος Αν
}
Σειρά "MMMCMXCIX", "LXXIIX", "MMXVII", "LXXIX", "CXCIX","MCMXCIX","MMMDCCCLXXXVIII"
Σειρά "CMXI","M","MCDXLIV","CCCC","IXV", "XLIXL","LXXIIX","IVM"
Σειρά "XXXIX", "XXXX", "XIXX","IVI", "XLIX","XCIX","XCIV","XLVIII"
Επιστροφή
}
Λατινικοί_Αριθμοί
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου
You can feel free to write any suggestion, or idea on the subject.