Δευτέρα 30 Νοεμβρίου 2015

Ειδικός Σωρός-Στοίβα-Ουρά στη Μ2000

(Μια μικρή αλλαγή στην Αναθεώρηση 99, επανέφερα την σταθερότητα της αναθεώρησης 97. στην εντολή κομ$, σε σχέση με τα νήματα)
Το παρακάτω "Σεντόνι" είναι ένα μακρύ παράδειγμα (έχει παύσεις με αναμονή πλήκτρου) για να κατανοήσει κανείς τις λειτουργίες (δεν είναι όλες) του ειδικού σωρού τιμών, της Μ2000 που εμφανίζεται ως στοίβα, ως ουρά ακόμα και ως πίνακας! Στην πράξη εσωτερικά ο σωρός είναι συλλογή (collection) η οποία είναι μια συνδεδεμένη λίστα και το κάθε στοιχείο της είναι ένα αντικείμενο. Άρα όταν γράφουμε στο σωρό κάτι, τρώει αρκετή μνήμη γιατί δημιουργείται ένα αντικείμενο Στις αρχικές εκδόσεις δεν ήταν παρά ένα και μόνο αλφαριθμητικό ο σωρός, τώρα αυτή η παλιά έκδοση μας δίνει τους σωρούς σε αλφαριθμητικά όπως θα δείτε στο τέλος του προγράμματος. Σε άλλο πρόγραμμα θα δείξω πώς επικοινωνούν ασύγχρονα δυο προγράμματα σε Μ2000 μέσω σωληνώσεως (pipe) μεταβιβάζοντας αλφαριθμητικό που είναι σωρός δηλαδή έχει τιμές αριθμητικές και αλφαριθμητικές μαζί, χωρίς να αποτελεί μέρος αρχείου, αλλά ολόκληρο ως μια τιμή μεταβλητής.

Ο σωρός εμφανίστηκε από την πρώτη έκδοση της Μ2000 ως δάνειο από την Forth. και χρησιμοποιείται για το πέρασμα τιμών σε τμήματα και συναρτήσεις. Κάθε τμήμα έχει το σωρό του πατρικού του, παίρνει και δίνει, δηλαδή εξάγει στο πέρας εκτέλεσης. Κάθε συνάρτηση ξεκινάει δικό της σωρό, και στην αναδρομή ξεκινάει νέο σωρό. Κάθε ρουτίνα ανήκει στο τμήμα και βλέπει τον ίδιο σωρό ακόμα και αν κάνει αναδρομή. Κάθε νήμα έχει δικό του σωρό αν και βλέπει τις μεταβλητές και τις ρουτίνες του τμήματος, αλλά κανείς δεν βλέπει το σωρό του! Γενικά σε κάθε περίπτωση ένας μόνο σωρός είναι ορατός. Μπορούμε πρόσκαιρα να ανοίξουμε έναν με την Σωρός Νέος { }. Υπάρχουν εντολές (όπως για τις βάσεις δεδομένων) που η επιστροφή τιμών είναι δυναμική, γίνεται στο σωρό με κορυφή τον αριθμό στοιχείων που ακολουθούν.

Όπως θα παρατηρήσουμε δεν χειριζόμαστε δείκτες στο σωρό. Ούτε για την κορυφή, ούτε για την βάση ή πυθμένα. Αν αναφερθούμε αριθμητικά σε κάποιο στοιχείο τότε το 1 είναι η κορυφή (0 δεν υπάρχει). Διαβάζω από το σωρό σημαίνει "σηκώνω" ταυτόχρονα, δηλαδή πετάω την κορυφή. Το διάβασμα γίνεται πάντα στη κορυφή. Άρα σηκώνουμε πάντα από την κορυφή. Το πώς θα μπει κάτι παίζει. Η Σειρά βάζει στο τέλος, η Βάλε στη κορυφή. Αλλά θα δείτε και άλλες εντολές που βάζουν την κορυφή. Όταν καλώ ένα τμήμα ας πούμε Α 10,20 τότε στη κορυφή θα είναι το 10 μετά το 20 και μετά όλα τα άλλα! Σε μια συνάρτηση...έχουμε καθαρό σωρό άρα δεν θα υπάρχουν "όλα τα άλλα".

Σε μια κλήση ρουτίνας με Διαμέσου και τιμές στο όνομα, θα περάσουν οι τιμές όπως στο τμήμα αλλά σε τοπικές μεταβλητές:
κ=1000
Διαμέσου αλφα(10,20)
Διαμέσου αλφα(10,20)
Τύπωσε κ
ρουτινα αλφα(χ)
      διαβασε τοπικά κ
      τυπωσε 
χ*κ
τελος ρουτίνας

(η εντολή διαμέσου Gosub στις γραμμές με την αλφα() είναι προαιρετική. Αν υπάρχει όμως πίνακας αλφα() είναι υποχρεωτική γιατί ο διερμηνευτήςθα πάρει το όνομα για πίνακα και θα ψάχνει το = ή άλλο σύμβολο πράξης π.χ. ++.

Αν στην διάβασε παραπάνω διαγράψουμε τον δείκτη τοπικά τότε η κ θα είναι 20, αλλιώς θα είναι 1000. Αν καλέσουμε την άλφα() χωρίς μια τιμή τότε θα βγει λάθος, Αν περάσουμε δέκα τιμές και δεν  διαβάσουμε τις υπόλοιπες εννιά για να τις "σηκώσουμε" θα μείνουν στο σωρό.

Δυο εντολές δεν υπάρχουν στο πρόγραμμα παρακάτω (εστιάζω στα στοιχεία περισσότερο), η ΠΕΤΑ και η ΠΑΝΩ. Η πρώτη πετάει έναν αριθμό στοιχείων από την κορυφή ΠΕΤΑ 2 πετάει δύο στοιχεία. Η ΠΑΝΩ βγάζει αντίγραφο από μια θέση. Χωρίς νούμερο διπλασιάζει τη κορυφή, και ισούται με το ΠΑΝΩ 1. Με ΠΑΝΩ 2 βγάζουμε αντίγραφο του του δεύτερου το βάζουμε στη κορυφή και το δεύτερο έχει γίνει τρίτο. Αν έχουμε ομάδα ή πίνακα στο σωρό η Πάνω βγάζει αντίγραφο. Αν είναι ομάδα το αντίγραφο είναι σε όλο το βάθος.

(Οι εντολές Πάνω, Φέρε, Φέρεπίσω, παίρνουν και δεύτερη παράμετρο (,Ν) για τον αριθμό των τεμαχίων, ουσιαστικά είναι σαν να εκτελούμε την εντολή Ν φορές)

Στις τελευταίες εκδόσεις της γλώσσας υπάρχει μεταβλητή δείκτης σε αντικείμενο σωρού. Υπάρχουν παραδείγματα στο Εγχειρίδιο και το Μικρό Εγχειρίδιο.

κλάση μια {
      πινακας α(10)
      κ=100
}
Α=μια()
Α.α(5)=μια()
Α.Α(5).κ++
Α.Α(5).Α(3)=μια()
Α.Α(5).Α(3).κ=2000
Τύπωσε Α.Α(5).Α(3).κ
Βάλε Α
Πίνακας Β(10)
Διάβασε Β(3)
Τύπωσε Β(3).Α(5).κ ' 101
Τύπωσε Β(3).Α(5).Α(3).κ ' 2000

Το στοιχείο Β(3) έχει το αντίγραφο της Α σε όλο το βάθος.
Β(4)=Β(3)
Τύπωσε Β(4).Α(5).Α(3).κ ' 2000

Τώρα και το Β(4) έχει ένα αντίγραφο. Αυτό σημαίνει ότι έχει ένα πίνακα α(10) και το κ=100, όπου το Α(5) έχει μια ομάδα με πίνακα Α(10) και κ=101, όπου έχει μια ομάδα στο Α(3) με πίνακα Α(10) και κ=2000. Άρα έχει τρεις πίνακες ο δεύτερος σε ένα στοιχείο του πρώτου και ο τρίτος σε ένα στοιχείο του δεύτερου.


Αντιγράψτε το παρακάτω σε ένα τμήμα (Σ α enter)


Άδειασε ' αυτή η εντολή αδειάζει το σωρό
Οθόνη 5,0
Πένα 14
Πίνακας Κ(20)=4
Βάλε 1,2,3,4,"αλφα", 5,6, Κ()
Σωρός
Διάβασε Β(), Α, Β, Γ$, Δ
Τύπωσε Β(4), Α, Β, Γ$, Δ
κκ$=κομ$ ' περιμένει ένα "κομβίο"...
Πίνακας Β(0) ' μόλις τον άδεισα αλλά δεν μπορώ να τον διαγράψω σαν όνομα
Σωρός Νέος {
      \\ σκιάζω τον σωρό με ένα νέο
      Βάλε 10, 20
      \\ τώρα τον αδειάζω
      Άδειασε
      Τύπωσε Κενό \\ τυπώνει -1
}
Τύπωσε Κενό \\ τυπώνει 0
Τύπωσε Μέγεθος.Σωρού \\τυπώνει 3
Τύπωσε Αριθμός \\ τυπώνει το 3
Τύπωσε Αριθμός \\ τυπώνει το 2
Τύπωσε Αριθμός \\ τυπώνει το 1
κκ$=κομ$
\\ το 1 μπήκε πρώτο και βγήκε τελευταίο, άρα ο σωρός μου είναι:
\\ LIFO και ως LIFO πρέπει να λέγεται ΣΤΟΙΒΑ
\\ Last In First Out
\\ Όμως δεν είναι μόνο LIFO αλλά και FIFO δηλαδή και ΟΥΡΑ
\\ First In First OUT
Άδειασε  \\ η μπορώ να ανοίξω ένα νέο σωρό εδώ
Σειρά 1,2,3,4,5
Ενώ όχι κενό { Τύπωσε Αριθμός }
\\ τελευταίο τυπώνει το 5 άρα έχω FIFO.
\\ Η εντολή ΣΕΙΡΑ προσθέτει κάθε στοιχείο στη βάση ή πυθμένα του σωρού.
\\ Η εντολή ΒΑΛΕ προσθέτει κάθε στοιχείο στη κορυφή του σωρού
\\ Η Διάβασε που βάζει σε μεταβλητές και ο Αριθμός και η Γράμμα$ διαβάζουν από τη κορυφή
\\ Άρα ο σωρός είναι μια διπλή λίστα; Όχι είναι πιο προχωρημένος!
κκ$=κομ$
Βάλε 1,2,3,4,5
Φέρε 3
Τύπωσε Αριθμός ' τυπώνει το 3
Φέρε 3 '' η φέρε φέρνει το ν-οστό στοιχείο στη κορυφή
Τύπωσε Αριθμός ' τυπώνει το 4
ΦέρεΠίσω 3 ' κάνει τη κορυφή το τρίτο στοιχείο
Τύπωσε Αριθμός, Αριθμός, Αριθμός ' τελευταίο τυπώθηκε το 1
κκ$=κομ$
\\ Άρα με τις εντολές Φέρε και ΦέρεΠίσω αλλάζω τη σειρά στα στοιχεία
\\ χωρίς να με ενδιαφέρει τι είναι αυτά, αν είναι απλές μεταβλητές, πίνακες, ομάδες ή αναφορές!
Βάλε 10*3, 1, "α"
Τύπωσε ΕινΑρ ' τυπώνει 0  δεν είναι αριθμός η κορυφή
Τύπωσε ΕινΓρ ' Τυπώνει -1 δεν είναι γράμματα (αλφαριθμητικό) η κορυφή
Τύπωσε Κενό ' Τυπώνει 0  δεν είναι κενός ο σωρός.
Τύπωσε Ταύτιση("ΓΑ") ' τυπώνει -1 γιατί έχουμε γράμματα και αριθμό
Τύπωσε Ταύτιση("ΓΑΑ") ' τυπώνει -1 γιατί έχουμε γράμματα και αριθμό και αριθμό
κκ$=κομ$
\\ μπορούμε να διαβάσουμε χωρίς να σηκώσουμε τις τιμές όπως κάνει η διάβασε, ο αριθμός και η γράμμα$
ι=0
σωρος
Ενώ ι <μέγεθος.σωρού {
      ι++
      Αν σωρουτύπος$(ι)="Number" τότε {
            Τύπωσε ΤιμήΣωρού(ι)
      } Αλλιώς.Αν σωρουτύπος$(ι)="String" τότε {
            Τύπωσε ΤιμήΣωρού$(ι)
      }
}
κκ$=κομ$
\\ Το ίδιο με το παραπάνω με άλλο τρόπο
\\ Η Φάκελος$() χωρίς παρέμετρους δίνει για όλα τα στοιχεία από ένα γράμμα
\\ στα λατινικά NSAG  G για ομάδα/Group A για πίνακα/Array
Α$=Φακελος$()
Αν Α$<>"" τότε {
      Για ι=1 έως Μήκος(Α$) {
            Επίλεξε με Μεσ$(Α$,ι,1)
            με "S"
                  Τύπωσε ΤιμήΣωρού$(ι)
            με "N"
                  Τύπωσε ΤιμήΣωρού(ι)
            Αλλιώς
                  Τύπωσε "Δεν το υποστηρίζω"
            Τέλος Επιλογής
      }
}
κκ$=κομ$
\\ Οι αναφορές στη Μ2000 είναι αλφαρηθμιτικά:
αα=100
Βάλε &αα
Τύπωσε ΤιμήΣωρού$(1)
Διάβασε &ββ
αα+=100
Τύπωσε ββ ' τυπώνει 200


κκ$=κομ$


\\ η αναφορά σε συναρτηση είναι αντιγραφή του ορισμού σε αλφαριθμητικό!
Συνάρτηση Κάπα {
      Διάβασε Χ
      =Χ**2 ' η δύναμη μπαίνει και με ^ και με **
}
Τύπωσε Κάπα(2) ' τυπώνει 4
Βάλε &Κάπα()
\\ Ο ορισμός έχει μια επιπλέον γραμμή για πληροφορίες για το σύστημα που βρίσκει τη θέση του λάθους!
Τύπωσε ΤιμήΣωρού$(1)
\\ Στις συναρτήσεις ομάδων μπαίνει και άλλη πληροφορία που συνδέει τον ορισμό με την ομάδα
\\ ώστε και η συνάρτηση με αναφορά να βλέπει τις κοινές μεταβλητές της ομάδας
Διάβασε &Λάμδα()
Τύπωσε Λάμδα(10) '' τυπώνει 100


κκ$=κομ$


\\ Μέχρι εδώ είδαμε πώς βάζουμε στοιχεία στο σωρό ένα προς ένα, και πώς τα διαβάζουμε
\\ ακόμα είδαμε πως βάζουμε αναφορές σε τιμές
\\ Μπορούμε να δημιουργούμε αλφαριθμητικά με τιμές για σωρό!
\\ Δεν μπορούμε σε αυτά να βάλουμε αντικείμενα, όπως πίνακες και ομάδες.
ΑΑ$=Σωρός$(10,"αλφα",45) ' έχουμε μια λίστα σωρού
Αδειασε
Σωρός ΑΑ$ ' το 10 θα είναι κορυφή
Τύπωσε Μήκος(ΑΑ$) ' το αλφαριθμητικό είναι άδειο
Άδειασε
ΑΑ$=Σωρός$(10,"αλφα",45)
ΒΒ$=Σωρός$(ΑΑ$, Σωρός$(11,"βήτα", 100),ΑΑ$) ' το ΒΒ$ έχει τρία στοιχεία αλφαριθμητικά
ΑΑ$=ΑΑ$+ΑΑ$ ' πρόσθεσα δυο λίστες το ΑΑ$ έχει έξι στοιχεία
Σωρός ΑΑ$, "Α"    
Σωρός ΑΑ$,"ΓΑ"
Φέρε 3 '' αλλιώς θα έχω "άλφα", 45, 10
Διάβασε Α, Β$, Γ
Τύπωσε Α, Β$, Γ
κκ$=κομ$
Σωρός Νέος {
      Σωρός ΑΑ$
      ΦέρεΠίσω 2 ' πάω το 1 στη θέση του 2
      Φέρε 3 '' πάω το 3 στη θέση του 1 άρα άλλαξα το τρίο με το πρώτο!
      ΑΑ$=Σωρός$(Αριθμός, Γράμμα$, Αριθμός)
}
Σωρός ΑΑ$
Διάβασε Α, Β$, Γ
Τύπωσε Α, Β$, Γ
κκ$=κομ$
Σωρος ΒΒ$, "Γ"
\\ θα το βάλω πίσω στη τελευταία θέση
\\ αλλά όχι "γυμνό" αλλά όπως θα το φτιάξει η Σωρός$
\\ τα αλφαριθμητικά έχουν δείκτη μήκους μέσα στο αλφαριθμητικό ως σωρός
\\ έτσι μπορεί να μπει οτιδήποτε, ακόμα και φωλιασμένα άλλα στοιχεία!
ΒΒ$=ΒΒ$+Σωρος$(Γράμμα$)
Σωρός ΒΒ$,"Γ"    ' η ΒΒ$ έχει δυο στοιχεία τώρα και το καθένα έχει τρία
Διαβασε ΓΓ$
Σωρός ΓΓ$ ' τώρα η ΓΓ$ άδειασε
Διάβασε Α, Β$, Γ
Τύπωσε Α, Β$, Γ ' 11,"βήτα", 100
Τύπωσε Φάκελος$(ΒΒ$) ' δίνει SS δηλαδή δυο String (αλφαριθμητικά)


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.